@sendbird/uikit-react-native 3.12.1 → 3.12.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 (90) hide show
  1. package/lib/commonjs/components/ChannelMessageList/index.js +1 -1
  2. package/lib/commonjs/components/ChannelMessageList/index.js.map +1 -1
  3. package/lib/commonjs/components/ChannelThreadMessageList/index.js +1 -1
  4. package/lib/commonjs/components/ChannelThreadMessageList/index.js.map +1 -1
  5. package/lib/commonjs/components/FileViewer/FileViewerContent.js +1 -1
  6. package/lib/commonjs/components/FileViewer/FileViewerContent.js.map +1 -1
  7. package/lib/commonjs/components/ReactionAddons/BottomSheetReactionAddon.js +57 -27
  8. package/lib/commonjs/components/ReactionAddons/BottomSheetReactionAddon.js.map +1 -1
  9. package/lib/commonjs/components/ReactionAddons/MessageReactionAddon.js +46 -17
  10. package/lib/commonjs/components/ReactionAddons/MessageReactionAddon.js.map +1 -1
  11. package/lib/commonjs/components/ReactionBottomSheets/ReactionListBottomSheet.js +52 -30
  12. package/lib/commonjs/components/ReactionBottomSheets/ReactionListBottomSheet.js.map +1 -1
  13. package/lib/commonjs/components/ReactionBottomSheets/ReactionUserListBottomSheet.js +1 -1
  14. package/lib/commonjs/components/ReactionBottomSheets/ReactionUserListBottomSheet.js.map +1 -1
  15. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +2 -2
  16. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  17. package/lib/commonjs/fragments/createGroupChannelMembersFragment.js +1 -1
  18. package/lib/commonjs/fragments/createGroupChannelMembersFragment.js.map +1 -1
  19. package/lib/commonjs/fragments/createOpenChannelParticipantsFragment.js +1 -1
  20. package/lib/commonjs/fragments/createOpenChannelParticipantsFragment.js.map +1 -1
  21. package/lib/commonjs/hooks/useMentionTextInput.js +1 -1
  22. package/lib/commonjs/hooks/useMentionTextInput.js.map +1 -1
  23. package/lib/commonjs/hooks/usePushTokenRegistration.js +1 -1
  24. package/lib/commonjs/hooks/usePushTokenRegistration.js.map +1 -1
  25. package/lib/commonjs/hooks/useVoiceMessageInput.js +1 -1
  26. package/lib/commonjs/hooks/useVoiceMessageInput.js.map +1 -1
  27. package/lib/commonjs/platform/createFileService.expo.js +4 -0
  28. package/lib/commonjs/platform/createFileService.expo.js.map +1 -1
  29. package/lib/commonjs/platform/createFileService.native.js +2 -0
  30. package/lib/commonjs/platform/createFileService.native.js.map +1 -1
  31. package/lib/commonjs/version.js +1 -1
  32. package/lib/commonjs/version.js.map +1 -1
  33. package/lib/module/components/ChannelMessageList/index.js +1 -1
  34. package/lib/module/components/ChannelMessageList/index.js.map +1 -1
  35. package/lib/module/components/ChannelThreadMessageList/index.js +1 -1
  36. package/lib/module/components/ChannelThreadMessageList/index.js.map +1 -1
  37. package/lib/module/components/FileViewer/FileViewerContent.js +1 -1
  38. package/lib/module/components/FileViewer/FileViewerContent.js.map +1 -1
  39. package/lib/module/components/ReactionAddons/BottomSheetReactionAddon.js +56 -26
  40. package/lib/module/components/ReactionAddons/BottomSheetReactionAddon.js.map +1 -1
  41. package/lib/module/components/ReactionAddons/MessageReactionAddon.js +45 -17
  42. package/lib/module/components/ReactionAddons/MessageReactionAddon.js.map +1 -1
  43. package/lib/module/components/ReactionBottomSheets/ReactionListBottomSheet.js +51 -29
  44. package/lib/module/components/ReactionBottomSheets/ReactionListBottomSheet.js.map +1 -1
  45. package/lib/module/components/ReactionBottomSheets/ReactionUserListBottomSheet.js +1 -1
  46. package/lib/module/components/ReactionBottomSheets/ReactionUserListBottomSheet.js.map +1 -1
  47. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +2 -2
  48. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  49. package/lib/module/fragments/createGroupChannelMembersFragment.js +1 -1
  50. package/lib/module/fragments/createGroupChannelMembersFragment.js.map +1 -1
  51. package/lib/module/fragments/createOpenChannelParticipantsFragment.js +1 -1
  52. package/lib/module/fragments/createOpenChannelParticipantsFragment.js.map +1 -1
  53. package/lib/module/hooks/useMentionTextInput.js +1 -1
  54. package/lib/module/hooks/useMentionTextInput.js.map +1 -1
  55. package/lib/module/hooks/usePushTokenRegistration.js +1 -1
  56. package/lib/module/hooks/usePushTokenRegistration.js.map +1 -1
  57. package/lib/module/hooks/useVoiceMessageInput.js +1 -1
  58. package/lib/module/hooks/useVoiceMessageInput.js.map +1 -1
  59. package/lib/module/platform/createFileService.expo.js +4 -0
  60. package/lib/module/platform/createFileService.expo.js.map +1 -1
  61. package/lib/module/platform/createFileService.native.js +2 -0
  62. package/lib/module/platform/createFileService.native.js.map +1 -1
  63. package/lib/module/version.js +1 -1
  64. package/lib/module/version.js.map +1 -1
  65. package/lib/typescript/src/components/ChannelMessageList/index.d.ts +1 -2
  66. package/lib/typescript/src/components/ChannelThreadMessageList/index.d.ts +1 -2
  67. package/lib/typescript/src/components/ReactionAddons/BottomSheetReactionAddon.d.ts +1 -1
  68. package/lib/typescript/src/containers/InternalErrorBoundaryContainer.d.ts +1 -1
  69. package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +1 -1
  70. package/lib/typescript/src/hooks/useChannelInputItems.d.ts +1 -1
  71. package/lib/typescript/src/hooks/useMentionTextInput.d.ts +1 -1
  72. package/lib/typescript/src/libs/MentionManager.d.ts +1 -1
  73. package/lib/typescript/src/version.d.ts +1 -1
  74. package/package.json +5 -5
  75. package/src/components/ChannelMessageList/index.tsx +4 -2
  76. package/src/components/ChannelThreadMessageList/index.tsx +4 -2
  77. package/src/components/FileViewer/FileViewerContent.tsx +1 -1
  78. package/src/components/ReactionAddons/BottomSheetReactionAddon.tsx +65 -18
  79. package/src/components/ReactionAddons/MessageReactionAddon.tsx +61 -25
  80. package/src/components/ReactionBottomSheets/ReactionListBottomSheet.tsx +61 -27
  81. package/src/components/ReactionBottomSheets/ReactionUserListBottomSheet.tsx +1 -1
  82. package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +2 -2
  83. package/src/fragments/createGroupChannelMembersFragment.tsx +1 -1
  84. package/src/fragments/createOpenChannelParticipantsFragment.tsx +1 -1
  85. package/src/hooks/useMentionTextInput.ts +1 -1
  86. package/src/hooks/usePushTokenRegistration.ts +1 -1
  87. package/src/hooks/useVoiceMessageInput.ts +1 -1
  88. package/src/platform/createFileService.expo.ts +4 -0
  89. package/src/platform/createFileService.native.ts +2 -0
  90. package/src/version.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"names":["getFileType","SBUError","expoBackwardUtils","expoPermissionGranted","createExpoFileService","imagePickerModule","documentPickerModule","mediaLibraryModule","fsModule","ExpoFileServiceInterface","hasCameraPermission","res","getCameraPermissionsAsync","requestCameraPermission","requestCameraPermissionsAsync","hasMediaLibraryReadPermission","perms","getMediaLibraryPermissionsAsync","requestMediaLibraryReadPermission","requestMediaLibraryPermissionsAsync","hasMediaLibraryWritePermission","getPermissionsAsync","requestMediaLibraryWritePermission","requestPermissionsAsync","openCamera","options","hasPermission","granted","_options$onOpenFailur","onOpenFailure","call","PERMISSIONS_DENIED","response","launchCameraAsync","mediaTypes","mediaType","MediaTypeOptions","Images","Videos","All","imagePicker","isCanceled","file","toFilePickerResponses","openMediaLibrary","_options$onOpenFailur2","selectionLimit","launchImageLibraryAsync","openDocument","getDocumentAsync","type","documentPicker","e","_options$onOpenFailur3","UNKNOWN","save","Error","basePath","fileSystem","getDocumentDirectory","getCacheDirectory","downloadPath","fileName","downloadFile","fileUrl","fileType","match","saveToLibraryAsync","uri","createRecordFilePath","customExtension","filename","Date","now","recordFilePath"],"sources":["createFileService.expo.ts"],"sourcesContent":["import 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 ExpoMediaLibrary from 'expo-media-library';\n\nimport { getFileType } from '@sendbird/uikit-utils';\n\nimport SBUError from '../libs/SBUError';\nimport expoBackwardUtils from '../utils/expoBackwardUtils';\nimport type { ExpoMediaLibraryPermissionResponse, ExpoPermissionResponse } from '../utils/expoPermissionGranted';\nimport expoPermissionGranted from '../utils/expoPermissionGranted';\nimport type {\n FilePickerResponse,\n FileServiceInterface,\n OpenCameraOptions,\n OpenDocumentOptions,\n OpenMediaLibraryOptions,\n SaveOptions,\n} from './types';\n\nconst createExpoFileService = ({\n imagePickerModule,\n documentPickerModule,\n mediaLibraryModule,\n fsModule,\n}: {\n imagePickerModule: typeof ExpoImagePicker;\n documentPickerModule: typeof ExpoDocumentPicker;\n mediaLibraryModule: typeof ExpoMediaLibrary;\n fsModule: typeof ExpoFs;\n}): FileServiceInterface => {\n class ExpoFileServiceInterface implements FileServiceInterface {\n async hasCameraPermission(): Promise<boolean> {\n const res = (await imagePickerModule.getCameraPermissionsAsync()) as ExpoPermissionResponse;\n return expoPermissionGranted([res]);\n }\n\n async requestCameraPermission(): Promise<boolean> {\n const res = (await imagePickerModule.requestCameraPermissionsAsync()) as ExpoPermissionResponse;\n return expoPermissionGranted([res]);\n }\n\n async hasMediaLibraryReadPermission(): Promise<boolean> {\n const perms = (await imagePickerModule.getMediaLibraryPermissionsAsync(\n false,\n )) as ExpoMediaLibraryPermissionResponse;\n return expoPermissionGranted([perms]);\n }\n\n async requestMediaLibraryReadPermission(): Promise<boolean> {\n const perms = (await imagePickerModule.requestMediaLibraryPermissionsAsync(\n false,\n )) as ExpoMediaLibraryPermissionResponse;\n return expoPermissionGranted([perms]);\n }\n\n async hasMediaLibraryWritePermission(): Promise<boolean> {\n const perms = (await mediaLibraryModule.getPermissionsAsync(true, [])) as ExpoMediaLibraryPermissionResponse;\n return expoPermissionGranted([perms]);\n }\n\n async requestMediaLibraryWritePermission(): Promise<boolean> {\n const perms = (await mediaLibraryModule.requestPermissionsAsync(true, [])) as ExpoMediaLibraryPermissionResponse;\n return expoPermissionGranted([perms]);\n }\n\n async openCamera(options?: OpenCameraOptions): Promise<FilePickerResponse> {\n const hasPermission = await this.hasCameraPermission();\n if (!hasPermission) {\n const granted = await this.requestCameraPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchCameraAsync({\n mediaTypes: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return imagePickerModule.MediaTypeOptions.Images;\n case 'video':\n return imagePickerModule.MediaTypeOptions.Videos;\n case 'all':\n return imagePickerModule.MediaTypeOptions.All;\n default:\n return imagePickerModule.MediaTypeOptions.Images;\n }\n })(),\n });\n\n if (expoBackwardUtils.imagePicker.isCanceled(response)) return null;\n\n const [file] = await expoBackwardUtils.imagePicker.toFilePickerResponses(response, fsModule);\n return file;\n }\n\n async openMediaLibrary(options: OpenMediaLibraryOptions) {\n const hasPermission = await this.hasMediaLibraryReadPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryReadPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const selectionLimit = options?.selectionLimit || 1;\n const response = await imagePickerModule.launchImageLibraryAsync({\n selectionLimit,\n mediaTypes: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return imagePickerModule.MediaTypeOptions.Images;\n case 'video':\n return imagePickerModule.MediaTypeOptions.Videos;\n case 'all':\n return imagePickerModule.MediaTypeOptions.All;\n default:\n return imagePickerModule.MediaTypeOptions.Images;\n }\n })(),\n });\n if (expoBackwardUtils.imagePicker.isCanceled(response)) return null;\n return expoBackwardUtils.imagePicker.toFilePickerResponses(response, fsModule);\n }\n\n async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {\n try {\n const response = await documentPickerModule.getDocumentAsync({ type: '*/*' });\n if (expoBackwardUtils.documentPicker.isCanceled(response)) return null;\n\n const [file] = await expoBackwardUtils.documentPicker.toFilePickerResponses(response);\n return file;\n } catch (e) {\n options?.onOpenFailure?.(SBUError.UNKNOWN, e);\n return null;\n }\n }\n\n async save(options: SaveOptions): Promise<string> {\n const hasPermission = await this.hasMediaLibraryWritePermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryWritePermission();\n if (!granted) throw new Error('Permission not granted');\n }\n\n const basePath =\n expoBackwardUtils.fileSystem.getDocumentDirectory(fsModule) ||\n expoBackwardUtils.fileSystem.getCacheDirectory(fsModule);\n if (!basePath) throw new Error('Cannot determine directory');\n\n const downloadPath = `${basePath}/${options.fileName}`;\n\n const response = await expoBackwardUtils.fileSystem.downloadFile(fsModule, options.fileUrl, downloadPath);\n if (getFileType(options.fileType || '').match(/video|image/)) {\n await mediaLibraryModule.saveToLibraryAsync(response.uri);\n }\n return response.uri;\n }\n\n createRecordFilePath(customExtension = 'm4a'): { recordFilePath: string; uri: string } {\n const basePath = expoBackwardUtils.fileSystem.getCacheDirectory(fsModule);\n if (!basePath) throw new Error('Cannot determine directory');\n\n const filename = `record-${Date.now()}.${customExtension}`;\n return {\n uri: `${basePath}/${filename}`,\n recordFilePath: `${basePath}/${filename}`,\n };\n }\n }\n\n return new ExpoFileServiceInterface();\n};\n\nexport default createExpoFileService;\n"],"mappings":"AAKA,SAASA,WAAW,QAAQ,uBAAuB;AAEnD,OAAOC,QAAQ,MAAM,kBAAkB;AACvC,OAAOC,iBAAiB,MAAM,4BAA4B;AAE1D,OAAOC,qBAAqB,MAAM,gCAAgC;AAUlE,MAAMC,qBAAqB,GAAGA,CAAC;EAC7BC,iBAAiB;EACjBC,oBAAoB;EACpBC,kBAAkB;EAClBC;AAMF,CAAC,KAA2B;EAC1B,MAAMC,wBAAwB,CAAiC;IAC7D,MAAMC,mBAAmBA,CAAA,EAAqB;MAC5C,MAAMC,GAAG,GAAI,MAAMN,iBAAiB,CAACO,yBAAyB,CAAC,CAA4B;MAC3F,OAAOT,qBAAqB,CAAC,CAACQ,GAAG,CAAC,CAAC;IACrC;IAEA,MAAME,uBAAuBA,CAAA,EAAqB;MAChD,MAAMF,GAAG,GAAI,MAAMN,iBAAiB,CAACS,6BAA6B,CAAC,CAA4B;MAC/F,OAAOX,qBAAqB,CAAC,CAACQ,GAAG,CAAC,CAAC;IACrC;IAEA,MAAMI,6BAA6BA,CAAA,EAAqB;MACtD,MAAMC,KAAK,GAAI,MAAMX,iBAAiB,CAACY,+BAA+B,CACpE,KACF,CAAwC;MACxC,OAAOd,qBAAqB,CAAC,CAACa,KAAK,CAAC,CAAC;IACvC;IAEA,MAAME,iCAAiCA,CAAA,EAAqB;MAC1D,MAAMF,KAAK,GAAI,MAAMX,iBAAiB,CAACc,mCAAmC,CACxE,KACF,CAAwC;MACxC,OAAOhB,qBAAqB,CAAC,CAACa,KAAK,CAAC,CAAC;IACvC;IAEA,MAAMI,8BAA8BA,CAAA,EAAqB;MACvD,MAAMJ,KAAK,GAAI,MAAMT,kBAAkB,CAACc,mBAAmB,CAAC,IAAI,EAAE,EAAE,CAAwC;MAC5G,OAAOlB,qBAAqB,CAAC,CAACa,KAAK,CAAC,CAAC;IACvC;IAEA,MAAMM,kCAAkCA,CAAA,EAAqB;MAC3D,MAAMN,KAAK,GAAI,MAAMT,kBAAkB,CAACgB,uBAAuB,CAAC,IAAI,EAAE,EAAE,CAAwC;MAChH,OAAOpB,qBAAqB,CAAC,CAACa,KAAK,CAAC,CAAC;IACvC;IAEA,MAAMQ,UAAUA,CAACC,OAA2B,EAA+B;MACzE,MAAMC,aAAa,GAAG,MAAM,IAAI,CAAChB,mBAAmB,CAAC,CAAC;MACtD,IAAI,CAACgB,aAAa,EAAE;QAClB,MAAMC,OAAO,GAAG,MAAM,IAAI,CAACd,uBAAuB,CAAC,CAAC;QACpD,IAAI,CAACc,OAAO,EAAE;UAAA,IAAAC,qBAAA;UACZH,OAAO,aAAPA,OAAO,gBAAAG,qBAAA,GAAPH,OAAO,CAAEI,aAAa,cAAAD,qBAAA,eAAtBA,qBAAA,CAAAE,IAAA,CAAAL,OAAO,EAAkBxB,QAAQ,CAAC8B,kBAAkB,CAAC;UACrD,OAAO,IAAI;QACb;MACF;MAEA,MAAMC,QAAQ,GAAG,MAAM3B,iBAAiB,CAAC4B,iBAAiB,CAAC;QACzDC,UAAU,EAAE,CAAC,MAAM;UACjB,QAAQT,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEU,SAAS;YACxB,KAAK,OAAO;cACV,OAAO9B,iBAAiB,CAAC+B,gBAAgB,CAACC,MAAM;YAClD,KAAK,OAAO;cACV,OAAOhC,iBAAiB,CAAC+B,gBAAgB,CAACE,MAAM;YAClD,KAAK,KAAK;cACR,OAAOjC,iBAAiB,CAAC+B,gBAAgB,CAACG,GAAG;YAC/C;cACE,OAAOlC,iBAAiB,CAAC+B,gBAAgB,CAACC,MAAM;UACpD;QACF,CAAC,EAAE;MACL,CAAC,CAAC;MAEF,IAAInC,iBAAiB,CAACsC,WAAW,CAACC,UAAU,CAACT,QAAQ,CAAC,EAAE,OAAO,IAAI;MAEnE,MAAM,CAACU,IAAI,CAAC,GAAG,MAAMxC,iBAAiB,CAACsC,WAAW,CAACG,qBAAqB,CAACX,QAAQ,EAAExB,QAAQ,CAAC;MAC5F,OAAOkC,IAAI;IACb;IAEA,MAAME,gBAAgBA,CAACnB,OAAgC,EAAE;MACvD,MAAMC,aAAa,GAAG,MAAM,IAAI,CAACX,6BAA6B,CAAC,CAAC;MAChE,IAAI,CAACW,aAAa,EAAE;QAClB,MAAMC,OAAO,GAAG,MAAM,IAAI,CAACT,iCAAiC,CAAC,CAAC;QAC9D,IAAI,CAACS,OAAO,EAAE;UAAA,IAAAkB,sBAAA;UACZpB,OAAO,aAAPA,OAAO,gBAAAoB,sBAAA,GAAPpB,OAAO,CAAEI,aAAa,cAAAgB,sBAAA,eAAtBA,sBAAA,CAAAf,IAAA,CAAAL,OAAO,EAAkBxB,QAAQ,CAAC8B,kBAAkB,CAAC;UACrD,OAAO,IAAI;QACb;MACF;MAEA,MAAMe,cAAc,GAAG,CAAArB,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEqB,cAAc,KAAI,CAAC;MACnD,MAAMd,QAAQ,GAAG,MAAM3B,iBAAiB,CAAC0C,uBAAuB,CAAC;QAC/DD,cAAc;QACdZ,UAAU,EAAE,CAAC,MAAM;UACjB,QAAQT,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEU,SAAS;YACxB,KAAK,OAAO;cACV,OAAO9B,iBAAiB,CAAC+B,gBAAgB,CAACC,MAAM;YAClD,KAAK,OAAO;cACV,OAAOhC,iBAAiB,CAAC+B,gBAAgB,CAACE,MAAM;YAClD,KAAK,KAAK;cACR,OAAOjC,iBAAiB,CAAC+B,gBAAgB,CAACG,GAAG;YAC/C;cACE,OAAOlC,iBAAiB,CAAC+B,gBAAgB,CAACC,MAAM;UACpD;QACF,CAAC,EAAE;MACL,CAAC,CAAC;MACF,IAAInC,iBAAiB,CAACsC,WAAW,CAACC,UAAU,CAACT,QAAQ,CAAC,EAAE,OAAO,IAAI;MACnE,OAAO9B,iBAAiB,CAACsC,WAAW,CAACG,qBAAqB,CAACX,QAAQ,EAAExB,QAAQ,CAAC;IAChF;IAEA,MAAMwC,YAAYA,CAACvB,OAA6B,EAA+B;MAC7E,IAAI;QACF,MAAMO,QAAQ,GAAG,MAAM1B,oBAAoB,CAAC2C,gBAAgB,CAAC;UAAEC,IAAI,EAAE;QAAM,CAAC,CAAC;QAC7E,IAAIhD,iBAAiB,CAACiD,cAAc,CAACV,UAAU,CAACT,QAAQ,CAAC,EAAE,OAAO,IAAI;QAEtE,MAAM,CAACU,IAAI,CAAC,GAAG,MAAMxC,iBAAiB,CAACiD,cAAc,CAACR,qBAAqB,CAACX,QAAQ,CAAC;QACrF,OAAOU,IAAI;MACb,CAAC,CAAC,OAAOU,CAAC,EAAE;QAAA,IAAAC,sBAAA;QACV5B,OAAO,aAAPA,OAAO,gBAAA4B,sBAAA,GAAP5B,OAAO,CAAEI,aAAa,cAAAwB,sBAAA,eAAtBA,sBAAA,CAAAvB,IAAA,CAAAL,OAAO,EAAkBxB,QAAQ,CAACqD,OAAO,EAAEF,CAAC,CAAC;QAC7C,OAAO,IAAI;MACb;IACF;IAEA,MAAMG,IAAIA,CAAC9B,OAAoB,EAAmB;MAChD,MAAMC,aAAa,GAAG,MAAM,IAAI,CAACN,8BAA8B,CAAC,CAAC;MACjE,IAAI,CAACM,aAAa,EAAE;QAClB,MAAMC,OAAO,GAAG,MAAM,IAAI,CAACL,kCAAkC,CAAC,CAAC;QAC/D,IAAI,CAACK,OAAO,EAAE,MAAM,IAAI6B,KAAK,CAAC,wBAAwB,CAAC;MACzD;MAEA,MAAMC,QAAQ,GACZvD,iBAAiB,CAACwD,UAAU,CAACC,oBAAoB,CAACnD,QAAQ,CAAC,IAC3DN,iBAAiB,CAACwD,UAAU,CAACE,iBAAiB,CAACpD,QAAQ,CAAC;MAC1D,IAAI,CAACiD,QAAQ,EAAE,MAAM,IAAID,KAAK,CAAC,4BAA4B,CAAC;MAE5D,MAAMK,YAAY,GAAG,GAAGJ,QAAQ,IAAIhC,OAAO,CAACqC,QAAQ,EAAE;MAEtD,MAAM9B,QAAQ,GAAG,MAAM9B,iBAAiB,CAACwD,UAAU,CAACK,YAAY,CAACvD,QAAQ,EAAEiB,OAAO,CAACuC,OAAO,EAAEH,YAAY,CAAC;MACzG,IAAI7D,WAAW,CAACyB,OAAO,CAACwC,QAAQ,IAAI,EAAE,CAAC,CAACC,KAAK,CAAC,aAAa,CAAC,EAAE;QAC5D,MAAM3D,kBAAkB,CAAC4D,kBAAkB,CAACnC,QAAQ,CAACoC,GAAG,CAAC;MAC3D;MACA,OAAOpC,QAAQ,CAACoC,GAAG;IACrB;IAEAC,oBAAoBA,CAACC,eAAe,GAAG,KAAK,EAA2C;MACrF,MAAMb,QAAQ,GAAGvD,iBAAiB,CAACwD,UAAU,CAACE,iBAAiB,CAACpD,QAAQ,CAAC;MACzE,IAAI,CAACiD,QAAQ,EAAE,MAAM,IAAID,KAAK,CAAC,4BAA4B,CAAC;MAE5D,MAAMe,QAAQ,GAAG,UAAUC,IAAI,CAACC,GAAG,CAAC,CAAC,IAAIH,eAAe,EAAE;MAC1D,OAAO;QACLF,GAAG,EAAE,GAAGX,QAAQ,IAAIc,QAAQ,EAAE;QAC9BG,cAAc,EAAE,GAAGjB,QAAQ,IAAIc,QAAQ;MACzC,CAAC;IACH;EACF;EAEA,OAAO,IAAI9D,wBAAwB,CAAC,CAAC;AACvC,CAAC;AAED,eAAeL,qBAAqB","ignoreList":[]}
