345 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			345 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
| <div class="gvfdktuvdgwhmztnuekzkswkjygptfcv"
 | |
| 	:data-is-selected="isSelected"
 | |
| 	:data-is-contextmenu-showing="isContextmenuShowing"
 | |
| 	@click="onClick"
 | |
| 	draggable="true"
 | |
| 	@dragstart="onDragstart"
 | |
| 	@dragend="onDragend"
 | |
| 	@contextmenu.prevent.stop="onContextmenu"
 | |
| 	:title="title"
 | |
| >
 | |
| 	<div class="label" v-if="$store.state.i.avatarId == file.id">
 | |
| 		<img src="/assets/label.svg"/>
 | |
| 		<p>%i18n:@avatar%</p>
 | |
| 	</div>
 | |
| 	<div class="label" v-if="$store.state.i.bannerId == file.id">
 | |
| 		<img src="/assets/label.svg"/>
 | |
| 		<p>%i18n:@banner%</p>
 | |
| 	</div>
 | |
| 	<div class="label red" v-if="file.isSensitive">
 | |
| 		<img src="/assets/label-red.svg"/>
 | |
| 		<p>%i18n:@nsfw%</p>
 | |
| 	</div>
 | |
| 	<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
 | |
| 		<img :src="file.thumbnailUrl" alt="" @load="onThumbnailLoaded"/>
 | |
| 	</div>
 | |
| 	<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>
 | |
| </div>
 | |
| </template>
 | |
| 
 | |
| <script lang="ts">
 | |
| import Vue from 'vue';
 | |
| import * as anime from 'animejs';
 | |
| import contextmenu from '../../api/contextmenu';
 | |
| import copyToClipboard from '../../../common/scripts/copy-to-clipboard';
 | |
| 
 | |
