mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-18 14:59:42 +02:00
Clean up filesystem sync setting
This commit is contained in:
@@ -24,6 +24,9 @@ crate-type = ["staticlib", "cdylib", "lib"]
|
|||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true # Automatically strip symbols from the binary.
|
strip = true # Automatically strip symbols from the binary.
|
||||||
|
|
||||||
|
[features]
|
||||||
|
cargo-clippy = []
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "2.0.4", features = [] }
|
tauri-build = { version = "2.0.4", features = [] }
|
||||||
|
|
||||||
|
|||||||
@@ -1764,7 +1764,7 @@ pub fn run() {
|
|||||||
.level(if is_dev() { log::LevelFilter::Debug } else { log::LevelFilter::Info })
|
.level(if is_dev() { log::LevelFilter::Debug } else { log::LevelFilter::Info })
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.plugin(tauri_plugin_single_instance::init(|app, args, _cwd| {
|
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
||||||
// When trying to open a new app instance (common operation on Linux),
|
// When trying to open a new app instance (common operation on Linux),
|
||||||
// focus the first existing window we find instead of opening a new one
|
// focus the first existing window we find instead of opening a new one
|
||||||
// TODO: Keep track of the last focused window and always focus that one
|
// TODO: Keep track of the last focused window and always focus that one
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { getWorkspaceMeta } from '../lib/store';
|
|||||||
import { Button } from './core/Button';
|
import { Button } from './core/Button';
|
||||||
import { PlainInput } from './core/PlainInput';
|
import { PlainInput } from './core/PlainInput';
|
||||||
import { VStack } from './core/Stacks';
|
import { VStack } from './core/Stacks';
|
||||||
import type { SyncToFilesystemSettingProps } from './SyncToFilesystemSetting';
|
|
||||||
import { SyncToFilesystemSetting } from './SyncToFilesystemSetting';
|
import { SyncToFilesystemSetting } from './SyncToFilesystemSetting';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -15,9 +14,7 @@ interface Props {
|
|||||||
|
|
||||||
export function CreateWorkspaceDialog({ hide }: Props) {
|
export function CreateWorkspaceDialog({ hide }: Props) {
|
||||||
const [name, setName] = useState<string>('');
|
const [name, setName] = useState<string>('');
|
||||||
const [settingSyncDir, setSettingSyncDir] = useState<
|
const [settingSyncDir, setSettingSyncDir] = useState<string | null>(null);
|
||||||
Parameters<SyncToFilesystemSettingProps['onChange']>[0]
|
|
||||||
>({ value: null, enabled: false });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack
|
<VStack
|
||||||
@@ -27,15 +24,14 @@ export function CreateWorkspaceDialog({ hide }: Props) {
|
|||||||
className="pb-3 max-h-[50vh]"
|
className="pb-3 max-h-[50vh]"
|
||||||
onSubmit={async (e) => {
|
onSubmit={async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const { enabled, value } = settingSyncDir ?? {};
|
if (!settingSyncDir) return;
|
||||||
if (enabled && !value) return;
|
|
||||||
const workspace = await upsertWorkspace.mutateAsync({ name });
|
const workspace = await upsertWorkspace.mutateAsync({ name });
|
||||||
if (workspace == null) return;
|
if (workspace == null) return;
|
||||||
|
|
||||||
// Do getWorkspaceMeta instead of naively creating one because it might have
|
// Do getWorkspaceMeta instead of naively creating one because it might have
|
||||||
// been created already when the store refreshes the workspace meta after
|
// been created already when the store refreshes the workspace meta after
|
||||||
const workspaceMeta = await getWorkspaceMeta(workspace.id);
|
const workspaceMeta = await getWorkspaceMeta(workspace.id);
|
||||||
upsertWorkspaceMeta.mutate({ ...workspaceMeta, settingSyncDir: value });
|
upsertWorkspaceMeta.mutate({ ...workspaceMeta, settingSyncDir });
|
||||||
|
|
||||||
// Navigate to workspace
|
// Navigate to workspace
|
||||||
await router.navigate({
|
await router.navigate({
|
||||||
@@ -46,19 +42,14 @@ export function CreateWorkspaceDialog({ hide }: Props) {
|
|||||||
hide();
|
hide();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PlainInput require label="Workspace Name" defaultValue={name} onChange={setName} />
|
<PlainInput require label="Name" defaultValue={name} onChange={setName} />
|
||||||
|
|
||||||
<SyncToFilesystemSetting
|
<SyncToFilesystemSetting
|
||||||
onChange={setSettingSyncDir}
|
onChange={setSettingSyncDir}
|
||||||
value={settingSyncDir.value}
|
value={settingSyncDir}
|
||||||
allowNonEmptyDirectory // Will do initial import when the workspace is created
|
allowNonEmptyDirectory // Will do initial import when the workspace is created
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button type="submit" color="primary" className="ml-auto mt-3">
|
||||||
type="submit"
|
|
||||||
color="primary"
|
|
||||||
className="ml-auto mt-3"
|
|
||||||
disabled={settingSyncDir.enabled && !settingSyncDir.value}
|
|
||||||
>
|
|
||||||
Create Workspace
|
Create Workspace
|
||||||
</Button>
|
</Button>
|
||||||
</VStack>
|
</VStack>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { readDir } from '@tauri-apps/plugin-fs';
|
import { readDir } from '@tauri-apps/plugin-fs';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Checkbox } from './core/Checkbox';
|
import { Banner } from './core/Banner';
|
||||||
import { VStack } from './core/Stacks';
|
import { VStack } from './core/Stacks';
|
||||||
import { SelectFile } from './SelectFile';
|
import { SelectFile } from './SelectFile';
|
||||||
|
|
||||||
export interface SyncToFilesystemSettingProps {
|
export interface SyncToFilesystemSettingProps {
|
||||||
onChange: (args: { value: string | null; enabled: boolean }) => void;
|
onChange: (filePath: string | null) => void;
|
||||||
value: string | null;
|
value: string | null;
|
||||||
allowNonEmptyDirectory?: boolean;
|
allowNonEmptyDirectory?: boolean;
|
||||||
}
|
}
|
||||||
@@ -15,47 +15,37 @@ export function SyncToFilesystemSetting({
|
|||||||
value,
|
value,
|
||||||
allowNonEmptyDirectory,
|
allowNonEmptyDirectory,
|
||||||
}: SyncToFilesystemSettingProps) {
|
}: SyncToFilesystemSettingProps) {
|
||||||
const [useSyncDir, setUseSyncDir] = useState<boolean>(!!value);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack space={1.5} className="w-full">
|
<details open={value != null}>
|
||||||
<Checkbox
|
<summary>Sync to filesystem</summary>
|
||||||
checked={useSyncDir}
|
<VStack className="my-2" space={3}>
|
||||||
onChange={(enabled) => {
|
<Banner color="info">
|
||||||
setUseSyncDir(enabled);
|
When enabled, workspace data syncs to the chosen folder as text files, ideal for backup
|
||||||
if (!enabled) {
|
and Git collaboration.
|
||||||
// Set value to null when disabling
|
</Banner>
|
||||||
onChange({ value: null, enabled });
|
{error && <div className="text-danger">{error}</div>}
|
||||||
} else {
|
|
||||||
onChange({ value, enabled });
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
title="Sync to a filesystem directory"
|
|
||||||
/>
|
|
||||||
{error && <div className="text-danger">{error}</div>}
|
|
||||||
{useSyncDir && (
|
|
||||||
<SelectFile
|
<SelectFile
|
||||||
directory
|
directory
|
||||||
|
color="primary"
|
||||||
size="xs"
|
size="xs"
|
||||||
noun="Directory"
|
noun="Directory"
|
||||||
filePath={value}
|
filePath={value}
|
||||||
onChange={async ({ filePath }) => {
|
onChange={async ({ filePath }) => {
|
||||||
setError(null);
|
if (filePath != null) {
|
||||||
if (filePath == null) {
|
|
||||||
setUseSyncDir(false);
|
|
||||||
} else {
|
|
||||||
const files = await readDir(filePath);
|
const files = await readDir(filePath);
|
||||||
if (files.length > 0 && !allowNonEmptyDirectory) {
|
if (files.length > 0 && !allowNonEmptyDirectory) {
|
||||||
setError('Directory must be empty');
|
setError('The directory must be empty');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange({ value: filePath, enabled: useSyncDir });
|
onChange(filePath);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
</VStack>
|
||||||
</VStack>
|
</details>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export function WorkspaceSettingsDialog({ workspaceId, hide }: Props) {
|
|||||||
return (
|
return (
|
||||||
<VStack space={3} alignItems="start" className="pb-3 h-full">
|
<VStack space={3} alignItems="start" className="pb-3 h-full">
|
||||||
<Input
|
<Input
|
||||||
label="Workspace Name"
|
label="Name"
|
||||||
defaultValue={workspace.name}
|
defaultValue={workspace.name}
|
||||||
onChange={(name) => upsertWorkspace.mutate({ ...workspace, name })}
|
onChange={(name) => upsertWorkspace.mutate({ ...workspace, name })}
|
||||||
stateKey={`name.${workspace.id}`}
|
stateKey={`name.${workspace.id}`}
|
||||||
@@ -60,9 +60,9 @@ export function WorkspaceSettingsDialog({ workspaceId, hide }: Props) {
|
|||||||
<VStack space={6} className="mt-3 w-full" alignItems="start">
|
<VStack space={6} className="mt-3 w-full" alignItems="start">
|
||||||
<SyncToFilesystemSetting
|
<SyncToFilesystemSetting
|
||||||
value={workspaceMeta.settingSyncDir}
|
value={workspaceMeta.settingSyncDir}
|
||||||
onChange={({ value: settingSyncDir }) => {
|
onChange={(settingSyncDir) =>
|
||||||
upsertWorkspaceMeta.mutate({ ...workspaceMeta, settingSyncDir });
|
upsertWorkspaceMeta.mutate({ ...workspaceMeta, settingSyncDir })
|
||||||
}}
|
}
|
||||||
/>
|
/>
|
||||||
<Separator />
|
<Separator />
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -10,7 +10,15 @@ const sizes = {
|
|||||||
/** @type {import("tailwindcss").Config} */
|
/** @type {import("tailwindcss").Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
darkMode: ['class', '[data-resolved-appearance="dark"]'],
|
darkMode: ['class', '[data-resolved-appearance="dark"]'],
|
||||||
content: ['./index.html', './**/*.{html,js,jsx,ts,tsx}'],
|
content: [
|
||||||
|
'./*.{html,ts,tsx}',
|
||||||
|
'./commands/**/*.{ts,tsx}',
|
||||||
|
'./components/**/*.{ts,tsx}',
|
||||||
|
'./hooks/**/*.{ts,tsx}',
|
||||||
|
'./init/**/*.{ts,tsx}',
|
||||||
|
'./lib/**/*.{ts,tsx}',
|
||||||
|
'./routes/**/*.{ts,tsx}',
|
||||||
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
opacity: {
|
opacity: {
|
||||||
|
|||||||
Reference in New Issue
Block a user