wip
This commit is contained in:
		
							parent
							
								
									6f34c74027
								
							
						
					
					
						commit
						cc43bc955a
					
				
					 1 changed files with 217 additions and 0 deletions
				
			
		
							
								
								
									
										217
									
								
								src/client/ui/desktop.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								src/client/ui/desktop.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,217 @@ | ||||||
|  | <template> | ||||||
|  | <div class="mk-app" v-hotkey.global="keymap"> | ||||||
|  | 	<XSidebar ref="nav" class="sidebar"/> | ||||||
|  | 
 | ||||||
|  | 	<div class="contents" ref="contents" :class="{ wallpaper }"> | ||||||
|  | 		<div v-if="isDesktop" class="widgets"> | ||||||
|  | 			<div ref="widgetsSpacer"></div> | ||||||
|  | 			<XWidgets @mounted="attachSticky"/> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | 
 | ||||||
|  | 	<XCommon/> | ||||||
|  | </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts"> | ||||||
|  | import { defineComponent, defineAsyncComponent, markRaw } from 'vue'; | ||||||
|  | import { faLayerGroup, faBars, faHome, faCircle, faWindowMaximize, faColumns } from '@fortawesome/free-solid-svg-icons'; | ||||||
|  | import { faBell } from '@fortawesome/free-regular-svg-icons'; | ||||||
|  | import { host } from '@/config'; | ||||||
|  | import { search } from '@/scripts/search'; | ||||||
|  | import { StickySidebar } from '@/scripts/sticky-sidebar'; | ||||||
|  | import XSidebar from '@/components/sidebar.vue'; | ||||||
|  | import XCommon from './_common_/common.vue'; | ||||||
|  | import XHeader from './_common_/header.vue'; | ||||||
|  | import XSide from './default.side.vue'; | ||||||
|  | import * as os from '@/os'; | ||||||
|  | import { sidebarDef } from '@/sidebar'; | ||||||
|  | 
 | ||||||
|  | const DESKTOP_THRESHOLD = 1100; | ||||||
|  | 
 | ||||||