1
+ {"version":3,"names":["getFileType","SBUError","expoBackwardUtils","expoPermissionGranted","createExpoFileService","imagePickerModule","documentPickerModule","mediaLibraryModule","fsModule","_imagePickerModule$UI","preferredAssetRepresentationMode","UIImagePickerPreferredAssetRepresentationMode","Compatible","ExpoFileServiceInterface","hasCameraPermission","res","getCameraPermissionsAsync","requestCameraPermission","requestCameraPermissionsAsync","hasMediaLibraryReadPermission","perms","getMediaLibraryPermissionsAsync","requestMediaLibraryReadPermission","requestMediaLibraryPermissionsAsync","hasMediaLibraryWritePermission","getPermissionsAsync","requestMediaLibraryWritePermission","requestPermissionsAsync","openCamera","options","hasPermission","granted","_options$onOpenFailur","onOpenFailure","call","PERMISSIONS_DENIED","response","launchCameraAsync","mediaTypes","mediaType","MediaTypeOptions","Images","Videos","All","imagePicker","isCanceled","file","toFilePickerResponses","openMediaLibrary","_options$onOpenFailur2","selectionLimit","launchImageLibraryAsync","openDocument","getDocumentAsync","type","documentPicker","e","_options$onOpenFailur3","UNKNOWN","save","Error","basePath","fileSystem","getDocumentDirectory","getCacheDirectory","downloadPath","fileName","downloadFile","fileUrl","fileType","match","saveToLibraryAsync","uri","createRecordFilePath","customExtension","filename","Date","now","recordFilePath"],"sources":["createFileService.expo.ts"],"sourcesContent":["import 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 ExpoMediaLibrary from 'expo-media-library';\n\nimport { getFileType } from '@sendbird/uikit-utils';\n\nimport SBUError from '../libs/SBUError';\nimport expoBackwardUtils from '../utils/expoBackwardUtils';\nimport type { ExpoMediaLibraryPermissionResponse, ExpoPermissionResponse } from '../utils/expoPermissionGranted';\nimport expoPermissionGranted from '../utils/expoPermissionGranted';\nimport type {\n FilePickerResponse,\n FileServiceInterface,\n OpenCameraOptions,\n OpenDocumentOptions,\n OpenMediaLibraryOptions,\n SaveOptions,\n} from './types';\n\nconst createExpoFileService = ({\n imagePickerModule,\n documentPickerModule,\n mediaLibraryModule,\n fsModule,\n}: {\n imagePickerModule: typeof ExpoImagePicker;\n documentPickerModule: typeof ExpoDocumentPicker;\n mediaLibraryModule: typeof ExpoMediaLibrary;\n fsModule: typeof ExpoFs;\n}): FileServiceInterface => {\n const preferredAssetRepresentationMode = imagePickerModule.UIImagePickerPreferredAssetRepresentationMode?.Compatible;\n\n class ExpoFileServiceInterface implements FileServiceInterface {\n async hasCameraPermission(): Promise<boolean> {\n const res = (await imagePickerModule.getCameraPermissionsAsync()) as ExpoPermissionResponse;\n return expoPermissionGranted([res]);\n }\n\n async requestCameraPermission(): Promise<boolean> {\n const res = (await imagePickerModule.requestCameraPermissionsAsync()) as ExpoPermissionResponse;\n return expoPermissionGranted([res]);\n }\n\n async hasMediaLibraryReadPermission(): Promise<boolean> {\n const perms = (await imagePickerModule.getMediaLibraryPermissionsAsync(\n false,\n )) as ExpoMediaLibraryPermissionResponse;\n return expoPermissionGranted([perms]);\n }\n\n async requestMediaLibraryReadPermission(): Promise<boolean> {\n const perms = (await imagePickerModule.requestMediaLibraryPermissionsAsync(\n false,\n )) as ExpoMediaLibraryPermissionResponse;\n return expoPermissionGranted([perms]);\n }\n\n async hasMediaLibraryWritePermission(): Promise<boolean> {\n const perms = (await mediaLibraryModule.getPermissionsAsync(true, [])) as ExpoMediaLibraryPermissionResponse;\n return expoPermissionGranted([perms]);\n }\n\n async requestMediaLibraryWritePermission(): Promise<boolean> {\n const perms = (await mediaLibraryModule.requestPermissionsAsync(true, [])) as ExpoMediaLibraryPermissionResponse;\n return expoPermissionGranted([perms]);\n }\n\n async openCamera(options?: OpenCameraOptions): Promise<FilePickerResponse> {\n const hasPermission = await this.hasCameraPermission();\n if (!hasPermission) {\n const granted = await this.requestCameraPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchCameraAsync({\n preferredAssetRepresentationMode,\n mediaTypes: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return imagePickerModule.MediaTypeOptions.Images;\n case 'video':\n return imagePickerModule.MediaTypeOptions.Videos;\n case 'all':\n return imagePickerModule.MediaTypeOptions.All;\n default:\n return imagePickerModule.MediaTypeOptions.Images;\n }\n })(),\n });\n\n if (expoBackwardUtils.imagePicker.isCanceled(response)) return null;\n\n const [file] = await expoBackwardUtils.imagePicker.toFilePickerResponses(response, fsModule);\n return file;\n }\n\n async openMediaLibrary(options: OpenMediaLibraryOptions) {\n const hasPermission = await this.hasMediaLibraryReadPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryReadPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const selectionLimit = options?.selectionLimit || 1;\n const response = await imagePickerModule.launchImageLibraryAsync({\n selectionLimit,\n preferredAssetRepresentationMode,\n mediaTypes: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return imagePickerModule.MediaTypeOptions.Images;\n case 'video':\n return imagePickerModule.MediaTypeOptions.Videos;\n case 'all':\n return imagePickerModule.MediaTypeOptions.All;\n default:\n return imagePickerModule.MediaTypeOptions.Images;\n }\n })(),\n });\n if (expoBackwardUtils.imagePicker.isCanceled(response)) return null;\n return expoBackwardUtils.imagePicker.toFilePickerResponses(response, fsModule);\n }\n\n async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {\n try {\n const response = await documentPickerModule.getDocumentAsync({ type: '*/*' });\n if (expoBackwardUtils.documentPicker.isCanceled(response)) return null;\n\n const [file] = await expoBackwardUtils.documentPicker.toFilePickerResponses(response);\n return file;\n } catch (e) {\n options?.onOpenFailure?.(SBUError.UNKNOWN, e);\n return null;\n }\n }\n\n async save(options: SaveOptions): Promise<string> {\n const hasPermission = await this.hasMediaLibraryWritePermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryWritePermission();\n if (!granted) throw new Error('Permission not granted');\n }\n\n const basePath =\n expoBackwardUtils.fileSystem.getDocumentDirectory(fsModule) ||\n expoBackwardUtils.fileSystem.getCacheDirectory(fsModule);\n if (!basePath) throw new Error('Cannot determine directory');\n\n const downloadPath = `${basePath}/${options.fileName}`;\n\n const response = await expoBackwardUtils.fileSystem.downloadFile(fsModule, options.fileUrl, downloadPath);\n if (getFileType(options.fileType || '').match(/video|image/)) {\n await mediaLibraryModule.saveToLibraryAsync(response.uri);\n }\n return response.uri;\n }\n\n createRecordFilePath(customExtension = 'm4a'): { recordFilePath: string; uri: string } {\n const basePath = expoBackwardUtils.fileSystem.getCacheDirectory(fsModule);\n if (!basePath) throw new Error('Cannot determine directory');\n\n const filename = `record-${Date.now()}.${customExtension}`;\n return {\n uri: `${basePath}/${filename}`,\n recordFilePath: `${basePath}/${filename}`,\n };\n }\n }\n\n return new ExpoFileServiceInterface();\n};\n\nexport default createExpoFileService;\n"],"mappings":"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","ignoreList":[]}
@@ -106,6 +106,7 @@ const createNativeFileService = ({
106
106
  const response = await imagePickerModule.launchCamera({
107
107
  presentationStyle: 'fullScreen',
108
108
  cameraType: (options === null || options === void 0 ? void 0 : options.cameraType) ?? 'back',
109
+ assetRepresentationMode: 'compatible',
109
110
  mediaType: (() => {
110
111
  switch (options === null || options === void 0 ? void 0 : options.mediaType) {
111
112
  case 'photo':
@@ -156,6 +157,7 @@ const createNativeFileService = ({
156
157
  const response = await imagePickerModule.launchImageLibrary({
157
158
  presentationStyle: 'fullScreen',
158
159
  selectionLimit,
160
+ assetRepresentationMode: 'compatible',
159
161
  mediaType: (() => {
160
162
  switch (options === null || options === void 0 ? void 0 : options.mediaType) {
161
163
  case 'photo':
@@ -1 +1 @@
1
- {"version":3,"names":["Platform","Logger","getFileExtension","getFileExtensionFromMime","getFileExtensionFromUri","getFileType","normalizeFileName","SBUError","nativePermissionGranted","normalizeFile","openDocument","getAndroidStoragePermissionsByAPILevel","permissionModule","OS","Version","PERMISSIONS","ANDROID","READ_EXTERNAL_STORAGE","WRITE_EXTERNAL_STORAGE","createNativeFileService","imagePickerModule","documentPickerModule","mediaLibraryModule","fsModule","requiredPermissions","select","ios","IOS","CAMERA","android","default","optionalPermissions","MICROPHONE","mediaLibraryPermissions","PHOTO_LIBRARY","PHOTO_LIBRARY_ADD_ONLY","NativeFileService","constructor","_defineProperty","options","dirname","Dirs","CacheDir","DocumentDir","context","filename","fileName","extension","fileType","fileUrl","path","buildDownloadPath","FileSystem","fetch","downloadedPath","file","name","type","hasCameraPermission","status","checkMultiple","requestCameraPermission","requiredPermissionsStatus","requestMultiple","hasMediaLibraryPermission","requestMediaLibraryPermission","openCamera","_response$assets","hasPermission","granted","_options$onOpenFailur","onOpenFailure","call","PERMISSIONS_DENIED","response","launchCamera","presentationStyle","cameraType","mediaType","didCancel","errorCode","_options$onOpenFailur2","DEVICE_UNAVAILABLE","Error","errorMessage","fileSize","size","uri","assets","openMediaLibrary","selectionLimit","_options$onOpenFailur3","launchImageLibrary","_options$onOpenFailur4","Promise","all","slice","map","save","downloadFile","mediaTypeMap","externalDirMap","externalDir","cpExternal","catch","error","createRecordFilePath","customExtension","Date","now","recordFilePath","startsWith"],"sources":["createFileService.native.ts"],"sourcesContent":["import type { CameraRoll } from '@react-native-camera-roll/camera-roll';\nimport { Platform } from 'react-native';\nimport type * as FileAccess from 'react-native-file-access';\nimport type * as ImagePicker from 'react-native-image-picker';\nimport type * as Permissions from 'react-native-permissions';\nimport type { Permission } from 'react-native-permissions';\n\nimport {\n Logger,\n getFileExtension,\n getFileExtensionFromMime,\n getFileExtensionFromUri,\n getFileType,\n normalizeFileName,\n} from '@sendbird/uikit-utils';\n\nimport SBUError from '../libs/SBUError';\nimport nativePermissionGranted from '../utils/nativePermissionGranted';\nimport normalizeFile from '../utils/normalizeFile';\nimport { DocumentPicker, openDocument } from './openDocument.native';\nimport type {\n FilePickerResponse,\n FileServiceInterface,\n OpenCameraOptions,\n OpenDocumentOptions,\n OpenMediaLibraryOptions,\n SaveOptions,\n} from './types';\n\nfunction getAndroidStoragePermissionsByAPILevel(permissionModule: typeof Permissions): Permission[] {\n if (Platform.OS !== 'android') return [];\n\n if (Platform.Version > 32) {\n return [];\n }\n\n if (Platform.Version > 28) {\n return [permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE];\n }\n\n return [\n permissionModule.PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,\n permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,\n ];\n}\n\nconst createNativeFileService = ({\n imagePickerModule,\n documentPickerModule,\n permissionModule,\n mediaLibraryModule,\n fsModule,\n}: {\n imagePickerModule: typeof ImagePicker;\n documentPickerModule: DocumentPicker;\n permissionModule: typeof Permissions;\n mediaLibraryModule: typeof CameraRoll;\n fsModule: typeof FileAccess;\n}): FileServiceInterface => {\n const requiredPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.CAMERA],\n android: [permissionModule.PERMISSIONS.ANDROID.CAMERA],\n default: [],\n });\n const optionalPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.MICROPHONE],\n android: [],\n default: [],\n });\n const mediaLibraryPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.PHOTO_LIBRARY, permissionModule.PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY],\n android: getAndroidStoragePermissionsByAPILevel(permissionModule),\n default: [],\n });\n\n class NativeFileService implements FileServiceInterface {\n async hasCameraPermission(): Promise<boolean> {\n const status = await permissionModule.checkMultiple(requiredPermissions);\n return nativePermissionGranted(status);\n }\n\n async requestCameraPermission(): Promise<boolean> {\n const requiredPermissionsStatus = await permissionModule.requestMultiple(requiredPermissions);\n if (!nativePermissionGranted(requiredPermissionsStatus)) return false;\n\n await permissionModule.requestMultiple(optionalPermissions);\n return true;\n }\n\n async hasMediaLibraryPermission(): Promise<boolean> {\n const status = await permissionModule.checkMultiple(mediaLibraryPermissions);\n return nativePermissionGranted(status);\n }\n\n async requestMediaLibraryPermission(): Promise<boolean> {\n const status = await permissionModule.requestMultiple(mediaLibraryPermissions);\n return nativePermissionGranted(status);\n }\n\n async openCamera(options?: OpenCameraOptions): Promise<FilePickerResponse> {\n const hasPermission = await this.hasCameraPermission();\n if (!hasPermission) {\n const granted = await this.requestCameraPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchCamera({\n presentationStyle: 'fullScreen',\n cameraType: options?.cameraType ?? 'back',\n mediaType: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return 'photo';\n case 'video':\n return 'video';\n case 'all':\n return 'mixed';\n default:\n return 'photo';\n }\n })(),\n });\n if (response.didCancel) return null;\n if (response.errorCode === 'camera_unavailable') {\n options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));\n return null;\n }\n\n const { fileName: name, fileSize: size, type, uri } = response.assets?.[0] ?? {};\n return normalizeFile({ uri, size, name, type });\n }\n\n async openMediaLibrary(options?: OpenMediaLibraryOptions): Promise<FilePickerResponse[] | null> {\n /**\n * NOTE: options.selectionLimit {@link https://github.com/react-native-image-picker/react-native-image-picker#options}\n * We do not support 0 (any number of files)\n **/\n const selectionLimit = options?.selectionLimit || 1;\n const hasPermission = await this.hasMediaLibraryPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchImageLibrary({\n presentationStyle: 'fullScreen',\n selectionLimit,\n mediaType: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return 'photo';\n case 'video':\n return 'video';\n case 'all':\n return 'mixed';\n default:\n return 'photo';\n }\n })(),\n });\n if (response.didCancel) return null;\n if (response.errorCode === 'camera_unavailable') {\n options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));\n return null;\n }\n\n return Promise.all(\n (response.assets || [])\n .slice(0, selectionLimit)\n .map(({ fileName: name, fileSize: size, type, uri }) => normalizeFile({ uri, size, name, type })),\n );\n }\n\n async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {\n return await openDocument(documentPickerModule, options);\n }\n\n async save(options: SaveOptions): Promise<string> {\n const hasPermission = await this.hasMediaLibraryPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryPermission();\n if (!granted) throw new Error('Permission not granted');\n }\n\n const { downloadedPath, file } = await this.downloadFile(options);\n\n if (Platform.OS === 'ios') {\n if (file.type === 'image' || file.type === 'video') {\n const mediaTypeMap = { 'image': 'photo', 'video': 'video' } as const;\n const mediaType = mediaTypeMap[file.type];\n await mediaLibraryModule.save(downloadedPath, { type: mediaType });\n }\n }\n\n if (Platform.OS === 'android') {\n const externalDirMap = { 'file': 'downloads', 'audio': 'audio', 'image': 'images', 'video': 'video' } as const;\n const externalDir = externalDirMap[file.type];\n await fsModule.FileSystem.cpExternal(downloadedPath, file.name, externalDir).catch(() => {\n Logger.error('Failed to save file to external storage. Retry saving to downloads directory instead.');\n return fsModule.FileSystem.cpExternal(downloadedPath, file.name, 'downloads');\n });\n }\n\n return downloadedPath;\n }\n\n private buildDownloadPath = async (options: SaveOptions) => {\n const dirname = Platform.select({ android: fsModule.Dirs.CacheDir, default: fsModule.Dirs.DocumentDir });\n const context = { dirname, filename: options.fileName };\n const extension =\n getFileExtension(options.fileName) ||\n getFileExtensionFromMime(options.fileType) ||\n getFileExtension(options.fileUrl) ||\n (await getFileExtensionFromUri(options.fileUrl));\n\n if (extension) context.filename = normalizeFileName(context.filename, extension);\n\n return { path: `${context.dirname}/${context.filename}`, ...context };\n };\n\n private downloadFile = async (options: SaveOptions) => {\n const { path, filename } = await this.buildDownloadPath(options);\n await fsModule.FileSystem.fetch(options.fileUrl, { path });\n return {\n downloadedPath: path,\n file: {\n name: filename,\n type: getFileType(getFileExtension(path)),\n } as const,\n };\n };\n\n createRecordFilePath(customExtension = 'm4a'): { recordFilePath: string; uri: string } {\n const filename = `record-${Date.now()}.${customExtension}`;\n const path = `${fsModule.Dirs.CacheDir}/${filename}`;\n return Platform.select({\n ios: {\n uri: path,\n recordFilePath: path,\n },\n android: {\n uri: path.startsWith('file://') ? path : 'file://' + path,\n recordFilePath: path,\n },\n default: {\n uri: path,\n recordFilePath: path,\n },\n });\n }\n }\n\n return new NativeFileService();\n};\n\nexport default createNativeFileService;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["Platform","Logger","getFileExtension","getFileExtensionFromMime","getFileExtensionFromUri","getFileType","normalizeFileName","SBUError","nativePermissionGranted","normalizeFile","openDocument","getAndroidStoragePermissionsByAPILevel","permissionModule","OS","Version","PERMISSIONS","ANDROID","READ_EXTERNAL_STORAGE","WRITE_EXTERNAL_STORAGE","createNativeFileService","imagePickerModule","documentPickerModule","mediaLibraryModule","fsModule","requiredPermissions","select","ios","IOS","CAMERA","android","default","optionalPermissions","MICROPHONE","mediaLibraryPermissions","PHOTO_LIBRARY","PHOTO_LIBRARY_ADD_ONLY","NativeFileService","constructor","_defineProperty","options","dirname","Dirs","CacheDir","DocumentDir","context","filename","fileName","extension","fileType","fileUrl","path","buildDownloadPath","FileSystem","fetch","downloadedPath","file","name","type","hasCameraPermission","status","checkMultiple","requestCameraPermission","requiredPermissionsStatus","requestMultiple","hasMediaLibraryPermission","requestMediaLibraryPermission","openCamera","_response$assets","hasPermission","granted","_options$onOpenFailur","onOpenFailure","call","PERMISSIONS_DENIED","response","launchCamera","presentationStyle","cameraType","assetRepresentationMode","mediaType","didCancel","errorCode","_options$onOpenFailur2","DEVICE_UNAVAILABLE","Error","errorMessage","fileSize","size","uri","assets","openMediaLibrary","selectionLimit","_options$onOpenFailur3","launchImageLibrary","_options$onOpenFailur4","Promise","all","slice","map","save","downloadFile","mediaTypeMap","externalDirMap","externalDir","cpExternal","catch","error","createRecordFilePath","customExtension","Date","now","recordFilePath","startsWith"],"sources":["createFileService.native.ts"],"sourcesContent":["import type { CameraRoll } from '@react-native-camera-roll/camera-roll';\nimport { Platform } from 'react-native';\nimport type * as FileAccess from 'react-native-file-access';\nimport type * as ImagePicker from 'react-native-image-picker';\nimport type * as Permissions from 'react-native-permissions';\nimport type { Permission } from 'react-native-permissions';\n\nimport {\n Logger,\n getFileExtension,\n getFileExtensionFromMime,\n getFileExtensionFromUri,\n getFileType,\n normalizeFileName,\n} from '@sendbird/uikit-utils';\n\nimport SBUError from '../libs/SBUError';\nimport nativePermissionGranted from '../utils/nativePermissionGranted';\nimport normalizeFile from '../utils/normalizeFile';\nimport { DocumentPicker, openDocument } from './openDocument.native';\nimport type {\n FilePickerResponse,\n FileServiceInterface,\n OpenCameraOptions,\n OpenDocumentOptions,\n OpenMediaLibraryOptions,\n SaveOptions,\n} from './types';\n\nfunction getAndroidStoragePermissionsByAPILevel(permissionModule: typeof Permissions): Permission[] {\n if (Platform.OS !== 'android') return [];\n\n if (Platform.Version > 32) {\n return [];\n }\n\n if (Platform.Version > 28) {\n return [permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE];\n }\n\n return [\n permissionModule.PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,\n permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,\n ];\n}\n\nconst createNativeFileService = ({\n imagePickerModule,\n documentPickerModule,\n permissionModule,\n mediaLibraryModule,\n fsModule,\n}: {\n imagePickerModule: typeof ImagePicker;\n documentPickerModule: DocumentPicker;\n permissionModule: typeof Permissions;\n mediaLibraryModule: typeof CameraRoll;\n fsModule: typeof FileAccess;\n}): FileServiceInterface => {\n const requiredPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.CAMERA],\n android: [permissionModule.PERMISSIONS.ANDROID.CAMERA],\n default: [],\n });\n const optionalPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.MICROPHONE],\n android: [],\n default: [],\n });\n const mediaLibraryPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.PHOTO_LIBRARY, permissionModule.PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY],\n android: getAndroidStoragePermissionsByAPILevel(permissionModule),\n default: [],\n });\n\n class NativeFileService implements FileServiceInterface {\n async hasCameraPermission(): Promise<boolean> {\n const status = await permissionModule.checkMultiple(requiredPermissions);\n return nativePermissionGranted(status);\n }\n\n async requestCameraPermission(): Promise<boolean> {\n const requiredPermissionsStatus = await permissionModule.requestMultiple(requiredPermissions);\n if (!nativePermissionGranted(requiredPermissionsStatus)) return false;\n\n await permissionModule.requestMultiple(optionalPermissions);\n return true;\n }\n\n async hasMediaLibraryPermission(): Promise<boolean> {\n const status = await permissionModule.checkMultiple(mediaLibraryPermissions);\n return nativePermissionGranted(status);\n }\n\n async requestMediaLibraryPermission(): Promise<boolean> {\n const status = await permissionModule.requestMultiple(mediaLibraryPermissions);\n return nativePermissionGranted(status);\n }\n\n async openCamera(options?: OpenCameraOptions): Promise<FilePickerResponse> {\n const hasPermission = await this.hasCameraPermission();\n if (!hasPermission) {\n const granted = await this.requestCameraPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchCamera({\n presentationStyle: 'fullScreen',\n cameraType: options?.cameraType ?? 'back',\n assetRepresentationMode: 'compatible',\n mediaType: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return 'photo';\n case 'video':\n return 'video';\n case 'all':\n return 'mixed';\n default:\n return 'photo';\n }\n })(),\n });\n if (response.didCancel) return null;\n if (response.errorCode === 'camera_unavailable') {\n options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));\n return null;\n }\n\n const { fileName: name, fileSize: size, type, uri } = response.assets?.[0] ?? {};\n return normalizeFile({ uri, size, name, type });\n }\n\n async openMediaLibrary(options?: OpenMediaLibraryOptions): Promise<FilePickerResponse[] | null> {\n /**\n * NOTE: options.selectionLimit {@link https://github.com/react-native-image-picker/react-native-image-picker#options}\n * We do not support 0 (any number of files)\n **/\n const selectionLimit = options?.selectionLimit || 1;\n const hasPermission = await this.hasMediaLibraryPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchImageLibrary({\n presentationStyle: 'fullScreen',\n selectionLimit,\n assetRepresentationMode: 'compatible',\n mediaType: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return 'photo';\n case 'video':\n return 'video';\n case 'all':\n return 'mixed';\n default:\n return 'photo';\n }\n })(),\n });\n if (response.didCancel) return null;\n if (response.errorCode === 'camera_unavailable') {\n options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));\n return null;\n }\n\n return Promise.all(\n (response.assets || [])\n .slice(0, selectionLimit)\n .map(({ fileName: name, fileSize: size, type, uri }) => normalizeFile({ uri, size, name, type })),\n );\n }\n\n async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {\n return await openDocument(documentPickerModule, options);\n }\n\n async save(options: SaveOptions): Promise<string> {\n const hasPermission = await this.hasMediaLibraryPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryPermission();\n if (!granted) throw new Error('Permission not granted');\n }\n\n const { downloadedPath, file } = await this.downloadFile(options);\n\n if (Platform.OS === 'ios') {\n if (file.type === 'image' || file.type === 'video') {\n const mediaTypeMap = { 'image': 'photo', 'video': 'video' } as const;\n const mediaType = mediaTypeMap[file.type];\n await mediaLibraryModule.save(downloadedPath, { type: mediaType });\n }\n }\n\n if (Platform.OS === 'android') {\n const externalDirMap = { 'file': 'downloads', 'audio': 'audio', 'image': 'images', 'video': 'video' } as const;\n const externalDir = externalDirMap[file.type];\n await fsModule.FileSystem.cpExternal(downloadedPath, file.name, externalDir).catch(() => {\n Logger.error('Failed to save file to external storage. Retry saving to downloads directory instead.');\n return fsModule.FileSystem.cpExternal(downloadedPath, file.name, 'downloads');\n });\n }\n\n return downloadedPath;\n }\n\n private buildDownloadPath = async (options: SaveOptions) => {\n const dirname = Platform.select({ android: fsModule.Dirs.CacheDir, default: fsModule.Dirs.DocumentDir });\n const context = { dirname, filename: options.fileName };\n const extension =\n getFileExtension(options.fileName) ||\n getFileExtensionFromMime(options.fileType) ||\n getFileExtension(options.fileUrl) ||\n (await getFileExtensionFromUri(options.fileUrl));\n\n if (extension) context.filename = normalizeFileName(context.filename, extension);\n\n return { path: `${context.dirname}/${context.filename}`, ...context };\n };\n\n private downloadFile = async (options: SaveOptions) => {\n const { path, filename } = await this.buildDownloadPath(options);\n await fsModule.FileSystem.fetch(options.fileUrl, { path });\n return {\n downloadedPath: path,\n file: {\n name: filename,\n type: getFileType(getFileExtension(path)),\n } as const,\n };\n };\n\n createRecordFilePath(customExtension = 'm4a'): { recordFilePath: string; uri: string } {\n const filename = `record-${Date.now()}.${customExtension}`;\n const path = `${fsModule.Dirs.CacheDir}/${filename}`;\n return Platform.select({\n ios: {\n uri: path,\n recordFilePath: path,\n },\n android: {\n uri: path.startsWith('file://') ? path : 'file://' + path,\n recordFilePath: path,\n },\n default: {\n uri: path,\n recordFilePath: path,\n },\n });\n }\n }\n\n return new NativeFileService();\n};\n\nexport default createNativeFileService;\n"],"mappings":"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","ignoreList":[]}
@@ -1,3 +1,3 @@
1
- const VERSION = '3.12.1';
1
+ const VERSION = '3.12.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.12.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.12.3';\nexport default VERSION;\n"],"mappings":"AAAA,MAAMA,OAAO,GAAG,QAAQ;AACxB,eAAeA,OAAO","ignoreList":[]}
@@ -65,6 +65,5 @@ export type ChannelMessageListProps<T extends SendbirdGroupChannel | SendbirdOpe
65
65
  } & {
66
66
  ref?: Ref<FlatList<SendbirdMessage>> | undefined;
67
67
  };
