diff options
Diffstat (limited to 'src/client/pages/my-settings/drive.vue')
| -rw-r--r-- | src/client/pages/my-settings/drive.vue | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/client/pages/my-settings/drive.vue b/src/client/pages/my-settings/drive.vue new file mode 100644 index 0000000000..55372687fc --- /dev/null +++ b/src/client/pages/my-settings/drive.vue @@ -0,0 +1,212 @@ +<template> +<section class="uawsfosz _card"> + <div class="_title"><fa :icon="faCloud"/> {{ $t('drive') }}</div> + <div class="_content"> + <mk-pagination :pagination="drivePagination" #default="{items}" class="drive" ref="drive"> + <div class="file" v-for="(file, i) in items" :key="file.id" @click="selected = file" :class="{ selected: selected && (selected.id === file.id) }"> + <x-file-thumbnail class="thumbnail" :file="file" fit="cover"/> + <div class="body"> + <p class="name"> + <span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span> + <span class="ext" v-if="file.name.lastIndexOf('.') != -1">{{ file.name.substr(file.name.lastIndexOf('.')) }}</span> + </p> + <footer> + <span class="type"><x-file-type-icon :type="file.type" class="icon"/>{{ file.type }}</span> + <span class="separator"></span> + <span class="data-size">{{ file.size | bytes }}</span> + <span class="separator"></span> + <span class="created-at"><fa :icon="faClock"/><mk-time :time="file.createdAt"/></span> + <template v-if="file.isSensitive"> + <span class="separator"></span> + <span class="nsfw"><fa :icon="faEyeSlash"/> {{ $t('nsfw') }}</span> + </template> + </footer> + </div> + </div> + </mk-pagination> + </div> + <div class="_footer"> + <mk-button primary inline :disabled="selected == null" @click="download()"><fa :icon="faDownload"/> {{ $t('download') }}</mk-button> + <mk-button inline :disabled="selected == null" @click="del()"><fa :icon="faTrashAlt"/> {{ $t('delete') }}</mk-button> + </div> +</section> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import { faCloud, faDownload } from '@fortawesome/free-solid-svg-icons'; +import { faClock, faEyeSlash, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; +import XFileTypeIcon from '../../components/file-type-icon.vue'; +import XFileThumbnail from '../../components/drive-file-thumbnail.vue'; +import MkButton from '../../components/ui/button.vue'; +import MkPagination from '../../components/ui/pagination.vue'; +import i18n from '../../i18n'; + +export default Vue.extend({ + i18n, + + components: { + XFileTypeIcon, + XFileThumbnail, + MkPagination, + MkButton, + }, + + data() { + return { + selected: null, + connection: null, + drivePagination: { + endpoint: 'drive/files', + limit: 10, + }, + faCloud, faClock, faEyeSlash, faDownload, faTrashAlt + } + }, + + created() { + this.connection = this.$root.stream.useSharedConnection('drive'); + + this.connection.on('fileCreated', this.onStreamDriveFileCreated); + this.connection.on('fileUpdated', this.onStreamDriveFileUpdated); + this.connection.on('fileDeleted', this.onStreamDriveFileDeleted); + }, + + beforeDestroy() { + this.connection.dispose(); + }, + + methods: { + onStreamDriveFileCreated(file) { + this.$refs.drive.prepend(file); + }, + + onStreamDriveFileUpdated(file) { + // TODO + }, + + onStreamDriveFileDeleted(fileId) { + this.$refs.drive.remove(x => x.id === fileId); + }, + + download() { + window.open(this.selected.url, '_blank'); + }, + + async del() { + const { canceled } = await this.$root.dialog({ + type: 'warning', + text: this.$t('driveFileDeleteConfirm', { name: this.selected.name }), + showCancelButton: true + }); + if (canceled) return; + + this.$root.api('drive/files/delete', { + fileId: this.selected.id + }); + } + } +}); +</script> + +<style lang="scss" scoped> +.uawsfosz { + > ._content { + max-height: 350px; + overflow: auto; + + > .drive { + > .file { + display: grid; + margin: 0 auto; + grid-template-columns: 64px 1fr; + grid-column-gap: 10px; + cursor: pointer; + + &.selected { + background: var(--accent); + box-shadow: 0 0 0 8px var(--accent); + color: #fff; + } + + &:not(:last-child) { + margin-bottom: 16px; + } + + > .thumbnail { + width: 64px; + height: 64px; + } + + > .body { + display: block; + word-break: break-all; + padding-top: 4px; + + > .name { + display: block; + margin: 0; + padding: 0; + font-size: 0.9em; + font-weight: bold; + word-break: break-word; + + > .ext { + opacity: 0.5; + } + } + + > .tags { + display: block; + margin: 4px 0 0 0; + padding: 0; + list-style: none; + font-size: 0.5em; + + > .tag { + display: inline-block; + margin: 0 5px 0 0; + padding: 1px 5px; + border-radius: 2px; + } + } + + > footer { + display: block; + margin: 4px 0 0 0; + font-size: 0.7em; + + > .separator { + padding: 0 4px; + } + + > .type { + opacity: 0.7; + + > .icon { + margin-right: 4px; + } + } + + > .data-size { + opacity: 0.7; + } + + > .created-at { + opacity: 0.7; + + > [data-icon] { + margin-right: 2px; + } + } + + > .nsfw { + color: #bf4633; + } + } + } + } + } + } +} +</style> |