mirror of
https://github.com/deiucanta/chatpad.git
synced 2026-03-11 09:04:31 +00:00
disable sharing
This commit is contained in:
parent
f4dd6d38c5
commit
550a23af9b
4 changed files with 73 additions and 34 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { ActionIcon, Box, Flex, Header, TextInput, Tooltip, useMantineTheme } from "@mantine/core";
|
||||
import { IconAdjustments, IconInfoCircle } from "@tabler/icons-react";
|
||||
import { IconAdjustments, IconInfoCircle, IconShare2, IconWorld } from "@tabler/icons-react";
|
||||
import { EditChatModal } from "./EditChatModal";
|
||||
import { Chat, detaDB } from "../db";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
|
@ -93,7 +93,20 @@ export function ChatHeader({ readOnly = false }: { readOnly?: boolean}) {
|
|||
},
|
||||
})}
|
||||
>
|
||||
<ShareChatModal chat={chat!} />
|
||||
<ShareChatModal chat={chat!} readOnly={readOnly}>
|
||||
<Tooltip label={chat!.shared && !readOnly ? "Shared Chat" : "Share Chat"}>
|
||||
<ActionIcon size="xl" loaderProps={{ size: 20 }} pos="relative">
|
||||
{chat!.shared && !readOnly ? (
|
||||
<>
|
||||
<IconWorld size={20} />
|
||||
<Box w={10} h={10} sx={(theme) => ({ background: theme.colors.blue[6], borderRadius: '100%' })} pos="absolute" top={8} right={8}></Box>
|
||||
</>
|
||||
) : (
|
||||
<IconShare2 size={20} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</ShareChatModal>
|
||||
|
||||
{!readOnly ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { ActionIcon, Flex, Menu, useMantineTheme } from "@mantine/core";
|
||||
import { IconDotsVertical, IconMessages } from "@tabler/icons-react";
|
||||
import { IconDotsVertical, IconMessages, IconWorld } from "@tabler/icons-react";
|
||||
import { Link } from "@tanstack/react-location";
|
||||
import { DeleteChatModal } from "./DeleteChatModal";
|
||||
import { EditChatModal } from "./EditChatModal";
|
||||
|
|
@ -7,6 +7,7 @@ import { MainLink } from "./MainLink";
|
|||
import { useHover } from "@mantine/hooks";
|
||||
import { Chat } from "../db";
|
||||
import { useIncognitoMode } from "../hooks/contexts";
|
||||
import { ShareChatModal } from "./ShareChatModal";
|
||||
|
||||
export function ChatItem({ chat, active = false }: { chat: Chat, active?: boolean }) {
|
||||
const { hovered, ref } = useHover();
|
||||
|
|
@ -18,6 +19,7 @@ export function ChatItem({ chat, active = false }: { chat: Chat, active?: boolea
|
|||
ref={ref}
|
||||
key={chat.key}
|
||||
className={active ? "active" : undefined}
|
||||
align='center'
|
||||
sx={(theme) => ({
|
||||
marginTop: 1,
|
||||
"&:hover, &.active": {
|
||||
|
|
@ -42,6 +44,12 @@ export function ChatItem({ chat, active = false }: { chat: Chat, active?: boolea
|
|||
label={chat.description}
|
||||
/>
|
||||
</Link>
|
||||
|
||||
{chat.shared && !hovered && (
|
||||
<ActionIcon mr={5}>
|
||||
<IconWorld size={18} />
|
||||
</ActionIcon>
|
||||
)}
|
||||
|
||||
<Menu shadow="md" width={200} keepMounted>
|
||||
{hovered && (
|
||||
|
|
@ -52,6 +60,11 @@ export function ChatItem({ chat, active = false }: { chat: Chat, active?: boolea
|
|||
</Menu.Target>
|
||||
)}
|
||||
<Menu.Dropdown>
|
||||
{chat.shared && (
|
||||
<ShareChatModal chat={chat}>
|
||||
<Menu.Item>Share</Menu.Item>
|
||||
</ShareChatModal>
|
||||
)}
|
||||
<EditChatModal chat={chat}>
|
||||
<Menu.Item>Edit</Menu.Item>
|
||||
</EditChatModal>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,28 @@
|
|||
import { ActionIcon, Button, Input, Modal, Stack, Text, Tooltip } from "@mantine/core";
|
||||
import { Button, Input, Modal, Stack, Text } from "@mantine/core";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { IconShare2 } from "@tabler/icons-react";
|
||||
import { useState } from "react";
|
||||
import { ReactElement, cloneElement, useState } from "react";
|
||||
import { Chat, detaDB } from "../db";
|
||||
import { useChat } from "../hooks/contexts";
|
||||
import { useChat, useChats } from "../hooks/contexts";
|
||||
|
||||
export function ShareChatModal({ chat }: { chat: Chat }) {
|
||||
export function ShareChatModal({ children, chat, readOnly }: { children: ReactElement, chat: Chat, readOnly?: boolean }) {
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [url, setUrl] = useState<string | null>(null);
|
||||
|
||||
const { setChat } = useChat()
|
||||
const { setChats } = useChats()
|
||||
|
||||
const handleClick = async () => {
|
||||
if (!chat.shared) {
|
||||
setSubmitting(true)
|
||||
await detaDB.chats.update({ shared: true }, chat.key)
|
||||
setChat(current => ({ ...(current as unknown as Chat), shared: true }))
|
||||
setSubmitting(false)
|
||||
setChats(current => (current || []).map(item => {
|
||||
if (item.key === chat.key) {
|
||||
return { ...item, shared: true };
|
||||
}
|
||||
|
||||
return item;
|
||||
}))
|
||||
|
||||
notifications.show({
|
||||
title: "Shared!",
|
||||
|
|
@ -43,23 +47,45 @@ export function ShareChatModal({ chat }: { chat: Chat }) {
|
|||
close()
|
||||
}
|
||||
|
||||
const handleDisable = async () => {
|
||||
await detaDB.chats.update({ shared: false }, chat.key)
|
||||
setChat(current => ({ ...(current as unknown as Chat), shared: false }))
|
||||
setChats(current => (current || []).map(item => {
|
||||
if (item.key === chat.key) {
|
||||
return { ...item, shared: false };
|
||||
}
|
||||
|
||||
return item;
|
||||
}))
|
||||
|
||||
notifications.show({
|
||||
title: "Disabled!",
|
||||
color: "green",
|
||||
message: "Chat is now private.",
|
||||
})
|
||||
|
||||
close()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal opened={opened} onClose={close} title="Share Chat" size="md">
|
||||
{cloneElement(children, { onClick: handleClick })}
|
||||
<Modal opened={opened} onClose={close} title={chat.shared && !readOnly ? "Shared Chat" : "Share Chat"} size="md">
|
||||
<Stack>
|
||||
<Text size="sm">Use this URL to share this chat with others:</Text>
|
||||
<Input readOnly value={url ?? ''} />
|
||||
<Button type="submit" onClick={handleCopy}>
|
||||
Copy URL
|
||||
</Button>
|
||||
<Stack spacing="xs">
|
||||
<Button type="submit" onClick={handleCopy}>
|
||||
Copy URL
|
||||
</Button>
|
||||
{!readOnly && (
|
||||
<Button variant="light" color="red" onClick={handleDisable}>
|
||||
Disable Sharing
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Modal>
|
||||
|
||||
<Tooltip label="Share Chat">
|
||||
<ActionIcon size="xl" onClick={handleClick} loading={submitting} loaderProps={{ size: 20 }}>
|
||||
<IconShare2 size={20} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import {
|
||||
AppShell,
|
||||
Burger,
|
||||
MediaQuery,
|
||||
useMantineColorScheme,
|
||||
useMantineTheme,
|
||||
} from "@mantine/core";
|
||||
import { useRouter } from "@tanstack/react-location";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Chat } from "../db";
|
||||
import { usePublicChatId } from "../hooks/useChatId";
|
||||
|
|
@ -14,14 +10,9 @@ import { ChatHeader } from "../components/ChatHeader";
|
|||
import { useLocalStorage } from "@mantine/hooks";
|
||||
|
||||
export function PublicLayout({ children }: { children: React.ReactNode }) {
|
||||
const theme = useMantineTheme();
|
||||
const router = useRouter();
|
||||
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const chatId = usePublicChatId();
|
||||
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
const [incognitoMode, setIncognitoMode] = useLocalStorage({
|
||||
key: 'incognito-mode', defaultValue: false, getInitialValueInEffect: false
|
||||
});
|
||||
|
|
@ -49,10 +40,6 @@ export function PublicLayout({ children }: { children: React.ReactNode }) {
|
|||
}
|
||||
}, [chatId]);
|
||||
|
||||
useEffect(() => {
|
||||
setOpened(false);
|
||||
}, [router.state.location]);
|
||||
|
||||
return (
|
||||
<ChatContext.Provider value={{ chat: chat, setChat: setChat }}>
|
||||
<IncognitoModeContext.Provider value={{ incognitoMode: incognitoMode, setIncognitoMode: setIncognitoMode }}>
|
||||
|
|
|
|||
Loading…
Reference in a new issue