Repository Public
1// Share links of one file or folder: the existing links with their state and actions, and the creation of a new one.2import { useQuery } from '@tanstack/react-query';3import { useState } from 'react';4import { get } from '../api.ts';5import { Glyph } from '../glyphs.tsx';6import { useT } from '../i18n.ts';7import type { Share } from '../types.ts';8import { Button, Dialog, ErrorState, Loading } from '../ui.tsx';9import { LinkOnce } from './common.tsx';10import { ShareForm, ShareItem, useInvalidateShares } from './ShareParts.tsx';1112export function ShareDialog({ target, onClose }: { target: { type: 'file' | 'folder'; id: string; name: string }; onClose: () => void }) {13 const t = useT();14 const invalidate = useInvalidateShares();15 const q = useQuery({ queryKey: ['shares', target.type, target.id], queryFn: () => get<Share[]>(`/shares?${target.type === 'file' ? 'fileId' : 'folderId'}=${target.id}`), refetchOnMount: 'always' });16 const [view, setView] = useState<{ kind: 'list' } | { kind: 'create' } | { kind: 'created'; url: string }>({ kind: 'list' });17 const empty = !q.isLoading && !q.error && !q.data?.length;18 return (19 <Dialog title={t('sharing.dialog.title', { name: target.name })} onClose={onClose} wide>20 {view.kind === 'created' ? (21 <div className="space-y-4" data-testid="share-created">22 <p className="flex items-center gap-2 text-sm font-medium text-ok"><Glyph name="check" size={18} />{t('sharing.dialog.created')}</p>23 <LinkOnce url={view.url} title={target.name} />24 <div className="flex justify-end"><Button variant="primary" onClick={() => setView({ kind: 'list' })}>{t('sharing.link.done')}</Button></div>25 </div>26 ) : view.kind === 'create' || empty ? (27 <div className="space-y-4">28 <p className="text-sm text-ink-2">{empty ? t('sharing.dialog.emptyIntro') : t('sharing.dialog.createIntro')}</p>29 <ShareForm target={target} onCancel={() => (empty ? onClose() : setView({ kind: 'list' }))} onDone={(r) => { void invalidate(); setView({ kind: 'created', url: r.url! }); }} />30 </div>31 ) : q.isLoading ? <Loading /> : q.error ? <ErrorState error={q.error} onRetry={() => void q.refetch()} /> : (32 <div className="space-y-3">33 <div className="flex items-center justify-between gap-3">34 <p className="text-sm text-ink-2">{t('sharing.dialog.count', { n: q.data!.length })}</p>35 <Button variant="primary" icon="plus" onClick={() => setView({ kind: 'create' })}>{t('sharing.form.create')}</Button>36 </div>37 {q.data!.map((s) => <ShareItem key={s.id} share={s} />)}38 </div>39 )}40 </Dialog>41 );42}43