2023-07-07 19:22:30 +00:00
|
|
|
/**
|
|
|
|
* Client entry point
|
|
|
|
*/
|
|
|
|
|
|
|
|
// https://vitejs.dev/config/build-options.html#build-modulepreload
|
|
|
|
import "vite/modulepreload-polyfill";
|
|
|
|
|
|
|
|
import "@/style.scss";
|
|
|
|
import "@phosphor-icons/web/bold";
|
|
|
|
import "@phosphor-icons/web/fill";
|
|
|
|
|
|
|
|
//#region account indexedDB migration
|
|
|
|
import { set } from "@/scripts/idb-proxy";
|
|
|
|
import {
|
2023-12-24 22:46:36 +00:00
|
|
|
App,
|
2023-07-23 13:31:28 +00:00
|
|
|
computed,
|
|
|
|
createApp,
|
2023-11-05 19:31:50 +00:00
|
|
|
defineAsyncComponent,
|
2023-07-23 13:31:28 +00:00
|
|
|
markRaw,
|
|
|
|
version as vueVersion,
|
2023-11-05 19:31:50 +00:00
|
|
|
watch,
|
2023-07-07 19:22:30 +00:00
|
|
|
} from "vue";
|
|
|
|
import { compareVersions } from "compare-versions";
|
|
|
|
|
|
|
|
import widgets from "@/widgets";
|
|
|
|
import directives from "@/directives";
|
2023-11-05 19:31:50 +00:00
|
|
|
import { lang, ui, version } from "@/config";
|
2023-07-07 19:22:30 +00:00
|
|
|
import { applyTheme } from "@/scripts/theme";
|
|
|
|
import { isDeviceDarkmode } from "@/scripts/is-device-darkmode";
|
|
|
|
import { i18n } from "@/i18n";
|
2023-11-05 19:31:50 +00:00
|
|
|
import { alert, confirm, popup, post, toast } from "@/os";
|
2023-07-07 19:22:30 +00:00
|
|
|
import { stream } from "@/stream";
|
|
|
|
import * as sound from "@/scripts/sound";
|
2023-11-05 19:31:50 +00:00
|
|
|
import { $i, login, refreshAccount, signout, updateAccount } from "@/account";
|
|
|
|
import { ColdDeviceStorage, defaultStore } from "@/store";
|
2023-07-07 19:22:30 +00:00
|
|
|
import { fetchInstance, instance } from "@/instance";
|
|
|
|
import { makeHotkey } from "@/scripts/hotkey";
|
|
|
|
import { search } from "@/scripts/search";
|
|
|
|
import { deviceKind } from "@/scripts/device-kind";
|
|
|
|
import { initializeSw } from "@/scripts/initialize-sw";
|
|
|
|
import { reloadChannel } from "@/scripts/unison-reload";
|
|
|
|
import { reactionPicker } from "@/scripts/reaction-picker";
|
|
|
|
import { getUrlWithoutLoginId } from "@/scripts/login-id";
|
|
|
|
import { getAccountFromId } from "@/scripts/get-account-from-id";
|
|
|
|
|
2023-11-07 02:11:22 +00:00
|
|
|
import Mfm from "./components/global/MkMisskeyFlavoredMarkdown.vue";
|
|
|
|
import MkA from "./components/global/MkA.vue";
|
|
|
|
import MkAcct from "./components/global/MkAcct.vue";
|
2023-12-27 23:34:52 +00:00
|
|
|
import MagAvatar from "./components/global/MagAvatar.vue";
|
|
|
|
import MagAvatarResolvingProxy from "./components/global/MagAvatarResolvingProxy.vue";
|
2023-11-07 02:11:22 +00:00
|
|
|
import MagEmoji from "./components/global/MagEmoji.vue";
|
|
|
|
import MkUserName from "./components/global/MkUserName.vue";
|
|
|
|
import MkEllipsis from "./components/global/MkEllipsis.vue";
|
|
|
|
import MkTime from "./components/global/MkTime.vue";
|
|
|
|
import MkUrl from "./components/global/MkUrl.vue";
|
|
|
|
import I18n from "./components/global/i18n";
|
|
|
|
import RouterView from "./components/global/RouterView.vue";
|
|
|
|
import MkLoading from "./components/global/MkLoading.vue";
|
|
|
|
import MkError from "./components/global/MkError.vue";
|
|
|
|
import MkPageHeader from "./components/global/MkPageHeader.vue";
|
|
|
|
import MkSpacer from "./components/global/MkSpacer.vue";
|
|
|
|
import MkStickyContainer from "./components/global/MkStickyContainer.vue";
|
|
|
|
|
|
|
|
function globalComponents(app: App) {
|
|
|
|
app.component("I18n", I18n);
|
|
|
|
app.component("RouterView", RouterView);
|
|
|
|
app.component("Mfm", Mfm);
|
|
|
|
app.component("MkA", MkA);
|
|
|
|
app.component("MkAcct", MkAcct);
|
2023-12-27 23:34:52 +00:00
|
|
|
app.component("MagAvatar", MagAvatar);
|
2023-11-07 02:11:22 +00:00
|
|
|
app.component("MagEmoji", MagEmoji);
|
|
|
|
app.component("MkUserName", MkUserName);
|
|
|
|
app.component("MkEllipsis", MkEllipsis);
|
|
|
|
app.component("MkTime", MkTime);
|
|
|
|
app.component("MkUrl", MkUrl);
|
|
|
|
app.component("MkLoading", MkLoading);
|
|
|
|
app.component("MkError", MkError);
|
|
|
|
app.component("MkPageHeader", MkPageHeader);
|
|
|
|
app.component("MkSpacer", MkSpacer);
|
|
|
|
app.component("MkStickyContainer", MkStickyContainer);
|
2023-12-27 23:34:52 +00:00
|
|
|
app.component("MagAvatarResolvingProxy", MagAvatarResolvingProxy);
|
2023-11-07 02:11:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
declare module "@vue/runtime-core" {
|
|
|
|
export interface GlobalComponents {
|
|
|
|
I18n: typeof I18n;
|
|
|
|
RouterView: typeof RouterView;
|
|
|
|
Mfm: typeof Mfm;
|
|
|
|
MkA: typeof MkA;
|
|
|
|
MkAcct: typeof MkAcct;
|
2023-12-27 23:34:52 +00:00
|
|
|
MagAvatar: typeof MagAvatar;
|
2023-11-07 02:11:22 +00:00
|
|
|
MagEmoji: typeof MagEmoji;
|
|
|
|
MkUserName: typeof MkUserName;
|
|
|
|
MkEllipsis: typeof MkEllipsis;
|
|
|
|
MkTime: typeof MkTime;
|
|
|
|
MkUrl: typeof MkUrl;
|
|
|
|
MkLoading: typeof MkLoading;
|
|
|
|
MkError: typeof MkError;
|
|
|
|
MkPageHeader: typeof MkPageHeader;
|
|
|
|
MkSpacer: typeof MkSpacer;
|
|
|
|
MkStickyContainer: typeof MkStickyContainer;
|
2023-12-27 23:34:52 +00:00
|
|
|
MagAvatarResolvingProxy: typeof MagAvatarResolvingProxy;
|
2023-11-07 02:11:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-05 19:31:50 +00:00
|
|
|
const accounts = localStorage.getItem("accounts");
|
|
|
|
if (accounts) {
|
|
|
|
set("accounts", JSON.parse(accounts));
|
|
|
|
localStorage.removeItem("accounts");
|
|
|
|
}
|
|
|
|
//#endregion
|
|
|
|
|
2023-07-07 19:22:30 +00:00
|
|
|
function checkForSplash() {
|
2023-07-23 13:31:28 +00:00
|
|
|
const splash = document.getElementById("splash");
|
|
|
|
// 念のためnullチェック(HTMLが古い場合があるため(そのうち消す))
|
|
|
|
if (splash) {
|
|
|
|
splash.style.opacity = "0";
|
|
|
|
splash.style.pointerEvents = "none";
|
|
|
|
splash.addEventListener("transitionend", () => {
|
|
|
|
splash.remove();
|
|
|
|
});
|
|
|
|
}
|
2023-07-07 19:22:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
(async () => {
|
2023-11-05 19:31:50 +00:00
|
|
|
console.info(`Magnetar v${version}`);
|
2023-07-07 19:22:30 +00:00
|
|
|
|
2023-07-23 13:31:28 +00:00
|
|
|
if (_DEV_) {
|
|
|
|
console.warn("Development mode!!!");
|
2023-07-07 19:22:30 +00:00
|
|
|
|
2023-07-23 13:31:28 +00:00
|
|
|
console.info(`vue ${vueVersion}`);
|
2023-07-07 19:22:30 +00:00
|
|
|
|
2023-07-23 13:31:28 +00:00
|
|
|
(window as any).$i = $i;
|
|
|
|
(window as any).$store = defaultStore;
|
2023-07-07 19:22:30 +00:00
|
|
|
|
2023-07-23 13:31:28 +00:00
|
|
|
window.addEventListener("error", (event) => {
|
|
|
|
console.error(event);
|
|
|
|
/*
|
2023-07-07 19:22:30 +00:00
|
|
|
alert({
|
|
|
|
type: 'error',
|
|
|
|
title: 'DEV: Unhandled error',
|
|
|
|
text: event.message
|
|
|
|
});
|
|
|
|
*/
|
2023-07-23 13:31:28 +00:00
|
|
|
});
|
2023-07-07 19:22:30 +00:00
|
|
|
|
2023-07-23 13:31:28 +00:00
|
|
|
window.addEventListener("unhandledrejection", (event) => {
|
|
|
|
console.error(event);
|
|
|
|
/*
|
2023-07-07 19:22:30 +00:00
|
|
|
alert({
|
|
|
|
type: 'error',
|
|
|
|
title: 'DEV: Unhandled promise rejection',
|
|
|
|
text: event.reason
|
|
|
|
});
|
|
|
|
*/
|
2023-07-23 13:31:28 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// タッチデバイスでCSSの:hoverを機能させる
|
|
|
|
document.addEventListener("touchend", () => {}, { passive: true });
|
|
|
|
|
|
|
|
// 一斉リロード
|
|
|
|
reloadChannel.addEventListener("message", (path) => {
|
|
|
|
if (path !== null) location.href = path;
|
|
|
|
else location.reload();
|
|
|
|
});
|
|
|
|
|
|
|
|
//#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
|
|
|
|
// TODO: いつの日にか消したい
|
|
|
|
const vh = window.innerHeight * 0.01;
|
|
|
|
document.documentElement.style.setProperty("--vh", `${vh}px`);
|
|
|
|
window.addEventListener("resize", () => {
|
|
|
|
const vh = window.innerHeight * 0.01;
|
|
|
|
document.documentElement.style.setProperty("--vh", `${vh}px`);
|
|
|
|
});
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
//#region Set lang attr
|
|
|
|
const html = document.documentElement;
|
|
|
|
html.setAttribute("lang", lang || "en-US");
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
//#region loginId
|
|
|
|
const params = new URLSearchParams(location.search);
|
|
|
|
const loginId = params.get("loginId");
|
|
|
|
|
|
|
|
if (loginId) {
|
|
|
|
const target = getUrlWithoutLoginId(location.href);
|
|
|
|
|
|
|
|
if (!$i || $i.id !== loginId) {
|
|
|
|
const account = await getAccountFromId(loginId);
|
|
|
|
if (account) {
|
|
|
|
await login(account.token, target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
history.replaceState({ misskey: "loginId" }, "", target);
|
|
|
|
}
|
|
|
|
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
//#region Fetch user
|
|
|
|
if ($i?.token) {
|
|
|
|
if (_DEV_) {
|
|
|
|
console.log("account cache found. refreshing...");
|
|
|
|
}
|
|
|
|
|
|
|
|
refreshAccount();
|
|
|
|
} else {
|
|
|
|
if (_DEV_) {
|
|
|
|
console.log("no account cache found.");
|
|
|
|
}
|
|
|
|
|
|
|
|
// 連携ログインの場合用にCookieを参照する
|
|
|
|
const i = (document.cookie.match(/igi=(\w+)/) || [null, null])[1];
|
|
|
|
|
|
|
|
if (i != null && i !== "null") {
|
|
|
|
if (_DEV_) {
|
|
|
|
console.log("signing...");
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
document.body.innerHTML = "<div>Please wait...</div>";
|
|
|
|
await login(i);
|
|
|
|
} catch (err) {
|
|
|
|
// Render the error screen
|
|
|
|
// TODO: ちゃんとしたコンポーネントをレンダリングする(v10とかのトラブルシューティングゲーム付きのやつみたいな)
|
|
|
|
document.body.innerHTML = '<div id="err">Oops!</div>';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (_DEV_) {
|
|
|
|
console.log("not signed in");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
const fetchInstanceMetaPromise = fetchInstance();
|
|
|
|
|
|
|
|
fetchInstanceMetaPromise.then(() => {
|
|
|
|
localStorage.setItem("v", instance.version);
|
|
|
|
|
|
|
|
// Init service worker
|
|
|
|
initializeSw();
|
|
|
|
});
|
|
|
|
|
|
|
|
const app = createApp(
|
|
|
|
window.location.search === "?zen"
|
|
|
|
? defineAsyncComponent(() => import("@/ui/zen.vue"))
|
|
|
|
: !$i
|
|
|
|
? defineAsyncComponent(() => import("@/ui/visitor.vue"))
|
|
|
|
: ui === "deck"
|
|
|
|
? defineAsyncComponent(() => import("@/ui/deck.vue"))
|
|
|
|
: defineAsyncComponent(() => import("@/ui/universal.vue"))
|
|
|
|
);
|
|
|
|
|
|
|
|
if (_DEV_) {
|
|
|
|
app.config.performance = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
app.config.globalProperties = {
|
|
|
|
$i,
|
|
|
|
$store: defaultStore,
|
|
|
|
$instance: instance,
|
|
|
|
$t: i18n.t,
|
|
|
|
$ts: i18n.ts,
|
|
|
|
};
|
|
|
|
|
|
|
|
widgets(app);
|
|
|
|
directives(app);
|
2023-11-07 02:11:22 +00:00
|
|
|
globalComponents(app);
|
2023-07-23 13:31:28 +00:00
|
|
|
|
|
|
|
checkForSplash();
|
|
|
|
|
|
|
|
// https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210
|
|
|
|
// なぜかinit.tsの内容が2回実行されることがあるため、mountするdivを1つに制限する
|
|
|
|
const rootEl = (() => {
|
|
|
|
const MISSKEY_MOUNT_DIV_ID = "calckey_app";
|
|
|
|
|
|
|
|
const currentEl = document.getElementById(MISSKEY_MOUNT_DIV_ID);
|
|
|
|
|
|
|
|
if (currentEl) {
|
|
|
|
console.warn("multiple import detected");
|
|
|
|
return currentEl;
|
|
|
|
}
|
|
|
|
|
|
|
|
const rootEl = document.createElement("div");
|
|
|
|
rootEl.id = MISSKEY_MOUNT_DIV_ID;
|
|
|
|
document.body.appendChild(rootEl);
|
|
|
|
return rootEl;
|
|
|
|
})();
|
|
|
|
|
|
|
|
app.mount(rootEl);
|
|
|
|
|
|
|
|
// boot.jsのやつを解除
|
|
|
|
window.onerror = null;
|
|
|
|
window.onunhandledrejection = null;
|
|
|
|
|
|
|
|
reactionPicker.init();
|
|
|
|
|
|
|
|
checkForSplash();
|
|
|
|
|
|
|
|
// クライアントが更新されたか?
|
|
|
|
const lastVersion = localStorage.getItem("lastVersion");
|
|
|
|
|
|
|
|
if (lastVersion !== version) {
|
|
|
|
localStorage.setItem("lastVersion", version);
|
|
|
|
|
|
|
|
// テーマリビルドするため
|
|
|
|
localStorage.removeItem("theme");
|
|
|
|
|
|
|
|
try {
|
|
|
|
// 変なバージョン文字列来るとcompareVersionsでエラーになるため
|
|
|
|
if (
|
|
|
|
lastVersion != null &&
|
|
|
|
compareVersions(version, lastVersion) === 1 &&
|
|
|
|
defaultStore.state.showUpdates
|
|
|
|
) {
|
|
|
|
// ログインしてる場合だけ
|
|
|
|
if ($i) {
|
|
|
|
popup(
|
|
|
|
defineAsyncComponent(
|
|
|
|
() => import("@/components/MkUpdated.vue")
|
|
|
|
),
|
|
|
|
{},
|
|
|
|
{},
|
|
|
|
"closed"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
console.error(err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため)
|
|
|
|
watch(
|
|
|
|
defaultStore.reactiveState.darkMode,
|
|
|
|
(darkMode) => {
|
|
|
|
applyTheme(
|
|
|
|
darkMode
|
|
|
|
? ColdDeviceStorage.get("darkTheme")
|
|
|
|
: ColdDeviceStorage.get("lightTheme")
|
|
|
|
);
|
|
|
|
},
|
|
|
|
{ immediate: localStorage.theme == null }
|
|
|
|
);
|
|
|
|
|
|
|
|
const darkTheme = computed(ColdDeviceStorage.makeGetterSetter("darkTheme"));
|
|
|
|
const lightTheme = computed(
|
|
|
|
ColdDeviceStorage.makeGetterSetter("lightTheme")
|
|
|
|
);
|
|
|
|
|
|
|
|
watch(darkTheme, (theme) => {
|
|
|
|
if (defaultStore.state.darkMode) {
|
|
|
|
applyTheme(theme);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
watch(lightTheme, (theme) => {
|
|
|
|
if (!defaultStore.state.darkMode) {
|
|
|
|
applyTheme(theme);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
//#region Sync dark mode
|
|
|
|
if (ColdDeviceStorage.get("syncDeviceDarkMode")) {
|
|
|
|
defaultStore.set("darkMode", isDeviceDarkmode());
|
|
|
|
}
|
|
|
|
window.matchMedia("(prefers-color-scheme: dark)").onchange = (mql) => {
|
|
|
|
if (ColdDeviceStorage.get("syncDeviceDarkMode")) {
|
|
|
|
defaultStore.set("darkMode", mql.matches);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
fetchInstanceMetaPromise.then(() => {
|
|
|
|
if (defaultStore.state.themeInitial) {
|
|
|
|
if (instance.defaultLightTheme != null)
|
|
|
|
ColdDeviceStorage.set(
|
|
|
|
"lightTheme",
|
|
|
|
JSON.parse(instance.defaultLightTheme)
|
|
|
|
);
|
|
|
|
if (instance.defaultDarkTheme != null)
|
|
|
|
ColdDeviceStorage.set(
|
|
|
|
"darkTheme",
|
|
|
|
JSON.parse(instance.defaultDarkTheme)
|
|
|
|
);
|
|
|
|
defaultStore.set("themeInitial", false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
watch(
|
|
|
|
defaultStore.reactiveState.useBlurEffectForModal,
|
|
|
|
(v) => {
|
|
|
|
document.documentElement.style.setProperty(
|
|
|
|
"--modalBgFilter",
|
|
|
|
v ? "blur(4px)" : "none"
|
|
|
|
);
|
|
|
|
},
|
|
|
|
{ immediate: true }
|
|
|
|
);
|
|
|
|
|
|
|
|
watch(
|
|
|
|
defaultStore.reactiveState.useBlurEffect,
|
|
|
|
(v) => {
|
|
|
|
if (v && deviceKind !== "smartphone") {
|
|
|
|
document.documentElement.style.removeProperty("--blur");
|
|
|
|
} else {
|
|
|
|
document.documentElement.style.setProperty("--blur", "none");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{ immediate: true }
|
|
|
|
);
|
|
|
|
|
|
|
|
let reloadDialogShowing = false;
|
|
|
|
stream.on("_disconnected_", async () => {
|
|
|
|
if (defaultStore.state.serverDisconnectedBehavior === "reload") {
|
|
|
|
location.reload();
|
|
|
|
} else if (defaultStore.state.serverDisconnectedBehavior === "dialog") {
|
|
|
|
if (reloadDialogShowing) return;
|
|
|
|
reloadDialogShowing = true;
|
|
|
|
const { canceled } = await confirm({
|
|
|
|
type: "warning",
|
|
|
|
title: i18n.ts.disconnectedFromServer,
|
|
|
|
text: i18n.ts.reloadConfirm,
|
|
|
|
});
|
|
|
|
reloadDialogShowing = false;
|
|
|
|
if (!canceled) {
|
|
|
|
location.reload();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
stream.on("emojiAdded", (emojiData) => {
|
|
|
|
// TODO
|
|
|
|
//store.commit('instance/set', );
|
|
|
|
});
|
|
|
|
|
|
|
|
const hotkeys = {
|
|
|
|
d: (): void => {
|
|
|
|
defaultStore.set("darkMode", !defaultStore.state.darkMode);
|
|
|
|
},
|
|
|
|
s: search,
|
|
|
|
};
|
|
|
|
|
|
|
|
if ($i) {
|
|
|
|
// only add post shortcuts if logged in
|
|
|
|
hotkeys["p|n"] = post;
|
|
|
|
|
|
|
|
if ($i.isDeleted) {
|
|
|
|
alert({
|
|
|
|
type: "warning",
|
|
|
|
text: i18n.ts.accountDeletionInProgress,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const lastUsed = localStorage.getItem("lastUsed");
|
|
|
|
if (lastUsed) {
|
|
|
|
const lastUsedDate = parseInt(lastUsed, 10);
|
|
|
|
// 二時間以上前なら
|
|
|
|
if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) {
|
|
|
|
toast(
|
|
|
|
i18n.t("welcomeBackWithName", {
|
|
|
|
name: $i.name || $i.username,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
localStorage.setItem("lastUsed", Date.now().toString());
|
|
|
|
|
|
|
|
if ("Notification" in window) {
|
|
|
|
// 許可を得ていなかったらリクエスト
|
|
|
|
if (Notification.permission === "default") {
|
|
|
|
Notification.requestPermission();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const main = markRaw(stream.useChannel("main", null, "System"));
|
|
|
|
|
|
|
|
// 自分の情報が更新されたとき
|
|
|
|
main.on("meUpdated", (i) => {
|
|
|
|
updateAccount(i);
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("readAllNotifications", () => {
|
|
|
|
updateAccount({ hasUnreadNotification: false });
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("unreadNotification", () => {
|
|
|
|
updateAccount({ hasUnreadNotification: true });
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("unreadMention", () => {
|
|
|
|
updateAccount({ hasUnreadMentions: true });
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("readAllUnreadMentions", () => {
|
|
|
|
updateAccount({ hasUnreadMentions: false });
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("unreadSpecifiedNote", () => {
|
|
|
|
updateAccount({ hasUnreadSpecifiedNotes: true });
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("readAllUnreadSpecifiedNotes", () => {
|
|
|
|
updateAccount({ hasUnreadSpecifiedNotes: false });
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("readAllAntennas", () => {
|
|
|
|
updateAccount({ hasUnreadAntenna: false });
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("unreadAntenna", () => {
|
|
|
|
updateAccount({ hasUnreadAntenna: true });
|
|
|
|
sound.play("antenna");
|
|
|
|
});
|
|
|
|
|
|
|
|
main.on("readAllAnnouncements", () => {
|
|
|
|
updateAccount({ hasUnreadAnnouncement: false });
|
|
|
|
});
|
|
|
|
|
|
|
|
// トークンが再生成されたとき
|
|
|
|
// このままではMisskeyが利用できないので強制的にサインアウトさせる
|
|
|
|
main.on("myTokenRegenerated", () => {
|
|
|
|
signout();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// shortcut
|
|
|
|
document.addEventListener("keydown", makeHotkey(hotkeys));
|
2023-07-07 19:22:30 +00:00
|
|
|
})();
|