@sendbird/uikit-react-native 3.11.1 → 3.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +0 -3
  2. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  3. package/lib/commonjs/libs/InternalLocalCacheStorage.js +6 -1
  4. package/lib/commonjs/libs/InternalLocalCacheStorage.js.map +1 -1
  5. package/lib/commonjs/platform/createFileService.expo.js +3 -3
  6. package/lib/commonjs/platform/createFileService.expo.js.map +1 -1
  7. package/lib/commonjs/platform/createMediaService.expo.js +1 -1
  8. package/lib/commonjs/platform/createMediaService.expo.js.map +1 -1
  9. package/lib/commonjs/platform/createNotificationService.native.js +31 -6
  10. package/lib/commonjs/platform/createNotificationService.native.js.map +1 -1
  11. package/lib/commonjs/types.js.map +1 -1
  12. package/lib/commonjs/utils/expoBackwardUtils.js +51 -1
  13. package/lib/commonjs/utils/expoBackwardUtils.js.map +1 -1
  14. package/lib/commonjs/version.js +1 -1
  15. package/lib/commonjs/version.js.map +1 -1
  16. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +0 -3
  17. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  18. package/lib/module/libs/InternalLocalCacheStorage.js +6 -1
  19. package/lib/module/libs/InternalLocalCacheStorage.js.map +1 -1
  20. package/lib/module/platform/createFileService.expo.js +3 -3
  21. package/lib/module/platform/createFileService.expo.js.map +1 -1
  22. package/lib/module/platform/createMediaService.expo.js +1 -1
  23. package/lib/module/platform/createMediaService.expo.js.map +1 -1
  24. package/lib/module/platform/createNotificationService.native.js +32 -6
  25. package/lib/module/platform/createNotificationService.native.js.map +1 -1
  26. package/lib/module/types.js.map +1 -1
  27. package/lib/module/utils/expoBackwardUtils.js +52 -1
  28. package/lib/module/utils/expoBackwardUtils.js.map +1 -1
  29. package/lib/module/version.js +1 -1
  30. package/lib/module/version.js.map +1 -1
  31. package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +1 -1
  32. package/lib/typescript/src/domain/openChannel/component/OpenChannelHeader.d.ts +1 -1
  33. package/lib/typescript/src/hooks/useChannelInputItems.d.ts +1 -1
  34. package/lib/typescript/src/platform/createNotificationService.native.d.ts +13 -1
  35. package/lib/typescript/src/types.d.ts +4 -1
  36. package/lib/typescript/src/utils/expoBackwardUtils.d.ts +36 -0
  37. package/lib/typescript/src/version.d.ts +1 -1
  38. package/package.json +14 -5
  39. package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +0 -3
  40. package/src/libs/InternalLocalCacheStorage.ts +6 -1
  41. package/src/platform/createFileService.expo.ts +5 -3
  42. package/src/platform/createMediaService.expo.tsx +1 -1
  43. package/src/platform/createNotificationService.native.ts +53 -7
  44. package/src/types.ts +5 -1
  45. package/src/utils/expoBackwardUtils.ts +71 -1
  46. package/src/version.ts +1 -1
@@ -1,4 +1,11 @@
1
1
  import normalizeFile from './normalizeFile';