| export default Vue.extend({
 | |
| 	props: ['file'],
 | |
| 	data() {
 | |
| 		return {
 | |
| 			isContextmenuShowing: false,
 | |
| 			isDragging: false
 | |
| 		};
 | |
| 	},
 | |
| 	computed: {
 | |
| 		browser(): any {
 | |
| 			return this.$parent;
 | |
| 		},
 | |
| 		isSelected(): boolean {
 | |
| 			return this.browser.selectedFiles.some(f => f.id == this.file.id);
 | |
| 		},
 | |
| 		title(): string {
 | |
| 			return `${this.file.name}\n${this.file.type} ${Vue.filter('bytes')(this.file.datasize)}`;
 | |
| 		},
 | |
| 		background(): string {
 | |
| 			return this.file.properties.avgColor && this.file.properties.avgColor.length == 3
 | |
| 				? `rgb(${this.file.properties.avgColor.join(',')})`
 | |
| 				: 'transparent';
 | |
| 		}
 | |
| 	},
 | |
| 	methods: {
 | |
| 		onClick() {
 | |
| 			this.browser.chooseFile(this.file);
 | |
| 		},
 | |
| 
 | |
| 		onContextmenu(e) {
 | |
| 			this.isContextmenuShowing = true;
 | |
| 			contextmenu((this as any).os)(e, [{
 | |
| 				type: 'item',
 | |
| 				text: '%i18n:@contextmenu.rename%',
 | |
| 				icon: '%fa:i-cursor%',
 | |
| 				action: this.rename
 | |
| 			}, {
 | |
| 				type: 'item',
 | |
| 				text: this.file.isSensitive ? '%i18n:@contextmenu.unmark-as-sensitive%' : '%i18n:@contextmenu.mark-as-sensitive%',
 | |
| 				icon: this.file.isSensitive ? '%fa:R eye%' : '%fa:R eye-slash%',
 | |
| 				action: this.toggleSensitive
 | |
| 			}, null, {
 | |
| 				type: 'item',
 | |
| 				text: '%i18n:@contextmenu.copy-url%',
 | |
| 				icon: '%fa:link%',
 | |
| 				action: this.copyUrl
 | |
| 			}, {
 | |
| 				type: 'link',
 | |
| 				href: `${this.file.url}?download`,
 | |
| 				text: '%i18n:@contextmenu.download%',
 | |
| 				icon: '%fa:download%',
 | |
| 			}, null, {
 | |
| 				type: 'item',
 | |
| 				text: '%i18n:common.delete%',
 | |
| 				icon: '%fa:R trash-alt%',
 | |
| 				action: this.deleteFile
 | |
| 			}, null, {
 | |
| 				type: 'nest',
 | |
| 				text: '%i18n:@contextmenu.else-files%',
 | |
| 				menu: [{
 | |
| 					type: 'item',
 | |
| 					text: '%i18n:@contextmenu.set-as-avatar%',
 | |
| 					action: this.setAsAvatar
 | |
| 				}, {
 | |
| 					type: 'item',
 | |
| 					text: '%i18n:@contextmenu.set-as-banner%',
 | |
| 					action: this.setAsBanner
 | |
| 				}]
 | |
| 			}, /*{
 | |
| 				type: 'nest',
 | |
| 				text: '%i18n:@contextmenu.open-in-app%',
 | |
| 				menu: [{
 | |
| 					type: 'item',
 | |
| 					text: '%i18n:@contextmenu.add-app%...',
 | |
| 					action: this.addApp
 | |
| 				}]
 | |
| 			}*/], {
 | |
| 					closed: () => {
 | |
| 						this.isContextmenuShowing = false;
 | |
| 					}
 | |
| 				});
 | |
| 		},
 | |
| 
 | |
| 		onDragstart(e) {
 | |
| 			e.dataTransfer.effectAllowed = 'move';
 | |
| 			e.dataTransfer.setData('mk_drive_file', JSON.stringify(this.file));
 | |
| 			this.isDragging = true;
 | |
| 
 | |
| 			// 親ブラウザに対して、ドラッグが開始されたフラグを立てる
 | |
| 			// (=あなたの子供が、ドラッグを開始しましたよ)
 | |
| 			this.browser.isDragSource = true;
 | |
| 		},
 | |
| 
 | |
| 		onDragend(e) {
 | |
| 			this.isDragging = false;
 | |
| 			this.browser.isDragSource = false;
 | |
| 		},
 | |
| 
 | |
| 		onThumbnailLoaded() {
 | |
| 			if (this.file.properties.avgColor && this.file.properties.avgColor.length == 3) {
 | |
| 				anime({
 | |
| 					targets: this.$refs.thumbnail,
 | |
| 					backgroundColor: `rgba(${this.file.properties.avgColor.join(',')}, 0)`,
 | |
| 					duration: 100,
 | |
| 					easing: 'linear'
 | |
| 				});
 | |
| 			}
 | |
| 		},
 | |
| 
 | |
| 		rename() {
 | |
| 			(this as any).apis.input({
 | |
| 				title: '%i18n:@contextmenu.rename-file%',
 | |
| 				placeholder: '%i18n:@contextmenu.input-new-file-name%',
 | |
| 				default: this.file.name,
 | |
| 				allowEmpty: false
 | |
| 			}).then(name => {
 | |
| 				(this as any).api('drive/files/update', {
 | |
| 					fileId: this.file.id,
 | |
| 					name: name
 | |
| 				});
 | |
| 			});
 | |
| 		},
 | |
| 
 | |
| 		toggleSensitive() {
 | |
| 			(this as any).api('drive/files/update', {
 | |
| 				fileId: this.file.id,
 | |
| 				isSensitive: !this.file.isSensitive
 | |
| 			});
 | |
| 		},
 | |
| 
 | |
| 		copyUrl() {
 | |
| 			copyToClipboard(this.file.url);
 | |
| 			(this as any).apis.dialog({
 | |
| 				title: '%fa:check%%i18n:@contextmenu.copied%',
 | |
| 				text: '%i18n:@contextmenu.copied-url-to-clipboard%',
 | |
| 				actions: [{
 | |
| 					text: '%i18n:common.ok%'
 | |
| 				}]
 | |
| 			});
 | |
| 		},
 | |
| 
 | |
| 		setAsAvatar() {
 | |
| 			(this as any).apis.updateAvatar(this.file);
 | |
| 		},
 | |
| 
 | |
| 		setAsBanner() {
 | |
| 			(this as any).apis.updateBanner(this.file);
 | |
| 		},
 | |
| 
 | |
| 		addApp() {
 | |
| 			alert('not implemented yet');
 | |
| 		},
 | |
| 
 | |
| 		deleteFile() {
 | |
| 			(this as any).api('drive/files/delete', {
 | |
| 				fileId: this.file.id
 | |
| 			});
 | |
| 		}
 | |
| 	}
 | |
| });
 | |
