import { useEffect, useMemo } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { fetchGuild, fetchMembers, guildMembersQueryKey, guildQueryKey } from '@/api/guilds'; import { fetchMyGuilds, myGuildsQueryKey } from '@/api/users'; import { ErrorNotice } from '@/components/ui/ErrorNotice'; import { Card } from '@/components/ui/primitives'; import { SkeletonLines } from '@/components/ui/Skeleton'; import { canAdministerGuild, canManageEmojis } from '@/lib/identity'; import { useCurrentUser } from '@/lib/hooks'; import { useSessionStore } from '@/stores/session'; import { GuildDangerSection } from '@/pages/settings/GuildDangerSection'; import { GuildEmojisSection } from '@/pages/settings/GuildEmojisSection'; import { GuildGeneralSection } from '@/pages/settings/GuildGeneralSection'; import { GuildMembersSection } from '@/pages/settings/GuildMembersSection'; import { GuildPicker } from '@/pages/settings/GuildPicker'; import { GuildRolesSection } from '@/pages/settings/GuildRolesSection'; /** * Пункт «Сервер» окна настроек: администрирование одного сервера — * общее (имя и описание), участники, роли, эмодзи и «Опасная зона». * * В отличие от вкладки «Профиль → Сервер» (там только свой никнейм), сюда * попадают через шестерёнку в шапке сервера или через пункт меню настроек. * Сервер можно переключить тем же выпадающим списком. */ export function GuildSettingsPage() { const sessionGuilds = useSessionStore((state) => state.guilds); const upsertGuild = useSessionStore((state) => state.upsertGuild); const selectSettingsGuild = useSessionStore((state) => state.selectSettingsGuild); // Подстраховка снапшота: без неё выбранный сервер не найти в сторе. const myGuilds = useQuery({ queryKey: myGuildsQueryKey, queryFn: ({ signal }) => fetchMyGuilds(signal), retry: 0, enabled: sessionGuilds.length === 0, }); useEffect(() => { if (sessionGuilds.length > 0 || myGuilds.data === undefined) { return; } for (const guild of myGuilds.data) { upsertGuild(guild); } }, [sessionGuilds.length, myGuilds.data, upsertGuild]); const guilds = useMemo( () => (sessionGuilds.length > 0 ? sessionGuilds : (myGuilds.data ?? [])), [sessionGuilds, myGuilds.data], ); return (
{myGuilds.isError ? ( void myGuilds.refetch()} /> ) : null}
); } /** Секции выбранного сервера: данные тянутся по REST только для него. */ function GuildSettingsBody({ guilds }: { guilds: { id: string }[] }) { const { t } = useTranslation(); const currentUser = useCurrentUser(); const selectedGuildId = useSessionStore((state) => state.settingsGuildId); const selectSettingsGuild = useSessionStore((state) => state.selectSettingsGuild); const active = useMemo( () => guilds.find((guild) => guild.id === selectedGuildId) ?? null, [guilds, selectedGuildId], ); // Первый доступный сервер выбираем сами: список только что загрузился. useEffect(() => { if (active !== null || guilds.length === 0) { return; } const first = guilds[0]; if (first !== undefined) { selectSettingsGuild(first.id); } }, [active, guilds, selectSettingsGuild]); const activeId = active?.id ?? null; const detail = useQuery({ queryKey: guildQueryKey(activeId ?? ''), queryFn: ({ signal }) => fetchGuild(activeId ?? '', signal), enabled: activeId !== null, retry: 0, }); const members = useQuery({ queryKey: guildMembersQueryKey(activeId ?? ''), queryFn: ({ signal }) => fetchMembers(activeId ?? '', signal), enabled: activeId !== null, retry: 0, }); if (activeId === null) { return (

{t('settings.servers.notFound')}

); } if (detail.isPending) { return ( ); } const guild = detail.data; if (guild === undefined) { return ( void detail.refetch()} /> ); } const canManage = canAdministerGuild( guild.my_permissions, guild.owner_id, currentUser.data?.id, currentUser.data?.is_instance_admin === true, ); // «Эмодзи» сервер разрешает владельцу, админу инстанса, ADMINISTRATOR // и MANAGE_EMOJIS: остальным секция не показывается. const canManageEmojiSet = canManageEmojis( guild.my_permissions, guild.owner_id, currentUser.data?.id, currentUser.data?.is_instance_admin === true, ); return ( <> void members.refetch()} /> {canManageEmojiSet ? ( ) : null} ); } export default GuildSettingsPage;