2
+
3
+ // Legacy expo-file-system API types (before SDK 54)
4
+
5
+ // New expo-file-system API types (SDK 54+)
6
+
7
+ // Union type for both legacy and new expo-file-system
8
+
2
9
  const expoBackwardUtils = {
3
10
  imagePicker: {
4
11
  isCanceled(result) {
@@ -96,11 +103,55 @@ const expoBackwardUtils = {
96
103
  }
97
104
  },
98
105
  toFileSize(info) {
99
- if ('size' in info) {
106
+ if ('size' in info && info.size !== undefined) {
100
107
  return info.size;
101
108
  } else {
102
109
  return 0;
103
110
  }
111
+ },
112
+ fileSystem: {
113
+ isLegacyModule(fsModule) {
114
+ try {
115
+ return 'documentDirectory' in fsModule || 'cacheDirectory' in fsModule;
116
+ } catch {
117
+ return false;
118
+ }
119
+ },
120
+ async getFileInfo(fsModule, uri) {
121
+ if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {
122
+ return await fsModule.getInfoAsync(uri);
123
+ } else {
124
+ const file = new fsModule.File(uri);
125
+ return file.info();
126
+ }
127
+ },
128
+ getDocumentDirectory(fsModule) {
129
+ if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {
130
+ return fsModule.documentDirectory || null;
131
+ } else {
132
+ var _fsModule$Paths;
133
+ return ((_fsModule$Paths = fsModule.Paths) === null || _fsModule$Paths === void 0 || (_fsModule$Paths = _fsModule$Paths.document) === null || _fsModule$Paths === void 0 ? void 0 : _fsModule$Paths.uri) || null;
134
+ }
135
+ },
136
+ getCacheDirectory(fsModule) {
137
+ if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {
138
+ return fsModule.cacheDirectory || null;
139
+ } else {
140
+ var _fsModule$Paths2;
141
+ return ((_fsModule$Paths2 = fsModule.Paths) === null || _fsModule$Paths2 === void 0 || (_fsModule$Paths2 = _fsModule$Paths2.cache) === null || _fsModule$Paths2 === void 0 ? void 0 : _fsModule$Paths2.uri) || null;
142
+ }
143
+ },
144
+ async downloadFile(fsModule, url, localUri) {
145
+ if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {
146
+ return await fsModule.downloadAsync(url, localUri);
147
+ } else {
148
+ const destination = new fsModule.File(localUri);
149
+ const result = await fsModule.File.downloadFileAsync(url, destination);
150
+ return {
151
+ uri: result.uri
152
+ };
153
+ }
154
+ }
104
155
  }
105
156
  };
106
157
  export default expoBackwardUtils;
@@ -1 +1 @@
1
- {"version":3,"names":["normalizeFile","expoBackwardUtils","imagePicker","isCanceled","result","canceled","cancelled","toFilePickerResponses","fsModule","assets","promises","map","fileName","name","fileSize","size","type","uri","Promise","all","fileInfo","getInfoAsync","response","toFileSize","documentPicker","mimeType","expoAV","isLegacyAVModule","module","Video","isAudioModule","useAudioRecorder","isVideoModule","useVideoPlayer","info"],"sources":["expoBackwardUtils.ts"],"sourcesContent":["import type * as ExpoAudio from 'expo-audio';\nimport type * as ExpoAV from 'expo-av';\nimport type * as ExpoDocumentPicker from 'expo-document-picker';\nimport type * as ExpoFs from 'expo-file-system';\nimport type * as ExpoImagePicker from 'expo-image-picker';\nimport type * as ExpoVideo from 'expo-video';\n\nimport type { FilePickerResponse } from '../platform/types';\nimport normalizeFile from './normalizeFile';\n\nconst expoBackwardUtils = {\n imagePicker: {\n isCanceled(result: ExpoImagePicker.ImagePickerResult) {\n // @ts-expect-error backward compatibility\n return result.canceled ?? result.cancelled;\n },\n async toFilePickerResponses(\n result: ExpoImagePicker.ImagePickerResult,\n fsModule: typeof ExpoFs,\n ): Promise<FilePickerResponse[]> {\n if (result.assets) {\n const assets = result.assets || [];\n const promises = assets.map(({ fileName: name, fileSize: size, type, uri }) =>\n normalizeFile({ uri, size, name, type }),\n );\n\n return Promise.all(promises);\n } else if ('uri' in result && typeof result.uri === 'string') {\n const fileInfo = await fsModule.getInfoAsync(result.uri);\n const response = await normalizeFile({ uri: result.uri, size: expoBackwardUtils.toFileSize(fileInfo) });\n return [response];\n } else {\n return [];\n }\n },\n },\n documentPicker: {\n isCanceled(result: ExpoDocumentPicker.DocumentPickerResult) {\n // @ts-expect-error backward compatibility\n return result.canceled ?? result.type === 'cancel';\n },\n async toFilePickerResponses(result: ExpoDocumentPicker.DocumentPickerResult): Promise<FilePickerResponse[]> {\n if (result.assets) {\n const assets = result.assets || [];\n const promises = assets.map(({ name, size, mimeType, uri }) =>\n normalizeFile({ uri, size, name, type: mimeType }),\n );\n\n return Promise.all(promises);\n } else if ('uri' in result && typeof result.uri === 'string') {\n // @ts-expect-error backward compatibility\n const { mimeType, uri, size, name } = result;\n const response = await normalizeFile({ uri, size, name, type: mimeType });\n\n return [response];\n } else {\n return [];\n }\n },\n },\n expoAV: {\n isLegacyAVModule(module: ExpoAudioModule | ExpoVideoModule): module is typeof ExpoAV {\n try {\n return 'Video' in module && 'Audio' in module && typeof module.Video === 'function';\n } catch {\n return false;\n }\n },\n isAudioModule(module: ExpoAudioModule): module is typeof ExpoAudio {\n try {\n return 'useAudioRecorder' in module && typeof module.useAudioRecorder === 'function';\n } catch {\n return false;\n }\n },\n isVideoModule(module: ExpoVideoModule): module is typeof ExpoVideo {\n try {\n return 'VideoView' in module && 'useVideoPlayer' in module && typeof module.useVideoPlayer === 'function';\n } catch {\n return false;\n }\n },\n },\n toFileSize(info: ExpoFs.FileInfo) {\n if ('size' in info) {\n return info.size;\n } else {\n return 0;\n }\n },\n};\n\nexport type ExpoAudioModule = typeof ExpoAV | typeof ExpoAudio;\nexport type ExpoVideoModule = typeof ExpoAV | typeof ExpoVideo;\n\nexport default expoBackwardUtils;\n"],"mappings":"AAQA,OAAOA,aAAa,MAAM,iBAAiB;AAE3C,MAAMC,iBAAiB,GAAG;EACxBC,WAAW,EAAE;IACXC,UAAUA,CAACC,MAAyC,EAAE;MACpD;MACA,OAAOA,MAAM,CAACC,QAAQ,IAAID,MAAM,CAACE,SAAS;IAC5C,CAAC;IACD,MAAMC,qBAAqBA,CACzBH,MAAyC,EACzCI,QAAuB,EACQ;MAC/B,IAAIJ,MAAM,CAACK,MAAM,EAAE;QACjB,MAAMA,MAAM,GAAGL,MAAM,CAACK,MAAM,IAAI,EAAE;QAClC,MAAMC,QAAQ,GAAGD,MAAM,CAACE,GAAG,CAAC,CAAC;UAAEC,QAAQ,EAAEC,IAAI;UAAEC,QAAQ,EAAEC,IAAI;UAAEC,IAAI;UAAEC;QAAI,CAAC,KACxEjB,aAAa,CAAC;UAAEiB,GAAG;UAAEF,IAAI;UAAEF,IAAI;UAAEG;QAAK,CAAC,CACzC,CAAC;QAED,OAAOE,OAAO,CAACC,GAAG,CAACT,QAAQ,CAAC;MAC9B,CAAC,MAAM,IAAI,KAAK,IAAIN,MAAM,IAAI,OAAOA,MAAM,CAACa,GAAG,KAAK,QAAQ,EAAE;QAC5D,MAAMG,QAAQ,GAAG,MAAMZ,QAAQ,CAACa,YAAY,CAACjB,MAAM,CAACa,GAAG,CAAC;QACxD,MAAMK,QAAQ,GAAG,MAAMtB,aAAa,CAAC;UAAEiB,GAAG,EAAEb,MAAM,CAACa,GAAG;UAAEF,IAAI,EAAEd,iBAAiB,CAACsB,UAAU,CAACH,QAAQ;QAAE,CAAC,CAAC;QACvG,OAAO,CAACE,QAAQ,CAAC;MACnB,CAAC,MAAM;QACL,OAAO,EAAE;MACX;IACF;EACF,CAAC;EACDE,cAAc,EAAE;IACdrB,UAAUA,CAACC,MAA+C,EAAE;MAC1D;MACA,OAAOA,MAAM,CAACC,QAAQ,IAAID,MAAM,CAACY,IAAI,KAAK,QAAQ;IACpD,CAAC;IACD,MAAMT,qBAAqBA,CAACH,MAA+C,EAAiC;MAC1G,IAAIA,MAAM,CAACK,MAAM,EAAE;QACjB,MAAMA,MAAM,GAAGL,MAAM,CAACK,MAAM,IAAI,EAAE;QAClC,MAAMC,QAAQ,GAAGD,MAAM,CAACE,GAAG,CAAC,CAAC;UAAEE,IAAI;UAAEE,IAAI;UAAEU,QAAQ;UAAER;QAAI,CAAC,KACxDjB,aAAa,CAAC;UAAEiB,GAAG;UAAEF,IAAI;UAAEF,IAAI;UAAEG,IAAI,EAAES;QAAS,CAAC,CACnD,CAAC;QAED,OAAOP,OAAO,CAACC,GAAG,CAACT,QAAQ,CAAC;MAC9B,CAAC,MAAM,IAAI,KAAK,IAAIN,MAAM,IAAI,OAAOA,MAAM,CAACa,GAAG,KAAK,QAAQ,EAAE;QAC5D;QACA,MAAM;UAAEQ,QAAQ;UAAER,GAAG;UAAEF,IAAI;UAAEF;QAAK,CAAC,GAAGT,MAAM;QAC5C,MAAMkB,QAAQ,GAAG,MAAMtB,aAAa,CAAC;UAAEiB,GAAG;UAAEF,IAAI;UAAEF,IAAI;UAAEG,IAAI,EAAES;QAAS,CAAC,CAAC;QAEzE,OAAO,CAACH,QAAQ,CAAC;MACnB,CAAC,MAAM;QACL,OAAO,EAAE;MACX;IACF;EACF,CAAC;EACDI,MAAM,EAAE;IACNC,gBAAgBA,CAACC,MAAyC,EAA2B;MACnF,IAAI;QACF,OAAO,OAAO,IAAIA,MAAM,IAAI,OAAO,IAAIA,MAAM,IAAI,OAAOA,MAAM,CAACC,KAAK,KAAK,UAAU;MACrF,CAAC,CAAC,MAAM;QACN,OAAO,KAAK;MACd;IACF,CAAC;IACDC,aAAaA,CAACF,MAAuB,EAA8B;MACjE,IAAI;QACF,OAAO,kBAAkB,IAAIA,MAAM,IAAI,OAAOA,MAAM,CAACG,gBAAgB,KAAK,UAAU;MACtF,CAAC,CAAC,MAAM;QACN,OAAO,KAAK;MACd;IACF,CAAC;IACDC,aAAaA,CAACJ,MAAuB,EAA8B;MACjE,IAAI;QACF,OAAO,WAAW,IAAIA,MAAM,IAAI,gBAAgB,IAAIA,MAAM,IAAI,OAAOA,MAAM,CAACK,cAAc,KAAK,UAAU;MAC3G,CAAC,CAAC,MAAM;QACN,OAAO,KAAK;MACd;IACF;EACF,CAAC;EACDV,UAAUA,CAACW,IAAqB,EAAE;IAChC,IAAI,MAAM,IAAIA,IAAI,EAAE;MAClB,OAAOA,IAAI,CAACnB,IAAI;IAClB,CAAC,MAAM;MACL,OAAO,CAAC;IACV;EACF;AACF,CAAC;AAKD,eAAed,iBAAiB","ignoreList":[]}
1
+ {"version":3,"names":["normalizeFile","expoBackwardUtils","imagePicker","isCanceled","result","canceled","cancelled","toFilePickerResponses","fsModule","assets","promises","map","fileName","name","fileSize","size","type","uri","Promise","all","fileInfo","getInfoAsync","response","toFileSize","documentPicker","mimeType","expoAV","isLegacyAVModule","module","Video","isAudioModule","useAudioRecorder","isVideoModule","useVideoPlayer","info","undefined","fileSystem","isLegacyModule","getFileInfo","file","File","getDocumentDirectory","documentDirectory","_fsModule$Paths","Paths","document","getCacheDirectory","cacheDirectory","_fsModule$Paths2","cache","downloadFile","url","localUri","downloadAsync","destination","downloadFileAsync"],"sources":["expoBackwardUtils.ts"],"sourcesContent":["import type * as ExpoAudio from 'expo-audio';\nimport type * as ExpoAV from 'expo-av';\nimport type * as ExpoDocumentPicker from 'expo-document-picker';\nimport type * as ExpoFs from 'expo-file-system';\nimport type * as ExpoImagePicker from 'expo-image-picker';\nimport type * as ExpoVideo from 'expo-video';\n\nimport type { FilePickerResponse } from '../platform/types';\nimport normalizeFile from './normalizeFile';\n\n// Legacy expo-file-system API types (before SDK 54)\ninterface ExpoFileSystemLegacy {\n documentDirectory: string | null;\n cacheDirectory: string | null;\n getInfoAsync(fileUri: string, options?: unknown): Promise<ExpoFs.FileInfo>;\n downloadAsync(uri: string, fileUri: string, options?: unknown): Promise<{ uri: string }>;\n}\n\n// New expo-file-system API types (SDK 54+)\ninterface ExpoDirectory {\n uri: string;\n}\n\ninterface ExpoFileSystemNew {\n File: {\n new (...uris: (string | unknown)[]): {\n info(options?: unknown): ExpoFs.FileInfo;\n };\n downloadFileAsync(url: string, destination: unknown, options?: unknown): Promise<{ uri: string }>;\n };\n Directory: new (...uris: (string | unknown)[]) => ExpoDirectory;\n Paths: {\n document: ExpoDirectory;\n cache: ExpoDirectory;\n };\n}\n\n// Union type for both legacy and new expo-file-system\ntype ExpoFileSystemModule = ExpoFileSystemLegacy | ExpoFileSystemNew | typeof ExpoFs;\n\nconst expoBackwardUtils = {\n imagePicker: {\n isCanceled(result: ExpoImagePicker.ImagePickerResult) {\n // @ts-expect-error backward compatibility\n return result.canceled ?? result.cancelled;\n },\n async toFilePickerResponses(\n result: ExpoImagePicker.ImagePickerResult,\n fsModule: typeof ExpoFs,\n ): Promise<FilePickerResponse[]> {\n if (result.assets) {\n const assets = result.assets || [];\n const promises = assets.map(({ fileName: name, fileSize: size, type, uri }) =>\n normalizeFile({ uri, size, name, type }),\n );\n\n return Promise.all(promises);\n } else if ('uri' in result && typeof result.uri === 'string') {\n const fileInfo = await fsModule.getInfoAsync(result.uri);\n const response = await normalizeFile({ uri: result.uri, size: expoBackwardUtils.toFileSize(fileInfo) });\n return [response];\n } else {\n return [];\n }\n },\n },\n documentPicker: {\n isCanceled(result: ExpoDocumentPicker.DocumentPickerResult) {\n // @ts-expect-error backward compatibility\n return result.canceled ?? result.type === 'cancel';\n },\n async toFilePickerResponses(result: ExpoDocumentPicker.DocumentPickerResult): Promise<FilePickerResponse[]> {\n if (result.assets) {\n const assets = result.assets || [];\n const promises = assets.map(({ name, size, mimeType, uri }) =>\n normalizeFile({ uri, size, name, type: mimeType }),\n );\n\n return Promise.all(promises);\n } else if ('uri' in result && typeof result.uri === 'string') {\n // @ts-expect-error backward compatibility\n const { mimeType, uri, size, name } = result;\n const response = await normalizeFile({ uri, size, name, type: mimeType });\n\n return [response];\n } else {\n return [];\n }\n },\n },\n expoAV: {\n isLegacyAVModule(module: ExpoAudioModule | ExpoVideoModule): module is typeof ExpoAV {\n try {\n return 'Video' in module && 'Audio' in module && typeof module.Video === 'function';\n } catch {\n return false;\n }\n },\n isAudioModule(module: ExpoAudioModule): module is typeof ExpoAudio {\n try {\n return 'useAudioRecorder' in module && typeof module.useAudioRecorder === 'function';\n } catch {\n return false;\n }\n },\n isVideoModule(module: ExpoVideoModule): module is typeof ExpoVideo {\n try {\n return 'VideoView' in module && 'useVideoPlayer' in module && typeof module.useVideoPlayer === 'function';\n } catch {\n return false;\n }\n },\n },\n toFileSize(info: ExpoFs.FileInfo) {\n if ('size' in info && info.size !== undefined) {\n return info.size;\n } else {\n return 0;\n }\n },\n fileSystem: {\n isLegacyModule(fsModule: ExpoFileSystemModule): fsModule is ExpoFileSystemLegacy {\n try {\n return 'documentDirectory' in fsModule || 'cacheDirectory' in fsModule;\n } catch {\n return false;\n }\n },\n async getFileInfo(fsModule: ExpoFileSystemModule, uri: string): Promise<ExpoFs.FileInfo> {\n if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {\n return await fsModule.getInfoAsync(uri);\n } else {\n const file = new fsModule.File(uri);\n return file.info();\n }\n },\n getDocumentDirectory(fsModule: ExpoFileSystemModule): string | null {\n if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {\n return fsModule.documentDirectory || null;\n } else {\n return fsModule.Paths?.document?.uri || null;\n }\n },\n getCacheDirectory(fsModule: ExpoFileSystemModule): string | null {\n if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {\n return fsModule.cacheDirectory || null;\n } else {\n return fsModule.Paths?.cache?.uri || null;\n }\n },\n async downloadFile(fsModule: ExpoFileSystemModule, url: string, localUri: string): Promise<{ uri: string }> {\n if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {\n return await fsModule.downloadAsync(url, localUri);\n } else {\n const destination = new fsModule.File(localUri);\n const result = await fsModule.File.downloadFileAsync(url, destination as never);\n return { uri: result.uri };\n }\n },\n },\n};\n\nexport type ExpoAudioModule = typeof ExpoAV | typeof ExpoAudio;\nexport type ExpoVideoModule = typeof ExpoAV | typeof ExpoVideo;\n\nexport default expoBackwardUtils;\n"],"mappings":"AAQA,OAAOA,aAAa,MAAM,iBAAiB;;AAE3C;;AAQA;;AAmBA;;AAGA,MAAMC,iBAAiB,GAAG;EACxBC,WAAW,EAAE;IACXC,UAAUA,CAACC,MAAyC,EAAE;MACpD;MACA,OAAOA,MAAM,CAACC,QAAQ,IAAID,MAAM,CAACE,SAAS;IAC5C,CAAC;IACD,MAAMC,qBAAqBA,CACzBH,MAAyC,EACzCI,QAAuB,EACQ;MAC/B,IAAIJ,MAAM,CAACK,MAAM,EAAE;QACjB,MAAMA,MAAM,GAAGL,MAAM,CAACK,MAAM,IAAI,EAAE;QAClC,MAAMC,QAAQ,GAAGD,MAAM,CAACE,GAAG,CAAC,CAAC;UAAEC,QAAQ,EAAEC,IAAI;UAAEC,QAAQ,EAAEC,IAAI;UAAEC,IAAI;UAAEC;QAAI,CAAC,KACxEjB,aAAa,CAAC;UAAEiB,GAAG;UAAEF,IAAI;UAAEF,IAAI;UAAEG;QAAK,CAAC,CACzC,CAAC;QAED,OAAOE,OAAO,CAACC,GAAG,CAACT,QAAQ,CAAC;MAC9B,CAAC,MAAM,IAAI,KAAK,IAAIN,MAAM,IAAI,OAAOA,MAAM,CAACa,GAAG,KAAK,QAAQ,EAAE;QAC5D,MAAMG,QAAQ,GAAG,MAAMZ,QAAQ,CAACa,YAAY,CAACjB,MAAM,CAACa,GAAG,CAAC;QACxD,MAAMK,QAAQ,GAAG,MAAMtB,aAAa,CAAC;UAAEiB,GAAG,EAAEb,MAAM,CAACa,GAAG;UAAEF,IAAI,EAAEd,iBAAiB,CAACsB,UAAU,CAACH,QAAQ;QAAE,CAAC,CAAC;QACvG,OAAO,CAACE,QAAQ,CAAC;MACnB,CAAC,MAAM;QACL,OAAO,EAAE;MACX;IACF;EACF,CAAC;EACDE,cAAc,EAAE;IACdrB,UAAUA,CAACC,MAA+C,EAAE;MAC1D;MACA,OAAOA,MAAM,CAACC,QAAQ,IAAID,MAAM,CAACY,IAAI,KAAK,QAAQ;IACpD,CAAC;IACD,MAAMT,qBAAqBA,CAACH,MAA+C,EAAiC;MAC1G,IAAIA,MAAM,CAACK,MAAM,EAAE;QACjB,MAAMA,MAAM,GAAGL,MAAM,CAACK,MAAM,IAAI,EAAE;QAClC,MAAMC,QAAQ,GAAGD,MAAM,CAACE,GAAG,CAAC,CAAC;UAAEE,IAAI;UAAEE,IAAI;UAAEU,QAAQ;UAAER;QAAI,CAAC,KACxDjB,aAAa,CAAC;UAAEiB,GAAG;UAAEF,IAAI;UAAEF,IAAI;UAAEG,IAAI,EAAES;QAAS,CAAC,CACnD,CAAC;QAED,OAAOP,OAAO,CAACC,GAAG,CAACT,QAAQ,CAAC;MAC9B,CAAC,MAAM,IAAI,KAAK,IAAIN,MAAM,IAAI,OAAOA,MAAM,CAACa,GAAG,KAAK,QAAQ,EAAE;QAC5D;QACA,MAAM;UAAEQ,QAAQ;UAAER,GAAG;UAAEF,IAAI;UAAEF;QAAK,CAAC,GAAGT,MAAM;QAC5C,MAAMkB,QAAQ,GAAG,MAAMtB,aAAa,CAAC;UAAEiB,GAAG;UAAEF,IAAI;UAAEF,IAAI;UAAEG,IAAI,EAAES;QAAS,CAAC,CAAC;QAEzE,OAAO,CAACH,QAAQ,CAAC;MACnB,CAAC,MAAM;QACL,OAAO,EAAE;MACX;IACF;EACF,CAAC;EACDI,MAAM,EAAE;IACNC,gBAAgBA,CAACC,MAAyC,EAA2B;MACnF,IAAI;QACF,OAAO,OAAO,IAAIA,MAAM,IAAI,OAAO,IAAIA,MAAM,IAAI,OAAOA,MAAM,CAACC,KAAK,KAAK,UAAU;MACrF,CAAC,CAAC,MAAM;QACN,OAAO,KAAK;MACd;IACF,CAAC;IACDC,aAAaA,CAACF,MAAuB,EAA8B;MACjE,IAAI;QACF,OAAO,kBAAkB,IAAIA,MAAM,IAAI,OAAOA,MAAM,CAACG,gBAAgB,KAAK,UAAU;MACtF,CAAC,CAAC,MAAM;QACN,OAAO,KAAK;MACd;IACF,CAAC;IACDC,aAAaA,CAACJ,MAAuB,EAA8B;MACjE,IAAI;QACF,OAAO,WAAW,IAAIA,MAAM,IAAI,gBAAgB,IAAIA,MAAM,IAAI,OAAOA,MAAM,CAACK,cAAc,KAAK,UAAU;MAC3G,CAAC,CAAC,MAAM;QACN,OAAO,KAAK;MACd;IACF;EACF,CAAC;EACDV,UAAUA,CAACW,IAAqB,EAAE;IAChC,IAAI,MAAM,IAAIA,IAAI,IAAIA,IAAI,CAACnB,IAAI,KAAKoB,SAAS,EAAE;MAC7C,OAAOD,IAAI,CAACnB,IAAI;IAClB,CAAC,MAAM;MACL,OAAO,CAAC;IACV;EACF,CAAC;EACDqB,UAAU,EAAE;IACVC,cAAcA,CAAC7B,QAA8B,EAAoC;MAC/E,IAAI;QACF,OAAO,mBAAmB,IAAIA,QAAQ,IAAI,gBAAgB,IAAIA,QAAQ;MACxE,CAAC,CAAC,MAAM;QACN,OAAO,KAAK;MACd;IACF,CAAC;IACD,MAAM8B,WAAWA,CAAC9B,QAA8B,EAAES,GAAW,EAA4B;MACvF,IAAIhB,iBAAiB,CAACmC,UAAU,CAACC,cAAc,CAAC7B,QAAQ,CAAC,EAAE;QACzD,OAAO,MAAMA,QAAQ,CAACa,YAAY,CAACJ,GAAG,CAAC;MACzC,CAAC,MAAM;QACL,MAAMsB,IAAI,GAAG,IAAI/B,QAAQ,CAACgC,IAAI,CAACvB,GAAG,CAAC;QACnC,OAAOsB,IAAI,CAACL,IAAI,CAAC,CAAC;MACpB;IACF,CAAC;IACDO,oBAAoBA,CAACjC,QAA8B,EAAiB;MAClE,IAAIP,iBAAiB,CAACmC,UAAU,CAACC,cAAc,CAAC7B,QAAQ,CAAC,EAAE;QACzD,OAAOA,QAAQ,CAACkC,iBAAiB,IAAI,IAAI;MAC3C,CAAC,MAAM;QAAA,IAAAC,eAAA;QACL,OAAO,EAAAA,eAAA,GAAAnC,QAAQ,CAACoC,KAAK,cAAAD,eAAA,gBAAAA,eAAA,GAAdA,eAAA,CAAgBE,QAAQ,cAAAF,eAAA,uBAAxBA,eAAA,CAA0B1B,GAAG,KAAI,IAAI;MAC9C;IACF,CAAC;IACD6B,iBAAiBA,CAACtC,QAA8B,EAAiB;MAC/D,IAAIP,iBAAiB,CAACmC,UAAU,CAACC,cAAc,CAAC7B,QAAQ,CAAC,EAAE;QACzD,OAAOA,QAAQ,CAACuC,cAAc,IAAI,IAAI;MACxC,CAAC,MAAM;QAAA,IAAAC,gBAAA;QACL,OAAO,EAAAA,gBAAA,GAAAxC,QAAQ,CAACoC,KAAK,cAAAI,gBAAA,gBAAAA,gBAAA,GAAdA,gBAAA,CAAgBC,KAAK,cAAAD,gBAAA,uBAArBA,gBAAA,CAAuB/B,GAAG,KAAI,IAAI;MAC3C;IACF,CAAC;IACD,MAAMiC,YAAYA,CAAC1C,QAA8B,EAAE2C,GAAW,EAAEC,QAAgB,EAA4B;MAC1G,IAAInD,iBAAiB,CAACmC,UAAU,CAACC,cAAc,CAAC7B,QAAQ,CAAC,EAAE;QACzD,OAAO,MAAMA,QAAQ,CAAC6C,aAAa,CAACF,GAAG,EAAEC,QAAQ,CAAC;MACpD,CAAC,MAAM;QACL,MAAME,WAAW,GAAG,IAAI9C,QAAQ,CAACgC,IAAI,CAACY,QAAQ,CAAC;QAC/C,MAAMhD,MAAM,GAAG,MAAMI,QAAQ,CAACgC,IAAI,CAACe,iBAAiB,CAACJ,GAAG,EAAEG,WAAoB,CAAC;QAC/E,OAAO;UAAErC,GAAG,EAAEb,MAAM,CAACa;QAAI,CAAC;MAC5B;IACF;EACF;AACF,CAAC;AAKD,eAAehB,iBAAiB","ignoreList":[]}
@@ -1,3 +1,3 @@
1
- const VERSION = '3.11.1';
1
+ const VERSION = '3.11.3';
2
2
  export default VERSION;
3
3
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["VERSION"],"sources":["version.ts"],"sourcesContent":["const VERSION = '3.11.1';\nexport default VERSION;\n"],"mappings":"AAAA,MAAMA,OAAO,GAAG,QAAQ;AACxB,eAAeA,OAAO","ignoreList":[]}
1
+ {"version":3,"names":["VERSION"],"sources":["version.ts"],"sourcesContent":["const VERSION = '3.11.3';\nexport default VERSION;\n"],"mappings":"AAAA,MAAMA,OAAO,GAAG,QAAQ;AACxB,eAAeA,OAAO","ignoreList":[]}
@@ -14,7 +14,7 @@ import type { StringSet } from '../localization/StringSet.type';
14
14
  import type { ClipboardServiceInterface, FileServiceInterface, MediaServiceInterface, NotificationServiceInterface, PlayerServiceInterface, RecorderServiceInterface } from '../platform/types';
15
15
  import { ErrorBoundaryProps, LocalCacheStorage } from '../types';
16
16
  export declare const SendbirdUIKit: Readonly<{
17
- VERSION: "3.11.1";
17
+ VERSION: "3.11.3";
18
18
  PLATFORM: string;
19
19
  DEFAULT: {
20
20
  AUTO_PUSH_TOKEN_REGISTRATION: boolean;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  declare const _default: React.MemoExoticComponent<({ onPressHeaderLeft, onPressHeaderRight, rightIconName }: {
3
- rightIconName: "search" | "stop" | "photo" | "recording" | "delete" | "message" | "done" | "user" | "add" | "chat-hide" | "chat-show" | "archive" | "arrow-left" | "audio-off-filled" | "audio-off" | "audio-on-filled" | "audio-on" | "ban" | "broadcast" | "camera" | "channels" | "chat-filled" | "chat" | "checkbox-off" | "checkbox-on" | "chevron-down" | "chevron-right" | "close" | "copy" | "create" | "document" | "done-all" | "download" | "edit" | "emoji-more" | "error" | "file-audio" | "file-document" | "freeze" | "gif" | "info" | "leave" | "mark-as-unread" | "members" | "moderation" | "more" | "mute" | "notifications-filled" | "notifications-off-filled" | "notifications" | "operator" | "pause" | "play" | "plus" | "question" | "radio-off" | "radio-on" | "refresh" | "remove" | "reply-filled" | "reply" | "send" | "settings-filled" | "spinner" | "streaming" | "supergroup" | "theme" | "thread" | "thumbnail-none" | "unarchive";
3
+ rightIconName: "search" | "stop" | "photo" | "recording" | "delete" | "remove" | "message" | "done" | "user" | "add" | "chat-hide" | "chat-show" | "archive" | "arrow-left" | "audio-off-filled" | "audio-off" | "audio-on-filled" | "audio-on" | "ban" | "broadcast" | "camera" | "channels" | "chat-filled" | "chat" | "checkbox-off" | "checkbox-on" | "chevron-down" | "chevron-right" | "close" | "copy" | "create" | "document" | "done-all" | "download" | "edit" | "emoji-more" | "error" | "file-audio" | "file-document" | "freeze" | "gif" | "info" | "leave" | "mark-as-unread" | "members" | "moderation" | "more" | "mute" | "notifications-filled" | "notifications-off-filled" | "notifications" | "operator" | "pause" | "play" | "plus" | "question" | "radio-off" | "radio-on" | "refresh" | "reply-filled" | "reply" | "send" | "settings-filled" | "spinner" | "streaming" | "supergroup" | "theme" | "thread" | "thumbnail-none" | "unarchive";
4
4
  onPressHeaderLeft: () => void;
5
5
  onPressHeaderRight: () => void;
6
6
  }) => React.JSX.Element>;
@@ -1,7 +1,7 @@
1
1
  import { SendbirdChannel } from '@sendbird/uikit-utils';
2
2
  import { FileType } from '../platform/types';
3
3
  export declare const useChannelInputItems: (channel: SendbirdChannel, sendFileMessage: (file: FileType) => void) => {
4
- icon?: "search" | "stop" | "photo" | "recording" | "delete" | "message" | "done" | "user" | "add" | "chat-hide" | "chat-show" | "archive" | "arrow-left" | "audio-off-filled" | "audio-off" | "audio-on-filled" | "audio-on" | "ban" | "broadcast" | "camera" | "channels" | "chat-filled" | "chat" | "checkbox-off" | "checkbox-on" | "chevron-down" | "chevron-right" | "close" | "copy" | "create" | "document" | "done-all" | "download" | "edit" | "emoji-more" | "error" | "file-audio" | "file-document" | "freeze" | "gif" | "info" | "leave" | "mark-as-unread" | "members" | "moderation" | "more" | "mute" | "notifications-filled" | "notifications-off-filled" | "notifications" | "operator" | "pause" | "play" | "plus" | "question" | "radio-off" | "radio-on" | "refresh" | "remove" | "reply-filled" | "reply" | "send" | "settings-filled" | "spinner" | "streaming" | "supergroup" | "theme" | "thread" | "thumbnail-none" | "unarchive" | undefined;
4
+ icon?: "search" | "stop" | "photo" | "recording" | "delete" | "remove" | "message" | "done" | "user" | "add" | "chat-hide" | "chat-show" | "archive" | "arrow-left" | "audio-off-filled" | "audio-off" | "audio-on-filled" | "audio-on" | "ban" | "broadcast" | "camera" | "channels" | "chat-filled" | "chat" | "checkbox-off" | "checkbox-on" | "chevron-down" | "chevron-right" | "close" | "copy" | "create" | "document" | "done-all" | "download" | "edit" | "emoji-more" | "error" | "file-audio" | "file-document" | "freeze" | "gif" | "info" | "leave" | "mark-as-unread" | "members" | "moderation" | "more" | "mute" | "notifications-filled" | "notifications-off-filled" | "notifications" | "operator" | "pause" | "play" | "plus" | "question" | "radio-off" | "radio-on" | "refresh" | "reply-filled" | "reply" | "send" | "settings-filled" | "spinner" | "streaming" | "supergroup" | "theme" | "thread" | "thumbnail-none" | "unarchive" | undefined;
5
5
  iconColor?: string | undefined;
6
6
  title: string;
7
7
  titleColor?: string | undefined;
@@ -1,8 +1,20 @@
1
1
  import type RNFBMessaging from '@react-native-firebase/messaging';
2
+ import type { FirebaseMessagingTypes } from '@react-native-firebase/messaging';
2
3
  import type * as Permissions from 'react-native-permissions';
3
4
  import type { NotificationServiceInterface } from './types';
5
+ type MessagingInstance = ReturnType<typeof RNFBMessaging>;
6
+ type ModularMessagingType = {
7
+ getMessaging: () => MessagingInstance;
8
+ getAPNSToken: (messaging: MessagingInstance) => Promise<string | null>;
9
+ getToken: (messaging: MessagingInstance) => Promise<string>;
10
+ hasPermission: (messaging: MessagingInstance) => Promise<FirebaseMessagingTypes.AuthorizationStatus>;
11
+ requestPermission: (messaging: MessagingInstance, iosPermissions?: FirebaseMessagingTypes.IOSPermissions) => Promise<FirebaseMessagingTypes.AuthorizationStatus>;
12
+ onTokenRefresh: (messaging: MessagingInstance, listener: (token: string) => void) => () => void;
13
+ AuthorizationStatus: typeof RNFBMessaging.AuthorizationStatus;
14
+ };
15
+ type FirebaseMessagingModule = typeof RNFBMessaging | ModularMessagingType;
4
16
  declare const createNativeNotificationService: ({ messagingModule, permissionModule, }: {
5
- messagingModule: typeof RNFBMessaging;
17
+ messagingModule: FirebaseMessagingModule;
6
18
  permissionModule: typeof Permissions;
7
19
  }) => NotificationServiceInterface;
8
20
  export default createNativeNotificationService;
@@ -13,7 +13,10 @@ export interface AsyncLocalCacheStorage {
13
13
  multiGet?(keys: string[]): Promise<readonly KeyValuePairGet[] | KeyValuePairGet[]>;
14
14
  multiRemove?(keys: string[]): Promise<void>;
15
15
  }
16
- export type MMKVLocalCacheStorage = Pick<MMKV, 'getString' | 'set' | 'delete' | 'getAllKeys'>;
16
+ export type MMKVLocalCacheStorage = Pick<MMKV, 'getString' | 'set' | 'getAllKeys'> & {
17
+ delete?: (key: string) => void;
18
+ remove?: (key: string) => void;
19
+ };
17
20
  export type ErrorBoundaryProps = {
18
21
  error: Error;
19
22
  errorInfo: ErrorInfo;
@@ -5,6 +5,33 @@ import type * as ExpoFs from 'expo-file-system';
5
5
  import type * as ExpoImagePicker from 'expo-image-picker';
6
6
  import type * as ExpoVideo from 'expo-video';
7
7
  import type { FilePickerResponse } from '../platform/types';
8
+ interface ExpoFileSystemLegacy {
9
+ documentDirectory: string | null;
10
+ cacheDirectory: string | null;
11
+ getInfoAsync(fileUri: string, options?: unknown): Promise<ExpoFs.FileInfo>;
12
+ downloadAsync(uri: string, fileUri: string, options?: unknown): Promise<{
13
+ uri: string;
14
+ }>;
15
+ }
16
+ interface ExpoDirectory {
17
+ uri: string;
18
+ }
19
+ interface ExpoFileSystemNew {
20
+ File: {
21
+ new (...uris: (string | unknown)[]): {
22
+ info(options?: unknown): ExpoFs.FileInfo;
23
+ };
24
+ downloadFileAsync(url: string, destination: unknown, options?: unknown): Promise<{
25
+ uri: string;
26
+ }>;
27
+ };
28
+ Directory: new (...uris: (string | unknown)[]) => ExpoDirectory;
29
+ Paths: {
30
+ document: ExpoDirectory;
31
+ cache: ExpoDirectory;
32
+ };
33
+ }
34
+ type ExpoFileSystemModule = ExpoFileSystemLegacy | ExpoFileSystemNew | typeof ExpoFs;
8
35
  declare const expoBackwardUtils: {
9
36
  imagePicker: {
10
37
  isCanceled(result: ExpoImagePicker.ImagePickerResult): boolean;
@@ -20,6 +47,15 @@ declare const expoBackwardUtils: {
20
47
  isVideoModule(module: ExpoVideoModule): module is typeof ExpoVideo;
21
48
  };
22
49
  toFileSize(info: ExpoFs.FileInfo): number;
50
+ fileSystem: {
51
+ isLegacyModule(fsModule: ExpoFileSystemModule): fsModule is ExpoFileSystemLegacy;
52
+ getFileInfo(fsModule: ExpoFileSystemModule, uri: string): Promise<ExpoFs.FileInfo>;
53
+ getDocumentDirectory(fsModule: ExpoFileSystemModule): string | null;
54
+ getCacheDirectory(fsModule: ExpoFileSystemModule): string | null;
55
+ downloadFile(fsModule: ExpoFileSystemModule, url: string, localUri: string): Promise<{
56
+ uri: string;
57
+ }>;
58
+ };
23
59
  };
24
60
  export type ExpoAudioModule = typeof ExpoAV | typeof ExpoAudio;
25
61
  export type ExpoVideoModule = typeof ExpoAV | typeof ExpoVideo;
@@ -1,2 +1,2 @@
1
- declare const VERSION = "3.11.1";
1
+ declare const VERSION = "3.11.3";
2
2
  export default VERSION;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendbird/uikit-react-native",
3
- "version": "3.11.1",
3
+ "version": "3.11.3",
4
4
  "description": "Sendbird UIKit for React Native: A feature-rich and customizable chat UI kit with messaging, channel management, and user authentication.",
5
5
  "keywords": [
6
6
  "sendbird",
@@ -25,6 +25,15 @@
25
25
  "types": "lib/typescript/src/index.d.ts",
26
26
  "react-native": "src/index",
27
27
  "source": "src/index",
28
+ "exports": {
29
+ "./package.json": "./package.json",
30
+ ".": {
31
+ "types": "./lib/typescript/src/index.d.ts",
32
+ "react-native": "./src/index.ts",
33
+ "require": "./lib/commonjs/index.js",
34
+ "import": "./lib/module/index.js"
35
+ }
36
+ },
28
37
  "files": [
29
38
  "src",
30
39
  "lib",
@@ -60,10 +69,10 @@
60
69
  },
61
70
  "dependencies": {
62
71
  "@openspacelabs/react-native-zoomable-view": "^2.1.5",
63
- "@sendbird/uikit-chat-hooks": "3.11.1",
64
- "@sendbird/uikit-react-native-foundation": "3.11.1",
72
+ "@sendbird/uikit-chat-hooks": "3.11.3",
73
+ "@sendbird/uikit-react-native-foundation": "3.11.3",
65
74
  "@sendbird/uikit-tools": "0.0.15",
66
- "@sendbird/uikit-utils": "3.11.1"
75
+ "@sendbird/uikit-utils": "3.11.3"
67
76
  },
68
77
  "devDependencies": {
69
78
  "@bam.tech/react-native-image-resizer": "^3.0.4",
@@ -242,5 +251,5 @@
242
251
  ]
243
252
  ]
244
253
  },
245
- "gitHead": "16f1f54e8c442492e79a9591ae32203d5db55c2b"
254
+ "gitHead": "519b9747203c1137ca88ab0ff5421a2b63b7bed3"
246
255
  }
@@ -256,9 +256,6 @@ const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
256
256
  lazyScrollToBottom({ animated: true, timeout: 250 });
257
257
  }
258
258
  },
259
- onChannelChanged(channel) {
260
- if (isDifferentChannel(channel, props.channel)) return;
261
- },
262
259
  });
