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>