embedのstoreでの変更が外部タブに影響しないように・されないように
This commit is contained in:
parent
e5415812e6
commit
6a7ed7e0d1
|
@ -32,6 +32,8 @@
|
||||||
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.')
|
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isEmbedPage = document.documentElement.classList.contains('embed');
|
||||||
|
|
||||||
//#region Detect language & fetch translations
|
//#region Detect language & fetch translations
|
||||||
if (!localStorage.hasOwnProperty('locale')) {
|
if (!localStorage.hasOwnProperty('locale')) {
|
||||||
const supportedLangs = LANGS;
|
const supportedLangs = LANGS;
|
||||||
|
@ -104,49 +106,51 @@
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Theme
|
if (!isEmbedPage) {
|
||||||
const theme = localStorage.getItem('theme');
|
//#region Theme
|
||||||
if (theme) {
|
const theme = localStorage.getItem('theme');
|
||||||
for (const [k, v] of Object.entries(JSON.parse(theme))) {
|
if (theme) {
|
||||||
document.documentElement.style.setProperty(`--${k}`, v.toString());
|
for (const [k, v] of Object.entries(JSON.parse(theme))) {
|
||||||
|
document.documentElement.style.setProperty(`--${k}`, v.toString());
|
||||||
|
|
||||||
// HTMLの theme-color 適用
|
// HTMLの theme-color 適用
|
||||||
if (k === 'htmlThemeColor') {
|
if (k === 'htmlThemeColor') {
|
||||||
for (const tag of document.head.children) {
|
for (const tag of document.head.children) {
|
||||||
if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
|
if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
|
||||||
tag.setAttribute('content', v);
|
tag.setAttribute('content', v);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
const colorScheme = localStorage.getItem('colorScheme');
|
||||||
const colorScheme = localStorage.getItem('colorScheme');
|
if (colorScheme) {
|
||||||
if (colorScheme) {
|
document.documentElement.style.setProperty('color-scheme', colorScheme);
|
||||||
document.documentElement.style.setProperty('color-scheme', colorScheme);
|
}
|
||||||
}
|
//#endregion
|
||||||
//#endregion
|
|
||||||
|
|
||||||
const fontSize = localStorage.getItem('fontSize');
|
const fontSize = localStorage.getItem('fontSize');
|
||||||
if (fontSize) {
|
if (fontSize) {
|
||||||
document.documentElement.classList.add('f-' + fontSize);
|
document.documentElement.classList.add('f-' + fontSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
const useSystemFont = localStorage.getItem('useSystemFont');
|
const useSystemFont = localStorage.getItem('useSystemFont');
|
||||||
if (useSystemFont) {
|
if (useSystemFont) {
|
||||||
document.documentElement.classList.add('useSystemFont');
|
document.documentElement.classList.add('useSystemFont');
|
||||||
}
|
}
|
||||||
|
|
||||||
const wallpaper = localStorage.getItem('wallpaper');
|
const wallpaper = localStorage.getItem('wallpaper');
|
||||||
if (wallpaper) {
|
if (wallpaper) {
|
||||||
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
|
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const customCss = localStorage.getItem('customCss');
|
const customCss = localStorage.getItem('customCss');
|
||||||
if (customCss && customCss.length > 0) {
|
if (customCss && customCss.length > 0) {
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
style.innerHTML = customCss;
|
style.innerHTML = customCss;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addStyle(styleText) {
|
async function addStyle(styleText) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import '@/style.embed.scss';
|
||||||
import type { CommonBootOptions } from '@/boot/common.js';
|
import type { CommonBootOptions } from '@/boot/common.js';
|
||||||
import { subBoot } from '@/boot/sub-boot.js';
|
import { subBoot } from '@/boot/sub-boot.js';
|
||||||
import { setIframeId, postMessageToParentWindow } from '@/scripts/post-message.js';
|
import { setIframeId, postMessageToParentWindow } from '@/scripts/post-message.js';
|
||||||
|
import { defaultStore } from '@/store.js';
|
||||||
|
|
||||||
const bootOptions: Partial<CommonBootOptions> = {};
|
const bootOptions: Partial<CommonBootOptions> = {};
|
||||||
|
|
||||||
|
@ -21,6 +22,11 @@ if (color && ['light', 'dark'].includes(color)) {
|
||||||
bootOptions.forceColorMode = color as 'light' | 'dark';
|
bootOptions.forceColorMode = color as 'light' | 'dark';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 外部タブでのstoreの変更の影響を受けないように
|
||||||
|
defaultStore.setConfig({
|
||||||
|
disableMessageChannel: true,
|
||||||
|
});
|
||||||
|
|
||||||
// iframeIdの設定
|
// iframeIdの設定
|
||||||
window.addEventListener('message', event => {
|
window.addEventListener('message', event => {
|
||||||
if (event.data?.type === 'misskey:embedParent:registerIframeId' && event.data.payload?.iframeId != null) {
|
if (event.data?.type === 'misskey:embedParent:registerIframeId' && event.data.payload?.iframeId != null) {
|
||||||
|
|
|
@ -32,6 +32,10 @@ type PizzaxChannelMessage<T extends StateDef> = {
|
||||||
userId?: string;
|
userId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PizzaxConfig = {
|
||||||
|
disableMessageChannel: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export class Storage<T extends StateDef> {
|
export class Storage<T extends StateDef> {
|
||||||
public readonly ready: Promise<void>;
|
public readonly ready: Promise<void>;
|
||||||
public readonly loaded: Promise<void>;
|
public readonly loaded: Promise<void>;
|
||||||
|
@ -47,6 +51,10 @@ export class Storage<T extends StateDef> {
|
||||||
public readonly state: State<T>;
|
public readonly state: State<T>;
|
||||||
public readonly reactiveState: ReactiveState<T>;
|
public readonly reactiveState: ReactiveState<T>;
|
||||||
|
|
||||||
|
private options: PizzaxConfig = {
|
||||||
|
disableMessageChannel: false,
|
||||||
|
};
|
||||||
|
|
||||||
private pizzaxChannel: BroadcastChannel<PizzaxChannelMessage<T>>;
|
private pizzaxChannel: BroadcastChannel<PizzaxChannelMessage<T>>;
|
||||||
|
|
||||||
// 簡易的にキューイングして占有ロックとする
|
// 簡易的にキューイングして占有ロックとする
|
||||||
|
@ -60,12 +68,13 @@ export class Storage<T extends StateDef> {
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(key: string, def: T) {
|
constructor(key: string, def: T, options?: Partial<PizzaxConfig>) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.deviceStateKeyName = `pizzax::${key}`;
|
this.deviceStateKeyName = `pizzax::${key}`;
|
||||||
this.deviceAccountStateKeyName = $i ? `pizzax::${key}::${$i.id}` : '';
|
this.deviceAccountStateKeyName = $i ? `pizzax::${key}::${$i.id}` : '';
|
||||||
this.registryCacheKeyName = $i ? `pizzax::${key}::cache::${$i.id}` : '';
|
this.registryCacheKeyName = $i ? `pizzax::${key}::cache::${$i.id}` : '';
|
||||||
this.def = def;
|
this.def = def;
|
||||||
|
this.options = Object.assign(this.options, options);
|
||||||
|
|
||||||
this.pizzaxChannel = new BroadcastChannel(`pizzax::${key}`);
|
this.pizzaxChannel = new BroadcastChannel(`pizzax::${key}`);
|
||||||
|
|
||||||
|
@ -119,7 +128,7 @@ export class Storage<T extends StateDef> {
|
||||||
this.pizzaxChannel.addEventListener('message', ({ where, key, value, userId }) => {
|
this.pizzaxChannel.addEventListener('message', ({ where, key, value, userId }) => {
|
||||||
// アカウント変更すればunisonReloadが効くため、このreturnが発火することは
|
// アカウント変更すればunisonReloadが効くため、このreturnが発火することは
|
||||||
// まずないと思うけど一応弾いておく
|
// まずないと思うけど一応弾いておく
|
||||||
if (where === 'deviceAccount' && !($i && userId !== $i.id)) return;
|
if ((where === 'deviceAccount' && !($i && userId !== $i.id) || this.options.disableMessageChannel)) return;
|
||||||
this.reactiveState[key].value = this.state[key] = value;
|
this.reactiveState[key].value = this.state[key] = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -174,6 +183,10 @@ export class Storage<T extends StateDef> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setConfig(config: Partial<PizzaxConfig>) {
|
||||||
|
this.options = Object.assign(this.options, config);
|
||||||
|
}
|
||||||
|
|
||||||
public set<K extends keyof T>(key: K, value: T[K]['default']): Promise<void> {
|
public set<K extends keyof T>(key: K, value: T[K]['default']): Promise<void> {
|
||||||
// IndexedDBやBroadcastChannelで扱うために単純なオブジェクトにする
|
// IndexedDBやBroadcastChannelで扱うために単純なオブジェクトにする
|
||||||
// (JSON.parse(JSON.stringify(value))の代わり)
|
// (JSON.parse(JSON.stringify(value))の代わり)
|
||||||
|
@ -187,11 +200,13 @@ export class Storage<T extends StateDef> {
|
||||||
if (_DEV_) console.log(`set ${String(key)} start`);
|
if (_DEV_) console.log(`set ${String(key)} start`);
|
||||||
switch (this.def[key].where) {
|
switch (this.def[key].where) {
|
||||||
case 'device': {
|
case 'device': {
|
||||||
this.pizzaxChannel.postMessage({
|
if (!this.options.disableMessageChannel) {
|
||||||
where: 'device',
|
this.pizzaxChannel.postMessage({
|
||||||
key,
|
where: 'device',
|
||||||
value: rawValue,
|
key,
|
||||||
});
|
value: rawValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
const deviceState = await get(this.deviceStateKeyName) || {};
|
const deviceState = await get(this.deviceStateKeyName) || {};
|
||||||
deviceState[key] = rawValue;
|
deviceState[key] = rawValue;
|
||||||
await set(this.deviceStateKeyName, deviceState);
|
await set(this.deviceStateKeyName, deviceState);
|
||||||
|
@ -199,12 +214,14 @@ export class Storage<T extends StateDef> {
|
||||||
}
|
}
|
||||||
case 'deviceAccount': {
|
case 'deviceAccount': {
|
||||||
if ($i == null) break;
|
if ($i == null) break;
|
||||||
this.pizzaxChannel.postMessage({
|
if (!this.options.disableMessageChannel) {
|
||||||
where: 'deviceAccount',
|
this.pizzaxChannel.postMessage({
|
||||||
key,
|
where: 'deviceAccount',
|
||||||
value: rawValue,
|
key,
|
||||||
userId: $i.id,
|
value: rawValue,
|
||||||
});
|
userId: $i.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
const deviceAccountState = await get(this.deviceAccountStateKeyName) || {};
|
const deviceAccountState = await get(this.deviceAccountStateKeyName) || {};
|
||||||
deviceAccountState[key] = rawValue;
|
deviceAccountState[key] = rawValue;
|
||||||
await set(this.deviceAccountStateKeyName, deviceAccountState);
|
await set(this.deviceAccountStateKeyName, deviceAccountState);
|
||||||
|
|
Loading…
Reference in New Issue