|  | export default defineComponent({ | ||||||
|  | 	components: { | ||||||
|  | 		XCommon, | ||||||
|  | 		XSidebar, | ||||||
|  | 		XHeader, | ||||||
|  | 		XWidgets: defineAsyncComponent(() => import('./default.widgets.vue')), | ||||||
|  | 		XSide, // NOTE: dynamic importするとAsyncComponentWrapperが間に入るせいでref取得できなくて面倒になる | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	provide() { | ||||||
|  | 		return { | ||||||
|  | 			sideViewHook: this.isDesktop ? (url) => { | ||||||
|  | 				this.$refs.side.navigate(url); | ||||||
|  | 			} : null | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			host: host, | ||||||
|  | 			connection: null, | ||||||
|  | 			isDesktop: window.innerWidth >= DESKTOP_THRESHOLD, | ||||||
|  | 			menuDef: sidebarDef, | ||||||
|  | 			navHidden: false, | ||||||
|  | 			widgetsShowing: false, | ||||||
|  | 			wallpaper: localStorage.getItem('wallpaper') != null, | ||||||
|  | 			faLayerGroup, faBars, faBell, faHome, faCircle, | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	computed: { | ||||||
|  | 		keymap(): any { | ||||||
|  | 			return { | ||||||
|  | 				'd': () => { | ||||||
|  | 					if (this.$store.state.device.syncDeviceDarkMode) return; | ||||||
|  | 					this.$store.commit('device/set', { key: 'darkMode', value: !this.$store.state.device.darkMode }); | ||||||
|  | 				}, | ||||||
|  | 				'p': os.post, | ||||||
|  | 				'n': os.post, | ||||||
|  | 				's': search, | ||||||
|  | 				'h|/': this.help | ||||||
|  | 			}; | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		widgets(): any { | ||||||
|  | 			return this.$store.state.deviceUser.widgets; | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		menu(): string[] { | ||||||
|  | 			return this.$store.state.deviceUser.menu; | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	created() { | ||||||
|  | 		this.connection = os.stream.useSharedConnection('main'); | ||||||
|  | 		this.connection.on('notification', this.onNotification); | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	mounted() { | ||||||
|  | 		this.adjustUI(); | ||||||
|  | 
 | ||||||
|  | 		const ro = new ResizeObserver((entries, observer) => { | ||||||
|  | 			this.adjustUI(); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		ro.observe(this.$refs.contents); | ||||||
|  | 
 | ||||||
|  | 		window.addEventListener('resize', this.adjustUI, { passive: true }); | ||||||
|  | 
 | ||||||
|  | 		if (!this.isDesktop) { | ||||||
|  | 			window.addEventListener('resize', () => { | ||||||
|  | 				if (window.innerWidth >= DESKTOP_THRESHOLD) this.isDesktop = true; | ||||||
|  | 			}, { passive: true }); | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	methods: { | ||||||
|  | 		changePage(page) { | ||||||
|  | 			if (page == null) return; | ||||||
|  | 			if (page.INFO) { | ||||||
|  | 				this.pageInfo = page.INFO; | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		adjustUI() { | ||||||
|  | 			const navWidth = this.$refs.nav.$el.offsetWidth; | ||||||
|  | 			this.navHidden = navWidth === 0; | ||||||
|  | 			if (this.$refs.contents == null) return; | ||||||
|  | 			const width = this.$refs.contents.offsetWidth; | ||||||
|  | 			this.$refs.header.style.width = `${width}px`; | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		showNav() { | ||||||
|  | 			this.$refs.nav.show(); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		attachSticky(el) { | ||||||
|  | 			const sticky = new StickySidebar(el, this.$refs.widgetsSpacer); | ||||||
|  | 			window.addEventListener('scroll', () => { | ||||||
|  | 				sticky.calc(window.scrollY); | ||||||
|  | 			}, { passive: true }); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		top() { | ||||||
|  | 			window.scroll({ top: 0, behavior: 'smooth' }); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		help() { | ||||||
|  | 			this.$router.push('/docs/keyboard-shortcut'); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		onTransition() { | ||||||
|  | 			if (window._scroll) window._scroll(); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		onContextmenu(e) { | ||||||
|  | 			const url = this.$route.path; | ||||||
|  | 			os.contextMenu([{ | ||||||
|  | 				type: 'label', | ||||||
|  | 				text: url, | ||||||
|  | 			}, { | ||||||
|  | 				icon: faColumns, | ||||||
|  | 				text: this.$t('openInSideView'), | ||||||
|  | 				action: () => { | ||||||
|  | 					this.$refs.side.navigate(url); | ||||||
|  | 				} | ||||||
|  | 			}, { | ||||||
|  | 				icon: faWindowMaximize, | ||||||
|  | 				text: this.$t('openInWindow'), | ||||||
|  | 				action: () => { | ||||||
|  | 					os.pageWindow(url); | ||||||
|  | 				} | ||||||
|  | 			}], e); | ||||||
|  | 		}, | ||||||
|  | 
 | ||||||
|  | 		async onNotification(notification) { | ||||||
|  | 			if (this.$store.state.i.mutingNotificationTypes.includes(notification.type)) { | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			if (document.visibilityState === 'visible') { | ||||||
|  | 				os.stream.send('readNotification', { | ||||||
|  | 					id: notification.id | ||||||
|  | 				}); | ||||||
|  | 
 | ||||||
|  | 				os.popup(await import('@/components/toast.vue'), { | ||||||
|  | 					notification | ||||||
|  | 				}, {}, 'closed'); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			os.sound('notification'); | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .mk-app { | ||||||
|  | 	min-height: calc(var(--vh, 1vh) * 100); | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | 
 | ||||||
|  | 	display: flex; | ||||||
|  | 
 | ||||||
|  | 	> .contents { | ||||||
|  | 		width: 100%; | ||||||
|  | 		min-width: 0; | ||||||
|  | 		padding-top: $header-height; | ||||||
|  | 
 | ||||||
|  | 		&.wallpaper { | ||||||
|  | 			background: var(--wallpaperOverlay); | ||||||
|  | 			//backdrop-filter: blur(4px); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		> .widgets { | ||||||
|  | 			padding: 0 var(--margin); | ||||||
|  | 			border-left: solid 1px var(--divider); | ||||||
|  | 
 | ||||||
|  | 			@media (max-width: $widgets-hide-threshold) { | ||||||
|  | 				display: none; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | 
 | ||||||
|  | <style lang="scss"> | ||||||
|  | </style> | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue