Improve deck
This commit is contained in:
		
							parent
							
								
									94598ab555
								
							
						
					
					
						commit
						78598a92f9
					
				
					 7 changed files with 123 additions and 98 deletions
				
			
		|  | @ -1524,6 +1524,7 @@ _deck: | |||
|   popRight: "右に出す" | ||||
| 
 | ||||
|   _columns: | ||||
|     main: "メイン" | ||||
|     widgets: "ウィジェット" | ||||
|     notifications: "通知" | ||||
|     tl: "タイムライン" | ||||
|  |  | |||
|  | @ -1,31 +1,25 @@ | |||
| <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"/> | ||||
| 
 | ||||
| 	<!-- 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"> | ||||
| 		<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)"/> | ||||
| 		</div> | ||||
| 		<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)"/> | ||||
| 		</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)" | ||||
| 			:style="columns.find(c => c.id === ids[0]).flexible ? { flex: 1 } : { width: columns.find(c => c.id === ids[0]).width + 'px' }" | ||||
| 		/> | ||||
| 	</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="post _buttonPrimary" @click="post()"><Fa :icon="faPencilAlt"/></button> | ||||
| 
 | ||||
|  | @ -41,9 +35,7 @@ import { v4 as uuid } from 'uuid'; | |||
| import { host } from '@/config'; | ||||
| import { search } from '@/scripts/search'; | ||||
| import DeckColumnCore from '@/ui/deck/column-core.vue'; | ||||
| import DeckColumn from '@/ui/deck/column.vue'; | ||||
| import XSidebar from '@/components/sidebar.vue'; | ||||
| import XHeader from './_common_/header.vue'; | ||||
| import { getScrollContainer } from '@/scripts/scroll'; | ||||
| import * as os from '@/os'; | ||||
| import { sidebarDef } from '@/sidebar'; | ||||
|  | @ -54,8 +46,6 @@ export default defineComponent({ | |||
| 	components: { | ||||
| 		XCommon, | ||||
| 		XSidebar, | ||||
| 		XHeader, | ||||
| 		DeckColumn, | ||||
| 		DeckColumnCore, | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -63,8 +53,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			deckStore, | ||||
| 			host: host, | ||||
| 			pageInfo: null, | ||||
| 			pageKey: 0, | ||||
| 			menuDef: sidebarDef, | ||||
| 			wallpaper: localStorage.getItem('wallpaper') != null, | ||||
| 			faPlus, faPencilAlt, faChevronLeft, faBars, faCircle | ||||
|  | @ -95,12 +83,6 @@ export default defineComponent({ | |||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	watch: { | ||||
| 		$route(to, from) { | ||||
| 			this.pageKey++; | ||||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	created() { | ||||
| 		document.documentElement.style.overflowY = 'hidden'; | ||||
| 		document.documentElement.style.scrollBehavior = 'auto'; | ||||
|  | @ -111,13 +93,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		changePage(page) { | ||||
| 			if (page == null) return; | ||||
| 			if (page.INFO) { | ||||
| 				this.pageInfo = page.INFO; | ||||
| 			} | ||||
| 		}, | ||||
| 
 | ||||
| 		onWheel(e) { | ||||
| 			if (getScrollContainer(e.target) == null) { | ||||
| 				document.documentElement.scrollLeft += e.deltaY > 0 ? 96 : -96; | ||||
|  | @ -138,6 +113,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 		async addColumn(ev) { | ||||
| 			const columns = [ | ||||
| 				'main', | ||||
| 				'widgets', | ||||
| 				'notifications', | ||||
| 				'tl', | ||||
|  | @ -166,6 +142,14 @@ export default defineComponent({ | |||
| 				width: 330, | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		onContextmenu(e) { | ||||
| 			os.contextMenu([{ | ||||
| 				text: this.$ts._deck.addColumn, | ||||
| 				icon: null, | ||||
| 				action: this.addColumn | ||||
| 			}], e); | ||||
| 		}, | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
|  | @ -175,7 +159,7 @@ export default defineComponent({ | |||
| 	$nav-hide-threshold: 650px; // TODO: どこかに集約したい | ||||
| 
 | ||||
| 	// TODO: この値を設定で変えられるようにする? | ||||
| 	$columnMargin: 12px; | ||||
| 	$columnMargin: 32px; | ||||
| 
 | ||||
| 	$deckMargin: $columnMargin; | ||||
| 
 | ||||
|  | @ -186,14 +170,14 @@ export default defineComponent({ | |||
| 	height: calc(var(--vh, 1vh) * 100); | ||||
| 	box-sizing: border-box; | ||||
| 	flex: 1; | ||||
| 	padding: $deckMargin 0 $deckMargin $deckMargin; | ||||
| 	padding: $deckMargin; | ||||
| 
 | ||||
| 	&.center { | ||||
| 		> .column:first-of-type { | ||||
| 			margin-left: auto; | ||||
| 		} | ||||
| 
 | ||||
| 		> .add { | ||||
| 		> .column:last-of-type { | ||||
| 			margin-right: auto; | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| <template> | ||||
| <!-- 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)"/> | ||||
| <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)"/> | ||||
|  | @ -12,6 +13,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import XMainColumn from './main-column.vue'; | ||||
| import XTlColumn from './tl-column.vue'; | ||||
| import XAntennaColumn from './antenna-column.vue'; | ||||
| import XListColumn from './list-column.vue'; | ||||
|  | @ -22,6 +24,7 @@ import XDirectColumn from './direct-column.vue'; | |||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		XMainColumn, | ||||
| 		XTlColumn, | ||||
| 		XAntennaColumn, | ||||
| 		XListColumn, | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ | |||
| 	@dragleave="onDragleave" | ||||
| 	@drop.prevent.stop="onDrop" | ||||
| 	v-hotkey="keymap" | ||||
| 	:style="{ width: `${width}px` }" | ||||
| > | ||||
| 	<header :class="{ indicated }" | ||||
| 		draggable="true" | ||||
|  | @ -14,7 +13,7 @@ | |||
| 		@dragend="onDragend" | ||||
| 		@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-else><Fa :icon="faAngleDown"/></template> | ||||
| 		</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 { faWindowMaximize, faTrashAlt, faWindowRestore } from '@fortawesome/free-regular-svg-icons'; | ||||
| 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({ | ||||
| 	props: { | ||||
|  | @ -78,11 +77,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 	computed: { | ||||
| 		isMainColumn(): boolean { | ||||
| 			return this.column == null; | ||||
| 		}, | ||||
| 
 | ||||
| 		width(): number { | ||||
| 			return this.isMainColumn ? 350 : this.column.width; | ||||
| 			return this.column.type === 'main'; | ||||
| 		}, | ||||
| 
 | ||||
| 		keymap(): any { | ||||
|  | @ -106,17 +101,13 @@ export default defineComponent({ | |||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		if (!this.isMainColumn) { | ||||
| 			os.deckGlobalEvents.on('column.dragStart', this.onOtherDragStart); | ||||
| 			os.deckGlobalEvents.on('column.dragEnd', this.onOtherDragEnd); | ||||
| 		} | ||||
| 		os.deckGlobalEvents.on('column.dragStart', this.onOtherDragStart); | ||||
| 		os.deckGlobalEvents.on('column.dragEnd', this.onOtherDragEnd); | ||||
| 	}, | ||||
| 
 | ||||
| 	beforeUnmount() { | ||||
| 		if (!this.isMainColumn) { | ||||
| 			os.deckGlobalEvents.off('column.dragStart', this.onOtherDragStart); | ||||
| 			os.deckGlobalEvents.off('column.dragEnd', this.onOtherDragEnd); | ||||
| 		} | ||||
| 		os.deckGlobalEvents.off('column.dragStart', this.onOtherDragStart); | ||||
| 		os.deckGlobalEvents.off('column.dragEnd', this.onOtherDragEnd); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
|  | @ -136,18 +127,27 @@ export default defineComponent({ | |||
| 		getMenu() { | ||||
| 			const items = [{ | ||||
| 				icon: faPencilAlt, | ||||
| 				text: this.$ts.rename, | ||||
| 				action: () => { | ||||
| 					os.dialog({ | ||||
| 						title: this.$ts.rename, | ||||
| 						input: { | ||||
| 							default: this.column.name, | ||||
| 							allowEmpty: false | ||||
| 				text: this.$ts.edit, | ||||
| 				action: async () => { | ||||
| 					const { canceled, result } = await os.form(this.column.name, { | ||||
| 						name: { | ||||
| 							type: 'string', | ||||
| 							label: this.$ts.name, | ||||
| 							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, { | ||||
| 				icon: faArrowLeft, | ||||
|  | @ -203,8 +203,7 @@ export default defineComponent({ | |||
| 		}, | ||||
| 
 | ||||
| 		onContextmenu(e) { | ||||
| 			if (this.isMainColumn) return; | ||||
| 			this.showMenu(); | ||||
| 			os.contextMenu(this.getMenu(), e); | ||||
| 		}, | ||||
| 
 | ||||
| 		showMenu() { | ||||
|  | @ -219,12 +218,6 @@ export default defineComponent({ | |||
| 		}, | ||||
| 
 | ||||
| 		onDragstart(e) { | ||||
| 			// メインカラムはドラッグさせない | ||||
| 			if (this.isMainColumn) { | ||||
| 				e.preventDefault(); | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			e.dataTransfer.effectAllowed = 'move'; | ||||
| 			e.dataTransfer.setData(_DATA_TRANSFER_DECK_COLUMN_, this.column.id); | ||||
| 			this.dragging = true; | ||||
|  | @ -235,12 +228,6 @@ export default defineComponent({ | |||
| 		}, | ||||
| 
 | ||||
| 		onDragover(e) { | ||||
| 			// メインカラムにはドロップさせない | ||||
| 			if (this.isMainColumn) { | ||||
| 				e.dataTransfer.dropEffect = 'none'; | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			// 自分自身がドラッグされている場合 | ||||
| 			if (this.dragging) { | ||||
| 				// 自分自身にはドロップさせない | ||||
|  |  | |||
|  | @ -36,10 +36,6 @@ export const deckStore = markRaw(new Storage('deck', { | |||
| 		where: 'deviceAccount', | ||||
| 		default: true | ||||
| 	}, | ||||
| 	mainColumnPlace: { | ||||
| 		where: 'deviceAccount', | ||||
| 		default: 'left' as 'left' | 'right' | ||||
| 	}, | ||||
| 	navWindow: { | ||||
| 		where: 'deviceAccount', | ||||
| 		default: true | ||||
|  | @ -200,16 +196,6 @@ export function updateColumnWidget(id: Column['id'], widgetId: string, data: any | |||
| 	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>) { | ||||
| 	const columns = copy(deckStore.state.columns); | ||||
| 	const columnIndex = deckStore.state.columns.findIndex(c => c.id === id); | ||||
|  |  | |||
							
								
								
									
										59
									
								
								src/client/ui/deck/main-column.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/client/ui/deck/main-column.vue
									
										
									
									
									
										Normal 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> | ||||
|  | @ -104,6 +104,11 @@ | |||
| 		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
 | ||||
| 	function refresh() { | ||||
| 		// Random
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue