Skip to content

Commit

Permalink
✨ FileChooser组件
Browse files Browse the repository at this point in the history
  • Loading branch information
zty012 committed Dec 6, 2024
1 parent f10205b commit a32306b
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 117 deletions.
32 changes: 32 additions & 0 deletions src/components/ui/FileChooser.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { open } from "@tauri-apps/plugin-dialog";
import { FolderOpen } from "lucide-react";
import Button from "./Button";
import Input from "./Input";

export default function FileChooser({
kind,
value = "",
onChange = () => {},
}: {
kind: "file" | "directory";
value?: string;
onChange?: (value: string) => void;
}) {
return (
<div className="flex items-center gap-2">
<Input type="text" value={value} onChange={onChange} />
<Button
onClick={() => {
open({
directory: kind === "directory",
multiple: false,
}).then((result) => {
onChange(result ?? "");
});
}}
>
{<FolderOpen />}
</Button>
</div>
);
}
42 changes: 13 additions & 29 deletions src/pages/settings/_field.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { RotateCw } from "lucide-react";
import React from "react";
import { useTranslation } from "react-i18next";
import Button from "../../components/ui/Button";
import FileChooser from "../../components/ui/FileChooser";
import Input from "../../components/ui/Input";
import Select from "../../components/ui/Select";
import Slider from "../../components/ui/Slider";
Expand All @@ -17,14 +17,16 @@ export function SettingField({
step = 1,
placeholder = "",
icon = <></>,
kind = "file",
}: {
settingKey: keyof Settings.Settings;
type?: "text" | "number" | "slider" | "switch" | "select";
type?: "text" | "number" | "slider" | "switch" | "select" | "file";
min?: number;
max?: number;
step?: number;
placeholder?: string;
icon?: React.ReactNode;
kind?: "file" | "directory";
}) {
const [value, setValue] = React.useState<any>();
const { t, i18n } = useTranslation("settings");
Expand All @@ -45,32 +47,11 @@ export function SettingField({
}, [value]);

return (
<div className="flex w-full items-center gap-2 rounded-xl p-4 hover:bg-white/10">
<div className="flex items-center gap-2">
{icon}
<div className="flex flex-col">
<span>{t(`${settingKey}.title`)}</span>
<div>
{t(`${settingKey}.description`, { defaultValue: "" })
.split("\n")
.map((dd, ii) => (
<p key={ii} className="text-xs text-gray-500">
{dd}
</p>
))}
</div>
<span className="text-xs text-gray-500">{settingKey}</span>
</div>
</div>
<div className="flex-1"></div>
<button
onClick={() => {
setValue(Settings.defaultSettings[settingKey]);
}}
className="transition-transform hover:rotate-180 hover:cursor-pointer"
>
<RotateCw size={16} className="text-gray-500" />
</button>
<Field
title={t(`${settingKey}.title`)}
description={t(`${settingKey}.description`, { defaultValue: "" })}
icon={icon}
>
{type === "text" && (
<Input value={value} onChange={setValue} placeholder={placeholder} />
)}
Expand Down Expand Up @@ -100,7 +81,10 @@ export function SettingField({
}))}
></Select>
)}
</div>
{type === "file" && (
<FileChooser kind={kind} value={value} onChange={setValue} />
)}
</Field>
);
}
export function ButtonField({
Expand Down
14 changes: 0 additions & 14 deletions src/pages/settings/automation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,22 @@ export default function AutoNamer() {
<SettingField
icon={<Tag />}
settingKey="autoNamerTemplate"
title={t("autoNamerTemplate.title")}
details={t("autoNamerTemplate.description")}
type="text"
placeholder="例如:p{{i}}"
/>
<SettingField
icon={<HardDriveDownload />}
settingKey="autoSaveWhenClose"
title={t("autoSaveWhenClose.title")}
details={t("autoSaveWhenClose.description")}
type="switch"
/>
<SettingField
icon={<HardDrive />}
settingKey="autoSave"
title={t("autoSave.title")}
details={t("autoSave.description")}
type="switch"
/>
<SettingField
icon={<Hourglass />}
settingKey="autoSaveInterval"
title={t("autoSaveInterval.title")}
details={t("autoSaveInterval.description")}
type="slider"
min={1}
max={60}
Expand All @@ -50,15 +42,11 @@ export default function AutoNamer() {
<SettingField
icon={<Database />}
settingKey="autoBackup"
title={t("autoBackup.title")}
details={t("autoBackup.description")}
type="switch"
/>
<SettingField
icon={<Hourglass />}
settingKey="autoBackupInterval"
title={t("autoBackupInterval.title")}
details={t("autoBackupInterval.description")}
type="slider"
min={60}
max={6000}
Expand All @@ -67,8 +55,6 @@ export default function AutoNamer() {
<SettingField
icon={<Folder />}
settingKey="autoBackupDraftPath"
title={t("autoBackupDraftPath.title")}
details={t("autoBackupDraftPath.description")}
type="text"
/>
</>
Expand Down
12 changes: 0 additions & 12 deletions src/pages/settings/control.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { Keyboard, Move, ScanEye, Skull } from "lucide-react";
import { SettingField } from "./_field";
import { useTranslation } from "react-i18next";

export default function Control() {
const { t } = useTranslation("settingsControl");

return (
<>
<SettingField
icon={<ScanEye />}
settingKey="scaleExponent"
title={t("scaleExponent.title")}
details={t("scaleExponent.description")}
type="slider"
min={0}
max={1}
Expand All @@ -20,15 +15,11 @@ export default function Control() {
<SettingField
icon={<Keyboard />}
settingKey="allowMoveCameraByWSAD"
title={"允许使用“WSAD”键来控制视角移动"}
details={"WSAD"}
type="switch"
/>
<SettingField
icon={<Move />}
settingKey="moveAmplitude"
title={t("moveAmplitude.title")}
details={t("moveAmplitude.description")}
type="slider"
min={0}
max={10}
Expand All @@ -37,8 +28,6 @@ export default function Control() {
<SettingField
icon={<Move />}
settingKey="moveFriction"
title={t("moveFriction.title")}
details={t("moveFriction.description")}
type="slider"
min={0}
max={1}
Expand All @@ -47,7 +36,6 @@ export default function Control() {
<SettingField
icon={<Skull />}
settingKey="gamepadDeadzone"
title={t("gamepadDeadzone")}
type="slider"
min={0}
max={1}
Expand Down
19 changes: 7 additions & 12 deletions src/pages/settings/performance.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import { useTranslation } from "react-i18next";
import { SettingField } from "./_field";
import { Sparkles, SquareStack } from "lucide-react";
import { SettingField } from "./_field";

export default function Performance() {

const { t } = useTranslation("settingsPerformance");

return <>
<SettingField
return (
<>
<SettingField
icon={<Sparkles />}
settingKey="renderEffect"
title={t("renderEffect")}
type="switch"
/>
<SettingField
<SettingField
icon={<SquareStack />}
settingKey="historySize"
title={t("historySize.title")}
details={t("historySize.description")}
type="slider"
min={10}
max={1000}
step={10}
/>
</>;
</>
);
}
16 changes: 4 additions & 12 deletions src/pages/settings/sounds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,22 @@ export default function Sounds() {
<SettingField
icon={<Folder />}
settingKey="cuttingLineStartSoundFile"
title={"切割线开始音效"}
details={"右键按下时刚开始创建切割线准备切割东西时播放的音效文件。"}
type="text"
type="file"
/>
<SettingField
icon={<Folder />}
settingKey="connectLineStartSoundFile"
title={"连接线开始音效"}
details={"右键按下时刚开始创建连接时播放的音效文件。"}
type="text"
type="file"
/>
<SettingField
icon={<Folder />}
settingKey="connectFindTargetSoundFile"
title={"连接线查找目标音效"}
details={"当"}
type="text"
type="file"
/>
<SettingField
icon={<Folder />}
settingKey="cuttingLineReleaseSoundFile"
title={"切断线释放特效"}
details={"纯粹解压用的"}
type="text"
type="file"
/>
</>
);
Expand Down
41 changes: 3 additions & 38 deletions src/pages/test.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
import { invoke } from "@tauri-apps/api/core";
import { TestTube2 } from "lucide-react";
import React from "react";
import { useTranslation } from "react-i18next";
import Button from "../components/ui/Button";
import FileChooser from "../components/ui/FileChooser";
import IconButton from "../components/ui/IconButton";
import Input from "../components/ui/Input";
import Switch from "../components/ui/Switch";
import { LastLaunch } from "../core/LastLaunch";
import { StageDumper } from "../core/stage/StageDumper";
import { usePopupDialog } from "../utils/popupDialog";
import { XML } from "../utils/xml";
import { SoundService } from "../core/SoundService";

export default function TestPage() {
const [switchValue, setSwitchValue] = React.useState(false);
const [file, setFile] = React.useState("");
const popupDialog = usePopupDialog();
const { t } = useTranslation();

const popup = () => {
popupDialog.show(<>test</>);
};

const handleTestHttp = async () => {};

return (
<div className="pt-20">
<Button onClick={popup}>button</Button>
Expand All @@ -31,35 +24,7 @@ export default function TestPage() {
</IconButton>
<Input placeholder="placeholder" />
<Switch value={switchValue} onChange={(e) => setSwitchValue(e)} />
{t("test")}
<p>test xml:</p>
{new XML("ompl")
.attr("version", "2.0")
.add("head")
.add("title")
.text("test")
.up()
.up()
.add("body")
.toString()}
<br />
<div className="h-64 overflow-auto p-2">
<h2>序列化信息</h2>
<pre className="text-xs">
{JSON.stringify(StageDumper.dump(), null, 2)}
</pre>
</div>
<Button onClick={handleTestHttp}>test http</Button>
<Button onClick={handleTestImageBase64}>getImageBase64</Button>
<Button onClick={SoundService.play.cuttingLineStart}>test sound</Button>
last launch: {LastLaunch.version}
<FileChooser kind="file" value={file} onChange={(e) => setFile(e)} />
</div>
);
}

function handleTestImageBase64() {
invoke<string>("convert_image_to_base64", {
imagePath:
"D:\\Projects\\Project-Tools\\project-graph\\src\\assets\\icon.png",
}).then((_res) => {});
}

0 comments on commit a32306b

Please sign in to comment.