Implement photo widget
This commit is contained in:
		
							parent
							
								
									1c757f10e0
								
							
						
					
					
						commit
						5f712fbf3c
					
				
					 6 changed files with 121 additions and 1 deletions
				
			
		|  | @ -13,6 +13,7 @@ unreleased | |||
| 	* タイムラインの途中におすすめのノートを表示できる機能 | ||||
| 	* 設定で有効/無効を切り替えられる | ||||
| * アクティビティウィジェットを実装 | ||||
| * フォトウィジェットを実装 | ||||
| * タイムラインの一番上までスクロールできるように | ||||
| * 管理者はモデレーターに変更できないように | ||||
| 
 | ||||
|  |  | |||
|  | @ -527,6 +527,7 @@ _widgets: | |||
|   clock: "時計" | ||||
|   rss: "RSSリーダー" | ||||
|   activity: "アクティビティ" | ||||
|   photos: "フォト" | ||||
| 
 | ||||
| _cw: | ||||
|   hide: "隠す" | ||||
|  |  | |||
|  | @ -608,6 +608,7 @@ export default Vue.extend({ | |||
| 				'trends', | ||||
| 				'clock', | ||||
| 				'activity', | ||||
| 				'photos', | ||||
| 			]; | ||||
| 
 | ||||
| 			this.$root.menu({ | ||||
|  |  | |||
|  | @ -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)"/> | ||||
|  |  | |||
|  | @ -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)); | ||||
|  |  | |||
							
								
								
									
										116
									
								
								src/client/widgets/photos.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/client/widgets/photos.vue
									
										
									
									
									
										Normal 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> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue