整理した
This commit is contained in:
317
src/client/app/desktop/views/components/drive.file.vue
Normal file
317
src/client/app/desktop/views/components/drive.file.vue
Normal file
@@ -0,0 +1,317 @@
|
||||
<template>
|
||||
<div class="root file"
|
||||
: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="os.i.avatarId == file.id"><img src="/assets/label.svg"/>
|
||||
<p>%i18n:desktop.tags.mk-drive-browser-file.avatar%</p>
|
||||
</div>
|
||||
<div class="label" v-if="os.i.bannerId == file.id"><img src="/assets/label.svg"/>
|
||||
<p>%i18n:desktop.tags.mk-drive-browser-file.banner%</p>
|
||||
</div>
|
||||
<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
|
||||
<img :src="`${file.url}?thumbnail&size=128`" 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
|
||||
? `rgb(${this.file.properties.avgColor.join(',')})`
|
||||
: 'transparent';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.browser.chooseFile(this.file);
|
||||
},
|
||||
|
||||
onContextmenu(e) {
|
||||
this.isContextmenuShowing = true;
|
||||
contextmenu(e, [{
|
||||
type: 'item',
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.rename%',
|
||||
icon: '%fa:i-cursor%',
|
||||
onClick: this.rename
|
||||
}, {
|
||||
type: 'item',
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.copy-url%',
|
||||
icon: '%fa:link%',
|
||||
onClick: this.copyUrl
|
||||
}, {
|
||||
type: 'link',
|
||||
href: `${this.file.url}?download`,
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.download%',
|
||||
icon: '%fa:download%',
|
||||
}, {
|
||||
type: 'divider',
|
||||
}, {
|
||||
type: 'item',
|
||||
text: '%i18n:common.delete%',
|
||||
icon: '%fa:R trash-alt%',
|
||||
onClick: this.deleteFile
|
||||
}, {
|
||||
type: 'divider',
|
||||
}, {
|
||||
type: 'nest',
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.else-files%',
|
||||
menu: [{
|
||||
type: 'item',
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.set-as-avatar%',
|
||||
onClick: this.setAsAvatar
|
||||
}, {
|
||||
type: 'item',
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.set-as-banner%',
|
||||
onClick: this.setAsBanner
|
||||
}]
|
||||
}, {
|
||||
type: 'nest',
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.open-in-app%',
|
||||
menu: [{
|
||||
type: 'item',
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-contextmenu.add-app%...',
|
||||
onClick: 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) {
|
||||
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:desktop.tags.mk-drive-browser-file-contextmenu.rename-file%',
|
||||
placeholder: '%i18n:desktop.tags.mk-drive-browser-file-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
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
copyUrl() {
|
||||
copyToClipboard(this.file.url);
|
||||
(this as any).apis.dialog({
|
||||
title: '%fa:check%%i18n:desktop.tags.mk-drive-browser-file-contextmenu.copied%',
|
||||
text: '%i18n:desktop.tags.mk-drive-browser-file-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() {
|
||||
alert('not implemented yet');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import '~const.styl'
|
||||
|
||||
.root.file
|
||||
padding 8px 0 0 0
|
||||
height 180px
|
||||
border-radius 4px
|
||||
|
||||
&, *
|
||||
cursor pointer
|
||||
|
||||
&:hover
|
||||
background rgba(0, 0, 0, 0.05)
|
||||
|
||||
> .label
|
||||
&:before
|
||||
&:after
|
||||
background #0b65a5
|
||||
|
||||
&:active
|
||||
background rgba(0, 0, 0, 0.1)
|
||||
|
||||
> .label
|
||||
&:before
|
||||
&:after
|
||||
background #0b588c
|
||||
|
||||
&[data-is-selected]
|
||||
background $theme-color
|
||||
|
||||
&:hover
|
||||
background lighten($theme-color, 10%)
|
||||
|
||||
&:active
|
||||
background darken($theme-color, 10%)
|
||||
|
||||
> .label
|
||||
&:before
|
||||
&:after
|
||||
display none
|
||||
|
||||
> .name
|
||||
color $theme-color-foreground
|
||||
|
||||
&[data-is-contextmenu-showing]
|
||||
&:after
|
||||
content ""
|
||||
pointer-events none
|
||||
position absolute
|
||||
top -4px
|
||||
right -4px
|
||||
bottom -4px
|
||||
left -4px
|
||||
border 2px dashed rgba($theme-color, 0.3)
|
||||
border-radius 4px
|
||||
|
||||
> .label
|
||||
position absolute
|
||||
top 0
|
||||
left 0
|
||||
pointer-events none
|
||||
|
||||
&:before
|
||||
content ""
|
||||
display block
|
||||
position absolute
|
||||
z-index 1
|
||||
top 0
|
||||
left 57px
|
||||
width 28px
|
||||
height 8px
|
||||
background #0c7ac9
|
||||
|
||||
&:after
|
||||
content ""
|
||||
display block
|
||||
position absolute
|
||||
z-index 1
|
||||
top 57px
|
||||
left 0
|
||||
width 8px
|
||||
height 28px
|
||||
background #0c7ac9
|
||||
|
||||
> 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 #444
|
||||
overflow hidden
|
||||
|
||||
> .ext
|
||||
opacity 0.5
|
||||
|
||||
</style>
|
Reference in New Issue
Block a user