import { AlertTriangle, Check, CloudOff, Eye, RefreshCw } from 'lucide-react' import type { BookRecord } from '@trek/shared' import type { SaveState } from './useBookStore' /** * Whether the book is safe. * * Autosave without a sign of it is a promise you are asking someone to take on * faith, and the moment they do not is the moment they close the tab to check. * So: a tick when it is written, a spinner while it is being written, and — the * one that matters — a real choice when someone else got there first. * * Quiet by design. This sits in the top bar of an editor, and a status that * announces every successful save is a status people learn to stop reading, * which is exactly the wrong habit for the one time it says something else. */ export function SaveIndicator({ state, t, onAcceptTheirs, onKeepMine, onRetry, onReload = reloadStudio, }: { state: SaveState t: (k: string) => string onAcceptTheirs: (current: BookRecord) => void onKeepMine: (current: BookRecord) => void onRetry: () => void /** Load this Studio again, for a book a newer one saved. A full reload by default. */ onReload?: () => void }) { if (state.status === 'conflict') { return (
{t('journey.studio.saveConflict')} {/* Two ways out, both stated plainly. There is no merge here and pretending otherwise would be worse than saying so: one of these documents is going to be the book. */}
) } if (state.status === 'newer') { /* * The one state with a way out the user has to take themselves: a newer * Studio saved this book, this tab cannot write it without losing what * that one added, and only a reload brings the newer Studio here. Loud * like a conflict, because until then nothing done here is kept. */ return (
{t('journey.studio.saveNewer')}
) } if (state.status === 'readonly') { /* * Not an error and not retryable: this person was invited to read the * journey, not to write it. Said once, plainly, and left standing — the * alternative is an editor that looks like it is saving and is not. */ return (
{t('journey.studio.saveReadOnly')}
) } if (state.status === 'error') { return ( ) } if (state.status === 'saving') { return (
{t('journey.studio.saving')}
) } if (state.status === 'saved') { return (
{t('journey.studio.saved')}
) } return null } /** The default way back to a current Studio: the page again, which loads the newest build. */ function reloadStudio() { window.location.reload() }