Skip to content

Commit

Permalink
Merge pull request #851 from The-Commit-Company/develop
Browse files Browse the repository at this point in the history
Minor fixes - v1.5.1
  • Loading branch information
nikkothari22 authored Apr 10, 2024
2 parents ebc9d6e + 6e16e94 commit fb3abe6
Show file tree
Hide file tree
Showing 24 changed files with 415 additions and 51 deletions.
3 changes: 2 additions & 1 deletion mobile/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "mobile",
"private": true,
"version": "1.5.0",
"version": "1.5.1",
"type": "module",
"scripts": {
"dev": "vite",
Expand All @@ -21,6 +21,7 @@
"@radix-ui/themes": "^3.0.2",
"@tiptap/extension-code-block-lowlight": "^2.2.3",
"@tiptap/extension-highlight": "^2.2.3",
"@tiptap/extension-image": "^2.2.3",
"@tiptap/extension-link": "^2.2.3",
"@tiptap/extension-mention": "^2.2.3",
"@tiptap/extension-placeholder": "^2.2.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export const ChatInterface = ({ channel }: { channel: ChannelListItem | DMChanne
<IonContent
className='flex flex-col'
onIonScrollStart={() => setIsScrolling(true)}
scrollEvents
onIonScrollEnd={() => setIsScrolling(false)}
fullscreen
ref={conRef}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { memo, useContext, useEffect, useMemo, useState } from 'react'
import { memo, useContext, useEffect, useMemo, useRef, useState } from 'react'
import { FileMessage, ImageMessage, Message, TextMessage, PollMessage } from '../../../../../../types/Messaging/Message'
import { IonIcon, IonSkeletonText, IonText } from '@ionic/react'
import { MarkdownRenderer } from '@/components/common/MarkdownRenderer'
import { UserFields } from '@/utils/users/UserListProvider'
import { DateObjectToFormattedDateStringWithoutYear, DateObjectToTimeString } from '@/utils/operations/operations'
import { ChannelMembersContext } from '../ChatInterface'
Expand All @@ -22,6 +21,7 @@ import { RavenPoll } from '@/types/RavenMessaging/RavenPoll'
import { RavenPollOption } from '@/types/RavenMessaging/RavenPollOption'
import { MdOutlineBarChart } from 'react-icons/md'
import { ViewPollVotes } from '../../polls/ViewPollVotes'
import { TiptapRenderer } from './components/TiptapRenderer/TiptapRenderer'

type Props = {
message: Message,
Expand Down Expand Up @@ -82,8 +82,13 @@ export const NonContinuationMessageBlock = ({ message, onMessageSelect, isScroll
const { user, isActive } = useGetUserDetails(message.is_bot_message && message.bot ? message.bot : message.owner)

const [disableLongPress, setDisableLongPress] = useState(false)

const scrollingRef = useRef<boolean>(isScrolling)

scrollingRef.current = isScrolling

const longPressEvent = useLongPress((e) => {
if (isScrolling) return
if (scrollingRef.current) return
if (disableLongPress) return
Haptics.impact({
style: ImpactStyle.Medium
Expand All @@ -95,7 +100,8 @@ export const NonContinuationMessageBlock = ({ message, onMessageSelect, isScroll
// const color = useMemo(() => generateAvatarColor(user?.full_name ?? userID), [user?.full_name, userID])
return <div>
<div className={clsx('px-2 mt-1 py-1 rounded-md select-none flex active:bg-gray-3 focus:bg-gray-3 focus-visible:bg-gray-3 focus-within:bg-gray-3',
isHighlighted ? 'bg-yellow-300/20 dark:bg-yellow-300/20' : '')} {...longPressEvent}>
isHighlighted ? 'bg-yellow-300/20 dark:bg-yellow-300/20' : '',
isScrolling ? `focus:bg-transparent active:bg-transparent` : '')} {...longPressEvent}>
<MessageSenderAvatar user={user} userID={message.owner} isActive={isActive} />
<div>
<div className='flex items-baseline'>
Expand Down Expand Up @@ -157,8 +163,12 @@ interface ContinuationMessageBlockProps {
const ContinuationMessageBlock = ({ message, onMessageSelect, isScrolling, isHighlighted, onReplyMessageClick }: ContinuationMessageBlockProps) => {

const [disableLongPress, setDisableLongPress] = useState(false)

const scrollingRef = useRef<boolean>(isScrolling)

scrollingRef.current = isScrolling
const longPressEvent = useLongPress((e) => {
if (isScrolling) return
if (scrollingRef.current) return
if (disableLongPress) return
Haptics.impact({
style: ImpactStyle.Medium
Expand All @@ -168,7 +178,8 @@ const ContinuationMessageBlock = ({ message, onMessageSelect, isScrolling, isHig

return <div>
<div className={clsx('px-2 py-1 flex rounded-md select-none active:bg-gray-3 focus:bg-gray-3 focus-visible:bg-gray-3 focus-within:bg-gray-3',
isHighlighted ? 'bg-yellow-300/20 dark:bg-yellow-300/20' : '')} {...longPressEvent}>
isHighlighted ? 'bg-yellow-300/20 dark:bg-yellow-300/20' : '',
isScrolling ? `focus:bg-transparent active:bg-transparent` : '')} {...longPressEvent}>
<div className='w-11'>
</div>
<div>
Expand Down Expand Up @@ -221,10 +232,7 @@ const MessageContent = ({ message, onReplyMessageClick, onLongPressDisabled, onL

const TextMessageBlock = ({ message, truncate = false }: { message: TextMessage, truncate?: boolean }) => {


return <div className={'py-0.5 rounded-lg' + (truncate ? ' line-clamp-3' : '')}>
<MarkdownRenderer content={message.text} truncate={truncate} />
</div>
return <TiptapRenderer message={message} />
}
const options = {
root: null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Blockquote } from '@radix-ui/themes';
import TiptapBlockquote from '@tiptap/extension-blockquote'
import { NodeViewRendererProps, NodeViewWrapper, ReactNodeViewRenderer } from "@tiptap/react";

export const CustomBlockquote = TiptapBlockquote.extend({
addNodeView() {
return ReactNodeViewRenderer(BlockquoteRenderer)
}
})

const BlockquoteRenderer = ({ node }: NodeViewRendererProps) => {
return (
<NodeViewWrapper>
<Blockquote m='2' size='3'>
{node.textContent}
</Blockquote>
</NodeViewWrapper>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import TiptapBold from '@tiptap/extension-bold'
import { mergeAttributes } from "@tiptap/react";

export const CustomBold = TiptapBold.extend({
renderHTML({ HTMLAttributes }) {
return [
"strong",
mergeAttributes(HTMLAttributes, {
class: 'rt-Strong'
}), // mergeAttributes is a exported function from @tiptap/core
0,
];
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// import { Skeleton } from '@/components/common/Skeleton';
// import { Box, Flex, Text } from '@radix-ui/themes';
import TiptapLink from '@tiptap/extension-link'
import { mergeAttributes, useCurrentEditor } from "@tiptap/react";
// import { useFrappeGetCall } from 'frappe-react-sdk';
// import { memo, useMemo } from 'react';

export const CustomLink = TiptapLink.extend({
renderHTML({ HTMLAttributes }) {
return [
"a",
mergeAttributes(HTMLAttributes, {
class: 'rt-Text rt-reset rt-Link rt-underline-auto break-all'
}), // mergeAttributes is a exported function from @tiptap/core
0,
];
},
}).configure({
protocols: ['mailto', 'https', 'http'],
openOnClick: false,
})

export type LinkPreviewDetails = {
title: string,
description: string,
image: string,
force_title: string,
absolute_image: string,
site_name: string
}

// export const LinkPreview = memo(({ isScrolling }: { isScrolling?: boolean }) => {

// const { editor } = useCurrentEditor()

// // We need to find the first mark of type link in a message and extract the href.

// const json = editor?.getJSON()

// const href = useMemo(() => {
// if (!json) return null

// let firstLink = ''

// // At every level of the json, we need to find the first mark of type link and extract the href.
// // Once we find the first link, we can stop searching.
// const findFirstLink = (json: any) => {
// if (firstLink) return firstLink

// if (Array.isArray(json)) {
// for (const item of json) {
// if (typeof item === 'object') {
// findFirstLink(item)
// }
// }
// } else {
// if (json?.type === 'link') {
// const link = json?.attrs?.href
// if (link?.startsWith('mailto')) {
// } else {
// firstLink = json?.attrs?.href
// }
// } else {
// for (const key in json) {
// if (typeof json?.[key] === 'object') {
// findFirstLink(json?.[key])
// }
// }
// }
// }
// }

// findFirstLink(json)

// return firstLink
// }, [json])

// // const href = editor?.getAttributes('link').href


// const { data, isLoading } = useFrappeGetCall<{ message: LinkPreviewDetails[] }>('raven.api.preview_links.get_preview_link', {
// urls: JSON.stringify([href])
// }, href ? undefined : null, {
// revalidateIfStale: false,
// revalidateOnFocus: false,
// revalidateOnReconnect: false,
// shouldRetryOnError: false,
// })

// if (!href) return null

// const linkPreview = data?.message?.[0]

// return <a href={href} target='_blank'>
// <Flex direction='column' gap='2' py='2'>
// {linkPreview ? linkPreview.site_name && linkPreview.description ? <Flex gap='4'>
// {(linkPreview.absolute_image || linkPreview.image) &&
// <Box className='relative min-w-[18rem] min-h-[9rem] w-72 h-36'>
// {/* Absolute positioned skeleton loader */}
// <Box className='absolute top-0 z-0 left-0 w-72 h-36' >
// <Box className='animate-pulse bg-gray-3 z-0 w-72 h-36 dark:bg-gray-5 rounded-md'>

// </Box>
// </Box>

// <img
// width='100%'
// className='absolute object-cover min-w-[18rem] min-h-[9rem] w-72 h-36 rounded-md z-50 top-0 left-0'
// src={linkPreview.absolute_image || linkPreview.image}
// alt={linkPreview.title} />

// </Box>
// }
// <Flex direction='column' gap='1' py='1' className='w-84'>
// <Flex gap='1' direction='column'>
// <Text as='span' weight='bold' size='5' className='cal-sans'>{linkPreview.title}</Text>
// <Text as='span' color='gray' size='2' weight='medium'>{linkPreview.site_name}</Text>
// </Flex>
// <Text as='p' size='2' className='whitespace-break-spaces'>{linkPreview.description}</Text>
// </Flex>
// </Flex> : null :

// null}
// </Flex>
// </a>

// })
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { UserAvatar } from '@/components/common/UserAvatar';
import { useGetUser } from '@/hooks/useGetUser';
import { useIsUserActive } from '@/hooks/useIsUserActive';
import { Flex, HoverCard, Link, Text } from '@radix-ui/themes';
import Mention from '@tiptap/extension-mention'
import { NodeViewRendererProps, NodeViewWrapper, ReactNodeViewRenderer } from "@tiptap/react";
import { BsFillCircleFill } from 'react-icons/bs';
import { Link as RouterLink } from 'react-router-dom';

export const CustomUserMention = Mention.extend({
name: 'userMention',
addNodeView() {
return ReactNodeViewRenderer(UserMentionRenderer)
}
})

export const CustomChannelMention = Mention.extend({
name: 'channelMention',
addNodeView() {
return ReactNodeViewRenderer(ChannelMentionRenderer)
}
})

const UserMentionRenderer = ({ node }: NodeViewRendererProps) => {

const user = useGetUser(node.attrs.id)
const isActive = useIsUserActive(node.attrs.id)

return (
<NodeViewWrapper as={'span'}>
<HoverCard.Root>
<HoverCard.Trigger>
<Link size='2'>
@{user?.full_name ?? node.attrs.label}
</Link>
</HoverCard.Trigger>
<HoverCard.Content>
<Flex gap='2' align='center'>
<UserAvatar src={user?.user_image} alt={user?.full_name ?? node.attrs.label} size='4' />
<Flex direction='column'>
<Flex gap='3' align='center'>
<Text className='text-gray-12' weight='bold' size='3'>{user?.full_name ?? node.attrs.label}</Text>
{isActive && <Flex gap='1' align='center'>
<BsFillCircleFill className='text-green-400' size='8' />
<Text className='text-gray-10' size='1'>Online</Text>
</Flex>}
</Flex>
{user && <Text className='text-gray-11' size='1'>{user?.name}</Text>}
</Flex>
</Flex>

</HoverCard.Content>
</HoverCard.Root>
{/* <Link>
@{node.attrs.label}
</Link> */}
</NodeViewWrapper>
);
};



const ChannelMentionRenderer = ({ node }: NodeViewRendererProps) => {


return (
<NodeViewWrapper as={'span'}>
<Link asChild>
<RouterLink to={`/channels/${node.attrs.id}`}>
@{node.attrs.label}
</RouterLink>
</Link>
</NodeViewWrapper>
);
};
Loading

0 comments on commit fb3abe6

Please sign in to comment.