diff --git a/packages/frontend-embed/src/_bootloader.ts b/packages/frontend-embed/src/_bootloader.ts
index 420ce43685..e7b3c2299b 100644
--- a/packages/frontend-embed/src/_bootloader.ts
+++ b/packages/frontend-embed/src/_bootloader.ts
@@ -5,22 +5,24 @@
'use strict';
+import { addStyle, bootloaderLocales, detectLanguage } from '@@/js/bootloader';
+
interface Window {
CLIENT_ENTRY: string | undefined;
}
// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので
(async () => {
- window.onerror = (e) => {
- console.error(e);
+ window.onerror = (error) => {
+ console.error(error);
renderError('SOMETHING_HAPPENED');
};
- window.onunhandledrejection = (e) => {
- console.error(e);
+ window.onunhandledrejection = (error) => {
+ console.error(error);
renderError('SOMETHING_HAPPENED_IN_PROMISE');
};
- let forceError = localStorage.getItem('forceError');
+ const forceError = localStorage.getItem('forceError');
if (forceError != null) {
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.');
return;
@@ -35,33 +37,13 @@ interface Window {
document.documentElement.classList.add('noborder');
}
- //#region Detect language & fetch translations
- const supportedLangs = _LANG_IDS_;
- /** @type { string } */
- let lang = localStorage.getItem('lang');
- if (lang == null || !supportedLangs.includes(lang)) {
- if (supportedLangs.includes(navigator.language)) {
- lang = navigator.language;
- } else {
- lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
-
- // Fallback
- if (lang == null) lang = 'en-US';
- }
- }
-
- // for https://github.com/misskey-dev/misskey/issues/10202
- if (lang == null || lang.toString == null || lang.toString() === 'null') {
- console.error('invalid lang value detected!!!', typeof lang, lang);
- lang = 'en-US';
- }
- //#endregion
+ const lang = detectLanguage();
//#region Script
async function importAppScript() {
await import(`/embed_vite/${(window.CLIENT_ENTRY ?? 'src/boot.ts').replace('scripts', lang)}`)
- .catch(async e => {
- console.error(e);
+ .catch(async error => {
+ console.error(error);
renderError('APP_IMPORT');
});
}
@@ -76,44 +58,19 @@ interface Window {
}
//#endregion
- async function addStyle(styleText) {
- let css = document.createElement('style');
- css.appendChild(document.createTextNode(styleText));
- document.head.appendChild(css);
- }
-
- async function renderError(code) {
+ async function renderError(code: string, _details?) {
// Cannot set property 'innerHTML' of null を回避
if (document.readyState === 'loading') {
await new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve));
}
- let messages = null;
- const bootloaderLocales = localStorage.getItem('bootloaderLocales');
- if (bootloaderLocales) {
- messages = JSON.parse(bootloaderLocales);
- }
- if (!messages) {
- // older version of misskey does not store bootloaderLocales, stores locale as a whole
- const legacyLocale = localStorage.getItem('locale');
- if (legacyLocale) {
- const parsed = JSON.parse(legacyLocale);
- messages = {
- ...(parsed._bootErrors ?? {}),
- reload: parsed.reload,
- };
- }
- }
- if (!messages) messages = {};
-
- const title = messages?.title || 'Failed to initialize Misskey';
- const reload = messages?.reload || 'Reload';
+ const messages = bootloaderLocales();
document.body.innerHTML = `
-
${title}
+ ${messages.title}
Error Code: ${code}
`;
addStyle(`
#misskey_app,
diff --git a/packages/frontend-shared/@types/global.d.ts b/packages/frontend-shared/@types/global.d.ts
index 52081d07b3..83011e7557 100644
--- a/packages/frontend-shared/@types/global.d.ts
+++ b/packages/frontend-shared/@types/global.d.ts
@@ -7,6 +7,7 @@
type FIXME = any;
declare const _LANGS_: string[][];
+declare const _LANG_IDS_: string[];
declare const _VERSION_: string;
declare const _ENV_: string;
declare const _DEV_: boolean;
diff --git a/packages/frontend-shared/js/bootloader.ts b/packages/frontend-shared/js/bootloader.ts
new file mode 100644
index 0000000000..792023f03f
--- /dev/null
+++ b/packages/frontend-shared/js/bootloader.ts
@@ -0,0 +1,74 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+// common portion of bootloader for frontend and frontend-embed
+
+import type { Locale } from '../../../locales/index.js';
+
+export function detectLanguage(): string {
+ const supportedLangs = _LANG_IDS_;
+ let lang: string | null | undefined = localStorage.getItem('lang');
+ if (lang == null || !supportedLangs.includes(lang)) {
+ if (supportedLangs.includes(navigator.language)) {
+ lang = navigator.language;
+ } else {
+ lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
+
+ // Fallback
+ lang ??= 'en-US';
+ }
+ }
+
+ // for https://github.com/misskey-dev/misskey/issues/10202
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (lang == null || lang.toString == null || lang.toString() === 'null') {
+ console.error('invalid lang value detected!!!', typeof lang, lang);
+ lang = 'en-US';
+ }
+
+ return lang;
+}
+
+type BootLoaderLocales = Locale['_bootErrors'] & Pick;
+
+export function bootloaderLocales(): BootLoaderLocales {
+ let messages: Partial | null = null;
+ const bootloaderLocalesJson = localStorage.getItem('bootloaderLocales');
+ if (bootloaderLocalesJson) {
+ messages = JSON.parse(bootloaderLocalesJson);
+ }
+ if (!messages) {
+ // older version of misskey does not store bootloaderLocales, stores locale as a whole
+ const legacyLocale = localStorage.getItem('locale');
+ if (legacyLocale) {
+ const parsed = JSON.parse(legacyLocale);
+ messages = {
+ ...(parsed._bootErrors ?? {}),
+ reload: parsed.reload,
+ };
+ }
+ }
+
+ return Object.assign({
+ title: 'Failed to initialize Misskey',
+ solution: 'The following actions may solve the problem.',
+ solution1: 'Update your os and browser',
+ solution2: 'Disable an adblocker',
+ solution3: 'Clear the browser cache',
+ solution4: '(Tor Browser) Set dom.webaudio.enabled to true',
+ otherOption: 'Other options',
+ otherOption1: 'Clear preferences and cache',
+ otherOption2: 'Start the simple client',
+ otherOption3: 'Start the repair tool',
+ otherOption4: 'Start Misskey in safe mode',
+ reload: 'Reload',
+ }, messages) as BootLoaderLocales;
+}
+
+export function addStyle(styleText: string) {
+ const styleElement = document.createElement('style');
+ styleElement.appendChild(document.createTextNode(styleText));
+ document.head.appendChild(styleElement);
+}
diff --git a/packages/frontend/src/_bootloader.ts b/packages/frontend/src/_bootloader.ts
index 75d53e0bdd..839e3b22bf 100644
--- a/packages/frontend/src/_bootloader.ts
+++ b/packages/frontend/src/_bootloader.ts
@@ -3,8 +3,12 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
+/* eslint no-restricted-globals: off */
+
'use strict';
+import { addStyle, bootloaderLocales, detectLanguage } from '@@/js/bootloader';
+
interface Window {
CLIENT_ENTRY: string | undefined;
}
@@ -13,42 +17,22 @@ interface Window {
(async () => {
const CLIENT_ENTRY = window.CLIENT_ENTRY;
- window.onerror = (e) => {
- console.error(e);
- renderError('SOMETHING_HAPPENED', e);
+ window.onerror = (error) => {
+ console.error(error);
+ renderError('SOMETHING_HAPPENED', error);
};
- window.onunhandledrejection = (e) => {
- console.error(e);
- renderError('SOMETHING_HAPPENED_IN_PROMISE', e);
+ window.onunhandledrejection = (error) => {
+ console.error(error);
+ renderError('SOMETHING_HAPPENED_IN_PROMISE', error);
};
- let forceError = localStorage.getItem('forceError');
+ const forceError = localStorage.getItem('forceError');
if (forceError != null) {
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.');
return;
}
- //#region Detect language
- const supportedLangs = _LANG_IDS_;
- /** @type { string } */
- let lang = localStorage.getItem('lang');
- if (lang == null || !supportedLangs.includes(lang)) {
- if (supportedLangs.includes(navigator.language)) {
- lang = navigator.language;
- } else {
- lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
-
- // Fallback
- if (lang == null) lang = 'en-US';
- }
- }
-
- // for https://github.com/misskey-dev/misskey/issues/10202
- if (lang == null || lang.toString == null || lang.toString() === 'null') {
- console.error('invalid lang value detected!!!', typeof lang, lang);
- lang = 'en-US';
- }
- //#endregion
+ const lang = detectLanguage();
//#region Script
async function importAppScript() {
@@ -84,7 +68,7 @@ interface Window {
if (!isSafeMode) {
const theme = localStorage.getItem('theme');
if (theme) {
- for (const [k, v] of Object.entries(JSON.parse(theme))) {
+ for (const [k, v] of Object.entries(JSON.parse(theme) as Record)) {
document.documentElement.style.setProperty(`--MI_THEME-${k}`, v.toString());
// HTMLの theme-color 適用
@@ -125,50 +109,13 @@ interface Window {
}
}
- async function addStyle(styleText) {
- let css = document.createElement('style');
- css.appendChild(document.createTextNode(styleText));
- document.head.appendChild(css);
- }
-
async function renderError(code, details) {
// Cannot set property 'innerHTML' of null を回避
if (document.readyState === 'loading') {
await new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve));
}
- let messages = null;
- const bootloaderLocales = localStorage.getItem('bootloaderLocales');
- if (bootloaderLocales) {
- messages = JSON.parse(bootloaderLocales);
- }
- if (!messages) {
- // older version of misskey does not store bootloaderLocales, stores locale as a whole
- const legacyLocale = localStorage.getItem('locale');
- if (legacyLocale) {
- const parsed = JSON.parse(legacyLocale);
- messages = {
- ...(parsed._bootErrors ?? {}),
- reload: parsed.reload,
- };
- }
- }
- if (!messages) messages = {};
-
- messages = Object.assign({
- title: 'Failed to initialize Misskey',
- solution: 'The following actions may solve the problem.',
- solution1: 'Update your os and browser',
- solution2: 'Disable an adblocker',
- solution3: 'Clear the browser cache',
- solution4: '(Tor Browser) Set dom.webaudio.enabled to true',
- otherOption: 'Other options',
- otherOption1: 'Clear preferences and cache',
- otherOption2: 'Start the simple client',
- otherOption3: 'Start the repair tool',
- otherOption4: 'Start Misskey in safe mode',
- reload: 'Reload',
- }, messages);
+ const messages = bootloaderLocales();
const safeModeUrl = new URL(window.location.href);
safeModeUrl.searchParams.set('safemode', 'true');
@@ -220,7 +167,7 @@ interface Window {
`;
- errorsElement = document.getElementById('errors');
+ errorsElement = document.getElementById('errors')!;
}
const detailsElement = document.createElement('details');
detailsElement.id = 'errorInfo';