| </script>
 | |
| 
 | |
| <style lang="stylus" scoped>
 | |
| .gvfdktuvdgwhmztnuekzkswkjygptfcv
 | |
| 	padding 8px 0 0 0
 | |
| 	height 180px
 | |
| 	border-radius 4px
 | |
| 
 | |
| 	&, *
 | |
| 		cursor pointer
 | |
| 
 | |
| 	&:hover
 | |
| 		background rgba(#000, 0.05)
 | |
| 
 | |
| 		> .label
 | |
| 			&:before
 | |
| 			&:after
 | |
| 				background #0b65a5
 | |
| 
 | |
| 			&.red
 | |
| 				&:before
 | |
| 				&:after
 | |
| 					background #c12113
 | |
| 
 | |
| 	&:active
 | |
| 		background rgba(#000, 0.1)
 | |
| 
 | |
| 		> .label
 | |
| 			&:before
 | |
| 			&:after
 | |
| 				background #0b588c
 | |
| 
 | |
| 			&.red
 | |
| 				&:before
 | |
| 				&:after
 | |
| 					background #ce2212
 | |
| 
 | |
| 	&[data-is-selected]
 | |
| 		background var(--primary)
 | |
| 
 | |
| 		&:hover
 | |
| 			background var(--primaryLighten10)
 | |
| 
 | |
| 		&:active
 | |
| 			background var(--primaryDarken10)
 | |
| 
 | |
| 		> .label
 | |
| 			&:before
 | |
| 			&:after
 | |
| 				display none
 | |
| 
 | |
| 		> .name
 | |
| 			color var(--primaryForeground)
 | |
| 
 | |
| 	&[data-is-contextmenu-showing]
 | |
| 		&:after
 | |
| 			content ""
 | |
| 			pointer-events none
 | |
| 			position absolute
 | |
| 			top -4px
 | |
| 			right -4px
 | |
| 			bottom -4px
 | |
| 			left -4px
 | |
| 			border 2px dashed var(--primaryAlpha03)
 | |
| 			border-radius 4px
 | |
| 
 | |
| 	> .label
 | |
| 		position absolute
 | |
| 		top 0
 | |
| 		left 0
 | |
| 		pointer-events none
 | |
| 
 | |
| 		&:before
 | |
| 		&:after
 | |
| 			content ""
 | |
| 			display block
 | |
| 			position absolute
 | |
| 			z-index 1
 | |
| 			background #0c7ac9
 | |
| 
 | |
| 		&:before
 | |
| 			top 0
 | |
| 			left 57px
 | |
| 			width 28px
 | |
| 			height 8px
 | |
| 
 | |
| 		&:after
 | |
| 			top 57px
 | |
| 			left 0
 | |
| 			width 8px
 | |
| 			height 28px
 | |
| 
 | |
| 		&.red
 | |
| 			&:before
 | |
| 			&:after
 | |
| 				background #c12113
 | |
| 
 | |
| 		> img
 | |
| 			position absolute
 | |
| 			z-index 2
 | |
| 			top 0
 | |
| 			left 0
 | |
| 
 | |
| 		> p
 | |
| 			position absolute
 | |
| 			z-index 3
 | |
| 			top 19px
 | |
| 			left -28px
 | |
| 			width 120px
 | |
| 			margin 0
 | |
| 			text-align center
 | |
| 			line-height 28px
 | |
| 			color #fff
 | |
| 			transform rotate(-45deg)
 | |
| 
 | |
| 	> .thumbnail
 | |
| 		width 128px
 | |
| 		height 128px
 | |
| 		margin auto
 | |
| 
 | |
| 		> img
 | |
| 			display block
 | |
| 			position absolute
 | |
| 			top 0
 | |
| 			left 0
 | |
| 			right 0
 | |
| 			bottom 0
 | |
| 			margin auto
 | |
| 			max-width 128px
 | |
| 			max-height 128px
 | |
| 			pointer-events none
 | |
| 
 | |
| 	> .name
 | |
| 		display block
 | |
| 		margin 4px 0 0 0
 | |
| 		font-size 0.8em
 | |
| 		text-align center
 | |
| 		word-break break-all
 | |
| 		color var(--text)
 | |
| 		overflow hidden
 | |
| 
 | |
| 		> .ext
 | |
| 			opacity 0.5
 | |
| 
 | |
| </style>
 | 
