Update config page style
This commit is contained in:
parent
fcab7cad4f
commit
a18efa9723
9 changed files with 120 additions and 125 deletions
|
@ -10,7 +10,7 @@ type ButtonInternalProps = {
|
|||
children?: React.ReactNode;
|
||||
label?: string;
|
||||
text?: string;
|
||||
start?: React.ReactElement | (() => React.ReactElement);
|
||||
start?: React.ReactNode | (() => React.ReactNode);
|
||||
};
|
||||
|
||||
type ButtonProps = {
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
.root {
|
||||
> div {
|
||||
min-width: 345px;
|
||||
@media (--breakpoint-not-small) {
|
||||
width: 360px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.root,
|
||||
.section {
|
||||
padding: 6px 15px 15px;
|
||||
@media (--breakpoint-not-small) {
|
||||
padding: 0 40px 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.sep {
|
||||
padding: 0 15px;
|
||||
@media (--breakpoint-not-small) {
|
||||
padding: 0 40px;
|
||||
}
|
||||
> div {
|
||||
border-top: 1px dashed #373737;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.narrow {
|
||||
width: 360px;
|
||||
}
|
39
src/components/Config.module.scss
Normal file
39
src/components/Config.module.scss
Normal file
|
@ -0,0 +1,39 @@
|
|||
.root,
|
||||
.section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(345px, 1fr));
|
||||
max-width: 900px;
|
||||
gap: 5px;
|
||||
@media (--breakpoint-not-small) {
|
||||
gap: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.root,
|
||||
.section {
|
||||
padding: 6px 15px 10px;
|
||||
@media (--breakpoint-not-small) {
|
||||
padding: 10px 40px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.wrapSwitch {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sep {
|
||||
max-width: 900px;
|
||||
padding: 0 15px;
|
||||
@media (--breakpoint-not-small) {
|
||||
padding: 0 40px;
|
||||
}
|
||||
> div {
|
||||
border-top: 1px dashed #373737;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
padding: 11px 0;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import { LogOut } from 'react-feather';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Select from 'src/components/shared/Select';
|
||||
import { ClashGeneralConfig, DispatchFn, State } from 'src/store/types';
|
||||
|
@ -12,55 +13,25 @@ import {
|
|||
import { fetchConfigs, getConfigs, updateConfigs } from '../store/configs';
|
||||
import { openModal } from '../store/modals';
|
||||
import Button from './Button';
|
||||
import s0 from './Config.module.css';
|
||||
import s0 from './Config.module.scss';
|
||||
import ContentHeader from './ContentHeader';
|
||||
import Input, { SelfControlledInput } from './Input';
|
||||
import { Selection2 } from './Selection';
|
||||
import { connect, useStoreActions } from './StateProvider';
|
||||
import Switch from './SwitchThemed';
|
||||
import ToggleSwitch from './ToggleSwitch';
|
||||
import TrafficChartSample from './TrafficChartSample';
|
||||
// import ToggleSwitch from './ToggleSwitch';
|
||||
|
||||
const { useEffect, useState, useCallback, useRef, useMemo } = React;
|
||||
|
||||
const propsList = [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }];
|
||||
|
||||
const optionsRule = [
|
||||
{
|
||||
label: 'Global',
|
||||
value: 'Global',
|
||||
},
|
||||
{
|
||||
label: 'Rule',
|
||||
value: 'Rule',
|
||||
},
|
||||
{
|
||||
label: 'Direct',
|
||||
value: 'Direct',
|
||||
},
|
||||
];
|
||||
|
||||
const optionsLogLevel = [
|
||||
{
|
||||
label: 'Debug',
|
||||
value: 'debug',
|
||||
},
|
||||
{
|
||||
label: 'Warning',
|
||||
value: 'warning',
|
||||
},
|
||||
{
|
||||
label: 'Info',
|
||||
value: 'info',
|
||||
},
|
||||
{
|
||||
label: 'Error',
|
||||
value: 'error',
|
||||
},
|
||||
{
|
||||
label: 'Silent',
|
||||
value: 'silent',
|
||||
},
|
||||
const logLeveOptions = [
|
||||
['debug', 'Debug'],
|
||||
['warning', 'Warning'],
|
||||
['info', 'Info'],
|
||||
['error', 'Error'],
|
||||
['silent', 'Silent'],
|
||||
];
|
||||
|
||||
const portFields = [
|
||||
|
@ -75,6 +46,12 @@ const langOptions = [
|
|||
['en', 'English'],
|
||||
];
|
||||
|
||||
const modeOptions = [
|
||||
['Global', 'Global'],
|
||||
['Rule', 'Rule'],
|
||||
['Direct', 'Direct'],
|
||||
];
|
||||
|
||||
const mapState = (s: State) => ({
|
||||
configs: getConfigs(s),
|
||||
apiConfig: getClashAPIConfig(s),
|
||||
|
@ -144,12 +121,9 @@ function ConfigImpl({
|
|||
[apiConfig, dispatch, setConfigState]
|
||||
);
|
||||
|
||||
const handleInputOnChange = useCallback(
|
||||
(e) => {
|
||||
const target = e.target;
|
||||
const { name } = target;
|
||||
const { value } = target;
|
||||
switch (target.name) {
|
||||
const handleChangeValue = useCallback(
|
||||
({ name, value }) => {
|
||||
switch (name) {
|
||||
case 'mode':
|
||||
case 'log-level':
|
||||
setConfigState(name, value);
|
||||
|
@ -159,8 +133,8 @@ function ConfigImpl({
|
|||
case 'socks-port':
|
||||
case 'mixed-port':
|
||||
case 'port':
|
||||
if (target.value !== '') {
|
||||
const num = parseInt(target.value, 10);
|
||||
if (value !== '') {
|
||||
const num = parseInt(value, 10);
|
||||
if (num < 0 || num > 65535) return;
|
||||
}
|
||||
setConfigState(name, value);
|
||||
|
@ -172,6 +146,11 @@ function ConfigImpl({
|
|||
[apiConfig, dispatch, setConfigState]
|
||||
);
|
||||
|
||||
const handleInputOnChange = useCallback(
|
||||
(e) => handleChangeValue(e.target),
|
||||
[handleChangeValue]
|
||||
);
|
||||
|
||||
const { selectChartStyleIndex, updateAppConfig } = useStoreActions();
|
||||
|
||||
const handleInputOnBlur = useCallback(
|
||||
|
@ -224,34 +203,39 @@ function ConfigImpl({
|
|||
</div>
|
||||
) : null
|
||||
)}
|
||||
<div>
|
||||
<div className={s0.label}>Allow LAN</div>
|
||||
<Switch
|
||||
name="allow-lan"
|
||||
checked={configState['allow-lan']}
|
||||
onChange={handleSwitchOnChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={s0.label}>Mode</div>
|
||||
<ToggleSwitch
|
||||
options={optionsRule}
|
||||
name="mode"
|
||||
value={mode}
|
||||
onChange={handleInputOnChange}
|
||||
<Select
|
||||
options={modeOptions}
|
||||
selected={mode}
|
||||
onChange={(e) =>
|
||||
handleChangeValue({ name: 'mode', value: e.target.value })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={s0.label}>Log Level</div>
|
||||
<ToggleSwitch
|
||||
options={optionsLogLevel}
|
||||
name="log-level"
|
||||
value={configState['log-level']}
|
||||
onChange={handleInputOnChange}
|
||||
<Select
|
||||
options={logLeveOptions}
|
||||
selected={configState['log-level']}
|
||||
onChange={(e) =>
|
||||
handleChangeValue({ name: 'log-level', value: e.target.value })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={s0.label}>Allow LAN</div>
|
||||
<div className={s0.wrapSwitch}>
|
||||
<Switch
|
||||
name="allow-lan"
|
||||
checked={configState['allow-lan']}
|
||||
onChange={handleSwitchOnChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={s0.sep}>
|
||||
|
@ -260,15 +244,6 @@ function ConfigImpl({
|
|||
|
||||
<div className={s0.section}>
|
||||
<div>
|
||||
<div className={s0.label}>{t('chart_style')}</div>
|
||||
<Selection2
|
||||
OptionComponent={TrafficChartSample}
|
||||
optionPropsList={propsList}
|
||||
selectedIndex={selectedChartStyleIndex}
|
||||
onChange={selectChartStyleIndex}
|
||||
/>
|
||||
</div>
|
||||
<div className={s0.narrow}>
|
||||
<div className={s0.label}>{t('latency_test_url')}</div>
|
||||
<SelfControlledInput
|
||||
name="latencyTestUrl"
|
||||
|
@ -277,13 +252,9 @@ function ConfigImpl({
|
|||
onBlur={handleInputOnBlur}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className={s0.label}>Action</div>
|
||||
<Button label="Switch backend" onClick={openAPIConfigModal} />
|
||||
</div>
|
||||
<div>
|
||||
<div className={s0.label}>{t('lang')}</div>
|
||||
<div className={s0.narrow}>
|
||||
<div>
|
||||
<Select
|
||||
options={langOptions}
|
||||
selected={i18n.language}
|
||||
|
@ -291,6 +262,25 @@ function ConfigImpl({
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={s0.label}>{t('chart_style')}</div>
|
||||
<Selection2
|
||||
OptionComponent={TrafficChartSample}
|
||||
optionPropsList={propsList}
|
||||
selectedIndex={selectedChartStyleIndex}
|
||||
onChange={selectChartStyleIndex}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={s0.label}>Action</div>
|
||||
<Button
|
||||
start={<LogOut size={16} />}
|
||||
label="Switch backend"
|
||||
onClick={openAPIConfigModal}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
border-radius: 4px;
|
||||
border: 1px solid var(--color-input-border);
|
||||
box-sizing: border-box;
|
||||
color: #c1c1c1;
|
||||
color: inherit;
|
||||
display: inline-block;
|
||||
font-size: inherit;
|
||||
height: 40px;
|
||||
|
@ -13,6 +13,7 @@
|
|||
padding: 0 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
box-shadow: rgba(66, 153, 225, 0.6) 0px 0px 0px 3px;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,10 @@ export function SelfControlledInput({ value, ...restProps }) {
|
|||
}
|
||||
refValue.current = value;
|
||||
}, [value]);
|
||||
const onChange = useCallback((e) => setInternalValue(e.target.value), [
|
||||
setInternalValue,
|
||||
]);
|
||||
const onChange = useCallback(
|
||||
(e) => setInternalValue(e.target.value),
|
||||
[setInternalValue]
|
||||
);
|
||||
|
||||
return (
|
||||
<input
|
||||
|
|
|
@ -47,12 +47,7 @@ export default function TrafficChart({ id }) {
|
|||
useLineChart(Chart, eleId, data, null, extraChartOptions);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: 130,
|
||||
padding: 5,
|
||||
}}
|
||||
>
|
||||
<div style={{ width: 100, padding: 5 }}>
|
||||
<canvas id={eleId} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -9,9 +9,8 @@
|
|||
padding-right: 20px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--color-input-border);
|
||||
transition: all 100ms ease 0s;
|
||||
background-image: url(data:image/svg+xml,%0A%20%20%20%20%3Csvg%20width%3D%228%22%20height%3D%2224%22%20viewBox%3D%220%200%208%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%207L7%2011H1L4%207Z%22%20fill%3D%22%23999999%22%20%2F%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%2017L1%2013L7%2013L4%2017Z%22%20fill%3D%22%23999999%22%20%2F%3E%0A%20%20%20%20%3C%2Fsvg%3E%0A%20%20);
|
||||
background-position: calc(100% - 8px) center;
|
||||
background-position: right 8px center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
|
4
src/custom.d.ts
vendored
4
src/custom.d.ts
vendored
|
@ -6,6 +6,10 @@ declare module '*.module.css' {
|
|||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
declare module '*.module.scss' {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
}
|
||||
|
||||
interface Window {
|
||||
i18n: any;
|
||||
|
|
Loading…
Reference in a new issue