263
260
 
264
261
  useEffect(() => {
@@ -42,7 +42,12 @@ export default class InternalLocalCacheStorage implements AsyncLocalCacheStorage
42
42
 
43
43
  async removeItem(key: string) {
44
44
  if (this._mmkv) {
45
- this._mmkv.delete(key);
45
+ // Support both v3.x (delete) and v4.x (remove) APIs for backward compatibility
46
+ if (this._mmkv.delete) {
47
+ this._mmkv.delete(key);
48
+ } else if (this._mmkv.remove) {
49
+ this._mmkv.remove(key);
50
+ }
46
51
  } else if (this._async) {
47
52
  return this._async.removeItem(key);
48
53
  }
@@ -145,12 +145,14 @@ const createExpoFileService = ({
145
145
  if (!granted) throw new Error('Permission not granted');
146
146
  }
147
147
 
148
- const basePath = fsModule.documentDirectory || fsModule.cacheDirectory;
148
+ const basePath =
149
+ expoBackwardUtils.fileSystem.getDocumentDirectory(fsModule) ||
150
+ expoBackwardUtils.fileSystem.getCacheDirectory(fsModule);
149
151
  if (!basePath) throw new Error('Cannot determine directory');
150
152
 
151
153
  const downloadPath = `${basePath}/${options.fileName}`;
152
154
 
153
- const response = await fsModule.downloadAsync(options.fileUrl, downloadPath);
155
+ const response = await expoBackwardUtils.fileSystem.downloadFile(fsModule, options.fileUrl, downloadPath);
154
156
  if (getFileType(options.fileType || '').match(/video|image/)) {
155
157
  await mediaLibraryModule.saveToLibraryAsync(response.uri);
156
158
  }
@@ -158,7 +160,7 @@ const createExpoFileService = ({
158
160
  }
159
161
 
160
162
  createRecordFilePath(customExtension = 'm4a'): { recordFilePath: string; uri: string } {
161
- const basePath = fsModule.cacheDirectory;
163
+ const basePath = expoBackwardUtils.fileSystem.getCacheDirectory(fsModule);
162
164
  if (!basePath) throw new Error('Cannot determine directory');
163
165
 
164
166
  const filename = `record-${Date.now()}.${customExtension}`;
@@ -122,7 +122,7 @@ const createExpoMediaService = ({
122
122
  const { uri: compressedURI } = await imageManipulator.manipulateAsync(uri, [{ resize: resizingSize }], {
123
123
  compress: Math.min(Math.max(0, compressionRate), 1),
124
124
  });
125
- const fileInfo = await fsModule.getInfoAsync(uri);
125
+ const fileInfo = await expoBackwardUtils.fileSystem.getFileInfo(fsModule, uri);
126
126
 
127
127
  return { uri: compressedURI, size: expoBackwardUtils.toFileSize(fileInfo) };
128
128
  },
@@ -1,27 +1,64 @@
1
1
  import type RNFBMessaging from '@react-native-firebase/messaging';
2
+ import type { FirebaseMessagingTypes } from '@react-native-firebase/messaging';
2
3
  import { Platform } from 'react-native';
3
4
  import type * as Permissions from 'react-native-permissions';
4
5
 
5
6
  import type { NotificationServiceInterface } from './types';
6
7
 
8
+ // Type definitions for Firebase Messaging Module instance
9
+ // This represents the instance returned by messaging() or getMessaging()
10
+ // We use a type alias to handle both v14 and v22+ types
11
+ type MessagingInstance = ReturnType<typeof RNFBMessaging>;
12
+
13
+ // Type definitions for modular API support (Firebase v22+)
14
+ // The modular API provides standalone functions that accept a messaging instance
15
+ type ModularMessagingType = {
16
+ getMessaging: () => MessagingInstance;
17
+ getAPNSToken: (messaging: MessagingInstance) => Promise<string | null>;
18
+ getToken: (messaging: MessagingInstance) => Promise<string>;
19
+ hasPermission: (messaging: MessagingInstance) => Promise<FirebaseMessagingTypes.AuthorizationStatus>;
20
+ requestPermission: (
21
+ messaging: MessagingInstance,
22
+ iosPermissions?: FirebaseMessagingTypes.IOSPermissions,
23
+ ) => Promise<FirebaseMessagingTypes.AuthorizationStatus>;
24
+ onTokenRefresh: (messaging: MessagingInstance, listener: (token: string) => void) => () => void;
25
+ AuthorizationStatus: typeof RNFBMessaging.AuthorizationStatus;
26
+ };
27
+
28
+ // Create a flexible type that can handle both v14 and v22+ Firebase modules
29
+ type FirebaseMessagingModule = typeof RNFBMessaging | ModularMessagingType;
30
+
31
+ const isModularAPI = (module: FirebaseMessagingModule): module is ModularMessagingType => {
32
+ return typeof (module as ModularMessagingType).getMessaging === 'function';
33
+ };
34
+
7
35
  const createNativeNotificationService = ({
8
36
  messagingModule,
9
37
  permissionModule,
10
38
  }: {
11
- messagingModule: typeof RNFBMessaging;
39
+ messagingModule: FirebaseMessagingModule;
12
40
  permissionModule: typeof Permissions;
13
41
  }): NotificationServiceInterface => {
14
- const module = messagingModule();
42
+ const isModular = isModularAPI(messagingModule);
43
+ const modularMessaging = isModular ? (messagingModule as ModularMessagingType) : null;
44
+ const messaging = isModular ? modularMessaging!.getMessaging() : (messagingModule as typeof RNFBMessaging)();
45
+
15
46
  const authorizedStatus = [
16
47
  messagingModule.AuthorizationStatus.AUTHORIZED,
17
48
  messagingModule.AuthorizationStatus.PROVISIONAL,
18
49
  ];
19
50
  return {
20
51
  getAPNSToken(): Promise<string | null> {
21
- return module.getAPNSToken();
52
+ if (modularMessaging) {
53
+ return modularMessaging.getAPNSToken(messaging);
54
+ }
55
+ return messaging.getAPNSToken();
22
56
  },
23
57
  getFCMToken(): Promise<string | null> {
24
- return module.getToken();
58
+ if (modularMessaging) {
59
+ return modularMessaging.getToken(messaging);
60
+ }
61
+ return messaging.getToken();
25
62
  },
26
63
  async hasPushPermission(): Promise<boolean> {
27
64
  if (Platform.OS === 'android') {
@@ -30,7 +67,9 @@ const createNativeNotificationService = ({
30
67
  }
31
68
 
32
69
  if (Platform.OS === 'ios') {
33
- const status = await module.hasPermission();
70
+ const status = modularMessaging
71
+ ? await modularMessaging.hasPermission(messaging)
72
+ : await messaging.hasPermission();
34
73
  return authorizedStatus.includes(status);
35
74
  }
36
75
 
@@ -43,14 +82,21 @@ const createNativeNotificationService = ({
43
82
  }
44
83
 
45
84
  if (Platform.OS === 'ios') {
46
- const status = await module.requestPermission();
85
+ const status = modularMessaging
86
+ ? await modularMessaging.requestPermission(messaging)
87
+ : await messaging.requestPermission();
47
88
  return authorizedStatus.includes(status);
48
89
  }
49
90
 
50
91
  return false;
51
92
  },
52
93
  onTokenRefresh(handler: (token: string) => void): () => void | undefined {
53
- return module.onTokenRefresh((token) => {
94
+ if (modularMessaging) {
95
+ return modularMessaging.onTokenRefresh(messaging, (token: string) => {
96
+ if (Platform.OS === 'android') handler(token);
97
+ });
98
+ }
99
+ return messaging.onTokenRefresh((token: string) => {
54
100
  if (Platform.OS === 'android') handler(token);
55
101
  });
56
102
  },
package/src/types.ts CHANGED
@@ -18,7 +18,11 @@ export interface AsyncLocalCacheStorage {
18
18
  multiRemove?(keys: string[]): Promise<void>;
19
19
  }
20
20
 
21
- export type MMKVLocalCacheStorage = Pick<MMKV, 'getString' | 'set' | 'delete' | 'getAllKeys'>;
21
+ export type MMKVLocalCacheStorage = Pick<MMKV, 'getString' | 'set' | 'getAllKeys'> & {
22
+ // Support both v3.x (delete) and v4.x (remove) APIs for backward compatibility
23
+ delete?: (key: string) => void;
24
+ remove?: (key: string) => void;
25
+ };
22
26
 
23
27
  export type ErrorBoundaryProps = { error: Error; errorInfo: ErrorInfo; reset: () => void };
24
28
 
@@ -8,6 +8,36 @@ import type * as ExpoVideo from 'expo-video';
8
8
  import type { FilePickerResponse } from '../platform/types';
9
9
  import normalizeFile from './normalizeFile';
10
10
 
11
+ // Legacy expo-file-system API types (before SDK 54)
12
+ interface ExpoFileSystemLegacy {
13
+ documentDirectory: string | null;
14
+ cacheDirectory: string | null;
15
+ getInfoAsync(fileUri: string, options?: unknown): Promise<ExpoFs.FileInfo>;
16
+ downloadAsync(uri: string, fileUri: string, options?: unknown): Promise<{ uri: string }>;
17
+ }
18
+
19
+ // New expo-file-system API types (SDK 54+)
20
+ interface ExpoDirectory {
21
+ uri: string;
22
+ }
23
+
24
+ interface ExpoFileSystemNew {
25
+ File: {
26
+ new (...uris: (string | unknown)[]): {
27
+ info(options?: unknown): ExpoFs.FileInfo;
28
+ };
29
+ downloadFileAsync(url: string, destination: unknown, options?: unknown): Promise<{ uri: string }>;
30
+ };
31
+ Directory: new (...uris: (string | unknown)[]) => ExpoDirectory;
32
+ Paths: {
33
+ document: ExpoDirectory;
34
+ cache: ExpoDirectory;
35
+ };
36
+ }
37
+
38
+ // Union type for both legacy and new expo-file-system
39
+ type ExpoFileSystemModule = ExpoFileSystemLegacy | ExpoFileSystemNew | typeof ExpoFs;
40
+
11
41
  const expoBackwardUtils = {
12
42
  imagePicker: {
13
43
  isCanceled(result: ExpoImagePicker.ImagePickerResult) {
@@ -82,12 +112,52 @@ const expoBackwardUtils = {
82
112
  },
83
113
  },
84
114
  toFileSize(info: ExpoFs.FileInfo) {
85
- if ('size' in info) {
115
+ if ('size' in info && info.size !== undefined) {
86
116
  return info.size;
87
117
  } else {
88
118
  return 0;
89
119
  }
90
120
  },
121
+ fileSystem: {
122
+ isLegacyModule(fsModule: ExpoFileSystemModule): fsModule is ExpoFileSystemLegacy {
123
+ try {
124
+ return 'documentDirectory' in fsModule || 'cacheDirectory' in fsModule;
125
+ } catch {
126
+ return false;
127
+ }
128
+ },
129
+ async getFileInfo(fsModule: ExpoFileSystemModule, uri: string): Promise<ExpoFs.FileInfo> {
130
+ if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {
131
+ return await fsModule.getInfoAsync(uri);
132
+ } else {
133
+ const file = new fsModule.File(uri);
134
+ return file.info();
135
+ }
136
+ },
137
+ getDocumentDirectory(fsModule: ExpoFileSystemModule): string | null {
138
+ if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {
139
+ return fsModule.documentDirectory || null;
140
+ } else {
141
+ return fsModule.Paths?.document?.uri || null;
142
+ }
143
+ },
144
+ getCacheDirectory(fsModule: ExpoFileSystemModule): string | null {
145
+ if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {
146
+ return fsModule.cacheDirectory || null;
147
+ } else {
148
+ return fsModule.Paths?.cache?.uri || null;
149
+ }
150
+ },
151
+ async downloadFile(fsModule: ExpoFileSystemModule, url: string, localUri: string): Promise<{ uri: string }> {
152
+ if (expoBackwardUtils.fileSystem.isLegacyModule(fsModule)) {
153
+ return await fsModule.downloadAsync(url, localUri);
154
+ } else {
155
+ const destination = new fsModule.File(localUri);
156
+ const result = await fsModule.File.downloadFileAsync(url, destination as never);
157
+ return { uri: result.uri };
158
+ }
159
+ },
160
+ },
91
161
  };
92
162
 
93
163
  export type ExpoAudioModule = typeof ExpoAV | typeof ExpoAudio;
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- const VERSION = '3.11.1';
1
+ const VERSION = '3.11.3';
2
2
  export default VERSION;