mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-11-23 09:23:09 +02:00
refactor(frontend): router.ts解きほぐし (#12907)
* refactor(frontend): router.ts解きほぐし * add debug hmr option * fix comment * fix not working * add comment * fix name * Update definition.ts --------- Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
parent
0ed2a220f4
commit
04f9147db6
49 changed files with 937 additions and 650 deletions
|
@ -4,7 +4,7 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "vite",
|
"watch": "vite",
|
||||||
"dev": "vite --config vite.config.local-dev.ts",
|
"dev": "vite --config vite.config.local-dev.ts --debug hmr",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"storybook-dev": "nodemon --verbose --watch src --ext \"mdx,ts,vue\" --ignore \"*.stories.ts\" --exec \"pnpm build-storybook-pre && pnpm exec storybook dev -p 6006 --ci\"",
|
"storybook-dev": "nodemon --verbose --watch src --ext \"mdx,ts,vue\" --ignore \"*.stories.ts\" --exec \"pnpm build-storybook-pre && pnpm exec storybook dev -p 6006 --ci\"",
|
||||||
"build-storybook-pre": "(tsc -p .storybook || echo done.) && node .storybook/generate.js && node .storybook/preload-locale.js && node .storybook/preload-theme.js",
|
"build-storybook-pre": "(tsc -p .storybook || echo done.) && node .storybook/generate.js && node .storybook/preload-locale.js && node .storybook/preload-theme.js",
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { getAccountFromId } from '@/scripts/get-account-from-id.js';
|
||||||
import { deckStore } from '@/ui/deck/deck-store.js';
|
import { deckStore } from '@/ui/deck/deck-store.js';
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
import { fetchCustomEmojis } from '@/custom-emojis.js';
|
import { fetchCustomEmojis } from '@/custom-emojis.js';
|
||||||
|
import { setupRouter } from '@/global/router/definition.js';
|
||||||
|
|
||||||
export async function common(createVue: () => App<Element>) {
|
export async function common(createVue: () => App<Element>) {
|
||||||
console.info(`Misskey v${version}`);
|
console.info(`Misskey v${version}`);
|
||||||
|
@ -241,6 +242,8 @@ export async function common(createVue: () => App<Element>) {
|
||||||
|
|
||||||
const app = createVue();
|
const app = createVue();
|
||||||
|
|
||||||
|
setupRouter(app);
|
||||||
|
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
app.config.performance = true;
|
app.config.performance = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,23 +3,23 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createApp, markRaw, defineAsyncComponent } from 'vue';
|
import { createApp, defineAsyncComponent, markRaw } from 'vue';
|
||||||
import { common } from './common.js';
|
import { common } from './common.js';
|
||||||
import { ui } from '@/config.js';
|
import { ui } from '@/config.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { confirm, alert, post, popup, toast } from '@/os.js';
|
import { alert, confirm, popup, post, toast } from '@/os.js';
|
||||||
import { useStream } from '@/stream.js';
|
import { useStream } from '@/stream.js';
|
||||||
import * as sound from '@/scripts/sound.js';
|
import * as sound from '@/scripts/sound.js';
|
||||||
import { $i, updateAccount, signout } from '@/account.js';
|
import { $i, signout, updateAccount } from '@/account.js';
|
||||||
import { defaultStore, ColdDeviceStorage } from '@/store.js';
|
import { ColdDeviceStorage, defaultStore } from '@/store.js';
|
||||||
import { makeHotkey } from '@/scripts/hotkey.js';
|
import { makeHotkey } from '@/scripts/hotkey.js';
|
||||||
import { reactionPicker } from '@/scripts/reaction-picker.js';
|
import { reactionPicker } from '@/scripts/reaction-picker.js';
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
import { claimAchievement, claimedAchievements } from '@/scripts/achievements.js';
|
import { claimAchievement, claimedAchievements } from '@/scripts/achievements.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { initializeSw } from '@/scripts/initialize-sw.js';
|
import { initializeSw } from '@/scripts/initialize-sw.js';
|
||||||
import { deckStore } from '@/ui/deck/deck-store.js';
|
import { deckStore } from '@/ui/deck/deck-store.js';
|
||||||
import { emojiPicker } from '@/scripts/emoji-picker.js';
|
import { emojiPicker } from '@/scripts/emoji-picker.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
export async function mainBoot() {
|
export async function mainBoot() {
|
||||||
const { isClientUpdated } = await common(() => createApp(
|
const { isClientUpdated } = await common(() => createApp(
|
||||||
|
|
|
@ -45,9 +45,9 @@ import bytes from '@/filters/bytes.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { getDriveFileMenu } from '@/scripts/get-drive-file-menu.js';
|
import { getDriveFileMenu } from '@/scripts/get-drive-file-menu.js';
|
||||||
import { deviceKind } from '@/scripts/device-kind.js';
|
import { deviceKind } from '@/scripts/device-kind.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -23,26 +23,26 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div ref="contents" :class="$style.root" style="container-type: inline-size;">
|
<div ref="contents" :class="$style.root" style="container-type: inline-size;">
|
||||||
<RouterView :key="reloadCount" :router="router"/>
|
<RouterView :key="reloadCount" :router="windowRouter"/>
|
||||||
</div>
|
</div>
|
||||||
</MkWindow>
|
</MkWindow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ComputedRef, onMounted, onUnmounted, provide, shallowRef, ref, computed } from 'vue';
|
import { computed, ComputedRef, onMounted, onUnmounted, provide, ref, shallowRef } from 'vue';
|
||||||
import RouterView from '@/components/global/RouterView.vue';
|
import RouterView from '@/components/global/RouterView.vue';
|
||||||
import MkWindow from '@/components/MkWindow.vue';
|
import MkWindow from '@/components/MkWindow.vue';
|
||||||
import { popout as _popout } from '@/scripts/popout.js';
|
import { popout as _popout } from '@/scripts/popout.js';
|
||||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||||
import { url } from '@/config.js';
|
import { url } from '@/config.js';
|
||||||
import { mainRouter, routes, page } from '@/router.js';
|
import { useScrollPositionManager } from '@/nirax.js';
|
||||||
import { $i } from '@/account.js';
|
|
||||||
import { Router, useScrollPositionManager } from '@/nirax.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
import { openingWindowsCount } from '@/os.js';
|
import { openingWindowsCount } from '@/os.js';
|
||||||
import { claimAchievement } from '@/scripts/achievements.js';
|
import { claimAchievement } from '@/scripts/achievements.js';
|
||||||
import { getScrollContainer } from '@/scripts/scroll.js';
|
import { getScrollContainer } from '@/scripts/scroll.js';
|
||||||
|
import { useRouterFactory } from '@/global/router/supplier.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
initialPath: string;
|
initialPath: string;
|
||||||
|
@ -52,14 +52,15 @@ defineEmits<{
|
||||||
(ev: 'closed'): void;
|
(ev: 'closed'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const router = new Router(routes, props.initialPath, !!$i, page(() => import('@/pages/not-found.vue')));
|
const routerFactory = useRouterFactory();
|
||||||
|
const windowRouter = routerFactory(props.initialPath);
|
||||||
|
|
||||||
const contents = shallowRef<HTMLElement>();
|
const contents = shallowRef<HTMLElement>();
|
||||||
const pageMetadata = ref<null | ComputedRef<PageMetadata>>();
|
const pageMetadata = ref<null | ComputedRef<PageMetadata>>();
|
||||||
const windowEl = shallowRef<InstanceType<typeof MkWindow>>();
|
const windowEl = shallowRef<InstanceType<typeof MkWindow>>();
|
||||||
const history = ref<{ path: string; key: any; }[]>([{
|
const history = ref<{ path: string; key: any; }[]>([{
|
||||||
path: router.getCurrentPath(),
|
path: windowRouter.getCurrentPath(),
|
||||||
key: router.getCurrentKey(),
|
key: windowRouter.getCurrentKey(),
|
||||||
}]);
|
}]);
|
||||||
const buttonsLeft = computed(() => {
|
const buttonsLeft = computed(() => {
|
||||||
const buttons = [];
|
const buttons = [];
|
||||||
|
@ -88,11 +89,11 @@ const buttonsRight = computed(() => {
|
||||||
});
|
});
|
||||||
const reloadCount = ref(0);
|
const reloadCount = ref(0);
|
||||||
|
|
||||||
router.addListener('push', ctx => {
|
windowRouter.addListener('push', ctx => {
|
||||||
history.value.push({ path: ctx.path, key: ctx.key });
|
history.value.push({ path: ctx.path, key: ctx.key });
|
||||||
});
|
});
|
||||||
|
|
||||||
provide('router', router);
|
provide('router', windowRouter);
|
||||||
provideMetadataReceiver((info) => {
|
provideMetadataReceiver((info) => {
|
||||||
pageMetadata.value = info;
|
pageMetadata.value = info;
|
||||||
});
|
});
|
||||||
|
@ -112,20 +113,20 @@ const contextmenu = computed(() => ([{
|
||||||
icon: 'ti ti-external-link',
|
icon: 'ti ti-external-link',
|
||||||
text: i18n.ts.openInNewTab,
|
text: i18n.ts.openInNewTab,
|
||||||
action: () => {
|
action: () => {
|
||||||
window.open(url + router.getCurrentPath(), '_blank', 'noopener');
|
window.open(url + windowRouter.getCurrentPath(), '_blank', 'noopener');
|
||||||
windowEl.value.close();
|
windowEl.value.close();
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
icon: 'ti ti-link',
|
icon: 'ti ti-link',
|
||||||
text: i18n.ts.copyLink,
|
text: i18n.ts.copyLink,
|
||||||
action: () => {
|
action: () => {
|
||||||
copyToClipboard(url + router.getCurrentPath());
|
copyToClipboard(url + windowRouter.getCurrentPath());
|
||||||
},
|
},
|
||||||
}]));
|
}]));
|
||||||
|
|
||||||
function back() {
|
function back() {
|
||||||
history.value.pop();
|
history.value.pop();
|
||||||
router.replace(history.value.at(-1)!.path, history.value.at(-1)!.key);
|
windowRouter.replace(history.value.at(-1)!.path, history.value.at(-1)!.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reload() {
|
function reload() {
|
||||||
|
@ -137,16 +138,16 @@ function close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function expand() {
|
function expand() {
|
||||||
mainRouter.push(router.getCurrentPath(), 'forcePage');
|
mainRouter.push(windowRouter.getCurrentPath(), 'forcePage');
|
||||||
windowEl.value.close();
|
windowEl.value.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function popout() {
|
function popout() {
|
||||||
_popout(router.getCurrentPath(), windowEl.value.$el);
|
_popout(windowRouter.getCurrentPath(), windowEl.value.$el);
|
||||||
windowEl.value.close();
|
windowEl.value.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
useScrollPositionManager(() => getScrollContainer(contents.value), router);
|
useScrollPositionManager(() => getScrollContainer(contents.value), windowRouter);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
openingWindowsCount.value++;
|
openingWindowsCount.value++;
|
||||||
|
|
|
@ -15,7 +15,7 @@ import * as os from '@/os.js';
|
||||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||||
import { url } from '@/config.js';
|
import { url } from '@/config.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { useRouter } from '@/router.js';
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
to: string;
|
to: string;
|
||||||
|
|
|
@ -16,12 +16,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { inject, onBeforeUnmount, provide, shallowRef, ref } from 'vue';
|
import { inject, onBeforeUnmount, provide, ref, shallowRef } from 'vue';
|
||||||
import { Resolved, Router } from '@/nirax.js';
|
import { IRouter, Resolved } from '@/nirax.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
router?: Router;
|
router?: IRouter;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const router = props.router ?? inject('router');
|
const router = props.router ?? inject('router');
|
||||||
|
|
571
packages/frontend/src/global/router/definition.ts
Normal file
571
packages/frontend/src/global/router/definition.ts
Normal file
|
@ -0,0 +1,571 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { App, AsyncComponentLoader, defineAsyncComponent, provide } from 'vue';
|
||||||
|
import { IRouter, Router } from '@/nirax.js';
|
||||||
|
import { $i, iAmModerator } from '@/account.js';
|
||||||
|
import MkLoading from '@/pages/_loading_.vue';
|
||||||
|
import MkError from '@/pages/_error_.vue';
|
||||||
|
import { setMainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
|
const page = (loader: AsyncComponentLoader<any>) => defineAsyncComponent({
|
||||||
|
loader: loader,
|
||||||
|
loadingComponent: MkLoading,
|
||||||
|
errorComponent: MkError,
|
||||||
|
});
|
||||||
|
const routes = [{
|
||||||
|
path: '/@:initUser/pages/:initPageName/view-source',
|
||||||
|
component: page(() => import('@/pages/page-editor/page-editor.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/@:username/pages/:pageName',
|
||||||
|
component: page(() => import('@/pages/page.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/@:acct/following',
|
||||||
|
component: page(() => import('@/pages/user/following.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/@:acct/followers',
|
||||||
|
component: page(() => import('@/pages/user/followers.vue')),
|
||||||
|
}, {
|
||||||
|
name: 'user',
|
||||||
|
path: '/@:acct/:page?',
|
||||||
|
component: page(() => import('@/pages/user/index.vue')),
|
||||||
|
}, {
|
||||||
|
name: 'note',
|
||||||
|
path: '/notes/:noteId',
|
||||||
|
component: page(() => import('@/pages/note.vue')),
|
||||||
|
}, {
|
||||||
|
name: 'list',
|
||||||
|
path: '/list/:listId',
|
||||||
|
component: page(() => import('@/pages/list.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/clips/:clipId',
|
||||||
|
component: page(() => import('@/pages/clip.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/instance-info/:host',
|
||||||
|
component: page(() => import('@/pages/instance-info.vue')),
|
||||||
|
}, {
|
||||||
|
name: 'settings',
|
||||||
|
path: '/settings',
|
||||||
|
component: page(() => import('@/pages/settings/index.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
children: [{
|
||||||
|
path: '/profile',
|
||||||
|
name: 'profile',
|
||||||
|
component: page(() => import('@/pages/settings/profile.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/avatar-decoration',
|
||||||
|
name: 'avatarDecoration',
|
||||||
|
component: page(() => import('@/pages/settings/avatar-decoration.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/roles',
|
||||||
|
name: 'roles',
|
||||||
|
component: page(() => import('@/pages/settings/roles.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/privacy',
|
||||||
|
name: 'privacy',
|
||||||
|
component: page(() => import('@/pages/settings/privacy.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/emoji-picker',
|
||||||
|
name: 'emojiPicker',
|
||||||
|
component: page(() => import('@/pages/settings/emoji-picker.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/drive',
|
||||||
|
name: 'drive',
|
||||||
|
component: page(() => import('@/pages/settings/drive.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/drive/cleaner',
|
||||||
|
name: 'drive',
|
||||||
|
component: page(() => import('@/pages/settings/drive-cleaner.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/notifications',
|
||||||
|
name: 'notifications',
|
||||||
|
component: page(() => import('@/pages/settings/notifications.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/email',
|
||||||
|
name: 'email',
|
||||||
|
component: page(() => import('@/pages/settings/email.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/security',
|
||||||
|
name: 'security',
|
||||||
|
component: page(() => import('@/pages/settings/security.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/general',
|
||||||
|
name: 'general',
|
||||||
|
component: page(() => import('@/pages/settings/general.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/theme/install',
|
||||||
|
name: 'theme',
|
||||||
|
component: page(() => import('@/pages/settings/theme.install.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/theme/manage',
|
||||||
|
name: 'theme',
|
||||||
|
component: page(() => import('@/pages/settings/theme.manage.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/theme',
|
||||||
|
name: 'theme',
|
||||||
|
component: page(() => import('@/pages/settings/theme.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/navbar',
|
||||||
|
name: 'navbar',
|
||||||
|
component: page(() => import('@/pages/settings/navbar.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/statusbar',
|
||||||
|
name: 'statusbar',
|
||||||
|
component: page(() => import('@/pages/settings/statusbar.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/sounds',
|
||||||
|
name: 'sounds',
|
||||||
|
component: page(() => import('@/pages/settings/sounds.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/plugin/install',
|
||||||
|
name: 'plugin',
|
||||||
|
component: page(() => import('@/pages/settings/plugin.install.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/plugin',
|
||||||
|
name: 'plugin',
|
||||||
|
component: page(() => import('@/pages/settings/plugin.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/import-export',
|
||||||
|
name: 'import-export',
|
||||||
|
component: page(() => import('@/pages/settings/import-export.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/mute-block',
|
||||||
|
name: 'mute-block',
|
||||||
|
component: page(() => import('@/pages/settings/mute-block.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/api',
|
||||||
|
name: 'api',
|
||||||
|
component: page(() => import('@/pages/settings/api.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/apps',
|
||||||
|
name: 'api',
|
||||||
|
component: page(() => import('@/pages/settings/apps.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/webhook/edit/:webhookId',
|
||||||
|
name: 'webhook',
|
||||||
|
component: page(() => import('@/pages/settings/webhook.edit.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/webhook/new',
|
||||||
|
name: 'webhook',
|
||||||
|
component: page(() => import('@/pages/settings/webhook.new.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/webhook',
|
||||||
|
name: 'webhook',
|
||||||
|
component: page(() => import('@/pages/settings/webhook.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/deck',
|
||||||
|
name: 'deck',
|
||||||
|
component: page(() => import('@/pages/settings/deck.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/preferences-backups',
|
||||||
|
name: 'preferences-backups',
|
||||||
|
component: page(() => import('@/pages/settings/preferences-backups.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/migration',
|
||||||
|
name: 'migration',
|
||||||
|
component: page(() => import('@/pages/settings/migration.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/custom-css',
|
||||||
|
name: 'general',
|
||||||
|
component: page(() => import('@/pages/settings/custom-css.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/accounts',
|
||||||
|
name: 'profile',
|
||||||
|
component: page(() => import('@/pages/settings/accounts.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/other',
|
||||||
|
name: 'other',
|
||||||
|
component: page(() => import('@/pages/settings/other.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/',
|
||||||
|
component: page(() => import('@/pages/_empty_.vue')),
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
path: '/reset-password/:token?',
|
||||||
|
component: page(() => import('@/pages/reset-password.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/signup-complete/:code',
|
||||||
|
component: page(() => import('@/pages/signup-complete.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/announcements',
|
||||||
|
component: page(() => import('@/pages/announcements.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/about',
|
||||||
|
component: page(() => import('@/pages/about.vue')),
|
||||||
|
hash: 'initialTab',
|
||||||
|
}, {
|
||||||
|
path: '/about-misskey',
|
||||||
|
component: page(() => import('@/pages/about-misskey.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/invite',
|
||||||
|
name: 'invite',
|
||||||
|
component: page(() => import('@/pages/invite.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/ads',
|
||||||
|
component: page(() => import('@/pages/ads.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/theme-editor',
|
||||||
|
component: page(() => import('@/pages/theme-editor.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/roles/:role',
|
||||||
|
component: page(() => import('@/pages/role.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/user-tags/:tag',
|
||||||
|
component: page(() => import('@/pages/user-tag.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/explore',
|
||||||
|
component: page(() => import('@/pages/explore.vue')),
|
||||||
|
hash: 'initialTab',
|
||||||
|
}, {
|
||||||
|
path: '/search',
|
||||||
|
component: page(() => import('@/pages/search.vue')),
|
||||||
|
query: {
|
||||||
|
q: 'query',
|
||||||
|
channel: 'channel',
|
||||||
|
type: 'type',
|
||||||
|
origin: 'origin',
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
path: '/authorize-follow',
|
||||||
|
component: page(() => import('@/pages/follow.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/share',
|
||||||
|
component: page(() => import('@/pages/share.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/api-console',
|
||||||
|
component: page(() => import('@/pages/api-console.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/scratchpad',
|
||||||
|
component: page(() => import('@/pages/scratchpad.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/auth/:token',
|
||||||
|
component: page(() => import('@/pages/auth.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/miauth/:session',
|
||||||
|
component: page(() => import('@/pages/miauth.vue')),
|
||||||
|
query: {
|
||||||
|
callback: 'callback',
|
||||||
|
name: 'name',
|
||||||
|
icon: 'icon',
|
||||||
|
permission: 'permission',
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
path: '/oauth/authorize',
|
||||||
|
component: page(() => import('@/pages/oauth.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/tags/:tag',
|
||||||
|
component: page(() => import('@/pages/tag.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/pages/new',
|
||||||
|
component: page(() => import('@/pages/page-editor/page-editor.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/pages/edit/:initPageId',
|
||||||
|
component: page(() => import('@/pages/page-editor/page-editor.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/pages',
|
||||||
|
component: page(() => import('@/pages/pages.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/play/:id/edit',
|
||||||
|
component: page(() => import('@/pages/flash/flash-edit.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/play/new',
|
||||||
|
component: page(() => import('@/pages/flash/flash-edit.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/play/:id',
|
||||||
|
component: page(() => import('@/pages/flash/flash.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/play',
|
||||||
|
component: page(() => import('@/pages/flash/flash-index.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/gallery/:postId/edit',
|
||||||
|
component: page(() => import('@/pages/gallery/edit.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/gallery/new',
|
||||||
|
component: page(() => import('@/pages/gallery/edit.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/gallery/:postId',
|
||||||
|
component: page(() => import('@/pages/gallery/post.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/gallery',
|
||||||
|
component: page(() => import('@/pages/gallery/index.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/channels/:channelId/edit',
|
||||||
|
component: page(() => import('@/pages/channel-editor.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/channels/new',
|
||||||
|
component: page(() => import('@/pages/channel-editor.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/channels/:channelId',
|
||||||
|
component: page(() => import('@/pages/channel.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/channels',
|
||||||
|
component: page(() => import('@/pages/channels.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/custom-emojis-manager',
|
||||||
|
component: page(() => import('@/pages/custom-emojis-manager.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/avatar-decorations',
|
||||||
|
name: 'avatarDecorations',
|
||||||
|
component: page(() => import('@/pages/avatar-decorations.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/registry/keys/:domain/:path(*)?',
|
||||||
|
component: page(() => import('@/pages/registry.keys.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/registry/value/:domain/:path(*)?',
|
||||||
|
component: page(() => import('@/pages/registry.value.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/registry',
|
||||||
|
component: page(() => import('@/pages/registry.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/install-extentions',
|
||||||
|
component: page(() => import('@/pages/install-extentions.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/admin/user/:userId',
|
||||||
|
component: iAmModerator ? page(() => import('@/pages/admin-user.vue')) : page(() => import('@/pages/not-found.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/admin/file/:fileId',
|
||||||
|
component: iAmModerator ? page(() => import('@/pages/admin-file.vue')) : page(() => import('@/pages/not-found.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/admin',
|
||||||
|
component: iAmModerator ? page(() => import('@/pages/admin/index.vue')) : page(() => import('@/pages/not-found.vue')),
|
||||||
|
children: [{
|
||||||
|
path: '/overview',
|
||||||
|
name: 'overview',
|
||||||
|
component: page(() => import('@/pages/admin/overview.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/users',
|
||||||
|
name: 'users',
|
||||||
|
component: page(() => import('@/pages/admin/users.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/emojis',
|
||||||
|
name: 'emojis',
|
||||||
|
component: page(() => import('@/pages/custom-emojis-manager.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/avatar-decorations',
|
||||||
|
name: 'avatarDecorations',
|
||||||
|
component: page(() => import('@/pages/avatar-decorations.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/queue',
|
||||||
|
name: 'queue',
|
||||||
|
component: page(() => import('@/pages/admin/queue.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/files',
|
||||||
|
name: 'files',
|
||||||
|
component: page(() => import('@/pages/admin/files.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/federation',
|
||||||
|
name: 'federation',
|
||||||
|
component: page(() => import('@/pages/admin/federation.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/announcements',
|
||||||
|
name: 'announcements',
|
||||||
|
component: page(() => import('@/pages/admin/announcements.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/ads',
|
||||||
|
name: 'ads',
|
||||||
|
component: page(() => import('@/pages/admin/ads.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/roles/:id/edit',
|
||||||
|
name: 'roles',
|
||||||
|
component: page(() => import('@/pages/admin/roles.edit.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/roles/new',
|
||||||
|
name: 'roles',
|
||||||
|
component: page(() => import('@/pages/admin/roles.edit.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/roles/:id',
|
||||||
|
name: 'roles',
|
||||||
|
component: page(() => import('@/pages/admin/roles.role.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/roles',
|
||||||
|
name: 'roles',
|
||||||
|
component: page(() => import('@/pages/admin/roles.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/database',
|
||||||
|
name: 'database',
|
||||||
|
component: page(() => import('@/pages/admin/database.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/abuses',
|
||||||
|
name: 'abuses',
|
||||||
|
component: page(() => import('@/pages/admin/abuses.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/modlog',
|
||||||
|
name: 'modlog',
|
||||||
|
component: page(() => import('@/pages/admin/modlog.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/settings',
|
||||||
|
name: 'settings',
|
||||||
|
component: page(() => import('@/pages/admin/settings.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/branding',
|
||||||
|
name: 'branding',
|
||||||
|
component: page(() => import('@/pages/admin/branding.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/moderation',
|
||||||
|
name: 'moderation',
|
||||||
|
component: page(() => import('@/pages/admin/moderation.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/email-settings',
|
||||||
|
name: 'email-settings',
|
||||||
|
component: page(() => import('@/pages/admin/email-settings.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/object-storage',
|
||||||
|
name: 'object-storage',
|
||||||
|
component: page(() => import('@/pages/admin/object-storage.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/security',
|
||||||
|
name: 'security',
|
||||||
|
component: page(() => import('@/pages/admin/security.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/relays',
|
||||||
|
name: 'relays',
|
||||||
|
component: page(() => import('@/pages/admin/relays.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/instance-block',
|
||||||
|
name: 'instance-block',
|
||||||
|
component: page(() => import('@/pages/admin/instance-block.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/proxy-account',
|
||||||
|
name: 'proxy-account',
|
||||||
|
component: page(() => import('@/pages/admin/proxy-account.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/external-services',
|
||||||
|
name: 'external-services',
|
||||||
|
component: page(() => import('@/pages/admin/external-services.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/other-settings',
|
||||||
|
name: 'other-settings',
|
||||||
|
component: page(() => import('@/pages/admin/other-settings.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/server-rules',
|
||||||
|
name: 'server-rules',
|
||||||
|
component: page(() => import('@/pages/admin/server-rules.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/invites',
|
||||||
|
name: 'invites',
|
||||||
|
component: page(() => import('@/pages/admin/invites.vue')),
|
||||||
|
}, {
|
||||||
|
path: '/',
|
||||||
|
component: page(() => import('@/pages/_empty_.vue')),
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
path: '/my/notifications',
|
||||||
|
component: page(() => import('@/pages/notifications.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/favorites',
|
||||||
|
component: page(() => import('@/pages/favorites.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/achievements',
|
||||||
|
component: page(() => import('@/pages/achievements.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/drive/folder/:folder',
|
||||||
|
component: page(() => import('@/pages/drive.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/drive',
|
||||||
|
component: page(() => import('@/pages/drive.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/drive/file/:fileId',
|
||||||
|
component: page(() => import('@/pages/drive.file.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/follow-requests',
|
||||||
|
component: page(() => import('@/pages/follow-requests.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/lists/:listId',
|
||||||
|
component: page(() => import('@/pages/my-lists/list.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/lists',
|
||||||
|
component: page(() => import('@/pages/my-lists/index.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/clips',
|
||||||
|
component: page(() => import('@/pages/my-clips/index.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/antennas/create',
|
||||||
|
component: page(() => import('@/pages/my-antennas/create.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/antennas/:antennaId',
|
||||||
|
component: page(() => import('@/pages/my-antennas/edit.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/my/antennas',
|
||||||
|
component: page(() => import('@/pages/my-antennas/index.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/timeline/list/:listId',
|
||||||
|
component: page(() => import('@/pages/user-list-timeline.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/timeline/antenna/:antennaId',
|
||||||
|
component: page(() => import('@/pages/antenna-timeline.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/clicker',
|
||||||
|
component: page(() => import('@/pages/clicker.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/bubble-game',
|
||||||
|
component: page(() => import('@/pages/drop-and-fusion.vue')),
|
||||||
|
loginRequired: true,
|
||||||
|
}, {
|
||||||
|
path: '/timeline',
|
||||||
|
component: page(() => import('@/pages/timeline.vue')),
|
||||||
|
}, {
|
||||||
|
name: 'index',
|
||||||
|
path: '/',
|
||||||
|
component: $i ? page(() => import('@/pages/timeline.vue')) : page(() => import('@/pages/welcome.vue')),
|
||||||
|
globalCacheKey: 'index',
|
||||||
|
}, {
|
||||||
|
path: '/:(*)',
|
||||||
|
component: page(() => import('@/pages/not-found.vue')),
|
||||||
|
}];
|
||||||
|
|
||||||
|
function createRouterImpl(path: string): IRouter {
|
||||||
|
return new Router(routes, path, !!$i, page(() => import('@/pages/not-found.vue')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Router}による画面遷移を可能とするために{@link mainRouter}をセットアップする。
|
||||||
|
* また、{@link Router}のインスタンスを作成するためのファクトリも{@link provide}経由で公開する(`routerFactory`というキーで取得可能)
|
||||||
|
*/
|
||||||
|
export function setupRouter(app: App) {
|
||||||
|
app.provide('routerFactory', createRouterImpl);
|
||||||
|
|
||||||
|
const mainRouter = createRouterImpl(location.pathname + location.search + location.hash);
|
||||||
|
|
||||||
|
window.history.replaceState({ key: mainRouter.getCurrentKey() }, '', location.href);
|
||||||
|
|
||||||
|
window.addEventListener('popstate', (event) => {
|
||||||
|
mainRouter.replace(location.pathname + location.search + location.hash, event.state?.key);
|
||||||
|
});
|
||||||
|
|
||||||
|
mainRouter.addListener('push', ctx => {
|
||||||
|
window.history.pushState({ key: ctx.key }, '', ctx.path);
|
||||||
|
});
|
||||||
|
|
||||||
|
setMainRouter(mainRouter);
|
||||||
|
}
|
163
packages/frontend/src/global/router/main.ts
Normal file
163
packages/frontend/src/global/router/main.ts
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ShallowRef } from 'vue';
|
||||||
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
import { IRouter, Resolved, RouteDef, RouterEvent } from '@/nirax.js';
|
||||||
|
|
||||||
|
function getMainRouter(): IRouter {
|
||||||
|
const router = mainRouterHolder;
|
||||||
|
if (!router) {
|
||||||
|
throw new Error('mainRouter is not found.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* メインルータを設定する。一度設定すると、それ以降は変更できない。
|
||||||
|
* {@link setupRouter}から呼び出されることのみを想定している。
|
||||||
|
*/
|
||||||
|
export function setMainRouter(router: IRouter) {
|
||||||
|
if (mainRouterHolder) {
|
||||||
|
throw new Error('mainRouter is already exists.');
|
||||||
|
}
|
||||||
|
|
||||||
|
mainRouterHolder = router;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mainRouter}用のプロキシ実装。
|
||||||
|
* {@link mainRouter}は起動シーケンスの一部にて初期化されるため、僅かにundefinedになる期間がある。
|
||||||
|
* その僅かな期間のためだけに型をundefined込みにしたくないのでこのクラスを緩衝材として使用する。
|
||||||
|
*/
|
||||||
|
class MainRouterProxy implements IRouter {
|
||||||
|
private supplier: () => IRouter;
|
||||||
|
|
||||||
|
constructor(supplier: () => IRouter) {
|
||||||
|
this.supplier = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
get current(): Resolved {
|
||||||
|
return this.supplier().current;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentRef(): ShallowRef<Resolved> {
|
||||||
|
return this.supplier().currentRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentRoute(): ShallowRef<RouteDef> {
|
||||||
|
return this.supplier().currentRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
get navHook(): ((path: string, flag?: any) => boolean) | null {
|
||||||
|
return this.supplier().navHook;
|
||||||
|
}
|
||||||
|
|
||||||
|
set navHook(value) {
|
||||||
|
this.supplier().navHook = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentKey(): string {
|
||||||
|
return this.supplier().getCurrentKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentPath(): any {
|
||||||
|
return this.supplier().getCurrentPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
push(path: string, flag?: any): void {
|
||||||
|
this.supplier().push(path, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
replace(path: string, key?: string | null): void {
|
||||||
|
this.supplier().replace(path, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(path: string): Resolved | null {
|
||||||
|
return this.supplier().resolve(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
eventNames(): Array<EventEmitter.EventNames<RouterEvent>> {
|
||||||
|
return this.supplier().eventNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
listeners<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
): Array<EventEmitter.EventListener<RouterEvent, T>> {
|
||||||
|
return this.supplier().listeners(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
listenerCount(
|
||||||
|
event: EventEmitter.EventNames<RouterEvent>,
|
||||||
|
): number {
|
||||||
|
return this.supplier().listenerCount(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
...args: EventEmitter.EventArgs<RouterEvent, T>
|
||||||
|
): boolean {
|
||||||
|
return this.supplier().emit(event, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
on<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any,
|
||||||
|
): this {
|
||||||
|
this.supplier().on(event, fn, context);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addListener<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any,
|
||||||
|
): this {
|
||||||
|
this.supplier().addListener(event, fn, context);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
once<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any,
|
||||||
|
): this {
|
||||||
|
this.supplier().once(event, fn, context);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeListener<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn?: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any,
|
||||||
|
once?: boolean,
|
||||||
|
): this {
|
||||||
|
this.supplier().removeListener(event, fn, context, once);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
off<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn?: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any,
|
||||||
|
once?: boolean,
|
||||||
|
): this {
|
||||||
|
this.supplier().off(event, fn, context, once);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeAllListeners(
|
||||||
|
event?: EventEmitter.EventNames<RouterEvent>,
|
||||||
|
): this {
|
||||||
|
this.supplier().removeAllListeners(event);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mainRouterHolder: IRouter | null = null;
|
||||||
|
|
||||||
|
export const mainRouter: IRouter = new MainRouterProxy(getMainRouter);
|
30
packages/frontend/src/global/router/supplier.ts
Normal file
30
packages/frontend/src/global/router/supplier.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { inject } from 'vue';
|
||||||
|
import { IRouter, Router } from '@/nirax.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* メインの{@link Router}を取得する。
|
||||||
|
* あらかじめ{@link setupRouter}を実行しておく必要がある({@link provide}により{@link IRouter}のインスタンスを注入可能であるならばこの限りではない)
|
||||||
|
*/
|
||||||
|
export function useRouter(): IRouter {
|
||||||
|
return inject<Router | null>('router', null) ?? mainRouter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任意の{@link Router}を取得するためのファクトリを取得する。
|
||||||
|
* あらかじめ{@link setupRouter}を実行しておく必要がある。
|
||||||
|
*/
|
||||||
|
export function useRouterFactory(): (path: string) => IRouter {
|
||||||
|
const factory = inject<(path: string) => IRouter>('routerFactory');
|
||||||
|
if (!factory) {
|
||||||
|
console.error('routerFactory is not defined.');
|
||||||
|
throw new Error('routerFactory is not defined.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return factory;
|
||||||
|
}
|
|
@ -5,11 +5,11 @@
|
||||||
|
|
||||||
// NIRAX --- A lightweight router
|
// NIRAX --- A lightweight router
|
||||||
|
|
||||||
import { EventEmitter } from 'eventemitter3';
|
|
||||||
import { Component, onMounted, shallowRef, ShallowRef } from 'vue';
|
import { Component, onMounted, shallowRef, ShallowRef } from 'vue';
|
||||||
|
import { EventEmitter } from 'eventemitter3';
|
||||||
import { safeURIDecode } from '@/scripts/safe-uri-decode.js';
|
import { safeURIDecode } from '@/scripts/safe-uri-decode.js';
|
||||||
|
|
||||||
type RouteDef = {
|
export type RouteDef = {
|
||||||
path: string;
|
path: string;
|
||||||
component: Component;
|
component: Component;
|
||||||
query?: Record<string, string>;
|
query?: Record<string, string>;
|
||||||
|
@ -27,6 +27,27 @@ type ParsedPath = (string | {
|
||||||
optional?: boolean;
|
optional?: boolean;
|
||||||
})[];
|
})[];
|
||||||
|
|
||||||
|
export type RouterEvent = {
|
||||||
|
change: (ctx: {
|
||||||
|
beforePath: string;
|
||||||
|
path: string;
|
||||||
|
resolved: Resolved;
|
||||||
|
key: string;
|
||||||
|
}) => void;
|
||||||
|
replace: (ctx: {
|
||||||
|
path: string;
|
||||||
|
key: string;
|
||||||
|
}) => void;
|
||||||
|
push: (ctx: {
|
||||||
|
beforePath: string;
|
||||||
|
path: string;
|
||||||
|
route: RouteDef | null;
|
||||||
|
props: Map<string, string> | null;
|
||||||
|
key: string;
|
||||||
|
}) => void;
|
||||||
|
same: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
export type Resolved = { route: RouteDef; props: Map<string, string | boolean>; child?: Resolved; };
|
export type Resolved = { route: RouteDef; props: Map<string, string | boolean>; child?: Resolved; };
|
||||||
|
|
||||||
function parsePath(path: string): ParsedPath {
|
function parsePath(path: string): ParsedPath {
|
||||||
|
@ -54,26 +75,85 @@ function parsePath(path: string): ParsedPath {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Router extends EventEmitter<{
|
export interface IRouter extends EventEmitter<RouterEvent> {
|
||||||
change: (ctx: {
|
current: Resolved;
|
||||||
beforePath: string;
|
currentRef: ShallowRef<Resolved>;
|
||||||
path: string;
|
currentRoute: ShallowRef<RouteDef>;
|
||||||
resolved: Resolved;
|
navHook: ((path: string, flag?: any) => boolean) | null;
|
||||||
key: string;
|
|
||||||
}) => void;
|
resolve(path: string): Resolved | null;
|
||||||
replace: (ctx: {
|
|
||||||
path: string;
|
getCurrentPath(): any;
|
||||||
key: string;
|
|
||||||
}) => void;
|
getCurrentKey(): string;
|
||||||
push: (ctx: {
|
|
||||||
beforePath: string;
|
push(path: string, flag?: any): void;
|
||||||
path: string;
|
|
||||||
route: RouteDef | null;
|
replace(path: string, key?: string | null): void;
|
||||||
props: Map<string, string> | null;
|
|
||||||
key: string;
|
/** @see EventEmitter */
|
||||||
}) => void;
|
eventNames(): Array<EventEmitter.EventNames<RouterEvent>>;
|
||||||
same: () => void;
|
|
||||||
}> {
|
/** @see EventEmitter */
|
||||||
|
listeners<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T
|
||||||
|
): Array<EventEmitter.EventListener<RouterEvent, T>>;
|
||||||
|
|
||||||
|
/** @see EventEmitter */
|
||||||
|
listenerCount(
|
||||||
|
event: EventEmitter.EventNames<RouterEvent>
|
||||||
|
): number;
|
||||||
|
|
||||||
|
/** @see EventEmitter */
|
||||||
|
emit<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
...args: EventEmitter.EventArgs<RouterEvent, T>
|
||||||
|
): boolean;
|
||||||
|
|
||||||
|
/** @see EventEmitter */
|
||||||
|
on<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/** @see EventEmitter */
|
||||||
|
addListener<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/** @see EventEmitter */
|
||||||
|
once<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/** @see EventEmitter */
|
||||||
|
removeListener<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn?: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any,
|
||||||
|
once?: boolean | undefined
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/** @see EventEmitter */
|
||||||
|
off<T extends EventEmitter.EventNames<RouterEvent>>(
|
||||||
|
event: T,
|
||||||
|
fn?: EventEmitter.EventListener<RouterEvent, T>,
|
||||||
|
context?: any,
|
||||||
|
once?: boolean | undefined
|
||||||
|
): this;
|
||||||
|
|
||||||
|
/** @see EventEmitter */
|
||||||
|
removeAllListeners(
|
||||||
|
event?: EventEmitter.EventNames<RouterEvent>
|
||||||
|
): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Router extends EventEmitter<RouterEvent> implements IRouter {
|
||||||
private routes: RouteDef[];
|
private routes: RouteDef[];
|
||||||
public current: Resolved;
|
public current: Resolved;
|
||||||
public currentRef: ShallowRef<Resolved> = shallowRef();
|
public currentRef: ShallowRef<Resolved> = shallowRef();
|
||||||
|
@ -277,7 +357,7 @@ export class Router extends EventEmitter<{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useScrollPositionManager(getScrollContainer: () => HTMLElement, router: Router) {
|
export function useScrollPositionManager(getScrollContainer: () => HTMLElement, router: IRouter) {
|
||||||
const scrollPosStore = new Map<string, number>();
|
const scrollPosStore = new Map<string, number>();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -36,8 +36,8 @@ import { instance } from '@/instance.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { lookupUser, lookupUserByEmail } from '@/scripts/lookup-user.js';
|
import { lookupUser, lookupUserByEmail } from '@/scripts/lookup-user.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { PageMetadata, definePageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, definePageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const isEmpty = (x: string | null) => x == null || x === '';
|
const isEmpty = (x: string | null) => x == null || x === '';
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,9 @@ import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { rolesCache } from '@/cache.js';
|
import { rolesCache } from '@/cache.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -70,12 +70,12 @@ import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
import MkPagination from '@/components/MkPagination.vue';
|
import MkPagination from '@/components/MkPagination.vue';
|
||||||
import { infoImageUrl } from '@/instance.js';
|
import { infoImageUrl } from '@/instance.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -237,9 +237,9 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||||
import { ROLE_POLICIES } from '@/const.js';
|
import { ROLE_POLICIES } from '@/const.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const baseRoleQ = ref('');
|
const baseRoleQ = ref('');
|
||||||
|
|
|
@ -30,9 +30,9 @@ import MkTimeline from '@/components/MkTimeline.vue';
|
||||||
import { scroll } from '@/scripts/scroll.js';
|
import { scroll } from '@/scripts/scroll.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -77,12 +77,12 @@ import MkColorInput from '@/components/MkColorInput.vue';
|
||||||
import { selectFile } from '@/scripts/select-file.js';
|
import { selectFile } from '@/scripts/select-file.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import MkTextarea from '@/components/MkTextarea.vue';
|
import MkTextarea from '@/components/MkTextarea.vue';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
|
const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,6 @@ import MkTimeline from '@/components/MkTimeline.vue';
|
||||||
import XChannelFollowButton from '@/components/MkChannelFollowButton.vue';
|
import XChannelFollowButton from '@/components/MkChannelFollowButton.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { $i, iAmModerator } from '@/account.js';
|
import { $i, iAmModerator } from '@/account.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
|
@ -92,6 +91,7 @@ import { PageHeaderItem } from '@/types/page-header.js';
|
||||||
import { isSupportShare } from '@/scripts/navigator.js';
|
import { isSupportShare } from '@/scripts/navigator.js';
|
||||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -58,9 +58,9 @@ import MkInput from '@/components/MkInput.vue';
|
||||||
import MkRadios from '@/components/MkRadios.vue';
|
import MkRadios from '@/components/MkRadios.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ import { infoImageUrl } from '@/instance.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { useRouter } from '@/router.js';
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
||||||
import MkCodeEditor from '@/components/MkCodeEditor.vue';
|
import MkCodeEditor from '@/components/MkCodeEditor.vue';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
import { useRouter } from '@/router.js';
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const PRESET_DEFAULT = `/// @ 0.16.0
|
const PRESET_DEFAULT = `/// @ 0.16.0
|
||||||
|
|
||||||
|
|
|
@ -42,9 +42,9 @@ import { computed, ref } from 'vue';
|
||||||
import MkFlashPreview from '@/components/MkFlashPreview.vue';
|
import MkFlashPreview from '@/components/MkFlashPreview.vue';
|
||||||
import MkPagination from '@/components/MkPagination.vue';
|
import MkPagination from '@/components/MkPagination.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ import { } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
async function follow(user): Promise<void> {
|
async function follow(user): Promise<void> {
|
||||||
const { canceled } = await os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
|
|
|
@ -48,9 +48,9 @@ import FormSuspense from '@/components/form/suspense.vue';
|
||||||
import { selectFiles } from '@/scripts/select-file.js';
|
import { selectFiles } from '@/scripts/select-file.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ import MkPagination from '@/components/MkPagination.vue';
|
||||||
import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue';
|
import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { useRouter } from '@/router.js';
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -72,13 +72,13 @@ import MkPagination from '@/components/MkPagination.vue';
|
||||||
import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue';
|
import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue';
|
||||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||||
import { url } from '@/config.js';
|
import { url } from '@/config.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
import { isSupportShare } from '@/scripts/navigator.js';
|
import { isSupportShare } from '@/scripts/navigator.js';
|
||||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ import { ref } from 'vue';
|
||||||
import XAntenna from './editor.vue';
|
import XAntenna from './editor.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { antennasCache } from '@/cache.js';
|
import { antennasCache } from '@/cache.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ import * as Misskey from 'misskey-js';
|
||||||
import XAntenna from './editor.vue';
|
import XAntenna from './editor.vue';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { antennasCache } from '@/cache.js';
|
import { antennasCache } from '@/cache.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,6 @@ import * as Misskey from 'misskey-js';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { userPage } from '@/filters/user.js';
|
import { userPage } from '@/filters/user.js';
|
||||||
|
@ -70,6 +69,7 @@ import { userListsCache } from '@/cache.js';
|
||||||
import { signinRequired } from '@/account.js';
|
import { signinRequired } from '@/account.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
import MkPagination from '@/components/MkPagination.vue';
|
import MkPagination from '@/components/MkPagination.vue';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
const $i = signinRequired();
|
const $i = signinRequired();
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,10 @@ import { url } from '@/config.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { selectFile } from '@/scripts/select-file.js';
|
import { selectFile } from '@/scripts/select-file.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
initPageId?: string;
|
initPageId?: string;
|
||||||
|
|
|
@ -40,9 +40,9 @@ import { computed, ref } from 'vue';
|
||||||
import MkPagePreview from '@/components/MkPagePreview.vue';
|
import MkPagePreview from '@/components/MkPagePreview.vue';
|
||||||
import MkPagination from '@/components/MkPagination.vue';
|
import MkPagination from '@/components/MkPagination.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ import MkInput from '@/components/MkInput.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
token?: string;
|
token?: string;
|
||||||
|
|
|
@ -51,8 +51,8 @@ import { i18n } from '@/i18n.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ import { i18n } from '@/i18n.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { useRouter } from '@/router.js';
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,9 @@ import MkSuperMenu from '@/components/MkSuperMenu.vue';
|
||||||
import { signout, $i } from '@/account.js';
|
import { signout, $i } from '@/account.js';
|
||||||
import { clearCache } from '@/scripts/clear-cache.js';
|
import { clearCache } from '@/scripts/clear-cache.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { PageMetadata, definePageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, definePageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const indexInfo = {
|
const indexInfo = {
|
||||||
title: i18n.ts.settings,
|
title: i18n.ts.settings,
|
||||||
|
|
|
@ -51,7 +51,7 @@ import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { useRouter } from '@/router.js';
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ import * as Misskey from 'misskey-js';
|
||||||
import MkTimeline from '@/components/MkTimeline.vue';
|
import MkTimeline from '@/components/MkTimeline.vue';
|
||||||
import { scroll } from '@/scripts/scroll.js';
|
import { scroll } from '@/scripts/scroll.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
|
@ -166,13 +166,13 @@ import { getUserMenu } from '@/scripts/get-user-menu.js';
|
||||||
import number from '@/filters/number.js';
|
import number from '@/filters/number.js';
|
||||||
import { userPage } from '@/filters/user.js';
|
import { userPage } from '@/filters/user.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { useRouter } from '@/router.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { $i, iAmModerator } from '@/account.js';
|
import { $i, iAmModerator } from '@/account.js';
|
||||||
import { dateString } from '@/filters/date.js';
|
import { dateString } from '@/filters/date.js';
|
||||||
import { confetti } from '@/scripts/confetti.js';
|
import { confetti } from '@/scripts/confetti.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js';
|
import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js';
|
||||||
|
import { useRouter } from '@/global/router/supplier.js';
|
||||||
|
|
||||||
function calcAge(birthdate: string): number {
|
function calcAge(birthdate: string): number {
|
||||||
const date = new Date(birthdate);
|
const date = new Date(birthdate);
|
||||||
|
|
|
@ -1,561 +0,0 @@
|
||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: syuilo and other misskey contributors
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { AsyncComponentLoader, defineAsyncComponent, inject } from 'vue';
|
|
||||||
import { Router } from '@/nirax.js';
|
|
||||||
import { $i, iAmModerator } from '@/account.js';
|
|
||||||
import MkLoading from '@/pages/_loading_.vue';
|
|
||||||
import MkError from '@/pages/_error_.vue';
|
|
||||||
|
|
||||||
export const page = (loader: AsyncComponentLoader<any>) => defineAsyncComponent({
|
|
||||||
loader: loader,
|
|
||||||
loadingComponent: MkLoading,
|
|
||||||
errorComponent: MkError,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const routes = [{
|
|
||||||
path: '/@:initUser/pages/:initPageName/view-source',
|
|
||||||
component: page(() => import('./pages/page-editor/page-editor.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/@:username/pages/:pageName',
|
|
||||||
component: page(() => import('./pages/page.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/@:acct/following',
|
|
||||||
component: page(() => import('./pages/user/following.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/@:acct/followers',
|
|
||||||
component: page(() => import('./pages/user/followers.vue')),
|
|
||||||
}, {
|
|
||||||
name: 'user',
|
|
||||||
path: '/@:acct/:page?',
|
|
||||||
component: page(() => import('./pages/user/index.vue')),
|
|
||||||
}, {
|
|
||||||
name: 'note',
|
|
||||||
path: '/notes/:noteId',
|
|
||||||
component: page(() => import('./pages/note.vue')),
|
|
||||||
}, {
|
|
||||||
name: 'list',
|
|
||||||
path: '/list/:listId',
|
|
||||||
component: page(() => import('./pages/list.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/clips/:clipId',
|
|
||||||
component: page(() => import('./pages/clip.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/instance-info/:host',
|
|
||||||
component: page(() => import('./pages/instance-info.vue')),
|
|
||||||
}, {
|
|
||||||
name: 'settings',
|
|
||||||
path: '/settings',
|
|
||||||
component: page(() => import('./pages/settings/index.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
children: [{
|
|
||||||
path: '/profile',
|
|
||||||
name: 'profile',
|
|
||||||
component: page(() => import('./pages/settings/profile.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/avatar-decoration',
|
|
||||||
name: 'avatarDecoration',
|
|
||||||
component: page(() => import('./pages/settings/avatar-decoration.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/roles',
|
|
||||||
name: 'roles',
|
|
||||||
component: page(() => import('./pages/settings/roles.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/privacy',
|
|
||||||
name: 'privacy',
|
|
||||||
component: page(() => import('./pages/settings/privacy.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/emoji-picker',
|
|
||||||
name: 'emojiPicker',
|
|
||||||
component: page(() => import('./pages/settings/emoji-picker.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/drive',
|
|
||||||
name: 'drive',
|
|
||||||
component: page(() => import('./pages/settings/drive.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/drive/cleaner',
|
|
||||||
name: 'drive',
|
|
||||||
component: page(() => import('./pages/settings/drive-cleaner.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/notifications',
|
|
||||||
name: 'notifications',
|
|
||||||
component: page(() => import('./pages/settings/notifications.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/email',
|
|
||||||
name: 'email',
|
|
||||||
component: page(() => import('./pages/settings/email.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/security',
|
|
||||||
name: 'security',
|
|
||||||
component: page(() => import('./pages/settings/security.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/general',
|
|
||||||
name: 'general',
|
|
||||||
component: page(() => import('./pages/settings/general.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/theme/install',
|
|
||||||
name: 'theme',
|
|
||||||
component: page(() => import('./pages/settings/theme.install.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/theme/manage',
|
|
||||||
name: 'theme',
|
|
||||||
component: page(() => import('./pages/settings/theme.manage.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/theme',
|
|
||||||
name: 'theme',
|
|
||||||
component: page(() => import('./pages/settings/theme.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/navbar',
|
|
||||||
name: 'navbar',
|
|
||||||
component: page(() => import('./pages/settings/navbar.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/statusbar',
|
|
||||||
name: 'statusbar',
|
|
||||||
component: page(() => import('./pages/settings/statusbar.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/sounds',
|
|
||||||
name: 'sounds',
|
|
||||||
component: page(() => import('./pages/settings/sounds.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/plugin/install',
|
|
||||||
name: 'plugin',
|
|
||||||
component: page(() => import('./pages/settings/plugin.install.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/plugin',
|
|
||||||
name: 'plugin',
|
|
||||||
component: page(() => import('./pages/settings/plugin.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/import-export',
|
|
||||||
name: 'import-export',
|
|
||||||
component: page(() => import('./pages/settings/import-export.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/mute-block',
|
|
||||||
name: 'mute-block',
|
|
||||||
component: page(() => import('./pages/settings/mute-block.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/api',
|
|
||||||
name: 'api',
|
|
||||||
component: page(() => import('./pages/settings/api.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/apps',
|
|
||||||
name: 'api',
|
|
||||||
component: page(() => import('./pages/settings/apps.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/webhook/edit/:webhookId',
|
|
||||||
name: 'webhook',
|
|
||||||
component: page(() => import('./pages/settings/webhook.edit.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/webhook/new',
|
|
||||||
name: 'webhook',
|
|
||||||
component: page(() => import('./pages/settings/webhook.new.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/webhook',
|
|
||||||
name: 'webhook',
|
|
||||||
component: page(() => import('./pages/settings/webhook.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/deck',
|
|
||||||
name: 'deck',
|
|
||||||
component: page(() => import('./pages/settings/deck.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/preferences-backups',
|
|
||||||
name: 'preferences-backups',
|
|
||||||
component: page(() => import('./pages/settings/preferences-backups.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/migration',
|
|
||||||
name: 'migration',
|
|
||||||
component: page(() => import('./pages/settings/migration.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/custom-css',
|
|
||||||
name: 'general',
|
|
||||||
component: page(() => import('./pages/settings/custom-css.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/accounts',
|
|
||||||
name: 'profile',
|
|
||||||
component: page(() => import('./pages/settings/accounts.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/other',
|
|
||||||
name: 'other',
|
|
||||||
component: page(() => import('./pages/settings/other.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/',
|
|
||||||
component: page(() => import('./pages/_empty_.vue')),
|
|
||||||
}],
|
|
||||||
}, {
|
|
||||||
path: '/reset-password/:token?',
|
|
||||||
component: page(() => import('./pages/reset-password.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/signup-complete/:code',
|
|
||||||
component: page(() => import('./pages/signup-complete.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/announcements',
|
|
||||||
component: page(() => import('./pages/announcements.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/about',
|
|
||||||
component: page(() => import('./pages/about.vue')),
|
|
||||||
hash: 'initialTab',
|
|
||||||
}, {
|
|
||||||
path: '/about-misskey',
|
|
||||||
component: page(() => import('./pages/about-misskey.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/invite',
|
|
||||||
name: 'invite',
|
|
||||||
component: page(() => import('./pages/invite.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/ads',
|
|
||||||
component: page(() => import('./pages/ads.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/theme-editor',
|
|
||||||
component: page(() => import('./pages/theme-editor.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/roles/:role',
|
|
||||||
component: page(() => import('./pages/role.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/user-tags/:tag',
|
|
||||||
component: page(() => import('./pages/user-tag.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/explore',
|
|
||||||
component: page(() => import('./pages/explore.vue')),
|
|
||||||
hash: 'initialTab',
|
|
||||||
}, {
|
|
||||||
path: '/search',
|
|
||||||
component: page(() => import('./pages/search.vue')),
|
|
||||||
query: {
|
|
||||||
q: 'query',
|
|
||||||
channel: 'channel',
|
|
||||||
type: 'type',
|
|
||||||
origin: 'origin',
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
path: '/authorize-follow',
|
|
||||||
component: page(() => import('./pages/follow.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/share',
|
|
||||||
component: page(() => import('./pages/share.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/api-console',
|
|
||||||
component: page(() => import('./pages/api-console.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/scratchpad',
|
|
||||||
component: page(() => import('./pages/scratchpad.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/auth/:token',
|
|
||||||
component: page(() => import('./pages/auth.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/miauth/:session',
|
|
||||||
component: page(() => import('./pages/miauth.vue')),
|
|
||||||
query: {
|
|
||||||
callback: 'callback',
|
|
||||||
name: 'name',
|
|
||||||
icon: 'icon',
|
|
||||||
permission: 'permission',
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
path: '/oauth/authorize',
|
|
||||||
component: page(() => import('./pages/oauth.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/tags/:tag',
|
|
||||||
component: page(() => import('./pages/tag.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/pages/new',
|
|
||||||
component: page(() => import('./pages/page-editor/page-editor.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/pages/edit/:initPageId',
|
|
||||||
component: page(() => import('./pages/page-editor/page-editor.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/pages',
|
|
||||||
component: page(() => import('./pages/pages.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/play/:id/edit',
|
|
||||||
component: page(() => import('./pages/flash/flash-edit.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/play/new',
|
|
||||||
component: page(() => import('./pages/flash/flash-edit.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/play/:id',
|
|
||||||
component: page(() => import('./pages/flash/flash.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/play',
|
|
||||||
component: page(() => import('./pages/flash/flash-index.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/gallery/:postId/edit',
|
|
||||||
component: page(() => import('./pages/gallery/edit.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/gallery/new',
|
|
||||||
component: page(() => import('./pages/gallery/edit.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/gallery/:postId',
|
|
||||||
component: page(() => import('./pages/gallery/post.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/gallery',
|
|
||||||
component: page(() => import('./pages/gallery/index.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/channels/:channelId/edit',
|
|
||||||
component: page(() => import('./pages/channel-editor.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/channels/new',
|
|
||||||
component: page(() => import('./pages/channel-editor.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/channels/:channelId',
|
|
||||||
component: page(() => import('./pages/channel.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/channels',
|
|
||||||
component: page(() => import('./pages/channels.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/custom-emojis-manager',
|
|
||||||
component: page(() => import('./pages/custom-emojis-manager.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/avatar-decorations',
|
|
||||||
name: 'avatarDecorations',
|
|
||||||
component: page(() => import('./pages/avatar-decorations.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/registry/keys/:domain/:path(*)?',
|
|
||||||
component: page(() => import('./pages/registry.keys.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/registry/value/:domain/:path(*)?',
|
|
||||||
component: page(() => import('./pages/registry.value.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/registry',
|
|
||||||
component: page(() => import('./pages/registry.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/install-extentions',
|
|
||||||
component: page(() => import('./pages/install-extentions.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/admin/user/:userId',
|
|
||||||
component: iAmModerator ? page(() => import('./pages/admin-user.vue')) : page(() => import('./pages/not-found.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/admin/file/:fileId',
|
|
||||||
component: iAmModerator ? page(() => import('./pages/admin-file.vue')) : page(() => import('./pages/not-found.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/admin',
|
|
||||||
component: iAmModerator ? page(() => import('./pages/admin/index.vue')) : page(() => import('./pages/not-found.vue')),
|
|
||||||
children: [{
|
|
||||||
path: '/overview',
|
|
||||||
name: 'overview',
|
|
||||||
component: page(() => import('./pages/admin/overview.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/users',
|
|
||||||
name: 'users',
|
|
||||||
component: page(() => import('./pages/admin/users.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/emojis',
|
|
||||||
name: 'emojis',
|
|
||||||
component: page(() => import('./pages/custom-emojis-manager.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/avatar-decorations',
|
|
||||||
name: 'avatarDecorations',
|
|
||||||
component: page(() => import('./pages/avatar-decorations.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/queue',
|
|
||||||
name: 'queue',
|
|
||||||
component: page(() => import('./pages/admin/queue.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/files',
|
|
||||||
name: 'files',
|
|
||||||
component: page(() => import('./pages/admin/files.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/federation',
|
|
||||||
name: 'federation',
|
|
||||||
component: page(() => import('./pages/admin/federation.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/announcements',
|
|
||||||
name: 'announcements',
|
|
||||||
component: page(() => import('./pages/admin/announcements.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/ads',
|
|
||||||
name: 'ads',
|
|
||||||
component: page(() => import('./pages/admin/ads.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/roles/:id/edit',
|
|
||||||
name: 'roles',
|
|
||||||
component: page(() => import('./pages/admin/roles.edit.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/roles/new',
|
|
||||||
name: 'roles',
|
|
||||||
component: page(() => import('./pages/admin/roles.edit.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/roles/:id',
|
|
||||||
name: 'roles',
|
|
||||||
component: page(() => import('./pages/admin/roles.role.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/roles',
|
|
||||||
name: 'roles',
|
|
||||||
component: page(() => import('./pages/admin/roles.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/database',
|
|
||||||
name: 'database',
|
|
||||||
component: page(() => import('./pages/admin/database.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/abuses',
|
|
||||||
name: 'abuses',
|
|
||||||
component: page(() => import('./pages/admin/abuses.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/modlog',
|
|
||||||
name: 'modlog',
|
|
||||||
component: page(() => import('./pages/admin/modlog.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/settings',
|
|
||||||
name: 'settings',
|
|
||||||
component: page(() => import('./pages/admin/settings.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/branding',
|
|
||||||
name: 'branding',
|
|
||||||
component: page(() => import('./pages/admin/branding.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/moderation',
|
|
||||||
name: 'moderation',
|
|
||||||
component: page(() => import('./pages/admin/moderation.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/email-settings',
|
|
||||||
name: 'email-settings',
|
|
||||||
component: page(() => import('./pages/admin/email-settings.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/object-storage',
|
|
||||||
name: 'object-storage',
|
|
||||||
component: page(() => import('./pages/admin/object-storage.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/security',
|
|
||||||
name: 'security',
|
|
||||||
component: page(() => import('./pages/admin/security.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/relays',
|
|
||||||
name: 'relays',
|
|
||||||
component: page(() => import('./pages/admin/relays.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/instance-block',
|
|
||||||
name: 'instance-block',
|
|
||||||
component: page(() => import('./pages/admin/instance-block.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/proxy-account',
|
|
||||||
name: 'proxy-account',
|
|
||||||
component: page(() => import('./pages/admin/proxy-account.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/external-services',
|
|
||||||
name: 'external-services',
|
|
||||||
component: page(() => import('./pages/admin/external-services.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/other-settings',
|
|
||||||
name: 'other-settings',
|
|
||||||
component: page(() => import('./pages/admin/other-settings.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/server-rules',
|
|
||||||
name: 'server-rules',
|
|
||||||
component: page(() => import('./pages/admin/server-rules.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/invites',
|
|
||||||
name: 'invites',
|
|
||||||
component: page(() => import('./pages/admin/invites.vue')),
|
|
||||||
}, {
|
|
||||||
path: '/',
|
|
||||||
component: page(() => import('./pages/_empty_.vue')),
|
|
||||||
}],
|
|
||||||
}, {
|
|
||||||
path: '/my/notifications',
|
|
||||||
component: page(() => import('./pages/notifications.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/favorites',
|
|
||||||
component: page(() => import('./pages/favorites.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/achievements',
|
|
||||||
component: page(() => import('./pages/achievements.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/drive/folder/:folder',
|
|
||||||
component: page(() => import('./pages/drive.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/drive',
|
|
||||||
component: page(() => import('./pages/drive.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/drive/file/:fileId',
|
|
||||||
component: page(() => import('./pages/drive.file.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/follow-requests',
|
|
||||||
component: page(() => import('./pages/follow-requests.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/lists/:listId',
|
|
||||||
component: page(() => import('./pages/my-lists/list.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/lists',
|
|
||||||
component: page(() => import('./pages/my-lists/index.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/clips',
|
|
||||||
component: page(() => import('./pages/my-clips/index.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/antennas/create',
|
|
||||||
component: page(() => import('./pages/my-antennas/create.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/antennas/:antennaId',
|
|
||||||
component: page(() => import('./pages/my-antennas/edit.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/my/antennas',
|
|
||||||
component: page(() => import('./pages/my-antennas/index.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/timeline/list/:listId',
|
|
||||||
component: page(() => import('./pages/user-list-timeline.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/timeline/antenna/:antennaId',
|
|
||||||
component: page(() => import('./pages/antenna-timeline.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/clicker',
|
|
||||||
component: page(() => import('./pages/clicker.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/bubble-game',
|
|
||||||
component: page(() => import('./pages/drop-and-fusion.vue')),
|
|
||||||
loginRequired: true,
|
|
||||||
}, {
|
|
||||||
path: '/timeline',
|
|
||||||
component: page(() => import('./pages/timeline.vue')),
|
|
||||||
}, {
|
|
||||||
name: 'index',
|
|
||||||
path: '/',
|
|
||||||
component: $i ? page(() => import('./pages/timeline.vue')) : page(() => import('./pages/welcome.vue')),
|
|
||||||
globalCacheKey: 'index',
|
|
||||||
}, {
|
|
||||||
path: '/:(*)',
|
|
||||||
component: page(() => import('./pages/not-found.vue')),
|
|
||||||
}];
|
|
||||||
|
|
||||||
export const mainRouter = new Router(routes, location.pathname + location.search + location.hash, !!$i, page(() => import('@/pages/not-found.vue')));
|
|
||||||
|
|
||||||
window.history.replaceState({ key: mainRouter.getCurrentKey() }, '', location.href);
|
|
||||||
|
|
||||||
mainRouter.addListener('push', ctx => {
|
|
||||||
window.history.pushState({ key: ctx.key }, '', ctx.path);
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('popstate', (event) => {
|
|
||||||
mainRouter.replace(location.pathname + location.search + location.hash, event.state?.key);
|
|
||||||
});
|
|
||||||
|
|
||||||
export function useRouter(): Router {
|
|
||||||
return inject<Router | null>('router', null) ?? mainRouter;
|
|
||||||
}
|
|
|
@ -13,11 +13,11 @@ import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { defaultStore, userActions } from '@/store.js';
|
import { defaultStore, userActions } from '@/store.js';
|
||||||
import { $i, iAmModerator } from '@/account.js';
|
import { $i, iAmModerator } from '@/account.js';
|
||||||
import { mainRouter } from '@/router.js';
|
import { IRouter } from '@/nirax.js';
|
||||||
import { Router } from '@/nirax.js';
|
|
||||||
import { antennasCache, rolesCache, userListsCache } from '@/cache.js';
|
import { antennasCache, rolesCache, userListsCache } from '@/cache.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router = mainRouter) {
|
export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter = mainRouter) {
|
||||||
const meId = $i ? $i.id : null;
|
const meId = $i ? $i.id : null;
|
||||||
|
|
||||||
const cleanups = [] as (() => void)[];
|
const cleanups = [] as (() => void)[];
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { Router } from '@/nirax.js';
|
import { Router } from '@/nirax.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
export async function lookup(router?: Router) {
|
export async function lookup(router?: Router) {
|
||||||
const _router = router ?? mainRouter;
|
const _router = router ?? mainRouter;
|
||||||
|
|
|
@ -7,8 +7,8 @@ import { post } from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { $i, login } from '@/account.js';
|
import { $i, login } from '@/account.js';
|
||||||
import { getAccountFromId } from '@/scripts/get-account-from-id.js';
|
import { getAccountFromId } from '@/scripts/get-account-from-id.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { deepClone } from '@/scripts/clone.js';
|
import { deepClone } from '@/scripts/clone.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
export function swInject() {
|
export function swInject() {
|
||||||
navigator.serviceWorker.addEventListener('message', async ev => {
|
navigator.serviceWorker.addEventListener('message', async ev => {
|
||||||
|
|
|
@ -52,11 +52,11 @@ import XCommon from './_common_/common.vue';
|
||||||
import { instanceName } from '@/config.js';
|
import { instanceName } from '@/config.js';
|
||||||
import { StickySidebar } from '@/scripts/sticky-sidebar.js';
|
import { StickySidebar } from '@/scripts/sticky-sidebar.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
const XHeaderMenu = defineAsyncComponent(() => import('./classic.header.vue'));
|
const XHeaderMenu = defineAsyncComponent(() => import('./classic.header.vue'));
|
||||||
const XWidgets = defineAsyncComponent(() => import('./universal.widgets.vue'));
|
const XWidgets = defineAsyncComponent(() => import('./universal.widgets.vue'));
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,6 @@ import * as os from '@/os.js';
|
||||||
import { navbarItemDef } from '@/navbar.js';
|
import { navbarItemDef } from '@/navbar.js';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { unisonReload } from '@/scripts/unison-reload.js';
|
import { unisonReload } from '@/scripts/unison-reload.js';
|
||||||
import { deviceKind } from '@/scripts/device-kind.js';
|
import { deviceKind } from '@/scripts/device-kind.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
@ -117,6 +116,7 @@ import XWidgetsColumn from '@/ui/deck/widgets-column.vue';
|
||||||
import XMentionsColumn from '@/ui/deck/mentions-column.vue';
|
import XMentionsColumn from '@/ui/deck/mentions-column.vue';
|
||||||
import XDirectColumn from '@/ui/deck/direct-column.vue';
|
import XDirectColumn from '@/ui/deck/direct-column.vue';
|
||||||
import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue';
|
import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
|
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
|
||||||
const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue'));
|
const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue'));
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ import XColumn from './column.vue';
|
||||||
import { deckStore, Column } from '@/ui/deck/deck-store.js';
|
import { deckStore, Column } from '@/ui/deck/deck-store.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
import { useScrollPositionManager } from '@/nirax.js';
|
import { useScrollPositionManager } from '@/nirax.js';
|
||||||
import { getScrollContainer } from '@/scripts/scroll.js';
|
import { getScrollContainer } from '@/scripts/scroll.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
column: Column;
|
column: Column;
|
||||||
|
|
|
@ -16,9 +16,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { provide, ComputedRef, ref } from 'vue';
|
import { provide, ComputedRef, ref } from 'vue';
|
||||||
import XCommon from './_common_/common.vue';
|
import XCommon from './_common_/common.vue';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
import { instanceName } from '@/config.js';
|
import { instanceName } from '@/config.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
const pageMetadata = ref<null | ComputedRef<PageMetadata>>();
|
const pageMetadata = ref<null | ComputedRef<PageMetadata>>();
|
||||||
|
|
||||||
|
|
|
@ -105,12 +105,12 @@ import { defaultStore } from '@/store.js';
|
||||||
import { navbarItemDef } from '@/navbar.js';
|
import { navbarItemDef } from '@/navbar.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
import { deviceKind } from '@/scripts/device-kind.js';
|
import { deviceKind } from '@/scripts/device-kind.js';
|
||||||
import { miLocalStorage } from '@/local-storage.js';
|
import { miLocalStorage } from '@/local-storage.js';
|
||||||
import { CURRENT_STICKY_BOTTOM } from '@/const.js';
|
import { CURRENT_STICKY_BOTTOM } from '@/const.js';
|
||||||
import { useScrollPositionManager } from '@/nirax.js';
|
import { useScrollPositionManager } from '@/nirax.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
const XWidgets = defineAsyncComponent(() => import('./universal.widgets.vue'));
|
const XWidgets = defineAsyncComponent(() => import('./universal.widgets.vue'));
|
||||||
const XSidebar = defineAsyncComponent(() => import('@/ui/_common_/navbar.vue'));
|
const XSidebar = defineAsyncComponent(() => import('@/ui/_common_/navbar.vue'));
|
||||||
|
|
|
@ -79,10 +79,10 @@ import { instance } from '@/instance.js';
|
||||||
import XSigninDialog from '@/components/MkSigninDialog.vue';
|
import XSigninDialog from '@/components/MkSigninDialog.vue';
|
||||||
import XSignupDialog from '@/components/MkSignupDialog.vue';
|
import XSignupDialog from '@/components/MkSignupDialog.vue';
|
||||||
import { ColdDeviceStorage, defaultStore } from '@/store.js';
|
import { ColdDeviceStorage, defaultStore } from '@/store.js';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkVisitorDashboard from '@/components/MkVisitorDashboard.vue';
|
import MkVisitorDashboard from '@/components/MkVisitorDashboard.vue';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
const DESKTOP_THRESHOLD = 1100;
|
const DESKTOP_THRESHOLD = 1100;
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { provide, ComputedRef, ref } from 'vue';
|
import { provide, ComputedRef, ref } from 'vue';
|
||||||
import XCommon from './_common_/common.vue';
|
import XCommon from './_common_/common.vue';
|
||||||
import { mainRouter } from '@/router.js';
|
|
||||||
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata.js';
|
||||||
import { instanceName, ui } from '@/config.js';
|
import { instanceName, ui } from '@/config.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
import { mainRouter } from '@/global/router/main.js';
|
||||||
|
|
||||||
const pageMetadata = ref<null | ComputedRef<PageMetadata>>();
|
const pageMetadata = ref<null | ComputedRef<PageMetadata>>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue