diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts deleted file mode 100644 index c90d4da5ec..0000000000 --- a/packages/frontend/src/account.ts +++ /dev/null @@ -1,390 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { defineAsyncComponent, reactive, ref } from 'vue'; -import * as Misskey from 'misskey-js'; -import { apiUrl } from '@@/js/config.js'; -import type { MenuItem, MenuButton } from '@/types/menu.js'; -import { defaultMemoryStorage } from '@/memory-storage'; -import { showSuspendedDialog } from '@/utility/show-suspended-dialog.js'; -import { i18n } from '@/i18n.js'; -import { miLocalStorage } from '@/local-storage.js'; -import { del, get, set } from '@/utility/idb-proxy.js'; -import { waiting, popup, popupMenu, success, alert } from '@/os.js'; -import { misskeyApi } from '@/utility/misskey-api.js'; -import { unisonReload, reloadChannel } from '@/utility/unison-reload.js'; - -// TODO: 他のタブと永続化されたstateを同期 -// TODO: accountsはpreferences管理にする(tokenは別管理) - -type Account = Misskey.entities.MeDetailed & { token: string }; - -const accountData = miLocalStorage.getItem('account'); - -// TODO: 外部からはreadonlyに -export const $i = accountData ? reactive(JSON.parse(accountData) as Account) : null; - -export const iAmModerator = $i != null && ($i.isAdmin === true || $i.isModerator === true); -export const iAmAdmin = $i != null && $i.isAdmin; - -export function signinRequired() { - if ($i == null) throw new Error('signin required'); - return $i; -} - -export let notesCount = $i == null ? 0 : $i.notesCount; -export function incNotesCount() { - notesCount++; -} - -export async function signout() { - if (!$i) return; - - defaultMemoryStorage.clear(); - - waiting(); - document.cookie.split(';').forEach((cookie) => { - const cookieName = cookie.split('=')[0].trim(); - if (cookieName === 'token') { - document.cookie = `${cookieName}=; max-age=0; path=/`; - } - }); - miLocalStorage.removeItem('account'); - await removeAccount($i.id); - const accounts = await getAccounts(); - - //#region Remove service worker registration - try { - if (navigator.serviceWorker.controller) { - const registration = await navigator.serviceWorker.ready; - const push = await registration.pushManager.getSubscription(); - if (push) { - await window.fetch(`${apiUrl}/sw/unregister`, { - method: 'POST', - body: JSON.stringify({ - i: $i.token, - endpoint: push.endpoint, - }), - headers: { - 'Content-Type': 'application/json', - }, - }); - } - } - - if (accounts.length === 0) { - await navigator.serviceWorker.getRegistrations() - .then(registrations => { - return Promise.all(registrations.map(registration => registration.unregister())); - }); - } - } catch (err) {} - //#endregion - - if (accounts.length > 0) login(accounts[0].token); - else unisonReload('/'); -} - -export async function getAccounts(): Promise<{ id: Account['id'], token: Account['token'] }[]> { - return (await get('accounts')) || []; -} - -export async function addAccount(id: Account['id'], token: Account['token']) { - const accounts = await getAccounts(); - if (!accounts.some(x => x.id === id)) { - await set('accounts', accounts.concat([{ id, token }])); - } -} - -export async function removeAccount(idOrToken: Account['id']) { - const accounts = await getAccounts(); - const i = accounts.findIndex(x => x.id === idOrToken || x.token === idOrToken); - if (i !== -1) accounts.splice(i, 1); - - if (accounts.length > 0) { - await set('accounts', accounts); - } else { - await del('accounts'); - } -} - -function fetchAccount(token: string, id?: string, forceShowDialog?: boolean): Promise<Account> { - document.cookie = 'token=; path=/; max-age=0'; - document.cookie = `token=${token}; path=/queue; max-age=86400; SameSite=Strict; Secure`; // bull dashboardの認証とかで使う - - return new Promise((done, fail) => { - window.fetch(`${apiUrl}/i`, { - method: 'POST', - body: JSON.stringify({ - i: token, - }), - headers: { - 'Content-Type': 'application/json', - }, - }) - .then(res => new Promise<Account | { error: Record<string, any> }>((done2, fail2) => { - if (res.status >= 500 && res.status < 600) { - // サーバーエラー(5xx)の場合をrejectとする - // (認証エラーなど4xxはresolve) - return fail2(res); - } - res.json().then(done2, fail2); - })) - .then(async res => { - if ('error' in res) { - if (res.error.id === 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370') { - // SUSPENDED - if (forceShowDialog || $i && (token === $i.token || id === $i.id)) { - await showSuspendedDialog(); - } - } else if (res.error.id === 'e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a') { - // USER_IS_DELETED - // アカウントが削除されている - if (forceShowDialog || $i && (token === $i.token || id === $i.id)) { - await alert({ - type: 'error', - title: i18n.ts.accountDeleted, - text: i18n.ts.accountDeletedDescription, - }); - } - } else if (res.error.id === 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14') { - // AUTHENTICATION_FAILED - // トークンが無効化されていたりアカウントが削除されたりしている - if (forceShowDialog || $i && (token === $i.token || id === $i.id)) { - await alert({ - type: 'error', - title: i18n.ts.tokenRevoked, - text: i18n.ts.tokenRevokedDescription, - }); - } - } else { - await alert({ - type: 'error', - title: i18n.ts.failedToFetchAccountInformation, - text: JSON.stringify(res.error), - }); - } - - // rejectかつ理由がtrueの場合、削除対象であることを示す - fail(true); - } else { - (res as Account).token = token; - done(res as Account); - } - }) - .catch(fail); - }); -} - -export function updateAccount(accountData: Account) { - if (!$i) return; - for (const key of Object.keys($i)) { - delete $i[key]; - } - for (const [key, value] of Object.entries(accountData)) { - $i[key] = value; - } - miLocalStorage.setItem('account', JSON.stringify($i)); -} - -export function updateAccountPartial(accountData: Partial<Account>) { - if (!$i) return; - for (const [key, value] of Object.entries(accountData)) { - $i[key] = value; - } - miLocalStorage.setItem('account', JSON.stringify($i)); -} - -export async function refreshAccount() { - if (!$i) return; - return fetchAccount($i.token, $i.id) - .then(updateAccount, reason => { - if (reason === true) return signout(); - return; - }); -} - -export async function login(token: Account['token'], redirect?: string) { - const showing = ref(true); - const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), { - success: false, - showing: showing, - }, { - closed: () => dispose(), - }); - if (_DEV_) console.log('logging as token ', token); - const me = await fetchAccount(token, undefined, true) - .catch(reason => { - if (reason === true) { - // 削除対象の場合 - removeAccount(token); - } - - showing.value = false; - throw reason; - }); - miLocalStorage.setItem('account', JSON.stringify(me)); - await addAccount(me.id, token); - - if (redirect) { - // 他のタブは再読み込みするだけ - reloadChannel.postMessage(null); - // このページはredirectで指定された先に移動 - location.href = redirect; - return; - } - - unisonReload(); -} - -export async function openAccountMenu(opts: { - includeCurrentAccount?: boolean; - withExtraOperation: boolean; - active?: Misskey.entities.UserDetailed['id']; - onChoose?: (account: Misskey.entities.UserDetailed) => void; -}, ev: MouseEvent) { - if (!$i) return; - - async function switchAccount(account: Misskey.entities.UserDetailed) { - const storedAccounts = await getAccounts(); - const found = storedAccounts.find(x => x.id === account.id); - if (found == null) return; - switchAccountWithToken(found.token); - } - - function switchAccountWithToken(token: string) { - login(token); - } - - const storedAccounts = await getAccounts().then(accounts => accounts.filter(x => x.id !== $i.id)); - const accountsPromise = misskeyApi('users/show', { userIds: storedAccounts.map(x => x.id) }); - - function createItem(account: Misskey.entities.UserDetailed) { - return { - type: 'user' as const, - user: account, - active: opts.active != null ? opts.active === account.id : false, - action: () => { - if (opts.onChoose) { - opts.onChoose(account); - } else { - switchAccount(account); - } - }, - }; - } - - const accountItemPromises = storedAccounts.map(a => new Promise<ReturnType<typeof createItem> | MenuButton>(res => { - accountsPromise.then(accounts => { - const account = accounts.find(x => x.id === a.id); - if (account == null) return res({ - type: 'button' as const, - text: a.id, - action: () => { - switchAccountWithToken(a.token); - }, - }); - - res(createItem(account)); - }); - })); - - const menuItems: MenuItem[] = []; - - if (opts.withExtraOperation) { - menuItems.push({ - type: 'link', - text: i18n.ts.profile, - to: `/@${$i.username}`, - avatar: $i, - }, { - type: 'divider', - }); - - if (opts.includeCurrentAccount) { - menuItems.push(createItem($i)); - } - - menuItems.push(...accountItemPromises); - - menuItems.push({ - type: 'parent', - icon: 'ti ti-plus', - text: i18n.ts.addAccount, - children: [{ - text: i18n.ts.existingAccount, - action: () => { - getAccountWithSigninDialog().then(res => { - if (res != null) { - success(); - } - }); - }, - }, { - text: i18n.ts.createAccount, - action: () => { - getAccountWithSignupDialog().then(res => { - if (res != null) { - switchAccountWithToken(res.token); - } - }); - }, - }], - }, { - type: 'link', - icon: 'ti ti-users', - text: i18n.ts.manageAccounts, - to: '/settings/accounts', - }); - } else { - if (opts.includeCurrentAccount) { - menuItems.push(createItem($i)); - } - - menuItems.push(...accountItemPromises); - } - - popupMenu(menuItems, ev.currentTarget ?? ev.target, { - align: 'left', - }); -} - -export function getAccountWithSigninDialog(): Promise<{ id: string, token: string } | null> { - return new Promise((resolve) => { - const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { - done: async (res: Misskey.entities.SigninFlowResponse & { finished: true }) => { - await addAccount(res.id, res.i); - resolve({ id: res.id, token: res.i }); - }, - cancelled: () => { - resolve(null); - }, - closed: () => { - dispose(); - }, - }); - }); -} - -export function getAccountWithSignupDialog(): Promise<{ id: string, token: string } | null> { - return new Promise((resolve) => { - const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, { - done: async (res: Misskey.entities.SignupResponse) => { - await addAccount(res.id, res.token); - resolve({ id: res.id, token: res.token }); - }, - cancelled: () => { - resolve(null); - }, - closed: () => { - dispose(); - }, - }); - }); -} - -if (_DEV_) { - (window as any).$i = $i; -} diff --git a/packages/frontend/src/accounts.ts b/packages/frontend/src/accounts.ts new file mode 100644 index 0000000000..2382a8ec32 --- /dev/null +++ b/packages/frontend/src/accounts.ts @@ -0,0 +1,341 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineAsyncComponent, ref } from 'vue'; +import * as Misskey from 'misskey-js'; +import { apiUrl, host } from '@@/js/config.js'; +import type { MenuItem } from '@/types/menu.js'; +import { showSuspendedDialog } from '@/utility/show-suspended-dialog.js'; +import { i18n } from '@/i18n.js'; +import { miLocalStorage } from '@/local-storage.js'; +import { waiting, popup, popupMenu, success, alert } from '@/os.js'; +import { unisonReload, reloadChannel } from '@/utility/unison-reload.js'; +import { prefer } from '@/preferences.js'; +import { store } from '@/store.js'; +import { $i } from '@/i.js'; +import { signout } from '@/signout.js'; + +// TODO: 他のタブと永続化されたstateを同期 + +type AccountWithToken = Misskey.entities.MeDetailed & { token: string }; + +export async function getAccounts(): Promise<{ + host: string; + user: Misskey.entities.User; + token: string | null; +}[]> { + const tokens = store.s.accountTokens; + const accounts = prefer.s.accounts; + return accounts.map(([host, user]) => ({ + host, + user, + token: tokens[host + '/' + user.id] ?? null, + })); +} + +async function addAccount(host: string, user: Misskey.entities.User, token: AccountWithToken['token']) { + if (!prefer.s.accounts.some(x => x[0] === host && x[1].id === user.id)) { + store.set('accountTokens', { ...store.s.accountTokens, [host + '/' + user.id]: token }); + prefer.commit('accounts', [...prefer.s.accounts, [host, user]]); + } +} + +export async function removeAccount(host: string, id: AccountWithToken['id']) { + const tokens = JSON.parse(JSON.stringify(store.s.accountTokens)); + delete tokens[host + '/' + id]; + store.set('accountTokens', tokens); + prefer.commit('accounts', prefer.s.accounts.filter(x => x[0] !== host || x[1].id !== id)); +} + +const isAccountDeleted = Symbol('isAccountDeleted'); + +function fetchAccount(token: string, id?: string, forceShowDialog?: boolean): Promise<Misskey.entities.MeDetailed> { + return new Promise((done, fail) => { + window.fetch(`${apiUrl}/i`, { + method: 'POST', + body: JSON.stringify({ + i: token, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(res => new Promise<Misskey.entities.MeDetailed | { error: Record<string, any> }>((done2, fail2) => { + if (res.status >= 500 && res.status < 600) { + // サーバーエラー(5xx)の場合をrejectとする + // (認証エラーなど4xxはresolve) + return fail2(res); + } + res.json().then(done2, fail2); + })) + .then(async res => { + if ('error' in res) { + if (res.error.id === 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370') { + // SUSPENDED + if (forceShowDialog || $i && (token === $i.token || id === $i.id)) { + await showSuspendedDialog(); + } + } else if (res.error.id === 'e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a') { + // USER_IS_DELETED + // アカウントが削除されている + if (forceShowDialog || $i && (token === $i.token || id === $i.id)) { + await alert({ + type: 'error', + title: i18n.ts.accountDeleted, + text: i18n.ts.accountDeletedDescription, + }); + } + } else if (res.error.id === 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14') { + // AUTHENTICATION_FAILED + // トークンが無効化されていたりアカウントが削除されたりしている + if (forceShowDialog || $i && (token === $i.token || id === $i.id)) { + await alert({ + type: 'error', + title: i18n.ts.tokenRevoked, + text: i18n.ts.tokenRevokedDescription, + }); + } + } else { + await alert({ + type: 'error', + title: i18n.ts.failedToFetchAccountInformation, + text: JSON.stringify(res.error), + }); + } + + fail(isAccountDeleted); + } else { + done(res); + } + }) + .catch(fail); + }); +} + +export function updateCurrentAccount(accountData: Misskey.entities.MeDetailed) { + if (!$i) return; + const token = $i.token; + for (const key of Object.keys($i)) { + delete $i[key]; + } + for (const [key, value] of Object.entries(accountData)) { + $i[key] = value; + } + prefer.commit('accounts', prefer.s.accounts.map(([host, user]) => { + // TODO: $iのホストも比較したいけど通常null + if (user.id === $i.id) { + return [host, $i]; + } else { + return [host, user]; + } + })); + $i.token = token; + miLocalStorage.setItem('account', JSON.stringify($i)); +} + +export function updateCurrentAccountPartial(accountData: Partial<Misskey.entities.MeDetailed>) { + if (!$i) return; + for (const [key, value] of Object.entries(accountData)) { + $i[key] = value; + } + prefer.commit('accounts', prefer.s.accounts.map(([host, user]) => { + // TODO: $iのホストも比較したいけど通常null + if (user.id === $i.id) { + const newUser = JSON.parse(JSON.stringify($i)); + for (const [key, value] of Object.entries(accountData)) { + newUser[key] = value; + } + return [host, newUser]; + } + return [host, user]; + })); + miLocalStorage.setItem('account', JSON.stringify($i)); +} + +export async function refreshCurrentAccount() { + if (!$i) return; + return fetchAccount($i.token, $i.id).then(updateCurrentAccount).catch(reason => { + if (reason === isAccountDeleted) { + removeAccount(host, $i.id); + if (Object.keys(store.s.accountTokens).length > 0) { + login(Object.values(store.s.accountTokens)[0]); + } else { + signout(); + } + } + }); +} + +export async function login(token: AccountWithToken['token'], redirect?: string) { + const showing = ref(true); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), { + success: false, + showing: showing, + }, { + closed: () => dispose(), + }); + + const me = await fetchAccount(token, undefined, true).catch(reason => { + showing.value = false; + throw reason; + }); + + miLocalStorage.setItem('account', JSON.stringify({ + ...me, + token, + })); + + await addAccount(host, me, token); + + if (redirect) { + // 他のタブは再読み込みするだけ + reloadChannel.postMessage(null); + // このページはredirectで指定された先に移動 + location.href = redirect; + return; + } + + unisonReload(); +} + +export async function switchAccount(host: string, id: string) { + const token = store.s.accountTokens[host + '/' + id]; + if (token) { + login(token); + } else { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { + done: async (res: Misskey.entities.SigninFlowResponse & { finished: true }) => { + store.set('accountTokens', { ...store.s.accountTokens, [host + '/' + res.id]: res.i }); + login(res.i); + }, + closed: () => { + dispose(); + }, + }); + } +} + +export async function openAccountMenu(opts: { + includeCurrentAccount?: boolean; + withExtraOperation: boolean; + active?: Misskey.entities.User['id']; + onChoose?: (account: Misskey.entities.User) => void; +}, ev: MouseEvent) { + if (!$i) return; + + function createItem(host: string, account: Misskey.entities.User): MenuItem { + return { + type: 'user' as const, + user: account, + active: opts.active != null ? opts.active === account.id : false, + action: async () => { + if (opts.onChoose) { + opts.onChoose(account); + } else { + switchAccount(host, account.id); + } + }, + }; + } + + const menuItems: MenuItem[] = []; + + // TODO: $iのホストも比較したいけど通常null + const accountItems = (await getAccounts().then(accounts => accounts.filter(x => x.user.id !== $i.id))).map(a => createItem(a.host, a.user)); + + if (opts.withExtraOperation) { + menuItems.push({ + type: 'link', + text: i18n.ts.profile, + to: `/@${$i.username}`, + avatar: $i, + }, { + type: 'divider', + }); + + if (opts.includeCurrentAccount) { + menuItems.push(createItem(host, $i)); + } + + menuItems.push(...accountItems); + + menuItems.push({ + type: 'parent', + icon: 'ti ti-plus', + text: i18n.ts.addAccount, + children: [{ + text: i18n.ts.existingAccount, + action: () => { + getAccountWithSigninDialog().then(res => { + if (res != null) { + success(); + } + }); + }, + }, { + text: i18n.ts.createAccount, + action: () => { + getAccountWithSignupDialog().then(res => { + if (res != null) { + switchAccount(host, res.id); + } + }); + }, + }], + }, { + type: 'link', + icon: 'ti ti-users', + text: i18n.ts.manageAccounts, + to: '/settings/accounts', + }); + } else { + if (opts.includeCurrentAccount) { + menuItems.push(createItem(host, $i)); + } + + menuItems.push(...accountItems); + } + + popupMenu(menuItems, ev.currentTarget ?? ev.target, { + align: 'left', + }); +} + +export function getAccountWithSigninDialog(): Promise<{ id: string, token: string } | null> { + return new Promise((resolve) => { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { + done: async (res: Misskey.entities.SigninFlowResponse & { finished: true }) => { + const user = await fetchAccount(res.i, res.id, true); + await addAccount(host, user, res.i); + resolve({ id: res.id, token: res.i }); + }, + cancelled: () => { + resolve(null); + }, + closed: () => { + dispose(); + }, + }); + }); +} + +export function getAccountWithSignupDialog(): Promise<{ id: string, token: string } | null> { + return new Promise((resolve) => { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, { + done: async (res: Misskey.entities.SignupResponse) => { + const user = JSON.parse(JSON.stringify(res)); + delete user.token; + await addAccount(host, user, res.token); + resolve({ id: res.id, token: res.token }); + }, + cancelled: () => { + resolve(null); + }, + closed: () => { + dispose(); + }, + }); + }); +} diff --git a/packages/frontend/src/aiscript/api.ts b/packages/frontend/src/aiscript/api.ts index 3acc1127c9..e7e396023d 100644 --- a/packages/frontend/src/aiscript/api.ts +++ b/packages/frontend/src/aiscript/api.ts @@ -9,7 +9,7 @@ import { url, lang } from '@@/js/config.js'; import { assertStringAndIsIn } from './common.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { miLocalStorage } from '@/local-storage.js'; import { customEmojis } from '@/custom-emojis.js'; diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index 122aa50ac0..73c4256c4b 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -15,7 +15,7 @@ import components from '@/components/index.js'; import { applyTheme } from '@/theme.js'; import { isDeviceDarkmode } from '@/utility/is-device-darkmode.js'; import { updateI18n, i18n } from '@/i18n.js'; -import { $i, refreshAccount, login } from '@/account.js'; +import { refreshCurrentAccount, login } from '@/accounts.js'; import { store } from '@/store.js'; import { fetchInstance, instance } from '@/instance.js'; import { deviceKind, updateDeviceKind } from '@/utility/device-kind.js'; @@ -29,6 +29,7 @@ import { fetchCustomEmojis } from '@/custom-emojis.js'; import { setupRouter } from '@/router/main.js'; import { createMainRouter } from '@/router/definition.js'; import { prefer } from '@/preferences.js'; +import { $i } from '@/i.js'; export async function common(createVue: () => App<Element>) { console.info(`Misskey v${version}`); @@ -38,11 +39,6 @@ export async function common(createVue: () => App<Element>) { console.info(`vue ${vueVersion}`); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (window as any).$i = $i; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (window as any).$store = store; - window.addEventListener('error', event => { console.error(event); /* @@ -244,7 +240,7 @@ export async function common(createVue: () => App<Element>) { console.log('account cache found. refreshing...'); } - refreshAccount(); + refreshCurrentAccount(); } //#endregion diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index be72eeb9e1..64e3a236e8 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -16,7 +16,7 @@ import { i18n } from '@/i18n.js'; import { alert, confirm, popup, post, toast } from '@/os.js'; import { useStream } from '@/stream.js'; import * as sound from '@/utility/sound.js'; -import { $i, signout, updateAccountPartial } from '@/account.js'; +import { $i } from '@/i.js'; import { instance } from '@/instance.js'; import { ColdDeviceStorage, store } from '@/store.js'; import { reactionPicker } from '@/utility/reaction-picker.js'; @@ -32,6 +32,8 @@ import { misskeyApi } from '@/utility/misskey-api.js'; import { deckStore } from '@/ui/deck/deck-store.js'; import { launchPlugins } from '@/plugin.js'; import { unisonReload } from '@/utility/unison-reload.js'; +import { updateCurrentAccountPartial } from '@/accounts.js'; +import { signout } from '@/signout.js'; export async function mainBoot() { const { isClientUpdated, lastVersion } = await common(() => { @@ -480,11 +482,11 @@ export async function mainBoot() { // 自分の情報が更新されたとき main.on('meUpdated', i => { - updateAccountPartial(i); + updateCurrentAccountPartial(i); }); main.on('readAllNotifications', () => { - updateAccountPartial({ + updateCurrentAccountPartial({ hasUnreadNotification: false, unreadNotificationsCount: 0, }); @@ -492,39 +494,39 @@ export async function mainBoot() { main.on('unreadNotification', () => { const unreadNotificationsCount = ($i?.unreadNotificationsCount ?? 0) + 1; - updateAccountPartial({ + updateCurrentAccountPartial({ hasUnreadNotification: true, unreadNotificationsCount, }); }); main.on('unreadMention', () => { - updateAccountPartial({ hasUnreadMentions: true }); + updateCurrentAccountPartial({ hasUnreadMentions: true }); }); main.on('readAllUnreadMentions', () => { - updateAccountPartial({ hasUnreadMentions: false }); + updateCurrentAccountPartial({ hasUnreadMentions: false }); }); main.on('unreadSpecifiedNote', () => { - updateAccountPartial({ hasUnreadSpecifiedNotes: true }); + updateCurrentAccountPartial({ hasUnreadSpecifiedNotes: true }); }); main.on('readAllUnreadSpecifiedNotes', () => { - updateAccountPartial({ hasUnreadSpecifiedNotes: false }); + updateCurrentAccountPartial({ hasUnreadSpecifiedNotes: false }); }); main.on('readAllAntennas', () => { - updateAccountPartial({ hasUnreadAntenna: false }); + updateCurrentAccountPartial({ hasUnreadAntenna: false }); }); main.on('unreadAntenna', () => { - updateAccountPartial({ hasUnreadAntenna: true }); + updateCurrentAccountPartial({ hasUnreadAntenna: true }); sound.playMisskeySfx('antenna'); }); main.on('readAllAnnouncements', () => { - updateAccountPartial({ hasUnreadAnnouncement: false }); + updateCurrentAccountPartial({ hasUnreadAnnouncement: false }); }); // 個人宛てお知らせが発行されたとき diff --git a/packages/frontend/src/components/MkAnnouncementDialog.vue b/packages/frontend/src/components/MkAnnouncementDialog.vue index 41fd2564d8..582bb137bc 100644 --- a/packages/frontend/src/components/MkAnnouncementDialog.vue +++ b/packages/frontend/src/components/MkAnnouncementDialog.vue @@ -29,7 +29,8 @@ import { misskeyApi } from '@/utility/misskey-api.js'; import MkModal from '@/components/MkModal.vue'; import MkButton from '@/components/MkButton.vue'; import { i18n } from '@/i18n.js'; -import { $i, updateAccountPartial } from '@/account.js'; +import { $i } from '@/i.js'; +import { updateCurrentAccountPartial } from '@/accounts.js'; const props = withDefaults(defineProps<{ announcement: Misskey.entities.Announcement; @@ -51,7 +52,7 @@ async function ok() { modal.value?.close(); misskeyApi('i/read-announcement', { announcementId: props.announcement.id }); - updateAccountPartial({ + updateCurrentAccountPartial({ unreadAnnouncements: $i!.unreadAnnouncements.filter(a => a.id !== props.announcement.id), }); } diff --git a/packages/frontend/src/components/MkAuthConfirm.vue b/packages/frontend/src/components/MkAuthConfirm.vue index 090c31044e..00bf8e68d9 100644 --- a/packages/frontend/src/components/MkAuthConfirm.vue +++ b/packages/frontend/src/components/MkAuthConfirm.vue @@ -117,10 +117,9 @@ SPDX-License-Identifier: AGPL-3.0-only <script setup lang="ts"> import { ref, computed } from 'vue'; import * as Misskey from 'misskey-js'; - import MkButton from '@/components/MkButton.vue'; - -import { $i, getAccounts, getAccountWithSigninDialog, getAccountWithSignupDialog } from '@/account.js'; +import { $i } from '@/i.js'; +import { getAccounts, getAccountWithSigninDialog, getAccountWithSignupDialog } from '@/accounts.js'; import { i18n } from '@/i18n.js'; import * as os from '@/os.js'; import { getProxiedImageUrl } from '@/utility/media-proxy.js'; @@ -158,7 +157,7 @@ async function init() { const accounts = await getAccounts(); - const accountIdsToFetch = accounts.map(a => a.id).filter(id => !users.value.has(id)); + const accountIdsToFetch = accounts.map(a => a.user.id).filter(id => !users.value.has(id)); if (accountIdsToFetch.length > 0) { const usersRes = await misskeyApi('users/show', { @@ -170,7 +169,7 @@ async function init() { users.value.set(user.id, { ...user, - token: accounts.find(a => a.id === user.id)!.token, + token: accounts.find(a => a.user.id === user.id)!.token, }); } } diff --git a/packages/frontend/src/components/MkClipPreview.vue b/packages/frontend/src/components/MkClipPreview.vue index 5b09ec90dd..2154c08ab3 100644 --- a/packages/frontend/src/components/MkClipPreview.vue +++ b/packages/frontend/src/components/MkClipPreview.vue @@ -26,7 +26,7 @@ SPDX-License-Identifier: AGPL-3.0-only import * as Misskey from 'misskey-js'; import { computed } from 'vue'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import number from '@/filters/number.js'; const props = withDefaults(defineProps<{ diff --git a/packages/frontend/src/components/MkCropperDialog.vue b/packages/frontend/src/components/MkCropperDialog.vue index 3c41d597de..4a89fb30ca 100644 --- a/packages/frontend/src/components/MkCropperDialog.vue +++ b/packages/frontend/src/components/MkCropperDialog.vue @@ -38,7 +38,7 @@ import tinycolor from 'tinycolor2'; import { apiUrl } from '@@/js/config.js'; import MkModalWindow from '@/components/MkModalWindow.vue'; import * as os from '@/os.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import { getProxiedImageUrl } from '@/utility/media-proxy.js'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/components/MkDrive.file.vue b/packages/frontend/src/components/MkDrive.file.vue index 733d50728e..f02a767186 100644 --- a/packages/frontend/src/components/MkDrive.file.vue +++ b/packages/frontend/src/components/MkDrive.file.vue @@ -44,7 +44,7 @@ import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue'; import bytes from '@/filters/bytes.js'; import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { getDriveFileMenu } from '@/utility/get-drive-file-menu.js'; import { deviceKind } from '@/utility/device-kind.js'; import { useRouter } from '@/router/supplier.js'; diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 384682277e..c0883b1342 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -136,7 +136,7 @@ import { deviceKind } from '@/utility/device-kind.js'; import { i18n } from '@/i18n.js'; import { store } from '@/store.js'; import { customEmojiCategories, customEmojis, customEmojisMap } from '@/custom-emojis.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { checkReactionPermissions } from '@/utility/check-reaction-permissions.js'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/components/MkFollowButton.vue b/packages/frontend/src/components/MkFollowButton.vue index a063854520..b62494fa20 100644 --- a/packages/frontend/src/components/MkFollowButton.vue +++ b/packages/frontend/src/components/MkFollowButton.vue @@ -44,7 +44,7 @@ import { useStream } from '@/stream.js'; import { i18n } from '@/i18n.js'; import { claimAchievement } from '@/utility/achievements.js'; import { pleaseLogin } from '@/utility/please-login.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { prefer } from '@/preferences.js'; const props = withDefaults(defineProps<{ diff --git a/packages/frontend/src/components/MkInstanceStats.vue b/packages/frontend/src/components/MkInstanceStats.vue index 70777bb89a..3113c6fad6 100644 --- a/packages/frontend/src/components/MkInstanceStats.vue +++ b/packages/frontend/src/components/MkInstanceStats.vue @@ -89,7 +89,7 @@ import { Chart } from 'chart.js'; import MkSelect from '@/components/MkSelect.vue'; import MkChart from '@/components/MkChart.vue'; import { useChartTooltip } from '@/use/use-chart-tooltip.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import * as os from '@/os.js'; import { misskeyApiGet } from '@/utility/misskey-api.js'; import { instance } from '@/instance.js'; diff --git a/packages/frontend/src/components/MkMediaAudio.vue b/packages/frontend/src/components/MkMediaAudio.vue index 33d4d269e7..096c51bbd6 100644 --- a/packages/frontend/src/components/MkMediaAudio.vue +++ b/packages/frontend/src/components/MkMediaAudio.vue @@ -98,7 +98,7 @@ import * as os from '@/os.js'; import bytes from '@/filters/bytes.js'; import { hms } from '@/filters/hms.js'; import MkMediaRange from '@/components/MkMediaRange.vue'; -import { $i, iAmModerator } from '@/account.js'; +import { $i, iAmModerator } from '@/i.js'; import { prefer } from '@/preferences.js'; const props = defineProps<{ diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue index 6029b1e0b6..20ac1a917e 100644 --- a/packages/frontend/src/components/MkMediaImage.vue +++ b/packages/frontend/src/components/MkMediaImage.vue @@ -60,7 +60,7 @@ import bytes from '@/filters/bytes.js'; import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue'; import { i18n } from '@/i18n.js'; import * as os from '@/os.js'; -import { $i, iAmModerator } from '@/account.js'; +import { $i, iAmModerator } from '@/i.js'; import { prefer } from '@/preferences.js'; const props = withDefaults(defineProps<{ diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue index 74c1aefc3a..403ec61736 100644 --- a/packages/frontend/src/components/MkMediaVideo.vue +++ b/packages/frontend/src/components/MkMediaVideo.vue @@ -121,7 +121,7 @@ import * as os from '@/os.js'; import { exitFullscreen, requestFullscreen } from '@/utility/fullscreen.js'; import hasAudio from '@/utility/media-has-audio.js'; import MkMediaRange from '@/components/MkMediaRange.vue'; -import { $i, iAmModerator } from '@/account.js'; +import { $i, iAmModerator } from '@/i.js'; import { prefer } from '@/preferences.js'; const props = defineProps<{ diff --git a/packages/frontend/src/components/MkMention.vue b/packages/frontend/src/components/MkMention.vue index 419407955f..f2cf33eb65 100644 --- a/packages/frontend/src/components/MkMention.vue +++ b/packages/frontend/src/components/MkMention.vue @@ -18,7 +18,7 @@ import { toUnicode } from 'punycode.js'; import { computed } from 'vue'; import { host as localHost } from '@@/js/config.js'; import type { MkABehavior } from '@/components/global/MkA.vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { getStaticImageUrl } from '@/utility/media-proxy.js'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index aa352d5163..a22ad346bf 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -208,7 +208,7 @@ import * as sound from '@/utility/sound.js'; import { misskeyApi, misskeyApiGet } from '@/utility/misskey-api.js'; import { reactionPicker } from '@/utility/reaction-picker.js'; import { extractUrlFromMfm } from '@/utility/extract-url-from-mfm.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import { getAbuseNoteMenu, getCopyNoteLinkMenu, getNoteClipMenu, getNoteMenu, getRenoteMenu } from '@/utility/get-note-menu.js'; import { useNoteCapture } from '@/use/use-note-capture.js'; diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index b3f99b702a..dd8d3567b2 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -238,7 +238,7 @@ import { misskeyApi, misskeyApiGet } from '@/utility/misskey-api.js'; import * as sound from '@/utility/sound.js'; import { reactionPicker } from '@/utility/reaction-picker.js'; import { extractUrlFromMfm } from '@/utility/extract-url-from-mfm.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import { getNoteClipMenu, getNoteMenu, getRenoteMenu } from '@/utility/get-note-menu.js'; import { useNoteCapture } from '@/use/use-note-capture.js'; diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue index bb7347cd26..4fd1c210cb 100644 --- a/packages/frontend/src/components/MkNoteSub.vue +++ b/packages/frontend/src/components/MkNoteSub.vue @@ -48,7 +48,7 @@ import MkCwButton from '@/components/MkCwButton.vue'; import { notePage } from '@/filters/note.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { userPage } from '@/filters/user.js'; import { checkWordMute } from '@/utility/check-word-mute.js'; diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue index 5d096cf92d..b2380a5e0e 100644 --- a/packages/frontend/src/components/MkNotification.vue +++ b/packages/frontend/src/components/MkNotification.vue @@ -169,7 +169,7 @@ import { notePage } from '@/filters/note.js'; import { userPage } from '@/filters/user.js'; import { i18n } from '@/i18n.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { infoImageUrl } from '@/instance.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/components/MkPasswordDialog.vue b/packages/frontend/src/components/MkPasswordDialog.vue index 4d1787d420..24750012d0 100644 --- a/packages/frontend/src/components/MkPasswordDialog.vue +++ b/packages/frontend/src/components/MkPasswordDialog.vue @@ -44,7 +44,7 @@ import MkInput from '@/components/MkInput.vue'; import MkButton from '@/components/MkButton.vue'; import MkModalWindow from '@/components/MkModalWindow.vue'; import { i18n } from '@/i18n.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index 5e379d08b7..c6958eea77 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -127,7 +127,8 @@ import { store } from '@/store.js'; import MkInfo from '@/components/MkInfo.vue'; import { i18n } from '@/i18n.js'; import { instance } from '@/instance.js'; -import { signinRequired, notesCount, incNotesCount, getAccounts, openAccountMenu as openAccountMenu_ } from '@/account.js'; +import { signinRequired, notesCount, incNotesCount } from '@/i.js'; +import { getAccounts, openAccountMenu as openAccountMenu_ } from '@/accounts.js'; import { uploadFile } from '@/utility/upload.js'; import { deepClone } from '@/utility/clone.js'; import MkRippleEffect from '@/components/MkRippleEffect.vue'; @@ -837,7 +838,7 @@ async function post(ev?: MouseEvent) { if (postAccount.value) { const storedAccounts = await getAccounts(); - token = storedAccounts.find(x => x.id === postAccount.value?.id)?.token; + token = storedAccounts.find(x => x.user.id === postAccount.value?.id)?.token; } posting.value = true; diff --git a/packages/frontend/src/components/MkPreview.vue b/packages/frontend/src/components/MkPreview.vue index 6efd99d14b..d8dfbd1655 100644 --- a/packages/frontend/src/components/MkPreview.vue +++ b/packages/frontend/src/components/MkPreview.vue @@ -43,7 +43,7 @@ import MkTextarea from '@/components/MkTextarea.vue'; import MkRadio from '@/components/MkRadio.vue'; import * as os from '@/os.js'; import * as config from '@@/js/config.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; const text = ref(''); const flag = ref(true); diff --git a/packages/frontend/src/components/MkPushNotificationAllowButton.vue b/packages/frontend/src/components/MkPushNotificationAllowButton.vue index 780f8bc6d0..9c37eb5e72 100644 --- a/packages/frontend/src/components/MkPushNotificationAllowButton.vue +++ b/packages/frontend/src/components/MkPushNotificationAllowButton.vue @@ -42,12 +42,13 @@ SPDX-License-Identifier: AGPL-3.0-only <script setup lang="ts"> import { ref } from 'vue'; -import { $i, getAccounts } from '@/account.js'; +import { $i } from '@/i.js'; import MkButton from '@/components/MkButton.vue'; import { instance } from '@/instance.js'; import { apiWithDialog, promiseDialog } from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; +import { getAccounts } from '@/accounts.js'; defineProps<{ primary?: boolean; diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue index d079e68cde..12a066c710 100644 --- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue +++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue @@ -27,7 +27,7 @@ import MkReactionIcon from '@/components/MkReactionIcon.vue'; import * as os from '@/os.js'; import { misskeyApi, misskeyApiGet } from '@/utility/misskey-api.js'; import { useTooltip } from '@/use/use-tooltip.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import MkReactionEffect from '@/components/MkReactionEffect.vue'; import { claimAchievement } from '@/utility/achievements.js'; import { i18n } from '@/i18n.js'; diff --git a/packages/frontend/src/components/MkSignin.vue b/packages/frontend/src/components/MkSignin.vue index 2dcc87f425..b0fbe3c490 100644 --- a/packages/frontend/src/components/MkSignin.vue +++ b/packages/frontend/src/components/MkSignin.vue @@ -67,20 +67,19 @@ SPDX-License-Identifier: AGPL-3.0-only import { nextTick, onBeforeUnmount, ref, shallowRef, useTemplateRef } from 'vue'; import * as Misskey from 'misskey-js'; import { supported as webAuthnSupported, parseRequestOptionsFromJSON } from '@github/webauthn-json/browser-ponyfill'; - import type { AuthenticationPublicKeyCredential } from '@github/webauthn-json/browser-ponyfill'; import type { OpenOnRemoteOptions } from '@/utility/please-login.js'; +import type { PwResponse } from '@/components/MkSignin.password.vue'; import { misskeyApi } from '@/utility/misskey-api.js'; import { showSuspendedDialog } from '@/utility/show-suspended-dialog.js'; -import { login } from '@/account.js'; import { i18n } from '@/i18n.js'; import * as os from '@/os.js'; import XInput from '@/components/MkSignin.input.vue'; import XPassword from '@/components/MkSignin.password.vue'; -import type { PwResponse } from '@/components/MkSignin.password.vue'; import XTotp from '@/components/MkSignin.totp.vue'; import XPasskey from '@/components/MkSignin.passkey.vue'; +import { login } from '@/accounts.js'; const emit = defineEmits<{ (ev: 'login', v: Misskey.entities.SigninFlowResponse & { finished: true }): void; diff --git a/packages/frontend/src/components/MkSignupDialog.form.vue b/packages/frontend/src/components/MkSignupDialog.form.vue index 151cd60fb2..78b6722c1e 100644 --- a/packages/frontend/src/components/MkSignupDialog.form.vue +++ b/packages/frontend/src/components/MkSignupDialog.form.vue @@ -85,13 +85,13 @@ import * as Misskey from 'misskey-js'; import * as config from '@@/js/config.js'; import MkButton from './MkButton.vue'; import MkInput from './MkInput.vue'; -import MkCaptcha from '@/components/MkCaptcha.vue'; import type { Captcha } from '@/components/MkCaptcha.vue'; +import MkCaptcha from '@/components/MkCaptcha.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { login } from '@/account.js'; import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; +import { login } from '@/accounts.js'; const props = withDefaults(defineProps<{ autoSet?: boolean; diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue index 62ae9a048a..e8b740eae2 100644 --- a/packages/frontend/src/components/MkTimeline.vue +++ b/packages/frontend/src/components/MkTimeline.vue @@ -25,7 +25,7 @@ import MkNotes from '@/components/MkNotes.vue'; import MkPullToRefresh from '@/components/MkPullToRefresh.vue'; import { useStream } from '@/stream.js'; import * as sound from '@/utility/sound.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { instance } from '@/instance.js'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/components/MkTokenGenerateWindow.vue b/packages/frontend/src/components/MkTokenGenerateWindow.vue index 31ecb15ab8..bed15031cb 100644 --- a/packages/frontend/src/components/MkTokenGenerateWindow.vue +++ b/packages/frontend/src/components/MkTokenGenerateWindow.vue @@ -55,7 +55,7 @@ import MkButton from './MkButton.vue'; import MkInfo from './MkInfo.vue'; import MkModalWindow from '@/components/MkModalWindow.vue'; import { i18n } from '@/i18n.js'; -import { iAmAdmin } from '@/account.js'; +import { iAmAdmin } from '@/i.js'; const props = withDefaults(defineProps<{ title?: string | null; diff --git a/packages/frontend/src/components/MkTutorialDialog.Note.vue b/packages/frontend/src/components/MkTutorialDialog.Note.vue index b26a01737e..59e1b096ae 100644 --- a/packages/frontend/src/components/MkTutorialDialog.Note.vue +++ b/packages/frontend/src/components/MkTutorialDialog.Note.vue @@ -27,7 +27,7 @@ import * as Misskey from 'misskey-js'; import { ref, reactive } from 'vue'; import { i18n } from '@/i18n.js'; import { globalEvents } from '@/events.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import MkNote from '@/components/MkNote.vue'; const props = defineProps<{ diff --git a/packages/frontend/src/components/MkTutorialDialog.Sensitive.vue b/packages/frontend/src/components/MkTutorialDialog.Sensitive.vue index f7b60fbc45..8ae6c1ceaa 100644 --- a/packages/frontend/src/components/MkTutorialDialog.Sensitive.vue +++ b/packages/frontend/src/components/MkTutorialDialog.Sensitive.vue @@ -31,7 +31,7 @@ import MkPostForm from '@/components/MkPostForm.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkInfo from '@/components/MkInfo.vue'; import MkNote from '@/components/MkNote.vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; const emit = defineEmits<{ (ev: 'succeeded'): void; diff --git a/packages/frontend/src/components/MkUserInfo.vue b/packages/frontend/src/components/MkUserInfo.vue index eb189b446b..cff531b2ca 100644 --- a/packages/frontend/src/components/MkUserInfo.vue +++ b/packages/frontend/src/components/MkUserInfo.vue @@ -39,7 +39,7 @@ import MkFollowButton from '@/components/MkFollowButton.vue'; import number from '@/filters/number.js'; import { userPage } from '@/filters/user.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/utility/isFfVisibleForMe.js'; import { getStaticImageUrl } from '@/utility/media-proxy.js'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/components/MkUserPopup.vue b/packages/frontend/src/components/MkUserPopup.vue index 8a89b253e3..7e8b1200d5 100644 --- a/packages/frontend/src/components/MkUserPopup.vue +++ b/packages/frontend/src/components/MkUserPopup.vue @@ -65,7 +65,7 @@ import { getUserMenu } from '@/utility/get-user-menu.js'; import number from '@/filters/number.js'; import { i18n } from '@/i18n.js'; import { prefer } from '@/preferences.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/utility/isFfVisibleForMe.js'; import { getStaticImageUrl } from '@/utility/media-proxy.js'; diff --git a/packages/frontend/src/components/MkUserSelectDialog.vue b/packages/frontend/src/components/MkUserSelectDialog.vue index e5c6df267b..6bf3eb44dc 100644 --- a/packages/frontend/src/components/MkUserSelectDialog.vue +++ b/packages/frontend/src/components/MkUserSelectDialog.vue @@ -70,7 +70,7 @@ import MkModalWindow from '@/components/MkModalWindow.vue'; import { misskeyApi } from '@/utility/misskey-api.js'; import { store } from '@/store.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { instance } from '@/instance.js'; const emit = defineEmits<{ diff --git a/packages/frontend/src/components/MkUserSetupDialog.Profile.vue b/packages/frontend/src/components/MkUserSetupDialog.Profile.vue index 14acfd3f89..7a5e5772a4 100644 --- a/packages/frontend/src/components/MkUserSetupDialog.Profile.vue +++ b/packages/frontend/src/components/MkUserSetupDialog.Profile.vue @@ -39,7 +39,7 @@ import FormSlot from '@/components/form/slot.vue'; import MkInfo from '@/components/MkInfo.vue'; import { chooseFileFromPc } from '@/utility/select-file.js'; import * as os from '@/os.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/components/global/MkAd.vue b/packages/frontend/src/components/global/MkAd.vue index c196519c15..b55069ca25 100644 --- a/packages/frontend/src/components/global/MkAd.vue +++ b/packages/frontend/src/components/global/MkAd.vue @@ -47,7 +47,7 @@ import { instance } from '@/instance.js'; import MkButton from '@/components/MkButton.vue'; import { store } from '@/store.js'; import * as os from '@/os.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { prefer } from '@/preferences.js'; type Ad = (typeof instance)['ads'][number]; diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue index 9981092dff..20a07e9c28 100644 --- a/packages/frontend/src/components/global/MkCustomEmoji.vue +++ b/packages/frontend/src/components/global/MkCustomEmoji.vue @@ -35,7 +35,7 @@ import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import * as sound from '@/utility/sound.js'; import { i18n } from '@/i18n.js'; import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { prefer } from '@/preferences.js'; const props = defineProps<{ diff --git a/packages/frontend/src/components/global/MkPageHeader.vue b/packages/frontend/src/components/global/MkPageHeader.vue index 728e37cf51..69bbd88cb6 100644 --- a/packages/frontend/src/components/global/MkPageHeader.vue +++ b/packages/frontend/src/components/global/MkPageHeader.vue @@ -50,7 +50,8 @@ import type { PageHeaderItem } from '@/types/page-header.js'; import type { PageMetadata } from '@/page.js'; import { globalEvents } from '@/events.js'; import { injectReactiveMetadata } from '@/page.js'; -import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js'; +import { openAccountMenu as openAccountMenu_ } from '@/accounts.js'; +import { $i } from '@/i.js'; const props = withDefaults(defineProps<{ overridePageMetadata?: PageMetadata; diff --git a/packages/frontend/src/i.ts b/packages/frontend/src/i.ts new file mode 100644 index 0000000000..aa84c6aa61 --- /dev/null +++ b/packages/frontend/src/i.ts @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { reactive } from 'vue'; +import * as Misskey from 'misskey-js'; +import { miLocalStorage } from '@/local-storage.js'; + +// TODO: 他のタブと永続化されたstateを同期 + +type AccountWithToken = Misskey.entities.MeDetailed & { token: string }; + +const accountData = miLocalStorage.getItem('account'); + +// TODO: 外部からはreadonlyに +export const $i = accountData ? reactive(JSON.parse(accountData) as AccountWithToken) : null; + +export const iAmModerator = $i != null && ($i.isAdmin === true || $i.isModerator === true); +export const iAmAdmin = $i != null && $i.isAdmin; + +export function signinRequired() { + if ($i == null) throw new Error('signin required'); + return $i; +} + +export let notesCount = $i == null ? 0 : $i.notesCount; +export function incNotesCount() { + notesCount++; +} + +if (_DEV_) { + (window as any).$i = $i; +} diff --git a/packages/frontend/src/local-storage.ts b/packages/frontend/src/local-storage.ts index 3977edb91b..099339fbee 100644 --- a/packages/frontend/src/local-storage.ts +++ b/packages/frontend/src/local-storage.ts @@ -9,7 +9,6 @@ export type Keys = ( 'instance' | 'instanceCachedAt' | 'account' | - 'accounts' | 'latestDonationInfoShownAt' | 'neverShowDonationInfo' | 'neverShowLocalOnlyInfo' | diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts index 837f333c9a..c0a6a370fc 100644 --- a/packages/frontend/src/navbar.ts +++ b/packages/frontend/src/navbar.ts @@ -5,7 +5,7 @@ import { computed, reactive } from 'vue'; import { clearCache } from './utility/clear-cache.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { miLocalStorage } from '@/local-storage.js'; import { openInstanceMenu, openToolsMenu } from '@/ui/_common_/common.js'; import { lookup } from '@/utility/lookup.js'; diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue index 5395429d7f..36dac2954d 100644 --- a/packages/frontend/src/pages/about-misskey.vue +++ b/packages/frontend/src/pages/about-misskey.vue @@ -146,7 +146,7 @@ import { instance } from '@/instance.js'; import * as os from '@/os.js'; import { definePage } from '@/page.js'; import { claimAchievement, claimedAchievements } from '@/utility/achievements.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { prefer } from '@/preferences.js'; const patronsWithIcon = [{ diff --git a/packages/frontend/src/pages/about.emojis.vue b/packages/frontend/src/pages/about.emojis.vue index d7d526f3ba..b166dfd940 100644 --- a/packages/frontend/src/pages/about.emojis.vue +++ b/packages/frontend/src/pages/about.emojis.vue @@ -44,7 +44,7 @@ import MkInput from '@/components/MkInput.vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import { customEmojis, customEmojiCategories, getCustomEmojiTags } from '@/custom-emojis.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; const customEmojiTags = getCustomEmojiTags(); const q = ref(''); diff --git a/packages/frontend/src/pages/achievements.vue b/packages/frontend/src/pages/achievements.vue index 53ce75f9bf..ca2443cc5b 100644 --- a/packages/frontend/src/pages/achievements.vue +++ b/packages/frontend/src/pages/achievements.vue @@ -17,7 +17,7 @@ import { onActivated, onDeactivated, onMounted, onUnmounted } from 'vue'; import MkAchievements from '@/components/MkAchievements.vue'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { claimAchievement } from '@/utility/achievements.js'; let timer: number | null; diff --git a/packages/frontend/src/pages/admin-file.vue b/packages/frontend/src/pages/admin-file.vue index 0af28e94fa..9274b90892 100644 --- a/packages/frontend/src/pages/admin-file.vue +++ b/packages/frontend/src/pages/admin-file.vue @@ -86,7 +86,7 @@ import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; -import { iAmAdmin, iAmModerator } from '@/account.js'; +import { iAmAdmin, iAmModerator } from '@/i.js'; const tab = ref('overview'); const file = ref<Misskey.entities.DriveFile | null>(null); diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue index 2efae999ce..ff1d5e64d3 100644 --- a/packages/frontend/src/pages/admin-user.vue +++ b/packages/frontend/src/pages/admin-user.vue @@ -233,7 +233,7 @@ import { misskeyApi } from '@/utility/misskey-api.js'; import { acct } from '@/filters/user.js'; import { definePage } from '@/page.js'; import { i18n } from '@/i18n.js'; -import { iAmAdmin, $i, iAmModerator } from '@/account.js'; +import { iAmAdmin, $i, iAmModerator } from '@/i.js'; import MkRolePreview from '@/components/MkRolePreview.vue'; import MkPagination from '@/components/MkPagination.vue'; diff --git a/packages/frontend/src/pages/announcement.vue b/packages/frontend/src/pages/announcement.vue index 977bbe0b47..6562610b12 100644 --- a/packages/frontend/src/pages/announcement.vue +++ b/packages/frontend/src/pages/announcement.vue @@ -55,8 +55,9 @@ import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; -import { $i, updateAccountPartial } from '@/account.js'; +import { $i } from '@/i.js'; import { prefer } from '@/preferences.js'; +import { updateCurrentAccountPartial } from '@/accounts.js'; const props = defineProps<{ announcementId: string; @@ -90,7 +91,7 @@ async function read(target: Misskey.entities.Announcement): Promise<void> { target.isRead = true; await misskeyApi('i/read-announcement', { announcementId: target.id }); if ($i) { - updateAccountPartial({ + updateCurrentAccountPartial({ unreadAnnouncements: $i.unreadAnnouncements.filter((a: { id: string; }) => a.id !== target.id), }); } diff --git a/packages/frontend/src/pages/announcements.vue b/packages/frontend/src/pages/announcements.vue index 13f28d9b35..2387ac728b 100644 --- a/packages/frontend/src/pages/announcements.vue +++ b/packages/frontend/src/pages/announcements.vue @@ -56,7 +56,8 @@ import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; -import { $i, updateAccountPartial } from '@/account.js'; +import { $i } from '@/i.js'; +import { updateCurrentAccountPartial } from '@/accounts.js'; const paginationCurrent = { endpoint: 'announcements' as const, @@ -94,7 +95,7 @@ async function read(target) { return a; }); misskeyApi('i/read-announcement', { announcementId: target.id }); - updateAccountPartial({ + updateCurrentAccountPartial({ unreadAnnouncements: $i!.unreadAnnouncements.filter(a => a.id !== target.id), }); } diff --git a/packages/frontend/src/pages/auth.vue b/packages/frontend/src/pages/auth.vue index 8b0fde4a25..e4699379f0 100644 --- a/packages/frontend/src/pages/auth.vue +++ b/packages/frontend/src/pages/auth.vue @@ -47,9 +47,10 @@ import * as Misskey from 'misskey-js'; import XForm from './auth.form.vue'; import MkSignin from '@/components/MkSignin.vue'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { $i, login } from '@/account.js'; +import { $i } from '@/i.js'; import { definePage } from '@/page.js'; import { i18n } from '@/i18n.js'; +import { login } from '@/accounts.js'; const props = defineProps<{ token: string; diff --git a/packages/frontend/src/pages/avatar-decoration-edit-dialog.vue b/packages/frontend/src/pages/avatar-decoration-edit-dialog.vue index a3c5a36614..884429dfeb 100644 --- a/packages/frontend/src/pages/avatar-decoration-edit-dialog.vue +++ b/packages/frontend/src/pages/avatar-decoration-edit-dialog.vue @@ -73,7 +73,7 @@ import { i18n } from '@/i18n.js'; import MkSwitch from '@/components/MkSwitch.vue'; import MkRolePreview from '@/components/MkRolePreview.vue'; import MkTextarea from '@/components/MkTextarea.vue'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/pages/avatar-decorations.vue b/packages/frontend/src/pages/avatar-decorations.vue index eb1015b19e..b84b9efc1a 100644 --- a/packages/frontend/src/pages/avatar-decorations.vue +++ b/packages/frontend/src/pages/avatar-decorations.vue @@ -28,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { ref, computed, defineAsyncComponent } from 'vue'; import * as Misskey from 'misskey-js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue index a774aa6e44..c5951f0e13 100644 --- a/packages/frontend/src/pages/channel.vue +++ b/packages/frontend/src/pages/channel.vue @@ -82,7 +82,7 @@ import MkTimeline from '@/components/MkTimeline.vue'; import XChannelFollowButton from '@/components/MkChannelFollowButton.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { $i, iAmModerator } from '@/account.js'; +import { $i, iAmModerator } from '@/i.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { deviceKind } from '@/utility/device-kind.js'; diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue index 9765ebf216..590a506a55 100644 --- a/packages/frontend/src/pages/clip.vue +++ b/packages/frontend/src/pages/clip.vue @@ -36,7 +36,7 @@ import * as Misskey from 'misskey-js'; import { url } from '@@/js/config.js'; import type { MenuItem } from '@/types/menu.js'; import MkNotes from '@/components/MkNotes.vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; diff --git a/packages/frontend/src/pages/drop-and-fusion.game.vue b/packages/frontend/src/pages/drop-and-fusion.game.vue index f760aca8ae..364006e9ad 100644 --- a/packages/frontend/src/pages/drop-and-fusion.game.vue +++ b/packages/frontend/src/pages/drop-and-fusion.game.vue @@ -208,7 +208,7 @@ import { claimAchievement } from '@/utility/achievements.js'; import { store } from '@/store.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import * as sound from '@/utility/sound.js'; import MkRange from '@/components/MkRange.vue'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; diff --git a/packages/frontend/src/pages/emojis.emoji.vue b/packages/frontend/src/pages/emojis.emoji.vue index 35a240b9ba..bedb0b64f9 100644 --- a/packages/frontend/src/pages/emojis.emoji.vue +++ b/packages/frontend/src/pages/emojis.emoji.vue @@ -22,7 +22,7 @@ import { misskeyApiGet } from '@/utility/misskey-api.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { i18n } from '@/i18n.js'; import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; const props = defineProps<{ emoji: Misskey.entities.EmojiSimple; diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue index 6bce6689d4..08ac913958 100644 --- a/packages/frontend/src/pages/flash/flash.vue +++ b/packages/frontend/src/pages/flash/flash.vue @@ -80,7 +80,7 @@ import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; import MkFolder from '@/components/MkFolder.vue'; import MkCode from '@/components/MkCode.vue'; import { prefer } from '@/preferences.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { isSupportShare } from '@/utility/navigator.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { pleaseLogin } from '@/utility/please-login.js'; diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue index bd48b882d2..7e496f522d 100644 --- a/packages/frontend/src/pages/follow-requests.vue +++ b/packages/frontend/src/pages/follow-requests.vue @@ -54,7 +54,7 @@ import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { infoImageUrl } from '@/instance.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>(); diff --git a/packages/frontend/src/pages/gallery/post.vue b/packages/frontend/src/pages/gallery/post.vue index 56ddb820cf..eb01aadbcc 100644 --- a/packages/frontend/src/pages/gallery/post.vue +++ b/packages/frontend/src/pages/gallery/post.vue @@ -77,7 +77,7 @@ import MkFollowButton from '@/components/MkFollowButton.vue'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { prefer } from '@/preferences.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { isSupportShare } from '@/utility/navigator.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { useRouter } from '@/router/supplier.js'; diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue index eddeb4aba9..c4aed8d6df 100644 --- a/packages/frontend/src/pages/instance-info.vue +++ b/packages/frontend/src/pages/instance-info.vue @@ -148,7 +148,7 @@ import MkSwitch from '@/components/MkSwitch.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import number from '@/filters/number.js'; -import { iAmModerator, iAmAdmin } from '@/account.js'; +import { iAmModerator, iAmAdmin } from '@/i.js'; import { definePage } from '@/page.js'; import { i18n } from '@/i18n.js'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; diff --git a/packages/frontend/src/pages/invite.vue b/packages/frontend/src/pages/invite.vue index 8369927d85..352e1d9386 100644 --- a/packages/frontend/src/pages/invite.vue +++ b/packages/frontend/src/pages/invite.vue @@ -45,7 +45,7 @@ import type { Paging } from '@/components/MkPagination.vue'; import MkInviteCode from '@/components/MkInviteCode.vue'; import { definePage } from '@/page.js'; import { serverErrorImageUrl, instance } from '@/instance.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>(); const currentInviteLimit = ref<null | number>(null); diff --git a/packages/frontend/src/pages/my-lists/index.vue b/packages/frontend/src/pages/my-lists/index.vue index 0bc9b3f3c2..cc701cb16b 100644 --- a/packages/frontend/src/pages/my-lists/index.vue +++ b/packages/frontend/src/pages/my-lists/index.vue @@ -37,7 +37,7 @@ import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { userListsCache } from '@/cache.js'; import { infoImageUrl } from '@/instance.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue index fdee890cfd..6481c0da0c 100644 --- a/packages/frontend/src/pages/my-lists/list.vue +++ b/packages/frontend/src/pages/my-lists/list.vue @@ -66,7 +66,7 @@ import MkSwitch from '@/components/MkSwitch.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkInput from '@/components/MkInput.vue'; import { userListsCache } from '@/cache.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import MkPagination from '@/components/MkPagination.vue'; import { mainRouter } from '@/router/main.js'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue index 6f53cba806..fb83993fee 100644 --- a/packages/frontend/src/pages/note.vue +++ b/packages/frontend/src/pages/note.vue @@ -65,7 +65,7 @@ import { prefer } from '@/preferences.js'; import { pleaseLogin } from '@/utility/please-login.js'; import { getAppearNote } from '@/utility/get-appear-note.js'; import { serverContext, assertServerContext } from '@/server-context.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; // contextは非ログイン状態の情報しかないためログイン時は利用できない const CTX_NOTE = !$i && assertServerContext(serverContext, 'note') ? serverContext.note : null; diff --git a/packages/frontend/src/pages/page-editor/page-editor.vue b/packages/frontend/src/pages/page-editor/page-editor.vue index ed701ed3c0..e2f6084252 100644 --- a/packages/frontend/src/pages/page-editor/page-editor.vue +++ b/packages/frontend/src/pages/page-editor/page-editor.vue @@ -75,7 +75,7 @@ import { misskeyApi } from '@/utility/misskey-api.js'; import { selectFile } from '@/utility/select-file.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { mainRouter } from '@/router/main.js'; import { getPageBlockList } from '@/pages/page-editor/common.js'; diff --git a/packages/frontend/src/pages/page.vue b/packages/frontend/src/pages/page.vue index 1c288442b5..00c664d2a0 100644 --- a/packages/frontend/src/pages/page.vue +++ b/packages/frontend/src/pages/page.vue @@ -115,7 +115,7 @@ import MkPagePreview from '@/components/MkPagePreview.vue'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { deepClone } from '@/utility/clone.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { isSupportShare } from '@/utility/navigator.js'; import { instance } from '@/instance.js'; import { getStaticImageUrl } from '@/utility/media-proxy.js'; diff --git a/packages/frontend/src/pages/reversi/game.board.vue b/packages/frontend/src/pages/reversi/game.board.vue index 71dd220cfe..ef9cc242c6 100644 --- a/packages/frontend/src/pages/reversi/game.board.vue +++ b/packages/frontend/src/pages/reversi/game.board.vue @@ -150,7 +150,7 @@ import MkFolder from '@/components/MkFolder.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import { deepClone } from '@/utility/clone.js'; import { useInterval } from '@@/js/use-interval.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { url } from '@@/js/config.js'; import { i18n } from '@/i18n.js'; import { misskeyApi } from '@/utility/misskey-api.js'; diff --git a/packages/frontend/src/pages/reversi/game.setting.vue b/packages/frontend/src/pages/reversi/game.setting.vue index 03b75f89ae..2715b70b95 100644 --- a/packages/frontend/src/pages/reversi/game.setting.vue +++ b/packages/frontend/src/pages/reversi/game.setting.vue @@ -114,7 +114,7 @@ import { computed, watch, ref, onMounted, shallowRef, onUnmounted } from 'vue'; import * as Misskey from 'misskey-js'; import * as Reversi from 'misskey-reversi'; import { i18n } from '@/i18n.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { deepClone } from '@/utility/clone.js'; import MkButton from '@/components/MkButton.vue'; import MkRadios from '@/components/MkRadios.vue'; diff --git a/packages/frontend/src/pages/reversi/game.vue b/packages/frontend/src/pages/reversi/game.vue index 053ec2aa08..662df00d9b 100644 --- a/packages/frontend/src/pages/reversi/game.vue +++ b/packages/frontend/src/pages/reversi/game.vue @@ -17,7 +17,7 @@ import GameBoard from './game.board.vue'; import { misskeyApi } from '@/utility/misskey-api.js'; import { definePage } from '@/page.js'; import { useStream } from '@/stream.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { useRouter } from '@/router/supplier.js'; import * as os from '@/os.js'; import { url } from '@@/js/config.js'; diff --git a/packages/frontend/src/pages/reversi/index.vue b/packages/frontend/src/pages/reversi/index.vue index ff2e7e922f..d66ff8db05 100644 --- a/packages/frontend/src/pages/reversi/index.vue +++ b/packages/frontend/src/pages/reversi/index.vue @@ -113,7 +113,7 @@ import { useStream } from '@/stream.js'; import MkButton from '@/components/MkButton.vue'; import MkFolder from '@/components/MkFolder.vue'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import MkPagination from '@/components/MkPagination.vue'; import { useRouter } from '@/router/supplier.js'; import * as os from '@/os.js'; diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue index ed5cd23b23..b0d3b5bbd2 100644 --- a/packages/frontend/src/pages/scratchpad.vue +++ b/packages/frontend/src/pages/scratchpad.vue @@ -66,7 +66,7 @@ import MkTextarea from '@/components/MkTextarea.vue'; import MkCodeEditor from '@/components/MkCodeEditor.vue'; import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; import * as os from '@/os.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { registerAsUiLib } from '@/aiscript/ui.js'; diff --git a/packages/frontend/src/pages/search.note.vue b/packages/frontend/src/pages/search.note.vue index bfe56e793b..4801e9bc27 100644 --- a/packages/frontend/src/pages/search.note.vue +++ b/packages/frontend/src/pages/search.note.vue @@ -114,7 +114,7 @@ SPDX-License-Identifier: AGPL-3.0-only import { computed, ref, shallowRef, toRef } from 'vue'; import type * as Misskey from 'misskey-js'; import type { Paging } from '@/components/MkPagination.vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { host as localHost } from '@@/js/config.js'; import { i18n } from '@/i18n.js'; import { instance } from '@/instance.js'; diff --git a/packages/frontend/src/pages/settings/2fa.qrdialog.vue b/packages/frontend/src/pages/settings/2fa.qrdialog.vue index 9093ffd7a9..41a2535813 100644 --- a/packages/frontend/src/pages/settings/2fa.qrdialog.vue +++ b/packages/frontend/src/pages/settings/2fa.qrdialog.vue @@ -117,7 +117,7 @@ import MkFolder from '@/components/MkFolder.vue'; import MkInfo from '@/components/MkInfo.vue'; import MkLink from '@/components/MkLink.vue'; import { confetti } from '@/utility/confetti.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue index 806599e801..20d1b0fe0f 100644 --- a/packages/frontend/src/pages/settings/2fa.vue +++ b/packages/frontend/src/pages/settings/2fa.vue @@ -92,8 +92,9 @@ import FormSection from '@/components/form/section.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkLink from '@/components/MkLink.vue'; import * as os from '@/os.js'; -import { signinRequired, updateAccountPartial } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { i18n } from '@/i18n.js'; +import { updateCurrentAccountPartial } from '@/accounts.js'; const $i = signinRequired(); @@ -131,7 +132,7 @@ async function unregisterTOTP(): Promise<void> { password: auth.result.password, token: auth.result.token, }).then(res => { - updateAccountPartial({ + updateCurrentAccountPartial({ twoFactorEnabled: false, }); }).catch(error => { diff --git a/packages/frontend/src/pages/settings/account-data.vue b/packages/frontend/src/pages/settings/account-data.vue index ed5fe48821..14bea577a3 100644 --- a/packages/frontend/src/pages/settings/account-data.vue +++ b/packages/frontend/src/pages/settings/account-data.vue @@ -167,7 +167,7 @@ import { misskeyApi } from '@/utility/misskey-api.js'; import { selectFile } from '@/utility/select-file.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import MkFeatureBanner from '@/components/MkFeatureBanner.vue'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/pages/settings/accounts.vue b/packages/frontend/src/pages/settings/accounts.vue index 2cf65be2d0..749ae5147f 100644 --- a/packages/frontend/src/pages/settings/accounts.vue +++ b/packages/frontend/src/pages/settings/accounts.vue @@ -4,80 +4,51 @@ SPDX-License-Identifier: AGPL-3.0-only --> <template> -<div class=""> - <FormSuspense :p="init"> - <div class="_gaps"> - <div class="_buttons"> - <MkButton primary @click="addAccount"><i class="ti ti-plus"></i> {{ i18n.ts.addAccount }}</MkButton> - <MkButton @click="init"><i class="ti ti-refresh"></i> {{ i18n.ts.reloadAccountsList }}</MkButton> - </div> - - <template v-for="[id, user] in accounts"> - <MkUserCardMini v-if="user != null" :key="user.id" :user="user" :class="$style.user" @click.prevent="menu(user, $event)"/> - <button v-else v-panel class="_button" :class="$style.unknownUser" @click="menu(id, $event)"> - <div :class="$style.unknownUserAvatarMock"><i class="ti ti-user-question"></i></div> - <div> - <div :class="$style.unknownUserTitle">{{ i18n.ts.unknown }}</div> - <div :class="$style.unknownUserSub">ID: <span class="_monospace">{{ id }}</span></div> - </div> - </button> - </template> +<SearchMarker path="/settings/accounts" :label="i18n.ts.accounts" :keywords="['accounts']" icon="ti ti-users"> + <div class="_gaps"> + <div class="_buttons"> + <MkButton primary @click="addAccount"><i class="ti ti-plus"></i> {{ i18n.ts.addAccount }}</MkButton> + <!--<MkButton @click="refreshAllAccounts"><i class="ti ti-refresh"></i></MkButton>--> </div> - </FormSuspense> -</div> + + <MkUserCardMini v-for="x in accounts" :key="x[0] + x[1].id" :user="x[1]" :class="$style.user" @click.prevent="menu(x[0], x[1], $event)"/> + </div> +</SearchMarker> </template> <script lang="ts" setup> import { ref, computed } from 'vue'; import * as Misskey from 'misskey-js'; -import FormSuspense from '@/components/form/suspense.vue'; +import type { MenuItem } from '@/types/menu.js'; import MkButton from '@/components/MkButton.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { getAccounts, removeAccount as _removeAccount, login, $i, getAccountWithSigninDialog, getAccountWithSignupDialog } from '@/account.js'; +import { $i } from '@/i.js'; +import { switchAccount, removeAccount, login, getAccountWithSigninDialog, getAccountWithSignupDialog } from '@/accounts.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; -import type { MenuItem } from '@/types/menu.js'; +import { prefer } from '@/preferences.js'; -const storedAccounts = ref<{ id: string, token: string }[] | null>(null); -const accounts = ref(new Map<string, Misskey.entities.UserDetailed | null>()); +const accounts = prefer.r.accounts; -const init = async () => { - getAccounts().then(accounts => { - storedAccounts.value = accounts.filter(x => x.id !== $i!.id); +function refreshAllAccounts() { + // TODO +} - return misskeyApi('users/show', { - userIds: storedAccounts.value.map(x => x.id), - }); - }).then(response => { - if (storedAccounts.value == null) return; - accounts.value = new Map(storedAccounts.value.map(x => [x.id, response.find((y: Misskey.entities.UserDetailed) => y.id === x.id) ?? null])); - }); -}; - -function menu(account: Misskey.entities.UserDetailed | string, ev: MouseEvent) { +function menu(host: string, account: Misskey.entities.UserDetailed, ev: MouseEvent) { let menu: MenuItem[]; - if (typeof account === 'string') { - menu = [{ - text: i18n.ts.logout, - icon: 'ti ti-trash', - danger: true, - action: () => removeAccount(account), - }]; - } else { - menu = [{ - text: i18n.ts.switch, - icon: 'ti ti-switch-horizontal', - action: () => switchAccount(account.id), - }, { - text: i18n.ts.logout, - icon: 'ti ti-trash', - danger: true, - action: () => removeAccount(account.id), - }]; - } + menu = [{ + text: i18n.ts.switch, + icon: 'ti ti-switch-horizontal', + action: () => switchAccount(host, account.id), + }, { + text: i18n.ts.logout, + icon: 'ti ti-trash', + danger: true, + action: () => removeAccount(host, account.id), + }]; os.popupMenu(menu, ev.currentTarget ?? ev.target); } @@ -92,16 +63,10 @@ function addAccount(ev: MouseEvent) { }], ev.currentTarget ?? ev.target); } -async function removeAccount(id: string) { - await _removeAccount(id); - accounts.value.delete(id); -} - function addExistingAccount() { getAccountWithSigninDialog().then((res) => { if (res != null) { os.success(); - init(); } }); } @@ -109,21 +74,11 @@ function addExistingAccount() { function createAccount() { getAccountWithSignupDialog().then((res) => { if (res != null) { - switchAccountWithToken(res.token); + login(res.token); } }); } -async function switchAccount(id: string) { - const fetchedAccounts = await getAccounts(); - const token = fetchedAccounts.find(x => x.id === id)!.token; - switchAccountWithToken(token); -} - -function switchAccountWithToken(token: string) { - login(token); -} - const headerActions = computed(() => []); const headerTabs = computed(() => []); diff --git a/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue index 3c9914b4e2..6b3bb1b513 100644 --- a/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue +++ b/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue @@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { computed } from 'vue'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue index 40542ad5b2..e4803eda2e 100644 --- a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue +++ b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue @@ -51,7 +51,7 @@ import MkModalWindow from '@/components/MkModalWindow.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import { i18n } from '@/i18n.js'; import MkRange from '@/components/MkRange.vue'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/pages/settings/avatar-decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.vue index ba25eee175..91549e5240 100644 --- a/packages/frontend/src/pages/settings/avatar-decoration.vue +++ b/packages/frontend/src/pages/settings/avatar-decoration.vue @@ -54,7 +54,7 @@ import MkButton from '@/components/MkButton.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import MkInfo from '@/components/MkInfo.vue'; import { definePage } from '@/page.js'; diff --git a/packages/frontend/src/pages/settings/drive.vue b/packages/frontend/src/pages/settings/drive.vue index 34941d5af0..0b25ee5e37 100644 --- a/packages/frontend/src/pages/settings/drive.vue +++ b/packages/frontend/src/pages/settings/drive.vue @@ -104,7 +104,7 @@ import bytes from '@/filters/bytes.js'; import MkChart from '@/components/MkChart.vue'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { prefer } from '@/preferences.js'; import MkPreferenceContainer from '@/components/MkPreferenceContainer.vue'; import MkFeatureBanner from '@/components/MkFeatureBanner.vue'; diff --git a/packages/frontend/src/pages/settings/email.vue b/packages/frontend/src/pages/settings/email.vue index 0cbda44882..10e2a000d4 100644 --- a/packages/frontend/src/pages/settings/email.vue +++ b/packages/frontend/src/pages/settings/email.vue @@ -67,7 +67,7 @@ import MkSwitch from '@/components/MkSwitch.vue'; import MkDisableSection from '@/components/MkDisableSection.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { instance } from '@/instance.js'; diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue index 0579b6d14a..ba5957f06a 100644 --- a/packages/frontend/src/pages/settings/index.vue +++ b/packages/frontend/src/pages/settings/index.vue @@ -38,7 +38,7 @@ import type { SuperMenuDef } from '@/components/MkSuperMenu.vue'; import { i18n } from '@/i18n.js'; import MkInfo from '@/components/MkInfo.vue'; import MkSuperMenu from '@/components/MkSuperMenu.vue'; -import { signout, $i } from '@/account.js'; +import { $i } from '@/i.js'; import { clearCache } from '@/utility/clear-cache.js'; import { instance } from '@/instance.js'; import { definePage, provideMetadataReceiver, provideReactiveMetadata } from '@/page.js'; @@ -47,6 +47,7 @@ import { useRouter } from '@/router/supplier.js'; import { searchIndexes } from '@/utility/autogen/settings-search-index.js'; import { enableAutoBackup, getPreferencesProfileMenu } from '@/preferences/utility.js'; import { store } from '@/store.js'; +import { signout } from '@/signout.js'; const SETTING_INDEX = searchIndexes; // TODO: lazy load diff --git a/packages/frontend/src/pages/settings/migration.vue b/packages/frontend/src/pages/settings/migration.vue index 60386da545..260e390b51 100644 --- a/packages/frontend/src/pages/settings/migration.vue +++ b/packages/frontend/src/pages/settings/migration.vue @@ -68,7 +68,7 @@ import MkUserInfo from '@/components/MkUserInfo.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { unisonReload } from '@/utility/unison-reload.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/pages/settings/mute-block.instance-mute.vue b/packages/frontend/src/pages/settings/mute-block.instance-mute.vue index 52e1937663..1c942e715a 100644 --- a/packages/frontend/src/pages/settings/mute-block.instance-mute.vue +++ b/packages/frontend/src/pages/settings/mute-block.instance-mute.vue @@ -19,7 +19,7 @@ import { ref, watch } from 'vue'; import MkTextarea from '@/components/MkTextarea.vue'; import MkInfo from '@/components/MkInfo.vue'; import MkButton from '@/components/MkButton.vue'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue index a5ab7caf99..ce762af071 100644 --- a/packages/frontend/src/pages/settings/mute-block.vue +++ b/packages/frontend/src/pages/settings/mute-block.vue @@ -188,7 +188,7 @@ import { definePage } from '@/page.js'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; import * as os from '@/os.js'; import { instance, infoImageUrl } from '@/instance.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import MkInfo from '@/components/MkInfo.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkSwitch from '@/components/MkSwitch.vue'; diff --git a/packages/frontend/src/pages/settings/notifications.vue b/packages/frontend/src/pages/settings/notifications.vue index 49910cdf4a..785fcdfbce 100644 --- a/packages/frontend/src/pages/settings/notifications.vue +++ b/packages/frontend/src/pages/settings/notifications.vue @@ -75,7 +75,7 @@ import FormSection from '@/components/form/section.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import * as os from '@/os.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue index 62b0f5c941..27fb743cb2 100644 --- a/packages/frontend/src/pages/settings/other.vue +++ b/packages/frontend/src/pages/settings/other.vue @@ -127,13 +127,14 @@ import MkKeyValue from '@/components/MkKeyValue.vue'; import MkButton from '@/components/MkButton.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { signout, signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { i18n } from '@/i18n.js'; import { definePage } from '@/page.js'; import { reloadAsk } from '@/utility/reload-ask.js'; import FormSection from '@/components/form/section.vue'; import { prefer } from '@/preferences.js'; import MkRolePreview from '@/components/MkRolePreview.vue'; +import { signout } from '@/signout.js'; const $i = signinRequired(); diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue index edc750c295..b73f781b9c 100644 --- a/packages/frontend/src/pages/settings/privacy.vue +++ b/packages/frontend/src/pages/settings/privacy.vue @@ -185,7 +185,7 @@ import MkFolder from '@/components/MkFolder.vue'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; import { instance } from '@/instance.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { definePage } from '@/page.js'; import FormSlot from '@/components/form/slot.vue'; import { formatDateTimeString } from '@/utility/format-time-string.js'; diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index 1d85ba7834..b12ba9fe93 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -164,7 +164,7 @@ import FormSlot from '@/components/form/slot.vue'; import { selectFile } from '@/utility/select-file.js'; import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; -import { signinRequired } from '@/account.js'; +import { signinRequired } from '@/i.js'; import { langmap } from '@/utility/langmap.js'; import { definePage } from '@/page.js'; import { claimAchievement } from '@/utility/achievements.js'; diff --git a/packages/frontend/src/pages/signup-complete.vue b/packages/frontend/src/pages/signup-complete.vue index c3f1b4b18e..e37f05f1be 100644 --- a/packages/frontend/src/pages/signup-complete.vue +++ b/packages/frontend/src/pages/signup-complete.vue @@ -28,10 +28,10 @@ SPDX-License-Identifier: AGPL-3.0-only import { ref } from 'vue'; import MkButton from '@/components/MkButton.vue'; import MkAnimBg from '@/components/MkAnimBg.vue'; -import { login } from '@/account.js'; import { i18n } from '@/i18n.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; +import { login } from '@/accounts.js'; const submitting = ref(false); diff --git a/packages/frontend/src/pages/tag.vue b/packages/frontend/src/pages/tag.vue index 1af69d82db..868c64d06d 100644 --- a/packages/frontend/src/pages/tag.vue +++ b/packages/frontend/src/pages/tag.vue @@ -25,7 +25,7 @@ import MkNotes from '@/components/MkNotes.vue'; import MkButton from '@/components/MkButton.vue'; import { definePage } from '@/page.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { store } from '@/store.js'; import * as os from '@/os.js'; import { genEmbedCode } from '@/utility/get-embed-code.js'; diff --git a/packages/frontend/src/pages/theme-editor.vue b/packages/frontend/src/pages/theme-editor.vue index 5ee42cc1ec..45d8c96ab7 100644 --- a/packages/frontend/src/pages/theme-editor.vue +++ b/packages/frontend/src/pages/theme-editor.vue @@ -86,7 +86,7 @@ import MkButton from '@/components/MkButton.vue'; import MkCodeEditor from '@/components/MkCodeEditor.vue'; import MkTextarea from '@/components/MkTextarea.vue'; import MkFolder from '@/components/MkFolder.vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { applyTheme } from '@/theme.js'; import * as os from '@/os.js'; import { store } from '@/store.js'; diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index 0ac6979b05..68f4b7a26d 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -48,7 +48,7 @@ import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { store } from '@/store.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { definePage } from '@/page.js'; import { antennasCache, userListsCache, favoritedChannelsCache } from '@/cache.js'; import { deviceKind } from '@/utility/device-kind.js'; diff --git a/packages/frontend/src/pages/user/achievements.vue b/packages/frontend/src/pages/user/achievements.vue index b78ac2dc17..8f13e959e1 100644 --- a/packages/frontend/src/pages/user/achievements.vue +++ b/packages/frontend/src/pages/user/achievements.vue @@ -14,7 +14,7 @@ import { onActivated, onDeactivated, onMounted, onUnmounted } from 'vue'; import * as Misskey from 'misskey-js'; import MkAchievements from '@/components/MkAchievements.vue'; import { claimAchievement } from '@/utility/achievements.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; const props = defineProps<{ user: Misskey.entities.User; diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue index 6450f1e077..149481f99b 100644 --- a/packages/frontend/src/pages/user/home.vue +++ b/packages/frontend/src/pages/user/home.vue @@ -176,7 +176,7 @@ import number from '@/filters/number.js'; import { userPage } from '@/filters/user.js'; import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; -import { $i, iAmModerator } from '@/account.js'; +import { $i, iAmModerator } from '@/i.js'; import { dateString } from '@/filters/date.js'; import { confetti } from '@/utility/confetti.js'; import { misskeyApi } from '@/utility/misskey-api.js'; diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue index b5127de390..16413a55cc 100644 --- a/packages/frontend/src/pages/user/index.vue +++ b/packages/frontend/src/pages/user/index.vue @@ -38,7 +38,7 @@ import { acct as getAcct } from '@/filters/user.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { definePage } from '@/page.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; import { serverContext, assertServerContext } from '@/server-context.js'; diff --git a/packages/frontend/src/pages/welcome.setup.vue b/packages/frontend/src/pages/welcome.setup.vue index 939ca934e8..d9e3ca9966 100644 --- a/packages/frontend/src/pages/welcome.setup.vue +++ b/packages/frontend/src/pages/welcome.setup.vue @@ -45,9 +45,9 @@ import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { login } from '@/account.js'; import { i18n } from '@/i18n.js'; import MkAnimBg from '@/components/MkAnimBg.vue'; +import { login } from '@/accounts.js'; const username = ref(''); const password = ref(''); diff --git a/packages/frontend/src/pizzax.ts b/packages/frontend/src/pizzax.ts index f55b1e93cf..3ebf2ab4e4 100644 --- a/packages/frontend/src/pizzax.ts +++ b/packages/frontend/src/pizzax.ts @@ -8,7 +8,7 @@ import { onUnmounted, ref, watch } from 'vue'; import { BroadcastChannel } from 'broadcast-channel'; import type { Ref } from 'vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { get, set } from '@/utility/idb-proxy.js'; import { store } from '@/store.js'; diff --git a/packages/frontend/src/preferences.ts b/packages/frontend/src/preferences.ts index 8785acd7d1..f9e6ab2a75 100644 --- a/packages/frontend/src/preferences.ts +++ b/packages/frontend/src/preferences.ts @@ -9,7 +9,7 @@ import { cloudBackup } from '@/preferences/utility.js'; import { miLocalStorage } from '@/local-storage.js'; import { isSameScope, PreferencesManager } from '@/preferences/manager.js'; import { store } from '@/store.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { misskeyApi } from '@/utility/misskey-api.js'; const TAB_ID = uuid(); diff --git a/packages/frontend/src/preferences/def.ts b/packages/frontend/src/preferences/def.ts index eb3d6eeac4..e460359acd 100644 --- a/packages/frontend/src/preferences/def.ts +++ b/packages/frontend/src/preferences/def.ts @@ -32,6 +32,10 @@ export type SoundStore = { // NOTE: デフォルト値は他の設定の状態に依存してはならない(依存していた場合、ユーザーがその設定項目単体で「初期値にリセット」した場合不具合の原因になる) export const PREF_DEF = { + accounts: { + default: [] as [host: string, user: Misskey.entities.User][], + }, + pinnedUserLists: { accountDependent: true, default: [] as Misskey.entities.UserList[], diff --git a/packages/frontend/src/preferences/manager.ts b/packages/frontend/src/preferences/manager.ts index b053cadacb..fad0226b6e 100644 --- a/packages/frontend/src/preferences/manager.ts +++ b/packages/frontend/src/preferences/manager.ts @@ -9,7 +9,7 @@ import { host, version } from '@@/js/config.js'; import { PREF_DEF } from './def.js'; import type { Ref, WritableComputedRef } from 'vue'; import type { MenuItem } from '@/types/menu.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import { i18n } from '@/i18n.js'; import * as os from '@/os.js'; diff --git a/packages/frontend/src/preferences/utility.ts b/packages/frontend/src/preferences/utility.ts index c37dbcf96b..bf3dfa157f 100644 --- a/packages/frontend/src/preferences/utility.ts +++ b/packages/frontend/src/preferences/utility.ts @@ -12,7 +12,7 @@ import { miLocalStorage } from '@/local-storage.js'; import { prefer } from '@/preferences.js'; import * as os from '@/os.js'; import { store } from '@/store.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { unisonReload } from '@/utility/unison-reload.js'; diff --git a/packages/frontend/src/router/definition.ts b/packages/frontend/src/router/definition.ts index 73920766d7..9a81032cc8 100644 --- a/packages/frontend/src/router/definition.ts +++ b/packages/frontend/src/router/definition.ts @@ -7,7 +7,7 @@ import { defineAsyncComponent } from 'vue'; import type { AsyncComponentLoader } from 'vue'; import type { IRouter, RouteDef } from '@/nirax.js'; import { Router } from '@/nirax.js'; -import { $i, iAmModerator } from '@/account.js'; +import { $i, iAmModerator } from '@/i.js'; import MkLoading from '@/pages/_loading_.vue'; import MkError from '@/pages/_error_.vue'; diff --git a/packages/frontend/src/signout.ts b/packages/frontend/src/signout.ts new file mode 100644 index 0000000000..8e90552546 --- /dev/null +++ b/packages/frontend/src/signout.ts @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineAsyncComponent, ref } from 'vue'; +import { apiUrl, host } from '@@/js/config.js'; +import { defaultMemoryStorage } from '@/memory-storage'; +import { i18n } from '@/i18n.js'; +import { miLocalStorage } from '@/local-storage.js'; +import { waiting, popup, popupMenu, success, alert } from '@/os.js'; +import { unisonReload, reloadChannel } from '@/utility/unison-reload.js'; +import { prefer } from '@/preferences.js'; +import { store } from '@/store.js'; +import { $i } from '@/i.js'; + +export async function signout() { + if (!$i) return; + + defaultMemoryStorage.clear(); + + waiting(); + miLocalStorage.removeItem('account'); + + // TODO: preferencesも削除 + + //#region Remove service worker registration + try { + if (navigator.serviceWorker.controller) { + const registration = await navigator.serviceWorker.ready; + const push = await registration.pushManager.getSubscription(); + if (push) { + await window.fetch(`${apiUrl}/sw/unregister`, { + method: 'POST', + body: JSON.stringify({ + i: $i.token, + endpoint: push.endpoint, + }), + headers: { + 'Content-Type': 'application/json', + }, + }); + } + } + + await navigator.serviceWorker.getRegistrations() + .then(registrations => { + return Promise.all(registrations.map(registration => registration.unregister())); + }); + } catch (err) {} + //#endregion + + unisonReload('/'); +} diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index 9a61e63d0e..ffbd8d10ef 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -104,6 +104,10 @@ export const store = markRaw(new Storage('base', { where: 'deviceAccount', default: {} as Record<string, string>, // plugin id, token }, + accountTokens: { + where: 'device', + default: {} as Record<string, string>, // host/userId, token + }, enablePreferencesAutoCloudBackup: { where: 'device', diff --git a/packages/frontend/src/stream.ts b/packages/frontend/src/stream.ts index e194e96a7f..c97d7d4071 100644 --- a/packages/frontend/src/stream.ts +++ b/packages/frontend/src/stream.ts @@ -5,7 +5,7 @@ import * as Misskey from 'misskey-js'; import { markRaw } from 'vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { wsOrigin } from '@@/js/config.js'; // TODO: No WebsocketモードでStreamMockが使えそう //import { StreamMock } from '@/utility/stream-mock.js'; diff --git a/packages/frontend/src/theme-store.ts b/packages/frontend/src/theme-store.ts index 5d09ec27f9..2ae5d8730e 100644 --- a/packages/frontend/src/theme-store.ts +++ b/packages/frontend/src/theme-store.ts @@ -5,7 +5,7 @@ import type { Theme } from '@/theme.js'; import { getBuiltinThemes } from '@/theme.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { prefer } from '@/preferences.js'; export function getThemes(): Theme[] { diff --git a/packages/frontend/src/timelines.ts b/packages/frontend/src/timelines.ts index 94eda3545e..a39ccd481d 100644 --- a/packages/frontend/src/timelines.ts +++ b/packages/frontend/src/timelines.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { instance } from '@/instance.js'; export const basicTimelineTypes = [ diff --git a/packages/frontend/src/ui/_common_/PreferenceRestore.vue b/packages/frontend/src/ui/_common_/PreferenceRestore.vue index c70b82cd0e..5fd9f5e44b 100644 --- a/packages/frontend/src/ui/_common_/PreferenceRestore.vue +++ b/packages/frontend/src/ui/_common_/PreferenceRestore.vue @@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only </template> <script lang="ts" setup> -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import { hideRestoreBackupSuggestion, restoreFromCloudBackup } from '@/preferences/utility.js'; diff --git a/packages/frontend/src/ui/_common_/announcements.vue b/packages/frontend/src/ui/_common_/announcements.vue index d153dc8726..f9af8e1ee7 100644 --- a/packages/frontend/src/ui/_common_/announcements.vue +++ b/packages/frontend/src/ui/_common_/announcements.vue @@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only </template> <script lang="ts" setup> -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; </script> <style lang="scss" module> diff --git a/packages/frontend/src/ui/_common_/common.ts b/packages/frontend/src/ui/_common_/common.ts index 8e5ba8927a..819e1fa42f 100644 --- a/packages/frontend/src/ui/_common_/common.ts +++ b/packages/frontend/src/ui/_common_/common.ts @@ -9,7 +9,7 @@ import * as os from '@/os.js'; import { instance } from '@/instance.js'; import { host } from '@@/js/config.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; function toolsMenuItems(): MenuItem[] { return [{ diff --git a/packages/frontend/src/ui/_common_/common.vue b/packages/frontend/src/ui/_common_/common.vue index e218cd8c62..a39a4ee86b 100644 --- a/packages/frontend/src/ui/_common_/common.vue +++ b/packages/frontend/src/ui/_common_/common.vue @@ -53,7 +53,7 @@ import { popups } from '@/os.js'; import { pendingApiRequestsCount } from '@/utility/misskey-api.js'; import { uploads } from '@/utility/upload.js'; import * as sound from '@/utility/sound.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { useStream } from '@/stream.js'; import { i18n } from '@/i18n.js'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue index 698e9d8d47..2fbc9ab4b3 100644 --- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue +++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue @@ -53,10 +53,11 @@ import { computed, defineAsyncComponent, toRef } from 'vue'; import { openInstanceMenu } from './common.js'; import * as os from '@/os.js'; import { navbarItemDef } from '@/navbar.js'; -import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js'; import { prefer } from '@/preferences.js'; import { i18n } from '@/i18n.js'; import { instance } from '@/instance.js'; +import { openAccountMenu as openAccountMenu_ } from '@/accounts.js'; +import { $i } from '@/i.js'; const menu = toRef(prefer.s, 'menu'); const otherMenuItemIndicated = computed(() => { diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue index 234972e76d..1810ec1743 100644 --- a/packages/frontend/src/ui/_common_/navbar.vue +++ b/packages/frontend/src/ui/_common_/navbar.vue @@ -93,13 +93,14 @@ import { computed, defineAsyncComponent, ref, watch } from 'vue'; import { openInstanceMenu } from './common.js'; import * as os from '@/os.js'; import { navbarItemDef } from '@/navbar.js'; -import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js'; import { store } from '@/store.js'; import { i18n } from '@/i18n.js'; import { instance } from '@/instance.js'; import { getHTMLElementOrNull } from '@/utility/get-dom-node-or-null.js'; import { useRouter } from '@/router/supplier.js'; import { prefer } from '@/preferences.js'; +import { openAccountMenu as openAccountMenu_ } from '@/accounts.js'; +import { $i } from '@/i.js'; const router = useRouter(); diff --git a/packages/frontend/src/ui/_common_/sw-inject.ts b/packages/frontend/src/ui/_common_/sw-inject.ts index df392c6532..ae61e497b5 100644 --- a/packages/frontend/src/ui/_common_/sw-inject.ts +++ b/packages/frontend/src/ui/_common_/sw-inject.ts @@ -5,10 +5,11 @@ import { post } from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { $i, login } from '@/account.js'; +import { $i } from '@/i.js'; import { getAccountFromId } from '@/utility/get-account-from-id.js'; import { deepClone } from '@/utility/clone.js'; import { mainRouter } from '@/router/main.js'; +import { login } from '@/accounts.js'; export function swInject() { navigator.serviceWorker.addEventListener('message', async ev => { diff --git a/packages/frontend/src/ui/classic.header.vue b/packages/frontend/src/ui/classic.header.vue index 39b40754ff..1e8a342977 100644 --- a/packages/frontend/src/ui/classic.header.vue +++ b/packages/frontend/src/ui/classic.header.vue @@ -51,12 +51,12 @@ import { computed, defineAsyncComponent, onMounted, ref } from 'vue'; import { openInstanceMenu } from './_common_/common.js'; import * as os from '@/os.js'; import { navbarItemDef } from '@/navbar.js'; -import { openAccountMenu as openAccountMenu_, $i } from '@/account.js'; import MkButton from '@/components/MkButton.vue'; -import { store } from '@/store.js'; import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; import { prefer } from '@/preferences.js'; +import { openAccountMenu as openAccountMenu_ } from '@/accounts.js'; +import { $i } from '@/i.js'; const WINDOW_THRESHOLD = 1400; diff --git a/packages/frontend/src/ui/classic.sidebar.vue b/packages/frontend/src/ui/classic.sidebar.vue index 259aad7401..096ea0d4cf 100644 --- a/packages/frontend/src/ui/classic.sidebar.vue +++ b/packages/frontend/src/ui/classic.sidebar.vue @@ -54,7 +54,6 @@ import { openInstanceMenu } from './_common_/common.js'; // import { host } from '@@/js/config.js'; import * as os from '@/os.js'; import { navbarItemDef } from '@/navbar.js'; -import { openAccountMenu as openAccountMenu_, $i } from '@/account.js'; import MkButton from '@/components/MkButton.vue'; // import { StickySidebar } from '@/utility/sticky-sidebar.js'; // import { mainRouter } from '@/router.js'; @@ -63,6 +62,8 @@ import { store } from '@/store.js'; import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; import { prefer } from '@/preferences.js'; +import { openAccountMenu as openAccountMenu_ } from '@/accounts.js'; +import { $i } from '@/i.js'; const WINDOW_THRESHOLD = 1400; diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index 337b0dac94..a5db4031e2 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -100,7 +100,7 @@ import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue'; import MkButton from '@/components/MkButton.vue'; import * as os from '@/os.js'; import { navbarItemDef } from '@/navbar.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import { deviceKind } from '@/utility/device-kind.js'; import { prefer } from '@/preferences.js'; diff --git a/packages/frontend/src/ui/universal.vue b/packages/frontend/src/ui/universal.vue index cb93b20c24..29248b2720 100644 --- a/packages/frontend/src/ui/universal.vue +++ b/packages/frontend/src/ui/universal.vue @@ -108,7 +108,7 @@ import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue'; import * as os from '@/os.js'; import { navbarItemDef } from '@/navbar.js'; import { i18n } from '@/i18n.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { provideMetadataReceiver, provideReactiveMetadata } from '@/page.js'; import { deviceKind } from '@/utility/device-kind.js'; import { miLocalStorage } from '@/local-storage.js'; diff --git a/packages/frontend/src/use/use-note-capture.ts b/packages/frontend/src/use/use-note-capture.ts index 0bc10e90e4..0de2dbb3c5 100644 --- a/packages/frontend/src/use/use-note-capture.ts +++ b/packages/frontend/src/use/use-note-capture.ts @@ -7,7 +7,7 @@ import { onUnmounted } from 'vue'; import type { Ref, ShallowRef } from 'vue'; import * as Misskey from 'misskey-js'; import { useStream } from '@/stream.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; export function useNoteCapture(props: { rootEl: ShallowRef<HTMLElement | undefined>; diff --git a/packages/frontend/src/utility/achievements.ts b/packages/frontend/src/utility/achievements.ts index 3025a985ba..f6ab587ae1 100644 --- a/packages/frontend/src/utility/achievements.ts +++ b/packages/frontend/src/utility/achievements.ts @@ -4,7 +4,7 @@ */ import { misskeyApi } from '@/utility/misskey-api.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; export const ACHIEVEMENT_TYPES = [ 'notes1', diff --git a/packages/frontend/src/utility/autogen/settings-search-index.ts b/packages/frontend/src/utility/autogen/settings-search-index.ts index ebc67eb58d..e768d8a5ae 100644 --- a/packages/frontend/src/utility/autogen/settings-search-index.ts +++ b/packages/frontend/src/utility/autogen/settings-search-index.ts @@ -814,6 +814,13 @@ export const searchIndexes: SearchIndexItem[] = [ path: '/settings/avatar-decoration', icon: 'ti ti-sparkles', }, + { + id: 'zK6posor9', + label: i18n.ts.accounts, + keywords: ['accounts'], + path: '/settings/accounts', + icon: 'ti ti-users', + }, { id: '330Q4mf8E', children: [ diff --git a/packages/frontend/src/utility/check-permissions.ts b/packages/frontend/src/utility/check-permissions.ts index ed86529d5b..2de8fd2cd1 100644 --- a/packages/frontend/src/utility/check-permissions.ts +++ b/packages/frontend/src/utility/check-permissions.ts @@ -4,7 +4,7 @@ */ import { instance } from '@/instance.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; export const notesSearchAvailable = ( // FIXME: instance.policies would be null in Vitest diff --git a/packages/frontend/src/utility/get-note-menu.ts b/packages/frontend/src/utility/get-note-menu.ts index 74eb326c4c..d2026de0b6 100644 --- a/packages/frontend/src/utility/get-note-menu.ts +++ b/packages/frontend/src/utility/get-note-menu.ts @@ -9,7 +9,7 @@ import { url } from '@@/js/config.js'; import { claimAchievement } from './achievements.js'; import type { Ref, ShallowRef } from 'vue'; import type { MenuItem } from '@/types/menu.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; import { instance } from '@/instance.js'; import * as os from '@/os.js'; diff --git a/packages/frontend/src/utility/get-user-menu.ts b/packages/frontend/src/utility/get-user-menu.ts index 1b9b0eac95..b89c7537e2 100644 --- a/packages/frontend/src/utility/get-user-menu.ts +++ b/packages/frontend/src/utility/get-user-menu.ts @@ -13,7 +13,7 @@ import { i18n } from '@/i18n.js'; import { copyToClipboard } from '@/utility/copy-to-clipboard.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; -import { $i, iAmModerator } from '@/account.js'; +import { $i, iAmModerator } from '@/i.js'; import { notesSearchAvailable, canSearchNonLocalNotes } from '@/utility/check-permissions.js'; import { antennasCache, rolesCache, userListsCache } from '@/cache.js'; import { mainRouter } from '@/router/main.js'; diff --git a/packages/frontend/src/utility/isFfVisibleForMe.ts b/packages/frontend/src/utility/isFfVisibleForMe.ts index e28e5725bc..48ef1c4e49 100644 --- a/packages/frontend/src/utility/isFfVisibleForMe.ts +++ b/packages/frontend/src/utility/isFfVisibleForMe.ts @@ -4,7 +4,7 @@ */ import * as Misskey from 'misskey-js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; export function isFollowingVisibleForMe(user: Misskey.entities.UserDetailed): boolean { if ($i && ($i.id === user.id || $i.isAdmin || $i.isModerator)) return true; diff --git a/packages/frontend/src/utility/misskey-api.ts b/packages/frontend/src/utility/misskey-api.ts index dc07ad477b..72ba54ade3 100644 --- a/packages/frontend/src/utility/misskey-api.ts +++ b/packages/frontend/src/utility/misskey-api.ts @@ -6,7 +6,7 @@ import * as Misskey from 'misskey-js'; import { ref } from 'vue'; import { apiUrl } from '@@/js/config.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; export const pendingApiRequestsCount = ref(0); export type Endpoint = keyof Misskey.Endpoints; diff --git a/packages/frontend/src/utility/please-login.ts b/packages/frontend/src/utility/please-login.ts index a8a330eb6d..9253105f48 100644 --- a/packages/frontend/src/utility/please-login.ts +++ b/packages/frontend/src/utility/please-login.ts @@ -4,7 +4,7 @@ */ import { defineAsyncComponent } from 'vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; import { popup } from '@/os.js'; diff --git a/packages/frontend/src/utility/show-moved-dialog.ts b/packages/frontend/src/utility/show-moved-dialog.ts index 35b3ef79d8..db21b028cd 100644 --- a/packages/frontend/src/utility/show-moved-dialog.ts +++ b/packages/frontend/src/utility/show-moved-dialog.ts @@ -4,7 +4,7 @@ */ import * as os from '@/os.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; export function showMovedDialog() { diff --git a/packages/frontend/src/utility/upload.ts b/packages/frontend/src/utility/upload.ts index d105a318a7..eb3cbd3dfa 100644 --- a/packages/frontend/src/utility/upload.ts +++ b/packages/frontend/src/utility/upload.ts @@ -9,7 +9,7 @@ import { v4 as uuid } from 'uuid'; import { readAndCompressImage } from '@misskey-dev/browser-image-resizer'; import { apiUrl } from '@@/js/config.js'; import { getCompressionConfig } from './upload/compress-config.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { alert } from '@/os.js'; import { i18n } from '@/i18n.js'; import { instance } from '@/instance.js'; diff --git a/packages/frontend/src/widgets/WidgetActivity.vue b/packages/frontend/src/widgets/WidgetActivity.vue index d911e71ab2..db03d1406c 100644 --- a/packages/frontend/src/widgets/WidgetActivity.vue +++ b/packages/frontend/src/widgets/WidgetActivity.vue @@ -28,7 +28,7 @@ import XChart from './WidgetActivity.chart.vue'; import type { GetFormResultType } from '@/utility/form.js'; import { misskeyApiGet } from '@/utility/misskey-api.js'; import MkContainer from '@/components/MkContainer.vue'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; const name = 'activity'; diff --git a/packages/frontend/src/widgets/WidgetAiscript.vue b/packages/frontend/src/widgets/WidgetAiscript.vue index b49041158f..c46fd81466 100644 --- a/packages/frontend/src/widgets/WidgetAiscript.vue +++ b/packages/frontend/src/widgets/WidgetAiscript.vue @@ -27,7 +27,7 @@ import type { GetFormResultType } from '@/utility/form.js'; import * as os from '@/os.js'; import MkContainer from '@/components/MkContainer.vue'; import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { i18n } from '@/i18n.js'; const name = 'aiscript'; diff --git a/packages/frontend/src/widgets/WidgetAiscriptApp.vue b/packages/frontend/src/widgets/WidgetAiscriptApp.vue index fb9dea1847..429b0e0ffb 100644 --- a/packages/frontend/src/widgets/WidgetAiscriptApp.vue +++ b/packages/frontend/src/widgets/WidgetAiscriptApp.vue @@ -21,7 +21,7 @@ import type { WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps import type { GetFormResultType } from '@/utility/form.js'; import * as os from '@/os.js'; import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import MkAsUi from '@/components/MkAsUi.vue'; import MkContainer from '@/components/MkContainer.vue'; import { registerAsUiLib } from '@/aiscript/ui.js'; diff --git a/packages/frontend/src/widgets/WidgetBirthdayFollowings.vue b/packages/frontend/src/widgets/WidgetBirthdayFollowings.vue index 8c7507ef44..be11a26917 100644 --- a/packages/frontend/src/widgets/WidgetBirthdayFollowings.vue +++ b/packages/frontend/src/widgets/WidgetBirthdayFollowings.vue @@ -33,7 +33,7 @@ import MkContainer from '@/components/MkContainer.vue'; import { misskeyApi } from '@/utility/misskey-api.js'; import { i18n } from '@/i18n.js'; import { infoImageUrl } from '@/instance.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; const name = i18n.ts._widgets.birthdayFollowings; diff --git a/packages/frontend/src/widgets/WidgetButton.vue b/packages/frontend/src/widgets/WidgetButton.vue index 3f0f9eb9fd..4afe735a22 100644 --- a/packages/frontend/src/widgets/WidgetButton.vue +++ b/packages/frontend/src/widgets/WidgetButton.vue @@ -18,7 +18,7 @@ import type { WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps import type { GetFormResultType } from '@/utility/form.js'; import * as os from '@/os.js'; import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import MkButton from '@/components/MkButton.vue'; const name = 'button'; diff --git a/packages/frontend/src/widgets/WidgetProfile.vue b/packages/frontend/src/widgets/WidgetProfile.vue index c86d1c9653..3fe8378a39 100644 --- a/packages/frontend/src/widgets/WidgetProfile.vue +++ b/packages/frontend/src/widgets/WidgetProfile.vue @@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only import { useWidgetPropsManager } from './widget.js'; import type { WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js'; import type { GetFormResultType } from '@/utility/form.js'; -import { $i } from '@/account.js'; +import { $i } from '@/i.js'; import { userPage } from '@/filters/user.js'; const name = 'profile'; diff --git a/packages/frontend/test/aiscript/api.test.ts b/packages/frontend/test/aiscript/api.test.ts index a569c0fa51..36838af163 100644 --- a/packages/frontend/test/aiscript/api.test.ts +++ b/packages/frontend/test/aiscript/api.test.ts @@ -33,7 +33,7 @@ async function exe(script: string): Promise<values.Value[]> { return outputs; } -let $iMock = vi.hoisted<Partial<typeof import('@/account.js').$i> | null >( +let $iMock = vi.hoisted<Partial<typeof import('@/i.js').$i> | null >( () => null );