Skip to content

Commit 278f216

Browse files
Merge pull request #2129 from The-Commit-Company/develop
Merge develop to main
2 parents 7b7147c + ae4d2cb commit 278f216

11 files changed

Lines changed: 112 additions & 46 deletions

File tree

apps/mobile/components/features/chat/ChatMessage/Renderers/ReplyMessageBox.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const ReplyMessageBox = ({ message, onPress }: ReplyMessageBoxProps) => {
3939
return (
4040
<View className="flex-row items-start gap-1">
4141
<BarChart width={18} height={18} fill={colors.icon} />
42-
<Text className="text-[15px] line-clamp-2 text-ellipsis overflow-hidden">
42+
<Text className="text-[15px] line-clamp-2 text-ellipsis overflow-hidden flex-1" numberOfLines={2} ellipsizeMode="tail">
4343
Poll: {replyMessageDetails.content?.split("\n")?.[0]}
4444
</Text>
4545
</View>
@@ -49,7 +49,7 @@ const ReplyMessageBox = ({ message, onPress }: ReplyMessageBoxProps) => {
4949
return <ImageFileReplyBlock file={replyMessageDetails.file} messageType={replyMessageDetails.message_type} owner={replyMessageDetails.owner} />
5050

5151
default:
52-
return <Text className="text-base text-foreground line-clamp-2 text-ellipsis overflow-hidden">
52+
return <Text className="text-base text-foreground line-clamp-2 text-ellipsis overflow-hidden flex-1" numberOfLines={2} ellipsizeMode="tail">
5353
{replyMessageDetails.content}
5454
</Text>
5555
}
@@ -122,4 +122,4 @@ const ImageFileReplyBlock = ({ file, messageType, owner }: { file: string, messa
122122
)
123123
}
124124

125-
export default ReplyMessageBox
125+
export default ReplyMessageBox

apps/mobile/components/features/workspaces/WorkspaceSwitcher.tsx

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import SiteSwitcher from '../auth/SiteSwitcher'
1515
import { getSiteNameFromUrl } from '@raven/lib/utils/operations'
1616
import ServerIcon from '@assets/icons/ServerIcon.svg'
1717
import AddSite from '../auth/AddSite'
18+
import { FrappeError, useFrappePostCall, useSWRConfig } from 'frappe-react-sdk'
19+
import { toast } from 'sonner-native'
20+
import { getErrorMessage } from '@components/common/ErrorBanner'
21+
import { ActivityIndicator } from '@components/nativewindui/ActivityIndicator'
1822

1923
const WorkspaceSwitcher = ({ workspace, setWorkspace }: { workspace: string, setWorkspace: (workspace: string) => Promise<void> }) => {
2024

@@ -108,6 +112,9 @@ interface SelectWorkspaceSheetProps {
108112

109113
const SelectWorkspaceSheet = ({ selectedWorkspace, workspaces, setWorkspace }: SelectWorkspaceSheetProps) => {
110114

115+
const { call: joinWorkspace, loading: joiningWorkspace } = useFrappePostCall('raven.api.workspaces.join_workspace')
116+
const { mutate } = useSWRConfig()
117+
111118
const { myWorkspaces, otherWorkspaces } = useMemo(() => {
112119
const myWorkspaces: Workspace[] = []
113120
const otherWorkspaces: Workspace[] = []
@@ -127,6 +134,26 @@ const SelectWorkspaceSheet = ({ selectedWorkspace, workspaces, setWorkspace }: S
127134
return { myWorkspaces, otherWorkspaces }
128135
}, [workspaces, selectedWorkspace])
129136

137+
const handleJoinOtherWorkspace = useCallback(
138+
(workspaceName: string) => {
139+
const displayName =
140+
workspaces.find((w) => w.name === workspaceName)?.workspace_name ?? workspaceName
141+
142+
joinWorkspace({ workspace: workspaceName })
143+
.then(() => Promise.all([mutate('workspaces_list'), mutate('channel_list')]))
144+
.then(() => setWorkspace(workspaceName))
145+
.then(() => {
146+
toast.success(`You have joined ${displayName}.`)
147+
})
148+
.catch((error: unknown) => {
149+
toast.error(
150+
getErrorMessage(error as FrappeError) || 'Failed to join the workspace.'
151+
)
152+
})
153+
},
154+
[joinWorkspace, setWorkspace, workspaces]
155+
)
156+
130157
const siteInfo = useSiteContext()
131158

132159
const urlWithoutProtocol = useMemo(() => {
@@ -163,6 +190,8 @@ const SelectWorkspaceSheet = ({ selectedWorkspace, workspaces, setWorkspace }: S
163190
workspace={workspace}
164191
setWorkspace={setWorkspace}
165192
isOtherWorkspace
193+
isJoining={joiningWorkspace}
194+
onJoinOtherWorkspace={handleJoinOtherWorkspace}
166195
isLast={index === otherWorkspaces.length - 1}
167196
/>
168197
))}
@@ -173,18 +202,45 @@ const SelectWorkspaceSheet = ({ selectedWorkspace, workspaces, setWorkspace }: S
173202
)
174203
}
175204

176-
const WorkspaceRow = ({ workspace, isLast, setWorkspace, isOtherWorkspace = false }: { workspace: Workspace, isLast: boolean, setWorkspace: (workspace: string) => Promise<void>, isOtherWorkspace?: boolean }) => {
205+
type WorkspaceRowProps = {
206+
workspace: Workspace
207+
isLast: boolean
208+
setWorkspace: (workspace: string) => Promise<void>
209+
isOtherWorkspace?: boolean
210+
/** True while this row's join request is in flight */
211+
isJoining?: boolean
212+
onJoinOtherWorkspace?: (workspaceName: string) => void
213+
}
214+
215+
const WorkspaceRow = ({
216+
workspace,
217+
isLast,
218+
setWorkspace,
219+
isOtherWorkspace = false,
220+
isJoining = false,
221+
onJoinOtherWorkspace,
222+
}: WorkspaceRowProps) => {
177223
const { colors } = useColorScheme()
178224

179-
const onClick = () => {
225+
const onPress = () => {
226+
if (isOtherWorkspace && onJoinOtherWorkspace) {
227+
void onJoinOtherWorkspace(workspace.name)
228+
return
229+
}
180230
if (!isOtherWorkspace) {
181-
setWorkspace(workspace.name)
231+
void setWorkspace(workspace.name)
182232
}
183233
}
184234

235+
const disabled = isOtherWorkspace && isJoining
236+
185237
return (
186-
<Pressable className='flex flex-col gap-2' onPress={onClick}>
187-
<View className='flex-row items-center gap-2'>
238+
<Pressable
239+
className='flex flex-col gap-2'
240+
onPress={onPress}
241+
disabled={disabled}
242+
>
243+
<View className={`flex-row items-center gap-2 ${disabled ? 'opacity-60' : ''}`}>
188244
<UserAvatar
189245
alt={workspace.workspace_name}
190246
src={getLogo(workspace)}
@@ -194,11 +250,13 @@ const WorkspaceRow = ({ workspace, isLast, setWorkspace, isOtherWorkspace = fals
194250
<Text className='text-sm font-semibold'>{workspace.workspace_name}</Text>
195251
<Text className='text-sm text-gray-500'>{workspace.type}</Text>
196252
</View>
197-
{workspace.isSelected &&
253+
{isJoining ? (
254+
<ActivityIndicator size="small" color={colors.primary} />
255+
) : workspace.isSelected ? (
198256
<View className='mr-2'>
199257
<CheckFilledIcon fill={colors.primary} height={20} width={20} />
200258
</View>
201-
}
259+
) : null}
202260
</View>
203261
{!isLast && <Divider className='mx-0' />}
204262
</Pressable>
@@ -216,4 +274,4 @@ const getLogo = (workspace: WorkspaceFields) => {
216274
return logo
217275
}
218276

219-
export default WorkspaceSwitcher
277+
export default WorkspaceSwitcher

frontend/package.json

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

frontend/public/sw.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,25 @@ try {
2121
}
2222

2323
onBackgroundMessage(messaging, (payload) => {
24-
const notificationTitle = payload.notification.title
24+
const data = payload.data || {}
25+
const notification = payload.notification || {}
26+
27+
const notificationTitle = data.title || notification.title
2528
let notificationOptions = {
26-
body: payload.notification.body || "",
29+
body: data.body || notification.body || "",
2730
}
28-
if (payload.data.image) {
29-
notificationOptions["icon"] = payload.data.image
31+
32+
if (data.image) {
33+
notificationOptions["icon"] = data.image
3034
}
3135

32-
if (payload.data.creation) {
33-
notificationOptions["timestamp"] = payload.data.creation
36+
if (data.creation) {
37+
notificationOptions["timestamp"] = data.creation
3438
}
35-
let url = `${payload.data.base_url}/raven/channel/${payload.data.channel_id}`
39+
let url = `${data.base_url}/raven/channel/${data.channel_id}`
3640

37-
if (payload.data.message_url) {
38-
url = payload.data.message_url
41+
if (data.message_url) {
42+
url = data.message_url
3943
}
4044

4145
if (isChrome()) {
@@ -68,4 +72,4 @@ try {
6872

6973
self.skipWaiting()
7074
clientsClaim()
71-
console.log("Service Worker Initialized")
75+
console.log("Service Worker Initialized")

frontend/src/components/layout/Sidebar/WorkspacesSidebar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ const WorkspaceItem = ({ workspace }: { workspace: WorkspaceFields & { unread_co
102102
</Tooltip>
103103
</Flex>
104104
{workspace.unread_count > 0 &&
105-
<Box className='rounded-full absolute -right-2 -bottom-1 bg-red-11 dark:bg-red-9 text-white w-4 h-4 flex items-center justify-center'>
106-
<Text as='span' size='1' weight='medium'>{workspace.unread_count}</Text>
105+
<Box className='rounded-lg absolute -right-2 -bottom-1 bg-red-11 dark:bg-red-9 text-white min-w-4 p-0.5 h-4 flex items-center justify-center'>
106+
<Text as='span' size='1' weight='medium'>{workspace.unread_count > 99 ? '99+' : workspace.unread_count}</Text>
107107
</Box>
108108
}
109109
</HStack>

frontend/src/utils/pushNotifications.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,27 @@ export const showNotification = (payload: any) => {
66
const registration = window.frappePushNotification.serviceWorkerRegistration
77
if (!registration) return
88

9-
const notificationTitle = payload?.notification?.title
9+
const data = payload?.data ?? {}
10+
const notification = payload?.notification ?? {}
11+
12+
13+
const notificationTitle = data.title || notification.title
1014
const notificationOptions = {
1115
body: payload?.notification?.body || "",
1216
}
13-
if (payload?.data?.image) {
17+
if (data.image) {
1418
// @ts-ignore
15-
notificationOptions["icon"] = payload.data.image
19+
notificationOptions["icon"] = data.image
1620
}
1721

18-
if (payload.data.creation) {
22+
if (data.creation) {
1923
// @ts-ignore
20-
notificationOptions["timestamp"] = payload.data.creation
24+
notificationOptions["timestamp"] = data.creation
2125
}
22-
let url = `${payload.data.base_url}/raven/channel/${payload.data.channel_id}`
26+
let url = `${data.base_url}/raven/channel/${data.channel_id}`
2327

24-
if (payload.data.message_url) {
25-
url = payload.data.message_url
28+
if (data.message_url) {
29+
url = data.message_url
2630
}
2731

2832
if (isChrome()) {
@@ -31,7 +35,7 @@ export const showNotification = (payload: any) => {
3135
url: url,
3236
}
3337
} else {
34-
if (payload?.data?.click_action) {
38+
if (data.click_action) {
3539
// @ts-ignore
3640
notificationOptions["actions"] = [
3741
{
@@ -43,4 +47,4 @@ export const showNotification = (payload: any) => {
4347
}
4448

4549
registration.showNotification(notificationTitle, notificationOptions)
46-
}
50+
}

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.8.10",
4+
"version": "2.8.11",
55
"description": "Messaging Application",
66
"workspaces": [
77
"frontend",

raven/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "2.8.10"
1+
__version__ = "2.8.11"
22

33
from raven.raven_integrations.doctype.raven_incoming_webhook.raven_incoming_webhook import ( # noqa
44
handle_incoming_webhook as webhook,

raven/api/preview_links.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ def get_preview_link(urls: list[str] | str):
6060
# TODO: We need to replace these special characters with the actual emojis
6161

6262
data = {
63-
"title": preview.title,
64-
"description": preview.description,
65-
"image": preview.image,
66-
"force_title": preview.force_title,
67-
"absolute_image": preview.absolute_image,
68-
"site_name": preview.site_name,
63+
"title": str(preview.title or ""),
64+
"description": str(preview.description or ""),
65+
"image": str(preview.image or ""),
66+
"force_title": str(preview.force_title or ""),
67+
"absolute_image": str(preview.absolute_image or ""),
68+
"site_name": str(preview.site_name or ""),
6969
}
7070
frappe.cache().set_value(url, data)
7171
message_links.append(data)

raven/api/raven_message.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ def save_message(message_id: str, add: str | bool = False):
108108
"""
109109
Save the message as a bookmark
110110
"""
111-
112-
if isinstance(add, str):
113-
add = add.lower() == "yes" or add == "1"
111+
# no need to check if arg add is string, as Yes is being passed, which is what is expected by toggle_like
112+
if isinstance(add, bool):
113+
add = "Yes" if add else "No"
114114

115115
if not frappe.has_permission(doctype="Raven Message", doc=message_id, ptype="read"):
116116
frappe.throw(_("You don't have permission to save this message"), frappe.PermissionError)

0 commit comments

Comments
 (0)