From 4df9083bf04b72f59b9cb09334c89412e8cb296c Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 10 Mar 2025 10:05:50 +0900
Subject: [PATCH] =?UTF-8?q?fix(frontend):=20=E3=83=86=E3=83=BC=E3=83=9E?=
 =?UTF-8?q?=E5=88=87=E3=82=8A=E6=9B=BF=E3=81=88=E6=99=82=E3=81=AB=E4=B8=80?=
 =?UTF-8?q?=E9=83=A8=E3=81=AE=E8=89=B2=E3=81=8C=E5=A4=89=E3=82=8F=E3=82=89?=
 =?UTF-8?q?=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md                                  |  1 +
 .../src/components/global/MkPageHeader.vue    | 10 +++----
 .../src/directives/adaptive-border.ts         | 27 ++++++++++++++-----
 packages/frontend/src/events.ts               |  1 +
 .../frontend/src/pages/admin/_header_.vue     |  6 ++---
 packages/frontend/src/theme.ts                |  5 +++-
 6 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea6dbdb961..e0b47ff5e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
 - Feat: 設定の管理が強化されました
   - 自動でバックアップされるように
 - Enhance: プラグインの管理が強化されました
+- Fix: テーマ切り替え時に一部の色が変わらない問題を修正
 
 ### Server
 - Fix: プロフィール追加情報で無効なURLに入力された場合に照会エラーを出るのを修正
diff --git a/packages/frontend/src/components/global/MkPageHeader.vue b/packages/frontend/src/components/global/MkPageHeader.vue
index a7cf70745e..d3c64bf85a 100644
--- a/packages/frontend/src/components/global/MkPageHeader.vue
+++ b/packages/frontend/src/components/global/MkPageHeader.vue
@@ -43,14 +43,14 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { onMounted, onUnmounted, ref, inject, shallowRef, computed } from 'vue';
 import tinycolor from 'tinycolor2';
+import { scrollToTop } from '@@/js/scroll.js';
 import XTabs from './MkPageHeader.tabs.vue';
 import type { Tab } from './MkPageHeader.tabs.vue';
-import { scrollToTop } from '@@/js/scroll.js';
+import type { PageHeaderItem } from '@/types/page-header.js';
+import type { PageMetadata } from '@/utility/page-metadata.js';
 import { globalEvents } from '@/events.js';
 import { injectReactiveMetadata } from '@/utility/page-metadata.js';
 import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
