From 08040924265cb9f8f4016ecc258c656449813c92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Mon, 16 Dec 2024 09:03:46 +0900
Subject: [PATCH] =?UTF-8?q?fix(frontend):=20serverContext=E3=81=AE?=
 =?UTF-8?q?=E5=9E=8B=E3=82=A8=E3=83=A9=E3=83=BC=E3=82=92=E4=BF=AE=E6=AD=A3?=
 =?UTF-8?q?=20(#15131)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): serverContextの型エラーを修正

* add comment
---
 packages/frontend/src/pages/clip.vue       |  5 +++--
 packages/frontend/src/pages/note.vue       |  6 ++++--
 packages/frontend/src/pages/user/index.vue |  5 +++--
 packages/frontend/src/server-context.ts    | 12 +++++-------
 4 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue
index 891d59d605..c925bac4d9 100644
--- a/packages/frontend/src/pages/clip.vue
+++ b/packages/frontend/src/pages/clip.vue
@@ -46,9 +46,10 @@ import { clipsCache } from '@/cache.js';
 import { isSupportShare } from '@/scripts/navigator.js';
 import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
 import { genEmbedCode } from '@/scripts/get-embed-code.js';
-import { getServerContext } from '@/server-context.js';
+import { assertServerContext, serverContext } from '@/server-context.js';
 
-const CTX_CLIP = getServerContext('clip');
+// contextは非ログイン状態の情報しかないためログイン時は利用できない
+const CTX_CLIP = $i && assertServerContext(serverContext, 'clip') ? serverContext.clip : null;
 
 const props = defineProps<{
 	clipId: string,
diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue
index 5cf8f56776..6eca04db8d 100644
--- a/packages/frontend/src/pages/note.vue
+++ b/packages/frontend/src/pages/note.vue
@@ -63,9 +63,11 @@ import { dateString } from '@/filters/date.js';
 import MkClipPreview from '@/components/MkClipPreview.vue';
 import { defaultStore } from '@/store.js';
 import { pleaseLogin } from '@/scripts/please-login.js';
-import { getServerContext } from '@/server-context.js';
+import { serverContext, assertServerContext } from '@/server-context.js';
+import { $i } from '@/account.js';
 
-const CTX_NOTE = getServerContext('note');
+// contextは非ログイン状態の情報しかないためログイン時は利用できない
+const CTX_NOTE = $i && assertServerContext(serverContext, 'note') ? serverContext.note : null;
 
 const props = defineProps<{
 	noteId: string;
diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue
index d862387401..c5cda79935 100644
--- a/packages/frontend/src/pages/user/index.vue
+++ b/packages/frontend/src/pages/user/index.vue
@@ -39,7 +39,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
 import { i18n } from '@/i18n.js';
 import { $i } from '@/account.js';
 import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
-import { getServerContext } from '@/server-context.js';
+import { serverContext, assertServerContext } from '@/server-context.js';
 
 const XHome = defineAsyncComponent(() => import('./home.vue'));
 const XTimeline = defineAsyncComponent(() => import('./index.timeline.vue'));
@@ -53,7 +53,8 @@ const XFlashs = defineAsyncComponent(() => import('./flashs.vue'));
 const XGallery = defineAsyncComponent(() => import('./gallery.vue'));
 const XRaw = defineAsyncComponent(() => import('./raw.vue'));
 
-const CTX_USER = getServerContext('user');
+// contextは非ログイン状態の情報しかないためログイン時は利用できない
+const CTX_USER = $i && assertServerContext(serverContext, 'user') ? serverContext.user : null;
 
 const props = withDefaults(defineProps<{
 	acct: string;
diff --git a/packages/frontend/src/server-context.ts b/packages/frontend/src/server-context.ts
index aa44a10290..e79d3fa314 100644
--- a/packages/frontend/src/server-context.ts
+++ b/packages/frontend/src/server-context.ts
@@ -2,22 +2,20 @@
  * SPDX-FileCopyrightText: syuilo and misskey-project
  * SPDX-License-Identifier: AGPL-3.0-only
  */
+
 import * as Misskey from 'misskey-js';
-import { $i } from '@/account.js';
 
 const providedContextEl = document.getElementById('misskey_clientCtx');
 
 export type ServerContext = {
 	clip?: Misskey.entities.Clip;
 	note?: Misskey.entities.Note;
-	user?: Misskey.entities.UserLite;
+	user?: Misskey.entities.UserDetailed;
 } | null;
 
 export const serverContext: ServerContext = (providedContextEl && providedContextEl.textContent) ? JSON.parse(providedContextEl.textContent) : null;
 
-export function getServerContext<K extends keyof NonNullable<ServerContext>>(entity: K): Required<Pick<NonNullable<ServerContext>, K>> | null {
-	// contextは非ログイン状態の情報しかないためログイン時は利用できない
-	if ($i) return null;
-
-	return serverContext ? (serverContext[entity] ?? null) : null;
+export function assertServerContext<K extends keyof NonNullable<ServerContext>>(ctx: ServerContext, entity: K): ctx is Required<Pick<NonNullable<ServerContext>, K>> {
+	if (ctx == null) return false;
+	return entity in ctx && ctx[entity] != null;
 }