diff --git a/dsh-usage/usage-records.json b/dsh-usage/usage-records.json new file mode 100644 index 0000000..9d8ce16 --- /dev/null +++ b/dsh-usage/usage-records.json @@ -0,0 +1 @@ +[{"time":1787101513563,"model":"deepseek-v4-flash","provider":"deepseek-official","purpose":"","inputTokens":61,"outputTokens":456,"cacheReadTokens":455808,"cacheWriteTokens":0,"reasoningTokens":57,"finishReason":"tool-calls"},{"time":1787101520738,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":480861,"outputTokens":2,"cacheReadTokens":0,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"max-tokens"},{"time":1787101573494,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"compaction","inputTokens":273495,"outputTokens":2448,"cacheReadTokens":96256,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101599679,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":69737,"outputTokens":2,"cacheReadTokens":368640,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"max-tokens"},{"time":1787101616660,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"compaction","inputTokens":0,"outputTokens":0,"cacheReadTokens":0,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101617108,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"","inputTokens":438648,"outputTokens":240,"cacheReadTokens":0,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787101654057,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"compaction","inputTokens":6150,"outputTokens":3411,"cacheReadTokens":366976,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101691891,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"","inputTokens":2164,"outputTokens":1718,"cacheReadTokens":438528,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787101715549,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"compaction","inputTokens":4369,"outputTokens":4698,"cacheReadTokens":372736,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101761185,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"","inputTokens":4498,"outputTokens":1076,"cacheReadTokens":440576,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787101777934,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"compaction","inputTokens":17,"outputTokens":5548,"cacheReadTokens":377088,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101828720,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"","inputTokens":1924,"outputTokens":2098,"cacheReadTokens":445056,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787101854064,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"compaction","inputTokens":0,"outputTokens":0,"cacheReadTokens":0,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101855634,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"","inputTokens":3659,"outputTokens":2377,"cacheReadTokens":446976,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787101884249,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"compaction","inputTokens":6223,"outputTokens":4096,"cacheReadTokens":379392,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101926806,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"","inputTokens":2752,"outputTokens":179,"cacheReadTokens":450560,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787101938376,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"compaction","inputTokens":2066,"outputTokens":4856,"cacheReadTokens":385152,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101986120,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"","inputTokens":1099,"outputTokens":521,"cacheReadTokens":453248,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787101986318,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":0,"outputTokens":0,"cacheReadTokens":0,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101986976,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":0,"outputTokens":0,"cacheReadTokens":0,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787101988220,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":186815,"outputTokens":640,"cacheReadTokens":0,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787101997159,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":3273,"outputTokens":114,"cacheReadTokens":186368,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787102002889,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"compaction","inputTokens":18,"outputTokens":4274,"cacheReadTokens":387200,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"error"},{"time":1787102018865,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":393,"outputTokens":126,"cacheReadTokens":189440,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787102043739,"model":"DeepSeek-V4-Flash-0731","provider":"scnet","purpose":"","inputTokens":987,"outputTokens":421,"cacheReadTokens":454272,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787102050021,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":2208,"outputTokens":129,"cacheReadTokens":189440,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"tool-calls"},{"time":1787102054433,"model":"DeepSeek-V4-Flash","provider":"scnet","purpose":"","inputTokens":721,"outputTokens":836,"cacheReadTokens":191488,"cacheWriteTokens":0,"reasoningTokens":0,"finishReason":"stop"}] \ No newline at end of file diff --git a/src/components/AppLayout.vue b/src/components/AppLayout.vue index 6112756..7279472 100644 --- a/src/components/AppLayout.vue +++ b/src/components/AppLayout.vue @@ -10,22 +10,44 @@ const { init } = useMqttBridge() const activeTab = ref<'connections' | 'presets' | 'dashboard'>('dashboard') const isDark = ref(false) +function applyTheme(dark: boolean) { + isDark.value = dark + document.documentElement.classList.toggle('dark', dark) +} + function toggleTheme() { - isDark.value = !isDark.value - document.documentElement.classList.toggle('dark', isDark.value) + applyTheme(!isDark.value) try { localStorage.setItem('mqttx_theme', isDark.value ? 'dark' : 'light') } catch { /* ignore */ } } +function getSystemTheme(): boolean { + return window.matchMedia('(prefers-color-scheme: dark)').matches +} + onMounted(() => { init() - // Restore theme preference + + // Listen for system theme changes + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { + const saved = localStorage.getItem('mqttx_theme') + // Only follow system if user hasn't explicitly set a preference + if (!saved) { + applyTheme(e.matches) + } + }) + + // Restore theme preference, fallback to system try { const saved = localStorage.getItem('mqttx_theme') if (saved === 'dark') { - isDark.value = true - document.documentElement.classList.add('dark') + applyTheme(true) + } else if (saved === 'light') { + applyTheme(false) + } else { + // No saved preference → follow system + applyTheme(getSystemTheme()) } } catch { /* ignore */ } }) @@ -68,7 +90,7 @@ onMounted(() => {
-