fix: Fix Sideview (#8235)
* Fix #7890 * a- * 3度目の正直 * fix * ✌️ * update CHANGELOG Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
		
							parent
							
								
									141c999acd
								
							
						
					
					
						commit
						ae3abc2126
					
				
					 4 changed files with 194 additions and 224 deletions
				
			
		|  | @ -22,6 +22,7 @@ | |||
| - 投稿フォームのハッシュタグ保持フィールドが動作しない問題を修正 | ||||
| - Add `img-src` and `media-src` directives to `Content-Security-Policy` for | ||||
|   files and media proxy | ||||
| - サイドビューが動かないのを修正 | ||||
| - ensure that specified users does not get duplicates | ||||
| 
 | ||||
| ## 12.102.1 (2022/01/27) | ||||
|  |  | |||
|  | @ -23,8 +23,9 @@ const props = withDefaults(defineProps<{ | |||
| 	behavior: null, | ||||
| }); | ||||
| 
 | ||||
| const navHook = inject('navHook', null); | ||||
| const sideViewHook = inject('sideViewHook', null); | ||||
| type Navigate = (path: string, record?: boolean) => void; | ||||
| const navHook = inject<null | Navigate>('navHook', null); | ||||
| const sideViewHook = inject<null | Navigate>('sideViewHook', null); | ||||
| 
 | ||||
| const active = $computed(() => { | ||||
| 	if (props.activeClass == null) return false; | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 		<header class="header" @contextmenu.prevent.stop="onContextmenu"> | ||||
| 			<button v-if="history.length > 0" class="_button" @click="back()"><i class="fas fa-chevron-left"></i></button> | ||||
| 			<button v-else class="_button" style="pointer-events: none;"><!-- マージンのバランスを取るためのダミー --></button> | ||||
| 			<span class="title">{{ pageInfo.title }}</span> | ||||
| 			<span class="title" v-text="pageInfo?.title" /> | ||||
| 			<button class="_button" @click="close()"><i class="fas fa-times"></i></button> | ||||
| 		</header> | ||||
| 		<MkHeader class="pageHeader" :info="pageInfo"/> | ||||
|  | @ -13,99 +13,89 @@ | |||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| <script lang="ts" setup> | ||||
| import { provide } from 'vue'; | ||||
| import * as os from '@/os'; | ||||
| import copyToClipboard from '@/scripts/copy-to-clipboard'; | ||||
| import { resolve } from '@/router'; | ||||
| import { url } from '@/config'; | ||||
| import { resolve, router } from '@/router'; | ||||
| import { url as root } from '@/config'; | ||||
| import * as symbols from '@/symbols'; | ||||
| import { i18n } from '@/i18n'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	provide() { | ||||
| 		return { | ||||
| 			navHook: (path) => { | ||||
| 				this.navigate(path); | ||||
| 			} | ||||
| 		}; | ||||
| 	}, | ||||
| provide('navHook', navigate); | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			path: null, | ||||
| 			component: null, | ||||
| 			props: {}, | ||||
| 			pageInfo: null, | ||||
| 			history: [], | ||||
| 		}; | ||||
| 	}, | ||||
| let path: string | null = $ref(null); | ||||
| let component: ReturnType<typeof resolve>['component'] | null = $ref(null); | ||||
| let props: any | null = $ref(null); | ||||
| let pageInfo: any | null = $ref(null); | ||||
| let history: string[] = $ref([]); | ||||
| 
 | ||||
| 	computed: { | ||||
| 		url(): string { | ||||
| 			return url + this.path; | ||||
| 		} | ||||
| 	}, | ||||
| let url = $computed(() => `${root}${path}`); | ||||
| 
 | ||||
| 	methods: { | ||||
| 		changePage(page) { | ||||
| function changePage(page) { | ||||
| 	if (page == null) return; | ||||
| 	if (page[symbols.PAGE_INFO]) { | ||||
| 				this.pageInfo = page[symbols.PAGE_INFO]; | ||||
| 		pageInfo = page[symbols.PAGE_INFO]; | ||||
| 	} | ||||
| } | ||||
| 		}, | ||||
| 
 | ||||
| 		navigate(path, record = true) { | ||||
| 			if (record && this.path) this.history.push(this.path); | ||||
| 			this.path = path; | ||||
| 			const { component, props } = resolve(path); | ||||
| 			this.component = component; | ||||
| 			this.props = props; | ||||
| 		}, | ||||
| function navigate(_path: string, record = true) { | ||||
| 	if (record && path) history.push($$(path).value); | ||||
| 	path = _path; | ||||
| 	const resolved = resolve(path); | ||||
| 	component = resolved.component; | ||||
| 	props = resolved.props; | ||||
| } | ||||
| 
 | ||||
| 		back() { | ||||
| 			this.navigate(this.history.pop(), false); | ||||
| 		}, | ||||
| function back() { | ||||
| 	const prev = history.pop(); | ||||
| 	if (prev) navigate(prev, false); | ||||
| } | ||||
| 
 | ||||
| 		close() { | ||||
| 			this.path = null; | ||||
| 			this.component = null; | ||||
| 			this.props = {}; | ||||
| 		}, | ||||
| function close() { | ||||
| 	path = null; | ||||
| 	component = null; | ||||
| 	props = {}; | ||||
| } | ||||
| 
 | ||||
| 		onContextmenu(ev: MouseEvent) { | ||||
| function onContextmenu(ev: MouseEvent) { | ||||
| 	os.contextMenu([{ | ||||
| 		type: 'label', | ||||
| 				text: this.path, | ||||
| 		text: path || '', | ||||
| 	}, { | ||||
| 		icon: 'fas fa-expand-alt', | ||||
| 				text: this.$ts.showInPage, | ||||
| 		text: i18n.ts.showInPage, | ||||
| 		action: () => { | ||||
| 					this.$router.push(this.path); | ||||
| 					this.close(); | ||||
| 			if (path) router.push(path); | ||||
| 			close(); | ||||
| 		} | ||||
| 	}, { | ||||
| 		icon: 'fas fa-window-maximize', | ||||
| 				text: this.$ts.openInWindow, | ||||
| 		text: i18n.ts.openInWindow, | ||||
| 		action: () => { | ||||
| 					os.pageWindow(this.path); | ||||
| 					this.close(); | ||||
| 			if (path) os.pageWindow(path); | ||||
| 			close(); | ||||
| 		} | ||||
| 	}, null, { | ||||
| 		icon: 'fas fa-external-link-alt', | ||||
| 				text: this.$ts.openInNewTab, | ||||
| 		text: i18n.ts.openInNewTab, | ||||
| 		action: () => { | ||||
| 					window.open(this.url, '_blank'); | ||||
| 					this.close(); | ||||
| 			window.open(url, '_blank'); | ||||
| 			close(); | ||||
| 		} | ||||
| 	}, { | ||||
| 		icon: 'fas fa-link', | ||||
| 				text: this.$ts.copyLink, | ||||
| 		text: i18n.ts.copyLink, | ||||
| 		action: () => { | ||||
| 					copyToClipboard(this.url); | ||||
| 			copyToClipboard(url); | ||||
| 		} | ||||
| 	}], ev); | ||||
| } | ||||
| 	} | ||||
| 
 | ||||
| defineExpose({ | ||||
| 	navigate, | ||||
| 	back, | ||||
| 	close, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ | |||
| 		</main> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<XSideView v-if="isDesktop" ref="side" class="side"/> | ||||
| 	<XSideView v-if="isDesktop" ref="sideEl" class="side"/> | ||||
| 
 | ||||
| 	<div v-if="isDesktop" ref="widgetsEl" class="widgets"> | ||||
| 		<XWidgets @mounted="attachSticky"/> | ||||
|  | @ -31,9 +31,9 @@ | |||
| 	<div v-if="isMobile" class="buttons"> | ||||
| 		<button class="button nav _button" @click="drawerMenuShowing = true"><i class="fas fa-bars"></i><span v-if="menuIndicated" class="indicator"><i class="fas fa-circle"></i></span></button> | ||||
| 		<button class="button home _button" @click="$route.name === 'index' ? top() : $router.push('/')"><i class="fas fa-home"></i></button> | ||||
| 		<button class="button notifications _button" @click="$router.push('/my/notifications')"><i class="fas fa-bell"></i><span v-if="$i.hasUnreadNotification" class="indicator"><i class="fas fa-circle"></i></span></button> | ||||
| 		<button class="button notifications _button" @click="$router.push('/my/notifications')"><i class="fas fa-bell"></i><span v-if="$i?.hasUnreadNotification" class="indicator"><i class="fas fa-circle"></i></span></button> | ||||
| 		<button class="button widget _button" @click="widgetsShowing = true"><i class="fas fa-layer-group"></i></button> | ||||
| 		<button class="button post _button" @click="post()"><i class="fas fa-pencil-alt"></i></button> | ||||
| 		<button class="button post _button" @click="os.post()"><i class="fas fa-pencil-alt"></i></button> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<transition :name="$store.state.animation ? 'menuDrawer-back' : ''"> | ||||
|  | @ -64,35 +64,26 @@ | |||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent, provide, onMounted, computed, ref, watch } from 'vue'; | ||||
| <script lang="ts" setup> | ||||
| import { defineAsyncComponent, provide, onMounted, computed, ref, watch } from 'vue'; | ||||
| import { instanceName } from '@/config'; | ||||
| import { StickySidebar } from '@/scripts/sticky-sidebar'; | ||||
| import XSidebar from '@/ui/_common_/sidebar.vue'; | ||||
| import XDrawerMenu from '@/ui/_common_/sidebar-for-mobile.vue'; | ||||
| import XCommon from './_common_/common.vue'; | ||||
| import XSideView from './classic.side.vue'; | ||||
| import * as os from '@/os'; | ||||
| import * as symbols from '@/symbols'; | ||||
| import { defaultStore } from '@/store'; | ||||
| import * as EventEmitter from 'eventemitter3'; | ||||
| import { menuDef } from '@/menu'; | ||||
| import { useRoute } from 'vue-router'; | ||||
| import { i18n } from '@/i18n'; | ||||
| import { $i } from '@/account'; | ||||
| const XWidgets = defineAsyncComponent(() => import('./universal.widgets.vue')); | ||||
| const XSidebar = defineAsyncComponent(() => import('@/ui/_common_/sidebar.vue')); | ||||
| 
 | ||||
| const DESKTOP_THRESHOLD = 1100; | ||||
| const MOBILE_THRESHOLD = 500; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		XCommon, | ||||
| 		XSidebar, | ||||
| 		XDrawerMenu, | ||||
| 		XWidgets: defineAsyncComponent(() => import('./universal.widgets.vue')), | ||||
| 		XSideView, // NOTE: dynamic importするとAsyncComponentWrapperが間に入るせいでref取得できなくて面倒になる | ||||
| 	}, | ||||
| 
 | ||||
| 	setup() { | ||||
| const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD); | ||||
| const isMobile = ref(window.innerWidth <= MOBILE_THRESHOLD); | ||||
| window.addEventListener('resize', () => { | ||||
|  | @ -100,13 +91,13 @@ export default defineComponent({ | |||
| }); | ||||
| 
 | ||||
| const pageInfo = ref(); | ||||
| 		const widgetsEl = ref<HTMLElement>(); | ||||
| const widgetsEl = $ref<HTMLElement>(); | ||||
| const widgetsShowing = ref(false); | ||||
| 
 | ||||
| 		const sideViewController = new EventEmitter(); | ||||
| let sideEl = $ref<InstanceType<typeof XSideView>>(); | ||||
| 
 | ||||
| provide('sideViewHook', isDesktop.value ? (url) => { | ||||
| 			sideViewController.emit('navigate', url); | ||||
| 	sideEl.navigate(url); | ||||
| } : null); | ||||
| 
 | ||||
| const menuIndicated = computed(() => { | ||||
|  | @ -164,7 +155,7 @@ export default defineComponent({ | |||
| 	}; | ||||
| 	if (isLink(ev.target)) return; | ||||
| 	if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(ev.target.tagName) || ev.target.attributes['contenteditable']) return; | ||||
| 			if (window.getSelection().toString() !== '') return; | ||||
| 	if (window.getSelection()?.toString() !== '') return; | ||||
| 	const path = route.path; | ||||
| 	os.contextMenu([{ | ||||
| 		type: 'label', | ||||
|  | @ -173,7 +164,7 @@ export default defineComponent({ | |||
| 		icon: 'fas fa-columns', | ||||
| 		text: i18n.ts.openInSideView, | ||||
| 		action: () => { | ||||
| 					this.$refs.side.navigate(path); | ||||
| 			sideEl.navigate(path); | ||||
| 		} | ||||
| 	}, { | ||||
| 		icon: 'fas fa-window-maximize', | ||||
|  | @ -185,34 +176,21 @@ export default defineComponent({ | |||
| }; | ||||
| 
 | ||||
| const attachSticky = (el) => { | ||||
| 			const sticky = new StickySidebar(widgetsEl.value); | ||||
| 	const sticky = new StickySidebar(widgetsEl); | ||||
| 	window.addEventListener('scroll', () => { | ||||
| 		sticky.calc(window.scrollY); | ||||
| 	}, { passive: true }); | ||||
| }; | ||||
| 
 | ||||
| 		return { | ||||
| 			pageInfo, | ||||
| 			isDesktop, | ||||
| 			isMobile, | ||||
| 			widgetsEl, | ||||
| 			widgetsShowing, | ||||
| 			drawerMenuShowing, | ||||
| 			menuIndicated, | ||||
| 			wallpaper: localStorage.getItem('wallpaper') != null, | ||||
| 			changePage, | ||||
| 			top: () => { | ||||
| function top() { | ||||
| 	window.scroll({ top: 0, behavior: 'smooth' }); | ||||
| 			}, | ||||
| 			onTransition: () => { | ||||
| } | ||||
| 
 | ||||
| function onTransition() { | ||||
| 	if (window._scroll) window._scroll(); | ||||
| 			}, | ||||
| 			post: os.post, | ||||
| 			onContextmenu, | ||||
| 			attachSticky, | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
| } | ||||
| 
 | ||||
| const wallpaper = localStorage.getItem('wallpaper') != null; | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue