summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authortamaina <tamaina@hotmail.co.jp>2022-02-01 23:48:19 +0900
committerGitHub <noreply@github.com>2022-02-01 23:48:19 +0900
commitae3abc2126409da909edc1134a057fa13d819ed8 (patch)
treebf14372e393db3f9649cb00ad8d1dcbc63b8fda4 /packages
parentMerge branch 'develop' of https://github.com/misskey-dev/misskey into develop (diff)
downloadmisskey-ae3abc2126409da909edc1134a057fa13d819ed8.tar.gz
misskey-ae3abc2126409da909edc1134a057fa13d819ed8.tar.bz2
misskey-ae3abc2126409da909edc1134a057fa13d819ed8.zip
fix: Fix Sideview (#8235)
* Fix #7890 * a- * 3度目の正直 * fix * :v: * update CHANGELOG Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Diffstat (limited to 'packages')
-rw-r--r--packages/client/src/components/global/a.vue5
-rw-r--r--packages/client/src/ui/classic.side.vue154
-rw-r--r--packages/client/src/ui/universal.vue224
3 files changed, 176 insertions, 207 deletions
diff --git a/packages/client/src/components/global/a.vue b/packages/client/src/components/global/a.vue
index b1b6a0cdaf..52fef50f9b 100644
--- a/packages/client/src/components/global/a.vue
+++ b/packages/client/src/components/global/a.vue
@@ -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;
diff --git a/packages/client/src/ui/classic.side.vue b/packages/client/src/ui/classic.side.vue
index f816834141..6c2329194e 100644
--- a/packages/client/src/ui/classic.side.vue
+++ b/packages/client/src/ui/classic.side.vue
@@ -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];
- }
- },
+function changePage(page) {
+ if (page == null) return;
+ if (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) {
- 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 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>
diff --git a/packages/client/src/ui/universal.vue b/packages/client/src/ui/universal.vue
index 8fe9dcffaf..b0dfc5aadc 100644
--- a/packages/client/src/ui/universal.vue
+++ b/packages/client/src/ui/universal.vue
@@ -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取得できなくて面倒になる
- },
+const isDesktop = ref(window.innerWidth >= DESKTOP_THRESHOLD);
+const isMobile = ref(window.innerWidth <= MOBILE_THRESHOLD);
+window.addEventListener('resize', () => {
+ isMobile.value = window.innerWidth <= MOBILE_THRESHOLD;
+});
- 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 pageInfo = ref();
- const widgetsEl = ref<HTMLElement>();
- const widgetsShowing = ref(false);
+let sideEl = $ref<InstanceType<typeof XSideView>>();
- const sideViewController = new EventEmitter();
+provide('sideViewHook', isDesktop.value ? (url) => {
+ sideEl.navigate(url);
+} : null);
- 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 menuIndicated = computed(() => {
- for (const def in menuDef) {
- if (def === 'notifications') continue; // 通知は下にボタンとして表示されてるから
- if (menuDef[def].indicated) return true;
- }
- return false;
- });
+const drawerMenuShowing = ref(false);
- const drawerMenuShowing = ref(false);
+const route = useRoute();
+watch(route, () => {
+ drawerMenuShowing.value = false;
+});
- const route = useRoute();
- watch(route, () => {
- drawerMenuShowing.value = false;
- });
+document.documentElement.style.overflowY = 'scroll';
- 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: {}
+ }]);
+}
- 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 });
+ }
+});
- 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 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 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);
+ window.addEventListener('scroll', () => {
+ sticky.calc(window.scrollY);
+ }, { passive: true });
+};
+
+function top() {
+ window.scroll({ top: 0, behavior: 'smooth' });
+}
- const attachSticky = (el) => {
- const sticky = new StickySidebar(widgetsEl.value);
- window.addEventListener('scroll', () => {
- sticky.calc(window.scrollY);
- }, { passive: true });
- };
+function onTransition() {
+ if (window._scroll) window._scroll();
+}
- 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 wallpaper = localStorage.getItem('wallpaper') != null;
</script>
<style lang="scss" scoped>