From ecb990fb7779d64f4f23fb46fef4c87ac6ee150b Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 12:48:39 +0200
Subject: [PATCH 47/58] Added docs to $i, iAmModerator, iAmAdmin.
---
packages/frontend/src/account.ts | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts
index 36186ecac1..fb31fef380 100644
--- a/packages/frontend/src/account.ts
+++ b/packages/frontend/src/account.ts
@@ -22,11 +22,35 @@ type Account = Misskey.entities.MeDetailed & { token: string };
const accountData = miLocalStorage.getItem('account');
// TODO: 外部からはreadonlyに
+/**
+ * Reactive state for the current account. "I" as in "I am logged in".
+ * Initialized from local storage if available, otherwise null.
+ *
+ * @type {Account | null}
+ */
export const $i = accountData ? reactive(JSON.parse(accountData) as Account) : null;
+/**
+ * Whether the current account is a moderator.
+ *
+ * @type {boolean}
+ */
export const iAmModerator = $i != null && ($i.isAdmin === true || $i.isModerator === true);
+
+/**
+ * Whether the current account is an administrator.
+ *
+ * @type {boolean}
+ */
export const iAmAdmin = $i != null && $i.isAdmin;
+/**
+ * Whether it is necessary to sign in; checks if the current
+ * account is null and throws an error if so.
+ *
+ * @throws {Error} If the current account is null
+ * @returns {Account} The current account
+ */
export function signinRequired() {
if ($i == null) throw new Error('signin required');
return $i;
From aeb568664d613c9f136b6628b43b07901e36b889 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 12:54:26 +0200
Subject: [PATCH 48/58] Added docs (and observations) to notes count.
---
packages/frontend/src/account.ts | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts
index fb31fef380..722f296732 100644
--- a/packages/frontend/src/account.ts
+++ b/packages/frontend/src/account.ts
@@ -56,13 +56,32 @@ export function signinRequired() {
return $i;
}
+/**
+ * Extracts the current number of notes from the current account.
+ *
+ * Note: This appears to only be used for the "notes1" achievement.
+ *
+ * Also, separating it like this might cause counts to get out-of-sync.
+ */
export let notesCount = $i == null ? 0 : $i.notesCount;
+
+/**
+ * Increments the number of notes by one.
+ *
+ * Documentation TODO: What about $i.notesCount? Why not increment that?
+ */
export function incNotesCount() {
notesCount++;
}
export async function signout() {
- if (!$i) return;
+
+ // If we're not signed in, there's nothing to do.
+ if (!$i) {
+ // Error log:
+ console.error('signout() called when not signed in');
+ return;
+ }
waiting();
miLocalStorage.removeItem('account');
From 8c1508fae4ca46cbeb16bbc61c5165b4d05b0bf6 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 12:59:32 +0200
Subject: [PATCH 49/58] Added docs to miLocalStorage.
---
packages/frontend/src/local-storage.ts | 35 ++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/packages/frontend/src/local-storage.ts b/packages/frontend/src/local-storage.ts
index 5b8ba77e01..5ca25dc5d9 100644
--- a/packages/frontend/src/local-storage.ts
+++ b/packages/frontend/src/local-storage.ts
@@ -44,16 +44,45 @@ export type Keys =
// セッション毎に廃棄されるLocalStorage代替(セーフモードなどで使用できそう)
//const safeSessionStorage = new Map();
+
+/**
+ * A utility object for interacting with the browser's localStorage.
+ *
+ * It's mostly a small wrapper around window.localStorage, but it validates
+ * keys with a typesafe enum, and provides a few convenience methods for JSON.
+ */
export const miLocalStorage = {
+ /**
+ * Retrieves an item from localStorage.
+ * @param {Keys} key - The key of the item to retrieve.
+ * @returns {string | null} The value of the item, or null if the item does not exist.
+ */
getItem: (key: Keys): string | null => {
return window.localStorage.getItem(key);
},
+
+ /**
+ * Stores an item in localStorage.
+ * @param {Keys} key - The key of the item to store.
+ * @param {string} value - The value of the item to store.
+ */
setItem: (key: Keys, value: string): void => {
window.localStorage.setItem(key, value);
},
+
+ /**
+ * Removes an item from localStorage.
+ * @param {Keys} key - The key of the item to remove.
+ */
removeItem: (key: Keys): void => {
window.localStorage.removeItem(key);
},
+
+ /**
+ * Retrieves an item from localStorage and parses it as JSON.
+ * @param {Keys} key - The key of the item to retrieve.
+ * @returns {any | undefined} The parsed value of the item, or undefined if the item does not exist.
+ */
getItemAsJson: (key: Keys): any | undefined => {
const item = miLocalStorage.getItem(key);
if (item === null) {
@@ -61,6 +90,12 @@ export const miLocalStorage = {
}
return JSON.parse(item);
},
+
+ /**
+ * Stores an item in localStorage as a JSON string.
+ * @param {Keys} key - The key of the item to store.
+ * @param {any} value - The value of the item to store.
+ */
setItemAsJson: (key: Keys, value: any): void => {
miLocalStorage.setItem(key, JSON.stringify(value));
},
From 7f6b4869768a430d1a99f57cb2cde9deac463cd5 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 12:59:58 +0200
Subject: [PATCH 50/58] Added docs to Keys for localStorage.
---
packages/frontend/src/local-storage.ts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/packages/frontend/src/local-storage.ts b/packages/frontend/src/local-storage.ts
index 5ca25dc5d9..828b01848f 100644
--- a/packages/frontend/src/local-storage.ts
+++ b/packages/frontend/src/local-storage.ts
@@ -3,6 +3,9 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
+/**
+ * A typesafe enum of keys for localStorage.
+ */
export type Keys =
'v' |
'lastVersion' |
From 2e51e779e7ad3d00b2973b14a36d4b5313ed41e1 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 13:16:05 +0200
Subject: [PATCH 51/58] Added docs idb proxy.
---
packages/frontend/src/scripts/idb-proxy.ts | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/packages/frontend/src/scripts/idb-proxy.ts b/packages/frontend/src/scripts/idb-proxy.ts
index 20f51660c7..425225fc42 100644
--- a/packages/frontend/src/scripts/idb-proxy.ts
+++ b/packages/frontend/src/scripts/idb-proxy.ts
@@ -26,6 +26,7 @@ if (window.Cypress) {
console.log('Cypress detected. It will use localStorage.');
}
+// Check for the availability of indexedDB.
if (idbAvailable) {
await iset('idb-test', 'test')
.catch(err => {
@@ -37,16 +38,36 @@ if (idbAvailable) {
console.error('indexedDB is unavailable. It will use localStorage.');
}
+/**
+ * Get a value from indexedDB (or localStorage as a fallback).
+ *
+ * @param key The key of the item to retrieve.
+ *
+ * @returns The value of the item.
+ */
export async function get(key: string) {
if (idbAvailable) return iget(key);
return miLocalStorage.getItemAsJson(`${PREFIX}${key}`);
}
+/**
+ * Set a value in indexedDB (or localStorage as a fallback).
+ *
+ * @param {string} key - The key of the item to set.
+ * @param {any} val - The value of the item to set.
+ * @returns {Promise} - A promise that resolves when the value has been set.`
+ */
export async function set(key: string, val: any) {
if (idbAvailable) return iset(key, val);
return miLocalStorage.setItemAsJson(`${PREFIX}${key}`, val);
}
+/**
+ * Delete a value from indexedDB (or localStorage as a fallback).
+ *
+ * @param {string} key - The key of the item to delete.
+ * @returns {Promise} - A promise that resolves when the value has been deleted.
+ */
export async function del(key: string) {
if (idbAvailable) return idel(key);
return miLocalStorage.removeItem(`${PREFIX}${key}`);
From 8457fa9b3bc757d5c7d6dcfe9f5443925a5a84a3 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 14:23:31 +0200
Subject: [PATCH 52/58] Added docs to popup list and popup id counter.
---
packages/frontend/src/os.ts | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index ea1b673de9..41b4dc3c0f 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -136,7 +136,16 @@ export function promiseDialog>(
return promise;
}
+/**
+ * Counter for generating unique popup IDs.
+ * @type {number}
+ */
let popupIdCount = 0;
+
+/**
+ * A reactive list of the currently opened popups. This is used in a Vue component
+ * in a v-for loop to render the popups.
+ */
export const popups = ref<{
id: number;
component: Component;
From 1613dafc397b561c1933492cba6079a7c95bb865 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 14:23:44 +0200
Subject: [PATCH 53/58] Added docs to z-index generator.
---
packages/frontend/src/os.ts | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 41b4dc3c0f..716d7a0b56 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -153,12 +153,23 @@ export const popups = ref<{
events: Record;
}[]>([]);
+/**
+ * An object containing z-index values for different priority levels.
+ */
const zIndexes = {
veryLow: 500000,
low: 1000000,
middle: 2000000,
high: 3000000,
};
+
+/**
+ * Claims a z-index value for a given priority level.
+ * Increments the z-index value for the specified priority by 100 and returns the new value.
+ *
+ * @param {keyof typeof zIndexes} [priority='low'] - The priority level for which to claim a z-index.
+ * @returns {number} The new z-index value for the specified priority.
+ */
export function claimZIndex(priority: keyof typeof zIndexes = 'low'): number {
zIndexes[priority] += 100;
return zIndexes[priority];
From a516383c66f8e43da73fd1cab0fdabe58ff97330 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 14:34:21 +0200
Subject: [PATCH 54/58] Added internal comments to popup()
---
packages/frontend/src/os.ts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 716d7a0b56..acfeff8ec5 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -204,13 +204,18 @@ export function popup(
): { dispose: () => void } {
markRaw(component);
+ // Generate a unique ID for this popup.
const id = ++popupIdCount;
+
+ // On disposal, remove this popup from the list of open popups.
const dispose = () => {
// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
window.setTimeout(() => {
popups.value = popups.value.filter(p => p.id !== id);
}, 0);
};
+
+ // Bundle the component, props, and events into a state object.
const state = {
component,
props,
@@ -218,8 +223,10 @@ export function popup(
id,
};
+ // Add the popup to the list of open popups.
popups.value.push(state);
+ // Return a function that can be called to close the popup.
return {
dispose,
};
From a505f3625255daf955b1990667fc09abaa93586a Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 14:34:31 +0200
Subject: [PATCH 55/58] Added doc comment to popup
---
packages/frontend/src/os.ts | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index acfeff8ec5..9dff33423e 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -197,6 +197,15 @@ type EmitsExtractor = {
[K in keyof T as K extends `onVnode${string}` ? never : K extends `on${infer E}` ? Uncapitalize : K extends string ? never : K]: T[K];
};
+/**
+ * Opens a popup with the specified component, props, and events.
+ *
+ * @template T - The type of the component.
+ * @param {T} component - The Vue component to display in the popup.
+ * @param {ComponentProps} props - The props to pass to the component.
+ * @param {ComponentEmit} [events={}] - The events to bind to the component.
+ * @returns {{ dispose: () => void }} An object containing a dispose function to close the popup.
+ */
export function popup(
component: T,
props: ComponentProps,
From ee574ae154c689ab9a2d9ecfc4eef16b8055436b Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 14:34:39 +0200
Subject: [PATCH 56/58] Added doc comment to pageWindow
---
packages/frontend/src/os.ts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 9dff33423e..fc37469b6b 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -241,6 +241,10 @@ export function popup(
};
}
+/**
+ * Open the page with the given path in a pop-up window.
+ * @param path The path of the page to open.
+ */
export function pageWindow(path: string) {
const { dispose } = popup(MkPageWindow, {
initialPath: path,
From 0bd7ed8191f47f64eb3cd18cb86ab2e8d89b34c5 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 14:34:47 +0200
Subject: [PATCH 57/58] Added doc comment to toast()
---
packages/frontend/src/os.ts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index fc37469b6b..92a7e4f2c6 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -253,6 +253,11 @@ export function pageWindow(path: string) {
});
}
+/**
+ * Displays a toast message to the user.
+ *
+ * @param {string} message - The message to display in the toast.
+ */
export function toast(message: string) {
const { dispose } = popup(MkToast, {
message,
From a858ee31c6c8298ef695856936cf65d3f2295d94 Mon Sep 17 00:00:00 2001
From: Mizah
Date: Sun, 17 Nov 2024 14:34:54 +0200
Subject: [PATCH 58/58] Added doc comment to alert()
---
packages/frontend/src/os.ts | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 92a7e4f2c6..0eb4e2ac53 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -266,6 +266,15 @@ export function toast(message: string) {
});
}
+/**
+ * Displays an alert dialog to the user.
+ *
+ * @param {Object} props - The properties for the alert dialog.
+ * @param {'error' | 'info' | 'success' | 'warning' | 'waiting' | 'question'} [props.type] - The type of the alert.
+ * @param {string} [props.title] - The title of the alert dialog.
+ * @param {string} [props.text] - The text content of the alert dialog.
+ * @returns {Promise} A promise that resolves when the alert dialog is closed.
+ */
export function alert(props: {
type?: 'error' | 'info' | 'success' | 'warning' | 'waiting' | 'question';
title?: string;