This commit is contained in:
syuilo 2018-06-08 11:46:45 +09:00
parent 335ab5ab54
commit ebeb7f8578
11 changed files with 117 additions and 81 deletions

View File

@ -4,7 +4,7 @@
<div class="popover" :class="{ hukidasi }" ref="popover"> <div class="popover" :class="{ hukidasi }" ref="popover">
<template v-for="item in items"> <template v-for="item in items">
<div v-if="item === null"></div> <div v-if="item === null"></div>
<button v-if="item" @click="clicked(item.onClick)" v-html="item.content"></button> <button v-if="item" @click="clicked(item.action)" v-html="item.icon ? item.icon + ' ' + item.text : item.text"></button>
</template> </template>
</div> </div>
</div> </div>

View File

@ -13,23 +13,23 @@ export default Vue.extend({
items() { items() {
const items = []; const items = [];
items.push({ items.push({
content: '%i18n:@favorite%', text: '%i18n:@favorite%',
onClick: this.favorite action: this.favorite
}); });
if (this.note.userId == this.$store.state.i.id) { if (this.note.userId == this.$store.state.i.id) {
items.push({ items.push({
content: '%i18n:@pin%', text: '%i18n:@pin%',
onClick: this.pin action: this.pin
}); });
items.push({ items.push({
content: '%i18n:@delete%', text: '%i18n:@delete%',
onClick: this.del action: this.del
}); });
} }
if (this.note.uri) { if (this.note.uri) {
items.push({ items.push({
content: '%i18n:@remote%', text: '%i18n:@remote%',
onClick: () => { action: () => {
window.open(this.note.uri, '_blank'); window.open(this.note.uri, '_blank');
} }
}); });

View File

@ -1,16 +1,18 @@
<template> <template>
<ul class="menu"> <ul class="menu">
<li v-for="(item, i) in menu" :class="item.type"> <li v-for="(item, i) in menu" :class="item ? item.type : item === null ? 'divider' : null">
<template v-if="item.type == 'item'"> <template v-if="item">
<template v-if="item.type == null || item.type == 'item'">
<p @click="click(item)"><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}</p> <p @click="click(item)"><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}</p>
</template> </template>
<template v-if="item.type == 'link'"> <template v-else-if="item.type == 'link'">
<a :href="item.href" :target="item.target" @click="click(item)"><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}</a> <a :href="item.href" :target="item.target" @click="click(item)"><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}</a>
</template> </template>
<template v-else-if="item.type == 'nest'"> <template v-else-if="item.type == 'nest'">
<p><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}...<span class="caret">%fa:caret-right%</span></p> <p><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}...<span class="caret">%fa:caret-right%</span></p>
<me-nu :menu="item.menu" @x="click"/> <me-nu :menu="item.menu" @x="click"/>
</template> </template>
</template>
</li> </li>
</ul> </ul>
</template> </template>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="context-menu" :style="{ left: `${x}px`, top: `${y}px` }" @contextmenu.prevent="() => {}"> <div class="context-menu" @contextmenu.prevent="() => {}">
<x-menu :menu="menu" @x="click"/> <x-menu :menu="menu" @x="click"/>
</div> </div>
</template> </template>
@ -17,6 +17,23 @@ export default Vue.extend({
props: ['x', 'y', 'menu'], props: ['x', 'y', 'menu'],
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
const width = this.$el.offsetWidth;
const height = this.$el.offsetHeight;
let x = this.x;
let y = this.y;
if (x + width > window.innerWidth) {
x = window.innerWidth - width;
}
if (y + height > window.innerHeight) {
y = window.innerHeight - height;
}
this.$el.style.left = x + 'px';
this.$el.style.top = y + 'px';
Array.from(document.querySelectorAll('body *')).forEach(el => { Array.from(document.querySelectorAll('body *')).forEach(el => {
el.addEventListener('mousedown', this.onMousedown); el.addEventListener('mousedown', this.onMousedown);
}); });
@ -38,7 +55,7 @@ export default Vue.extend({
return false; return false;
}, },
click(item) { click(item) {
if (item.onClick) item.onClick(); if (item.action) item.action();
this.close(); this.close();
}, },
close() { close() {
@ -59,7 +76,6 @@ root(isDark)
$item-height = 38px $item-height = 38px
$padding = 10px $padding = 10px
display none
position fixed position fixed
top 0 top 0
left 0 left 0

View File

@ -66,37 +66,33 @@ export default Vue.extend({
type: 'item', type: 'item',
text: '%i18n:@contextmenu.rename%', text: '%i18n:@contextmenu.rename%',
icon: '%fa:i-cursor%', icon: '%fa:i-cursor%',
onClick: this.rename action: this.rename
}, { }, {
type: 'item', type: 'item',
text: '%i18n:@contextmenu.copy-url%', text: '%i18n:@contextmenu.copy-url%',
icon: '%fa:link%', icon: '%fa:link%',
onClick: this.copyUrl action: this.copyUrl
}, { }, {
type: 'link', type: 'link',
href: `${this.file.url}?download`, href: `${this.file.url}?download`,
text: '%i18n:@contextmenu.download%', text: '%i18n:@contextmenu.download%',
icon: '%fa:download%', icon: '%fa:download%',
}, { }, null, {
type: 'divider',
}, {
type: 'item', type: 'item',
text: '%i18n:common.delete%', text: '%i18n:common.delete%',
icon: '%fa:R trash-alt%', icon: '%fa:R trash-alt%',
onClick: this.deleteFile action: this.deleteFile
}, { }, null, {
type: 'divider',
}, {
type: 'nest', type: 'nest',
text: '%i18n:@contextmenu.else-files%', text: '%i18n:@contextmenu.else-files%',
menu: [{ menu: [{
type: 'item', type: 'item',
text: '%i18n:@contextmenu.set-as-avatar%', text: '%i18n:@contextmenu.set-as-avatar%',
onClick: this.setAsAvatar action: this.setAsAvatar
}, { }, {
type: 'item', type: 'item',
text: '%i18n:@contextmenu.set-as-banner%', text: '%i18n:@contextmenu.set-as-banner%',
onClick: this.setAsBanner action: this.setAsBanner
}] }]
}, { }, {
type: 'nest', type: 'nest',
@ -104,7 +100,7 @@ export default Vue.extend({
menu: [{ menu: [{
type: 'item', type: 'item',
text: '%i18n:@contextmenu.add-app%...', text: '%i18n:@contextmenu.add-app%...',
onClick: this.addApp action: this.addApp
}] }]
}], { }], {
closed: () => { closed: () => {

View File

@ -56,26 +56,22 @@ export default Vue.extend({
type: 'item', type: 'item',
text: '%i18n:@contextmenu.move-to-this-folder%', text: '%i18n:@contextmenu.move-to-this-folder%',
icon: '%fa:arrow-right%', icon: '%fa:arrow-right%',
onClick: this.go action: this.go
}, { }, {
type: 'item', type: 'item',
text: '%i18n:@contextmenu.show-in-new-window%', text: '%i18n:@contextmenu.show-in-new-window%',
icon: '%fa:R window-restore%', icon: '%fa:R window-restore%',
onClick: this.newWindow action: this.newWindow
}, { }, null, {
type: 'divider',
}, {
type: 'item', type: 'item',
text: '%i18n:@contextmenu.rename%', text: '%i18n:@contextmenu.rename%',
icon: '%fa:i-cursor%', icon: '%fa:i-cursor%',
onClick: this.rename action: this.rename
}, { }, null, {
type: 'divider',
}, {
type: 'item', type: 'item',
text: '%i18n:common.delete%', text: '%i18n:common.delete%',
icon: '%fa:R trash-alt%', icon: '%fa:R trash-alt%',
onClick: this.deleteFolder action: this.deleteFolder
}], { }], {
closed: () => { closed: () => {
this.isContextmenuShowing = false; this.isContextmenuShowing = false;

View File

@ -140,17 +140,17 @@ export default Vue.extend({
type: 'item', type: 'item',
text: '%i18n:@contextmenu.create-folder%', text: '%i18n:@contextmenu.create-folder%',
icon: '%fa:R folder%', icon: '%fa:R folder%',
onClick: this.createFolder action: this.createFolder
}, { }, {
type: 'item', type: 'item',
text: '%i18n:@contextmenu.upload%', text: '%i18n:@contextmenu.upload%',
icon: '%fa:upload%', icon: '%fa:upload%',
onClick: this.selectLocalFile action: this.selectLocalFile
}, { }, {
type: 'item', type: 'item',
text: '%i18n:@contextmenu.url-upload%', text: '%i18n:@contextmenu.url-upload%',
icon: '%fa:cloud-upload-alt%', icon: '%fa:cloud-upload-alt%',
onClick: this.urlUpload action: this.urlUpload
}]); }]);
}, },

View File

@ -10,6 +10,7 @@
@click="toggleActive" @click="toggleActive"
@dragstart="onDragstart" @dragstart="onDragstart"
@dragend="onDragend" @dragend="onDragend"
@contextmenu.prevent.stop="onContextmenu"
> >
<slot name="header"></slot> <slot name="header"></slot>
<span class="count" v-if="count > 0">({{ count }})</span> <span class="count" v-if="count > 0">({{ count }})</span>
@ -24,6 +25,7 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import Menu from '../../../../common/views/components/menu.vue'; import Menu from '../../../../common/views/components/menu.vue';
import contextmenu from '../../../api/contextmenu';
export default Vue.extend({ export default Vue.extend({
props: { props: {
@ -132,10 +134,11 @@ export default Vue.extend({
} }
}, },
showMenu() { getMenu() {
const items = [{ const items = [{
content: '%fa:pencil-alt% %i18n:common.deck.rename%', icon: '%fa:pencil-alt%',
onClick: () => { text: '%i18n:common.deck.rename%',
action: () => {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:common.deck.rename%', title: '%i18n:common.deck.rename%',
default: this.name, default: this.name,
@ -145,38 +148,45 @@ export default Vue.extend({
}); });
} }
}, null, { }, null, {
content: '%fa:arrow-left% %i18n:common.deck.swap-left%', icon: '%fa:arrow-left%',
onClick: () => { text: '%i18n:common.deck.swap-left%',
action: () => {
this.$store.dispatch('settings/swapLeftDeckColumn', this.column.id); this.$store.dispatch('settings/swapLeftDeckColumn', this.column.id);
} }
}, { }, {
content: '%fa:arrow-right% %i18n:common.deck.swap-right%', icon: '%fa:arrow-right%',
onClick: () => { text: '%i18n:common.deck.swap-right%',
action: () => {
this.$store.dispatch('settings/swapRightDeckColumn', this.column.id); this.$store.dispatch('settings/swapRightDeckColumn', this.column.id);
} }
}, this.isStacked ? { }, this.isStacked ? {
content: '%fa:arrow-up% %i18n:common.deck.swap-up%', icon: '%fa:arrow-up%',
onClick: () => { text: '%i18n:common.deck.swap-up%',
action: () => {
this.$store.dispatch('settings/swapUpDeckColumn', this.column.id); this.$store.dispatch('settings/swapUpDeckColumn', this.column.id);
} }
} : undefined, this.isStacked ? { } : undefined, this.isStacked ? {
content: '%fa:arrow-down% %i18n:common.deck.swap-down%', icon: '%fa:arrow-down%',
onClick: () => { text: '%i18n:common.deck.swap-down%',
action: () => {
this.$store.dispatch('settings/swapDownDeckColumn', this.column.id); this.$store.dispatch('settings/swapDownDeckColumn', this.column.id);
} }
} : undefined, null, { } : undefined, null, {
content: '%fa:window-restore R% %i18n:common.deck.stack-left%', icon: '%fa:window-restore R%',
onClick: () => { text: '%i18n:common.deck.stack-left%',
action: () => {
this.$store.dispatch('settings/stackLeftDeckColumn', this.column.id); this.$store.dispatch('settings/stackLeftDeckColumn', this.column.id);
} }
}, this.isStacked ? { }, this.isStacked ? {
content: '%fa:window-maximize R% %i18n:common.deck.pop-right%', icon: '%fa:window-maximize R%',
onClick: () => { text: '%i18n:common.deck.pop-right%',
action: () => {
this.$store.dispatch('settings/popRightDeckColumn', this.column.id); this.$store.dispatch('settings/popRightDeckColumn', this.column.id);
} }
} : undefined, null, { } : undefined, null, {
content: '%fa:trash-alt R% %i18n:common.deck.remove%', icon: '%fa:trash-alt R%',
onClick: () => { text: '%i18n:common.deck.remove%',
action: () => {
this.$store.dispatch('settings/removeDeckColumn', this.column.id); this.$store.dispatch('settings/removeDeckColumn', this.column.id);
} }
}]; }];
@ -186,10 +196,18 @@ export default Vue.extend({
this.menu.reverse().forEach(i => items.unshift(i)); this.menu.reverse().forEach(i => items.unshift(i));
} }
return items;
},
onContextmenu(e) {
contextmenu((this as any).os)(e, this.getMenu());
},
showMenu() {
this.os.new(Menu, { this.os.new(Menu, {
source: this.$refs.menu, source: this.$refs.menu,
compact: false, compact: false,
items items: this.getMenu()
}); });
}, },

View File

@ -45,8 +45,9 @@ export default Vue.extend({
return { return {
edit: false, edit: false,
menu: [{ menu: [{
content: '%fa:cog% %i18n:@edit%', icon: '%fa:cog%',
onClick: () => { text: '%i18n:@edit%',
action: () => {
this.edit = !this.edit; this.edit = !this.edit;
} }
}] }]

View File

@ -102,32 +102,36 @@ export default Vue.extend({
source: this.$refs.add, source: this.$refs.add,
compact: true, compact: true,
items: [{ items: [{
content: '%i18n:common.deck.home%', icon: '%fa:home%',
onClick: () => { text: '%i18n:common.deck.home%',
action: () => {
this.$store.dispatch('settings/addDeckColumn', { this.$store.dispatch('settings/addDeckColumn', {
id: uuid(), id: uuid(),
type: 'home' type: 'home'
}); });
} }
}, { }, {
content: '%i18n:common.deck.local%', icon: '%fa:comments R%',
onClick: () => { text: '%i18n:common.deck.local%',
action: () => {
this.$store.dispatch('settings/addDeckColumn', { this.$store.dispatch('settings/addDeckColumn', {
id: uuid(), id: uuid(),
type: 'local' type: 'local'
}); });
} }
}, { }, {
content: '%i18n:common.deck.global%', icon: '%fa:globe%',
onClick: () => { text: '%i18n:common.deck.global%',
action: () => {
this.$store.dispatch('settings/addDeckColumn', { this.$store.dispatch('settings/addDeckColumn', {
id: uuid(), id: uuid(),
type: 'global' type: 'global'
}); });
} }
}, { }, {
content: '%i18n:common.deck.list%', icon: '%fa:list%',
onClick: () => { text: '%i18n:common.deck.list%',
action: () => {
const w = (this as any).os.new(MkUserListsWindow); const w = (this as any).os.new(MkUserListsWindow);
w.$once('choosen', list => { w.$once('choosen', list => {
this.$store.dispatch('settings/addDeckColumn', { this.$store.dispatch('settings/addDeckColumn', {
@ -139,16 +143,18 @@ export default Vue.extend({
}); });
} }
}, { }, {
content: '%i18n:common.deck.notifications%', icon: '%fa:bell R%',
onClick: () => { text: '%i18n:common.deck.notifications%',
action: () => {
this.$store.dispatch('settings/addDeckColumn', { this.$store.dispatch('settings/addDeckColumn', {
id: uuid(), id: uuid(),
type: 'notifications' type: 'notifications'
}); });
} }
}, { }, {
content: '%i18n:common.deck.widgets%', icon: '%fa:calculator%',
onClick: () => { text: '%i18n:common.deck.widgets%',
action: () => {
this.$store.dispatch('settings/addDeckColumn', { this.$store.dispatch('settings/addDeckColumn', {
id: uuid(), id: uuid(),
type: 'widgets', type: 'widgets',

View File

@ -92,8 +92,9 @@ export default Vue.extend({
created() { created() {
this.menu = [{ this.menu = [{
content: '%fa:cog% %i18n:@edit%', icon: '%fa:cog%',
onClick: () => { text: '%i18n:@edit%',
action: () => {
this.edit = !this.edit; this.edit = !this.edit;
} }
}]; }];