Implement photo widget

This commit is contained in:
syuilo 2020-02-18 19:47:30 +09:00
parent f25e361bc8
commit c2e447ef6d
6 changed files with 121 additions and 1 deletions

View File

@ -13,6 +13,7 @@ unreleased
* タイムラインの途中におすすめのノートを表示できる機能 * タイムラインの途中におすすめのノートを表示できる機能
* 設定で有効/無効を切り替えられる * 設定で有効/無効を切り替えられる
* アクティビティウィジェットを実装 * アクティビティウィジェットを実装
* フォトウィジェットを実装
* タイムラインの一番上までスクロールできるように * タイムラインの一番上までスクロールできるように
* 管理者はモデレーターに変更できないように * 管理者はモデレーターに変更できないように

View File

@ -527,6 +527,7 @@ _widgets:
clock: "時計" clock: "時計"
rss: "RSSリーダー" rss: "RSSリーダー"
activity: "アクティビティ" activity: "アクティビティ"
photos: "フォト"
_cw: _cw:
hide: "隠す" hide: "隠す"

View File

@ -608,6 +608,7 @@ export default Vue.extend({
'trends', 'trends',
'clock', 'clock',
'activity', 'activity',
'photos',
]; ];
this.$root.menu({ this.$root.menu({

View File

@ -4,7 +4,7 @@
<template #header><fa :icon="faChartBar"/>{{ $t('_widgets.activity') }}</template> <template #header><fa :icon="faChartBar"/>{{ $t('_widgets.activity') }}</template>
<template #func><button @click="toggleView()" class="_button"><fa :icon="faSort"/></button></template> <template #func><button @click="toggleView()" class="_button"><fa :icon="faSort"/></button></template>
<div class=""> <div>
<mk-loading v-if="fetching"/> <mk-loading v-if="fetching"/>
<template v-else> <template v-else>
<x-calendar v-show="props.view === 0" :data="[].concat(activity)"/> <x-calendar v-show="props.view === 0" :data="[].concat(activity)"/>

View File

@ -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-trends', () => import('./trends.vue').then(m => m.default));
Vue.component('mkw-clock', () => import('./clock.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-activity', () => import('./activity.vue').then(m => m.default));
Vue.component('mkw-photos', () => import('./photos.vue').then(m => m.default));

View File

@ -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>