diff --git a/src/Popup.scss b/src/Popup.scss index 4f055c9..2b2c8cb 100644 --- a/src/Popup.scss +++ b/src/Popup.scss @@ -73,8 +73,6 @@ body { background-color: var(--bg-color); margin: 0px 0px; padding: 0px; - display: flex; - flex-direction: column; min-width: 300px; max-width: 800px; max-height: 600px; @@ -86,16 +84,7 @@ body.startup { height: var(--startup-height)!important; } -body > :first-child { - flex: 0 0 auto; -} - -body > :nth-child(2) { - flex: 1 1 auto; -} - body > :nth-child(3), body > :nth-child(3):hover, body > :nth-child(3):focus, body > :nth-child(3):active { - flex: 0 0 auto; box-sizing: content-box; border-top-width: 1px!important; border-top-color: var(--line-color); diff --git a/src/Popup.tsx b/src/Popup.tsx index e405042..b5b1488 100644 --- a/src/Popup.tsx +++ b/src/Popup.tsx @@ -5,8 +5,10 @@ import PopupHeader from './components/PopupHeader'; import PopupContainer from './components/PopupContainer'; import PopupFooter from './components/PopupFooter'; import ContextMenu from './components/ContextMenu'; +import { applyTheme } from './utils/theme'; import './Popup.scss'; + interface PopupProps { config: Configuration } @@ -62,52 +64,4 @@ function adjustHeight(length: number) { const rootStyle = document.documentElement.style; const height = (length + 2) * 30; rootStyle.setProperty('--startup-height', (height > 600) ? '600px' : height + 'px'); -} - -function applyTheme(theme: 'auto' | 'light' | 'dark') { - const rootElm = document.documentElement; - - const applyDarkTheme = () => { - rootElm.classList.add('theme-dark'); - rootElm.classList.remove('theme-light'); - chrome.action.setIcon({ - path: { - "16": "/icons/qbm16-dark.png", - "32": "/icons/qbm32-dark.png" - } - }); - } - - const applyLightTheme = () => { - rootElm.classList.add('theme-light'); - rootElm.classList.remove('theme-dark'); - chrome.action.setIcon({ - path: { - "16": "/icons/qbm16.png", - "32": "/icons/qbm32.png" - } - }); - } - - switch (theme) { - case 'light': - applyLightTheme(); - break; - case 'dark': - applyDarkTheme(); - break; - case 'auto': - default: - const mql = window.matchMedia('(prefers-color-scheme: dark)'); - const colorSchemeTest = (e: MediaQueryListEvent | MediaQueryList) => { - if (e.matches) { - applyDarkTheme(); - } else { - applyLightTheme(); - } - }; - mql.onchange = colorSchemeTest; - colorSchemeTest(mql); - break; - } } \ No newline at end of file diff --git a/src/components/PopupContainer/OptionsItem.tsx b/src/components/PopupContainer/OptionsItem.tsx index cde7e9c..05ae109 100644 --- a/src/components/PopupContainer/OptionsItem.tsx +++ b/src/components/PopupContainer/OptionsItem.tsx @@ -20,22 +20,21 @@ export interface OptionsItem { type: 'radio' | 'checkbox'; /** This item's options */ options: Option[]; + /** callback after value change */ + callback?: (val: any) => void; } interface OptionsItemProps extends OptionsItem { } -export default function OptionsItem({ name: itemName, storage, type, options }: OptionsItemProps) { +export default function OptionsItem({ name: itemName, storage, type, options, callback }: OptionsItemProps) { const [value, setValue] = useState(options[0].value); const name = itemName.replace('_', '-'); const saveValue = async (val: any) => { - chrome.storage.local.set({ [storage]: val }) - .then(() => { - setValue(val); - }); - - if (itemName === 'root_folder') { - chrome.storage.local.set({ startup: [val, 18] }); + await chrome.storage.local.set({ [storage]: val }); + setValue(val); + if (callback && typeof callback === 'function') { + callback(val); } }; diff --git a/src/components/PopupContainer/OptionsPage.tsx b/src/components/PopupContainer/OptionsPage.tsx index 72e2ad2..e5729f0 100644 --- a/src/components/PopupContainer/OptionsPage.tsx +++ b/src/components/PopupContainer/OptionsPage.tsx @@ -1,6 +1,7 @@ import { h } from 'preact'; import { useEffect, useState } from 'preact/hooks'; import OptionsItemComponent, { OptionsItem } from './OptionsItem'; +import { applyTheme } from '../../utils/theme'; import "./OptionsPage.scss"; const optionsItems: OptionsItem[] = [ @@ -92,7 +93,10 @@ const optionsItems: OptionsItem[] = [ name: 'root_folder', storage: 'root', type: 'radio', - options: [{ name: '', value: '0' }] + options: [{ name: '', value: '0' }], + callback: (val) => { + chrome.storage.local.set({ startup: [val, 18] }); + } }, { name: 'color_theme', @@ -111,7 +115,10 @@ const optionsItems: OptionsItem[] = [ name: 'dark', value: 'dark', } - ] + ], + callback: (val) => { + applyTheme(val); + } }, { name: 'scroll_layout', diff --git a/src/components/PopupContainer/PopupContainer.scss b/src/components/PopupContainer/PopupContainer.scss index 78ff2b4..1081d08 100644 --- a/src/components/PopupContainer/PopupContainer.scss +++ b/src/components/PopupContainer/PopupContainer.scss @@ -4,6 +4,7 @@ position: relative; max-width: 800px; min-width: 300px; + max-height: 538px; &-horiz { overflow-x: auto; diff --git a/src/utils/theme.ts b/src/utils/theme.ts new file mode 100644 index 0000000..8d0b673 --- /dev/null +++ b/src/utils/theme.ts @@ -0,0 +1,51 @@ +let mql: MediaQueryList | null = null; + +export function applyTheme(theme: 'auto' | 'light' | 'dark') { + const rootElm = document.documentElement; + + const applyDarkTheme = () => { + rootElm.classList.add('theme-dark'); + rootElm.classList.remove('theme-light'); + chrome.action.setIcon({ + path: { + "16": "/icons/qbm16-dark.png", + "32": "/icons/qbm32-dark.png" + } + }); + } + + const applyLightTheme = () => { + rootElm.classList.add('theme-light'); + rootElm.classList.remove('theme-dark'); + chrome.action.setIcon({ + path: { + "16": "/icons/qbm16.png", + "32": "/icons/qbm32.png" + } + }); + } + + switch (theme) { + case 'light': + applyLightTheme(); + break; + case 'dark': + applyDarkTheme(); + break; + case 'auto': + default: + const colorSchemeTest = (e: MediaQueryListEvent | MediaQueryList) => { + if (e.matches) { + applyDarkTheme(); + } else { + applyLightTheme(); + } + }; + if(!mql) { + mql = window.matchMedia('(prefers-color-scheme: dark)'); + mql.addEventListener("change", colorSchemeTest); + } + colorSchemeTest(mql); + break; + } +} \ No newline at end of file