Files
spacedrive/interface/app/$libraryId/settings/library/sync.tsx
Vítor Vasconcellos 561462760b Fix autoformat CI & format codebase (#2581)
* Update pnpm version

* Fix autoformat

* Improve autoformat msg

* Attempt to fix autoformat 2

* Fix autoformat

* Ignore deleted files in auto-format

* Fix diff filter

* Autoformat whole codebase

* Improve error message for autoformat CI

* Test autoformat CI

* Revert "Test autoformat CI"

This reverts commit 0bf2f46d1a.
2024-07-04 08:57:43 +00:00

229 lines
5.1 KiB
TypeScript

import { inferSubscriptionResult } from '@oscartbeaumont-sd/rspc-client';
import clsx from 'clsx';
import { useEffect, useState } from 'react';
import {
Procedures,
useFeatureFlag,
useLibraryMutation,
useLibraryQuery,
useLibrarySubscription,
useZodForm
} from '@sd/client';
import { Button, Dialog, dialogManager, useDialog, UseDialogProps, z } from '@sd/ui';
import { useLocale } from '~/hooks';
import { Heading } from '../Layout';
import Setting from '../Setting';
const ACTORS = {
Ingest: 'Sync Ingest',
CloudSend: 'Cloud Sync Sender',
CloudReceive: 'Cloud Sync Receiver',
CloudIngest: 'Cloud Sync Ingest'
};
export const Component = () => {
const { t } = useLocale();
const syncEnabled = useLibraryQuery(['sync.enabled']);
const backfillSync = useLibraryMutation(['sync.backfill'], {
onSuccess: async () => {
await syncEnabled.refetch();
}
});
const [data, setData] = useState<inferSubscriptionResult<Procedures, 'library.actors'>>({});
useLibrarySubscription(['library.actors'], { onData: setData });
const cloudSync = useFeatureFlag('cloudSync');
return (
<>
<Heading title={t('sync')} description={t('sync_description')} />
{syncEnabled.data === false ? (
<Setting mini title={t('enable_sync')} description={t('enable_sync_description')}>
<div>
<Button
className="text-nowrap"
variant="accent"
onClick={() => {
dialogManager.create((dialogProps) => (
<SyncBackfillDialog
onEnabled={() => syncEnabled.refetch()}
{...dialogProps}
/>
));
}}
disabled={backfillSync.isLoading}
>
{t('enable_sync')}
</Button>
</div>
</Setting>
) : (
<>
<Setting
mini
title={
<>
{t('ingester')}
<OnlineIndicator online={data[ACTORS.Ingest] ?? false} />
</>
}
description={t('injester_description')}
>
<div>
{data[ACTORS.Ingest] ? (
<StopButton name={ACTORS.Ingest} />
) : (
<StartButton name={ACTORS.Ingest} />
)}
</div>
</Setting>
{cloudSync && <CloudSync data={data} />}
</>
)}
</>
);
};
function SyncBackfillDialog(props: UseDialogProps & { onEnabled: () => void }) {
const form = useZodForm({ schema: z.object({}) });
const dialog = useDialog(props);
const { t } = useLocale();
const enableSync = useLibraryMutation(['sync.backfill'], {});
// dialog is in charge of enabling sync
useEffect(() => {
form.handleSubmit(
async () => {
await enableSync.mutateAsync(null).then(() => (dialog.state.open = false));
await props.onEnabled();
},
() => {}
)();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<Dialog
title={t('backfill_sync')}
description={t('backfill_sync_description')}
form={form}
dialog={dialog}
hideButtons
ignoreClickOutside
/>
);
}
function CloudSync({ data }: { data: inferSubscriptionResult<Procedures, 'library.actors'> }) {
const { t } = useLocale();
return (
<>
<div>
<h1 className="mb-0.5 text-lg font-bold text-ink">{t('cloud_sync')}</h1>
<p className="text-sm text-ink-faint">{t('cloud_sync_description')}</p>
</div>
<Setting
mini
title={
<>
{t('sender')} <OnlineIndicator online={data[ACTORS.CloudSend] ?? false} />
</>
}
description={t('sender_description')}
>
<div>
{data[ACTORS.CloudSend] ? (
<StopButton name={ACTORS.CloudSend} />
) : (
<StartButton name={ACTORS.CloudSend} />
)}
</div>
</Setting>
<Setting
mini
title={
<>
{t('receiver')}
<OnlineIndicator online={data[ACTORS.CloudReceive] ?? false} />
</>
}
description={t('receiver_description')}
>
<div>
{data[ACTORS.CloudReceive] ? (
<StopButton name={ACTORS.CloudReceive} />
) : (
<StartButton name={ACTORS.CloudReceive} />
)}
</div>
</Setting>
<Setting
mini
title={
<>
{t('ingester')}
<OnlineIndicator online={data[ACTORS.CloudIngest] ?? false} />
</>
}
description={t('ingester_description')}
>
<div>
{data[ACTORS.CloudIngest] ? (
<StopButton name={ACTORS.CloudIngest} />
) : (
<StartButton name={ACTORS.CloudIngest} />
)}
</div>
</Setting>
</>
);
}
function StartButton({ name }: { name: string }) {
const startActor = useLibraryMutation(['library.startActor']);
const { t } = useLocale();
return (
<Button
variant="accent"
disabled={startActor.isLoading}
onClick={() => startActor.mutate(name)}
>
{startActor.isLoading ? t('starting') : t('start')}
</Button>
);
}
function StopButton({ name }: { name: string }) {
const stopActor = useLibraryMutation(['library.stopActor']);
const { t } = useLocale();
return (
<Button
variant="accent"
disabled={stopActor.isLoading}
onClick={() => stopActor.mutate(name)}
>
{stopActor.isLoading ? t('stopping') : t('stop')}
</Button>
);
}
function OnlineIndicator({ online }: { online: boolean }) {
return (
<div
className={clsx(
'ml-1.5 inline-block size-2.5 rounded-full',
online ? 'bg-green-500' : 'bg-red-500'
)}
/>
);
}