From af961d805e165c5a52318d29299b235711935067 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Thu, 2 Jul 2026 09:10:33 -0400 Subject: [PATCH] feat: channel settings modal now has name editing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added [OVERVIEW] tab to ChannelSettingsModal with an editable channel name field. The ⚙ button on each channel opens the modal. Users can rename channels without needing to know about the right-click context menu. --- web/src/components/ChannelSettingsModal.tsx | 59 ++++++++++++++++++--- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/web/src/components/ChannelSettingsModal.tsx b/web/src/components/ChannelSettingsModal.tsx index f09bb9c..5beb412 100644 --- a/web/src/components/ChannelSettingsModal.tsx +++ b/web/src/components/ChannelSettingsModal.tsx @@ -1,7 +1,9 @@ -import { useEffect, useState } from 'react'; -import { usePermissionStore, PERMISSION_LABELS, PERMS, type ChannelOverride, hasPermission } from '../stores/permissions.ts'; -import { useRoleStore } from '../stores/role.ts'; -import { useMemberStore } from '../stores/member.ts'; +import { useEffect, useState } from "react"; +import { usePermissionStore, PERMISSION_LABELS, PERMS, type ChannelOverride, hasPermission } from "../stores/permissions.ts"; +import { useRoleStore } from "../stores/role.ts"; +import { useMemberStore } from "../stores/member.ts"; +import { useChannelStore } from "../stores/channel.ts"; +import { api } from "../lib/api.ts"; interface ChannelSettingsModalProps { serverId: string; @@ -10,7 +12,7 @@ interface ChannelSettingsModalProps { onClose: () => void; } -type Tab = 'permissions'; +type Tab = 'overview' | 'permissions'; type TargetMode = 'role' | 'user'; interface OverrideFormData { @@ -76,10 +78,13 @@ function OverrideMatrix({ allow, deny, onChange }: { allow: number; deny: number } export function ChannelSettingsModal({ serverId, channelId, channelName, onClose }: ChannelSettingsModalProps) { - const [tab] = useState('permissions'); + const [tab, setTab] = useState('overview'); const [form, setForm] = useState({ targetType: 'role', targetId: '', allow: 0, deny: 0 }); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); + const [editName, setEditName] = useState(channelName); + const [savingName, setSavingName] = useState(false); + const updateChannel = useChannelStore((s) => s.updateChannel); const overrides = usePermissionStore((s) => s.overridesByChannel[channelId] || []); const fetchOverrides = usePermissionStore((s) => s.fetchOverrides); @@ -122,6 +127,24 @@ export function ChannelSettingsModal({ serverId, channelId, channelName, onClose } }; + const handleSaveName = async () => { + const name = editName.trim(); + if (!name || name === channelName) return; + setSavingName(true); + setError(null); + try { + const updated = await api.patch<{ id: string; server_id: string; name: string; type: string; category: string | null; position: number; group_id?: string | null }>( + `/servers/${serverId}/channels/${channelId}`, + { name } + ); + updateChannel(updated as any); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to rename channel'); + } finally { + setSavingName(false); + } + }; + const targets = form.targetType === 'role' ? roles.filter((r) => !r.is_default).map((r) => ({ id: r.id, label: r.name })) : members.map((m) => ({ id: m.id, label: m.username })); @@ -134,9 +157,31 @@ export function ChannelSettingsModal({ serverId, channelId, channelName, onClose
- + +
+ {tab === 'overview' && ( +
+
Channel name
+
+ setEditName(e.target.value)} + onKeyDown={(e) => { if (e.key === 'Enter') handleSaveName(); }} + className="terminal-input text-sm flex-1" + /> + +
+ {error &&
ERR: {error}
} +
+ )} {tab === 'permissions' && (
Existing overrides