From 724a77bf072994219aa4bc74cc6b1ffebe2ac36b Mon Sep 17 00:00:00 2001 From: Stef Coenen Date: Wed, 22 Jan 2025 14:06:19 +0100 Subject: [PATCH] Added compatibility for new transfer history while keeping current state support; --- .../src/hooks/auth/useDotYouClientContext.ts | 6 +- .../Chat/Chat-Delivery-Indicator.tsx | 15 +- .../Chat/Reactions/Modal/ReportModal.tsx | 13 +- .../Chat/Reactions/Modal/RetryModal.tsx | 28 ++- .../Feed/Interacts/PostInteracts.tsx | 8 +- .../src/components/Feed/Meta/Actions.tsx | 10 +- .../src/components/ui/Media/BoringFile.tsx | 4 - packages/mobile/src/hooks/auth/useAuth.ts | 1 + .../hooks/chat/getSynchronousDotYouClient.ts | 1 + .../src/hooks/chat/useLiveChatProcessor.ts | 21 +- .../src/hooks/feed/useManageSocialFeed.ts | 4 +- .../src/hooks/file/useTransferHistory.ts | 29 +++ packages/mobile/src/pages/chat/chat-page.tsx | 45 +++-- .../src/pages/chat/message-info-page.tsx | 42 +++- .../mobile/src/provider/chat/ChatProvider.ts | 180 +++++++++++------- .../provider/feed/RNPostReactionProvider.ts | 10 +- .../src/provider/feed/RNPostUploadProvider.ts | 34 ++-- 17 files changed, 305 insertions(+), 146 deletions(-) create mode 100644 packages/mobile/src/hooks/file/useTransferHistory.ts diff --git a/packages/common/src/hooks/auth/useDotYouClientContext.ts b/packages/common/src/hooks/auth/useDotYouClientContext.ts index 52598948..01ddc199 100644 --- a/packages/common/src/hooks/auth/useDotYouClientContext.ts +++ b/packages/common/src/hooks/auth/useDotYouClientContext.ts @@ -1,9 +1,7 @@ -import { ApiType, DotYouClient } from '@homebase-id/js-lib/core'; +import { DotYouClient } from '@homebase-id/js-lib/core'; import { useContext, createContext } from 'react'; -export const DotYouClientContext = createContext( - new DotYouClient({ api: ApiType.Guest }) -); +export const DotYouClientContext = createContext(null); export const useDotYouClientContext = () => { const dotYouClient = useContext(DotYouClientContext); diff --git a/packages/mobile/src/components/Chat/Chat-Delivery-Indicator.tsx b/packages/mobile/src/components/Chat/Chat-Delivery-Indicator.tsx index 26d92982..96f4d16e 100644 --- a/packages/mobile/src/components/Chat/Chat-Delivery-Indicator.tsx +++ b/packages/mobile/src/components/Chat/Chat-Delivery-Indicator.tsx @@ -1,4 +1,4 @@ -import { HomebaseFile } from '@homebase-id/js-lib/core'; +import { HomebaseFile, RecipientTransferHistory } from '@homebase-id/js-lib/core'; import { ChatDeliveryStatus, ChatMessage } from '../../provider/chat/ChatProvider'; import { t, useDotYouClientContext } from 'homebase-id-app-common'; import { Pressable, StyleProp, Text, TextStyle, View, ViewStyle } from 'react-native'; @@ -32,17 +32,14 @@ export const ChatDeliveryIndicator = ({ }; export const FailedDeliveryDetails = ({ - msg, - recipient, + transferHistory, style, }: { - msg: HomebaseFile; - recipient: string; + transferHistory: RecipientTransferHistory | undefined; style?: StyleProp; }) => { - const deliveryDetails = msg.serverMetadata?.transferHistory?.recipients[recipient]; - if (!deliveryDetails) return null; - if (deliveryDetails.latestSuccessfullyDeliveredVersionTag) return null; + if (!transferHistory) return null; + if (transferHistory.latestSuccessfullyDeliveredVersionTag) return null; return ( - {t(deliveryDetails.latestTransferStatus)} + {t(transferHistory.latestTransferStatus)} ); }; diff --git a/packages/mobile/src/components/Chat/Reactions/Modal/ReportModal.tsx b/packages/mobile/src/components/Chat/Reactions/Modal/ReportModal.tsx index 57846279..52173b62 100644 --- a/packages/mobile/src/components/Chat/Reactions/Modal/ReportModal.tsx +++ b/packages/mobile/src/components/Chat/Reactions/Modal/ReportModal.tsx @@ -35,11 +35,14 @@ export const ReportModal = forwardRef( ); }; const identity = useAuth().getIdentity(); - const host = new DotYouClient({ - api: ApiType.Guest, - loggedInIdentity: identity || undefined, - hostIdentity: identity || undefined, - }).getRoot(); + const host = + (identity && + new DotYouClient({ + api: ApiType.Guest, + loggedInIdentity: identity, + hostIdentity: identity, + }).getRoot()) || + ''; const onBlock = () => openURL(`${host}/owner/connections/${message?.fileMetadata.originalAuthor}/block`); diff --git a/packages/mobile/src/components/Chat/Reactions/Modal/RetryModal.tsx b/packages/mobile/src/components/Chat/Reactions/Modal/RetryModal.tsx index a7876185..5223be6d 100644 --- a/packages/mobile/src/components/Chat/Reactions/Modal/RetryModal.tsx +++ b/packages/mobile/src/components/Chat/Reactions/Modal/RetryModal.tsx @@ -12,11 +12,13 @@ import { Container } from '../../../ui/Container/Container'; import { StyleSheet } from 'react-native'; import { TouchableHighlight } from 'react-native-gesture-handler'; import { useChatMessage } from '../../../../hooks/chat/useChatMessage'; -import { HomebaseFile } from '@homebase-id/js-lib/core'; +import { HomebaseFile, RecipientTransferHistory } from '@homebase-id/js-lib/core'; import { ChatMessage } from '../../../../provider/chat/ChatProvider'; -import { UnifiedConversation } from '../../../../provider/chat/ConversationProvider'; +import { ChatDrive, UnifiedConversation } from '../../../../provider/chat/ConversationProvider'; import { ErrorNotification } from '../../../ui/Alert/ErrorNotification'; import { Backdrop } from '../../../ui/Modal/Backdrop'; +import { useTransferHistory } from '../../../../hooks/file/useTransferHistory'; + export const RetryModal = forwardRef( ( { @@ -32,7 +34,26 @@ export const RetryModal = forwardRef( ) => { const { isDarkMode } = useDarkMode(); const { mutate, error } = useChatMessage().update; - const recipients = message?.serverMetadata?.transferHistory?.recipients; + const { data: transferHistory } = useTransferHistory( + message && { + fileId: message?.fileId, + targetDrive: ChatDrive, + } + ).fetch; + + const recipients = + (message?.serverMetadata?.transferHistory && + 'recipients' in message.serverMetadata.transferHistory && + (message.serverMetadata.transferHistory as unknown as { + [key: string]: RecipientTransferHistory; + })) || + transferHistory?.history.results.reduce( + (acc, curr) => { + acc[curr.recipient] = curr; + return acc; + }, + {} as Record + ); const onRetry = useCallback(() => { if (!message) return; @@ -69,6 +90,7 @@ export const RetryModal = forwardRef( return recipients[failedRecipient[0]].latestTransferStatus; } }, [failedRecipient, recipients]); + return ( - `${new DotYouClient({ hostIdentity: odinId || undefined, api: ApiType.Guest }).getRoot()}/posts/${postContent.channelId}/${ - postContent.slug ?? postContent.id - }`, + odinId + ? `${new DotYouClient({ hostIdentity: odinId, api: ApiType.Guest }).getRoot()}/posts/${postContent.channelId}/${ + postContent.slug ?? postContent.id + }` + : '', [odinId, postContent] ); diff --git a/packages/mobile/src/components/Feed/Meta/Actions.tsx b/packages/mobile/src/components/Feed/Meta/Actions.tsx index 68eaa259..2711e969 100644 --- a/packages/mobile/src/components/Feed/Meta/Actions.tsx +++ b/packages/mobile/src/components/Feed/Meta/Actions.tsx @@ -42,10 +42,12 @@ export const ExternalActions = memo( getReportContentUrl, } = useManageSocialFeed({ odinId }); - const host = new DotYouClient({ - api: ApiType.Guest, - loggedInIdentity: identity || undefined, - }).getRoot(); + const host = identity + ? new DotYouClient({ + api: ApiType.Guest, + hostIdentity: identity, + }).getRoot() + : ''; const options: ActionGroupProps[] = [ { icon: , diff --git a/packages/mobile/src/components/ui/Media/BoringFile.tsx b/packages/mobile/src/components/ui/Media/BoringFile.tsx index 397b8542..30001458 100644 --- a/packages/mobile/src/components/ui/Media/BoringFile.tsx +++ b/packages/mobile/src/components/ui/Media/BoringFile.tsx @@ -31,10 +31,6 @@ export const BoringFile = memo( const isPending = 'pendingFile' in file; - const progressPercentage = Math.round( - ((file as NewPayloadDescriptor)?.uploadProgress?.progress || 0) * 100 - ); - const openDocument = useCallback( async (payload?: OdinBlob) => { if (!blob && !payload) { diff --git a/packages/mobile/src/hooks/auth/useAuth.ts b/packages/mobile/src/hooks/auth/useAuth.ts index b8052c12..79700f45 100644 --- a/packages/mobile/src/hooks/auth/useAuth.ts +++ b/packages/mobile/src/hooks/auth/useAuth.ts @@ -170,6 +170,7 @@ export const useAuth = () => { if (!sharedSecret || !identity || !authToken) { return new DotYouClient({ api: ApiType.App, + hostIdentity: '', }); } diff --git a/packages/mobile/src/hooks/chat/getSynchronousDotYouClient.ts b/packages/mobile/src/hooks/chat/getSynchronousDotYouClient.ts index daaf08fe..0d6267ad 100644 --- a/packages/mobile/src/hooks/chat/getSynchronousDotYouClient.ts +++ b/packages/mobile/src/hooks/chat/getSynchronousDotYouClient.ts @@ -22,6 +22,7 @@ export const getSynchronousDotYouClient = async () => { if (!sharedSecret || !identity) { return new DotYouClient({ api: ApiType.App, + hostIdentity: '', }); } diff --git a/packages/mobile/src/hooks/chat/useLiveChatProcessor.ts b/packages/mobile/src/hooks/chat/useLiveChatProcessor.ts index 44bcfd19..e625d588 100644 --- a/packages/mobile/src/hooks/chat/useLiveChatProcessor.ts +++ b/packages/mobile/src/hooks/chat/useLiveChatProcessor.ts @@ -311,9 +311,14 @@ const useChatWebsocket = (isEnabled: boolean) => { fileMetadata: { ...m.fileMetadata, updated: - Object.values(m.serverMetadata?.transferHistory?.recipients || []).reduce((acc, cur) => { - return Math.max(acc, cur.lastUpdated || 0); - }, 0) || + (m.serverMetadata?.transferHistory && + 'recipients' in m.serverMetadata.transferHistory && + Object.values(m.serverMetadata?.transferHistory?.recipients || []).reduce( + (acc, cur) => { + return Math.max(acc, cur.lastUpdated || 0); + }, + 0 + )) || m.fileMetadata.updated || 0, }, @@ -433,11 +438,11 @@ const processChatMessagesBatch = async ( uniqueMessagesPerConversation[conversationId].map(async (newMessage) => typeof newMessage.fileMetadata.appData.content === 'string' ? await dsrToMessage( - dotYouClient, - newMessage as HomebaseFile, - ChatDrive, - true - ) + dotYouClient, + newMessage as HomebaseFile, + ChatDrive, + true + ) : (newMessage as HomebaseFile) ) ) diff --git a/packages/mobile/src/hooks/feed/useManageSocialFeed.ts b/packages/mobile/src/hooks/feed/useManageSocialFeed.ts index f8dacba7..2ba1af07 100644 --- a/packages/mobile/src/hooks/feed/useManageSocialFeed.ts +++ b/packages/mobile/src/hooks/feed/useManageSocialFeed.ts @@ -23,7 +23,9 @@ export const useManageSocialFeed = (props?: { odinId: string }) => { }; const getContentReportUrl = () => { - const host = new DotYouClient({ hostIdentity: odinId, api: ApiType.Guest }).getRoot(); + const host = odinId + ? new DotYouClient({ hostIdentity: odinId, api: ApiType.Guest }).getRoot() + : ''; // Fetch the reporting url from the other identities config return fetch(`${host}/config/reporting`) diff --git a/packages/mobile/src/hooks/file/useTransferHistory.ts b/packages/mobile/src/hooks/file/useTransferHistory.ts new file mode 100644 index 00000000..3ee6a241 --- /dev/null +++ b/packages/mobile/src/hooks/file/useTransferHistory.ts @@ -0,0 +1,29 @@ +import { getTransferHistory, SystemFileType, TargetDrive } from '@homebase-id/js-lib/core'; +import { useQuery } from '@tanstack/react-query'; +import { useDotYouClientContext } from 'homebase-id-app-common'; + +export const useTransferHistory = (props?: { + fileId: string; + targetDrive: TargetDrive; + systemFileType?: SystemFileType; +}) => { + const { fileId, targetDrive, systemFileType } = props || {}; + + const dotYouClient = useDotYouClientContext(); + + const fetchTransferHistory = async () => { + if (!fileId || !targetDrive) return null; + + return getTransferHistory(dotYouClient, targetDrive, fileId, { + systemFileType, + }); + }; + + return { + fetch: useQuery({ + queryFn: fetchTransferHistory, + queryKey: ['transferHistory', targetDrive?.alias, fileId], + enabled: !!props, + }), + }; +}; diff --git a/packages/mobile/src/pages/chat/chat-page.tsx b/packages/mobile/src/pages/chat/chat-page.tsx index d62ada0b..531b7e73 100644 --- a/packages/mobile/src/pages/chat/chat-page.tsx +++ b/packages/mobile/src/pages/chat/chat-page.tsx @@ -4,6 +4,7 @@ import { DotYouClient, FailedTransferStatuses, HomebaseFile, + RecipientTransferHistory, RichText, } from '@homebase-id/js-lib/core'; import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; @@ -281,14 +282,34 @@ const ChatPage = memo(({ route, navigation }: ChatProp) => { (recipient) => recipient !== identity ); - const anyRecipientMissingConversation = filteredRecipients.some((recipient) => { - const latestTransferStatus = - conversation.serverMetadata?.transferHistory?.recipients[recipient] - ?.latestTransferStatus; + const anyRecipientMissingConversation = (() => { + if ( + conversation.serverMetadata?.transferHistory && + 'recipients' in conversation.serverMetadata.transferHistory + ) { + return filteredRecipients.some((recipient) => { + const latestTransferStatus = ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + conversation.serverMetadata as any as { + transferHistory: { + recipients: { + [key: string]: RecipientTransferHistory; + }; + }; + } + ).transferHistory.recipients[recipient]?.latestTransferStatus; + + if (!latestTransferStatus) return true; + return FailedTransferStatuses.includes(latestTransferStatus); + }); + } + + return ( + conversation.serverMetadata?.originalRecipientCount !== + conversation.serverMetadata?.transferHistory?.summary.totalDelivered + ); + })(); - if (!latestTransferStatus) return true; - return FailedTransferStatuses.includes(latestTransferStatus); - }); if (anyRecipientMissingConversation) { console.log('invite recipient'); inviteRecipient({ conversation }); @@ -495,10 +516,12 @@ const ChatPage = memo(({ route, navigation }: ChatProp) => { const [isOpen, setIsOpen] = useState(false); const { isDarkMode } = useDarkMode(); - const host = new DotYouClient({ - api: ApiType.Guest, - loggedInIdentity: identity || undefined, - }).getRoot(); + const host = identity + ? new DotYouClient({ + api: ApiType.Guest, + hostIdentity: identity, + }).getRoot() + : ''; const chatOptions: { label: string; onPress: () => void; diff --git a/packages/mobile/src/pages/chat/message-info-page.tsx b/packages/mobile/src/pages/chat/message-info-page.tsx index cda3b4dc..4d35af2e 100644 --- a/packages/mobile/src/pages/chat/message-info-page.tsx +++ b/packages/mobile/src/pages/chat/message-info-page.tsx @@ -12,8 +12,13 @@ import { useDotYouClientContext } from 'homebase-id-app-common'; import { ChatStackParamList } from '../../app/ChatStack'; import { Avatar, OwnerAvatar } from '../../components/ui/Avatars/Avatar'; import { SafeAreaView } from '../../components/ui/SafeAreaView/SafeAreaView'; -import { EmojiReaction } from '@homebase-id/js-lib/core'; -import { ChatDeliveryStatus } from '../../provider/chat/ChatProvider'; +import { EmojiReaction, RecipientTransferHistory } from '@homebase-id/js-lib/core'; +import { + ChatDeliveryStatus, + transferHistoryToChatDeliveryStatus, +} from '../../provider/chat/ChatProvider'; +import { useTransferHistory } from '../../hooks/file/useTransferHistory'; +import { ChatDrive } from '../../provider/chat/ConversationProvider'; export type MessageInfoProp = NativeStackScreenProps; @@ -27,7 +32,6 @@ const dateTimeFormat: Intl.DateTimeFormatOptions = { export const MessageInfoPage = ({ route }: MessageInfoProp) => { const { message, conversation } = route.params; - const messageContent = message.fileMetadata.appData.content; const identity = useDotYouClientContext().getLoggedInIdentity(); const conversationContent = conversation.fileMetadata.appData.content; @@ -43,6 +47,13 @@ export const MessageInfoPage = ({ route }: MessageInfoProp) => { messageGlobalTransitId: message.fileMetadata.globalTransitId, }).get; + const { data: transferHistory } = useTransferHistory( + message && { + fileId: message?.fileId, + targetDrive: ChatDrive, + } + ).fetch; + function renderDetails() { return ( @@ -75,10 +86,28 @@ export const MessageInfoPage = ({ route }: MessageInfoProp) => { } function renderRecipients() { if (!recipients.length) return null; + + const recipientTransferHistory = + (message?.serverMetadata?.transferHistory && + 'recipients' in message.serverMetadata.transferHistory && + (message.serverMetadata.transferHistory.recipients as unknown as { + [key: string]: RecipientTransferHistory; + })) || + transferHistory?.history.results.reduce( + (acc, curr) => { + acc[curr.recipient] = curr; + return acc; + }, + {} as Record + ); + return (
{recipients.map((recipient) => { + const deliveryStatus = transferHistoryToChatDeliveryStatus( + recipientTransferHistory?.[recipient] + ); return ( { - {isAuthor ? ( + {isAuthor && recipientTransferHistory ? ( ) : null} @@ -107,7 +135,7 @@ export const MessageInfoPage = ({ route }: MessageInfoProp) => { {isAuthor ? ( diff --git a/packages/mobile/src/provider/chat/ChatProvider.ts b/packages/mobile/src/provider/chat/ChatProvider.ts index 0573f09d..657a733f 100644 --- a/packages/mobile/src/provider/chat/ChatProvider.ts +++ b/packages/mobile/src/provider/chat/ChatProvider.ts @@ -36,13 +36,15 @@ import { getFileHeader, DEFAULT_PAYLOAD_KEY, UpdateHeaderInstructionSet, + RecipientTransferSummary, } from '@homebase-id/js-lib/core'; -import { ChatDrive, UnifiedConversation } from './ConversationProvider'; +import { ChatDrive, ConversationWithYourselfId, UnifiedConversation } from './ConversationProvider'; import { assertIfDefined, getNewId, getRandom16ByteArray, jsonStringify64, + stringGuidsEqual, stringToUint8Array, tryJsonParse, } from '@homebase-id/js-lib/helpers'; @@ -89,7 +91,6 @@ export interface ChatMessage { /// DeliveryStatus of the message. Indicates if the message is sent, delivered or read deliveryStatus: ChatDeliveryStatus; - deliveryDetails?: Record; } const CHAT_MESSAGE_PAYLOAD_KEY = 'chat_mbl'; @@ -174,14 +175,31 @@ export const dsrToMessage = async ( if (!msgContent) return null; if ( - (msgContent.deliveryStatus === ChatDeliveryStatus.Sent || - msgContent.deliveryStatus === ChatDeliveryStatus.Failed) && - dsr.serverMetadata?.transferHistory?.recipients + msgContent.deliveryStatus === ChatDeliveryStatus.Sent || + msgContent.deliveryStatus === ChatDeliveryStatus.Failed ) { - msgContent.deliveryDetails = buildDeliveryDetails( - dsr.serverMetadata.transferHistory.recipients - ); - msgContent.deliveryStatus = buildDeliveryStatus(msgContent.deliveryDetails); + if ( + dsr.serverMetadata?.transferHistory && + 'recipients' in dsr.serverMetadata.transferHistory + ) { + msgContent.deliveryStatus = buildDeliveryStatusBasedOnDeprecatedDeliveryDetails( + buildDeprecatedDeliveryDetails( + dsr.serverMetadata.transferHistory.recipients as { + [key: string]: RecipientTransferHistory; + } + ) + ); + } else if (dsr.serverMetadata?.transferHistory?.summary) { + msgContent.deliveryStatus = stringGuidsEqual( + dsr.fileMetadata.appData.groupId, + ConversationWithYourselfId + ) + ? ChatDeliveryStatus.Read + : buildDeliveryStatus( + dsr.serverMetadata.originalRecipientCount, + dsr.serverMetadata.transferHistory.summary + ); + } } const chatMessage: HomebaseFile = { @@ -204,7 +222,10 @@ export const dsrToMessage = async ( } }; -const buildDeliveryDetails = (recipientTransferHistory: { +/** + * @deprecated Use buildDeliveryStatus instead + */ +const buildDeprecatedDeliveryDetails = (recipientTransferHistory: { [key: string]: RecipientTransferHistory; }): Record => { const deliveryDetails: Record = {}; @@ -233,7 +254,10 @@ const buildDeliveryDetails = (recipientTransferHistory: { return deliveryDetails; }; -const buildDeliveryStatus = ( +/** + * @deprecated Use buildDeliveryStatus instead + */ +const buildDeliveryStatusBasedOnDeprecatedDeliveryDetails = ( deliveryDetails: Record ): ChatDeliveryStatus => { const values = Object.values(deliveryDetails); @@ -251,6 +275,42 @@ const buildDeliveryStatus = ( return ChatDeliveryStatus.Sent; }; +export const transferHistoryToChatDeliveryStatus = ( + transferHistory: RecipientTransferHistory | undefined +): ChatDeliveryStatus => { + if (!transferHistory) return ChatDeliveryStatus.Failed; + + if (transferHistory.latestSuccessfullyDeliveredVersionTag) { + if (transferHistory.isReadByRecipient) { + return ChatDeliveryStatus.Read; + } else { + return ChatDeliveryStatus.Delivered; + } + } + + const latest = transferHistory.latestTransferStatus; + const transferStatus = + latest && typeof latest === 'string' + ? (latest?.toLocaleLowerCase() as TransferStatus) + : undefined; + if (transferStatus && FailedTransferStatuses.includes(transferStatus)) { + return ChatDeliveryStatus.Failed; + } + return ChatDeliveryStatus.Sent; +}; + +export const buildDeliveryStatus = ( + recipientCount: number | undefined, + transferSummary: RecipientTransferSummary +): ChatDeliveryStatus => { + if (transferSummary.totalFailed > 0) return ChatDeliveryStatus.Failed; + + if (transferSummary.totalReadByRecipient >= (recipientCount || 0)) return ChatDeliveryStatus.Read; + if (transferSummary.totalDelivered >= (recipientCount || 0)) return ChatDeliveryStatus.Delivered; + + return ChatDeliveryStatus.Sent; +}; + export const uploadChatMessage = async ( dotYouClient: DotYouClient, message: NewHomebaseFile, @@ -271,19 +331,19 @@ export const uploadChatMessage = async ( }, transitOptions: distribute ? { - recipients: [...recipients], - schedule: ScheduleOptions.SendLater, - priority: PriorityOptions.High, - sendContents: SendContents.All, - useAppNotification: true, - appNotificationOptions: { - appId: CHAT_APP_ID, - typeId: message.fileMetadata.appData.groupId || getNewId(), - tagId: message.fileMetadata.appData.uniqueId || getNewId(), - silent: false, - unEncryptedMessage: notificationBody, - }, - } + recipients: [...recipients], + schedule: ScheduleOptions.SendLater, + priority: PriorityOptions.High, + sendContents: SendContents.All, + useAppNotification: true, + appNotificationOptions: { + appId: CHAT_APP_ID, + typeId: message.fileMetadata.appData.groupId || getNewId(), + tagId: message.fileMetadata.appData.uniqueId || getNewId(), + silent: false, + unEncryptedMessage: notificationBody, + }, + } : undefined, }; @@ -300,11 +360,10 @@ export const uploadChatMessage = async ( const content = shouldEmbedContent ? jsonContent : jsonStringify64({ - message: ellipsisAtMaxChar(getPlainTextFromRichText(messageContent.message), 400), - replyId: messageContent.replyId, - deliveryDetails: messageContent.deliveryDetails, - deliveryStatus: messageContent.deliveryStatus, - }); // We only embed the content if it's less than 3kb + message: ellipsisAtMaxChar(getPlainTextFromRichText(messageContent.message), 400), + replyId: messageContent.replyId, + deliveryStatus: messageContent.deliveryStatus, + }); // We only embed the content if it's less than 3kb if (!shouldEmbedContent) { payloads.push({ @@ -346,10 +405,10 @@ export const uploadChatMessage = async ( const imageSource: ImageSource | undefined = linkPreviewWithImage ? { - height: linkPreviewWithImage.imageHeight || 0, - width: linkPreviewWithImage.imageWidth || 0, - uri: linkPreviewWithImage.imageUrl, - } + height: linkPreviewWithImage.imageHeight || 0, + width: linkPreviewWithImage.imageWidth || 0, + uri: linkPreviewWithImage.imageUrl, + } : undefined; const { tinyThumb } = imageSource @@ -461,23 +520,13 @@ export const uploadChatMessage = async ( } if ( - recipients.some( - (recipient) => - uploadResult.recipientStatus?.[recipient].toLowerCase() === - TransferUploadStatus.EnqueuedFailed + Object.values(uploadResult.recipientStatus).some( + (recipienStatus) => recipienStatus.toLowerCase() === TransferUploadStatus.EnqueuedFailed ) ) { message.fileId = uploadResult.file.fileId; message.fileMetadata.versionTag = uploadResult.newVersionTag; - message.fileMetadata.appData.content.deliveryStatus = ChatDeliveryStatus.Sent; - message.fileMetadata.appData.content.deliveryDetails = {}; - for (const recipient of recipients) { - message.fileMetadata.appData.content.deliveryDetails[recipient] = - uploadResult.recipientStatus?.[recipient].toLowerCase() === - TransferUploadStatus.EnqueuedFailed - ? ChatDeliveryStatus.Failed - : ChatDeliveryStatus.Delivered; - } + message.fileMetadata.appData.content.deliveryStatus = ChatDeliveryStatus.Failed; const updateResult = await updateChatMessage( dotYouClient, @@ -491,7 +540,7 @@ export const uploadChatMessage = async ( ...uploadResult, newVersionTag: updateResult?.newVersionTag || uploadResult?.newVersionTag, previewThumbnail: uploadMetadata.appData.previewThumbnail, - chatDeliveryStatus: ChatDeliveryStatus.Sent, // Should we set failed, or does an enqueueFailed have a retry? (Either way it should auto-solve if it does) + chatDeliveryStatus: ChatDeliveryStatus.Failed, // Should we set failed, or does an enqueueFailed have a retry? (Either way it should auto-solve if it does) }; } @@ -518,11 +567,11 @@ export const updateChatMessage = async ( }, transitOptions: distribute ? { - recipients: [...recipients], - schedule: ScheduleOptions.SendLater, - priority: PriorityOptions.High, - sendContents: SendContents.All, - } + recipients: [...recipients], + schedule: ScheduleOptions.SendLater, + priority: PriorityOptions.High, + sendContents: SendContents.All, + } : undefined, storageIntent: 'header', }; @@ -579,19 +628,20 @@ export const softDeleteChatMessage = async ( let runningVersionTag = message.fileMetadata.versionTag; const { payloads } = message.fileMetadata; if (payloads) { - await Promise.all(payloads.map(async (payload) => { - // TODO: Should the payload be deleted for everyone? With "TransitOptions" - const deleteResult = await deletePayload( - dotYouClient, - ChatDrive, - message.fileId, - payload.key, - runningVersionTag - ); - if (!deleteResult) throw new Error('Failed to delete payload'); - runningVersionTag = deleteResult.newVersionTag; - } - )); + await Promise.all( + payloads.map(async (payload) => { + // TODO: Should the payload be deleted for everyone? With "TransitOptions" + const deleteResult = await deletePayload( + dotYouClient, + ChatDrive, + message.fileId, + payload.key, + runningVersionTag + ); + if (!deleteResult) throw new Error('Failed to delete payload'); + runningVersionTag = deleteResult.newVersionTag; + }) + ); } message.fileMetadata.versionTag = runningVersionTag; diff --git a/packages/mobile/src/provider/feed/RNPostReactionProvider.ts b/packages/mobile/src/provider/feed/RNPostReactionProvider.ts index 24d52a77..69594ab7 100644 --- a/packages/mobile/src/provider/feed/RNPostReactionProvider.ts +++ b/packages/mobile/src/provider/feed/RNPostReactionProvider.ts @@ -24,11 +24,7 @@ import { getRandom16ByteArray, } from '@homebase-id/js-lib/helpers'; -import { - TransitInstructionSet, - TransitUploadResult, - uploadFileOverPeer, -} from '@homebase-id/js-lib/peer'; +import { TransitInstructionSet, uploadFileOverPeer } from '@homebase-id/js-lib/peer'; import { GetTargetDriveFromChannelId, ReactionConfig, @@ -195,7 +191,7 @@ export const saveComment = async ( systemFileType: 'Comment', }; - const result: TransitUploadResult = await uploadFileOverPeer( + const result = await uploadFileOverPeer( dotYouClient, instructionSet, metadata, @@ -204,6 +200,8 @@ export const saveComment = async ( encrypt ); + if (!result) throw new Error('Upload failed'); + if ( TransferUploadStatus.EnqueuedFailed === result.recipientStatus[context.odinId].toLowerCase() ) { diff --git a/packages/mobile/src/provider/feed/RNPostUploadProvider.ts b/packages/mobile/src/provider/feed/RNPostUploadProvider.ts index 2969feb1..4f654bc8 100644 --- a/packages/mobile/src/provider/feed/RNPostUploadProvider.ts +++ b/packages/mobile/src/provider/feed/RNPostUploadProvider.ts @@ -106,7 +106,7 @@ export const savePost = async ( const encrypt = !( file.serverMetadata?.accessControlList?.requiredSecurityGroup === SecurityGroupType.Anonymous || file.serverMetadata?.accessControlList?.requiredSecurityGroup === - SecurityGroupType.Authenticated + SecurityGroupType.Authenticated ); const targetDrive = GetTargetDriveFromChannelId(channelId); @@ -133,10 +133,10 @@ export const savePost = async ( const imageSource: ImageSource | undefined = linkPreviewWithImage ? { - height: linkPreviewWithImage.imageHeight || 0, - width: linkPreviewWithImage.imageWidth || 0, - uri: linkPreviewWithImage.imageUrl, - } + height: linkPreviewWithImage.imageHeight || 0, + width: linkPreviewWithImage.imageWidth || 0, + uri: linkPreviewWithImage.imageUrl, + } : undefined; const { tinyThumb } = imageSource @@ -210,10 +210,10 @@ export const savePost = async ( if (file.fileMetadata.appData.content.type !== 'Article') { file.fileMetadata.appData.content.primaryMediaFile = payloads[0] ? { - fileId: undefined, - fileKey: payloads[0].key, - type: payloads[0].payload.type, - } + fileId: undefined, + fileKey: payloads[0].key, + type: payloads[0].payload.type, + } : undefined; } @@ -261,7 +261,7 @@ const uploadPost = async ( const encrypt = !( file.serverMetadata?.accessControlList?.requiredSecurityGroup === SecurityGroupType.Anonymous || file.serverMetadata?.accessControlList?.requiredSecurityGroup === - SecurityGroupType.Authenticated + SecurityGroupType.Authenticated ); const instructionSet: UploadInstructionSet = { @@ -290,8 +290,9 @@ const uploadPost = async ( !stringGuidsEqual(existingPostWithThisSlug?.fileId, file.fileId) ) { // There is clash with an existing slug - file.fileMetadata.appData.content.slug = `${file.fileMetadata.appData.content.slug - }-${new Date().getTime()}`; + file.fileMetadata.appData.content.slug = `${ + file.fileMetadata.appData.content.slug + }-${new Date().getTime()}`; } } const uniqueId = file.fileMetadata.appData.content.slug @@ -386,7 +387,7 @@ const uploadPost = async ( recipients: [odinId], }; - const result: TransitUploadResult = await uploadFileOverPeer( + const result = await uploadFileOverPeer( dotYouClient, transitInstructionSet, metadata, @@ -430,11 +431,12 @@ const uploadPostHeader = async ( if ( existingPostWithThisSlug && existingPostWithThisSlug?.fileMetadata.appData.content.id !== - file.fileMetadata.appData.content.id + file.fileMetadata.appData.content.id ) { // There is clash with an existing slug - file.fileMetadata.appData.content.slug = `${file.fileMetadata.appData.content.slug - }-${new Date().getTime()}`; + file.fileMetadata.appData.content.slug = `${ + file.fileMetadata.appData.content.slug + }-${new Date().getTime()}`; } const uniqueId = file.fileMetadata.appData.content.slug