From 0072623225c73303da32b912ec1523e4f250a4d2 Mon Sep 17 00:00:00 2001 From: vishtree Date: Thu, 3 Feb 2022 17:35:54 +0100 Subject: [PATCH 1/3] fix: fixing logic for resizing image url --- package/package.json | 1 + .../__tests__/getResizedImageUrl.test.js | 56 +++++++++++++++++++ package/src/utils/getResizedImageUrl.ts | 31 +++++----- package/yarn.lock | 50 +++++++++++++---- 4 files changed, 113 insertions(+), 25 deletions(-) create mode 100644 package/src/utils/__tests__/getResizedImageUrl.test.js diff --git a/package/package.json b/package/package.json index b7494a94c0..fee530b1a9 100644 --- a/package/package.json +++ b/package/package.json @@ -80,6 +80,7 @@ "path": "0.12.7", "react-art": "^17.0.2", "react-native-markdown-package": "1.8.1", + "react-native-url-polyfill": "^1.3.0", "stream-chat": "^5.1.2" }, "peerDependencies": { diff --git a/package/src/utils/__tests__/getResizedImageUrl.test.js b/package/src/utils/__tests__/getResizedImageUrl.test.js new file mode 100644 index 0000000000..ff540ca473 --- /dev/null +++ b/package/src/utils/__tests__/getResizedImageUrl.test.js @@ -0,0 +1,56 @@ +import { PixelRatio } from 'react-native'; + +import { getResizedImageUrl } from '../getResizedImageUrl'; + +describe('getResizedImageUrl', () => { + it('should return same url if its not cloudfront cdn', () => { + const testUrl = 'http://foo.com/blah_(wikipedia)#cite-1'; + + const resizedUrl = getResizedImageUrl({ height: 100, url: testUrl, width: 100 }); + expect(resizedUrl).toEqual(testUrl); + }); + + it('should append given height, width and resize mode to url', () => { + const testUrl = 'http://us-east.stream-io-cdn.com/blah'; + + const testConfigs = [ + { height: 100, resize: 'scale', width: 100 }, + { height: 200, resize: 'fill', width: 300 }, + { height: 1000, resize: 'clip', width: 10 }, + ]; + + testConfigs.forEach(({ height, resize, width }) => { + const resizedUrl = getResizedImageUrl({ height, resize, url: testUrl, width }); + const parsedUrl = new URL(resizedUrl); + expect(parsedUrl.searchParams.get('h')).toEqual( + `${PixelRatio.getPixelSizeForLayoutSize(height)}`, + ); + expect(parsedUrl.searchParams.get('w')).toEqual( + `${PixelRatio.getPixelSizeForLayoutSize(width)}`, + ); + expect(parsedUrl.searchParams.get('resize')).toEqual(resize); + }); + }); + + it('should replace wildcards with given height, width and resize mode within url', () => { + const testUrl = 'http://us-east.stream-io-cdn.com/blah?h=*&w=*&resize=*'; + + const testConfigs = [ + { height: 100, resize: 'scale', width: 100 }, + { height: 200, resize: 'fill', width: 300 }, + { height: 1000, resize: 'clip', width: 10 }, + ]; + + testConfigs.forEach(({ height, resize, width }) => { + const resizedUrl = getResizedImageUrl({ height, resize, url: testUrl, width }); + const parsedUrl = new URL(resizedUrl); + expect(parsedUrl.searchParams.get('h')).toEqual( + `${PixelRatio.getPixelSizeForLayoutSize(height)}`, + ); + expect(parsedUrl.searchParams.get('w')).toEqual( + `${PixelRatio.getPixelSizeForLayoutSize(width)}`, + ); + expect(parsedUrl.searchParams.get('resize')).toEqual(resize); + }); + }); +}); diff --git a/package/src/utils/getResizedImageUrl.ts b/package/src/utils/getResizedImageUrl.ts index 1605d0b166..2b954494bf 100644 --- a/package/src/utils/getResizedImageUrl.ts +++ b/package/src/utils/getResizedImageUrl.ts @@ -1,8 +1,12 @@ import { PixelRatio } from 'react-native'; +import { setupURLPolyfill } from 'react-native-url-polyfill'; + +setupURLPolyfill(); type GetResizedImageUrlParams = { url: string; height?: string | number; + resize?: 'clip' | 'crop' | 'fill' | 'scale'; width?: string | number; }; @@ -18,26 +22,27 @@ type GetResizedImageUrlParams = { * * @returns {string} Url of the image with given height and width. */ -export function getResizedImageUrl({ height, url, width }: GetResizedImageUrlParams) { - const isResizableUrl = url.includes('&h=*') && url.includes('&w=*') && url.includes('&resize=*'); - +export function getResizedImageUrl({ + height, + resize = 'clip', + url, + width, +}: GetResizedImageUrlParams) { + // Check if url belongs to cloudfront CDN + const isResizableUrl = url.includes('.stream-io-cdn.com'); if (!isResizableUrl || (!height && !width)) return url; - let resizedUrl = url; + const parsedUrl = new URL(url); if (height) { - resizedUrl = resizedUrl.replace( - 'h=*', - `h=${PixelRatio.getPixelSizeForLayoutSize(Number(height))}`, - ); + parsedUrl.searchParams.set('h', `${PixelRatio.getPixelSizeForLayoutSize(Number(height))}`); } if (width) { - resizedUrl = resizedUrl.replace( - 'w=*', - `w=${PixelRatio.getPixelSizeForLayoutSize(Number(width))}`, - ); + parsedUrl.searchParams.set('w', `${PixelRatio.getPixelSizeForLayoutSize(Number(width))}`); } - return resizedUrl.replace('resize=*', `resize=clip`); + parsedUrl.searchParams.set('resize', `${resize}`); + + return parsedUrl.toString(); } diff --git a/package/yarn.lock b/package/yarn.lock index 7a4fb36ab9..ea31105649 100644 --- a/package/yarn.lock +++ b/package/yarn.lock @@ -3183,7 +3183,7 @@ base-64@^0.1.0: resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" integrity sha1-eAqZyE59YAJgNhURxId2E78k9rs= -base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.5.1: +base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -3467,6 +3467,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.4.3: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -5544,7 +5552,7 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@^1.0.0, follow-redirects@^1.10.0: +follow-redirects@^1.0.0, follow-redirects@^1.14.4: version "1.14.7" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== @@ -6149,7 +6157,7 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -6414,21 +6422,14 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.2.0, is-core-module@^2.8.0: +is-core-module@^2.2.0: version "2.8.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== dependencies: has "^1.0.3" -is-core-module@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== - dependencies: - has "^1.0.3" - -is-core-module@^2.8.0: +is-core-module@^2.8.0, is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== @@ -9746,6 +9747,13 @@ react-native-typescript-transformer@1.2.13: semver "^5.4.1" source-map "^0.5.6" +react-native-url-polyfill@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-1.3.0.tgz#c1763de0f2a8c22cc3e959b654c8790622b6ef6a" + integrity sha512-w9JfSkvpqqlix9UjDvJjm1EjSt652zVQ6iwCIj1cVVkwXf4jQhQgTNXY6EVTwuAmUjg6BC6k9RHCBynoLFo3IQ== + dependencies: + whatwg-url-without-unicode "8.0.0-3" + react-native-web@0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.15.0.tgz#c97d47dfc43bfd99a562370fefb43ca38beb38b0" @@ -10248,6 +10256,15 @@ resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.1 is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@^1.20.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.3: version "2.0.0-next.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" @@ -12123,6 +12140,15 @@ whatwg-mimetype@^2.3.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url-without-unicode@8.0.0-3: + version "8.0.0-3" + resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b" + integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig== + dependencies: + buffer "^5.4.3" + punycode "^2.1.1" + webidl-conversions "^5.0.0" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" From c77fc7b08f4c15ba8253f46553cf8e0642cee000 Mon Sep 17 00:00:00 2001 From: vishtree Date: Fri, 4 Feb 2022 08:13:55 +0100 Subject: [PATCH 2/3] test: fixed buildGallery tests --- .../components/Attachment/__tests__/buildGallery.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package/src/components/Attachment/__tests__/buildGallery.test.js b/package/src/components/Attachment/__tests__/buildGallery.test.js index 4abe329da0..96d2a1655a 100644 --- a/package/src/components/Attachment/__tests__/buildGallery.test.js +++ b/package/src/components/Attachment/__tests__/buildGallery.test.js @@ -97,7 +97,7 @@ describe('buildGallery', () => { it('thumbnail size should be smaller than the limits set by sizeConfig', () => { const bigImage = generateImageAttachment({ image_url: - 'https://stream-io.cdn.com/23kn4k2j3n4k2n3k4n23?sig=34k23n4k23nk423&h=*&w=*&resize=*', + 'https://us-east.stream-io-cdn.com/23kn4k2j3n4k2n3k4n23?sig=34k23n4k23nk423&h=*&w=*&resize=*', original_height: 1200, original_width: 900, }); @@ -107,13 +107,13 @@ describe('buildGallery', () => { sizeConfig: defaultSizeConfig, }); const t1 = tg1[0][0]; - expect(t1.url.includes(`h=${PixelRatio.getPixelSizeForLayoutSize(t1.height)}`)).toBe(true); + expect(t1.url.includes(`&h=${PixelRatio.getPixelSizeForLayoutSize(t1.height)}`)).toBe(true); expect(t1.url.includes(`&w=${PixelRatio.getPixelSizeForLayoutSize(t1.width)}`)).toBe(true); expect(t1.url.includes(`&resize=clip`)).toBe(true); const smallImage = generateImageAttachment({ image_url: - 'https://stream-io.cdn.com/23kn4k2j3n4k2n3k4n23?sig=34k23n4k23nk423&h=*&w=*&resize=*', + 'https://us-east.stream-io-cdn.com/23kn4k2j3n4k2n3k4n23?sig=34k23n4k23nk423&h=*&w=*&resize=*', original_height: 30, original_width: 20, }); @@ -124,7 +124,7 @@ describe('buildGallery', () => { }); const t2 = tg2[0][0]; - expect(t2.url.includes(`h=*`)).toBe(true); + expect(t2.url.includes(`&h=*`)).toBe(true); expect(t2.url.includes(`&w=*`)).toBe(true); expect(t2.url.includes(`&resize=*`)).toBe(true); }); From 74aa571dd34de8b5c8d596c4780763a468b68786 Mon Sep 17 00:00:00 2001 From: vishtree Date: Fri, 4 Feb 2022 09:10:06 +0100 Subject: [PATCH 3/3] refactor: moving setup part to Chat component --- package/src/components/Chat/Chat.tsx | 3 +++ package/src/init.ts | 5 +++++ package/src/utils/getResizedImageUrl.ts | 3 --- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 package/src/init.ts diff --git a/package/src/components/Chat/Chat.tsx b/package/src/components/Chat/Chat.tsx index 9aeb1b7277..61a15e4319 100644 --- a/package/src/components/Chat/Chat.tsx +++ b/package/src/components/Chat/Chat.tsx @@ -18,6 +18,7 @@ import { TranslationProvider, } from '../../contexts/translationContext/TranslationContext'; import { useStreami18n } from '../../hooks/useStreami18n'; +import init from '../../init'; import { SDK } from '../../native'; import type { @@ -33,6 +34,8 @@ import type { import type { Streami18n } from '../../utils/Streami18n'; import { version } from '../../version.json'; +init(); + export type ChatProps< At extends UnknownType = DefaultAttachmentType, Ch extends UnknownType = DefaultChannelType, diff --git a/package/src/init.ts b/package/src/init.ts new file mode 100644 index 0000000000..87ebe031a9 --- /dev/null +++ b/package/src/init.ts @@ -0,0 +1,5 @@ +import { setupURLPolyfill } from 'react-native-url-polyfill'; + +export default () => { + setupURLPolyfill(); +}; diff --git a/package/src/utils/getResizedImageUrl.ts b/package/src/utils/getResizedImageUrl.ts index 2b954494bf..6276b96bc4 100644 --- a/package/src/utils/getResizedImageUrl.ts +++ b/package/src/utils/getResizedImageUrl.ts @@ -1,7 +1,4 @@ import { PixelRatio } from 'react-native'; -import { setupURLPolyfill } from 'react-native-url-polyfill'; - -setupURLPolyfill(); type GetResizedImageUrlParams = { url: string;