diff --git a/README.md b/README.md index 906868657..e2b334d73 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,12 @@ Install on Frappe Cloud»

- Learn More » + Learn More »

Issues · - Discussions + Community · Sponsor Us!

diff --git a/frontend/package.json b/frontend/package.json index d248c6d6d..d9abe5eeb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -2,7 +2,7 @@ "name": "raven-ui", "private": true, "license": "AGPL-3.0-only", - "version": "1.6.12", + "version": "1.6.13", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/feature/channel-details/leave-channel/LeaveChannelButton.tsx b/frontend/src/components/feature/channel-details/leave-channel/LeaveChannelButton.tsx index 23ebc6edf..20c236c69 100644 --- a/frontend/src/components/feature/channel-details/leave-channel/LeaveChannelButton.tsx +++ b/frontend/src/components/feature/channel-details/leave-channel/LeaveChannelButton.tsx @@ -3,6 +3,8 @@ import { LeaveChannelModal } from './LeaveChannelModal' import { useState } from 'react' import { AlertDialog, Button } from '@radix-ui/themes' import { DIALOG_CONTENT_CLASS } from '@/utils/layout/dialog' +import { Drawer, DrawerContent, DrawerTrigger } from '@/components/layout/Drawer' +import { useIsDesktop } from '@/hooks/useMediaQuery' interface LeaveChannelButtonProps { channelData: ChannelListItem, @@ -16,19 +18,43 @@ export const LeaveChannelButton = ({ channelData, onClose: onParentClose }: Leav setOpen(false) } - return ( - - - - - - - - - ) + const isDesktop = useIsDesktop() + + if (isDesktop) { + + return ( + + + + + + + + + ) + } else { + return ( + + + + + +
+ +
+
+
+ ) + } } \ No newline at end of file diff --git a/frontend/src/components/feature/channel-details/leave-channel/LeaveChannelModal.tsx b/frontend/src/components/feature/channel-details/leave-channel/LeaveChannelModal.tsx index ecc940e18..e6a0b7d34 100644 --- a/frontend/src/components/feature/channel-details/leave-channel/LeaveChannelModal.tsx +++ b/frontend/src/components/feature/channel-details/leave-channel/LeaveChannelModal.tsx @@ -1,11 +1,11 @@ import { useFrappeDeleteDoc, useFrappeGetCall } from 'frappe-react-sdk' -import { useContext } from 'react' +import { Fragment, useContext } from 'react' import { useNavigate } from 'react-router-dom' import { UserContext } from '../../../../utils/auth/UserProvider' import { ErrorBanner } from '../../../layout/AlertBanner' import { ChannelListContext, ChannelListContextType, ChannelListItem } from '@/utils/channel/ChannelListProvider' import { ChannelIcon } from '@/utils/layout/channelIcon' -import { AlertDialog, Button, Flex, Text } from '@radix-ui/themes' +import { AlertDialog, Button, Dialog, Flex, Text } from '@radix-ui/themes' import { Loader } from '@/components/common/Loader' import { toast } from 'sonner' import { getErrorMessage } from '@/components/layout/AlertBanner/ErrorBanner' @@ -13,10 +13,11 @@ import { getErrorMessage } from '@/components/layout/AlertBanner/ErrorBanner' interface LeaveChannelModalProps { onClose: () => void, channelData: ChannelListItem, - closeDetailsModal: () => void + closeDetailsModal: () => void, + isDrawer?: boolean } -export const LeaveChannelModal = ({ onClose, channelData, closeDetailsModal }: LeaveChannelModalProps) => { +export const LeaveChannelModal = ({ onClose, channelData, isDrawer, closeDetailsModal }: LeaveChannelModalProps) => { const { currentUser } = useContext(UserContext) const { deleteDoc, loading: deletingDoc, error } = useFrappeDeleteDoc() @@ -46,15 +47,20 @@ export const LeaveChannelModal = ({ onClose, channelData, closeDetailsModal }: L }) } + const Title = isDrawer ? Dialog.Title : AlertDialog.Title + const DialogCancel = isDrawer ? Fragment : AlertDialog.Cancel + const DialogAction = isDrawer ? Fragment : AlertDialog.Action + return ( <> - + + <Flex gap='1'> <Text>Leave </Text> <ChannelIcon type={channelData?.type} className={'mt-1'} /> <Text>{channelData?.channel_name}?</Text> </Flex> - </AlertDialog.Title> + @@ -65,17 +71,17 @@ export const LeaveChannelModal = ({ onClose, channelData, closeDetailsModal }: L - - - - + + - + ) diff --git a/frontend/src/components/feature/channel-settings/archive-channel/ArchiveChannelButton.tsx b/frontend/src/components/feature/channel-settings/archive-channel/ArchiveChannelButton.tsx index 096e4f31e..40e4477e1 100644 --- a/frontend/src/components/feature/channel-settings/archive-channel/ArchiveChannelButton.tsx +++ b/frontend/src/components/feature/channel-settings/archive-channel/ArchiveChannelButton.tsx @@ -4,6 +4,8 @@ import { ChannelListItem } from "@/utils/channel/ChannelListProvider"; import { useState } from "react"; import { AlertDialog, Button } from "@radix-ui/themes"; import { DIALOG_CONTENT_CLASS } from "@/utils/layout/dialog"; +import { useIsDesktop } from "@/hooks/useMediaQuery"; +import { Drawer, DrawerContent, DrawerTrigger } from "@/components/layout/Drawer"; interface ArchiveChannelButtonProps { onClose: () => void, @@ -18,20 +20,46 @@ export const ArchiveChannelButton = ({ onClose: onCloseParent, channelData, allo setOpen(false) } - return ( - - - - - - - - - ) + const isDesktop = useIsDesktop() + + if (isDesktop) { + return ( + + + + + + + + + ) + } else { + return ( + + + + + +
+ +
+
+
+ ) + } + + } \ No newline at end of file diff --git a/frontend/src/components/feature/channel-settings/archive-channel/ArchiveChannelModal.tsx b/frontend/src/components/feature/channel-settings/archive-channel/ArchiveChannelModal.tsx index 193697c06..dc21b002d 100644 --- a/frontend/src/components/feature/channel-settings/archive-channel/ArchiveChannelModal.tsx +++ b/frontend/src/components/feature/channel-settings/archive-channel/ArchiveChannelModal.tsx @@ -2,17 +2,19 @@ import { useFrappeUpdateDoc } from 'frappe-react-sdk' import { ErrorBanner } from '../../../layout/AlertBanner' import { useNavigate } from 'react-router-dom' import { ChannelListItem } from '@/utils/channel/ChannelListProvider' -import { AlertDialog, Flex, Text, Button } from '@radix-ui/themes' +import { AlertDialog, Flex, Text, Button, Dialog } from '@radix-ui/themes' import { Loader } from '@/components/common/Loader' import { toast } from 'sonner' +import { Fragment } from 'react' interface ArchiveChannelModalProps { onClose: () => void, onCloseViewDetails: () => void, - channelData: ChannelListItem + channelData: ChannelListItem, + isDrawer?: boolean } -export const ArchiveChannelModal = ({ onClose, onCloseViewDetails, channelData }: ArchiveChannelModalProps) => { +export const ArchiveChannelModal = ({ onClose, onCloseViewDetails, channelData, isDrawer }: ArchiveChannelModalProps) => { const { updateDoc, loading: archivingDoc, error } = useFrappeUpdateDoc() const navigate = useNavigate() @@ -23,14 +25,21 @@ export const ArchiveChannelModal = ({ onClose, onCloseViewDetails, channelData } }).then(() => { onClose() onCloseViewDetails() - navigate('/channel/general') + navigate('/channel') toast('Channel archived') }) } + const Title = isDrawer ? Dialog.Title : AlertDialog.Title + const DialogCancel = isDrawer ? Fragment : AlertDialog.Cancel + const DialogAction = isDrawer ? Fragment : AlertDialog.Action return ( <> - Archive this channel? + {isDrawer ? + Archive this channel? + : + Archive this channel? + } @@ -45,17 +54,17 @@ export const ArchiveChannelModal = ({ onClose, onCloseViewDetails, channelData } - + - - + + - + ) diff --git a/frontend/src/components/feature/channel-settings/change-channel-type/ChangeChannelTypeButton.tsx b/frontend/src/components/feature/channel-settings/change-channel-type/ChangeChannelTypeButton.tsx index 5281857ba..bd8840f5d 100644 --- a/frontend/src/components/feature/channel-settings/change-channel-type/ChangeChannelTypeButton.tsx +++ b/frontend/src/components/feature/channel-settings/change-channel-type/ChangeChannelTypeButton.tsx @@ -4,6 +4,8 @@ import { ChangeChannelTypeModal } from './ChangeChannelTypeModal' import { useState } from 'react' import { Button, Dialog, Separator } from '@radix-ui/themes' import { DIALOG_CONTENT_CLASS } from '@/utils/layout/dialog' +import { useIsDesktop } from '@/hooks/useMediaQuery' +import { Drawer, DrawerContent, DrawerTrigger } from '@/components/layout/Drawer' interface ChangeChannelTypeButtonProps { channelData: ChannelListItem, @@ -44,22 +46,47 @@ const ChangeChannelTypePublicPrivate = ({ channelData, allowSettingChange }: Cha setOpen(false) } - return ( - - - - - - - - - ) + const isDesktop = useIsDesktop() + + if (isDesktop) { + + return ( + + + + + + + + + ) + } + else { + return ( + + + + + +
+ +
+
+
+ ) + } } const ChangeChannelTypeOpenPublic = ({ channelData, allowSettingChange }: ChangeChannelTypeButtonProps) => { @@ -69,22 +96,46 @@ const ChangeChannelTypeOpenPublic = ({ channelData, allowSettingChange }: Change setOpen(false) } - return ( - - - - - - - - - ) + const isDesktop = useIsDesktop() + + if (isDesktop) { + + return ( + + + + + + + + + ) + } else { + return ( + + + + + +
+ +
+
+
+ ) + } } const ChangeChannelTypeOpenPrivate = ({ channelData, allowSettingChange }: ChangeChannelTypeButtonProps) => { @@ -94,20 +145,44 @@ const ChangeChannelTypeOpenPrivate = ({ channelData, allowSettingChange }: Chang setOpen(false) } - return ( - - - - - - - - - ) + const isDesktop = useIsDesktop() + + if (isDesktop) { + + return ( + + + + + + + + + ) + } else { + return ( + + + + + +
+ +
+
+
+ ) + } } diff --git a/frontend/src/components/feature/channel-settings/delete-channel/DeleteChannelButton.tsx b/frontend/src/components/feature/channel-settings/delete-channel/DeleteChannelButton.tsx index df64a51b5..dbd9d59ed 100644 --- a/frontend/src/components/feature/channel-settings/delete-channel/DeleteChannelButton.tsx +++ b/frontend/src/components/feature/channel-settings/delete-channel/DeleteChannelButton.tsx @@ -4,6 +4,8 @@ import { BiTrash } from 'react-icons/bi' import { useState } from 'react' import { AlertDialog, Button } from '@radix-ui/themes' import { DIALOG_CONTENT_CLASS } from '@/utils/layout/dialog' +import { useIsDesktop } from '@/hooks/useMediaQuery' +import { Drawer, DrawerContent, DrawerTrigger } from '@/components/layout/Drawer' interface DeleteChannelButtonProps { onClose: () => void, @@ -18,20 +20,45 @@ export const DeleteChannelButton = ({ onClose: onCloseParent, channelData, allow setOpen(false) } - return ( - - - - - - - - - ) + const isDesktop = useIsDesktop() + + if (isDesktop) { + + return ( + + + + + + + + + ) + } else { + return ( + + + + + +
+ +
+
+
+ ) + } } \ No newline at end of file diff --git a/frontend/src/components/feature/channel-settings/delete-channel/DeleteChannelModal.tsx b/frontend/src/components/feature/channel-settings/delete-channel/DeleteChannelModal.tsx index 77c36aa83..49e91ab91 100644 --- a/frontend/src/components/feature/channel-settings/delete-channel/DeleteChannelModal.tsx +++ b/frontend/src/components/feature/channel-settings/delete-channel/DeleteChannelModal.tsx @@ -1,9 +1,9 @@ import { ErrorBanner } from '../../../layout/AlertBanner' -import { useState } from 'react' +import { Fragment, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useFrappeDeleteDoc } from 'frappe-react-sdk' import { ChannelListItem } from '@/utils/channel/ChannelListProvider' -import { AlertDialog, Button, Callout, Checkbox, Flex, Text } from '@radix-ui/themes' +import { AlertDialog, Button, Callout, Checkbox, Dialog, Flex, Text } from '@radix-ui/themes' import { Loader } from '@/components/common/Loader' import { FiAlertTriangle } from 'react-icons/fi' import { toast } from 'sonner' @@ -11,10 +11,11 @@ import { toast } from 'sonner' type DeleteChannelModalProps = { onClose: () => void, onCloseParent: () => void, - channelData: ChannelListItem + channelData: ChannelListItem, + isDrawer?: boolean } -export const DeleteChannelModal = ({ onClose, onCloseParent, channelData }: DeleteChannelModalProps) => { +export const DeleteChannelModal = ({ onClose, onCloseParent, isDrawer, channelData }: DeleteChannelModalProps) => { const { deleteDoc, error, loading: deletingDoc, reset } = useFrappeDeleteDoc() @@ -40,11 +41,13 @@ export const DeleteChannelModal = ({ onClose, onCloseParent, channelData }: Dele const [allowDelete, setAllowDelete] = useState(false) + const Title = isDrawer ? Dialog.Title : AlertDialog.Title + const DialogCancel = isDrawer ? Fragment : AlertDialog.Cancel + const DialogAction = isDrawer ? Fragment : AlertDialog.Action + return ( <> - - Delete this channel? - + Delete this channel? @@ -72,15 +75,19 @@ export const DeleteChannelModal = ({ onClose, onCloseParent, channelData }: Dele - + + - - + + + + + ) diff --git a/frontend/src/components/feature/chat/ChatInput/RightToolbarButtons.tsx b/frontend/src/components/feature/chat/ChatInput/RightToolbarButtons.tsx index b081cc1cf..6131ebee3 100644 --- a/frontend/src/components/feature/chat/ChatInput/RightToolbarButtons.tsx +++ b/frontend/src/components/feature/chat/ChatInput/RightToolbarButtons.tsx @@ -188,16 +188,32 @@ export const SendButton = ({ sendMessage, messageSending, setContent, ...props } const onClick = () => { if (editor) { - const hasContent = editor.getText().trim().length > 0 const hasInlineImage = editor.getHTML().includes('img') let html = '' - let json = {} + let json: any = {} if (hasContent || hasInlineImage) { - html = editor.getHTML() json = editor.getJSON() + + // remove empty paragraphs at the end of the content + const content = json.content + + for (let i = content.length - 1; i >= 0; i--) { + if (content[i].type === 'paragraph' && (!content[i].content || content[i].content.length === 0)) { + content.pop() + } else { + break + } + } + + json.content = content + + // Get the HTMl content + editor.commands.setContent(json) + + html = editor.getHTML() } editor.setEditable(false) sendMessage(html, json) diff --git a/frontend/src/components/feature/chat/ChatInput/Tiptap.tsx b/frontend/src/components/feature/chat/ChatInput/Tiptap.tsx index 85f4b896d..315e580f8 100644 --- a/frontend/src/components/feature/chat/ChatInput/Tiptap.tsx +++ b/frontend/src/components/feature/chat/ChatInput/Tiptap.tsx @@ -499,7 +499,8 @@ const Tiptap = ({ isEdit, slotBefore, fileProps, onMessageSend, replyMessage, cl // followCursor: true, offset: [90, 15], inlinePositioning: true, - }}> + }} + editor={editor}>
diff --git a/frontend/src/components/feature/userSettings/PushNotifications/PushNotificationToggle.tsx b/frontend/src/components/feature/userSettings/PushNotifications/PushNotificationToggle.tsx index 03bd27f8c..238f21cc8 100644 --- a/frontend/src/components/feature/userSettings/PushNotifications/PushNotificationToggle.tsx +++ b/frontend/src/components/feature/userSettings/PushNotifications/PushNotificationToggle.tsx @@ -35,23 +35,28 @@ const PushNotificationToggle = (props: Props) => { } const enablePushNotifications = async () => { - // @ts-expect-error - window.frappePushNotification - .enableNotification() - .then((data: any) => { - if (data.permission_granted) { - setPushNotificationsEnabled(true) - toast.success("Push notifications enabled") - } else { - toast.error("Permission denied for push notifications") + + + toast.promise( + // @ts-expect-error + window.frappePushNotification + .enableNotification() + .then((data: any) => { + if (data.permission_granted) { + setPushNotificationsEnabled(true) + } else { + setPushNotificationsEnabled(false) + throw new Error("Permission denied for push notifications") + } + }) + .catch((error: any) => { setPushNotificationsEnabled(false) - } - }) - .catch((error: any) => { - toast.error("Error enabling push notifications", { - description: getErrorMessage(error) + throw error }) - setPushNotificationsEnabled(false) + , { + success: "Push notifications enabled", + loading: "Enabling...", + error: (e: Error) => e.message }) } diff --git a/frontend/src/components/layout/Sidebar/SidebarHeader.tsx b/frontend/src/components/layout/Sidebar/SidebarHeader.tsx index 3dcc0a66e..02c7fec98 100644 --- a/frontend/src/components/layout/Sidebar/SidebarHeader.tsx +++ b/frontend/src/components/layout/Sidebar/SidebarHeader.tsx @@ -1,8 +1,9 @@ import { useTheme } from '@/ThemeProvider' import { commandMenuOpenAtom } from '@/components/feature/CommandMenu/CommandMenu' -import { Flex, IconButton, Text } from '@radix-ui/themes' -import { BiCommand, BiMoon, BiSun } from 'react-icons/bi' +import { Flex, IconButton, Text, Tooltip } from '@radix-ui/themes' +import { BiMoon, BiSun } from 'react-icons/bi' import { useSetAtom } from 'jotai' +import { TbSearch } from 'react-icons/tb' export const SidebarHeader = () => { return ( @@ -14,7 +15,7 @@ export const SidebarHeader = () => { pt='1' height='48px'> raven - + @@ -28,17 +29,19 @@ const SearchButton = () => { const setOpen = useSetAtom(commandMenuOpenAtom) return ( - setOpen(true)} - > - - + + setOpen(true)} + > + + + ) } diff --git a/package.json b/package.json index 5400ee89b..10cd0808e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "raven", - "version": "1.6.12", + "version": "1.6.13", "description": "Messaging Application", "workspaces": [ "frontend" diff --git a/raven/__init__.py b/raven/__init__.py index 44bc99cdf..765214ea8 100644 --- a/raven/__init__.py +++ b/raven/__init__.py @@ -1 +1 @@ -__version__ = "1.6.12" +__version__ = "1.6.13" diff --git a/raven/package.json b/raven/package.json index 591f9b23d..6848da4ea 100644 --- a/raven/package.json +++ b/raven/package.json @@ -1,6 +1,6 @@ { "name": "raven-app", - "version": "1.6.12", + "version": "1.6.13", "description": "", "main": "index.js", "scripts": {