diff --git a/docs/FRONTEND.md b/docs/FRONTEND.md index 8b5b958..a3ea702 100644 --- a/docs/FRONTEND.md +++ b/docs/FRONTEND.md @@ -60,11 +60,13 @@ No router library — a tiny history wrapper (`lib/route.ts`: `navigate()`, share button), message list (`Markdown` for assistant, emerald bubble for user), rounded composer with paperclip attach menu, attachment chips (Enter to send, Shift+Enter for newline). With `readOnly` (archived chat) - the composer and share button are replaced by an unarchive banner. + the composer is replaced by an unarchive banner with a share button + (archived chats stay shareable, but an archived public chat cannot go + private again — `DELETE …/share` answers 403 until unarchived). - `dialogs.tsx` — `ConvEditDialog` (title + topic), `ShareModal` (public link, copy, unshare), `SettingsModal` (display name, avatar upload box with drag & drop, avatar URL, theme, plus an "Archived chats" category to - view / unarchive / delete archived conversations). + view / unarchive / delete / share archived conversations). - `AdminPanel.tsx` — No-KYC account management: create (key shown once), regenerate (revokes sessions), edit, delete with confirm, plus server-side search / sort (newest, oldest, A–Z, Z–A) / email filter / pagination. diff --git a/frontend/src/components/Chat.tsx b/frontend/src/components/Chat.tsx index 3e5b535..803c06f 100644 --- a/frontend/src/components/Chat.tsx +++ b/frontend/src/components/Chat.tsx @@ -625,6 +625,15 @@ export function Chat({

{t("archived.readonly")}

+ + {!archived ? ( + + ) : ( + + )} @@ -651,6 +663,7 @@ function ArchivedSection({ onView, onChanged }: { onView: (c: Conversation) => v const [error, setError] = useState(""); const [busyId, setBusyId] = useState(null); const [deleteTarget, setDeleteTarget] = useState(null); + const [shareTarget, setShareTarget] = useState(null); async function refresh() { try { @@ -738,6 +751,16 @@ function ArchivedSection({ onView, onChanged }: { onView: (c: Conversation) => v > +