Skip to content

Commit 0ecee49

Browse files
authored
fix: prefer local uri when sharing if there (#3118)
* fix: prefer local uri when sharing if there * fix: failing tests and add new ones
1 parent 41940f0 commit 0ecee49

File tree

2 files changed

+121
-12
lines changed

2 files changed

+121
-12
lines changed

package/src/components/ImageGallery/__tests__/ImageGalleryFooter.test.tsx

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,21 +159,115 @@ describe('ImageGalleryFooter', () => {
159159
});
160160
});
161161

162-
it('should trigger the share button onPress Handler', async () => {
162+
it('should trigger the share button onPress Handler with local attachment and no mime_type', async () => {
163163
const user = userEvent.setup();
164164
const chatClient = await getTestClientWithUser({ id: 'testID' });
165165
const saveFileMock = jest.spyOn(NativeHandlers, 'saveFile');
166166
const shareImageMock = jest.spyOn(NativeHandlers, 'shareImage');
167167
const deleteFileMock = jest.spyOn(NativeHandlers, 'deleteFile');
168168

169+
const attachment = generateImageAttachment();
170+
171+
render(
172+
<OverlayProvider>
173+
<ImageGalleryContext.Provider
174+
value={
175+
{
176+
messages: [
177+
generateMessage({
178+
attachments: [attachment],
179+
}),
180+
] as unknown as LocalMessage[],
181+
} as unknown as ImageGalleryContextValue
182+
}
183+
>
184+
<Chat client={chatClient}>
185+
<ImageGallery overlayOpacity={{ value: 1 } as SharedValue<number>} />
186+
</Chat>
187+
</ImageGalleryContext.Provider>
188+
</OverlayProvider>,
189+
);
190+
191+
await waitFor(() => {
192+
user.press(screen.queryByLabelText('Share Button') as ReactTestInstance);
193+
});
194+
195+
await waitFor(() => {
196+
expect(saveFileMock).not.toHaveBeenCalled();
197+
expect(shareImageMock).toHaveBeenCalledWith({
198+
type: 'image/jpeg',
199+
url: attachment.image_url,
200+
});
201+
expect(deleteFileMock).not.toHaveBeenCalled();
202+
});
203+
});
204+
205+
it('should trigger the share button onPress Handler with local attachment and existing mime_type', async () => {
206+
const user = userEvent.setup();
207+
const chatClient = await getTestClientWithUser({ id: 'testID' });
208+
const saveFileMock = jest.spyOn(NativeHandlers, 'saveFile');
209+
const shareImageMock = jest.spyOn(NativeHandlers, 'shareImage');
210+
const deleteFileMock = jest.spyOn(NativeHandlers, 'deleteFile');
211+
212+
const attachment = { ...generateImageAttachment(), mime_type: 'image/png' };
213+
214+
render(
215+
<OverlayProvider>
216+
<ImageGalleryContext.Provider
217+
value={
218+
{
219+
messages: [
220+
generateMessage({
221+
attachments: [attachment],
222+
}),
223+
] as unknown as LocalMessage[],
224+
} as unknown as ImageGalleryContextValue
225+
}
226+
>
227+
<Chat client={chatClient}>
228+
<ImageGallery overlayOpacity={{ value: 1 } as SharedValue<number>} />
229+
</Chat>
230+
</ImageGalleryContext.Provider>
231+
</OverlayProvider>,
232+
);
233+
234+
await waitFor(() => {
235+
user.press(screen.queryByLabelText('Share Button') as ReactTestInstance);
236+
});
237+
238+
await waitFor(() => {
239+
expect(saveFileMock).not.toHaveBeenCalled();
240+
expect(shareImageMock).toHaveBeenCalledWith({
241+
type: 'image/png',
242+
url: attachment.image_url,
243+
});
244+
expect(deleteFileMock).not.toHaveBeenCalled();
245+
});
246+
});
247+
248+
it('should trigger the share button onPress Handler with cdn attachment', async () => {
249+
const user = userEvent.setup();
250+
const chatClient = await getTestClientWithUser({ id: 'testID' });
251+
const saveFileMock = jest
252+
.spyOn(NativeHandlers, 'saveFile')
253+
.mockResolvedValue('file:///local/asset/url');
254+
const shareImageMock = jest.spyOn(NativeHandlers, 'shareImage');
255+
const deleteFileMock = jest.spyOn(NativeHandlers, 'deleteFile');
256+
257+
const attachment = {
258+
...generateImageAttachment(),
259+
image_url: 'https://my-image-service/image/123456',
260+
mime_type: 'image/png',
261+
};
262+
169263
render(
170264
<OverlayProvider>
171265
<ImageGalleryContext.Provider
172266
value={
173267
{
174268
messages: [
175269
generateMessage({
176-
attachments: [generateImageAttachment()],
270+
attachments: [attachment],
177271
}),
178272
] as unknown as LocalMessage[],
179273
} as unknown as ImageGalleryContextValue
@@ -192,7 +286,10 @@ describe('ImageGalleryFooter', () => {
192286

193287
await waitFor(() => {
194288
expect(saveFileMock).toHaveBeenCalled();
195-
expect(shareImageMock).toHaveBeenCalled();
289+
expect(shareImageMock).toHaveBeenCalledWith({
290+
type: 'image/png',
291+
url: 'file:///local/asset/url',
292+
});
196293
expect(deleteFileMock).toHaveBeenCalled();
197294
});
198295
});

package/src/components/ImageGallery/components/ImageGalleryFooter.tsx

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,29 @@ export const ImageGalleryFooterWithContext = (props: ImageGalleryFooterPropsWith
142142
return;
143143
}
144144
const extension = photo.mime_type?.split('/')[1] || 'jpg';
145-
setSavingInProgress(true);
146-
const localFile = await NativeHandlers.saveFile({
147-
fileName: `${photo.user?.id || 'ChatPhoto'}-${
148-
photo.messageId
149-
}-${selectedIndex}.${extension}`,
150-
fromUrl: photo.uri,
151-
});
152-
setSavingInProgress(false);
145+
const shouldDownload = photo.uri && photo.uri.includes('http');
146+
let localFile;
147+
// If the file is already uploaded to a CDN, create a local reference to
148+
// it first; otherwise just use the local file
149+
if (shouldDownload) {
150+
setSavingInProgress(true);
151+
localFile = await NativeHandlers.saveFile({
152+
fileName: `${photo.user?.id || 'ChatPhoto'}-${
153+
photo.messageId
154+
}-${selectedIndex}.${extension}`,
155+
fromUrl: photo.uri,
156+
});
157+
setSavingInProgress(false);
158+
} else {
159+
localFile = photo.uri;
160+
}
161+
153162
// `image/jpeg` is added for the case where the mime_type isn't available for a file/image
154163
await NativeHandlers.shareImage({ type: photo.mime_type || 'image/jpeg', url: localFile });
155-
await NativeHandlers.deleteFile({ uri: localFile });
164+
// Only delete the file if a local reference has been created beforehand
165+
if (shouldDownload) {
166+
await NativeHandlers.deleteFile({ uri: localFile });
167+
}
156168
} catch (error) {
157169
setSavingInProgress(false);
158170
console.log(error);

0 commit comments

Comments
 (0)