diff --git a/src/components/BottomDrawer.tsx b/src/components/BottomDrawer.tsx new file mode 100644 index 000000000..00956009e --- /dev/null +++ b/src/components/BottomDrawer.tsx @@ -0,0 +1,56 @@ +import { cx } from '@/utils/class-names' +import { Transition } from '@headlessui/react' +import { createPortal } from 'react-dom' +import { HiXMark } from 'react-icons/hi2' +import Button from './Button' +import { ModalFunctionalityProps, ModalProps } from './modals/Modal' + +export default function BottomDrawer({ + isOpen, + children, + closeModal, + title, + description, +}: ModalFunctionalityProps & + Pick) { + return createPortal( + <> + + + +
+
+ {title} + {description} +
+
{children}
+
+
+ , + document.body + ) +} diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx index ce7e63f73..823d310c9 100644 --- a/src/components/ErrorBoundary.tsx +++ b/src/components/ErrorBoundary.tsx @@ -1,6 +1,5 @@ import { Component } from 'react' -import Card from './Card' -import LinkText from './LinkText' +import Button from './Button' import Logo from './Logo' export default class ErrorBoundary extends Component { @@ -27,16 +26,14 @@ export default class ErrorBoundary extends Component {

Oops, something went wrong 🥲

-

- If you encounter this message inside Iframe, please enable cookies -

- - Go to{' '} - - chrome://settings/cookies - {' '} - and uncheck "Block third-party cookies" option - +
) diff --git a/src/components/chats/ChatForm.tsx b/src/components/chats/ChatForm.tsx index adc65aba6..02339eba0 100644 --- a/src/components/chats/ChatForm.tsx +++ b/src/components/chats/ChatForm.tsx @@ -230,6 +230,19 @@ export default function ChatForm({ return } + const linkRegex = /(https?:\/\/[^\s]+)/g + if (linkRegex.test(messageParams.message ?? '')) { + toast.custom((t) => ( + + )) + return + } + unsentMessageStorage.set(JSON.stringify(messageParams), chatId) hasSentMessageStorage.set('true') diff --git a/src/components/chats/ChatItem/ChatItemMenus.tsx b/src/components/chats/ChatItem/ChatItemMenus.tsx index fb0e11303..52b94d9b3 100644 --- a/src/components/chats/ChatItem/ChatItemMenus.tsx +++ b/src/components/chats/ChatItem/ChatItemMenus.tsx @@ -34,6 +34,7 @@ import { copyToClipboard } from '@/utils/strings' import { Transition } from '@headlessui/react' import { ImageProperties, PostData } from '@subsocial/api/types' import { SocialCallDataArgs } from '@subsocial/data-hub-sdk' +import dayjs from 'dayjs' import { useEffect, useState } from 'react' import { BsFillPinAngleFill } from 'react-icons/bs' import { FaCheck } from 'react-icons/fa6' @@ -126,7 +127,20 @@ export default function ChatItemMenus({ } if (isMessageOwner && !isOptimisticMessage) { menus.unshift(hideMenu) - if ((message?.content?.body.trim().length ?? 0) > 0) + + const approvedTime = message?.struct.approvedInRootPostAtTime + const createdTime = message?.struct.createdAtTime + const isApproved = message?.struct.approvedInRootPost + + const isAutoApproved = isApproved && approvedTime === createdTime + const isAfter5MinsOfCreation = + dayjs(createdTime).diff(dayjs(), 'minute') < 5 + + if ( + (message?.content?.body.trim().length ?? 0) > 0 && + ((!isAutoApproved && isAfter5MinsOfCreation && !isApproved) || + (isAutoApproved && isAfter5MinsOfCreation)) + ) menus.unshift(editItem) } diff --git a/src/components/chats/ChatList/ChatList.tsx b/src/components/chats/ChatList/ChatList.tsx index ea1bab474..f8cefd7f5 100644 --- a/src/components/chats/ChatList/ChatList.tsx +++ b/src/components/chats/ChatList/ChatList.tsx @@ -177,7 +177,7 @@ function ChatListContent({ sendEvent('load_more_messages', { currentPage }) }} className={cx( - 'relative flex w-full flex-col-reverse !overflow-hidden pb-2', + 'relative flex w-full flex-col-reverse !overflow-hidden', // need to have enough room to open message menu 'min-h-[400px]' )} diff --git a/src/components/chats/ChatRoom/ChatRoom.tsx b/src/components/chats/ChatRoom/ChatRoom.tsx index 064a3ab6f..d6a817a3d 100644 --- a/src/components/chats/ChatRoom/ChatRoom.tsx +++ b/src/components/chats/ChatRoom/ChatRoom.tsx @@ -104,7 +104,7 @@ function ChatInputWrapper({ return ( <> - +
{/* - ( ), }} - > - {body} - + > */} + {body} + {/* */} {!isMyMessage && othersMessage.checkMark === 'bottom' && ( {otherMessageCheckMarkElement()} diff --git a/src/components/extensions/common/CommonExtensionModal.tsx b/src/components/extensions/common/CommonExtensionModal.tsx index 3a63e7b81..397b201bd 100644 --- a/src/components/extensions/common/CommonExtensionModal.tsx +++ b/src/components/extensions/common/CommonExtensionModal.tsx @@ -1,5 +1,6 @@ +import BottomDrawer from '@/components/BottomDrawer' import ChatForm, { ChatFormProps } from '@/components/chats/ChatForm' -import Modal, { ModalProps } from '@/components/modals/Modal' +import { ModalProps } from '@/components/modals/Modal' import { sendEventWithRef } from '@/components/referral/analytics' import { SendMessageParams } from '@/services/subsocial/commentIds/types' import { useSendEvent } from '@/stores/analytics' @@ -7,6 +8,8 @@ import { useMessageData } from '@/stores/message' import { useMyMainAddress } from '@/stores/my-account' import { cx } from '@/utils/class-names' import { PostContentExtension } from '@subsocial/api/types' +import { useViewportRaw } from '@tma.js/sdk-react' +import { usePrevious } from '@uidotdev/usehooks' import { useEffect } from 'react' export type BeforeMessageResult = { @@ -58,20 +61,17 @@ export default function CommonExtensionModal({ setShowEmptyPrimaryChatInput(props.isOpen) }, [props.isOpen, setShowEmptyPrimaryChatInput]) - const commonClassName = cx('px-5 md:px-6') + const viewport = useViewportRaw(true) + const viewportHeight = viewport?.result?.stableHeight + const prevHeight = usePrevious(viewportHeight) + const offset = Math.max(0, (prevHeight ?? 0) - (viewportHeight ?? 0)) const isUsingBigButton = !!sendButtonText return ( - +
@@ -89,13 +89,12 @@ export default function CommonExtensionModal({ className='pb-1 pt-0.5' inputProps={{ className: cx( - 'rounded-none bg-transparent pl-4 md:pl-5 py-4 pr-20 !ring-0', + 'rounded-none bg-transparent py-4 pl-2 pr-20 !ring-0', !isUsingBigButton && 'rounded-b-2xl' ), }} sendButtonProps={{ disabled: disableSendButton, - className: cx(!isUsingBigButton ? 'mr-4' : 'mx-5 md:px-6'), }} buildAdditionalTxParams={buildAdditionalTxParams} onSubmit={() => { @@ -114,6 +113,8 @@ export default function CommonExtensionModal({ }} /> )} - + {/* blank space offset so the input got pushed up, because in telegram apps, virtual keyboard doesn't push the content up when opened */} +
+ ) } diff --git a/src/components/extensions/image/ImageModal.tsx b/src/components/extensions/image/ImageModal.tsx index a6a66ad54..869ef069f 100644 --- a/src/components/extensions/image/ImageModal.tsx +++ b/src/components/extensions/image/ImageModal.tsx @@ -59,6 +59,17 @@ export default function ImageModal({ loadedLink: null, }) + useEffect(() => { + setImageLinkStatus({ + isShowingImage: false, + loadedLink: null, + }) + setImageUploadStatus({ + isShowingImage: false, + loadedLink: null, + }) + }, [isOpen]) + const isImageLoaded = imageLinkStatus.loadedLink || imageUploadStatus.loadedLink @@ -252,7 +263,7 @@ function ImageUpload({ if (currentLoadedImage.current === imageUrl) { setUploadedImageLink((prev) => ({ ...prev, isShowingImage })) } else { - setUploadedImageLink({ isShowingImage, loadedLink: null }) + setUploadedImageLink({ isShowingImage: false, loadedLink: null }) } }, [setUploadedImageLink, imageUrl, isLoading, isError]) diff --git a/src/components/modals/RewardPerDayModal.tsx b/src/components/modals/RewardPerDayModal.tsx index 7ab24cd94..cd5761a2e 100644 --- a/src/components/modals/RewardPerDayModal.tsx +++ b/src/components/modals/RewardPerDayModal.tsx @@ -31,10 +31,11 @@ export default function RewardPerDayModal({ const stakerReward = Number(data?.earned.staker ?? '0') const creatorReward = Number(data?.earned.creator ?? '0') - const twitterShareText = `💰 Turn your love of memes into rewards! -Epic lets you earn tokens simply by liking and posting memes. + const twitterShareText = `💰 Turn your love of memes into rewards! +@EpicAppNet lets you earn tokens simply by liking and posting memes. -Sounds too good to be true? Join me and see for yourself! 😉` +Sounds too good to be true? Join me and see for yourself! 😉 +` useHotkeys('esc', close) diff --git a/src/hooks/useTgNoScroll.ts b/src/hooks/useTgNoScroll.ts index 1674741bc..8011a7a53 100644 --- a/src/hooks/useTgNoScroll.ts +++ b/src/hooks/useTgNoScroll.ts @@ -1,7 +1,9 @@ +import { useViewportRaw } from '@tma.js/sdk-react' import { useEffect } from 'react' // Solution from https://github.com/deptyped/vue-telegram/issues/11#issuecomment-1999265843 export default function useTgNoScroll() { + const viewport = useViewportRaw(true) useEffect(() => { const overflow = 750 document.body.style.overflow = 'hidden' @@ -16,5 +18,5 @@ export default function useTgNoScroll() { document.body.style.height = 'auto' document.body.style.paddingBottom = '0' } - }, []) + }, [viewport?.result?.stableHeight]) } diff --git a/src/modules/telegram/TasksPage/index.tsx b/src/modules/telegram/TasksPage/index.tsx index 5c94dde9a..cc613726e 100644 --- a/src/modules/telegram/TasksPage/index.tsx +++ b/src/modules/telegram/TasksPage/index.tsx @@ -199,7 +199,9 @@ function BasicTasks() { {data.map((task, index) => { const tag = task.tag as Exclude - const { image, title, event } = modalConfigByVariant[tag] + const variant = modalConfigByVariant[tag] + if (!variant) return null + const { image, title, event } = variant || {} return (