misskey/src/web/app/common/views/components/uploader.vue

213 lines
4.6 KiB
Vue
Raw Normal View History

2018-02-14 12:58:48 +01:00
<template>
<div class="mk-uploader">
<ol v-if="uploads.length > 0">
<li v-for="ctx in uploads" :key="ctx.id">
<div class="img" :style="{ backgroundImage: `url(${ ctx.img })` }"></div>
<p class="name">%fa:spinner .pulse%{{ ctx.name }}</p>
<p class="status">
<span class="initing" v-if="ctx.progress == undefined">%i18n:common.tags.mk-uploader.waiting%<mk-ellipsis/></span>
2018-02-14 12:59:30 +01:00
<span class="kb" v-if="ctx.progress != undefined">{{ String(Math.floor(ctx.progress.value / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i> / {{ String(Math.floor(ctx.progress.max / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i></span>
2018-02-14 12:58:48 +01:00
<span class="percentage" v-if="ctx.progress != undefined">{{ Math.floor((ctx.progress.value / ctx.progress.max) * 100) }}</span>
</p>
<progress v-if="ctx.progress != undefined && ctx.progress.value != ctx.progress.max" :value="ctx.progress.value" :max="ctx.progress.max"></progress>
<div class="progress initing" v-if="ctx.progress == undefined"></div>
<div class="progress waiting" v-if="ctx.progress != undefined && ctx.progress.value == ctx.progress.max"></div>
</li>
</ol>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
2018-02-16 07:38:12 +01:00
import { apiUrl } from '../../../config';
2018-02-14 12:58:48 +01:00
export default Vue.extend({
data() {
return {
uploads: []
};
},
methods: {
upload(file, folder) {
if (folder && typeof folder == 'object') folder = folder.id;
const id = Math.random();
const ctx = {
id: id,
name: file.name || 'untitled',
2018-02-16 07:38:12 +01:00
progress: undefined,
img: undefined
2018-02-14 12:58:48 +01:00
};
this.uploads.push(ctx);
this.$emit('change', this.uploads);
const reader = new FileReader();
2018-02-16 07:38:12 +01:00
reader.onload = (e: any) => {
2018-02-14 12:58:48 +01:00
ctx.img = e.target.result;
};
reader.readAsDataURL(file);
const data = new FormData();
2018-02-18 04:35:18 +01:00
data.append('i', (this as any).os.i.token);
2018-02-14 12:58:48 +01:00
data.append('file', file);
if (folder) data.append('folder_id', folder);
const xhr = new XMLHttpRequest();
2018-02-16 07:38:12 +01:00
xhr.open('POST', apiUrl + '/drive/files/create', true);
xhr.onload = (e: any) => {
2018-02-14 12:58:48 +01:00
const driveFile = JSON.parse(e.target.response);
this.$emit('uploaded', driveFile);
this.uploads = this.uploads.filter(x => x.id != id);
this.$emit('change', this.uploads);
};
xhr.upload.onprogress = e => {
if (e.lengthComputable) {
if (ctx.progress == undefined) ctx.progress = {};
ctx.progress.max = e.total;
ctx.progress.value = e.loaded;
}
};
xhr.send(data);
}
}
});
</script>
<style lang="stylus" scoped>
2018-03-03 05:47:55 +01:00
@import '~const.styl'
2018-02-14 12:58:48 +01:00
.mk-uploader
overflow auto
&:empty
display none
> ol
display block
margin 0
padding 0
list-style none
> li
display block
margin 8px 0 0 0
padding 0
height 36px
box-shadow 0 -1px 0 rgba($theme-color, 0.1)
border-top solid 8px transparent
&:first-child
margin 0
box-shadow none
border-top none
> .img
display block
position absolute
top 0
left 0
width 36px
height 36px
background-size cover
background-position center center
> .name
display block
position absolute
top 0
left 44px
margin 0
padding 0
max-width 256px
font-size 0.8em
color rgba($theme-color, 0.7)
white-space nowrap
text-overflow ellipsis
overflow hidden
> [data-fa]
margin-right 4px
> .status
display block
position absolute
top 0
right 0
margin 0
padding 0
font-size 0.8em
> .initing
color rgba($theme-color, 0.5)
> .kb
color rgba($theme-color, 0.5)
> .percentage
display inline-block
width 48px
text-align right
color rgba($theme-color, 0.7)
&:after
content '%'
> progress
display block
position absolute
bottom 0
right 0
margin 0
width calc(100% - 44px)
height 8px
background transparent
border none
border-radius 4px
overflow hidden
&::-webkit-progress-value
background $theme-color
&::-webkit-progress-bar
background rgba($theme-color, 0.1)
> .progress
display block
position absolute
bottom 0
right 0
margin 0
width calc(100% - 44px)
height 8px
border none
border-radius 4px
background linear-gradient(
45deg,
lighten($theme-color, 30%) 25%,
$theme-color 25%,
$theme-color 50%,
lighten($theme-color, 30%) 50%,
lighten($theme-color, 30%) 75%,
$theme-color 75%,
$theme-color
)
background-size 32px 32px
animation bg 1.5s linear infinite
&.initing
opacity 0.3
@keyframes bg
from {background-position: 0 0;}
to {background-position: -64px 32px;}
</style>