diff --git a/android/buildscript-gradle.lockfile b/android/buildscript-gradle.lockfile index dfde0b3d60..3a4a440688 100644 --- a/android/buildscript-gradle.lockfile +++ b/android/buildscript-gradle.lockfile @@ -130,6 +130,7 @@ org.jetbrains.kotlin:kotlin-gradle-plugins-bom:2.0.21=classpath org.jetbrains.kotlin:kotlin-klib-commonizer-api:2.0.21=classpath org.jetbrains.kotlin:kotlin-native-utils:2.0.21=classpath org.jetbrains.kotlin:kotlin-reflect:1.9.20=classpath +org.jetbrains.kotlin:kotlin-stdlib-common:2.0.21=classpath org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20=classpath org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20=classpath org.jetbrains.kotlin:kotlin-stdlib:2.0.21=classpath @@ -137,6 +138,11 @@ org.jetbrains.kotlin:kotlin-tooling-core:2.0.21=classpath org.jetbrains.kotlin:kotlin-util-io:2.0.21=classpath org.jetbrains.kotlin:kotlin-util-klib:2.0.21=classpath org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4=classpath +org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.3=classpath +org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.6.3=classpath +org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.3=classpath +org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.6.3=classpath +org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3=classpath org.jetbrains:annotations:23.0.0=classpath org.jvnet.staxex:stax-ex:1.8.1=classpath org.ow2.asm:asm-analysis:9.6=classpath diff --git a/app.json b/app.json index 08eb45fcd9..914911c17a 100644 --- a/app.json +++ b/app.json @@ -1,4 +1,7 @@ { "name": "Mattermost", - "displayName": "Mattermost" + "displayName": "Mattermost", + "plugins": [ + "expo-web-browser" + ] } diff --git a/app/components/expo_image/index.tsx b/app/components/expo_image/index.tsx index 9dbffd7ca6..bd70fffb9c 100644 --- a/app/components/expo_image/index.tsx +++ b/app/components/expo_image/index.tsx @@ -8,6 +8,8 @@ import Animated from 'react-native-reanimated'; import {useServerUrl} from '@context/server'; import {urlSafeBase64Encode} from '@utils/security'; +import type {SharedRefType} from 'expo'; + type ExpoImagePropsWithId = ImageProps & {id: string}; type ExpoImagePropsMemoryOnly = ImageProps & {cachePolicy: 'memory'; id?: string}; type ExpoImageProps = ExpoImagePropsWithId | ExpoImagePropsMemoryOnly; @@ -25,13 +27,13 @@ const ExpoImage = forwardRef(({id, ...props}, ref) => { * for filesystem path compatibility (avoiding special characters in directory names). */ const cachePath = useMemo(() => urlSafeBase64Encode(serverUrl), [serverUrl]); - const source: ImageSource = useMemo(() => { - if (typeof props.source === 'number') { + const source: ImageSource | string | number | ImageSource[] | string[] | SharedRefType<'image'> | null | undefined = useMemo(() => { + if (typeof props.source === 'number' || typeof props.source === 'string' || Array.isArray(props.source) || !props.source) { return props.source; } // Only add cacheKey and cachePath if id is provided (i.e., not memory-only caching) - if (id) { + if (id && typeof props.source === 'object' && 'uri' in props.source) { return { ...props.source, cacheKey: id, @@ -43,13 +45,13 @@ const ExpoImage = forwardRef(({id, ...props}, ref) => { }, [id, props.source, cachePath]); // Process placeholder to add cachePath and cacheKey if it has a uri - const placeholder: ImageSource | undefined = useMemo(() => { - if (!props.placeholder || typeof props.placeholder === 'number' || typeof props.placeholder === 'string') { + const placeholder: ImageSource | string | number | ImageSource[] | string[] | SharedRefType<'image'> | null | undefined = useMemo(() => { + if (!props.placeholder || typeof props.placeholder === 'number' || typeof props.placeholder === 'string' || Array.isArray(props.placeholder)) { return props.placeholder; } // If placeholder has a uri and id is provided, add cachePath and cacheKey - if (props.placeholder.uri && id) { + if (typeof props.placeholder === 'object' && 'uri' in props.placeholder && props.placeholder.uri && id) { return { ...props.placeholder, cacheKey: `${id}-thumb`, @@ -74,13 +76,13 @@ ExpoImage.displayName = 'ExpoImage'; const ExpoImageBackground = ({id, ...props}: ExpoImageBackgroundProps) => { const serverUrl = useServerUrl(); const cachePath = useMemo(() => urlSafeBase64Encode(serverUrl), [serverUrl]); - const source: ImageSource = useMemo(() => { - if (typeof props.source === 'number') { + const source: ImageSource | string | number | ImageSource[] | string[] | SharedRefType<'image'> | null | undefined = useMemo(() => { + if (typeof props.source === 'number' || typeof props.source === 'string' || Array.isArray(props.source) || !props.source) { return props.source; } // Only add cacheKey and cachePath if id is provided (i.e., not memory-only caching) - if (id) { + if (id && typeof props.source === 'object' && 'uri' in props.source) { return { ...props.source, cacheKey: id, @@ -92,13 +94,13 @@ const ExpoImageBackground = ({id, ...props}: ExpoImageBackgroundProps) => { }, [id, props.source, cachePath]); // Process placeholder to add cachePath and cacheKey if it has a uri - const placeholder: ImageSource | undefined = useMemo(() => { - if (!props.placeholder || typeof props.placeholder === 'number' || typeof props.placeholder === 'string') { + const placeholder: ImageSource | string | number | ImageSource[] | string[] | SharedRefType<'image'> | null | undefined = useMemo(() => { + if (!props.placeholder || typeof props.placeholder === 'number' || typeof props.placeholder === 'string' || Array.isArray(props.placeholder)) { return props.placeholder; } // If placeholder has a uri and id is provided, add cachePath and cacheKey - if (props.placeholder.uri && id) { + if (typeof props.placeholder === 'object' && 'uri' in props.placeholder && props.placeholder.uri && id) { return { ...props.placeholder, cacheKey: `${id}-thumb`, diff --git a/package.json b/package.json index 80a6ffba49..47bb39cdcb 100644 --- a/package.json +++ b/package.json @@ -53,15 +53,17 @@ "deep-equal": "2.2.3", "deepmerge": "4.3.1", "emoji-regex": "10.4.0", - "expo": "52.0.47", + "expo": "53.0.24", "expo-application": "6.0.2", + "expo-constants": "17.1.7", "expo-crypto": "14.0.2", "expo-device": "7.0.3", - "expo-image": "2.0.7", - "expo-linear-gradient": "14.0.2", + "expo-file-system": "18.1.11", + "expo-image": "2.4.1", + "expo-linear-gradient": "14.1.5", "expo-store-review": "8.0.1", "expo-video-thumbnails": "9.0.3", - "expo-web-browser": "14.0.2", + "expo-web-browser": "~14.2.0", "fflate": "0.8.2", "fuse.js": "7.1.0", "html-entities": "2.6.0", diff --git a/patches/expo-file-system+18.0.12.patch b/patches/expo-file-system+18.1.11.patch similarity index 100% rename from patches/expo-file-system+18.0.12.patch rename to patches/expo-file-system+18.1.11.patch diff --git a/patches/expo-image+2.0.7.patch b/patches/expo-image+2.4.1.patch similarity index 92% rename from patches/expo-image+2.0.7.patch rename to patches/expo-image+2.4.1.patch index 69520d0097..bece1d88a3 100644 --- a/patches/expo-image+2.0.7.patch +++ b/patches/expo-image+2.4.1.patch @@ -1,16 +1,3 @@ -diff --git a/node_modules/expo-image/android/build.gradle b/node_modules/expo-image/android/build.gradle -index 11492a2..b6bb941 100644 ---- a/node_modules/expo-image/android/build.gradle -+++ b/node_modules/expo-image/android/build.gradle -@@ -44,7 +44,7 @@ dependencies { - kapt "com.github.bumptech.glide:compiler:${GLIDE_VERSION}" - api 'com.caverock:androidsvg-aar:1.4' - -- implementation "com.github.penfeizhou.android.animation:glide-plugin:3.0.2" -+ implementation("com.github.penfeizhou.android.animation:glide-plugin:3.0.3") - implementation "com.github.bumptech.glide:avif-integration:${GLIDE_VERSION}" - - api 'com.github.bumptech.glide:okhttp3-integration:4.11.0' diff --git a/node_modules/expo-image/android/src/main/java/expo/modules/image/ExpoImageAppGlideModule.kt b/node_modules/expo-image/android/src/main/java/expo/modules/image/ExpoImageAppGlideModule.kt index 5735515..dbbb924 100644 --- a/node_modules/expo-image/android/src/main/java/expo/modules/image/ExpoImageAppGlideModule.kt @@ -36,7 +23,7 @@ index 5735515..dbbb924 100644 } } diff --git a/node_modules/expo-image/android/src/main/java/expo/modules/image/ExpoImageModule.kt b/node_modules/expo-image/android/src/main/java/expo/modules/image/ExpoImageModule.kt -index 73641a0..186fe54 100644 +index 0170d9b..169425c 100644 --- a/node_modules/expo-image/android/src/main/java/expo/modules/image/ExpoImageModule.kt +++ b/node_modules/expo-image/android/src/main/java/expo/modules/image/ExpoImageModule.kt @@ -148,13 +148,17 @@ class ExpoImageModule : Module() { @@ -299,10 +286,10 @@ index 72ad8fa..60ceaac 100644 private fun getCustomHeaders(): Headers { diff --git a/node_modules/expo-image/build/Image.d.ts b/node_modules/expo-image/build/Image.d.ts -index 44ea175..14b20d9 100644 +index 765a3db..6982c6d 100644 --- a/node_modules/expo-image/build/Image.d.ts +++ b/node_modules/expo-image/build/Image.d.ts -@@ -33,6 +33,16 @@ export declare class Image extends React.PureComponent { +@@ -35,6 +35,16 @@ export declare class Image extends React.PureComponent { * finished prefetching. */ static prefetch(urls: string | string[], options?: ImagePrefetchOptions): Promise; @@ -319,7 +306,7 @@ index 44ea175..14b20d9 100644 /** * Asynchronously clears all images stored in memory. * @platform android -@@ -46,11 +56,13 @@ export declare class Image extends React.PureComponent { +@@ -48,11 +58,13 @@ export declare class Image extends React.PureComponent { * Asynchronously clears all images from the disk cache. * @platform android * @platform ios @@ -335,10 +322,10 @@ index 44ea175..14b20d9 100644 * Asynchronously checks if an image exists in the disk cache and resolves to * the path of the cached image if it does. diff --git a/node_modules/expo-image/build/Image.types.d.ts b/node_modules/expo-image/build/Image.types.d.ts -index 493fd68..1f71756 100644 +index f690040..af43e4a 100644 --- a/node_modules/expo-image/build/Image.types.d.ts +++ b/node_modules/expo-image/build/Image.types.d.ts -@@ -46,6 +46,14 @@ export type ImageSource = { +@@ -45,6 +45,14 @@ export type ImageSource = { * If not provided, the `uri` is used also as the cache key. */ cacheKey?: string; @@ -354,15 +341,16 @@ index 493fd68..1f71756 100644 * The max width of the viewport for which this source should be selected. * Has no effect if `source` prop is not an array or has only 1 element. diff --git a/node_modules/expo-image/ios/ExpoImage.podspec b/node_modules/expo-image/ios/ExpoImage.podspec -index 21bef71..d662d23 100644 +index 40e2b49..695f137 100644 --- a/node_modules/expo-image/ios/ExpoImage.podspec +++ b/node_modules/expo-image/ios/ExpoImage.podspec -@@ -20,9 +20,7 @@ Pod::Spec.new do |s| +@@ -20,10 +20,8 @@ Pod::Spec.new do |s| s.dependency 'ExpoModulesCore' - s.dependency 'SDWebImage', '~> 5.19.1' + s.dependency 'SDWebImage', '~> 5.21.0' - s.dependency 'SDWebImageAVIFCoder', '~> 0.11.0' s.dependency 'SDWebImageSVGCoder', '~> 1.7.0' + s.dependency 'SDWebImageWebPCoder', '~> 0.14.6' - s.dependency 'libavif/libdav1d' # Swift/Objective-C compatibility @@ -384,7 +372,7 @@ index a0dacf9..36a2908 100644 if let maxSize { context[.imageThumbnailPixelSize] = maxSize diff --git a/node_modules/expo-image/ios/ImageModule.swift b/node_modules/expo-image/ios/ImageModule.swift -index 4bab386..4d9ca4f 100644 +index 1451696..3985a30 100644 --- a/node_modules/expo-image/ios/ImageModule.swift +++ b/node_modules/expo-image/ios/ImageModule.swift @@ -2,7 +2,6 @@ @@ -395,7 +383,7 @@ index 4bab386..4d9ca4f 100644 import SDWebImageSVGCoder public final class ImageModule: Module { -@@ -150,6 +149,36 @@ public final class ImageModule: Module { +@@ -170,6 +169,36 @@ public final class ImageModule: Module { } } @@ -432,7 +420,7 @@ index 4bab386..4d9ca4f 100644 AsyncFunction("generateBlurhashAsync") { (url: URL, numberOfComponents: CGSize, promise: Promise) in let downloader = SDWebImageDownloader() let parsedNumberOfComponents = (Int(numberOfComponents.width), Int(numberOfComponents.height)) -@@ -170,9 +199,22 @@ public final class ImageModule: Module { +@@ -190,9 +219,22 @@ public final class ImageModule: Module { return true } @@ -458,10 +446,10 @@ index 4bab386..4d9ca4f 100644 } } -@@ -211,7 +253,6 @@ public final class ImageModule: Module { +@@ -230,7 +272,6 @@ public final class ImageModule: Module { + static func registerCoders() { - // By default Animated WebP is not supported - SDImageCodersManager.shared.addCoder(SDImageAWebPCoder.shared) + SDImageCodersManager.shared.addCoder(WebPCoder.shared) - SDImageCodersManager.shared.addCoder(SDImageAVIFCoder.shared) SDImageCodersManager.shared.addCoder(SDImageSVGCoder.shared) SDImageCodersManager.shared.addCoder(SDImageHEICCoder.shared) @@ -481,19 +469,19 @@ index 88082fd..5025f0e 100644 return width * height * scale * scale } diff --git a/node_modules/expo-image/ios/ImageUtils.swift b/node_modules/expo-image/ios/ImageUtils.swift -index 34f2231..a58943e 100644 +index e24e776..fc32c79 100644 --- a/node_modules/expo-image/ios/ImageUtils.swift +++ b/node_modules/expo-image/ios/ImageUtils.swift -@@ -172,7 +172,7 @@ func createCacheKeyFilter(_ cacheKey: String?) -> SDWebImageCacheKeyFilter? { +@@ -158,7 +158,7 @@ func createCacheKeyFilter(_ cacheKey: String?) -> SDWebImageCacheKeyFilter? { /** Creates a default image context based on the source and the cache policy. */ --func createSDWebImageContext(forSource source: ImageSource, cachePolicy: ImageCachePolicy = .disk) -> SDWebImageContext { -+func createSDWebImageContext(forSource source: ImageSource, cachePolicy: ImageCachePolicy = .disk, customCache: SDImageCache? = nil) -> SDWebImageContext { +-func createSDWebImageContext(forSource source: ImageSource, cachePolicy: ImageCachePolicy = .disk, useAppleWebpCodec: Bool = true) -> SDWebImageContext { ++func createSDWebImageContext(forSource source: ImageSource, cachePolicy: ImageCachePolicy = .disk, customCache: SDImageCache? = nil, useAppleWebpCodec: Bool = true) -> SDWebImageContext { var context = SDWebImageContext() // Modify URL request to add headers. -@@ -209,6 +209,12 @@ func createSDWebImageContext(forSource source: ImageSource, cachePolicy: ImageCa +@@ -202,6 +202,12 @@ func createSDWebImageContext(forSource source: ImageSource, cachePolicy: ImageCa // Some loaders (e.g. blurhash) may need access to the source. context[ImageView.contextSourceKey] = source @@ -507,7 +495,7 @@ index 34f2231..a58943e 100644 } diff --git a/node_modules/expo-image/ios/ImageView.swift b/node_modules/expo-image/ios/ImageView.swift -index 2ab4cba..0d423ea 100644 +index bb6f6a5..de3468b 100644 --- a/node_modules/expo-image/ios/ImageView.swift +++ b/node_modules/expo-image/ios/ImageView.swift @@ -8,6 +8,79 @@ import VisionKit @@ -590,33 +578,33 @@ index 2ab4cba..0d423ea 100644 // swiftlint:disable:next type_body_length public final class ImageView: ExpoView { static let contextSourceKey = SDWebImageContextOption(rawValue: "source") -@@ -129,7 +202,10 @@ public final class ImageView: ExpoView { +@@ -152,7 +225,10 @@ public final class ImageView: ExpoView { if sdImageView.image == nil { sdImageView.contentMode = contentFit.toContentMode() } -- var context = createSDWebImageContext(forSource: source, cachePolicy: cachePolicy) +- var context = createSDWebImageContext(forSource: source, cachePolicy: cachePolicy, useAppleWebpCodec: useAppleWebpCodec) + + // Get custom cache if cachePath is specified + let customCache = CachePathManager.shared.getCacheForPath(source.cachePath) -+ var context = createSDWebImageContext(forSource: source, cachePolicy: cachePolicy, customCache: customCache) ++ var context = createSDWebImageContext(forSource: source, cachePolicy: cachePolicy, customCache: customCache, useAppleWebpCodec: useAppleWebpCodec) // Cancel currently running load requests. cancelPendingOperation() -@@ -311,7 +387,8 @@ public final class ImageView: ExpoView { +@@ -337,7 +413,8 @@ public final class ImageView: ExpoView { // to cache them or apply the same policy as with the proper image? // Basically they are also cached in memory as the `placeholderImage` property, // so just `disk` policy sounds like a good idea. -- var context = createSDWebImageContext(forSource: placeholder, cachePolicy: .disk) +- var context = createSDWebImageContext(forSource: placeholder, cachePolicy: .disk, useAppleWebpCodec: useAppleWebpCodec) + let customCache = CachePathManager.shared.getCacheForPath(placeholder.cachePath) -+ var context = createSDWebImageContext(forSource: placeholder, cachePolicy: .disk, customCache: customCache) ++ var context = createSDWebImageContext(forSource: placeholder, cachePolicy: .disk, customCache: customCache, useAppleWebpCodec: useAppleWebpCodec) let isPlaceholderHash = placeholder.isBlurhash || placeholder.isThumbhash diff --git a/node_modules/expo-image/src/Image.tsx b/node_modules/expo-image/src/Image.tsx -index 7721bd9..584cb02 100644 +index c52e711..c392133 100644 --- a/node_modules/expo-image/src/Image.tsx +++ b/node_modules/expo-image/src/Image.tsx -@@ -69,8 +69,18 @@ export class Image extends React.PureComponent { +@@ -70,8 +70,18 @@ export class Image extends React.PureComponent { * finished prefetching. */ static async prefetch(urls: string | string[], options?: ImagePrefetchOptions): Promise; @@ -636,7 +624,7 @@ index 7721bd9..584cb02 100644 options?: ImagePrefetchOptions['cachePolicy'] | ImagePrefetchOptions ): Promise { let cachePolicy: ImagePrefetchOptions['cachePolicy'] = 'memory-disk'; -@@ -85,7 +95,18 @@ export class Image extends React.PureComponent { +@@ -86,7 +96,18 @@ export class Image extends React.PureComponent { break; } @@ -655,12 +643,23 @@ index 7721bd9..584cb02 100644 + } } + /** +@@ -109,8 +130,8 @@ export class Image extends React.PureComponent { + * It may resolve to `false` on Android when the activity is no longer available. + * Resolves to `false` on Web. + */ +- static async clearDiskCache(): Promise { +- return await ImageModule.clearDiskCache(); ++ static async clearDiskCache(path?: string): Promise { ++ return await ImageModule.clearDiskCache(path); + } + /** diff --git a/node_modules/expo-image/src/Image.types.ts b/node_modules/expo-image/src/Image.types.ts -index 63445be..c67ad0c 100644 +index 0b4e7a5..efbe5ee 100644 --- a/node_modules/expo-image/src/Image.types.ts +++ b/node_modules/expo-image/src/Image.types.ts -@@ -51,6 +51,16 @@ export type ImageSource = { +@@ -50,6 +50,16 @@ export type ImageSource = { * If not provided, the `uri` is used also as the cache key. */ cacheKey?: string; diff --git a/patches/expo-modules-core+2.2.3.patch b/patches/expo-modules-core+2.5.0.patch similarity index 100% rename from patches/expo-modules-core+2.2.3.patch rename to patches/expo-modules-core+2.5.0.patch