MisskeyDeck: カラムをスタックできるように
This commit is contained in:
		
							parent
							
								
									44ef60c8a2
								
							
						
					
					
						commit
						79d592b431
					
				
					 9 changed files with 275 additions and 143 deletions
				
			
		| 
						 | 
					@ -88,6 +88,8 @@ common:
 | 
				
			||||||
    remove: "カラムを削除"
 | 
					    remove: "カラムを削除"
 | 
				
			||||||
    add-column: "カラムを追加"
 | 
					    add-column: "カラムを追加"
 | 
				
			||||||
    rename: "名前を変更"
 | 
					    rename: "名前を変更"
 | 
				
			||||||
 | 
					    stack-left: "左に重ねる"
 | 
				
			||||||
 | 
					    pop-right: "右に出す"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
common/views/components/connect-failed.vue:
 | 
					common/views/components/connect-failed.vue:
 | 
				
			||||||
  title: "サーバーに接続できません"
 | 
					  title: "サーバーに接続できません"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="mk-menu">
 | 
					<div class="mk-menu">
 | 
				
			||||||
	<div class="backdrop" ref="backdrop" @click="close"></div>
 | 
						<div class="backdrop" ref="backdrop" @click="close"></div>
 | 
				
			||||||
	<div class="popover" :class="{ compact }" 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-else @click="clicked(item.onClick)" v-html="item.content"></button>
 | 
								<button v-else @click="clicked(item.onClick)" v-html="item.content"></button>
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,11 @@ import * as anime from 'animejs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	props: ['source', 'compact', 'items'],
 | 
						props: ['source', 'compact', 'items'],
 | 
				
			||||||
 | 
						data() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								hukidasi: !this.compact
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	mounted() {
 | 
						mounted() {
 | 
				
			||||||
		this.$nextTick(() => {
 | 
							this.$nextTick(() => {
 | 
				
			||||||
			const popover = this.$refs.popover as any;
 | 
								const popover = this.$refs.popover as any;
 | 
				
			||||||
| 
						 | 
					@ -24,18 +29,34 @@ export default Vue.extend({
 | 
				
			||||||
			const width = popover.offsetWidth;
 | 
								const width = popover.offsetWidth;
 | 
				
			||||||
			const height = popover.offsetHeight;
 | 
								const height = popover.offsetHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								let left;
 | 
				
			||||||
 | 
								let top;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (this.compact) {
 | 
								if (this.compact) {
 | 
				
			||||||
				const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
 | 
									const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
 | 
				
			||||||
				const y = rect.top + window.pageYOffset + (this.source.offsetHeight / 2);
 | 
									const y = rect.top + window.pageYOffset + (this.source.offsetHeight / 2);
 | 
				
			||||||
				popover.style.left = (x - (width / 2)) + 'px';
 | 
									left = (x - (width / 2));
 | 
				
			||||||
				popover.style.top = (y - (height / 2)) + 'px';
 | 
									top = (y - (height / 2));
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
 | 
									const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
 | 
				
			||||||
				const y = rect.top + window.pageYOffset + this.source.offsetHeight;
 | 
									const y = rect.top + window.pageYOffset + this.source.offsetHeight;
 | 
				
			||||||
				popover.style.left = (x - (width / 2)) + 'px';
 | 
									left = (x - (width / 2));
 | 
				
			||||||
				popover.style.top = y + 'px';
 | 
									top = y;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (left + width > window.innerWidth) {
 | 
				
			||||||
 | 
									left = window.innerWidth - width;
 | 
				
			||||||
 | 
									this.hukidasi = false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (top + height > window.innerHeight) {
 | 
				
			||||||
 | 
									top = window.innerHeight - height;
 | 
				
			||||||
 | 
									this.hukidasi = false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								popover.style.left = left + 'px';
 | 
				
			||||||
 | 
								popover.style.top = top + 'px';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			anime({
 | 
								anime({
 | 
				
			||||||
				targets: this.$refs.backdrop,
 | 
									targets: this.$refs.backdrop,
 | 
				
			||||||
				opacity: 1,
 | 
									opacity: 1,
 | 
				
			||||||
| 
						 | 
					@ -113,7 +134,7 @@ $border-color = rgba(27, 31, 35, 0.15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$balloon-size = 16px
 | 
							$balloon-size = 16px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		&:not(.compact)
 | 
							&.hukidasi
 | 
				
			||||||
			margin-top $balloon-size
 | 
								margin-top $balloon-size
 | 
				
			||||||
			transform-origin center -($balloon-size)
 | 
								transform-origin center -($balloon-size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										48
									
								
								src/client/app/desktop/views/pages/deck/deck.column-core.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/client/app/desktop/views/pages/deck/deck.column-core.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,48 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<x-widgets-column v-if="column.type == 'widgets'"/>
 | 
				
			||||||
 | 
					<x-notifications-column v-else-if="column.type == 'notifications'"/>
 | 
				
			||||||
 | 
					<x-tl-column v-else-if="column.type == 'home'"/>
 | 
				
			||||||
 | 
					<x-tl-column v-else-if="column.type == 'local'"/>
 | 
				
			||||||
 | 
					<x-tl-column v-else-if="column.type == 'global'"/>
 | 
				
			||||||
 | 
					<x-tl-column v-else-if="column.type == 'list'"/>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					import XTlColumn from './deck.tl-column.vue';
 | 
				
			||||||
 | 
					import XNotificationsColumn from './deck.notifications-column.vue';
 | 
				
			||||||
 | 
					import XWidgetsColumn from './deck.widgets-column.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						components: {
 | 
				
			||||||
 | 
							XTlColumn,
 | 
				
			||||||
 | 
							XNotificationsColumn,
 | 
				
			||||||
 | 
							XWidgetsColumn
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							column: {
 | 
				
			||||||
 | 
								type: Object,
 | 
				
			||||||
 | 
								required: true
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							isStacked: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false,
 | 
				
			||||||
 | 
								default: false
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							isActive: {
 | 
				
			||||||
 | 
								type: Boolean,
 | 
				
			||||||
 | 
								required: false,
 | 
				
			||||||
 | 
								default: true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						provide() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								column: this.column,
 | 
				
			||||||
 | 
								isStacked: this.isStacked,
 | 
				
			||||||
 | 
								isActive: this.isActive
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs" :class="{ naked, narrow }">
 | 
					<div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs" :class="{ naked, narrow, isActive, isStacked }">
 | 
				
			||||||
	<header :class="{ indicate }">
 | 
						<header :class="{ indicate }" @click="toggleActive">
 | 
				
			||||||
		<slot name="header"></slot>
 | 
							<slot name="header"></slot>
 | 
				
			||||||
		<button ref="menu" @click="showMenu">%fa:caret-down%</button>
 | 
							<button ref="menu" @click.stop="showMenu">%fa:caret-down%</button>
 | 
				
			||||||
	</header>
 | 
						</header>
 | 
				
			||||||
	<div ref="body">
 | 
						<div ref="body" v-show="isActive">
 | 
				
			||||||
		<slot></slot>
 | 
							<slot></slot>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
| 
						 | 
					@ -16,17 +16,14 @@ import Menu from '../../../../common/views/components/menu.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	props: {
 | 
						props: {
 | 
				
			||||||
		id: {
 | 
					 | 
				
			||||||
			type: String,
 | 
					 | 
				
			||||||
			required: false
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		name: {
 | 
							name: {
 | 
				
			||||||
			type: String,
 | 
								type: String,
 | 
				
			||||||
			required: false
 | 
								required: false
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		menu: {
 | 
							menu: {
 | 
				
			||||||
			type: Array,
 | 
								type: Array,
 | 
				
			||||||
			required: false
 | 
								required: false,
 | 
				
			||||||
 | 
								default: null
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		naked: {
 | 
							naked: {
 | 
				
			||||||
			type: Boolean,
 | 
								type: Boolean,
 | 
				
			||||||
| 
						 | 
					@ -40,9 +37,17 @@ export default Vue.extend({
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inject: {
 | 
				
			||||||
 | 
							column: { from: 'column' },
 | 
				
			||||||
 | 
							_isActive: { from: 'isActive' },
 | 
				
			||||||
 | 
							isStacked: { from: 'isStacked' },
 | 
				
			||||||
 | 
							getColumnVm: { from: 'getColumnVm' }
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data() {
 | 
						data() {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			indicate: false
 | 
								indicate: false,
 | 
				
			||||||
 | 
								isActive: this._isActive
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,6 +67,13 @@ export default Vue.extend({
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
 | 
							toggleActive() {
 | 
				
			||||||
 | 
								if (!this.isStacked) return;
 | 
				
			||||||
 | 
								const vms = this.$store.state.settings.deck.layout.find(ids => ids.indexOf(this.column.id) != -1).map(id => this.getColumnVm(id));
 | 
				
			||||||
 | 
								if (this.isActive && vms.filter(vm => vm.$el.classList.contains('isActive')).length == 1) return;
 | 
				
			||||||
 | 
								this.isActive = !this.isActive;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		isScrollTop() {
 | 
							isScrollTop() {
 | 
				
			||||||
			return this.$refs.body.scrollTop == 0;
 | 
								return this.$refs.body.scrollTop == 0;
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					@ -86,23 +98,33 @@ export default Vue.extend({
 | 
				
			||||||
						default: this.name,
 | 
											default: this.name,
 | 
				
			||||||
						allowEmpty: false
 | 
											allowEmpty: false
 | 
				
			||||||
					}).then(name => {
 | 
										}).then(name => {
 | 
				
			||||||
						this.$store.dispatch('settings/renameDeckColumn', { id: this.id, name });
 | 
											this.$store.dispatch('settings/renameDeckColumn', { id: this.column.id, name });
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}, null, {
 | 
								}, null, {
 | 
				
			||||||
				content: '%fa:arrow-left% %i18n:common.deck.swap-left%',
 | 
									content: '%fa:arrow-left% %i18n:common.deck.swap-left%',
 | 
				
			||||||
				onClick: () => {
 | 
									onClick: () => {
 | 
				
			||||||
					this.$store.dispatch('settings/swapLeftDeckColumn', this.id);
 | 
										this.$store.dispatch('settings/swapLeftDeckColumn', this.column.id);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
				content: '%fa:arrow-right% %i18n:common.deck.swap-right%',
 | 
									content: '%fa:arrow-right% %i18n:common.deck.swap-right%',
 | 
				
			||||||
				onClick: () => {
 | 
									onClick: () => {
 | 
				
			||||||
					this.$store.dispatch('settings/swapRightDeckColumn', this.id);
 | 
										this.$store.dispatch('settings/swapRightDeckColumn', this.column.id);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}, null, {
 | 
				
			||||||
 | 
									content: '%fa:window-restore R% %i18n:common.deck.stack-left%',
 | 
				
			||||||
 | 
									onClick: () => {
 | 
				
			||||||
 | 
										this.$store.dispatch('settings/stackLeftDeckColumn', this.column.id);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									content: '%fa:window-restore R% %i18n:common.deck.pop-right%',
 | 
				
			||||||
 | 
									onClick: () => {
 | 
				
			||||||
 | 
										this.$store.dispatch('settings/popRightDeckColumn', this.column.id);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}, null, {
 | 
								}, null, {
 | 
				
			||||||
				content: '%fa:trash-alt R% %i18n:common.deck.remove%',
 | 
									content: '%fa:trash-alt R% %i18n:common.deck.remove%',
 | 
				
			||||||
				onClick: () => {
 | 
									onClick: () => {
 | 
				
			||||||
					this.$store.dispatch('settings/removeDeckColumn', this.id);
 | 
										this.$store.dispatch('settings/removeDeckColumn', this.column.id);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}];
 | 
								}];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,14 +150,20 @@ root(isDark)
 | 
				
			||||||
	$header-height = 42px
 | 
						$header-height = 42px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	width 330px
 | 
						width 330px
 | 
				
			||||||
 | 
						min-width 330px
 | 
				
			||||||
	height 100%
 | 
						height 100%
 | 
				
			||||||
	background isDark ? #282C37 : #fff
 | 
						background isDark ? #282C37 : #fff
 | 
				
			||||||
	border-radius 6px
 | 
						border-radius 6px
 | 
				
			||||||
	box-shadow 0 2px 16px rgba(#000, 0.1)
 | 
						box-shadow 0 2px 16px rgba(#000, 0.1)
 | 
				
			||||||
	overflow hidden
 | 
						overflow hidden
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	&.narrow
 | 
						&:not(.isActive)
 | 
				
			||||||
 | 
							flex-basis $header-height
 | 
				
			||||||
 | 
							min-height $header-height
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&:not(.isStacked).narrow
 | 
				
			||||||
		width 285px
 | 
							width 285px
 | 
				
			||||||
 | 
							min-width 285px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	&.naked
 | 
						&.naked
 | 
				
			||||||
		background rgba(#000, isDark ? 0.25 : 0.1)
 | 
							background rgba(#000, isDark ? 0.25 : 0.1)
 | 
				
			||||||
| 
						 | 
					@ -157,6 +185,9 @@ root(isDark)
 | 
				
			||||||
		background isDark ? #313543 : #fff
 | 
							background isDark ? #313543 : #fff
 | 
				
			||||||
		box-shadow 0 1px rgba(#000, 0.15)
 | 
							box-shadow 0 1px rgba(#000, 0.15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&, *
 | 
				
			||||||
 | 
								user-select none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		&.indicate
 | 
							&.indicate
 | 
				
			||||||
			box-shadow 0 3px 0 0 $theme-color
 | 
								box-shadow 0 3px 0 0 $theme-color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,9 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div>
 | 
					<x-column :name="name">
 | 
				
			||||||
	<x-column :id="column.id" :name="name">
 | 
					 | 
				
			||||||
	<span slot="header">%fa:bell R%{{ name }}</span>
 | 
						<span slot="header">%fa:bell R%{{ name }}</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<x-notifications/>
 | 
						<x-notifications/>
 | 
				
			||||||
	</x-column>
 | 
					</x-column>
 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
| 
						 | 
					@ -19,12 +17,7 @@ export default Vue.extend({
 | 
				
			||||||
		XNotifications
 | 
							XNotifications
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	props: {
 | 
						inject: ['column'],
 | 
				
			||||||
		column: {
 | 
					 | 
				
			||||||
			type: Object,
 | 
					 | 
				
			||||||
			required: true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	computed: {
 | 
						computed: {
 | 
				
			||||||
		name(): string {
 | 
							name(): string {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div>
 | 
					<x-column :menu="menu" :name="name">
 | 
				
			||||||
	<x-column :id="column.id" :menu="menu" :name="name">
 | 
					 | 
				
			||||||
	<span slot="header">
 | 
						<span slot="header">
 | 
				
			||||||
		<template v-if="column.type == 'home'">%fa:home%</template>
 | 
							<template v-if="column.type == 'home'">%fa:home%</template>
 | 
				
			||||||
		<template v-if="column.type == 'local'">%fa:R comments%</template>
 | 
							<template v-if="column.type == 'local'">%fa:R comments%</template>
 | 
				
			||||||
| 
						 | 
					@ -15,8 +14,7 @@
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<x-list-tl v-if="column.type == 'list'" :list="column.list" :media-only="column.isMediaOnly"/>
 | 
						<x-list-tl v-if="column.type == 'list'" :list="column.list" :media-only="column.isMediaOnly"/>
 | 
				
			||||||
	<x-tl v-else :src="column.type" :media-only="column.isMediaOnly"/>
 | 
						<x-tl v-else :src="column.type" :media-only="column.isMediaOnly"/>
 | 
				
			||||||
	</x-column>
 | 
					</x-column>
 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
| 
						 | 
					@ -32,12 +30,7 @@ export default Vue.extend({
 | 
				
			||||||
		XListTl
 | 
							XListTl
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	props: {
 | 
						inject: ['column'],
 | 
				
			||||||
		column: {
 | 
					 | 
				
			||||||
			type: Object,
 | 
					 | 
				
			||||||
			required: true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data() {
 | 
						data() {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,13 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<mk-ui :class="$style.root">
 | 
					<mk-ui :class="$style.root">
 | 
				
			||||||
	<div class="qlvquzbjribqcaozciifydkngcwtyzje" :data-darkmode="$store.state.device.darkmode">
 | 
						<div class="qlvquzbjribqcaozciifydkngcwtyzje" :data-darkmode="$store.state.device.darkmode">
 | 
				
			||||||
		<template v-for="column in columns">
 | 
							<template v-for="ids in layout">
 | 
				
			||||||
			<x-widgets-column v-if="column.type == 'widgets'" :key="column.id" :column="column"/>
 | 
								<div v-if="ids.length > 1" class="folder">
 | 
				
			||||||
			<x-notifications-column v-if="column.type == 'notifications'" :key="column.id" :column="column"/>
 | 
									<template v-for="id, i in ids">
 | 
				
			||||||
			<x-tl-column v-if="column.type == 'home'" :key="column.id" :column="column"/>
 | 
										<x-column-core :ref="id" :key="id" :column="columns.find(c => c.id == id)" :is-stacked="true" :is-active="i == 0"/>
 | 
				
			||||||
			<x-tl-column v-if="column.type == 'local'" :key="column.id" :column="column"/>
 | 
									</template>
 | 
				
			||||||
			<x-tl-column v-if="column.type == 'global'" :key="column.id" :column="column"/>
 | 
								</div>
 | 
				
			||||||
			<x-tl-column v-if="column.type == 'list'" :key="column.id" :column="column"/>
 | 
								<x-column-core v-else :ref="ids[0]" :key="ids[0]" :column="columns.find(c => c.id == ids[0])"/>
 | 
				
			||||||
		</template>
 | 
							</template>
 | 
				
			||||||
		<button ref="add" @click="add" title="%i18n:common.deck.add-column%">%fa:plus%</button>
 | 
							<button ref="add" @click="add" title="%i18n:common.deck.add-column%">%fa:plus%</button>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
| 
						 | 
					@ -16,27 +16,34 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
import XTlColumn from './deck.tl-column.vue';
 | 
					import XColumnCore from './deck.column-core.vue';
 | 
				
			||||||
import XNotificationsColumn from './deck.notifications-column.vue';
 | 
					 | 
				
			||||||
import XWidgetsColumn from './deck.widgets-column.vue';
 | 
					 | 
				
			||||||
import Menu from '../../../../common/views/components/menu.vue';
 | 
					import Menu from '../../../../common/views/components/menu.vue';
 | 
				
			||||||
import MkUserListsWindow from '../../components/user-lists-window.vue';
 | 
					import MkUserListsWindow from '../../components/user-lists-window.vue';
 | 
				
			||||||
import * as uuid from 'uuid';
 | 
					import * as uuid from 'uuid';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	components: {
 | 
						components: {
 | 
				
			||||||
		XTlColumn,
 | 
							XColumnCore
 | 
				
			||||||
		XNotificationsColumn,
 | 
					 | 
				
			||||||
		XWidgetsColumn
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	computed: {
 | 
						computed: {
 | 
				
			||||||
		columns() {
 | 
							columns(): any[] {
 | 
				
			||||||
			if (this.$store.state.settings.deck == null) return [];
 | 
								if (this.$store.state.settings.deck == null) return [];
 | 
				
			||||||
			return this.$store.state.settings.deck.columns;
 | 
								return this.$store.state.settings.deck.columns;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							layout(): any[] {
 | 
				
			||||||
 | 
								if (this.$store.state.settings.deck == null) return [];
 | 
				
			||||||
 | 
								if (this.$store.state.settings.deck.layout == null) return this.$store.state.settings.deck.columns.map(c => [c.id]);
 | 
				
			||||||
 | 
								return this.$store.state.settings.deck.layout;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						provide() {
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								getColumnVm: this.getColumnVm
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	created() {
 | 
						created() {
 | 
				
			||||||
		if (this.$store.state.settings.deck == null) {
 | 
							if (this.$store.state.settings.deck == null) {
 | 
				
			||||||
			const deck = {
 | 
								const deck = {
 | 
				
			||||||
| 
						 | 
					@ -58,11 +65,23 @@ export default Vue.extend({
 | 
				
			||||||
				}]
 | 
									}]
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								deck.layout = deck.columns.map(c => [c.id]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.$store.dispatch('settings/set', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				key: 'deck',
 | 
									key: 'deck',
 | 
				
			||||||
				value: deck
 | 
									value: deck
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 互換性のため
 | 
				
			||||||
 | 
							if (this.$store.state.settings.deck != null && this.$store.state.settings.deck.layout == null) {
 | 
				
			||||||
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
 | 
									key: 'deck',
 | 
				
			||||||
 | 
									value: Object.assign({}, this.$store.state.settings.deck, {
 | 
				
			||||||
 | 
										layout: this.$store.state.settings.deck.columns.map(c => [c.id])
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mounted() {
 | 
						mounted() {
 | 
				
			||||||
| 
						 | 
					@ -74,6 +93,10 @@ export default Vue.extend({
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
 | 
							getColumnVm(id) {
 | 
				
			||||||
 | 
								return this.$refs[id][0];
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		add() {
 | 
							add() {
 | 
				
			||||||
			this.os.new(Menu, {
 | 
								this.os.new(Menu, {
 | 
				
			||||||
				source: this.$refs.add,
 | 
									source: this.$refs.add,
 | 
				
			||||||
| 
						 | 
					@ -159,6 +182,13 @@ root(isDark)
 | 
				
			||||||
		&:last-of-type
 | 
							&:last-of-type
 | 
				
			||||||
			margin-right 0
 | 
								margin-right 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&.folder
 | 
				
			||||||
 | 
								display flex
 | 
				
			||||||
 | 
								flex-direction column
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> *:not(:last-child)
 | 
				
			||||||
 | 
									margin-bottom 8px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> *
 | 
						> *
 | 
				
			||||||
		&:first-child
 | 
							&:first-child
 | 
				
			||||||
			margin-left auto
 | 
								margin-left auto
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="wtdtxvecapixsepjtcupubtsmometobz">
 | 
					<x-column :menu="menu" :naked="true" :narrow="true" :name="name" class="wtdtxvecapixsepjtcupubtsmometobz">
 | 
				
			||||||
	<x-column :id="column.id" :menu="menu" :naked="true" :narrow="true" :name="name">
 | 
					 | 
				
			||||||
	<span slot="header">%fa:calculator%{{ name }}</span>
 | 
						<span slot="header">%fa:calculator%{{ name }}</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<div class="gqpwvtwtprsbmnssnbicggtwqhmylhnq">
 | 
						<div class="gqpwvtwtprsbmnssnbicggtwqhmylhnq">
 | 
				
			||||||
| 
						 | 
					@ -50,8 +49,7 @@
 | 
				
			||||||
			<component class="widget" v-for="widget in column.widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="deck"/>
 | 
								<component class="widget" v-for="widget in column.widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="deck"/>
 | 
				
			||||||
		</template>
 | 
							</template>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	</x-column>
 | 
					</x-column>
 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
| 
						 | 
					@ -66,12 +64,7 @@ export default Vue.extend({
 | 
				
			||||||
		XDraggable
 | 
							XDraggable
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	props: {
 | 
						inject: ['column'],
 | 
				
			||||||
		column: {
 | 
					 | 
				
			||||||
			type: Object,
 | 
					 | 
				
			||||||
			required: true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data() {
 | 
						data() {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,23 +173,22 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				addDeckColumn(state, column) {
 | 
									addDeckColumn(state, column) {
 | 
				
			||||||
					if (state.deck.columns == null) state.deck.columns = [];
 | 
					 | 
				
			||||||
					state.deck.columns.push(column);
 | 
										state.deck.columns.push(column);
 | 
				
			||||||
 | 
										state.deck.layout.push([column.id]);
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				removeDeckColumn(state, id) {
 | 
									removeDeckColumn(state, id) {
 | 
				
			||||||
					if (state.deck.columns == null) return;
 | 
					 | 
				
			||||||
					state.deck.columns = state.deck.columns.filter(c => c.id != id);
 | 
										state.deck.columns = state.deck.columns.filter(c => c.id != id);
 | 
				
			||||||
 | 
										state.deck.layout = state.deck.layout.map(ids => ids.filter(x => x != id));
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				swapLeftDeckColumn(state, id) {
 | 
									swapLeftDeckColumn(state, id) {
 | 
				
			||||||
					if (state.deck.columns == null) return;
 | 
										state.deck.layout.some((ids, i) => {
 | 
				
			||||||
					state.deck.columns.some((c, i) => {
 | 
											if (ids.indexOf(id) != -1) {
 | 
				
			||||||
						if (c.id == id) {
 | 
												const left = state.deck.layout[i - 1];
 | 
				
			||||||
							const left = state.deck.columns[i - 1];
 | 
					 | 
				
			||||||
							if (left) {
 | 
												if (left) {
 | 
				
			||||||
								state.deck.columns[i - 1] = state.deck.columns[i];
 | 
													state.deck.layout[i - 1] = state.deck.layout[i];
 | 
				
			||||||
								state.deck.columns[i] = left;
 | 
													state.deck.layout[i] = left;
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							return true;
 | 
												return true;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
| 
						 | 
					@ -197,28 +196,40 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				swapRightDeckColumn(state, id) {
 | 
									swapRightDeckColumn(state, id) {
 | 
				
			||||||
					if (state.deck.columns == null) return;
 | 
										state.deck.layout.some((ids, i) => {
 | 
				
			||||||
					state.deck.columns.some((c, i) => {
 | 
											if (ids.indexOf(id) != -1) {
 | 
				
			||||||
						if (c.id == id) {
 | 
												const right = state.deck.layout[i + 1];
 | 
				
			||||||
							const right = state.deck.columns[i + 1];
 | 
					 | 
				
			||||||
							if (right) {
 | 
												if (right) {
 | 
				
			||||||
								state.deck.columns[i + 1] = state.deck.columns[i];
 | 
													state.deck.layout[i + 1] = state.deck.layout[i];
 | 
				
			||||||
								state.deck.columns[i] = right;
 | 
													state.deck.layout[i] = right;
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							return true;
 | 
												return true;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									stackLeftDeckColumn(state, id) {
 | 
				
			||||||
 | 
										const i = state.deck.layout.findIndex(ids => ids.indexOf(id) != -1);
 | 
				
			||||||
 | 
										state.deck.layout = state.deck.layout.map(ids => ids.filter(x => x != id));
 | 
				
			||||||
 | 
										const left = state.deck.layout[i - 1];
 | 
				
			||||||
 | 
										if (left) state.deck.layout[i - 1].push(id);
 | 
				
			||||||
 | 
										state.deck.layout = state.deck.layout.filter(ids => ids.length > 0);
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									popRightDeckColumn(state, id) {
 | 
				
			||||||
 | 
										const i = state.deck.layout.findIndex(ids => ids.indexOf(id) != -1);
 | 
				
			||||||
 | 
										state.deck.layout = state.deck.layout.map(ids => ids.filter(x => x != id));
 | 
				
			||||||
 | 
										state.deck.layout.splice(i + 1, 0, [id]);
 | 
				
			||||||
 | 
										state.deck.layout = state.deck.layout.filter(ids => ids.length > 0);
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				addDeckWidget(state, x) {
 | 
									addDeckWidget(state, x) {
 | 
				
			||||||
					if (state.deck.columns == null) return;
 | 
					 | 
				
			||||||
					const column = state.deck.columns.find(c => c.id == x.id);
 | 
										const column = state.deck.columns.find(c => c.id == x.id);
 | 
				
			||||||
					if (column == null) return;
 | 
										if (column == null) return;
 | 
				
			||||||
					column.widgets.unshift(x.widget);
 | 
										column.widgets.unshift(x.widget);
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				removeDeckWidget(state, x) {
 | 
									removeDeckWidget(state, x) {
 | 
				
			||||||
					if (state.deck.columns == null) return;
 | 
					 | 
				
			||||||
					const column = state.deck.columns.find(c => c.id == x.id);
 | 
										const column = state.deck.columns.find(c => c.id == x.id);
 | 
				
			||||||
					if (column == null) return;
 | 
										if (column == null) return;
 | 
				
			||||||
					column.widgets = column.widgets.filter(w => w.id != x.widget.id);
 | 
										column.widgets = column.widgets.filter(w => w.id != x.widget.id);
 | 
				
			||||||
| 
						 | 
					@ -277,6 +288,16 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
					ctx.dispatch('saveDeck');
 | 
										ctx.dispatch('saveDeck');
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									stackLeftDeckColumn(ctx, id) {
 | 
				
			||||||
 | 
										ctx.commit('stackLeftDeckColumn', id);
 | 
				
			||||||
 | 
										ctx.dispatch('saveDeck');
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									popRightDeckColumn(ctx, id) {
 | 
				
			||||||
 | 
										ctx.commit('popRightDeckColumn', id);
 | 
				
			||||||
 | 
										ctx.dispatch('saveDeck');
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				addDeckWidget(ctx, x) {
 | 
									addDeckWidget(ctx, x) {
 | 
				
			||||||
					ctx.commit('addDeckWidget', x);
 | 
										ctx.commit('addDeckWidget', x);
 | 
				
			||||||
					ctx.dispatch('saveDeck');
 | 
										ctx.dispatch('saveDeck');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue