fix: Fix Sideview (#8235)
* Fix #7890 * a- * 3度目の正直 * fix * ✌️ * update CHANGELOG Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
		@@ -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) {
 | 
			
		||||
			if (page == null) return;
 | 
			
		||||
			if (page[symbols.PAGE_INFO]) {
 | 
			
		||||
				this.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;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		back() {
 | 
			
		||||
			this.navigate(this.history.pop(), false);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		close() {
 | 
			
		||||
			this.path = null;
 | 
			
		||||
			this.component = null;
 | 
			
		||||
			this.props = {};
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		onContextmenu(ev: MouseEvent) {
 | 
			
		||||
			os.contextMenu([{
 | 
			
		||||
				type: 'label',
 | 
			
		||||
				text: this.path,
 | 
			
		||||
			}, {
 | 
			
		||||
				icon: 'fas fa-expand-alt',
 | 
			
		||||
				text: this.$ts.showInPage,
 | 
			
		||||
				action: () => {
 | 
			
		||||
					this.$router.push(this.path);
 | 
			
		||||
					this.close();
 | 
			
		||||
				}
 | 
			
		||||
			}, {
 | 
			
		||||
				icon: 'fas fa-window-maximize',
 | 
			
		||||
				text: this.$ts.openInWindow,
 | 
			
		||||
				action: () => {
 | 
			
		||||
					os.pageWindow(this.path);
 | 
			
		||||
					this.close();
 | 
			
		||||
				}
 | 
			
		||||
			}, null, {
 | 
			
		||||
				icon: 'fas fa-external-link-alt',
 | 
			
		||||
				text: this.$ts.openInNewTab,
 | 
			
		||||
				action: () => {
 | 
			
		||||
					window.open(this.url, '_blank');
 | 
			
		||||
					this.close();
 | 
			
		||||
				}
 | 
			
		||||
			}, {
 | 
			
		||||
				icon: 'fas fa-link',
 | 
			
		||||
				text: this.$ts.copyLink,
 | 
			
		||||
				action: () => {
 | 
			
		||||
					copyToClipboard(this.url);
 | 
			
		||||
				}
 | 
			
		||||
			}], ev);
 | 
			
		||||
		}
 | 
			
		||||
function changePage(page) {
 | 
			
		||||
	if (page == null) return;
 | 
			
		||||
	if (page[symbols.PAGE_INFO]) {
 | 
			
		||||
		pageInfo = page[symbols.PAGE_INFO];
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function back() {
 | 
			
		||||
	const prev = history.pop();
 | 
			
		||||
	if (prev) navigate(prev, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function close() {
 | 
			
		||||
	path = null;
 | 
			
		||||
	component = null;
 | 
			
		||||
	props = {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onContextmenu(ev: MouseEvent) {
 | 
			
		||||
	os.contextMenu([{
 | 
			
		||||
		type: 'label',
 | 
			
		||||
		text: path || '',
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'fas fa-expand-alt',
 | 
			
		||||
		text: i18n.ts.showInPage,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			if (path) router.push(path);
 | 
			
		||||
			close();
 | 
			
		||||
		}
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'fas fa-window-maximize',
 | 
			
		||||
		text: i18n.ts.openInWindow,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			if (path) os.pageWindow(path);
 | 
			
		||||
			close();
 | 
			
		||||
		}
 | 
			
		||||
	}, null, {
 | 
			
		||||
		icon: 'fas fa-external-link-alt',
 | 
			
		||||
		text: i18n.ts.openInNewTab,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			window.open(url, '_blank');
 | 
			
		||||
			close();
 | 
			
		||||
		}
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'fas fa-link',
 | 
			
		||||
		text: i18n.ts.copyLink,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			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,155 +64,133 @@
 | 
			
		||||
</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', () => {
 | 
			
		||||
			isMobile.value = window.innerWidth <= MOBILE_THRESHOLD;
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		const pageInfo = ref();
 | 
			
		||||
		const widgetsEl = ref<HTMLElement>();
 | 
			
		||||
		const widgetsShowing = ref(false);
 | 
			
		||||
 | 
			
		||||
		const sideViewController = new EventEmitter();
 | 
			
		||||
 | 
			
		||||
		provide('sideViewHook', isDesktop.value ? (url) => {
 | 
			
		||||
			sideViewController.emit('navigate', url);
 | 
			
		||||
		} : null);
 | 
			
		||||
 | 
			
		||||
		const menuIndicated = computed(() => {
 | 
			
		||||
			for (const def in menuDef) {
 | 
			
		||||
				if (def === 'notifications') continue; // 通知は下にボタンとして表示されてるから
 | 
			
		||||
				if (menuDef[def].indicated) return true;
 | 
			
		||||
			}
 | 
			
		||||
			return false;
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		const drawerMenuShowing = ref(false);
 | 
			
		||||
 | 
			
		||||
		const route = useRoute();
 | 
			
		||||
		watch(route, () => {
 | 
			
		||||
			drawerMenuShowing.value = false;
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		document.documentElement.style.overflowY = 'scroll';
 | 
			
		||||
 | 
			
		||||
		if (defaultStore.state.widgets.length === 0) {
 | 
			
		||||
			defaultStore.set('widgets', [{
 | 
			
		||||
				name: 'calendar',
 | 
			
		||||
				id: 'a', place: 'right', data: {}
 | 
			
		||||
			}, {
 | 
			
		||||
				name: 'notifications',
 | 
			
		||||
				id: 'b', place: 'right', data: {}
 | 
			
		||||
			}, {
 | 
			
		||||
				name: 'trends',
 | 
			
		||||
				id: 'c', place: 'right', data: {}
 | 
			
		||||
			}]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		onMounted(() => {
 | 
			
		||||
			if (!isDesktop.value) {
 | 
			
		||||
				window.addEventListener('resize', () => {
 | 
			
		||||
					if (window.innerWidth >= DESKTOP_THRESHOLD) isDesktop.value = true;
 | 
			
		||||
				}, { passive: true });
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		const changePage = (page) => {
 | 
			
		||||
			if (page == null) return;
 | 
			
		||||
			if (page[symbols.PAGE_INFO]) {
 | 
			
		||||
				pageInfo.value = page[symbols.PAGE_INFO];
 | 
			
		||||
				document.title = `${pageInfo.value.title} | ${instanceName}`;
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		const onContextmenu = (ev) => {
 | 
			
		||||
			const isLink = (el: HTMLElement) => {
 | 
			
		||||
				if (el.tagName === 'A') return true;
 | 
			
		||||
				if (el.parentElement) {
 | 
			
		||||
					return isLink(el.parentElement);
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
			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;
 | 
			
		||||
			const path = route.path;
 | 
			
		||||
			os.contextMenu([{
 | 
			
		||||
				type: 'label',
 | 
			
		||||
				text: path,
 | 
			
		||||
			}, {
 | 
			
		||||
				icon: 'fas fa-columns',
 | 
			
		||||
				text: i18n.ts.openInSideView,
 | 
			
		||||
				action: () => {
 | 
			
		||||
					this.$refs.side.navigate(path);
 | 
			
		||||
				}
 | 
			
		||||
			}, {
 | 
			
		||||
				icon: 'fas fa-window-maximize',
 | 
			
		||||
				text: i18n.ts.openInWindow,
 | 
			
		||||
				action: () => {
 | 
			
		||||
					os.pageWindow(path);
 | 
			
		||||
				}
 | 
			
		||||
			}], ev);
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		const attachSticky = (el) => {
 | 
			
		||||
			const sticky = new StickySidebar(widgetsEl.value);
 | 
			
		||||
			window.addEventListener('scroll', () => {
 | 
			
		||||
				sticky.calc(window.scrollY);
 | 
			
		||||
			}, { passive: true });
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		return {
 | 
			
		||||
			pageInfo,
 | 
			
		||||
			isDesktop,
 | 
			
		||||
			isMobile,
 | 
			
		||||
			widgetsEl,
 | 
			
		||||
			widgetsShowing,
 | 
			
		||||
			drawerMenuShowing,
 | 
			
		||||
			menuIndicated,
 | 
			
		||||
			wallpaper: localStorage.getItem('wallpaper') != null,
 | 
			
		||||
			changePage,
 | 
			
		||||
			top: () => {
 | 
			
		||||
				window.scroll({ top: 0, behavior: 'smooth' });
 | 
			
		||||
			},
 | 
			
		||||
			onTransition: () => {
 | 
			
		||||
				if (window._scroll) window._scroll();
 | 
			
		||||
			},
 | 
			
		||||
			post: os.post,
 | 
			
		||||
			onContextmenu,
 | 
			
		||||
			attachSticky,
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD);
 | 
			
		||||
const isMobile = ref(window.innerWidth <= MOBILE_THRESHOLD);
 | 
			
		||||
window.addEventListener('resize', () => {
 | 
			
		||||
	isMobile.value = window.innerWidth <= MOBILE_THRESHOLD;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const pageInfo = ref();
 | 
			
		||||
const widgetsEl = $ref<HTMLElement>();
 | 
			
		||||
const widgetsShowing = ref(false);
 | 
			
		||||
 | 
			
		||||
let sideEl = $ref<InstanceType<typeof XSideView>>();
 | 
			
		||||
 | 
			
		||||
provide('sideViewHook', isDesktop.value ? (url) => {
 | 
			
		||||
	sideEl.navigate(url);
 | 
			
		||||
} : null);
 | 
			
		||||
 | 
			
		||||
const menuIndicated = computed(() => {
 | 
			
		||||
	for (const def in menuDef) {
 | 
			
		||||
		if (def === 'notifications') continue; // 通知は下にボタンとして表示されてるから
 | 
			
		||||
		if (menuDef[def].indicated) return true;
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const drawerMenuShowing = ref(false);
 | 
			
		||||
 | 
			
		||||
const route = useRoute();
 | 
			
		||||
watch(route, () => {
 | 
			
		||||
	drawerMenuShowing.value = false;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
document.documentElement.style.overflowY = 'scroll';
 | 
			
		||||
 | 
			
		||||
if (defaultStore.state.widgets.length === 0) {
 | 
			
		||||
	defaultStore.set('widgets', [{
 | 
			
		||||
		name: 'calendar',
 | 
			
		||||
		id: 'a', place: 'right', data: {}
 | 
			
		||||
	}, {
 | 
			
		||||
		name: 'notifications',
 | 
			
		||||
		id: 'b', place: 'right', data: {}
 | 
			
		||||
	}, {
 | 
			
		||||
		name: 'trends',
 | 
			
		||||
		id: 'c', place: 'right', data: {}
 | 
			
		||||
	}]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
	if (!isDesktop.value) {
 | 
			
		||||
		window.addEventListener('resize', () => {
 | 
			
		||||
			if (window.innerWidth >= DESKTOP_THRESHOLD) isDesktop.value = true;
 | 
			
		||||
		}, { passive: true });
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const changePage = (page) => {
 | 
			
		||||
	if (page == null) return;
 | 
			
		||||
	if (page[symbols.PAGE_INFO]) {
 | 
			
		||||
		pageInfo.value = page[symbols.PAGE_INFO];
 | 
			
		||||
		document.title = `${pageInfo.value.title} | ${instanceName}`;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const onContextmenu = (ev) => {
 | 
			
		||||
	const isLink = (el: HTMLElement) => {
 | 
			
		||||
		if (el.tagName === 'A') return true;
 | 
			
		||||
		if (el.parentElement) {
 | 
			
		||||
			return isLink(el.parentElement);
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
	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;
 | 
			
		||||
	const path = route.path;
 | 
			
		||||
	os.contextMenu([{
 | 
			
		||||
		type: 'label',
 | 
			
		||||
		text: path,
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'fas fa-columns',
 | 
			
		||||
		text: i18n.ts.openInSideView,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			sideEl.navigate(path);
 | 
			
		||||
		}
 | 
			
		||||
	}, {
 | 
			
		||||
		icon: 'fas fa-window-maximize',
 | 
			
		||||
		text: i18n.ts.openInWindow,
 | 
			
		||||
		action: () => {
 | 
			
		||||
			os.pageWindow(path);
 | 
			
		||||
		}
 | 
			
		||||
	}], ev);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const attachSticky = (el) => {
 | 
			
		||||
	const sticky = new StickySidebar(widgetsEl);
 | 
			
		||||
	window.addEventListener('scroll', () => {
 | 
			
		||||
		sticky.calc(window.scrollY);
 | 
			
		||||
	}, { passive: true });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function top() {
 | 
			
		||||
	window.scroll({ top: 0, behavior: 'smooth' });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onTransition() {
 | 
			
		||||
	if (window._scroll) window._scroll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const wallpaper = localStorage.getItem('wallpaper') != null;
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user