import { useState, useEffect } from 'react'; import { useSettingsStore } from '../../../stores/settingsStore'; import { useUIStore } from '../../../stores/uiStore'; import { Toggle } from '../../ui/Toggle'; import type { InstanceAdminSettings } from '@backspace/shared'; export function GeneralPanel() { const instanceSettings = useSettingsStore((s) => s.instanceSettings); const updateInstanceSettings = useSettingsStore((s) => s.updateInstanceSettings); const addToast = useUIStore((s) => s.addToast); const [draft, setDraft] = useState(null); const [saving, setSaving] = useState(false); const [saveError, setSaveError] = useState(''); const [gifKeyDirty, setGifKeyDirty] = useState(false); const [gifKeyDraft, setGifKeyDraft] = useState(''); useEffect(() => { if (instanceSettings) { setDraft({ ...instanceSettings }); setGifKeyDraft(''); setGifKeyDirty(false); } }, [instanceSettings]); if (!draft) return
Loading settings...
; const baseChanges = instanceSettings && draft ? draft.instanceName !== instanceSettings.instanceName || draft.discoveryEnabled !== instanceSettings.discoveryEnabled : false; const hasChanges = baseChanges || gifKeyDirty; const handleSave = async () => { setSaving(true); setSaveError(''); try { const payload: Partial = { instanceName: draft!.instanceName, discoveryEnabled: draft!.discoveryEnabled, }; if (gifKeyDirty) { payload.gifApiKey = gifKeyDraft; } await updateInstanceSettings(payload); setGifKeyDirty(false); setGifKeyDraft(''); addToast('Settings saved', 'success', 2000); } catch (err) { setSaveError(err instanceof Error ? err.message : 'Failed to save'); } finally { setSaving(false); } }; const handleReset = () => { if (instanceSettings) setDraft({ ...instanceSettings }); setGifKeyDirty(false); setGifKeyDraft(''); setSaveError(''); }; return (
e.preventDefault()}>

General

Configure your Backspace instance. These settings affect all users.
{/* Instance Name */}
Instance Name

The name shown on the login page and to federated instances.

setDraft({ ...draft, instanceName: e.target.value.slice(0, 32) })} placeholder="Backspace" className="input-standard w-full" />
{draft.instanceName.length}/32
{/* Discovery */}
Discovery
{/* GIF Search */}
GIF Search

Enable GIF search powered by Klipy. Get a free API key from the Klipy developer portal.

{ setGifKeyDraft(e.target.value); setGifKeyDirty(true); }} placeholder={draft.gifEnabled ? 'Key saved — enter new key to replace' : 'Klipy API key'} className="input-standard w-full" autoComplete="off" />
{draft.gifEnabled ? 'Enabled' : 'Not configured'} {draft.gifEnabled && !gifKeyDirty && ( )}
{/* Status messages */} {saveError && (
{saveError}
)} {/* Save / Reset bar */} {hasChanges && (
)}
); }