dark mode + a bit more polish

This commit is contained in:
nick comer
2024-05-01 21:54:52 -04:00
parent 92e99149c1
commit b826ce9c63
2 changed files with 97 additions and 18 deletions

View File

@@ -140,6 +140,33 @@ body {
background-color: white; background-color: white;
} }
@media (prefers-color-scheme: dark) { .ht-tab:hover {
/* Dark Mode styles go here. */ background-color: #efefef;
}
.ht-tab-location {
color: #e9e9e9;
}
@media (prefers-color-scheme: dark) {
html {
background-color: black;
}
body {
background-color: #2b2b2b;
color: #f2f2f2;
}
.ht-search-wrapper .ht-search-input {
background-color: #2b2b2b;
}
.ht-tab-location {
color: #e9e9e9;
}
.ht-tab:hover {
background-color: #4e4e4e;
}
} }

View File

@@ -33,7 +33,7 @@ function useBackgroundPage(): BackgroundPage {
resolve: (value: T | PromiseLike<T>) => void; resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: any) => void; reject: (reason?: any) => void;
}; };
const waiter = new Map<number, PromiseFinishers<unknown>>(); const waiter = useRef(new Map<number, PromiseFinishers<unknown>>());
useEffect(() => { useEffect(() => {
const msgListener: Parameters< const msgListener: Parameters<
typeof port.current.onMessage.addListener typeof port.current.onMessage.addListener
@@ -41,11 +41,11 @@ function useBackgroundPage(): BackgroundPage {
if (!("id" in message) || typeof message.id !== "number") { if (!("id" in message) || typeof message.id !== "number") {
return; return;
} }
const promfinishers = waiter.get(message.id); const promfinishers = waiter.current.get(message.id);
if (!promfinishers) { if (!promfinishers) {
return; return;
} }
waiter.delete(message.id); waiter.current.delete(message.id);
if (message.error) { if (message.error) {
promfinishers.reject(message.error); promfinishers.reject(message.error);
} else { } else {
@@ -64,14 +64,12 @@ function useBackgroundPage(): BackgroundPage {
listTabs() { listTabs() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const id = ++msgId.current; const id = ++msgId.current;
waiter.set(id, { waiter.current.set(id, {
reject, reject,
resolve(value) { resolve(value) {
console.timeEnd(`bgpage:rpc:listTabs:${id}`);
resolve(value as chrome.tabs.Tab[]); resolve(value as chrome.tabs.Tab[]);
}, },
}); });
console.time(`bgpage:rpc:listTabs:${id}`);
port.current.postMessage({ rpc: "listTabs", id }); port.current.postMessage({ rpc: "listTabs", id });
}); });
}, },
@@ -86,11 +84,14 @@ const focusTab = (tabId: number, windowId: number): void => {
const HighlightMatches: FunctionComponent<{ const HighlightMatches: FunctionComponent<{
text: string; text: string;
match?: FuseResultMatch; match?: Omit<FuseResultMatch, "key">;
}> = ({ text, match }) => { }> = ({ text, match }) => {
if (!match) { if (!match) {
return <>{text}</>; return <>{text}</>;
} }
if (text.toLowerCase().includes("spec.matrix")) {
console.log({ text, match });
}
const parts: JSX.Element[] = []; const parts: JSX.Element[] = [];
const indicies = structuredClone(match.indices) as RangeTuple[]; const indicies = structuredClone(match.indices) as RangeTuple[];
let currentPart = ""; let currentPart = "";
@@ -158,7 +159,29 @@ function faviconURL(t: chrome.tabs.Tab, size: number): string | undefined {
return url.toString(); return url.toString();
} }
const prefersDarkMode = (): boolean => {
return window.matchMedia("(prefers-color-scheme: dark)").matches;
};
const useDarkMode = (): boolean => {
const [dm, setdm] = useState(() => {
return prefersDarkMode();
});
useEffect(() => {
const mql = window.matchMedia("(prefers-color-scheme: dark)");
const onChange = (ev: MediaQueryListEvent) => {
setdm(ev.matches);
};
mql.addEventListener("change", onChange);
return () => {
mql.removeEventListener("change", onChange);
};
}, []);
return dm;
};
const Popup: FunctionComponent = () => { const Popup: FunctionComponent = () => {
const darkMode = useDarkMode();
const [tabSelector, setTabSelector] = useState(0); const [tabSelector, setTabSelector] = useState(0);
const [tabs, setTabs] = useState<chrome.tabs.Tab[]>([]); const [tabs, setTabs] = useState<chrome.tabs.Tab[]>([]);
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
@@ -179,7 +202,6 @@ const Popup: FunctionComponent = () => {
if (tabs.length === 0) { if (tabs.length === 0) {
return; return;
} }
console.log({ tabs });
}, [tabs]); }, [tabs]);
useEffect(() => { useEffect(() => {
@@ -246,7 +268,6 @@ const Popup: FunctionComponent = () => {
const bgpage = useBackgroundPage(); const bgpage = useBackgroundPage();
useEffect(() => { useEffect(() => {
console.time("queryTabs");
bgpage bgpage
.listTabs() .listTabs()
.then((returnedTabs) => { .then((returnedTabs) => {
@@ -255,9 +276,7 @@ const Popup: FunctionComponent = () => {
} }
setTabs(returnedTabs); setTabs(returnedTabs);
}) })
.finally(() => { .finally(() => {});
console.timeEnd("queryTabs");
});
}, []); }, []);
const selectedTabEle = useRef<HTMLDivElement>(null); const selectedTabEle = useRef<HTMLDivElement>(null);
@@ -273,10 +292,29 @@ const Popup: FunctionComponent = () => {
return ( return (
<div> <div>
<div style={{ padding: "1em" }}> <div
style={{ padding: "1em", display: "flex" }}
className="ht-search-wrapper"
>
<div style={{ marginRight: "1em" }}>
<svg
style={{ scale: "0.85" }}
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path
fill={darkMode ? "#e9e9e9" : "#636363"}
d="M23.809 21.646l-6.205-6.205c1.167-1.605 1.857-3.579 1.857-5.711 0-5.365-4.365-9.73-9.731-9.73-5.365 0-9.73 4.365-9.73 9.73 0 5.366 4.365 9.73 9.73 9.73 2.034 0 3.923-.627 5.487-1.698l6.238 6.238 2.354-2.354zm-20.955-11.916c0-3.792 3.085-6.877 6.877-6.877s6.877 3.085 6.877 6.877-3.085 6.877-6.877 6.877c-3.793 0-6.877-3.085-6.877-6.877z"
/>
</svg>
</div>
<input <input
className="ht-search-input"
type="text" type="text"
autoFocus autoFocus
placeholder="Search Tabs"
value={searchQuery} value={searchQuery}
style={{ style={{
width: "100%", width: "100%",
@@ -301,6 +339,9 @@ const Popup: FunctionComponent = () => {
/> />
</div> </div>
<hr style={{ opacity: "0.3", marginTop: "0px" }} /> <hr style={{ opacity: "0.3", marginTop: "0px" }} />
<div style={{ padding: "1em", fontWeight: "bold" }}>
Open Tabs ({tabs.length})
</div>
<div <div
style={{ style={{
maxHeight: "500px", maxHeight: "500px",
@@ -332,7 +373,13 @@ const Popup: FunctionComponent = () => {
ref={i === tabSelector ? selectedTabEle : undefined} ref={i === tabSelector ? selectedTabEle : undefined}
style={{ style={{
padding: "10px", padding: "10px",
backgroundColor: i === selectedTab ? "#e9e9e9" : undefined, cursor: "pointer",
backgroundColor:
i === selectedTab
? darkMode
? "#535353"
: "#e9e9e9"
: undefined,
// favicon support // favicon support
...(enableFavicons ...(enableFavicons
@@ -344,19 +391,24 @@ const Popup: FunctionComponent = () => {
}} }}
> >
{favicURL && ( {favicURL && (
<div className="ht-tab-favicon" style={{ marginRight: "1em" }}> <div
className="ht-tab-favicon"
style={{ marginRight: "1em", padding: ".5em" }}
>
<img width={16} height={16} src={favicURL} /> <img width={16} height={16} src={favicURL} />
</div> </div>
)} )}
<div> <div className="ht-tab-right" style={{ width: "93%" }}>
<div <div
className="ht-tab-title" className="ht-tab-title"
style={{ style={{
color: darkMode ? "#e9e9e9" : "#2b2b2b",
whiteSpace: "nowrap", whiteSpace: "nowrap",
overflow: "hidden", overflow: "hidden",
textOverflow: "ellipsis", textOverflow: "ellipsis",
fontSize: "1.1em", fontSize: "1.1em",
marginBottom: "6px", marginBottom: "6px",
width: "98%",
}} }}
> >
{ {