From 44bc838f6aeb4ac5b1f7f67e47edb4fd10286733 Mon Sep 17 00:00:00 2001
From: qixing-jk <street-anime-olive@duck.com>
Date: Sun, 7 Sep 2025 22:06:28 +0800
Subject: feat(extension): Add theme and dynamic icon support (#1894)

* feat: add theme selection support to browser extension

- integrate theme settings with plugin settings storage
- add theme selector dropdown to options page
- implement custom ThemeProvider using plugin settings
- include new Select UI component for theme selection

* feat(extension): add dynamic icon theme switching (#1100)

Add updateIcon() function to dynamically change extension icon based on
selected theme (light/dark/system). Update icon on initial load and when
settings change to reflect current theme preference.

Closes #1100

* fix(extension): switch dark mode strategy from media to selector

This allows manual control over dark mode via class toggling rather
than relying on the OS/browser preference.

* fix(extension): move icon update logic to content script

The `window` object is inaccessible in the background script, causing
icon updates to fail. This change relocates the icon update logic to the
content script where `window.matchMedia` is available.

- Remove `updateIcon` function from background script
- Add icon update logic to `ThemeProvider` component
- Consolidate theme and icon updates in single effect

* feat(settings): make theme field required in settings schema

Remove optional flag from theme field to enforce presence in
settings validation schema.

* deps: Upgrade the extension deps

* minor fixes

---------

Co-authored-by: MohamedBassem <me@mbassem.com>
---
 apps/browser-extension/src/OptionsPage.tsx | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

(limited to 'apps/browser-extension/src/OptionsPage.tsx')

diff --git a/apps/browser-extension/src/OptionsPage.tsx b/apps/browser-extension/src/OptionsPage.tsx
index 41b72178..ef51bc02 100644
--- a/apps/browser-extension/src/OptionsPage.tsx
+++ b/apps/browser-extension/src/OptionsPage.tsx
@@ -2,14 +2,23 @@ import React, { useEffect } from "react";
 import { useNavigate } from "react-router-dom";
 
 import { Button } from "./components/ui/button";
+import {
+  Select,
+  SelectContent,
+  SelectItem,
+  SelectTrigger,
+  SelectValue,
+} from "./components/ui/select";
 import Logo from "./Logo";
 import Spinner from "./Spinner";
 import usePluginSettings from "./utils/settings";
+import { useTheme } from "./utils/ThemeProvider";
 import { api } from "./utils/trpc";
 
 export default function OptionsPage() {
   const navigate = useNavigate();
   const { settings, setSettings } = usePluginSettings();
+  const { setTheme, theme } = useTheme();
 
   const { data: whoami, error: whoAmIError } = api.users.whoami.useQuery(
     undefined,
@@ -63,6 +72,19 @@ export default function OptionsPage() {
         <span className="my-auto">Logged in as:</span>
         {loggedInMessage}
       </div>
+      <div className="flex gap-2">
+        <span className="my-auto">Theme:</span>
+        <Select value={theme} onValueChange={setTheme}>
+          <SelectTrigger className="w-24">
+            <SelectValue placeholder="Theme" />
+          </SelectTrigger>
+          <SelectContent>
+            <SelectItem value="light">Light</SelectItem>
+            <SelectItem value="dark">Dark</SelectItem>
+            <SelectItem value="system">System</SelectItem>
+          </SelectContent>
+        </Select>
+      </div>
       <Button onClick={onLogout}>Logout</Button>
     </div>
   );
-- 
cgit v1.2.3-70-g09d2