68
- declare const ChannelMessageList: <T extends SendbirdGroupChannel | SendbirdOpenChannel>({ searchItem, hasNext, channel, onEditMessage, onReplyMessage, onReplyInThreadMessage, onDeleteMessage, onResendFailedMessage, onPressMediaMessage, onPressParentMessage, onPressMarkAsUnreadMessage, currentUserId, renderUnreadMessagesFloating, renderNewMessagesButton, renderScrollToBottomButton, renderMessage, messages, newMessages, unreadFirstMessage, enableMessageGrouping, onScrolledAwayFromBottom, scrolledAwayFromBottom, onBottomReached, onTopReached, flatListComponent, flatListProps, onViewableItemsChanged, onPressNewMessagesButton, onPressScrollToBottomButton, unreadMessagesFloatingProps, }: ChannelMessageListProps<T>, ref: React.ForwardedRef<FlatList<SendbirdMessage>>) => React.JSX.Element;
69
- declare const _default: typeof ChannelMessageList;
68
+ declare const _default: <T extends SendbirdGroupChannel | SendbirdOpenChannel>(props: ChannelMessageListProps<T>) => React.ReactElement | null;
70
69
  export default _default;
@@ -51,6 +51,5 @@ export type ChannelThreadMessageListProps<T extends SendbirdGroupChannel | Sendb
51
51
  } & {
52
52
  ref?: Ref<FlatList<SendbirdMessage>> | undefined;
53
53
  };
