Skip to content

Commit 02fa4be

Browse files
authored
Merge pull request #1535 from The-Commit-Company/develop
Release v2.1.11
2 parents ee28fb9 + d30962e commit 02fa4be

16 files changed

Lines changed: 182 additions & 115 deletions

File tree

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "raven-ui",
33
"private": true,
44
"license": "AGPL-3.0-only",
5-
"version": "2.1.10",
5+
"version": "2.1.11",
66
"type": "module",
77
"scripts": {
88
"dev": "vite",

frontend/src/components/common/LinkField/LinkField.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ const LinkField = ({ doctype, filters, hideLabel = false, label, placeholder, va
9696
items.map((item, index) => (
9797
<li
9898
className={clsx(
99-
highlightedIndex === index && 'bg-accent-4',
99+
highlightedIndex === index && 'bg-gray-3 dark:bg-gray-4',
100100
selectedItem === item && 'font-bold',
101101
'py-2 px-3 shadow-sm flex gap-2 items-center',
102102
)}

frontend/src/components/feature/chat/ChatInput/DocumentLinkButton.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Box, Button, Dialog, Flex, IconButton, Tooltip } from '@radix-ui/themes'
22
import { DEFAULT_BUTTON_STYLE, ICON_PROPS } from './ToolPanel'
33
import { LuFileBox } from 'react-icons/lu'
4-
import { DIALOG_CONTENT_CLASS } from '@/utils/layout/dialog'
54
import { FormProvider, useForm } from 'react-hook-form'
65
import LinkFormField from '@/components/common/LinkField/LinkFormField'
76
import { ErrorText } from '@/components/common/Form'
@@ -34,7 +33,7 @@ const DocumentLinkButton = ({ channelID }: { channelID: string }) => {
3433
</IconButton>
3534
</Dialog.Trigger>
3635
</Tooltip>
37-
<Dialog.Content className={clsx(DIALOG_CONTENT_CLASS, 'static')}>
36+
<Dialog.Content className={'static'}>
3837
<Dialog.Title className='mb-1'>Send a document</Dialog.Title>
3938
<Dialog.Description size='2'>Choose a document from the system to send.</Dialog.Description>
4039
<DocumentLinkForm channelID={channelID} onClose={off} />

frontend/src/components/feature/chat/ChatMessage/LeftRightLayout/LeftRightLayout.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,25 @@ export const LeftRightLayout = ({ message, user, isActive, isHighlighted, onRepl
8080

8181
const alignToRight = CHAT_STYLE === "Left-Right" && currentUser === userID && !is_bot_message
8282

83+
const [selectedText, setSelectedText] = useState('')
84+
85+
const onContextMenuChange = (open: boolean) => {
86+
if (open) {
87+
// Get the selection that te user is actually highlighting
88+
const selection = document.getSelection()
89+
if (selection) {
90+
setSelectedText(selection.toString().trim())
91+
}
92+
} else {
93+
setSelectedText('')
94+
}
95+
}
96+
8397
return (
8498
<div className={clsx('flex py-0.5', alignToRight ? 'justify-end mr-4' : 'justify-start')}>
8599
<Flex align={'start'} gap={'2'}>
86100
{!alignToRight && <MessageLeftElement message={message} user={user} isActive={isActive} className="mt-[5px]" />}
87-
<ContextMenu.Root>
101+
<ContextMenu.Root modal={false} onOpenChange={onContextMenuChange}>
88102
<ContextMenu.Trigger
89103
{...bind}
90104
ref={ref}
@@ -157,6 +171,7 @@ export const LeftRightLayout = ({ message, user, isActive, isHighlighted, onRepl
157171
onDelete={onDelete}
158172
showThreadButton={showThreadButton}
159173
onEdit={onEdit}
174+
selectedText={selectedText}
160175
onReply={onReply}
161176
onForward={onForward}
162177
onViewReaction={onViewReaction}

frontend/src/components/feature/chat/ChatMessage/MessageActions/AttachFileToDocument.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import { useCallback, useState } from 'react'
33
import { Message } from '../../../../../../../types/Messaging/Message'
44
import { useIsDesktop } from '@/hooks/useMediaQuery'
55
import { Drawer, DrawerContent } from '@/components/layout/Drawer'
6-
import { DIALOG_CONTENT_CLASS } from '@/utils/layout/dialog'
7-
import clsx from 'clsx'
86
import AttachFileToDocumentModal from '../ActionModals/AttachFileToDocumentModal'
97

108
type Props = {
@@ -41,7 +39,7 @@ const AttachFileToDocumentDialog = ({ message, isOpen, onClose }: AttacFileToDoc
4139

4240
if (isDesktop) {
4341
return <Dialog.Root open={isOpen} onOpenChange={onClose}>
44-
<Dialog.Content className={clsx(DIALOG_CONTENT_CLASS, 'static')}>
42+
<Dialog.Content className={'static'}>
4543
{message &&
4644
<AttachFileToDocumentModal
4745
message={message}

frontend/src/components/feature/chat/ChatMessage/MessageActions/MessageActions.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ContextMenu, Flex } from '@radix-ui/themes'
2-
import { FileMessage, ImageMessage, Message } from '../../../../../../../types/Messaging/Message'
2+
import { FileMessage, Message } from '../../../../../../../types/Messaging/Message'
33
import { useContext } from 'react'
44
import { UserContext } from '@/utils/auth/UserProvider'
55
import { BiBookmarkMinus, BiBookmarkPlus, BiCopy, BiDownload, BiLink, BiPaperclip, BiTrash } from 'react-icons/bi'
@@ -24,11 +24,12 @@ export interface MessageContextMenuProps {
2424
onForward: VoidFunction,
2525
onViewReaction?: VoidFunction,
2626
onAttachDocument: VoidFunction,
27-
showThreadButton?: boolean
27+
showThreadButton?: boolean,
28+
selectedText?: string
2829
}
29-
export const MessageContextMenu = ({ message, onDelete, onEdit, onReply, onForward, showThreadButton, onAttachDocument, onViewReaction }: MessageContextMenuProps) => {
30+
export const MessageContextMenu = ({ message, onDelete, onEdit, onReply, onForward, showThreadButton, onAttachDocument, onViewReaction, selectedText }: MessageContextMenuProps) => {
3031

31-
const copy = useMessageCopy(message)
32+
const copy = useMessageCopy(message, selectedText)
3233
const { currentUser } = useContext(UserContext)
3334

3435
const isOwner = currentUser === message?.owner && !message?.is_bot_message
@@ -58,11 +59,11 @@ export const MessageContextMenu = ({ message, onDelete, onEdit, onReply, onForwa
5859
<CopyMessageLink message={message} />
5960
<ContextMenu.Separator />
6061
<ContextMenu.Group>
61-
{message.message_type === 'Text' &&
62+
{(message.text || selectedText) &&
6263
<ContextMenu.Item>
6364
<Flex gap='2' width='100%' onClick={copy}>
6465
<BiCopy size='18' />
65-
Copy
66+
Copy {selectedText ? 'Selected Text' : ''}
6667
</Flex>
6768
</ContextMenu.Item>
6869
}

frontend/src/components/feature/chat/ChatMessage/MessageActions/useMessageCopy.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@ import { Message } from '../../../../../../../types/Messaging/Message'
33
import turndown from 'turndown'
44
type Props = {}
55

6-
export const useMessageCopy = (message?: Message | null) => {
6+
export const useMessageCopy = (message?: Message | null, selectedText?: string) => {
77

88
const copy = () => {
99
if (!message) return
10+
if (selectedText) {
11+
navigator.clipboard.writeText(selectedText)
12+
toast.success('Text copied to clipboard')
13+
return
14+
}
1015
if (message.message_type === 'Text') {
1116

1217
// Remove all empty lines

frontend/src/components/feature/chat/ChatMessage/MessageItem.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,20 @@ export const MessageItem = ({ message, setDeleteMessage, isHighlighted, onReplyM
120120
// @ts-ignore
121121
const CHAT_STYLE = window.frappe?.boot?.chat_style ?? 'Simple'
122122

123+
const [selectedText, setSelectedText] = useState('')
124+
125+
const onContextMenuChange = (open: boolean) => {
126+
if (open) {
127+
// Get the selection that te user is actually highlighting
128+
const selection = document.getSelection()
129+
if (selection) {
130+
setSelectedText(selection.toString().trim())
131+
}
132+
} else {
133+
setSelectedText('')
134+
}
135+
}
136+
123137
return (
124138
<>
125139
{CHAT_STYLE === 'Left-Right' ? <LeftRightLayout
@@ -149,7 +163,7 @@ export const MessageItem = ({ message, setDeleteMessage, isHighlighted, onReplyM
149163
top-[42px]
150164
left-6 z-0`}>
151165
</div> : null}
152-
<ContextMenu.Root modal={false}>
166+
<ContextMenu.Root modal={false} onOpenChange={onContextMenuChange}>
153167
<ContextMenu.Trigger
154168
{...bind}
155169
ref={ref}
@@ -241,6 +255,7 @@ export const MessageItem = ({ message, setDeleteMessage, isHighlighted, onReplyM
241255
onReply={onReply}
242256
onForward={onForward}
243257
onViewReaction={onViewReaction}
258+
selectedText={selectedText}
244259
onAttachDocument={onAttachToDocument}
245260
/>
246261
</ContextMenu.Root>

frontend/src/hooks/usePostMessageReaction.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,37 @@ const usePostMessageReaction = () => {
3131
// If the message ID matches, we need to update the reactions object
3232
const existingReactions = JSON.parse(m.message_reactions ?? '{}') as Record<string, ReactionObject>
3333

34+
const emojiKey = is_custom ? (emoji_name ?? emoji) : emoji
35+
3436
// Check if the emoji is already in the reactions object
35-
if (existingReactions[emoji]) {
37+
if (existingReactions[emojiKey]) {
38+
const hasCurrentUserReacted = existingReactions[emojiKey].users.includes(username)
3639
// If it is, check how many users have reacted to the message
37-
const userCount = existingReactions[emoji].count
38-
39-
// If the user has already reacted, remove their reaction
40-
if (userCount > 1) {
41-
existingReactions[emoji].users = existingReactions[emoji].users.filter(u => u !== username)
42-
existingReactions[emoji].count = existingReactions[emoji].count - 1
40+
const userCount = existingReactions[emojiKey].count
41+
42+
if (hasCurrentUserReacted) {
43+
// Remove the user from the reaction
44+
if (userCount === 1) {
45+
delete existingReactions[emojiKey]
46+
} else {
47+
existingReactions[emojiKey].users = existingReactions[emojiKey].users.filter(u => u !== username)
48+
existingReactions[emojiKey].count = existingReactions[emojiKey].count - 1
49+
}
4350
} else {
44-
// If there is only one user, remove the reaction
45-
delete existingReactions[emoji]
51+
// If the user has not reacted, add them to the reaction
52+
existingReactions[emojiKey].users.push(username)
53+
existingReactions[emojiKey].count = existingReactions[emojiKey].count + 1
4654
}
4755
} else {
4856
// If it's not, add it
49-
existingReactions[emoji] = {
57+
existingReactions[emojiKey] = {
5058
reaction: emoji,
5159
users: [username],
5260
count: 1,
5361
emoji_name: emoji_name ?? ''
5462
}
5563
}
64+
5665
return {
5766
...m,
5867
message_reactions: JSON.stringify(existingReactions)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": true,
33
"name": "raven",
4-
"version": "2.1.10",
4+
"version": "2.1.11",
55
"description": "Messaging Application",
66
"workspaces": [
77
"frontend"

0 commit comments

Comments
 (0)