feat(fe): enable allow background customization and auto theme switching in fe

This commit is contained in:
hexxa 2022-04-09 19:22:58 +08:00 committed by Hexxa
parent f55581efb8
commit 939eb8e8b7
7 changed files with 176 additions and 115 deletions

View file

@ -371,7 +371,7 @@
color: #16a085;
}
.theme-default a:hover {
color: cc#2ecc71;
color: #2ecc71;
}
.theme-default input:focus {
opacity: 0.8;

View file

@ -34,6 +34,7 @@ describe("PaneSettings", () => {
const paneSettings = new PaneSettings({
msg: coreState.msg,
login: coreState.login,
ui: coreState.ui,
update: (updater: (prevState: ICoreState) => ICoreState) => {},
});

View file

@ -62,6 +62,7 @@ export class SettingsDialog extends React.Component<Props, State, {}> {
<PaneSettings
login={this.props.login}
msg={this.props.msg}
ui={this.props.ui}
update={this.props.update}
/>
</div>

View file

@ -576,20 +576,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
return (
<div className="font-m">
<Container>
<Flexbox
children={List([
<h5 className="title-m">{this.props.msg.pkg.get("siteSettings")}</h5>,
<button onClick={this.addUser} className="button-default">
{this.props.msg.pkg.get("update")}
</button>,
])}
childrenStyles={List([{}, { justifyContent: "flex-end" }])}
/>
</Container>
<Container>
<BgCfg
<SiteCfg
ui={this.props.ui}
msg={this.props.msg}
update={this.props.update}
@ -718,20 +705,26 @@ export class AdminPane extends React.Component<Props, State, {}> {
}
}
interface BgProps {
interface SiteCfgProps {
msg: MsgProps;
ui: UIProps;
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
}
interface BgState { }
export class BgCfg extends React.Component<BgProps, BgState, {}> {
interface SiteCfgState {}
export class SiteCfg extends React.Component<SiteCfgProps, SiteCfgState, {}> {
onChangeSiteName = (ev: React.ChangeEvent<HTMLInputElement>) => {
updater().setClientCfg({ ...this.props.ui.clientCfg, siteName: ev.target.value });
updater().setClientCfg({
...this.props.ui.clientCfg,
siteName: ev.target.value,
});
this.props.update(updater().updateUI);
};
onChangeSiteDesc = (ev: React.ChangeEvent<HTMLInputElement>) => {
updater().setClientCfg({ ...this.props.ui.clientCfg, siteDesc: ev.target.value });
updater().setClientCfg({
...this.props.ui.clientCfg,
siteDesc: ev.target.value,
});
this.props.update(updater().updateUI);
};
onChangeAllowSetBg = (enabled: boolean) => {
@ -782,7 +775,7 @@ export class BgCfg extends React.Component<BgProps, BgState, {}> {
this.props.update(updater().updateUI);
};
constructor(p: BgProps) {
constructor(p: SiteCfgProps) {
super(p);
}
@ -870,7 +863,9 @@ export class BgCfg extends React.Component<BgProps, BgState, {}> {
<div>
<Flexbox
children={List([
<h5 className="title-m">{this.props.msg.pkg.get("cfg.bg")}</h5>,
<h5 className="title-m">
{this.props.msg.pkg.get("siteSettings")}
</h5>,
<span>
<button
@ -912,13 +907,19 @@ export class BgCfg extends React.Component<BgProps, BgState, {}> {
/>
</span>
<div className="hr"></div>
<div>
<div className="label">{this.props.msg.pkg.get("allowSetBg")}</div>
<button
onClick={() => {
this.onChangeAllowSetBg(true);
}}
className="button-default inline-block margin-r-m"
className={`${
this.props.ui.clientCfg.allowSetBg
? "white-font focus-bg"
: "button-default"
} inline-block margin-r-m`}
>
{this.props.msg.pkg.get("term.enabled")}
</button>
@ -926,19 +927,29 @@ export class BgCfg extends React.Component<BgProps, BgState, {}> {
onClick={() => {
this.onChangeAllowSetBg(false);
}}
className="button-default inline-block margin-r-m"
className={`${
this.props.ui.clientCfg.allowSetBg
? "button-default"
: "white-font focus-bg"
} inline-block margin-r-m`}
>
{this.props.msg.pkg.get("term.disabled")}
</button>
</div>
<div className="hr"></div>
<div>
<div className="label">{this.props.msg.pkg.get("autoTheme")}</div>
<button
onClick={() => {
this.onChangeAutoTheme(true);
}}
className="button-default inline-block margin-r-m"
className={`${
this.props.ui.clientCfg.autoTheme
? "white-font focus-bg"
: "button-default"
} inline-block margin-r-m`}
>
{this.props.msg.pkg.get("term.enabled")}
</button>
@ -946,7 +957,11 @@ export class BgCfg extends React.Component<BgProps, BgState, {}> {
onClick={() => {
this.onChangeAutoTheme(false);
}}
className="button-default inline-block margin-r-m"
className={`${
this.props.ui.clientCfg.autoTheme
? "button-default"
: "white-font focus-bg"
} inline-block margin-r-m`}
>
{this.props.msg.pkg.get("term.disabled")}
</button>

View file

@ -15,6 +15,7 @@ import { loadingCtrl, ctrlOn, ctrlOff } from "../common/controls";
export interface Props {
login: LoginProps;
msg: MsgProps;
ui: UIProps;
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
}
@ -211,6 +212,86 @@ export class PaneSettings extends React.Component<Props, State, {}> {
render() {
const errRows = this.prepareErrorRows();
const bgConfigPane = this.props.ui.clientCfg.allowSetBg ? (
<Container>
<Flexbox
children={List([
<h5 className="title-m">{this.props.msg.pkg.get("cfg.bg")}</h5>,
<button className="button-default" onClick={this.syncPreferences}>
{this.props.msg.pkg.get("update")}
</button>,
])}
childrenStyles={List([{}, { justifyContent: "flex-end" }])}
/>
<div className="hr"></div>
<div>
<div className="inline-block margin-r-m">
<div className="label">{this.props.msg.pkg.get("cfg.bg.url")}</div>
<input
name="bg_url"
type="text"
onChange={this.changeBgUrl}
value={this.props.login.preferences.bg.url}
placeholder={this.props.msg.pkg.get("cfg.bg.url")}
/>
</div>
<div className="inline-block margin-r-m">
<div className="label">
{this.props.msg.pkg.get("cfg.bg.repeat")}
</div>
<input
name="bg_repeat"
type="text"
onChange={this.changeBgRepeat}
value={this.props.login.preferences.bg.repeat}
placeholder={this.props.msg.pkg.get("cfg.bg.repeat")}
/>
</div>
<div className="inline-block margin-r-m">
<div className="label">{this.props.msg.pkg.get("cfg.bg.pos")}</div>
<input
name="bg_pos"
type="text"
onChange={this.changeBgPos}
value={this.props.login.preferences.bg.position}
placeholder={this.props.msg.pkg.get("cfg.bg.pos")}
/>
</div>
<div className="inline-block margin-r-m">
<div className="label">
{this.props.msg.pkg.get("cfg.bg.align")}
</div>
<input
name="bg_align"
type="text"
onChange={this.changeBgAlign}
value={this.props.login.preferences.bg.align}
placeholder={this.props.msg.pkg.get("cfg.bg.align")}
/>
</div>
<div className="inline-block margin-r-m">
<div className="label">
{this.props.msg.pkg.get("cfg.bg.bgColor")}
</div>
<input
name="bg_bgColor"
type="text"
onChange={this.changeBgBgColor}
value={this.props.login.preferences.bg.bgColor}
placeholder={this.props.msg.pkg.get("cfg.bg.bgColor")}
/>
</div>
</div>
</Container>
) : null;
const errorReportPane =
errRows.size > 0 ? (
<Container>
@ -361,7 +442,11 @@ export class PaneSettings extends React.Component<Props, State, {}> {
onClick={() => {
this.setLan("en_US");
}}
className="button-default inline-block margin-r-m"
className={`${
this.props.login.preferences.lan === "en_US"
? "focus-bg white-font"
: "button-default"
} inline-block margin-r-m`}
>
{this.props.msg.pkg.get("enUS")}
</button>
@ -369,7 +454,11 @@ export class PaneSettings extends React.Component<Props, State, {}> {
onClick={() => {
this.setLan("zh_CN");
}}
className="button-default inline-block margin-r-m"
className={`${
this.props.login.preferences.lan === "zh_CN"
? "focus-bg white-font"
: "button-default"
} inline-block margin-r-m`}
>
{this.props.msg.pkg.get("zhCN")}
</button>
@ -391,7 +480,11 @@ export class PaneSettings extends React.Component<Props, State, {}> {
onClick={() => {
this.setTheme("light");
}}
className="button-default inline-block margin-r-m"
className={`${
this.props.login.preferences.theme === "light"
? "focus-bg white-font"
: "button-default"
} inline-block margin-r-m`}
>
{this.props.msg.pkg.get("theme.light")}
</button>
@ -399,7 +492,11 @@ export class PaneSettings extends React.Component<Props, State, {}> {
onClick={() => {
this.setTheme("dark");
}}
className="button-default inline-block margin-r-m"
className={`${
this.props.login.preferences.theme === "dark"
? "focus-bg white-font"
: "button-default"
} inline-block margin-r-m`}
>
{this.props.msg.pkg.get("theme.dark")}
</button>
@ -443,88 +540,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
</div>
</Container> */}
<Container>
<Flexbox
children={List([
<h5 className="title-m">{this.props.msg.pkg.get("cfg.bg")}</h5>,
<button className="button-default" onClick={this.syncPreferences}>
{this.props.msg.pkg.get("update")}
</button>,
])}
childrenStyles={List([{}, { justifyContent: "flex-end" }])}
/>
<div className="hr"></div>
<div>
<div className="inline-block margin-r-m">
<div className="label">
{this.props.msg.pkg.get("cfg.bg.url")}
</div>
<input
name="bg_url"
type="text"
onChange={this.changeBgUrl}
value={this.props.login.preferences.bg.url}
placeholder={this.props.msg.pkg.get("cfg.bg.url")}
/>
</div>
<div className="inline-block margin-r-m">
<div className="label">
{this.props.msg.pkg.get("cfg.bg.repeat")}
</div>
<input
name="bg_repeat"
type="text"
onChange={this.changeBgRepeat}
value={this.props.login.preferences.bg.repeat}
placeholder={this.props.msg.pkg.get("cfg.bg.repeat")}
/>
</div>
<div className="inline-block margin-r-m">
<div className="label">
{this.props.msg.pkg.get("cfg.bg.pos")}
</div>
<input
name="bg_pos"
type="text"
onChange={this.changeBgPos}
value={this.props.login.preferences.bg.position}
placeholder={this.props.msg.pkg.get("cfg.bg.pos")}
/>
</div>
<div className="inline-block margin-r-m">
<div className="label">
{this.props.msg.pkg.get("cfg.bg.align")}
</div>
<input
name="bg_align"
type="text"
onChange={this.changeBgAlign}
value={this.props.login.preferences.bg.align}
placeholder={this.props.msg.pkg.get("cfg.bg.align")}
/>
</div>
<div className="inline-block margin-r-m">
<div className="label">
{this.props.msg.pkg.get("cfg.bg.bgColor")}
</div>
<input
name="bg_bgColor"
type="text"
onChange={this.changeBgBgColor}
value={this.props.login.preferences.bg.bgColor}
placeholder={this.props.msg.pkg.get("cfg.bg.bgColor")}
/>
</div>
</div>
</Container>
{bgConfigPane}
{errorReportPane}
{/* <div className="hr"></div>

View file

@ -11,6 +11,8 @@ import { LoginProps } from "./pane_login";
import { Layers } from "./layers";
import { AdminProps } from "./pane_admin";
import { TopBar } from "./topbar";
import { CronTable } from "../common/cron";
import { updater } from "./state_updater";
export const controlName = "panelTabs";
export interface Props {
@ -30,6 +32,18 @@ export class RootFrame extends React.Component<Props, State, {}> {
super(p);
}
componentDidMount(): void {
CronTable().setInterval("autoSwitchTheme", {
func: updater().autoSwitchTheme,
args: [],
delay: 60 * 1000,
});
}
componentWillUnmount() {
CronTable().clearInterval("autoSwitchTheme");
}
makeBgStyle = (): Object => {
if (
this.props.login.preferences != null &&

View file

@ -562,8 +562,6 @@ export class Updater {
return initClientCfgStatus;
}
console.log(this.props.ui.control.controls.toJSON());
this.initControls(paramMap);
this.initUITree();
@ -791,6 +789,22 @@ export class Updater {
this.props.login.preferences.theme = theme;
};
autoSwitchTheme = () => {
if (!this.props.ui.clientCfg.autoTheme) {
return;
}
const date = new Date();
if (
(date.getHours() >= 18 && date.getHours() <= 23) ||
(date.getHours() >= 0 && date.getHours() <= 6)
) {
this.setTheme("dark");
} else {
this.setTheme("light");
}
};
setControlOption = (controlName: string, option: string): boolean => {
const controlExists = this.props.ui.control.controls.has(controlName);
const optionsExists = this.props.ui.control.options.has(controlName);