54
- declare const ChannelThreadMessageList: <T extends SendbirdGroupChannel | SendbirdOpenChannel>({ searchItem, hasNext, channel, onEditMessage, onDeleteMessage, onResendFailedMessage, onPressMediaMessage, currentUserId, renderNewMessagesButton, renderScrollToBottomButton, renderMessage, messages, newMessages, enableMessageGrouping, onScrolledAwayFromBottom, scrolledAwayFromBottom, onBottomReached, onTopReached, flatListProps, onPressNewMessagesButton, onPressScrollToBottomButton, }: ChannelThreadMessageListProps<T>, ref: React.ForwardedRef<FlatList<SendbirdMessage>>) => React.JSX.Element;
55
- declare const _default: typeof ChannelThreadMessageList;
54
+ declare const _default: <T extends SendbirdGroupChannel | SendbirdOpenChannel>(props: ChannelThreadMessageListProps<T>) => React.ReactElement | null;
56
55
  export default _default;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { SendbirdBaseChannel, SendbirdBaseMessage } from '@sendbird/uikit-utils';
2
+ import type { SendbirdBaseChannel, SendbirdBaseMessage } from '@sendbird/uikit-utils';
3
3
  type Props = {
4
4
  onClose: () => Promise<void>;
5
5
  channel: SendbirdBaseChannel;
@@ -14,6 +14,6 @@ declare class InternalErrorBoundaryContainer extends React.PureComponent<{
14
14
  };
15
15
  componentDidCatch: (error: Error, errorInfo: ErrorInfo) => void;
16
16
  reset: () => void;
17
- render: () => string | number | boolean | React.JSX.Element | Iterable<React.ReactNode> | null;
17
+ render: () => string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null;
18
18
  }
