Add the Theme Switcher storage and options functionality.
This commit is contained in:
parent
893a2173f3
commit
9d5f0d1afc
|
@ -8,5 +8,6 @@ export {JumpToNewCommentSetting} from "./jump-to-new-comment.js";
|
|||
export {MarkdownToolbarSetting} from "./markdown-toolbar.js";
|
||||
export {MiscellaneousSetting} from "./miscellaneous.js";
|
||||
export {ThemedLogoSetting} from "./themed-logo.js";
|
||||
export {ThemeSwitcherSetting} from "./theme-switcher.js";
|
||||
export {UserLabelsSetting} from "./user-labels.js";
|
||||
export {UsernameColorsSetting} from "./username-colors.js";
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
import {Component} from "preact";
|
||||
import {type Value} from "@holllo/webextension-storage";
|
||||
import {
|
||||
Data,
|
||||
Feature,
|
||||
fromStorage,
|
||||
type ThemeSwitcherData,
|
||||
} from "../../storage/exports.js";
|
||||
import {Setting, type SettingProps} from "./index.js";
|
||||
|
||||
type State = {
|
||||
data: Value<ThemeSwitcherData> | undefined;
|
||||
hasUnsavedChanges: boolean;
|
||||
themesList: Array<[string, string]>;
|
||||
};
|
||||
|
||||
export class ThemeSwitcherSetting extends Component<SettingProps, State> {
|
||||
constructor(props: SettingProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
data: undefined,
|
||||
hasUnsavedChanges: false,
|
||||
themesList: [],
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const themesList = await fromStorage(Data.ThemesList);
|
||||
this.setState({
|
||||
data: await fromStorage(Feature.ThemeSwitcher),
|
||||
themesList: themesList.value,
|
||||
});
|
||||
}
|
||||
|
||||
onChange = (event: Event, key: keyof ThemeSwitcherData) => {
|
||||
const {data} = this.state;
|
||||
const target = event.target as HTMLInputElement | HTMLSelectElement;
|
||||
|
||||
if (data === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.value[key] = target.value;
|
||||
this.setState({data, hasUnsavedChanges: true});
|
||||
};
|
||||
|
||||
save = async () => {
|
||||
const {data} = this.state;
|
||||
if (data === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
await data.save();
|
||||
this.setState({hasUnsavedChanges: false});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {data, hasUnsavedChanges, themesList} = this.state;
|
||||
if (data === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const themeOptions = themesList.map(([value, text]) => (
|
||||
<option value={value}>{text}</option>
|
||||
));
|
||||
|
||||
const unsavedChanges = hasUnsavedChanges ? "unsaved-changes" : "";
|
||||
|
||||
return (
|
||||
<Setting {...this.props}>
|
||||
<p class="info">
|
||||
Automatically switch between two themes at certain times of the day.
|
||||
</p>
|
||||
|
||||
<button
|
||||
class={`button margin-bottom-8 has-save-status ${unsavedChanges}`}
|
||||
onClick={this.save}
|
||||
>
|
||||
Save{hasUnsavedChanges ? "*" : ""}
|
||||
</button>
|
||||
|
||||
<p>
|
||||
Switch to{" "}
|
||||
<select
|
||||
class="styled-select"
|
||||
onChange={(event) => {
|
||||
this.onChange(event, "themeA");
|
||||
}}
|
||||
value={data.value.themeA}
|
||||
>
|
||||
{themeOptions}
|
||||
</select>{" "}
|
||||
at{" "}
|
||||
<input
|
||||
class="styled-text-input"
|
||||
onChange={(event) => {
|
||||
this.onChange(event, "hourA");
|
||||
}}
|
||||
type="text"
|
||||
value={data.value.hourA}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Switch to{" "}
|
||||
<select
|
||||
class="styled-select"
|
||||
onChange={(event) => {
|
||||
this.onChange(event, "themeB");
|
||||
}}
|
||||
value={data.value.themeB}
|
||||
>
|
||||
{themeOptions}
|
||||
</select>{" "}
|
||||
at{" "}
|
||||
<input
|
||||
class="styled-text-input"
|
||||
onChange={(event) => {
|
||||
this.onChange(event, "hourB");
|
||||
}}
|
||||
type="text"
|
||||
value={data.value.hourB}
|
||||
/>
|
||||
</p>
|
||||
</Setting>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import {
|
|||
JumpToNewCommentSetting,
|
||||
MarkdownToolbarSetting,
|
||||
MiscellaneousSetting,
|
||||
ThemeSwitcherSetting,
|
||||
ThemedLogoSetting,
|
||||
UserLabelsSetting,
|
||||
UsernameColorsSetting,
|
||||
|
@ -83,6 +84,13 @@ export const features: FeatureData[] = [
|
|||
title: "Miscellaneous",
|
||||
component: MiscellaneousSetting,
|
||||
},
|
||||
{
|
||||
availableSince: new Date("2023-12-24"),
|
||||
index: 0,
|
||||
key: Feature.ThemeSwitcher,
|
||||
title: "Theme Switcher",
|
||||
component: ThemeSwitcherSetting,
|
||||
},
|
||||
{
|
||||
availableSince: new Date("2022-02-27"),
|
||||
index: 0,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
@mixin button {
|
||||
--button-color: var(--blue);
|
||||
--button-color: var(--save-status-color, var(--blue));
|
||||
--button-color-alt: var(--dark-blue);
|
||||
|
||||
background-color: var(--button-color);
|
||||
|
|
|
@ -157,10 +157,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
.styled-text-input,
|
||||
.styled-select {
|
||||
background-color: var(--background-primary);
|
||||
border: 1px solid var(--save-status-color, var(--blue));
|
||||
color: var(--foreground);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.margin-bottom-8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ export enum Feature {
|
|||
MarkdownToolbar = "markdown-toolbar",
|
||||
Miscellaneous = "miscellaneous-features",
|
||||
ThemedLogo = "themed-logo",
|
||||
ThemeSwitcher = "theme-switcher",
|
||||
UserLabels = "user-labels",
|
||||
UsernameColors = "username-colors",
|
||||
}
|
||||
|
|
|
@ -27,6 +27,23 @@ export type HideVotesData = {
|
|||
ownTopics: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* The data stored for the Theme Switcher feature.
|
||||
*/
|
||||
export type ThemeSwitcherData = {
|
||||
/** The hour to switch to theme A. */
|
||||
hourA: string;
|
||||
|
||||
/** The hour to switch to theme B. */
|
||||
hourB: string;
|
||||
|
||||
/** The value of the theme from the theme selector for the first theme. */
|
||||
themeA: string;
|
||||
|
||||
/** The value of the theme from the theme selector for the second theme. */
|
||||
themeB: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* All storage {@link Value}s stored in WebExtension storage.
|
||||
*/
|
||||
|
@ -134,6 +151,18 @@ export const storageValues = {
|
|||
},
|
||||
storage: browser.storage.sync,
|
||||
}),
|
||||
[Feature.ThemeSwitcher]: createValue<ThemeSwitcherData>({
|
||||
deserialize: (input) => JSON.parse(input) as ThemeSwitcherData,
|
||||
serialize: (input) => JSON.stringify(input),
|
||||
key: Feature.ThemeSwitcher,
|
||||
value: {
|
||||
hourA: "09:00",
|
||||
hourB: "21:00",
|
||||
themeA: "white",
|
||||
themeB: "black",
|
||||
},
|
||||
storage: browser.storage.sync,
|
||||
}),
|
||||
[Feature.UserLabels]: collectUserLabels(),
|
||||
[Feature.UsernameColors]: collectUsernameColors(),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue