misskey/packages/frontend/src/embed/init.ts

154 lines
4.3 KiB
TypeScript

import JSON5 from 'json5';
import { miLocalStorage } from '@/local-storage';
import { version, lang, updateLocale, url } from '@/config';
import { embedInitI18n } from './scripts/embed-i18n';
import '@/style.scss';
import './embed.scss';
import 'iframe-resizer/js/iframeResizer.contentWindow';
import { embedInitLinkAnime } from './scripts/link-anime';
import { parseMfm } from './scripts/parse-mfm';
import { renderNotFound } from './scripts/render-not-found';
import { parseEmoji } from './scripts/parse-emoji';
import { applyTheme } from './scripts/theme';
import lightTheme from '@/themes/_light.json5';
import darkTheme from '@/themes/_dark.json5';
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode';
console.info(`Misskey (Embed Sandbox) v${version}`);
const supportedEmbedEntity: string[] = [
'notes'
];
if (_DEV_) {
console.warn('Development mode!!!');
window.addEventListener('error', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled error',
text: event.message
});
*/
});
window.addEventListener('unhandledrejection', event => {
console.error(event);
/*
alert({
type: 'error',
title: 'DEV: Unhandled promise rejection',
text: event.reason
});
*/
});
}
//#region Detect language & fetch translations
const localeVersion = miLocalStorage.getItem('localeVersion');
const localeOutdated = (localeVersion == null || localeVersion !== version);
if (localeOutdated) {
const res = await window.fetch(`/assets/locales/${lang}.${version}.json`);
if (res.status === 200) {
const newLocale = await res.text();
const parsedNewLocale = JSON.parse(newLocale);
miLocalStorage.setItem('locale', newLocale);
miLocalStorage.setItem('localeVersion', version);
updateLocale(parsedNewLocale);
embedInitI18n();
}
}
//#endregion
// タッチデバイスでCSSの:hoverを機能させる
document.addEventListener('touchend', () => {}, { passive: true });
//#region Set lang attr
const html = document.documentElement;
html.setAttribute('lang', lang);
//#endregion
//#region ページのパスをパース
// パス構造: /{entityName}/{id}/embed
const path = location.pathname;
if (!path.includes('/embed')) {
location.href = url;
throw new Error('Embed script was loaded on non-embed page. Force redirect to the top page.');
}
const pageMetaValues:string[] = path.split('/').filter((e) => e != '' && e != 'embed');
const pageMeta: { entityName: string; id: string; } = {
entityName: pageMetaValues[0],
id: pageMetaValues[1],
};
const URLParams = new URLSearchParams(location.search);
const enableAnimatedMfm = URLParams.get("mfm") === 'animated';
const disableRootRound = URLParams.get("rounded") === "0";
//#endregion
const rootEl = document.getElementById("container");
if (disableRootRound && rootEl) {
rootEl.style.borderRadius = "0";
}
//#region テーマ適用
const themePreferences = localStorage.getItem('theme');
const getTheme = async () => {
// テーマが指定されている場合
if (URLParams.has("theme")) {
switch (URLParams.get("theme")) {
case 'light':
return lightTheme;
case 'dark':
return darkTheme;
default:
return await import(`../themes/${URLParams.get("theme")}.json5`).catch((_) => {
return isDeviceDarkmode() ? darkTheme : lightTheme;
});
}
} else {
return isDeviceDarkmode() ? darkTheme : lightTheme;
}
};
if (!themePreferences || URLParams.has("theme")) {
applyTheme(await getTheme(), false);
}
//#endregion
//埋め込みページごとのスクリプト読み込み
if (!supportedEmbedEntity.includes(pageMeta.entityName)) {
renderNotFound();
afterPageInitialization();
} else {
import(`./pages/${pageMeta.entityName}.ts`).then(() => {
afterPageInitialization();
});
}
function afterPageInitialization() {
embedInitI18n();
//@ts-ignore
document.querySelectorAll(".mfm").forEach((e: HTMLElement) => {
e.innerHTML = parseMfm(e.innerText, enableAnimatedMfm).outerHTML;
});
parseEmoji();
//#region ロード画面解除
const splash = document.getElementById('splash');
// 念のためnullチェック(HTMLが古い場合があるため(そのうち消す))
if (splash) splash.addEventListener('transitionend', () => {
splash.remove();
});
if (splash) {
splash.style.opacity = '0';
splash.style.pointerEvents = 'none';
}
//#endregion
embedInitLinkAnime();
}