mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 01:28:35 +02:00
Allow opening workspace if sync dir not empty
This commit is contained in:
@@ -1,20 +1,11 @@
|
|||||||
import { open } from '@tauri-apps/plugin-dialog';
|
|
||||||
import { applySync, calculateSyncFsOnly } from '@yaakapp-internal/sync';
|
import { applySync, calculateSyncFsOnly } from '@yaakapp-internal/sync';
|
||||||
import { createFastMutation } from '../hooks/useFastMutation';
|
import { createFastMutation } from '../hooks/useFastMutation';
|
||||||
import { showSimpleAlert } from '../lib/alert';
|
import { showSimpleAlert } from '../lib/alert';
|
||||||
import { router } from '../lib/router';
|
import { router } from '../lib/router';
|
||||||
|
|
||||||
export const openWorkspaceFromSyncDir = createFastMutation<void>({
|
export const openWorkspaceFromSyncDir = createFastMutation<void, void, string>({
|
||||||
mutationKey: [],
|
mutationKey: [],
|
||||||
mutationFn: async () => {
|
mutationFn: async (dir) => {
|
||||||
const dir = await open({
|
|
||||||
title: 'Select Workspace Directory',
|
|
||||||
directory: true,
|
|
||||||
multiple: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (dir == null) return;
|
|
||||||
|
|
||||||
const ops = await calculateSyncFsOnly(dir);
|
const ops = await calculateSyncFsOnly(dir);
|
||||||
|
|
||||||
const workspace = ops
|
const workspace = ops
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function CreateWorkspaceDialog({ hide }: Props) {
|
|||||||
const [syncConfig, setSyncConfig] = useState<{
|
const [syncConfig, setSyncConfig] = useState<{
|
||||||
filePath: string | null;
|
filePath: string | null;
|
||||||
initGit?: boolean;
|
initGit?: boolean;
|
||||||
}>({ filePath: null, initGit: true });
|
}>({ filePath: null, initGit: false });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack
|
<VStack
|
||||||
@@ -62,8 +62,8 @@ export function CreateWorkspaceDialog({ hide }: Props) {
|
|||||||
|
|
||||||
<SyncToFilesystemSetting
|
<SyncToFilesystemSetting
|
||||||
onChange={setSyncConfig}
|
onChange={setSyncConfig}
|
||||||
|
onCreateNewWorkspace={hide}
|
||||||
value={syncConfig}
|
value={syncConfig}
|
||||||
allowNonEmptyDirectory // Will do initial import when the workspace is created
|
|
||||||
/>
|
/>
|
||||||
<Button type="submit" color="primary" className="ml-auto mt-3">
|
<Button type="submit" color="primary" className="ml-auto mt-3">
|
||||||
Create Workspace
|
Create Workspace
|
||||||
|
|||||||
@@ -1,33 +1,54 @@
|
|||||||
import { readDir } from '@tauri-apps/plugin-fs';
|
import { readDir } from '@tauri-apps/plugin-fs';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { openWorkspaceFromSyncDir } from '../commands/openWorkspaceFromSyncDir';
|
||||||
import { Banner } from './core/Banner';
|
import { Banner } from './core/Banner';
|
||||||
|
import { Button } from './core/Button';
|
||||||
import { Checkbox } from './core/Checkbox';
|
import { Checkbox } from './core/Checkbox';
|
||||||
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: { filePath: string | null; initGit?: boolean }) => void;
|
onChange: (args: { filePath: string | null; initGit?: boolean }) => void;
|
||||||
|
onCreateNewWorkspace: () => void;
|
||||||
value: { filePath: string | null; initGit?: boolean };
|
value: { filePath: string | null; initGit?: boolean };
|
||||||
allowNonEmptyDirectory?: boolean;
|
|
||||||
forceOpen?: boolean;
|
forceOpen?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SyncToFilesystemSetting({
|
export function SyncToFilesystemSetting({
|
||||||
onChange,
|
onChange,
|
||||||
|
onCreateNewWorkspace,
|
||||||
value,
|
value,
|
||||||
allowNonEmptyDirectory,
|
|
||||||
forceOpen,
|
forceOpen,
|
||||||
}: SyncToFilesystemSettingProps) {
|
}: SyncToFilesystemSettingProps) {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [isNonEmpty, setIsNonEmpty] = useState<string | null>(null);
|
||||||
return (
|
return (
|
||||||
<details open={forceOpen || !!value.filePath} className="w-full">
|
<details open={forceOpen || !!value.filePath} className="w-full">
|
||||||
<summary>Data directory {typeof value.initGit === 'boolean' && ' and Git'}</summary>
|
<summary>Data directory {typeof value.initGit === 'boolean' && ' and Git'}</summary>
|
||||||
<VStack className="my-2" space={3}>
|
<VStack className="my-2" space={3}>
|
||||||
<Banner color="info">
|
{isNonEmpty ? (
|
||||||
Sync workspace data to folder as plain text files, ideal for backup and Git collaboration.
|
<Banner color="notice" className="flex flex-col gap-1.5">
|
||||||
Environments are excluded in order to keep your secrets private.
|
<p>The selected directory must be empty. Did you want to open it instead?</p>
|
||||||
</Banner>
|
<div>
|
||||||
{error && <div className="text-danger">{error}</div>}
|
<Button
|
||||||
|
variant="border"
|
||||||
|
color="notice"
|
||||||
|
size="xs"
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
openWorkspaceFromSyncDir.mutate(isNonEmpty);
|
||||||
|
onCreateNewWorkspace();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Open Workspace
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Banner>
|
||||||
|
) : (
|
||||||
|
<Banner color="info">
|
||||||
|
Sync workspace data to folder as plain text files, ideal for backup and Git
|
||||||
|
collaboration. Environments are excluded in order to keep your secrets private.
|
||||||
|
</Banner>
|
||||||
|
)}
|
||||||
|
|
||||||
<SelectFile
|
<SelectFile
|
||||||
directory
|
directory
|
||||||
@@ -37,12 +58,13 @@ export function SyncToFilesystemSetting({
|
|||||||
onChange={async ({ filePath }) => {
|
onChange={async ({ filePath }) => {
|
||||||
if (filePath != null) {
|
if (filePath != null) {
|
||||||
const files = await readDir(filePath);
|
const files = await readDir(filePath);
|
||||||
if (files.length > 0 && !allowNonEmptyDirectory) {
|
if (files.length > 0) {
|
||||||
setError('The directory must be empty');
|
setIsNonEmpty(filePath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsNonEmpty(null);
|
||||||
onChange({ ...value, filePath });
|
onChange({ ...value, filePath });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import {open} from "@tauri-apps/plugin-dialog";
|
||||||
import { revealItemInDir } from '@tauri-apps/plugin-opener';
|
import { revealItemInDir } from '@tauri-apps/plugin-opener';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
@@ -75,7 +76,16 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
|||||||
{
|
{
|
||||||
label: 'Open Existing Workspace',
|
label: 'Open Existing Workspace',
|
||||||
leftSlot: <Icon icon="folder_open" />,
|
leftSlot: <Icon icon="folder_open" />,
|
||||||
onSelect: openWorkspaceFromSyncDir.mutate,
|
onSelect: async () => {
|
||||||
|
const dir = await open({
|
||||||
|
title: 'Select Workspace Directory',
|
||||||
|
directory: true,
|
||||||
|
multiple: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dir == null) return;
|
||||||
|
openWorkspaceFromSyncDir.mutate(dir);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export function WorkspaceSettingsDialog({ workspaceId, hide, openSyncMenu }: Pro
|
|||||||
<SyncToFilesystemSetting
|
<SyncToFilesystemSetting
|
||||||
value={{ filePath: workspaceMeta.settingSyncDir }}
|
value={{ filePath: workspaceMeta.settingSyncDir }}
|
||||||
forceOpen={openSyncMenu}
|
forceOpen={openSyncMenu}
|
||||||
|
onCreateNewWorkspace={hide}
|
||||||
onChange={({ filePath }) => {
|
onChange={({ filePath }) => {
|
||||||
upsertWorkspaceMeta.mutate({ ...workspaceMeta, settingSyncDir: filePath });
|
upsertWorkspaceMeta.mutate({ ...workspaceMeta, settingSyncDir: filePath });
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user