Improve deck

This commit is contained in:
syuilo 2020-12-26 18:33:54 +09:00
parent 94598ab555
commit 78598a92f9
7 changed files with 123 additions and 98 deletions

View file

@ -1524,6 +1524,7 @@ _deck:
popRight: "右に出す" popRight: "右に出す"
_columns: _columns:
main: "メイン"
widgets: "ウィジェット" widgets: "ウィジェット"
notifications: "通知" notifications: "通知"
tl: "タイムライン" tl: "タイムライン"

View file

@ -1,31 +1,25 @@
<template> <template>
<div class="mk-deck" :class="`${deckStore.state.columnAlign}`" v-hotkey.global="keymap"> <div class="mk-deck" :class="`${deckStore.state.columnAlign}`" v-hotkey.global="keymap" @contextmenu.self.prevent="onContextmenu">
<XSidebar ref="nav"/> <XSidebar ref="nav"/>
<!-- TODO: deckMainColumnPlace を見て位置変える -->
<DeckColumn class="column" v-if="deckStore.state.alwaysShowMainColumn || $route.name !== 'index'">
<template #header>
<XHeader :info="pageInfo"/>
</template>
<router-view v-slot="{ Component }">
<transition>
<keep-alive :include="['timeline']">
<component :is="Component" :ref="changePage"/>
</keep-alive>
</transition>
</router-view>
</DeckColumn>
<template v-for="ids in layout"> <template v-for="ids in layout">
<div v-if="ids.length > 1" class="folder column"> <!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section v-if="ids.length > 1"
class="folder column"
:style="{ width: Math.max(...columns.filter(c => ids.includes(c.id)).map(c => c.width)) + 'px' }"
>
<DeckColumnCore v-for="id in ids" :ref="id" :key="id" :column="columns.find(c => c.id === id)" :is-stacked="true" @parent-focus="moveFocus(id, $event)"/> <DeckColumnCore v-for="id in ids" :ref="id" :key="id" :column="columns.find(c => c.id === id)" :is-stacked="true" @parent-focus="moveFocus(id, $event)"/>
</div> </section>
<DeckColumnCore v-else class="column" :ref="ids[0]" :key="ids[0]" :column="columns.find(c => c.id === ids[0])" @parent-focus="moveFocus(ids[0], $event)"/> <DeckColumnCore v-else
class="column"
:ref="ids[0]"
:key="ids[0]"
:column="columns.find(c => c.id === ids[0])"
@parent-focus="moveFocus(ids[0], $event)"
:style="columns.find(c => c.id === ids[0]).flexible ? { flex: 1 } : { width: columns.find(c => c.id === ids[0]).width + 'px' }"
/>
</template> </template>
<button @click="addColumn" class="_button add"><Fa :icon="faPlus"/></button>
<button v-if="$i" class="nav _button" @click="showNav()"><Fa :icon="faBars"/><i v-if="navIndicated"><Fa :icon="faCircle"/></i></button> <button v-if="$i" class="nav _button" @click="showNav()"><Fa :icon="faBars"/><i v-if="navIndicated"><Fa :icon="faCircle"/></i></button>
<button v-if="$i" class="post _buttonPrimary" @click="post()"><Fa :icon="faPencilAlt"/></button> <button v-if="$i" class="post _buttonPrimary" @click="post()"><Fa :icon="faPencilAlt"/></button>
@ -41,9 +35,7 @@ import { v4 as uuid } from 'uuid';
import { host } from '@/config'; import { host } from '@/config';
import { search } from '@/scripts/search'; import { search } from '@/scripts/search';
import DeckColumnCore from '@/ui/deck/column-core.vue'; import DeckColumnCore from '@/ui/deck/column-core.vue';
import DeckColumn from '@/ui/deck/column.vue';
import XSidebar from '@/components/sidebar.vue'; import XSidebar from '@/components/sidebar.vue';
import XHeader from './_common_/header.vue';
import { getScrollContainer } from '@/scripts/scroll'; import { getScrollContainer } from '@/scripts/scroll';
import * as os from '@/os'; import * as os from '@/os';
import { sidebarDef } from '@/sidebar'; import { sidebarDef } from '@/sidebar';
@ -54,8 +46,6 @@ export default defineComponent({
components: { components: {
XCommon, XCommon,
XSidebar, XSidebar,
XHeader,
DeckColumn,
DeckColumnCore, DeckColumnCore,
}, },
@ -63,8 +53,6 @@ export default defineComponent({
return { return {
deckStore, deckStore,
host: host, host: host,
pageInfo: null,
pageKey: 0,
menuDef: sidebarDef, menuDef: sidebarDef,
wallpaper: localStorage.getItem('wallpaper') != null, wallpaper: localStorage.getItem('wallpaper') != null,
faPlus, faPencilAlt, faChevronLeft, faBars, faCircle faPlus, faPencilAlt, faChevronLeft, faBars, faCircle
@ -95,12 +83,6 @@ export default defineComponent({
}, },
}, },
watch: {
$route(to, from) {
this.pageKey++;
},
},
created() { created() {
document.documentElement.style.overflowY = 'hidden'; document.documentElement.style.overflowY = 'hidden';
document.documentElement.style.scrollBehavior = 'auto'; document.documentElement.style.scrollBehavior = 'auto';
@ -111,13 +93,6 @@ export default defineComponent({
}, },
methods: { methods: {
changePage(page) {
if (page == null) return;
if (page.INFO) {
this.pageInfo = page.INFO;
}
},
onWheel(e) { onWheel(e) {
if (getScrollContainer(e.target) == null) { if (getScrollContainer(e.target) == null) {
document.documentElement.scrollLeft += e.deltaY > 0 ? 96 : -96; document.documentElement.scrollLeft += e.deltaY > 0 ? 96 : -96;
@ -138,6 +113,7 @@ export default defineComponent({
async addColumn(ev) { async addColumn(ev) {
const columns = [ const columns = [
'main',
'widgets', 'widgets',
'notifications', 'notifications',
'tl', 'tl',
@ -166,6 +142,14 @@ export default defineComponent({
width: 330, width: 330,
}); });
}, },
onContextmenu(e) {
os.contextMenu([{
text: this.$ts._deck.addColumn,
icon: null,
action: this.addColumn
}], e);
},
} }
}); });
</script> </script>
@ -175,7 +159,7 @@ export default defineComponent({
$nav-hide-threshold: 650px; // TODO: $nav-hide-threshold: 650px; // TODO:
// TODO: // TODO:
$columnMargin: 12px; $columnMargin: 32px;
$deckMargin: $columnMargin; $deckMargin: $columnMargin;
@ -186,14 +170,14 @@ export default defineComponent({
height: calc(var(--vh, 1vh) * 100); height: calc(var(--vh, 1vh) * 100);
box-sizing: border-box; box-sizing: border-box;
flex: 1; flex: 1;
padding: $deckMargin 0 $deckMargin $deckMargin; padding: $deckMargin;
&.center { &.center {
> .column:first-of-type { > .column:first-of-type {
margin-left: auto; margin-left: auto;
} }
> .add { > .column:last-of-type {
margin-right: auto; margin-right: auto;
} }
} }

View file

@ -1,6 +1,7 @@
<template> <template>
<!-- TODO: リファクタの余地がありそう --> <!-- TODO: リファクタの余地がありそう -->
<XWidgetsColumn v-if="column.type === 'widgets'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/> <XMainColumn v-if="column.type === 'main'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/>
<XWidgetsColumn v-else-if="column.type === 'widgets'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/>
<XNotificationsColumn v-else-if="column.type === 'notifications'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/> <XNotificationsColumn v-else-if="column.type === 'notifications'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/>
<XTlColumn v-else-if="column.type === 'tl'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/> <XTlColumn v-else-if="column.type === 'tl'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/>
<XListColumn v-else-if="column.type === 'list'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/> <XListColumn v-else-if="column.type === 'list'" :column="column" :is-stacked="isStacked" @parent-focus="$emit('parent-focus', $event)"/>
@ -12,6 +13,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import XMainColumn from './main-column.vue';
import XTlColumn from './tl-column.vue'; import XTlColumn from './tl-column.vue';
import XAntennaColumn from './antenna-column.vue'; import XAntennaColumn from './antenna-column.vue';
import XListColumn from './list-column.vue'; import XListColumn from './list-column.vue';
@ -22,6 +24,7 @@ import XDirectColumn from './direct-column.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
XMainColumn,
XTlColumn, XTlColumn,
XAntennaColumn, XAntennaColumn,
XListColumn, XListColumn,

View file

@ -5,7 +5,6 @@
@dragleave="onDragleave" @dragleave="onDragleave"
@drop.prevent.stop="onDrop" @drop.prevent.stop="onDrop"
v-hotkey="keymap" v-hotkey="keymap"
:style="{ width: `${width}px` }"
> >
<header :class="{ indicated }" <header :class="{ indicated }"
draggable="true" draggable="true"
@ -14,7 +13,7 @@
@dragend="onDragend" @dragend="onDragend"
@contextmenu.prevent.stop="onContextmenu" @contextmenu.prevent.stop="onContextmenu"
> >
<button class="toggleActive _button" @click="toggleActive" v-if="isStacked"> <button class="toggleActive _button" @click="toggleActive" v-if="isStacked && !isMainColumn">
<template v-if="active"><Fa :icon="faAngleUp"/></template> <template v-if="active"><Fa :icon="faAngleUp"/></template>
<template v-else><Fa :icon="faAngleDown"/></template> <template v-else><Fa :icon="faAngleDown"/></template>
</button> </button>
@ -35,7 +34,7 @@ import { defineComponent } from 'vue';
import { faArrowUp, faArrowDown, faAngleUp, faAngleDown, faCaretDown, faArrowRight, faArrowLeft, faPencilAlt } from '@fortawesome/free-solid-svg-icons'; import { faArrowUp, faArrowDown, faAngleUp, faAngleDown, faCaretDown, faArrowRight, faArrowLeft, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
import { faWindowMaximize, faTrashAlt, faWindowRestore } from '@fortawesome/free-regular-svg-icons'; import { faWindowMaximize, faTrashAlt, faWindowRestore } from '@fortawesome/free-regular-svg-icons';
import * as os from '@/os'; import * as os from '@/os';
import { renameColumn, swapLeftColumn, swapRightColumn, swapUpColumn, swapDownColumn, stackLeftColumn, popRightColumn, removeColumn, swapColumn } from './deck-store'; import { updateColumn, swapLeftColumn, swapRightColumn, swapUpColumn, swapDownColumn, stackLeftColumn, popRightColumn, removeColumn, swapColumn } from './deck-store';
export default defineComponent({ export default defineComponent({
props: { props: {
@ -78,11 +77,7 @@ export default defineComponent({
computed: { computed: {
isMainColumn(): boolean { isMainColumn(): boolean {
return this.column == null; return this.column.type === 'main';
},
width(): number {
return this.isMainColumn ? 350 : this.column.width;
}, },
keymap(): any { keymap(): any {
@ -106,17 +101,13 @@ export default defineComponent({
}, },
mounted() { mounted() {
if (!this.isMainColumn) {
os.deckGlobalEvents.on('column.dragStart', this.onOtherDragStart); os.deckGlobalEvents.on('column.dragStart', this.onOtherDragStart);
os.deckGlobalEvents.on('column.dragEnd', this.onOtherDragEnd); os.deckGlobalEvents.on('column.dragEnd', this.onOtherDragEnd);
}
}, },
beforeUnmount() { beforeUnmount() {
if (!this.isMainColumn) {
os.deckGlobalEvents.off('column.dragStart', this.onOtherDragStart); os.deckGlobalEvents.off('column.dragStart', this.onOtherDragStart);
os.deckGlobalEvents.off('column.dragEnd', this.onOtherDragEnd); os.deckGlobalEvents.off('column.dragEnd', this.onOtherDragEnd);
}
}, },
methods: { methods: {
@ -136,18 +127,27 @@ export default defineComponent({
getMenu() { getMenu() {
const items = [{ const items = [{
icon: faPencilAlt, icon: faPencilAlt,
text: this.$ts.rename, text: this.$ts.edit,
action: () => { action: async () => {
os.dialog({ const { canceled, result } = await os.form(this.column.name, {
title: this.$ts.rename, name: {
input: { type: 'string',
default: this.column.name, label: this.$ts.name,
allowEmpty: false default: this.column.name
},
width: {
type: 'number',
label: this.$ts.width,
default: this.column.width
},
flexible: {
type: 'boolean',
label: this.$ts.flexible,
default: this.column.flexible
} }
}).then(({ canceled, result: name }) => {
if (canceled) return;
renameColumn(this.column.id, name);
}); });
if (canceled) return;
updateColumn(this.column.id, result);
} }
}, null, { }, null, {
icon: faArrowLeft, icon: faArrowLeft,
@ -203,8 +203,7 @@ export default defineComponent({
}, },
onContextmenu(e) { onContextmenu(e) {
if (this.isMainColumn) return; os.contextMenu(this.getMenu(), e);
this.showMenu();
}, },
showMenu() { showMenu() {
@ -219,12 +218,6 @@ export default defineComponent({
}, },
onDragstart(e) { onDragstart(e) {
//
if (this.isMainColumn) {
e.preventDefault();
return;
}
e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData(_DATA_TRANSFER_DECK_COLUMN_, this.column.id); e.dataTransfer.setData(_DATA_TRANSFER_DECK_COLUMN_, this.column.id);
this.dragging = true; this.dragging = true;
@ -235,12 +228,6 @@ export default defineComponent({
}, },
onDragover(e) { onDragover(e) {
//
if (this.isMainColumn) {
e.dataTransfer.dropEffect = 'none';
return;
}
// //
if (this.dragging) { if (this.dragging) {
// //

View file

@ -36,10 +36,6 @@ export const deckStore = markRaw(new Storage('deck', {
where: 'deviceAccount', where: 'deviceAccount',
default: true default: true
}, },
mainColumnPlace: {
where: 'deviceAccount',
default: 'left' as 'left' | 'right'
},
navWindow: { navWindow: {
where: 'deviceAccount', where: 'deviceAccount',
default: true default: true
@ -200,16 +196,6 @@ export function updateColumnWidget(id: Column['id'], widgetId: string, data: any
deckStore.set('columns', columns); deckStore.set('columns', columns);
} }
export function renameColumn(id: Column['id'], name: Column['name']) {
const columns = copy(deckStore.state.columns);
const columnIndex = deckStore.state.columns.findIndex(c => c.id === id);
const column = copy(deckStore.state.columns[columnIndex]);
if (column == null) return;
column.name = name;
columns[columnIndex] = column;
deckStore.set('columns', columns);
}
export function updateColumn(id: Column['id'], column: Partial<Column>) { export function updateColumn(id: Column['id'], column: Partial<Column>) {
const columns = copy(deckStore.state.columns); const columns = copy(deckStore.state.columns);
const columnIndex = deckStore.state.columns.findIndex(c => c.id === id); const columnIndex = deckStore.state.columns.findIndex(c => c.id === id);

View file

@ -0,0 +1,59 @@
<template>
<XColumn v-if="deckStore.state.alwaysShowMainColumn || $route.name !== 'index'" :column="column" :is-stacked="isStacked">
<template #header>
<XHeader :info="pageInfo"/>
</template>
<router-view v-slot="{ Component }">
<transition>
<keep-alive :include="['timeline']">
<component :is="Component" :ref="changePage"/>
</keep-alive>
</transition>
</router-view>
</XColumn>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import XColumn from './column.vue';
import XNotes from '@/components/notes.vue';
import XHeader from '@/ui/_common_/header.vue';
import { deckStore } from '@/ui/deck/deck-store';
export default defineComponent({
components: {
XColumn,
XHeader,
XNotes
},
props: {
column: {
type: Object,
required: true
},
isStacked: {
type: Boolean,
required: true
}
},
data() {
return {
deckStore,
pageInfo: null,
pageKey: 0,
}
},
methods: {
changePage(page) {
if (page == null) return;
if (page.INFO) {
this.pageInfo = page.INFO;
}
},
}
});
</script>

View file

@ -104,6 +104,11 @@
document.documentElement.classList.add('useSystemFont'); document.documentElement.classList.add('useSystemFont');
} }
const wallpaper = localStorage.getItem('wallpaper');
if (wallpaper) {
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
}
// eslint-disable-next-line no-inner-declarations // eslint-disable-next-line no-inner-declarations
function refresh() { function refresh() {
// Random // Random