19
19
  export default InternalErrorBoundaryContainer;
@@ -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.12.1";
17
+ VERSION: "3.12.3";
18
18
  PLATFORM: string;
19
19
  DEFAULT: {
20
20
  AUTO_PUSH_TOKEN_REGISTRATION: boolean;
@@ -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" | "remove" | "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" | "reply-filled" | "reply" | "send" | "settings-filled" | "spinner" | "streaming" | "supergroup" | "theme" | "thread" | "thumbnail-none" | "unarchive";
4
+ icon?: "search" | "stop" | "photo" | "recording" | "remove" | "delete" | "message" | "done" | "add" | "user" | "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";
5
5
  iconColor?: string;
6
6
  title: string;
7
7
  titleColor?: string;
@@ -4,7 +4,7 @@ import type { MentionedUser } from '../types';
4
4
  declare const useMentionTextInput: (params: {
5
5
  messageToEdit?: SendbirdUserMessage | SendbirdFileMessage;
6
6
  }) => {
7
- textInputRef: import("react").MutableRefObject<TextInput | undefined>;
7
+ textInputRef: import("react").RefObject<TextInput | undefined>;
8
8
  selection: {
9
9
  start: number;
10
10
  end: number;
@@ -45,7 +45,7 @@ declare class MentionManager {
45
45
  /**
46
46
  * @description Bold @user.nickname
47
47
  * */
48
- textToMentionedComponents: (text: string, mentionedUsers: MentionedUser[], mentionEnabled: boolean) => string | (string | number | boolean | React.JSX.Element | Iterable<React.ReactNode> | null | undefined)[];
48
+ textToMentionedComponents: (text: string, mentionedUsers: MentionedUser[], mentionEnabled: boolean) => string | (string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined)[];
49
49
  textToMentionedMessageTemplate: (text: string, mentionedUsers: MentionedUser[], mentionEnabled: boolean) => string;
50
50
  /**
51
51
  * @description Convert @{user.id} template to @user.nickname text and MentionedUser[] array.
@@ -1,2 +1,2 @@
1
- declare const VERSION = "3.12.1";
1
+ declare const VERSION = "3.12.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.12.1",
3
+ "version": "3.12.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",
@@ -69,10 +69,10 @@
69
69
  },
70
70
  "dependencies": {
71
71
  "@openspacelabs/react-native-zoomable-view": "^2.3.0",
72
- "@sendbird/uikit-chat-hooks": "3.12.1",
73
- "@sendbird/uikit-react-native-foundation": "3.12.1",
72
+ "@sendbird/uikit-chat-hooks": "3.12.3",
73
+ "@sendbird/uikit-react-native-foundation": "3.12.3",
74
74
  "@sendbird/uikit-tools": "0.0.15",
75
- "@sendbird/uikit-utils": "3.12.1"
75
+ "@sendbird/uikit-utils": "3.12.3"
76
76
  },
77
77
  "devDependencies": {
78
78
  "@bam.tech/react-native-image-resizer": "^3.0.11",
@@ -256,5 +256,5 @@
256
256
  ]
257
257
  ]
258
258
  },
259
- "gitHead": "367f6209c4e1db1ec2d44dbdc3e3d3a55c6beb78"
259
+ "gitHead": "6c20512fbcfb708b75339474c47558225e8ce262"
260
260
  }
@@ -526,5 +526,7 @@ const styles = createStyleSheet({
526
526
  },
527
527
  });
528
528
 
529
- // NOTE: Due to Generic inference is not working on forwardRef, we need to cast it as typeof ChannelMessageList and implicit `ref` prop
530
- export default React.forwardRef(ChannelMessageList) as typeof ChannelMessageList;
529
+ // NOTE: Due to Generic inference is not working on forwardRef, we need to cast it properly for React 19 compatibility
530
+ export default React.forwardRef(ChannelMessageList) as <T extends SendbirdGroupChannel | SendbirdOpenChannel>(
531
+ props: ChannelMessageListProps<T>,
532
+ ) => React.ReactElement | null;
@@ -409,5 +409,7 @@ const styles = createStyleSheet({
409
409
  },
410
410
  });
411
411
 
412
- // NOTE: Due to Generic inference is not working on forwardRef, we need to cast it as typeof ChannelMessageList and implicit `ref` prop
413
- export default React.forwardRef(ChannelThreadMessageList) as typeof ChannelThreadMessageList;
412
+ // NOTE: Due to Generic inference is not working on forwardRef, we need to cast it properly for React 19 compatibility
413
+ export default React.forwardRef(ChannelThreadMessageList) as <T extends SendbirdGroupChannel | SendbirdOpenChannel>(
414
+ props: ChannelThreadMessageListProps<T>,
415
+ ) => React.ReactElement | null;
@@ -89,7 +89,7 @@ const ZoomableImageView = ({
89
89
  }) => {
90
90
  const { width, height } = useWindowDimensions();
91
91
 
92
- const imageSize = useRef<{ width: number; height: number }>();
92
+ const imageSize = useRef<{ width: number; height: number } | undefined>(undefined);
93
93
  const [contentSizeProps, setContentSizeProps] = useState<{
94
94
  contentWidth: number;
95
95
  contentHeight: number;
@@ -1,10 +1,11 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { Pressable, View } from 'react-native';
3
3
 
4
4
  import type { BaseMessage } from '@sendbird/chat/message';
5
5
  import { Icon, Image, createStyleSheet, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
6
6
  import { useGroupChannelHandler } from '@sendbird/uikit-tools';
7
- import { Logger, SendbirdBaseChannel, SendbirdBaseMessage, useSafeAreaPadding } from '@sendbird/uikit-utils';
7
+ import { Logger, useSafeAreaPadding } from '@sendbird/uikit-utils';
8
+ import type { SendbirdBaseChannel, SendbirdBaseMessage } from '@sendbird/uikit-utils';
8
9
 
9
10
  import { UNKNOWN_USER_ID } from '../../constants';
10
11
  import { useReaction, useSendbirdChat } from '../../hooks/useContext';
@@ -14,6 +15,57 @@ type Props = {
14
15
  channel: SendbirdBaseChannel;
15
16
  message: SendbirdBaseMessage;
16
17
  };
18
+
19
+ const EmojiReactionPressable = ({
20
+ url,
21
+ reacted,
22
+ selectedBackground,
23
+ enabledBackground,
24
+ onPress,
25
+ }: {
26
+ url: string;
27
+ reacted: boolean;
28
+ selectedBackground: string;
29
+ enabledBackground: string;
30
+ onPress: () => void;
31
+ }) => {
32
+ const [pressed, setPressed] = useState(false);
33
+ return (
34
+ <Pressable
35
+ onPress={onPress}
36
+ onPressIn={() => setPressed(true)}
37
+ onPressOut={() => setPressed(false)}
38
+ style={[styles.button, { backgroundColor: reacted || pressed ? selectedBackground : enabledBackground }]}
39
+ >
40
+ <Image source={{ uri: url }} style={styles.emoji} />
41
+ </Pressable>
42
+ );
43
+ };
44
+
45
+ const EmojiMorePressable = ({
46
+ selectedBackground,
47
+ enabledBackground,
48
+ iconColor,
49
+ onPress,
50
+ }: {
51
+ selectedBackground: string;
52
+ enabledBackground: string;
53
+ iconColor: string;
54
+ onPress: () => void;
55
+ }) => {
56
+ const [pressed, setPressed] = useState(false);
57
+ return (
58
+ <Pressable
59
+ onPress={onPress}
60
+ onPressIn={() => setPressed(true)}
61
+ onPressOut={() => setPressed(false)}
62
+ style={[styles.button, { backgroundColor: pressed ? selectedBackground : enabledBackground }]}
63
+ >
64
+ <Icon icon={'emoji-more'} style={styles.emoji} color={iconColor} />
65
+ </Pressable>
66
+ );
67
+ };
68
+
17
69
  const BottomSheetReactionAddon = ({ onClose, message, channel }: Props) => {
18
70
  const { emojiManager, currentUser, sdk } = useSendbirdChat();
19
71
  const { updateReactionFocusedItem, openReactionList } = useReaction();
@@ -59,31 +111,26 @@ const BottomSheetReactionAddon = ({ onClose, message, channel }: Props) => {
59
111
  };
60
112
 
61
113
  return (
62
- <Pressable
114
+ <EmojiReactionPressable
63
115
  key={key}
116
+ url={url}
117
+ reacted={reacted}
118
+ selectedBackground={color.selected.background}
119
+ enabledBackground={color.enabled.background}
64
120
  onPress={onPress}
65
- style={({ pressed }) => [
66
- styles.button,
67
- { backgroundColor: reacted || pressed ? color.selected.background : color.enabled.background },
68
- ]}
69
- >
70
- <Image source={{ uri: url }} style={styles.emoji} />
71
- </Pressable>
121
+ />
72
122
  );
73
123
  })}
74
124
 
75
- <Pressable
125
+ <EmojiMorePressable
126
+ selectedBackground={color.selected.background}
127
+ enabledBackground={color.enabled.background}
128
+ iconColor={colors.onBackground03}
76
129
  onPress={async () => {
77
130
  await onClose();
78
131
  openReactionList({ channel, message });
79
132
  }}
80
- style={({ pressed }) => [
81
- styles.button,
82
- { backgroundColor: pressed ? color.selected.background : color.enabled.background },
83
- ]}
84
- >
85
- <Icon icon={'emoji-more'} style={styles.emoji} color={colors.onBackground03} />
86
- </Pressable>
133
+ />
87
134
  </View>
88
135
  );
89
136
  };
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import { ImageProps, Pressable } from 'react-native';
1
+ import React, { useState } from 'react';
2
+ import { ImageProps, Pressable, StyleProp, ViewStyle } from 'react-native';
3
3
 
4
4
  import { createStyleSheet, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
5
5
  import { useForceUpdate, useGroupChannelHandler } from '@sendbird/uikit-tools';
@@ -29,6 +29,51 @@ const createOnPressReaction = (
29
29
  };
30
30
  };
31
31
 
32
+ const ReactionPressable = ({
33
+ reaction,
34
+ channel,
35
+ message,
36
+ source,
37
+ onOpenReactionUserList,
38
+ index,
39
+ style,
40
+ }: {
41
+ reaction: SendbirdReaction;
42
+ channel: SendbirdBaseChannel;
43
+ message: SendbirdBaseMessage;
44
+ source: ImageProps['source'];
45
+ onOpenReactionUserList: (focusIndex: number) => void;
46
+ index: number;
47
+ style: StyleProp<ViewStyle>;
48
+ }) => {
49
+ const [pressed, setPressed] = useState(false);
50
+ return (
51
+ <Pressable
52
+ onPress={createOnPressReaction(reaction, channel, message, reaction.hasCurrentUserReacted)}
53
+ onLongPress={() => onOpenReactionUserList(index)}
54
+ delayLongPress={DEFAULT_LONG_PRESS_DELAY}
55
+ onPressIn={() => setPressed(true)}
56
+ onPressOut={() => setPressed(false)}
57
+ >
58
+ <ReactionRoundedButton
59
+ source={source}
60
+ count={getReactionCount(reaction)}
61
+ reacted={pressed || reaction.hasCurrentUserReacted}
62
+ style={style}
63
+ />
64
+ </Pressable>
65
+ );
66
+ };
67
+
68
+ const ReactionMorePressable = ({ onPress }: { onPress: () => void }) => {
69
+ const [pressed, setPressed] = useState(false);
70
+ return (
71
+ <Pressable onPress={onPress} onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)}>
72
+ <ReactionRoundedButton.More pressed={pressed} />
73
+ </Pressable>
74
+ );
75
+ };
76
+
32
77
  const createReactionButtons = (
33
78
  channel: SendbirdBaseChannel,
34
79
  message: SendbirdBaseMessage,
@@ -43,33 +88,24 @@ const createReactionButtons = (
43
88
  const isNotLastOfRow = index % NUM_COL !== NUM_COL - 1;
44
89
  const isNotLastOfCol = index < NUM_COL && reactions.length >= NUM_COL;
45
90
  return (
46
- <Pressable
91
+ <ReactionPressable
47
92
  key={reaction.key}
48
- onPress={createOnPressReaction(reaction, channel, message, reaction.hasCurrentUserReacted)}
49
- onLongPress={() => onOpenReactionUserList(index)}
50
- delayLongPress={DEFAULT_LONG_PRESS_DELAY}
51
- >
52
- {({ pressed }) => (
53
- <ReactionRoundedButton
54
- source={getIconSource(reaction.key)}
55
- count={getReactionCount(reaction)}
56
- reacted={pressed || reaction.hasCurrentUserReacted}
57
- style={
58
- reactionAddonType === 'default'
59
- ? [isNotLastOfRow && styles.marginEnd, isNotLastOfCol && styles.marginBottom]
60
- : [styles.marginEnd, styles.marginBottom]
61
- }
62
- />
63
- )}
64
- </Pressable>
93
+ reaction={reaction}
94
+ channel={channel}
95
+ message={message}
96
+ source={getIconSource(reaction.key)}
97
+ onOpenReactionUserList={onOpenReactionUserList}
98
+ index={index}
99
+ style={
100
+ reactionAddonType === 'default'
101
+ ? [isNotLastOfRow && styles.marginEnd, isNotLastOfCol && styles.marginBottom]
102
+ : [styles.marginEnd, styles.marginBottom]
103
+ }
104
+ />
65
105
  );
66
106
  });
67
107
  if (buttons.length < emojiLimit) {
68
- buttons.push(
69
- <Pressable key={REACTION_MORE_KEY} onPress={onOpenReactionList}>
70
- {({ pressed }) => <ReactionRoundedButton.More pressed={pressed} />}
71
- </Pressable>,
72
- );
108
+ buttons.push(<ReactionMorePressable key={REACTION_MORE_KEY} onPress={onOpenReactionList} />);
73
109
  }
74
110
 
75
111
  return buttons;