feat: simple config fields

This commit is contained in:
EnixCoda 2022-06-01 01:18:44 +08:00
parent ff1bdd6f0f
commit 43aaa3874c
10 changed files with 159 additions and 106 deletions

View file

@ -0,0 +1,19 @@
import { Checkbox as PrimerCheckbox, CheckboxProps, FormControl } from '@primer/react';
import * as React from 'react';
export function Checkbox({
label, value, onChange, checked = value, ...rest
}: Override<CheckboxProps, { label: React.ReactNode; } & IO<boolean>>) {
return (
<FormControl>
<PrimerCheckbox
sx={{
marginTop: '4px', // align label
}}
checked={checked}
onChange={e => onChange(e.target.checked)}
{...rest} />
<FormControl.Label>{label}</FormControl.Label>
</FormControl>
);
}

View file

@ -7,19 +7,18 @@ export type Option<T> = {
value: T
}
export type SelectInputProps<T> = Override<SelectProps, IO<T> & {
label: React.ReactNode
options: Option<T>[]
}>
export function SelectInput<T>({
value,
onChange,
label,
options,
...selectProps
}: Override<
SelectProps,
IO<T> & {
label: string
options: Option<T>[]
}
>) {
}: SelectInputProps<T>) {
return (
<FormControl
sx={{

View file

@ -1,68 +0,0 @@
import { Checkbox, FormControl } from '@primer/react'
import { useConfigs } from 'containers/ConfigsContext'
import * as React from 'react'
import { Config, ConfigKeys } from 'utils/config/helper'
export type SimpleField<Key extends ConfigKeys> = {
key: Key
label: string
wikiLink?: string
tooltip?: string
disabled?: boolean
overwrite?: {
value: (value: Config[Key]) => boolean
onChange: (checked: boolean) => Config[Key]
}
}
type Props<Key extends ConfigKeys> = {
field: SimpleField<Key>
}
export function SimpleToggleField<Key extends ConfigKeys>({ field }: Props<Key>) {
const { overwrite } = field
const configContext = useConfigs()
const value = configContext.value[field.key]
const checked = React.useMemo(
() => (overwrite ? overwrite.value(value) : Boolean(value)),
[overwrite, value],
)
const handleChange = React.useCallback(
(checked: boolean) => {
const enabled = checked
configContext.onChange({ [field.key]: overwrite ? overwrite.onChange(enabled) : enabled })
},
[field.key, overwrite, configContext],
)
return (
<FormControl>
<Checkbox
sx={{
marginTop: '4px', // align label
}}
value={field.key}
disabled={field.disabled}
onChange={e => handleChange(e.target.checked)}
checked={checked}
/>
<FormControl.Label>
{field.label}
{(field.wikiLink || field.tooltip) && ' '}
{field.wikiLink ? (
<a href={field.wikiLink} title={field.tooltip} target="_blank" rel="noopener noreferrer">
(?)
</a>
) : (
field.tooltip && (
<span className={'help'} title={field.tooltip}>
(?)
</span>
)
)}
</FormControl.Label>
</FormControl>
)
}

View file

@ -1,10 +1,10 @@
import { wikiLinks } from 'components/settings/SettingsBar'
import { SimpleToggleField } from 'components/SimpleToggleField'
import { useConfigs } from 'containers/ConfigsContext'
import { SimpleConfigFieldCheckbox } from 'components/settings/SimpleConfigField/Checkbox'
import * as React from 'react'
import { Config } from 'utils/config/helper'
import { Option, SelectInput } from '../SelectInput'
import { Option } from '../Inputs/SelectInput'
import { SettingsSection } from './SettingsSection'
import { SimpleConfigFieldSelect } from './SimpleConfigField/SelectInput'
const iconOptions: Option<Config['icons']>[] = [
{
@ -38,32 +38,23 @@ const recursiveToggleFolderOptions: Option<Config['recursiveToggleFolder']>[] =
]
export function FileTreeSettings() {
const configContext = useConfigs()
const { recursiveToggleFolder, icons } = configContext.value
return (
<SettingsSection title={'File Tree'}>
<SelectInput
label="Toggle folders recursively while holding"
<SimpleConfigFieldSelect
field={{
key: 'recursiveToggleFolder',
label: 'Toggle folders recursively while holding',
}}
options={recursiveToggleFolderOptions}
onChange={v => {
configContext.onChange({
recursiveToggleFolder: v,
})
}}
value={recursiveToggleFolder}
/>
<SelectInput<Config['icons']>
label="Icons"
<SimpleConfigFieldSelect
field={{
key: 'icons',
label: 'Icons',
}}
options={iconOptions}
onChange={v => {
configContext.onChange({
icons: v,
})
}}
value={icons}
/>
<SimpleToggleField
<SimpleConfigFieldCheckbox
field={{
key: 'compressSingletonFolder',
label: 'Compress singleton folder',
@ -71,21 +62,21 @@ export function FileTreeSettings() {
tooltip: 'Merge folders and their only child folder to make UI more compact.',
}}
/>
<SimpleToggleField
<SimpleConfigFieldCheckbox
field={{
key: 'restoreExpandedFolders',
label: 'Restore expanded folders',
tooltip: 'Folders will be expanded again when clear search input',
}}
/>
<SimpleToggleField
<SimpleConfigFieldCheckbox
field={{
key: 'commentToggle',
label: 'Show PR file comments',
tooltip: 'Show number of comments next to file names in Pull Requests.',
}}
/>
<SimpleToggleField
<SimpleConfigFieldCheckbox
field={{
key: 'compactFileTree',
label: 'Compact file tree layout',

View file

@ -3,11 +3,12 @@ import { platform } from 'platforms'
import { GitHub } from 'platforms/GitHub'
import * as React from 'react'
import { useStateIO } from 'utils/hooks/useStateIO'
import { SimpleField, SimpleToggleField } from '../SimpleToggleField'
import { AccessTokenSettings } from './AccessTokenSettings'
import { FileTreeSettings } from './FileTreeSettings'
import { SettingsSection } from './SettingsSection'
import { SidebarSettings } from './SidebarSettings'
import { SimpleConfigField } from './SimpleConfigField'
import { SimpleConfigFieldCheckbox } from './SimpleConfigField/Checkbox'
const WIKI_HOME_LINK = 'https://github.com/EnixCoda/Gitako/wiki'
export const wikiLinks = {
@ -19,7 +20,7 @@ export const wikiLinks = {
createAccessToken: `${WIKI_HOME_LINK}/Access-token-for-Gitako`,
}
const moreFields: SimpleField<'copyFileButton' | 'copySnippetButton' | 'codeFolding'>[] =
const moreFields: SimpleConfigField<'copyFileButton' | 'copySnippetButton' | 'codeFolding'>[] =
platform === GitHub
? [
{
@ -64,7 +65,7 @@ export function SettingsBarContent({ toggleShow }: { toggleShow: () => void }) {
<SettingsSection title={'More'}>
{moreFields.map(field => (
<React.Fragment key={field.key}>
<SimpleToggleField field={field} />
<SimpleConfigFieldCheckbox field={field} />
</React.Fragment>
))}

View file

@ -1,5 +1,5 @@
import { Box, Button, FormControl, TextInput } from '@primer/react'
import { SimpleToggleField } from 'components/SimpleToggleField'
import { SimpleConfigFieldCheckbox } from 'components/settings/SimpleConfigField/Checkbox'
import { useConfigs } from 'containers/ConfigsContext'
import * as React from 'react'
import { friendlyFormatShortcut, noop } from 'utils/general'
@ -13,7 +13,7 @@ export function SidebarSettings() {
return (
<SettingsSection title={'Sidebar'}>
<ToggleSidebarShortcutSettings />
<SimpleToggleField
<SimpleConfigFieldCheckbox
field={{
key: 'intelligentToggle',
label: 'Auto expand',

View file

@ -0,0 +1,20 @@
import * as React from 'react'
import { ConfigKeys } from 'utils/config/helper'
import { SimpleConfigFieldProps, useSimpleConfigFieldIO } from '.'
import { Checkbox } from '../../Inputs/Checkbox'
import { FieldLabel } from './FieldLabel'
export function SimpleConfigFieldCheckbox<Key extends ConfigKeys>({
field,
}: SimpleConfigFieldProps<Key>) {
const { value, onChange } = useSimpleConfigFieldIO(field) as IO<boolean>
return (
<Checkbox
label={<FieldLabel {...field} />}
disabled={field.disabled}
value={value}
onChange={onChange}
/>
)
}

View file

@ -0,0 +1,27 @@
import * as React from 'react'
import { ConfigKeys } from 'utils/config/helper'
import { SimpleConfigField } from '.'
export function FieldLabel<Key extends ConfigKeys>({
label,
wikiLink,
tooltip,
}: SimpleConfigField<Key>) {
return (
<>
{label}
{(wikiLink || tooltip) && ' '}
{wikiLink ? (
<a href={wikiLink} title={tooltip} target="_blank" rel="noopener noreferrer">
(?)
</a>
) : (
tooltip && (
<span className={'help'} title={tooltip}>
(?)
</span>
)
)}
</>
)
}

View file

@ -0,0 +1,27 @@
import { SelectInput, SelectInputProps } from 'components/Inputs/SelectInput'
import * as React from 'react'
import { Config, ConfigKeys } from 'utils/config/helper'
import {
SimpleConfigFieldProps,
useSimpleConfigFieldIO
} from '.'
import { FieldLabel } from './FieldLabel'
export function SimpleConfigFieldSelect<Key extends ConfigKeys>({
field,
options,
}: SimpleConfigFieldProps<Key> & {
options: SelectInputProps<Config[Key]>['options']
}) {
const { value, onChange } = useSimpleConfigFieldIO(field)
return (
<SelectInput
label={<FieldLabel {...field} />}
disabled={field.disabled}
value={value}
onChange={onChange}
options={options}
/>
)
}

View file

@ -0,0 +1,37 @@
import { useConfigs } from 'containers/ConfigsContext'
import React from 'react'
import { Config, ConfigKeys } from 'utils/config/helper'
export type SimpleConfigField<Key extends ConfigKeys> = {
label: string
wikiLink?: string
tooltip?: string
key: Key
disabled?: boolean
overwrite?: {
value: (value: Config[Key]) => Config[Key]
onChange: (newValue: Config[Key]) => Config[Key]
}
}
export type SimpleConfigFieldProps<Key extends ConfigKeys> = {
field: SimpleConfigField<Key>
}
export function useSimpleConfigFieldIO<Key extends ConfigKeys>(
field: SimpleConfigField<Key>,
): IO<Config[Key]> {
const { overwrite } = field
const configContext = useConfigs()
const value = configContext.value[field.key]
return {
value: React.useMemo(() => (overwrite ? overwrite.value(value) : value), [overwrite, value]),
onChange: React.useCallback(
(newValue: Config[Key]) => {
configContext.onChange({ [field.key]: overwrite ? overwrite.onChange(newValue) : newValue })
},
[field.key, overwrite, configContext],
),
}
}