From 7a4b1907b19569ce99c05205ee403d6da01950dd Mon Sep 17 00:00:00 2001
From: TAKAHASHI Shuuji <shuuji3@gmail.com>
Date: Sat, 30 Nov 2024 23:41:33 +0900
Subject: [PATCH] chore: change default theme color and fix color contrast
 (#3062)

---
 components/nav/NavLogo.vue                  |  3 ++
 components/settings/SettingsThemeColors.vue | 43 ++++++++++++++++++---
 constants/index.ts                          |  1 +
 3 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/components/nav/NavLogo.vue b/components/nav/NavLogo.vue
index f541f257..6fc5549d 100644
--- a/components/nav/NavLogo.vue
+++ b/components/nav/NavLogo.vue
@@ -1,3 +1,6 @@
+<script setup lang="ts">
+</script>
+
 <template>
   <span shrink-0 aspect="1/1" sm:h-8 xl:h-10 class="rtl-flip"><svg
     xmlns="http://www.w3.org/2000/svg" w-full
diff --git a/components/settings/SettingsThemeColors.vue b/components/settings/SettingsThemeColors.vue
index 6caceb10..1fc3c946 100644
--- a/components/settings/SettingsThemeColors.vue
+++ b/components/settings/SettingsThemeColors.vue
@@ -1,10 +1,42 @@
 <script setup lang="ts">
 import type { ThemeColors } from '~/composables/settings'
+import { THEME_COLORS } from '~/constants'
+
+const themes = await import('~/constants/themes.json').then((r) => {
+  const map = new Map<'dark' | 'light', [string, ThemeColors][]>([['dark', []], ['light', []]])
+  const themes = r.default as [string, ThemeColors][]
+  for (const [key, theme] of themes) {
+    map.get('dark')!.push([key, theme])
+    map.get('light')!.push([key, {
+      ...theme,
+      '--c-primary': `color-mix(in srgb, ${theme['--c-primary']}, black 25%)`,
+    }])
+  }
+  return map
+})
 
-const themes = await import('~/constants/themes.json').then(r => r.default) as [string, ThemeColors][]
 const settings = useUserSettings()
 
-const currentTheme = computed(() => settings.value.themeColors?.['--theme-color-name'] || themes[0][1]['--theme-color-name'])
+const media = useMediaQuery('(prefers-color-scheme: dark)')
+
+const colorMode = useColorMode()
+
+const useThemes = shallowRef<[string, ThemeColors][]>([])
+
+watch(() => colorMode.preference, (cm) => {
+  const dark = cm === 'dark' || (cm === 'system' && media.value)
+  const newThemes = dark ? themes.get('dark')! : themes.get('light')!
+  const key = settings.value.themeColors?.['--theme-color-name'] || THEME_COLORS.defaultTheme
+  for (const [k, theme] of newThemes) {
+    if (k === key) {
+      settings.value.themeColors = theme
+      break
+    }
+  }
+  useThemes.value = newThemes
+}, { immediate: true, flush: 'post' })
+
+const currentTheme = computed(() => settings.value.themeColors?.['--theme-color-name'] || THEME_COLORS.defaultTheme)
 
 function updateTheme(theme: ThemeColors) {
   settings.value.themeColors = theme
@@ -18,10 +50,11 @@ function updateTheme(theme: ThemeColors) {
     </h2>
     <div flex="~ gap4 wrap" p2 role="group" aria-labelledby="interface-tc">
       <button
-        v-for="[key, theme] in themes" :key="key"
+        v-for="[key, theme] in useThemes" :key="key"
         :style="{
-          'background': key,
-          '--local-ring-color': key,
+          '--rgb-primary': theme['--rgb-primary'],
+          'background': theme['--c-primary'],
+          '--local-ring-color': theme['--c-primary'],
         }"
         type="button"
         :class="currentTheme === theme['--theme-color-name'] ? 'ring-2' : 'scale-90'"
diff --git a/constants/index.ts b/constants/index.ts
index aff99d1f..2ded6500 100644
--- a/constants/index.ts
+++ b/constants/index.ts
@@ -31,6 +31,7 @@ export const HANDLED_MASTO_URLS = /^(https?:\/\/)?([\w\-]+\.)+\w+\/(@[@\w\-.]+)(
 export const NOTIFICATION_FILTER_TYPES: mastodon.v1.NotificationType[] = ['status', 'reblog', 'follow', 'follow_request', 'favourite', 'poll', 'update', 'admin.sign_up', 'admin.report']
 
 export const THEME_COLORS = {
+  defaultTheme: '#cc7d24',
   themeDark: '#111111',
   themeLight: '#fafafa',
   backgroundDark: '#fafafa',