web: allow editing group and channel descriptions in chat info
Some checks failed
CI / test (push) Failing after 2m11s
Some checks failed
CI / test (push) Failing after 2m11s
This commit is contained in:
@@ -29,10 +29,10 @@ Legend:
|
|||||||
20. GIF - `DONE` (web GIF picker with provider search, preset fallback, and favorites)
|
20. GIF - `DONE` (web GIF picker with provider search, preset fallback, and favorites)
|
||||||
21. Message History/Search - `DONE` (history/pagination/chat+global search)
|
21. Message History/Search - `DONE` (history/pagination/chat+global search)
|
||||||
22. Text Formatting - `DONE` (bold/italic/underline/spoiler/mono/links + strikethrough + quote/code block; web composer supports keyboard shortcuts `Ctrl/Cmd+B/I/U/K`, `Ctrl/Cmd+Shift+X`, `Ctrl/Cmd+Shift+\``)
|
22. Text Formatting - `DONE` (bold/italic/underline/spoiler/mono/links + strikethrough + quote/code block; web composer supports keyboard shortcuts `Ctrl/Cmd+B/I/U/K`, `Ctrl/Cmd+Shift+X`, `Ctrl/Cmd+Shift+\``)
|
||||||
23. Groups - `DONE` (create/add/remove/invite link with role-aware moderation flows in web Chat Info and covered invite/join behavior)
|
23. Groups - `DONE` (create/add/remove/invite link with role-aware moderation flows in web Chat Info, including owner/admin editing of title and description)
|
||||||
24. Roles - `DONE` (owner/admin/member)
|
24. Roles - `DONE` (owner/admin/member)
|
||||||
25. Admin Rights - `DONE` (delete/pin/edit info + ban/unban/member role management with role-gated UI and APIs for groups/channels; member role no longer sees participants lists in group/channel chat info)
|
25. Admin Rights - `DONE` (delete/pin/edit info + ban/unban/member role management with role-gated UI and APIs for groups/channels; member role no longer sees participants lists in group/channel chat info)
|
||||||
26. Channels - `DONE` (create/post/edit/delete/subscribe/unsubscribe with role-aware channel behavior and invite-link flows)
|
26. Channels - `DONE` (create/post/edit/delete/subscribe/unsubscribe with role-aware channel behavior and invite-link flows; owner/admin can edit channel title and description in web Chat Info)
|
||||||
27. Channel Types - `DONE` (public/private)
|
27. Channel Types - `DONE` (public/private)
|
||||||
28. Notifications - `DONE` (browser notifications + mute/settings/sound; mention override for muted chats, realtime sync for mute state, notification click deep-link (`/?chat=..&message=..`) restores chat/message focus after auth)
|
28. Notifications - `DONE` (browser notifications + mute/settings/sound; mention override for muted chats, realtime sync for mute state, notification click deep-link (`/?chat=..&message=..`) restores chat/message focus after auth)
|
||||||
29. Archive - `DONE`
|
29. Archive - `DONE`
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export function ChatInfoPanel({ chatId, open, onClose }: Props) {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [titleDraft, setTitleDraft] = useState("");
|
const [titleDraft, setTitleDraft] = useState("");
|
||||||
|
const [descriptionDraft, setDescriptionDraft] = useState("");
|
||||||
const [savingTitle, setSavingTitle] = useState(false);
|
const [savingTitle, setSavingTitle] = useState(false);
|
||||||
const [chatAvatarUploading, setChatAvatarUploading] = useState(false);
|
const [chatAvatarUploading, setChatAvatarUploading] = useState(false);
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
@@ -210,6 +211,7 @@ export function ChatInfoPanel({ chatId, open, onClose }: Props) {
|
|||||||
const detail = await getChatDetail(targetChatId);
|
const detail = await getChatDetail(targetChatId);
|
||||||
setChat(detail);
|
setChat(detail);
|
||||||
setTitleDraft(detail.title ?? "");
|
setTitleDraft(detail.title ?? "");
|
||||||
|
setDescriptionDraft(detail.description ?? "");
|
||||||
const notificationSettings = await getChatNotificationSettings(targetChatId);
|
const notificationSettings = await getChatNotificationSettings(targetChatId);
|
||||||
setMuted(notificationSettings.muted);
|
setMuted(notificationSettings.muted);
|
||||||
if (detail.type === "private" && !detail.is_saved && detail.counterpart_user_id) {
|
if (detail.type === "private" && !detail.is_saved && detail.counterpart_user_id) {
|
||||||
@@ -487,23 +489,38 @@ export function ChatInfoPanel({ chatId, open, onClose }: Props) {
|
|||||||
value={titleDraft}
|
value={titleDraft}
|
||||||
onChange={(e) => setTitleDraft(e.target.value)}
|
onChange={(e) => setTitleDraft(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
<p className="mt-2 text-xs text-slate-400">Description</p>
|
||||||
|
<textarea
|
||||||
|
className="mt-1 min-h-[88px] w-full resize-y rounded bg-slate-800 px-3 py-2 text-sm outline-none"
|
||||||
|
maxLength={512}
|
||||||
|
onChange={(e) => setDescriptionDraft(e.target.value)}
|
||||||
|
placeholder="Enter chat description"
|
||||||
|
value={descriptionDraft}
|
||||||
|
/>
|
||||||
|
<p className="mt-1 text-[11px] text-slate-500">{descriptionDraft.length}/512</p>
|
||||||
<button
|
<button
|
||||||
className="mt-2 w-full rounded bg-sky-500 px-3 py-2 text-sm font-semibold text-slate-950 disabled:opacity-60"
|
className="mt-2 w-full rounded bg-sky-500 px-3 py-2 text-sm font-semibold text-slate-950 disabled:opacity-60"
|
||||||
disabled={savingTitle || !titleDraft.trim() || chatAvatarUploading}
|
disabled={savingTitle || !titleDraft.trim() || chatAvatarUploading}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setSavingTitle(true);
|
setSavingTitle(true);
|
||||||
try {
|
try {
|
||||||
const updated = await updateChatProfile(chatId, { title: titleDraft.trim() });
|
const normalizedDescription = descriptionDraft.trim();
|
||||||
|
const updated = await updateChatProfile(chatId, {
|
||||||
|
title: titleDraft.trim(),
|
||||||
|
description: normalizedDescription.length ? normalizedDescription : null,
|
||||||
|
});
|
||||||
setChat((prev) => (prev ? { ...prev, ...updated } : prev));
|
setChat((prev) => (prev ? { ...prev, ...updated } : prev));
|
||||||
|
setDescriptionDraft(updated.description ?? "");
|
||||||
await loadChats();
|
await loadChats();
|
||||||
|
showToast("Chat profile updated");
|
||||||
} catch {
|
} catch {
|
||||||
setError("Failed to update title");
|
setError("Failed to update chat profile");
|
||||||
} finally {
|
} finally {
|
||||||
setSavingTitle(false);
|
setSavingTitle(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Save title
|
Save profile
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
Reference in New Issue
Block a user