-import type { PageHeaderItem } from '@/types/page-header.js';
-import type { PageMetadata } from '@/utility/page-metadata.js';
 
 const props = withDefaults(defineProps<{
 	overridePageMetadata?: PageMetadata;
@@ -114,7 +114,7 @@ let ro: ResizeObserver | null;
 
 onMounted(() => {
 	calcBg();
-	globalEvents.on('themeChanged', calcBg);
+	globalEvents.on('themeChanging', calcBg);
 
 	if (el.value && el.value.parentElement) {
 		narrow.value = el.value.parentElement.offsetWidth < 500;
@@ -128,7 +128,7 @@ onMounted(() => {
 });
 
 onUnmounted(() => {
-	globalEvents.off('themeChanged', calcBg);
+	globalEvents.off('themeChanging', calcBg);
 	if (ro) ro.disconnect();
 });
 </script>
diff --git a/packages/frontend/src/directives/adaptive-border.ts b/packages/frontend/src/directives/adaptive-border.ts
index af7deb5960..8072a1ffd9 100644
--- a/packages/frontend/src/directives/adaptive-border.ts
+++ b/packages/frontend/src/directives/adaptive-border.ts
@@ -5,17 +5,32 @@
 
 import type { Directive } from 'vue';
 import { getBgColor } from '@/utility/get-bg-color.js';
+import { globalEvents } from '@/events.js';
+
+const handlerMap = new WeakMap<any, any>();
 
 export default {
 	mounted(src, binding, vn) {
-		const parentBg = getBgColor(src.parentElement) ?? 'transparent';
+		function calc() {
+			const parentBg = getBgColor(src.parentElement) ?? 'transparent';
 
-		const myBg = window.getComputedStyle(src).backgroundColor;
+			const myBg = window.getComputedStyle(src).backgroundColor;
 
-		if (parentBg === myBg) {
-			src.style.borderColor = 'var(--MI_THEME-divider)';
-		} else {
-			src.style.borderColor = myBg;
+			if (parentBg === myBg) {
+				src.style.borderColor = 'var(--MI_THEME-divider)';
+			} else {
+				src.style.borderColor = myBg;
+			}
 		}
+
+		handlerMap.set(src, calc);
+
+		calc();
+
+		globalEvents.on('themeChanged', calc);
+	},
+
+	unmounted(src, binding, vn) {
+		globalEvents.off('themeChanged', handlerMap.get(src));
 	},
 } as Directive;
diff --git a/packages/frontend/src/events.ts b/packages/frontend/src/events.ts
index d476aec04a..a74018223c 100644
--- a/packages/frontend/src/events.ts
+++ b/packages/frontend/src/events.ts
@@ -7,6 +7,7 @@ import { EventEmitter } from 'eventemitter3';
 import * as Misskey from 'misskey-js';
 
 export const globalEvents = new EventEmitter<{
+	themeChanging: () => void;
 	themeChanged: () => void;
 	clientNotification: (notification: Misskey.entities.Notification) => void;
 	requestClearPageCache: () => void;
diff --git a/packages/frontend/src/pages/admin/_header_.vue b/packages/frontend/src/pages/admin/_header_.vue
index 8ba35d65d5..d5dac40e86 100644
--- a/packages/frontend/src/pages/admin/_header_.vue
+++ b/packages/frontend/src/pages/admin/_header_.vue
@@ -35,8 +35,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { computed, onMounted, onUnmounted, ref, shallowRef, watch, nextTick } from 'vue';
 import tinycolor from 'tinycolor2';
-import { popupMenu } from '@/os.js';
 import { scrollToTop } from '@@/js/scroll.js';
+import { popupMenu } from '@/os.js';
 import MkButton from '@/components/MkButton.vue';
 import { globalEvents } from '@/events.js';
 import { injectReactiveMetadata } from '@/utility/page-metadata.js';
@@ -127,7 +127,7 @@ const calcBg = () => {
 
 onMounted(() => {
 	calcBg();
-	globalEvents.on('themeChanged', calcBg);
+	globalEvents.on('themeChanging', calcBg);
 
 	watch(() => [props.tab, props.tabs], () => {
 		nextTick(() => {
@@ -147,7 +147,7 @@ onMounted(() => {
 });
 
 onUnmounted(() => {
-	globalEvents.off('themeChanged', calcBg);
+	globalEvents.off('themeChanging', calcBg);
 });
 </script>
 
diff --git a/packages/frontend/src/theme.ts b/packages/frontend/src/theme.ts
index 0f44d777f9..ed2f1d3164 100644
--- a/packages/frontend/src/theme.ts
+++ b/packages/frontend/src/theme.ts
@@ -72,6 +72,9 @@ export function applyTheme(theme: Theme, persist = true) {
 
 	timeout = window.setTimeout(() => {
 		document.documentElement.classList.remove('_themeChanging_');
+
+		// 色計算など再度行えるようにクライアント全体に通知
+		globalEvents.emit('themeChanged');
 	}, 1000);
 
 	const colorScheme = theme.base === 'dark' ? 'dark' : 'light';
@@ -108,7 +111,7 @@ export function applyTheme(theme: Theme, persist = true) {
 	}
 
 	// 色計算など再度行えるようにクライアント全体に通知
-	globalEvents.emit('themeChanged');
+	globalEvents.emit('themeChanging');
 }
 
 function compile(theme: Theme): Record<string, string> {