168 lines
8.4 KiB
TypeScript
168 lines
8.4 KiB
TypeScript
import { ActionAvatar } from "@/app/components/ActionAvatar/ActionAvatar";
|
|
import { Breadcrumbs } from "@/app/components/Breadcrumbs/Breadcrumbs";
|
|
import { GroupInvite } from "@/app/components/GroupInvite/GroupInvite";
|
|
import { InternalScreen } from "@/app/components/InternalScreen/InternalScreen";
|
|
import { KeyImage } from "@/app/components/KeyImage/KeyImage";
|
|
import { SettingsInput } from "@/app/components/SettingsInput/SettingsInput";
|
|
import { SettingsPaper } from "@/app/components/SettingsPaper/SettingsPaper";
|
|
import { SettingsText } from "@/app/components/SettingsText/SettingsText";
|
|
import { SettingsTitle } from "@/app/components/SettingsTitle/SettingsTitle";
|
|
import { UsersTable } from "@/app/components/UsersTable/UsersTable";
|
|
import { VerifiedBadge } from "@/app/components/VerifiedBadge/VerifiedBadge";
|
|
import { useRosettaColors } from "@/app/hooks/useRosettaColors";
|
|
import { usePublicKey } from "@/app/providers/AccountProvider/usePublicKey";
|
|
import { useGroupMembers } from "@/app/providers/InformationProvider/useGroupMembers";
|
|
import { useGroups } from "@/app/providers/DialogProvider/useGroups";
|
|
import { useGroupInformation } from "@/app/providers/InformationProvider/useGroupInformation";
|
|
import { Button, Flex, Paper, Skeleton, Text, useMantineTheme } from "@mantine/core";
|
|
import { IconBan, IconDoorExit, IconMessage } from "@tabler/icons-react";
|
|
import { useEffect, useState } from "react";
|
|
import { useNavigate, useParams } from "react-router-dom";
|
|
import { modals } from "@mantine/modals";
|
|
|
|
|
|
export function GroupInfo() {
|
|
const params = useParams();
|
|
const {groupInfo} = useGroupInformation(params.id!);
|
|
const {members, loading: membersLoading} = useGroupMembers(params.id!, true);
|
|
const publicKey = usePublicKey();
|
|
const isAdmin = members.length > 0 && members[0] == publicKey;
|
|
const colors = useRosettaColors();
|
|
const navigate = useNavigate();
|
|
const [groupKey, setGroupKey] = useState<string>('');
|
|
const {getGroupKey, leaveGroup, banUserOnGroup, loading, getPrefix} = useGroups();
|
|
const theme = useMantineTheme();
|
|
|
|
useEffect(() => {
|
|
initGroupKey();
|
|
}, [params.id]);
|
|
|
|
const initGroupKey = async () => {
|
|
const key = await getGroupKey(groupInfo.groupId);
|
|
setGroupKey(key);
|
|
}
|
|
|
|
const leaveGroupWithModal = () => {
|
|
modals.openConfirmModal({
|
|
title: 'Leave group',
|
|
centered: true,
|
|
children: (
|
|
<Text size="sm">
|
|
You are attempting to leave the group. Are you sure you want to proceed?
|
|
</Text>
|
|
),
|
|
withCloseButton: false,
|
|
labels: { confirm: 'Leave', cancel: "Cancel" },
|
|
confirmProps: { color: 'red' },
|
|
onConfirm: () => {
|
|
leaveGroup(groupInfo.groupId);
|
|
}
|
|
});
|
|
}
|
|
|
|
const banUserWithModal = (userPublicKey: string) => {
|
|
modals.openConfirmModal({
|
|
title: 'Ban user from group',
|
|
centered: true,
|
|
children: (
|
|
<Text size="sm">
|
|
You are attempting to ban this user from the group.
|
|
</Text>
|
|
),
|
|
withCloseButton: false,
|
|
labels: { confirm: 'Ban', cancel: "Cancel" },
|
|
confirmProps: { color: 'red' },
|
|
onConfirm: () => {
|
|
confirmBan(userPublicKey);
|
|
}
|
|
});
|
|
}
|
|
|
|
const confirmBan = (userPublicKey: string) => {
|
|
banUserOnGroup(userPublicKey, groupInfo.groupId);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Breadcrumbs text={groupInfo.title} rightSection={
|
|
<Button loading={loading} color={'red'} leftSection={<IconDoorExit size={15} />} onClick={leaveGroupWithModal} p={0} pr={6} variant={'transparent'}>Leave</Button>
|
|
}></Breadcrumbs>
|
|
<InternalScreen>
|
|
{(members.length > 0 || !membersLoading) && (
|
|
<>
|
|
<Paper radius="md" p="lg" bg={'transparent'}>
|
|
<ActionAvatar
|
|
forceChangeable={isAdmin}
|
|
title={groupInfo.title}
|
|
publicKey={getPrefix() + groupInfo.groupId} />
|
|
<Flex align={'center'} mt={'md'} justify={'center'} gap={5}>
|
|
<Text ta="center" fz="lg" fw={500}>{groupInfo.title.trim()}</Text>
|
|
</Flex>
|
|
<Text ta="center" c="dimmed" fz="sm">
|
|
{members.length} member{members.length !== 1 ? 's' : ''}
|
|
</Text>
|
|
</Paper>
|
|
{groupInfo.description.trim().length > 0 && (
|
|
<SettingsPaper p="xs">
|
|
<Text fw={500} pl={'xs'} fz={'xs'} c={'blue'}>Information</Text>
|
|
<Text pl={'xs'} fz={12} mt={3} c={'dimmed'}>
|
|
{groupInfo.description.trim()}
|
|
</Text>
|
|
</SettingsPaper>
|
|
)}
|
|
{isAdmin && (
|
|
<GroupInvite groupId={groupInfo.groupId} mt={'sm'}></GroupInvite>
|
|
)}
|
|
<SettingsInput.Clickable mt={'sm'} onClick={() => navigate('/main/groupencrypt/' + groupKey)} hit="Encryption key" settingsIcon={
|
|
<KeyImage radius={0} colors={[
|
|
theme.colors.blue[1],
|
|
theme.colors.blue[2],
|
|
theme.colors.blue[3],
|
|
theme.colors.blue[4],
|
|
theme.colors.blue[5]
|
|
]} size={18} keyRender={groupKey}></KeyImage>
|
|
}></SettingsInput.Clickable>
|
|
<SettingsText>Click to see encryption key for secure group communication</SettingsText>
|
|
{members.length > 0 && isAdmin && (
|
|
<>
|
|
<SettingsTitle mt={'sm'}>Group Members</SettingsTitle>
|
|
<UsersTable rightSection={(userPublicKey: string) => (
|
|
<>
|
|
<IconMessage onClick={() => navigate('/main/chat/' + userPublicKey)} stroke={1.4} size={20} color={colors.brandColor}></IconMessage>
|
|
{publicKey == userPublicKey && (
|
|
<IconDoorExit onClick={leaveGroupWithModal} stroke={1.4} size={20} color={colors.error}></IconDoorExit>
|
|
)}
|
|
{publicKey != userPublicKey && isAdmin && (
|
|
<IconBan onClick={() => banUserWithModal(userPublicKey)} stroke={1.4} size={20} color={colors.error}></IconBan>
|
|
)}
|
|
</>
|
|
)} usersPublicKeys={members} />
|
|
<SettingsText>
|
|
Members are listed in order of group creation. The first member is the group admin and can manage group settings.
|
|
</SettingsText>
|
|
</>
|
|
)}
|
|
{!isAdmin && (
|
|
<Flex mt={'lg'} gap={5} align={'center'}>
|
|
<Text fz={10} pl={'xs'} c={'gray'}>
|
|
Group administrator has marked in messages with
|
|
</Text>
|
|
<VerifiedBadge size={17} color={'gold'} verified={3}></VerifiedBadge>
|
|
</Flex>
|
|
)}
|
|
</>
|
|
)}
|
|
{membersLoading && members.length <= 0 && (
|
|
<>
|
|
<Flex direction={'column'} w={'100%'}>
|
|
<Skeleton h={150}></Skeleton>
|
|
<Skeleton h={50} mt={'sm'}></Skeleton>
|
|
<Skeleton h={50} mt={'sm'}></Skeleton>
|
|
<Skeleton h={50} mt={'sm'}></Skeleton>
|
|
</Flex>
|
|
</>
|
|
)}
|
|
</InternalScreen>
|
|
</>
|
|
);
|
|
} |