From 5f712fbf3cc0a177fb28955dd3fcd28ea7ff4f29 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Tue, 18 Feb 2020 19:47:30 +0900 Subject: [PATCH] Implement photo widget --- CHANGELOG.md | 1 + locales/ja-JP.yml | 1 + src/client/app.vue | 1 + src/client/widgets/activity.vue | 2 +- src/client/widgets/index.ts | 1 + src/client/widgets/photos.vue | 116 ++++++++++++++++++++++++++++++++ 6 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 src/client/widgets/photos.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index a3b6a28634..976acb27b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ unreleased * タイムラインの途中におすすめのノートを表示できる機能 * 設定で有効/無効を切り替えられる * アクティビティウィジェットを実装 +* フォトウィジェットを実装 * タイムラインの一番上までスクロールできるように * 管理者はモデレーターに変更できないように diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index f1271c809f..e8bf1ca281 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -527,6 +527,7 @@ _widgets: clock: "時計" rss: "RSSリーダー" activity: "アクティビティ" + photos: "フォト" _cw: hide: "隠す" diff --git a/src/client/app.vue b/src/client/app.vue index e88979f001..e892b393dc 100644 --- a/src/client/app.vue +++ b/src/client/app.vue @@ -608,6 +608,7 @@ export default Vue.extend({ 'trends', 'clock', 'activity', + 'photos', ]; this.$root.menu({ diff --git a/src/client/widgets/activity.vue b/src/client/widgets/activity.vue index 5f18c17d48..e08676c9a0 100644 --- a/src/client/widgets/activity.vue +++ b/src/client/widgets/activity.vue @@ -4,7 +4,7 @@ <template #header><fa :icon="faChartBar"/>{{ $t('_widgets.activity') }}</template> <template #func><button @click="toggleView()" class="_button"><fa :icon="faSort"/></button></template> - <div class=""> + <div> <mk-loading v-if="fetching"/> <template v-else> <x-calendar v-show="props.view === 0" :data="[].concat(activity)"/> diff --git a/src/client/widgets/index.ts b/src/client/widgets/index.ts index 9f8bbc8882..b18cf5548d 100644 --- a/src/client/widgets/index.ts +++ b/src/client/widgets/index.ts @@ -8,3 +8,4 @@ Vue.component('mkw-rss', () => import('./rss.vue').then(m => m.default)); Vue.component('mkw-trends', () => import('./trends.vue').then(m => m.default)); Vue.component('mkw-clock', () => import('./clock.vue').then(m => m.default)); Vue.component('mkw-activity', () => import('./activity.vue').then(m => m.default)); +Vue.component('mkw-photos', () => import('./photos.vue').then(m => m.default)); diff --git a/src/client/widgets/photos.vue b/src/client/widgets/photos.vue new file mode 100644 index 0000000000..fb2e6de0be --- /dev/null +++ b/src/client/widgets/photos.vue @@ -0,0 +1,116 @@ +<template> +<div> + <mk-container :show-header="props.design === 0" :naked="props.design === 2" :class="$style.root" :data-melt="props.design == 2"> + <template #header><fa :icon="faCamera"/>{{ $t('_widgets.photos') }}</template> + + <div class=""> + <mk-loading v-if="fetching"/> + <div v-else :class="$style.stream"> + <div v-for="(image, i) in images" :key="i" + :class="$style.img" + :style="`background-image: url(${thumbnail(image)})`" + ></div> + </div> + </div> + </mk-container> +</div> +</template> + +<script lang="ts"> +import { faCamera } from '@fortawesome/free-solid-svg-icons'; +import MkContainer from '../components/ui/container.vue'; +import define from './define'; +import i18n from '../i18n'; +import { getStaticImageUrl } from '../scripts/get-static-image-url'; + +export default define({ + name: 'photos', + props: () => ({ + design: 0, + }) +}).extend({ + i18n, + components: { + MkContainer, + }, + data() { + return { + images: [], + fetching: true, + connection: null, + faCamera + }; + }, + mounted() { + this.connection = this.$root.stream.useSharedConnection('main'); + + this.connection.on('driveFileCreated', this.onDriveFileCreated); + + this.$root.api('drive/stream', { + type: 'image/*', + limit: 9 + }).then(images => { + this.images = images; + this.fetching = false; + }); + }, + beforeDestroy() { + this.connection.dispose(); + }, + methods: { + onDriveFileCreated(file) { + if (/^image\/.+$/.test(file.type)) { + this.images.unshift(file); + if (this.images.length > 9) this.images.pop(); + } + }, + + func() { + if (this.props.design == 2) { + this.props.design = 0; + } else { + this.props.design++; + } + this.save(); + }, + + thumbnail(image: any): string { + return this.$store.state.device.disableShowingAnimatedImages + ? getStaticImageUrl(image.thumbnailUrl) + : image.thumbnailUrl; + }, + } +}); +</script> + +<style lang="scss" module> +.root[data-melt] { + .stream { + padding: 0; + } + + .img { + border: solid 4px transparent; + border-radius: 8px; + } +} + +.stream { + display: flex; + justify-content: center; + flex-wrap: wrap; + padding: 8px; + + .img { + flex: 1 1 33%; + width: 33%; + height: 80px; + box-sizing: border-box; + background-position: center center; + background-size: cover; + background-clip: content-box; + border: solid 2px transparent; + border-radius: 4px; + } +} +</style>