Skip to content

Commit 5c0741e

Browse files
committed
新增 MutationObserver 监听 data-theme,并用去重逻辑避免和自定义事件重复刷新
1 parent 89d9410 commit 5c0741e

2 files changed

Lines changed: 32 additions & 6 deletions

File tree

static/subtitle-shared.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,13 +880,37 @@
880880
applyState(state, { changedKeys: [], source: 'init' });
881881
cleanupFns.push(subscribeSettings(applyState, { immediate: false }));
882882

883+
var observedThemeDark = isDarkThemeActive();
884+
var applyThemeStateIfChanged = function(source) {
885+
var nextThemeDark = isDarkThemeActive();
886+
if (nextThemeDark === observedThemeDark) return;
887+
observedThemeDark = nextThemeDark;
888+
applyState(getSettings(), { changedKeys: ['theme'], source: source });
889+
};
883890
var onThemeChanged = function() {
884-
applyState(getSettings(), { changedKeys: ['theme'], source: 'subtitle-ui-theme' });
891+
applyThemeStateIfChanged('subtitle-ui-theme-event');
885892
};
886893
window.addEventListener('neko-theme-changed', onThemeChanged);
887894
cleanupFns.push(function() {
888895
window.removeEventListener('neko-theme-changed', onThemeChanged);
889896
});
897+
if (window.MutationObserver && document.documentElement) {
898+
var themeObserver = new MutationObserver(function(mutations) {
899+
for (var i = 0; i < mutations.length; i += 1) {
900+
if (mutations[i].attributeName === 'data-theme') {
901+
applyThemeStateIfChanged('subtitle-ui-theme-attribute');
902+
break;
903+
}
904+
}
905+
});
906+
themeObserver.observe(document.documentElement, {
907+
attributes: true,
908+
attributeFilter: ['data-theme']
909+
});
910+
cleanupFns.push(function() {
911+
themeObserver.disconnect();
912+
});
913+
}
890914

891915
if (window.i18next && typeof window.i18next.on === 'function') {
892916
var onLanguageChanged = function(nextLocale) {

tests/frontend/test_subtitle_incremental.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,25 @@ def test_subtitle_background_opacity_tracks_dark_theme(
5252

5353
result = mock_page.evaluate(
5454
"""
55-
() => {
55+
async () => {
5656
const controller = window.nekoSubtitleShared.initSubtitleUI({ host: 'web' });
5757
const display = document.getElementById('subtitle-display');
5858
const darkBackground = display.style.background;
5959
document.documentElement.removeAttribute('data-theme');
60-
window.dispatchEvent(new CustomEvent('neko-theme-changed', {
61-
detail: { darkMode: false },
62-
}));
60+
await new Promise((resolve) => setTimeout(resolve, 0));
6361
const lightBackground = display.style.background;
62+
document.documentElement.setAttribute('data-theme', 'dark');
63+
await new Promise((resolve) => setTimeout(resolve, 0));
64+
const darkBackgroundAfterAttributeChange = display.style.background;
6465
controller.destroy();
65-
return { darkBackground, lightBackground };
66+
return { darkBackground, lightBackground, darkBackgroundAfterAttributeChange };
6667
}
6768
"""
6869
)
6970

7071
assert "rgba(18, 29, 45, 0.8)" in result["darkBackground"]
7172
assert "rgba(68, 183, 254, 0.8)" in result["lightBackground"]
73+
assert "rgba(18, 29, 45, 0.8)" in result["darkBackgroundAfterAttributeChange"]
7274

7375

7476
@pytest.mark.frontend

0 commit comments

Comments
 (0)