This commit is contained in:
Sanster
2022-04-12 20:58:57 +08:00
parent e570e85e64
commit aa411c7524
25 changed files with 769 additions and 22 deletions

View File

@@ -0,0 +1,137 @@
import React, { ReactNode } from 'react'
import { useRecoilState } from 'recoil'
import { settingState } from '../../store/Atoms'
import NumberInput from '../shared/NumberInput'
import Selector from '../shared/Selector'
import SettingBlock from './SettingBlock'
export enum HDStrategy {
ORIGINAL = 'Original',
REISIZE = 'Resize',
CROP = 'Crop',
}
interface PixelSizeInputProps {
title: string
value: string
onValue: (val: string) => void
}
function PixelSizeInputSetting(props: PixelSizeInputProps) {
const { title, value, onValue } = props
return (
<SettingBlock
title={title}
input={
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '8px',
}}
>
<NumberInput
style={{ width: '80px' }}
value={`${value}`}
onValue={onValue}
/>
<span>pixel</span>
</div>
}
/>
)
}
function HDSettingBlock() {
const [setting, setSettingState] = useRecoilState(settingState)
const onStrategyChange = (value: HDStrategy) => {
setSettingState(old => {
return { ...old, hdStrategy: value }
})
}
const onResizeLimitChange = (value: string) => {
setSettingState(old => {
return { ...old, hdStrategyResizeLimit: value }
})
}
const onCropTriggerSizeChange = (value: string) => {
setSettingState(old => {
return { ...old, hdStrategyCropTrigerSize: value }
})
}
const renderOriginalOptionDesc = () => {
return (
<div>
Use the original resolution of the picture, suitable for picture size
below 2K, of course you can try it on higher resolution pictures
</div>
)
}
const renderResizeOptionDesc = () => {
return (
<div>
<div>
Resize the longer side of the image to a specific size(keep ratio),
then do inpainting on the entire resized image.
</div>
<PixelSizeInputSetting
title="Size limit"
value={`${setting.hdStrategyResizeLimit}`}
onValue={onResizeLimitChange}
/>
</div>
)
}
const renderCropOptionDesc = () => {
return (
<div>
<div>
Crop masking area from the original image to do inpainting, and paste
the result back. Mainly for performance and memory reasons on high
resolution image.
</div>
<PixelSizeInputSetting
title="Trigger size"
value={`${setting.hdStrategyCropTrigerSize}`}
onValue={onCropTriggerSizeChange}
/>
</div>
)
}
const renderHDStrategyOptionDesc = (): ReactNode => {
switch (setting.hdStrategy) {
case HDStrategy.ORIGINAL:
return renderOriginalOptionDesc()
case HDStrategy.CROP:
return renderCropOptionDesc()
case HDStrategy.REISIZE:
return renderResizeOptionDesc()
default:
return renderOriginalOptionDesc()
}
}
return (
<SettingBlock
title="High Resolution Strategy"
input={
<Selector
options={Object.values(HDStrategy)}
onChange={val => onStrategyChange(val as HDStrategy)}
/>
}
optionDesc={renderHDStrategyOptionDesc()}
/>
)
}
export default HDSettingBlock

View File

@@ -0,0 +1,19 @@
import React, { ReactNode } from 'react'
import { useRecoilState } from 'recoil'
import { Switch, SwitchThumb } from '../shared/Switch'
import SettingBlock from './SettingBlock'
function SavePathSettingBlock() {
return (
<SettingBlock
title="Download image at same folder of origin image"
input={
<Switch defaultChecked>
<SwitchThumb />
</Switch>
}
/>
)
}
export default SavePathSettingBlock

View File

@@ -0,0 +1,19 @@
@use '../../styles/Mixins/' as *;
@import './SettingBlock.scss';
.modal-setting {
grid-area: main-content;
background-color: var(--modal-bg);
color: var(--modal-text-color);
box-shadow: 0px 0px 20px rgb(0, 0, 40, 0.2);
min-height: 450px;
width: 700px;
@include mobile {
display: grid;
width: 100%;
height: auto;
margin-top: -11rem;
animation: slideDown 0.2s ease-out;
}
}

View File

@@ -0,0 +1,31 @@
.setting-block {
display: flex;
flex-direction: column;
margin-top: 12px;
.option-desc {
margin-top: 12px;
border: 1px solid var(--border-color);
border-radius: 0.3rem;
padding: 2rem;
}
}
.setting-block-content {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12rem;
}
.setting-block-content-title {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.setting-block-desc {
font-size: 1rem;
margin-top: 8px;
color: var(--text-color-gray);
}

View File

@@ -0,0 +1,27 @@
import React, { ReactNode } from 'react'
interface SettingBlockProps {
title: string
desc?: string
input: ReactNode
optionDesc?: ReactNode
className?: string
}
function SettingBlock(props: SettingBlockProps) {
const { title, desc, input, optionDesc, className } = props
return (
<div className={`setting-block ${className}`}>
<div className="setting-block-content">
<div className="setting-block-content-title">
<span>{title}</span>
{desc && <span className="setting-block-desc">{desc}</span>}
</div>
{input}
</div>
{optionDesc && <div className="option-desc">{optionDesc}</div>}
</div>
)
}
export default SettingBlock

View File

@@ -0,0 +1,46 @@
import React from 'react'
import { useRecoilState } from 'recoil'
import { settingState } from '../../store/Atoms'
import Button from '../shared/Button'
const SettingIcon = () => {
const [setting, setSettingState] = useRecoilState(settingState)
const onClick = () => {
setSettingState({ ...setting, show: !setting.show })
}
return (
<div>
<Button
onClick={onClick}
style={{ border: 0 }}
icon={
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
role="img"
width="28"
height="28"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
}
/>
</div>
)
}
export default SettingIcon

View File

@@ -0,0 +1,29 @@
import React from 'react'
import { useRecoilState } from 'recoil'
import { settingState } from '../../store/Atoms'
import Modal from '../shared/Modal'
import HDSettingBlock from './HDSettingBlock'
import SavePathSettingBlock from './SavePathSettingBlock'
export default function SettingModal() {
const [setting, setSettingState] = useRecoilState(settingState)
const onClose = () => {
setSettingState(old => {
return { ...old, show: false }
})
}
return (
<Modal
onClose={onClose}
title="Settings"
className="modal-setting"
show={setting.show}
>
<SavePathSettingBlock />
<HDSettingBlock />
</Modal>
)
}