From 85078601c2a98eef5683816783bc738ce319f201 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 10 Sep 2023 17:40:59 +0900
Subject: [PATCH] enhance(frontend): cache user lists / antennas

---
 CHANGELOG.md                             |  1 +
 packages/frontend/src/local-storage.ts   | 10 ++++++++++
 packages/frontend/src/pages/timeline.vue | 17 +++++++++++++++--
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2f950c46..b0ca091ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -43,6 +43,7 @@
 - Playの操作を行うAPI TokenをAPIコンソールから発行できるように
 - リアクションの表示サイズをより大きくできるように
 - ノート詳細ページ読み込み時のパフォーマンスを改善
+- タイムラインでリスト/アンテナ選択時のパフォーマンスを改善
 - Fix: サーバー情報画面(`/instance-info/{domain}`)でブロックができないのを修正
 - Fix: 未読のお知らせの「わかった」をクリック・タップしてもその場で「わかった」が消えない問題を修正
 - Fix: iOSで画面を回転させるとテキストサイズが変わる問題を修正
diff --git a/packages/frontend/src/local-storage.ts b/packages/frontend/src/local-storage.ts
index d9dce2859..f4c11d613 100644
--- a/packages/frontend/src/local-storage.ts
+++ b/packages/frontend/src/local-storage.ts
@@ -30,6 +30,8 @@ type Keys =
 	'message_drafts' |
 	'scratchpad' |
 	'debug' |
+	'userListsCache' |
+	'antennasCache' |
 	`miux:${string}` |
 	`ui:folder:${string}` |
 	`themes:${string}` |
@@ -41,4 +43,12 @@ export const miLocalStorage = {
 	getItem: (key: Keys): string | null => window.localStorage.getItem(key),
 	setItem: (key: Keys, value: string): void => window.localStorage.setItem(key, value),
 	removeItem: (key: Keys): void => window.localStorage.removeItem(key),
+	getItemAsJson: (key: Keys): any | undefined => {
+		const item = miLocalStorage.getItem(key);
+		if (item === null) {
+			return undefined;
+		}
+		return JSON.parse(item);
+	},
+	setItemAsJson: (key: Keys, value: any): void => window.localStorage.setItem(key, JSON.stringify(value)),
 };
diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue
index f5fadb389..3ec4a6788 100644
--- a/packages/frontend/src/pages/timeline.vue
+++ b/packages/frontend/src/pages/timeline.vue
@@ -38,6 +38,7 @@ import { i18n } from '@/i18n';
 import { instance } from '@/instance';
 import { $i } from '@/account';
 import { definePageMetadata } from '@/scripts/page-metadata';
+import { miLocalStorage } from '@/local-storage';
 
 provide('shouldOmitHeaderTitle', true);
 
@@ -67,17 +68,24 @@ function top(): void {
 }
 
 async function chooseList(ev: MouseEvent): Promise<void> {
-	const lists = await os.api('users/lists/list');
+	const cachedLists = miLocalStorage.getItemAsJson('userListsCache');
+	const lists = cachedLists ?? await os.api('users/lists/list');
 	const items = lists.map(list => ({
 		type: 'link' as const,
 		text: list.name,
 		to: `/timeline/list/${list.id}`,
 	}));
 	os.popupMenu(items, ev.currentTarget ?? ev.target);
+	if (cachedLists == null) {
+		miLocalStorage.setItemAsJson('userListsCache', lists);
+	} else {
+		miLocalStorage.setItemAsJson('userListsCache', await os.api('users/lists/list'));
+	}
 }
 
 async function chooseAntenna(ev: MouseEvent): Promise<void> {
-	const antennas = await os.api('antennas/list');
+	const cachedAntennas = miLocalStorage.getItemAsJson('antennasCache');
+	const antennas = cachedAntennas ?? await os.api('antennas/list');
 	const items = antennas.map(antenna => ({
 		type: 'link' as const,
 		text: antenna.name,
@@ -85,6 +93,11 @@ async function chooseAntenna(ev: MouseEvent): Promise<void> {
 		to: `/timeline/antenna/${antenna.id}`,
 	}));
 	os.popupMenu(items, ev.currentTarget ?? ev.target);
+	if (cachedAntennas == null) {
+		miLocalStorage.setItemAsJson('antennasCache', antennas);
+	} else {
+		miLocalStorage.setItemAsJson('antennasCache', await os.api('antennas/list'));
+	}
 }
 
 async function chooseChannel(ev: MouseEvent): Promise<void> {