From f28d30cfc91dc7f95b66e7cc5fe7c9258490b5d8 Mon Sep 17 00:00:00 2001
From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Wed, 7 May 2025 10:32:29 +0900
Subject: [PATCH 1/2] =?UTF-8?q?enhance(frontend):=20=E3=83=86=E3=83=BC?=
=?UTF-8?q?=E3=83=9E=E5=88=87=E3=82=8A=E6=9B=BF=E3=81=88=E3=81=AE=E3=82=A2?=
=?UTF-8?q?=E3=83=8B=E3=83=A1=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92?=
=?UTF-8?q?View=20Transition=E3=81=AB=E5=A4=89=E6=9B=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/components/MkFoldableSection.vue | 16 +++++-
packages/frontend/src/style.scss | 39 ++++++++++++++-
packages/frontend/src/theme.ts | 49 +++++++++++++------
3 files changed, 86 insertions(+), 18 deletions(-)
diff --git a/packages/frontend/src/components/MkFoldableSection.vue b/packages/frontend/src/components/MkFoldableSection.vue
index b9888d9b64..0fa7bea7ab 100644
--- a/packages/frontend/src/components/MkFoldableSection.vue
+++ b/packages/frontend/src/components/MkFoldableSection.vue
@@ -31,9 +31,10 @@ SPDX-License-Identifier: AGPL-3.0-only
diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss
index 341f5cb621..9b8734b4fd 100644
--- a/packages/frontend/src/style.scss
+++ b/packages/frontend/src/style.scss
@@ -90,12 +90,49 @@ html {
}
}
-html._themeChanging_ {
+html._themeChangingFallback_ {
&, * {
transition: background 1s ease, border 1s ease !important;
}
}
+html._themeChanging_ {
+ view-transition-name: theme-changing;
+}
+
+html::view-transition-new(theme-changing) {
+ z-index: 4000001;
+ animation: themeChangingNew 1s ease;
+ animation-fill-mode: forwards;
+}
+
+html::view-transition-old(theme-changing) {
+ z-index: 4000000;
+ animation: themeChangingOld 1s ease;
+ animation-fill-mode: forwards;
+}
+
+@keyframes themeChangingNew {
+ 0% {
+ opacity: 0;
+ }
+
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes themeChangingOld {
+ 0% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+
+}
+
html,
body,
#misskey_app {
diff --git a/packages/frontend/src/theme.ts b/packages/frontend/src/theme.ts
index 268f879d17..064a7c254d 100644
--- a/packages/frontend/src/theme.ts
+++ b/packages/frontend/src/theme.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { ref } from 'vue';
+import { ref, nextTick } from 'vue';
import tinycolor from 'tinycolor2';
import lightTheme from '@@/themes/_light.json5';
import darkTheme from '@@/themes/_dark.json5';
@@ -88,20 +88,7 @@ export async function removeTheme(theme: Theme): Promise {
prefer.commit('themes', themes);
}
-let timeout: number | null = null;
-
-export function applyTheme(theme: Theme, persist = true) {
- if (timeout) window.clearTimeout(timeout);
-
- window.document.documentElement.classList.add('_themeChanging_');
-
- timeout = window.setTimeout(() => {
- window.document.documentElement.classList.remove('_themeChanging_');
-
- // 色計算など再度行えるようにクライアント全体に通知
- globalEvents.emit('themeChanged');
- }, 1000);
-
+function applyThemeInternal(theme: Theme, persist: boolean) {
const colorScheme = theme.base === 'dark' ? 'dark' : 'light';
window.document.documentElement.dataset.colorScheme = colorScheme;
@@ -139,6 +126,38 @@ export function applyTheme(theme: Theme, persist = true) {
globalEvents.emit('themeChanging');
}
+let timeout: number | null = null;
+
+export function applyTheme(theme: Theme, persist = true) {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+
+ if (document.startViewTransition != null && prefer.s.animation) {
+ window.document.documentElement.classList.add('_themeChanging_');
+ document.startViewTransition(async () => {
+ applyThemeInternal(theme, persist);
+ await nextTick();
+ }).finished.then(() => {
+ window.document.documentElement.classList.remove('_themeChanging_');
+ globalEvents.emit('themeChanged');
+ });
+ } else {
+ // TODO: ViewTransition API が主要ブラウザで対応したら消す
+
+ window.document.documentElement.classList.add('_themeChangingFallback_');
+ timeout = window.setTimeout(() => {
+ window.document.documentElement.classList.remove('_themeChangingFallback_');
+
+ // 色計算など再度行えるようにクライアント全体に通知
+ globalEvents.emit('themeChanged');
+ }, 1000);
+
+ applyThemeInternal(theme, persist);
+ }
+}
+
export function compile(theme: Theme): Record {
function getColor(val: string): tinycolor.Instance {
if (val[0] === '@') { // ref (prop)
From ccac9700c08bb53ffee6c89b4fdf7a6b210f45c6 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: Thu, 8 May 2025 11:56:27 +0900
Subject: [PATCH 2/2] fix lint
---
packages/frontend/src/theme.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/frontend/src/theme.ts b/packages/frontend/src/theme.ts
index 064a7c254d..003fd8b6f0 100644
--- a/packages/frontend/src/theme.ts
+++ b/packages/frontend/src/theme.ts
@@ -130,13 +130,13 @@ let timeout: number | null = null;
export function applyTheme(theme: Theme, persist = true) {
if (timeout) {
- clearTimeout(timeout);
+ window.clearTimeout(timeout);
timeout = null;
}
- if (document.startViewTransition != null && prefer.s.animation) {
+ if (window.document.startViewTransition != null && prefer.s.animation) {
window.document.documentElement.classList.add('_themeChanging_');
- document.startViewTransition(async () => {
+ window.document.startViewTransition(async () => {
applyThemeInternal(theme, persist);
await nextTick();
}).finished.then(() => {