Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: UI issues in v1.3 #579

Merged
merged 13 commits into from
Dec 8, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SquareAvatar, UserAvatar } from '@/components/common/UserAvatar'
import { MarkdownRenderer } from '@/components/common/MarkdownRenderer'
import { UserFields } from '@/utils/users/UserListProvider'
import { DateObjectToFormattedDateString, DateObjectToFormattedDateStringWithoutYear, DateObjectToTimeString } from '@/utils/operations/operations'
import { useFrappeGetDoc } from 'frappe-react-sdk'
import { useFrappeGetCall, useFrappeGetDoc } from 'frappe-react-sdk'
import { ChannelMembersContext } from './ChatView'
import { openOutline } from 'ionicons/icons'
import { Haptics, ImpactStyle } from '@capacitor/haptics'
Expand Down Expand Up @@ -160,12 +160,18 @@ const FileMessageBlock = ({ message }: { message: FileMessage }) => {
const ReplyBlock = ({ linked_message }: { linked_message: string }) => {
const members = useContext(ChannelMembersContext)

//TODO: Cache the messages to prevent API calls
const { data } = useFrappeGetDoc<Message>('Raven Message', linked_message)
const { data, isLoading } = useFrappeGetCall('raven.api.chat.get_reply_message_content', {
message_id: linked_message
}, `reply_message_${linked_message}`, {
revalidateIfStale: false,
revalidateOnFocus: false,
shouldRetryOnError: false,
revalidateOnReconnect: false
})

const user = useMemo(() => {
if (data) {
return members[data.owner]
if (data && data.message) {
return members[data?.message.owner]
} else {
return undefined
}
Expand All @@ -178,20 +184,20 @@ const ReplyBlock = ({ linked_message }: { linked_message: string }) => {
document.getElementById(`message-${linked_message}`)?.scrollIntoView({ behavior: 'smooth' })
}

const date = data ? new Date(data?.creation) : null
const date = data ? new Date(data?.message?.creation) : null
return <div onClick={scrollToMessage} className='px-2 py-1.5 my-2 rounded-e-sm bg-neutral-900 border-l-4 border-l-neutral-500'>
{data && <div>
{data && data.message && <div>
<div className='flex items-end pb-1'>
<IonText className='font-bold text-sm'>{user?.full_name ?? data.owner}</IonText>
<IonText className='font-bold text-sm'>{user?.full_name ?? data.message.owner}</IonText>
{date && <IonText className='font-normal text-xs pl-2' color='medium'>on {DateObjectToFormattedDateStringWithoutYear(date)} at {DateObjectToTimeString(date)}</IonText>}
</div>
{data.message_type === 'Text' && <div className='text-sm text-neutral-400'><TextMessageBlock message={data} truncate /></div>}
{data.message_type === 'Image' && <div className='flex items-center space-x-2'>
<img src={data.file} alt={`Image`} className='inline-block w-10 h-10 rounded-md' />
{data.message.message_type === 'Text' && <div className='text-sm text-neutral-400'><TextMessageBlock message={data.message} truncate /></div>}
{data.message.message_type === 'Image' && <div className='flex items-center space-x-2'>
<img src={data.message.file} alt={`Image`} className='inline-block w-10 h-10 rounded-md' />
<p className='text-sm font-semibold'>📸 &nbsp;Image</p>
</div>}
{data.message_type === 'File' && <p
className='text-sm font-semibold'>📎 &nbsp;{data.file?.split('/')[3]}</p>}
{data.message.message_type === 'File' && <p
className='text-sm font-semibold'>📎 &nbsp;{data.message.file?.split('/')[3]}</p>}
</div>
}
</div>
Expand Down
2 changes: 1 addition & 1 deletion raven-app/src/components/common/Toast/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const ToastViewport = React.forwardRef<
<ToastPrimitives.Viewport
ref={ref}
className={clsx(
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 right-14 sm:bottom-0 sm:top-auto sm:flex-col md:max-w-[320px]",
className
)}
{...props}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ export const DMChannelHeader = ({ channelData, channelMembers }: DMChannelHeader
return (
<PageHeader>
<Flex gap='2' align='center'>
<UserAvatar key={peer} alt={channelMembers?.[peer]?.full_name ?? peer} src={channelMembers?.[peer]?.user_image ?? ''} isActive={isActive} size='2' />
<UserAvatar
key={peer}
alt={channelMembers?.[peer]?.full_name ?? peer} src={channelMembers?.[peer]?.user_image ?? ''}
isActive={isActive}
skeletonSize='6'
size='2' />
<Heading size='5'>{channelMembers?.[peer]?.full_name ?? peer}</Heading>
</Flex>
<SearchButton />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const EmojiPicker = lazy(() => import('@/components/common/EmojiPicker/EmojiPick
type RightToolbarButtonsProps = {
fileProps?: ToolbarFileProps,
sendMessage: (html: string, json: any) => Promise<void>,
messageSending: boolean
messageSending: boolean,
setContent: (content: string) => void
}
/**
* Component to render the right toolbar buttons:
Expand Down Expand Up @@ -131,9 +132,10 @@ const FilePickerButton = ({ fileProps }: { fileProps: ToolbarFileProps }) => {
}


const SendButton = ({ sendMessage, messageSending }: {
const SendButton = ({ sendMessage, messageSending, setContent }: {
sendMessage: RightToolbarButtonsProps['sendMessage'],
messageSending: boolean
messageSending: boolean,
setContent: RightToolbarButtonsProps['setContent']
}) => {
const { editor } = useCurrentEditor()
const onClick = () => {
Expand All @@ -151,6 +153,7 @@ const SendButton = ({ sendMessage, messageSending }: {
editor.setEditable(false)
sendMessage(html, json)
.then(() => {
setContent('')
editor.chain().focus().clearContent(true).run()
editor.setEditable(true)
})
Expand Down
22 changes: 6 additions & 16 deletions raven-app/src/components/feature/chat/ChatInput/Tiptap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface ToolbarFileProps {
type TiptapEditorProps = {
slotBefore?: React.ReactNode,
slotAfter?: React.ReactNode,
placeholder?: string,
sessionStorageKey?: string,
disableSessionStorage?: boolean,
fileProps?: ToolbarFileProps,
Expand All @@ -50,18 +51,6 @@ type TiptapEditorProps = {
defaultText?: string
}

const COOL_PLACEHOLDERS = [
"Sure - you can send your message via pigeons, only if you want them covered in poop 😷",
"Delivering messages atop dragons 🐉 is available on a chargeable basis.",
"Note 🚨: Service beyond the wall is currently disrupted due to bad weather.",
"Pigeons just have better brand recognition tbh 🤷🏻",
"Ravens double up as spies. Eyes everywhere 👀",
"Ravens do not 'slack' off. See what we did there? 😉",
"Were you expecting a funny placeholder? 😂",
"Want to know who writes these placeholders? 🤔. No one.",
"Type a message..."
]

export const UserMention = Mention.extend({
name: 'userMention',
})
Expand All @@ -81,7 +70,7 @@ export const ChannelMention = Mention.extend({
pluginKey: new PluginKey('channelMention'),
}
})
const Tiptap = ({ slotBefore, fileProps, onMessageSend, messageSending, sessionStorageKey = 'tiptap-editor', disableSessionStorage = false, defaultText = '' }: TiptapEditorProps) => {
const Tiptap = ({ slotBefore, fileProps, onMessageSend, placeholder = 'Type a message...', messageSending, sessionStorageKey = 'tiptap-editor', disableSessionStorage = false, defaultText = '' }: TiptapEditorProps) => {

const { users } = useContext(UserListContext)

Expand Down Expand Up @@ -406,7 +395,7 @@ const Tiptap = ({ slotBefore, fileProps, onMessageSend, messageSending, sessionS
}),
Placeholder.configure({
// Pick a random placeholder from the list.
placeholder: COOL_PLACEHOLDERS[Math.floor(Math.random() * (COOL_PLACEHOLDERS.length))],
placeholder,
}),
CodeBlockLowlight.configure({
lowlight
Expand All @@ -420,7 +409,6 @@ const Tiptap = ({ slotBefore, fileProps, onMessageSend, messageSending, sessionS
const editor = useEditor({
extensions,
content,
autofocus: "end",
editorProps: {
attributes: {
class: 'tiptap-editor'
Expand All @@ -431,6 +419,8 @@ const Tiptap = ({ slotBefore, fileProps, onMessageSend, messageSending, sessionS
}
}, [onMessageSend])



useEffect(() => {
editor?.commands.setContent(content)
}, [onMessageSend])
Expand All @@ -443,7 +433,7 @@ const Tiptap = ({ slotBefore, fileProps, onMessageSend, messageSending, sessionS
<EditorContent editor={editor} />
<ToolPanel>
<TextFormattingMenu />
<RightToolbarButtons fileProps={fileProps} sendMessage={onMessageSend} messageSending={messageSending} />
<RightToolbarButtons fileProps={fileProps} setContent={setContent} sendMessage={onMessageSend} messageSending={messageSending} />
</ToolPanel>
</EditorContext.Provider>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const SaveMessageAction = ({ message, updateMessages }: { message: Message, upda
}).then(() => {
toast({
title: isSaved ? 'Message unsaved' : 'Message saved',
variant: isSaved ? 'default' : 'accent',
variant: 'accent',
duration: 800,
})
updateMessages()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ export const QuickActions = ({ message, onReply, onEdit, updateMessages, isOwner
-top-6
right-4
group-hover:visible
z-2
group-hover:transition-all
group-hover:delay-100
z-50
p-1
shadow-md
rounded-md
Expand All @@ -70,13 +72,13 @@ export const QuickActions = ({ message, onReply, onEdit, updateMessages, isOwner

<EmojiPickerButton saveReaction={onEmojiReact} />

{isOwner && message.message_type === 'Text' ? <Tooltip content='Edit'><QuickActionButton
{isOwner && message.message_type === 'Text' ? <QuickActionButton
onClick={onEdit}
tooltip='Edit message'
aria-label='Edit message'>
<BiEditAlt size='18' />
</QuickActionButton>
</Tooltip> :
:
<QuickActionButton
tooltip='Reply'
aria-label='Reply to this message'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export const MessageItem = ({ message, setDeleteMessage, onReplyMessageClick, se
<ContextMenu.Root>
<ContextMenu.Trigger className='group
hover:bg-gray-100
dark:hover:bg-gray-5
hover:transition-all
hover:delay-100
dark:hover:bg-gray-3
data-[state=open]:bg-accent-2
dark:data-[state=open]:bg-gray-4
data-[state=open]:shadow-sm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const CustomLink = TiptapLink.extend({
return [
"a",
mergeAttributes(HTMLAttributes, {
class: 'rt-Text rt-reset rt-Link rt-underline-auto'
class: 'rt-Text rt-reset rt-Link rt-underline-auto break-all line-clamp-3'
}), // mergeAttributes is a exported function from @tiptap/core
0,
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { CustomUserMention } from './Mention'
import { CustomLink, LinkPreview } from './Link'
import { CustomItalic } from './Italic'
import { CustomUnderline } from './Underline'
import { clsx } from 'clsx'
const lowlight = createLowlight(common)

lowlight.register('html', html)
Expand Down Expand Up @@ -78,7 +79,7 @@ export const TiptapRenderer = ({ message, user, showLinkPreview = true, ...props
})

return (
<Box {...props}>
<Box className={clsx('overflow-x-hidden', props.className)} {...props}>
<EditorContent
editor={editor}
readOnly />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FileMessage, Message, TextMessage } from "../../../../../../../types/Messaging/Message"
import { Flex, Separator, Text } from "@radix-ui/themes"
import { Box, Flex, Separator, Text } from "@radix-ui/themes"
import { useGetUser } from "@/hooks/useGetUser"
import { DateMonthAtHourMinuteAmPm } from "@/utils/dateConversions"
import { FileExtensionIcon } from "@/utils/layout/FileExtIcon"
Expand Down Expand Up @@ -31,15 +31,16 @@ export const ReplyMessageBox = ({ message, children, className, ...props }: Repl
<DateMonthAtHourMinuteAmPm date={message.creation} />
</Text>
</Flex>
{['File', 'Image'].includes(message.message_type) ?
<Flex gap='1'>
{message.message_type === 'File' && <FileExtensionIcon ext={getFileExtension(message.file)} />}
{message.message_type === 'Image' && <img src={message.file} alt={`Image sent by ${message.owner}`} height='30' width='30' className="object-cover" />}
<Text as='span'>{getFileName((message as FileMessage).file)}</Text>
</Flex>
: <TruncatedTiptapRenderer message={message as TextMessage} />
}

<Box className="max-w-3xl">
{['File', 'Image'].includes(message.message_type) ?
<Flex gap='1'>
{message.message_type === 'File' && <FileExtensionIcon ext={getFileExtension(message.file)} />}
{message.message_type === 'Image' && <img src={message.file} alt={`Image sent by ${message.owner}`} height='30' width='30' className="object-cover" />}
<Text as='span'>{getFileName((message as FileMessage).file)}</Text>
</Flex>
: <TruncatedTiptapRenderer message={message as TextMessage} />
}
</Box>
</Flex>
{children}
</Flex>
Expand All @@ -54,12 +55,8 @@ interface ReplyMessageProps extends FlexProps {
*/
export const ReplyMessage = ({ messageID, ...props }: ReplyMessageProps) => {

const { data, isLoading } = useFrappeGetCall('frappe.client.get_value', {
doctype: 'Raven Message',
filters: {
name: messageID
},
fieldname: JSON.stringify(['owner', 'creation', 'message_type', 'file', 'text', 'channel_id', 'name'])
const { data, isLoading } = useFrappeGetCall('raven.api.chat.get_reply_message_content', {
message_id: messageID
}, `reply_message_${messageID}`, {
revalidateIfStale: false,
revalidateOnFocus: false,
Expand Down
26 changes: 21 additions & 5 deletions raven-app/src/components/feature/chat/ChatStream/ChatBoxBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ import { BiX } from "react-icons/bi"


const Tiptap = lazy(() => import("../ChatInput/Tiptap"))

const COOL_PLACEHOLDERS = [
"Sure - you can send your message via pigeons, only if you want them covered in poop 😷",
"Delivering messages atop dragons 🐉 is available on a chargeable basis.",
"Note 🚨: Service beyond the wall is currently disrupted due to bad weather.",
"Pigeons just have better brand recognition tbh 🤷🏻",
"Ravens double up as spies. Eyes everywhere 👀",
"Ravens do not 'slack' off. See what we did there? 😉",
"Were you expecting a funny placeholder? 😂",
"Want to know who writes these placeholders? 🤔. No one.",
"Type a message..."
]
const randomPlaceholder = COOL_PLACEHOLDERS[Math.floor(Math.random() * (COOL_PLACEHOLDERS.length))]
interface ChatBoxBodyProps {
channelData: ChannelListItem | DMChannelListItem
}
Expand Down Expand Up @@ -101,17 +114,19 @@ export const ChatBoxBody = ({ channelData }: ChatBoxBodyProps) => {
if (data) {
return (
<Flex height='100%' direction='column' justify={'end'} p='4' pt='9' className="overflow-hidden">

<FileDrop
files={files}
ref={fileInputRef}
onFileChange={setFiles}
maxFiles={10}
maxFileSize={10000000}>
<ChatHistory
parsedMessages={data.message}
replyToMessage={handleReplyAction}
channelData={channelData} />

{isLoading ? <FullPageLoader className="w-full" /> :
<ChatHistory
parsedMessages={data.message}
replyToMessage={handleReplyAction}
channelData={channelData} />
}
{channelData?.is_archived == 0 && (isUserInChannel || channelData?.type === 'Open')
&&
<Suspense fallback={<Flex align='center' justify='center' width='100%' height='9'><Loader /></Flex>}>
Expand All @@ -121,6 +136,7 @@ export const ChatBoxBody = ({ channelData }: ChatBoxBodyProps) => {
fileInputRef,
addFile
}}
placeholder={randomPlaceholder}
sessionStorageKey={`tiptap-${channelData.name}`}
onMessageSend={sendMessage}
messageSending={loading}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useCallback, useContext, useRef } from "react";
import { Virtuoso } from 'react-virtuoso';
import { VirtuosoRefContext } from "../../../../utils/message/VirtuosoRefProvider";
import { ChannelListItem, DMChannelListItem } from "@/utils/channel/ChannelListProvider";
import { Box, Flex } from "@radix-ui/themes";
import { Box } from "@radix-ui/themes";
import { DateMonthYear } from "@/utils/dateConversions";
import { MessageItem } from "../ChatMessage/MessageItem";
import { DeleteMessageDialog, useDeleteMessage } from "../ChatMessage/MessageActions/DeleteMessage";
Expand Down Expand Up @@ -134,7 +134,7 @@ const RenderItem = ({ index, replyToMessage, updateMessages, block, onReplyMessa
}
if (block.block_type === 'message') {
return (
<Box>
<Box className="w-full overflow-x--hidden">
<MessageItem
message={block.data}
updateMessages={updateMessages}
Expand Down
4 changes: 2 additions & 2 deletions raven-app/src/components/feature/file-upload/FileListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export const FileListItem = ({ file, removeFile, uploadProgress }: FileListItemP

return (
<Flex width='100%' justify={'start'} gap='2' className='border rounded-md border-slate-8 dark:bg-slate-5 bg-slate-2' px='1' py='1'>
<Flex align='center' justify='center' width='6'>
{previewURL ? <img src={previewURL} alt='File preview' className='aspect-square object-cover rounded-md' /> : <FileExtensionIcon ext={getFileExtension(file.name)} />}
<Flex align='center' justify='center' className='w-12 h-12'>
{previewURL ? <img src={previewURL} alt='File preview' className='w-10 h-10 aspect-square object-cover rounded-md' /> : <FileExtensionIcon ext={getFileExtension(file.name)} className='h-10' />}
</Flex>
<Flex justify="between" className='w-48' align='center'>
<Flex direction='column' width='100%' pr='2' className='overflow-hidden whitespace-nowrap'>
Expand Down
Loading