diff --git a/lib/utils/message-ops-utils.js b/lib/utils/message-ops-utils.js --- a/lib/utils/message-ops-utils.js +++ b/lib/utils/message-ops-utils.js @@ -1,8 +1,16 @@ // @flow +import invariant from 'invariant'; +import _keyBy from 'lodash/fp/keyBy'; + import { messageID } from '../shared/message-utils'; import { messageSpecs } from '../shared/messages/message-specs'; -import type { Media, ClientDBMediaInfo, Image } from '../types/media-types'; +import type { + Media, + ClientDBMediaInfo, + Image, + Video, +} from '../types/media-types'; import { type ClientDBMessageInfo, type RawMessageInfo, @@ -11,6 +19,7 @@ type MessageStoreOperation, type ClientDBMessageStoreOperation, } from '../types/message-types'; +import type { MediaMessageServerDBContent } from '../types/messages/media.js'; function translateMediaToClientDBMediaInfos( media: $ReadOnlyArray, @@ -66,6 +75,63 @@ }; } +function translateClientDBMediaInfosToMedia( + clientDBMessageInfo: ClientDBMessageInfo, +): $ReadOnlyArray { + if (parseInt(clientDBMessageInfo.type) === messageTypes.IMAGES) { + invariant(clientDBMessageInfo.media_infos, 'media_infos must exist'); + return clientDBMessageInfo.media_infos.map( + translateClientDBMediaInfoToImage, + ); + } + invariant(clientDBMessageInfo.media_infos, 'media_infos must exist'); + const mediaInfos: $ReadOnlyArray = + clientDBMessageInfo.media_infos; + const mediaMap = _keyBy('id')(mediaInfos); + + invariant(clientDBMessageInfo.content, 'content must exist'); + const messageContent: $ReadOnlyArray = JSON.parse( + clientDBMessageInfo.content, + ); + + const translatedMedia = []; + for (const media of messageContent) { + if (media.type === 'photo') { + const extras = JSON.parse(mediaMap[media.uploadID].extras); + const { dimensions } = extras; + + const image: Image = { + id: media.uploadID, + uri: mediaMap[media.uploadID].uri, + type: 'photo', + dimensions, + }; + translatedMedia.push(image); + } else if (media.type === 'video') { + const extras = JSON.parse(mediaMap[media.uploadID].extras); + const { + dimensions, + loop, + local_media_selection: localMediaSelection, + } = extras; + + const video: Video = { + id: media.uploadID, + uri: mediaMap[media.uploadID].uri, + type: 'video', + dimensions, + loop, + thumbnailID: media.thumbnailUploadID, + thumbnailURI: mediaMap[media.thumbnailUploadID].uri, + }; + translatedMedia.push( + localMediaSelection ? { ...video, localMediaSelection } : video, + ); + } + } + return translatedMedia; +} + function translateRawMessageInfoToClientDBMessageInfo( rawMessageInfo: RawMessageInfo, ): ClientDBMessageInfo { @@ -132,4 +198,5 @@ translateClientDBMessageInfoToRawMessageInfo, translateClientDBMessageInfosToRawMessageInfos, convertMessageStoreOperationsToClientDBOperations, + translateClientDBMediaInfosToMedia, }; diff --git a/lib/utils/message-ops-utils.test.js b/lib/utils/message-ops-utils.test.js --- a/lib/utils/message-ops-utils.test.js +++ b/lib/utils/message-ops-utils.test.js @@ -1,6 +1,9 @@ // @flow -import type { RawSidebarSourceMessageInfo } from '../types/message-types'; +import type { + ClientDBMessageInfo, + RawSidebarSourceMessageInfo, +} from '../types/message-types'; import type { RawAddMembersMessageInfo } from '../types/messages/add-members'; import type { RawChangeSettingsMessageInfo } from '../types/messages/change-settings'; import type { RawCreateEntryMessageInfo } from '../types/messages/create-entry'; @@ -19,6 +22,7 @@ import { translateRawMessageInfoToClientDBMessageInfo, translateClientDBMessageInfoToRawMessageInfo, + translateClientDBMediaInfosToMedia, } from './message-ops-utils'; test('TEXT: rawMessageInfo -> clientDBMessageInfo -> rawMessageInfo', () => { @@ -379,3 +383,69 @@ ), ).toStrictEqual(rawCreateSidebarMessageInfo); }); + +test('Test translateClientDBMediaInfosToMedia(...) with one video', () => { + const clientDBMessageInfo: ClientDBMessageInfo = { + id: 'local0', + local_id: 'local0', + thread: '90145', + user: '90134', + type: '15', + future_type: null, + time: '1665014145088', + content: + '[{"type":"video","uploadID":"localUpload0","thumbnailUploadID":"localUpload1"}]', + media_infos: [ + { + id: 'localUpload0', + uri: + 'assets-library://asset/asset.mov?id=6F1BEA56-3875-474C-B3AF-B11DEDCBAFF2&ext=mov', + type: 'video', + extras: + '{"dimensions":{"height":1010,"width":576},"loop":false,"local_media_selection":{"step":"video_library","dimensions":{"height":1010,"width":576},"uri":"assets-library://asset/asset.mov?id=6F1BEA56-3875-474C-B3AF-B11DEDCBAFF2&ext=mov","filename":"IMG_0007.MOV","mediaNativeID":"6F1BEA56-3875-474C-B3AF-B11DEDCBAFF2/L0/001","duration":25.866666666666667,"selectTime":1665014144968,"sendTime":1665014144968,"retries":0}}', + }, + { + id: 'localUpload1', + uri: + 'assets-library://asset/asset.mov?id=6F1BEA56-3875-474C-B3AF-B11DEDCBAFF2&ext=mov', + type: 'photo', + extras: '{"dimensions":{"height":1010,"width":576},"loop":false}', + }, + ], + }; + const rawMessageInfo = { + type: 15, + threadID: '90145', + creatorID: '90134', + time: 1665014145088, + media: [ + { + id: 'localUpload0', + uri: + 'assets-library://asset/asset.mov?id=6F1BEA56-3875-474C-B3AF-B11DEDCBAFF2&ext=mov', + type: 'video', + dimensions: { height: 1010, width: 576 }, + localMediaSelection: { + step: 'video_library', + dimensions: { height: 1010, width: 576 }, + uri: + 'assets-library://asset/asset.mov?id=6F1BEA56-3875-474C-B3AF-B11DEDCBAFF2&ext=mov', + filename: 'IMG_0007.MOV', + mediaNativeID: '6F1BEA56-3875-474C-B3AF-B11DEDCBAFF2/L0/001', + duration: 25.866666666666667, + selectTime: 1665014144968, + sendTime: 1665014144968, + retries: 0, + }, + loop: false, + thumbnailID: 'localUpload1', + thumbnailURI: + 'assets-library://asset/asset.mov?id=6F1BEA56-3875-474C-B3AF-B11DEDCBAFF2&ext=mov', + }, + ], + localID: 'local0', + }; + expect(translateClientDBMediaInfosToMedia(clientDBMessageInfo)).toStrictEqual( + rawMessageInfo.media, + ); +});