Dir sync filesystem watching

This commit is contained in:
Gregory Schier
2025-01-06 09:24:07 -08:00
parent c72180bb59
commit c2ea2a5fe5
35 changed files with 525 additions and 482 deletions

View File

@@ -1,3 +1,4 @@
import { useCallback } from 'react';
import type { DialogProps } from '../components/core/Dialog';
import type { ConfirmProps } from './Confirm';
import { Confirm } from './Confirm';
@@ -5,27 +6,30 @@ import { useDialog } from './useDialog';
export function useConfirm() {
const dialog = useDialog();
return ({
id,
title,
description,
variant,
confirmText,
}: {
id: string;
title: DialogProps['title'];
description?: DialogProps['description'];
variant?: ConfirmProps['variant'];
confirmText?: ConfirmProps['confirmText'];
}) =>
new Promise((onResult: ConfirmProps['onResult']) => {
dialog.show({
id,
title,
description,
hideX: true,
size: 'sm',
render: ({ hide }) => Confirm({ onHide: hide, variant, onResult, confirmText }),
});
});
return useCallback(
({
id,
title,
description,
variant,
confirmText,
}: {
id: string;
title: DialogProps['title'];
description?: DialogProps['description'];
variant?: ConfirmProps['variant'];
confirmText?: ConfirmProps['confirmText'];
}) =>
new Promise((onResult: ConfirmProps['onResult']) => {
dialog.show({
id,
title,
description,
hideX: true,
size: 'sm',
render: ({ hide }) => Confirm({ onHide: hide, variant, onResult, confirmText }),
});
}),
[dialog],
);
}

View File

@@ -1,6 +1,6 @@
import { debounce } from '@yaakapp-internal/lib';
import type { Dispatch, SetStateAction } from 'react';
import { useMemo, useState } from 'react';
import { debounce } from '../lib/debounce';
export function useDebouncedState<T>(
defaultValue: T,

View File

@@ -1,8 +1,8 @@
import type { OsType } from '@tauri-apps/plugin-os';
import { useEffect, useRef } from 'react';
import { capitalize } from '../lib/capitalize';
import { debounce } from '../lib/debounce';
import { useOsInfo } from './useOsInfo';
import { debounce } from '@yaakapp-internal/lib';
const HOLD_KEYS = ['Shift', 'Control', 'Command', 'Alt', 'Meta'];

View File

@@ -0,0 +1,102 @@
import { debounce } from '@yaakapp-internal/lib';
import type { Workspace } from '@yaakapp-internal/models';
import { applySync, calculateSync } from '@yaakapp-internal/sync';
import { useCallback, useMemo } from 'react';
import { InlineCode } from '../components/core/InlineCode';
import { VStack } from '../components/core/Stacks';
import { fallbackRequestName } from '../lib/fallbackRequestName';
import { pluralizeCount } from '../lib/pluralize';
import { useConfirm } from './useConfirm';
export function useSyncWorkspace(
workspace: Workspace | null,
{
debounceMillis = 1000,
}: {
debounceMillis?: number;
} = {},
) {
const confirm = useConfirm();
const sync = useCallback(async () => {
if (workspace == null) return;
const ops = await calculateSync(workspace);
if (ops.length === 0) {
return;
}
const dbChanges = ops.filter((o) => o.type.startsWith('db'));
if (dbChanges.length === 0) {
await applySync(workspace, ops);
return;
}
const confirmed = await confirm({
id: 'commit-sync',
title: 'Filesystem Changes Detected',
confirmText: 'Apply Changes',
description: (
<VStack space={3}>
<p>
{pluralizeCount('file', dbChanges.length)} in the directory have changed. Do you want to
apply the updates to your workspace?
</p>
<div className="overflow-y-auto max-h-[10rem]">
<table className="w-full text-sm mb-auto min-w-full max-w-full divide-y divide-surface-highlight">
<thead>
<tr>
<th className="py-1 text-left">Name</th>
<th className="py-1 text-right pl-4">Operation</th>
</tr>
</thead>
<tbody className="divide-y divide-surface-highlight">
{dbChanges.map((op, i) => {
let name = '';
let label = '';
let color = '';
if (op.type === 'dbCreate') {
label = 'create';
name = fallbackRequestName(op.fs.model);
color = 'text-success';
} else if (op.type === 'dbUpdate') {
label = 'update';
name = fallbackRequestName(op.fs.model);
color = 'text-info';
} else if (op.type === 'dbDelete') {
label = 'delete';
name = fallbackRequestName(op.model);
color = 'text-danger';
} else {
return null;
}
return (
<tr key={i} className="text-text">
<td className="py-1">{name}</td>
<td className="py-1 pl-4 text-right">
<InlineCode className={color}>{label}</InlineCode>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</VStack>
),
});
if (confirmed) {
await applySync(workspace, ops);
}
}, [confirm, workspace]);
const debouncedSync = useMemo(() => {
return debounce(sync, debounceMillis);
}, [debounceMillis, sync]);
return { sync, debouncedSync };
}