fix: 深色模式入口移至外观分组并移除侧边栏按钮(1.0.6)

- 设置入口 group 改为官方 interface(外观)分组
- 删除侧边栏 ThemeToggle 注入器及组件,设置页成为唯一入口
- verify-toggle.py 改为直接驱动主题状态并校验翻转
- 同步 README 与脚本文档,版本升级 1.0.6
This commit is contained in:
2026-08-08 19:25:27 +08:00
parent 5cbce86e03
commit 394613f516
10 changed files with 174 additions and 141 deletions
-64
View File
@@ -1,64 +0,0 @@
<script setup lang="ts">
import IconSunLine from '~icons/ri/sun-line'
import IconMoonLine from '~icons/ri/moon-line'
import { useDarkMode } from '../composables/useDarkMode'
const { isDark, toggle } = useDarkMode()
</script>
<template>
<button
type="button"
class="theme-toggle"
:aria-pressed="isDark"
:aria-label="isDark ? '切换到浅色模式' : '切换到深色模式'"
@click="toggle"
>
<IconSunLine v-if="isDark" class="theme-toggle__icon" />
<IconMoonLine v-else class="theme-toggle__icon" />
<span class="theme-toggle__label">
{{ isDark ? '浅色模式' : '深色模式' }}
</span>
</button>
</template>
<style scoped>
.theme-toggle {
display: flex;
align-items: center;
gap: 0.5rem;
width: 100%;
padding: 0.5rem 0.75rem;
border: 0;
background: transparent;
color: var(--halo-text-secondary);
font: inherit;
cursor: pointer;
border-radius: 0.25rem;
transition:
background-color 0.15s,
color 0.15s;
user-select: none;
}
.theme-toggle:hover {
background-color: var(--halo-bg-hover);
color: var(--halo-text-primary);
}
.theme-toggle:focus-visible {
outline: 2px solid var(--halo-accent-primary);
outline-offset: 2px;
}
.theme-toggle__icon {
width: 1.125rem;
height: 1.125rem;
flex-shrink: 0;
}
.theme-toggle__label {
font-size: 0.8125rem;
white-space: nowrap;
}
</style>
+2 -4
View File
@@ -3,10 +3,7 @@ import { IconPalette } from '@halo-dev/components'
import { markRaw } from 'vue'
import './styles/index.css'
import { initDarkReaderEngine } from './darkreader-engine'
import { injectThemeToggle } from './injector'
// 在插件加载后将切换器注入到侧边栏,暗色转换完全交给 Dark Reader
injectThemeToggle()
initDarkReaderEngine()
export default definePlugin({
@@ -23,7 +20,8 @@ export default definePlugin({
searchable: true,
menu: {
name: '深色模式',
group: '偏好设置',
// Halo 官方「外观」分组
group: 'interface',
icon: markRaw(IconPalette),
priority: 50,
},
-46
View File
@@ -1,46 +0,0 @@
import { createVNode, render } from 'vue'
import ThemeToggle from './components/ThemeToggle.vue'
const CONTAINER_CLASS = 'plugin-dark-mode-toggle'
const TARGET_SELECTOR = '.sidebar__profile'
let mounted = false
/**
* 将 ThemeToggle 注入到侧边栏中 UserProfileBanner 上方。
* 使用 MutationObserver 等待侧边栏 DOM 渲染完成。
*/
export function injectThemeToggle(): void {
if (mounted) return
// 先尝试直接查找(侧边栏可能已经渲染)
tryMount()
// 如果还没渲染,等待 DOM 变化
if (!mounted) {
const observer = new MutationObserver(() => {
tryMount()
if (mounted) observer.disconnect()
})
observer.observe(document.body, { childList: true, subtree: true })
}
}
function tryMount(): void {
// 避免重复挂载
if (document.querySelector(`.${CONTAINER_CLASS}`)) {
mounted = true
return
}
const profileEl = document.querySelector(TARGET_SELECTOR)
if (!profileEl?.parentNode) return
const container = document.createElement('div')
container.className = CONTAINER_CLASS
profileEl.parentNode.insertBefore(container, profileEl)
const vnode = createVNode(ThemeToggle)
render(vnode, container)
mounted = true
}
+10 -3
View File
@@ -20,7 +20,10 @@ const modeOptions: { value: ThemeMode; label: string; description: string }[] =
const optionEls = ref<HTMLButtonElement[]>([])
const activeIndex = computed(() =>
Math.max(0, modeOptions.findIndex((option) => option.value === theme.value)),
Math.max(
0,
modeOptions.findIndex((option) => option.value === theme.value),
),
)
function setOptionRef(el: unknown, index: number): void {
@@ -79,7 +82,11 @@ function onKeydown(event: KeyboardEvent): void {
:class="{ 'is-active': theme === option.value }"
:aria-checked="theme === option.value"
:tabindex="theme === option.value ? 0 : -1"
:ref="(el: unknown) => { setOptionRef(el, index) }"
:ref="
(el: unknown) => {
setOptionRef(el, index)
}
"
@click="setTheme(option.value)"
>
<div class="dark-mode-settings__option-label">{{ option.label }}</div>
@@ -177,4 +184,4 @@ function onKeydown(event: KeyboardEvent): void {
font-size: 0.8125rem;
color: var(--halo-text-tertiary);
}
</style>
</style>