1- import React , { PropsWithChildren , useMemo } from 'react' ;
2- import { View , StyleSheet , Rationale , TouchableOpacity , Dimensions , Image } from 'react-native' ;
1+ import React , { PropsWithChildren , useMemo , ComponentType } from 'react' ;
2+ import {
3+ View ,
4+ StyleSheet ,
5+ Rationale ,
6+ TouchableOpacity ,
7+ ModalProps ,
8+ ImageURISource ,
9+ ImageRequireSource ,
10+ } from 'react-native' ;
311import { CameraOptions , ImagePickerResponse } from 'react-native-image-picker' ;
4- import { Theme , Flex , ActionSheet , ActionSheetItem , MaskLayer , TransitionImage , Icon , Text } from '@uiw/react-native' ;
12+ import { Theme , Flex , ActionSheet , ActionSheetItem , TransitionImage , Icon , Text } from '@uiw/react-native' ;
13+ import ImageView from 'react-native-image-viewing' ;
514import { useTheme } from '@shopify/restyle' ;
615import useImagePicker from './useImagePicker' ;
716
17+ export type ImageSource = ImageURISource | ImageRequireSource ;
818export interface File {
919 fileName : string ;
1020 fileType : string ;
@@ -24,17 +34,19 @@ export type ImagePickerProps = PropsWithChildren<{
2434 /** 上传图片后是否在背景图展示,如果为 true 上传后会自动展示上传图片(此时只能上传一张) */
2535 showUploadImg ?: boolean ;
2636 /** 上传文件之前的钩子,参数为上传的文件,若返回 false 则停止上传,同时可以在里面执行一些上传提示操作 */
27- beforeUpload ?: ( file : File ) => boolean | ( ( file : File ) => Promise < boolean > ) ;
37+ beforeUpload ?: ( file : File [ ] ) => boolean | ( ( file : File ) => Promise < boolean > ) ;
2838 /** 上传 */
29- upload ?: ( file : File ) => Promise < string > ;
39+ upload ?: ( file : File [ ] ) => string [ ] ;
3040 /** 上传完成 */
31- uploadFinish ?: ( result ?: string ) => void ;
41+ uploadFinish ?: ( result ?: string [ ] | undefined ) => void ;
3242 /** 取消上传事件回调 */
3343 onCancel ?: ( response : ImagePickerResponse ) => void ;
3444 /** 上传失败事件回调 */
3545 onFail ?: ( response : ImagePickerResponse ) => void ;
3646 /** 授权失败的回调 */
3747 onGrantFail ?: ( ) => void ;
48+ /** 预览时长按图片保存回调 */
49+ onSave ?: ( ( image : any ) => void ) | undefined ;
3850 /** 打开相册授权的文本 */
3951 libraryRationale ?: Rationale ;
4052 /** 打开摄像头授权的文本 */
@@ -43,11 +55,29 @@ export type ImagePickerProps = PropsWithChildren<{
4355 launchLibraryText ?: string ;
4456 /** 打开摄像头文本 */
4557 launchCameraText ?: string ;
58+ /** 从相册选择多少张图片 */
59+ selectionLimit ?: number ;
60+ // ImageViewProps
61+ onLongPress ?: ( image : ImageSource ) => void ;
62+ onImageIndexChange ?: ( imageIndex : number ) => void ;
63+ presentationStyle ?: ModalProps [ 'presentationStyle' ] ;
64+ animationType ?: ModalProps [ 'animationType' ] ;
65+ backgroundColor ?: string ;
66+ swipeToCloseEnabled ?: boolean ;
67+ doubleTapToZoomEnabled ?: boolean ;
68+ delayLongPress ?: number ;
69+ HeaderComponent ?: ComponentType < {
70+ imageIndex : number ;
71+ } > ;
72+ FooterComponent ?: ComponentType < {
73+ imageIndex : number ;
74+ } > ;
4675} > ;
4776
4877const ImagePicker = ( {
4978 width = 100 ,
5079 height = 100 ,
80+ selectionLimit = 1 ,
5181 value = [ ] ,
5282 options,
5383 showUploadImg = true ,
@@ -72,7 +102,8 @@ const ImagePicker = ({
72102 buttonNeutral : '下次再说' ,
73103 } ,
74104 launchLibraryText = '打开相册' ,
75- launchCameraText = '打开摄像头' ,
105+ launchCameraText = '打开相机' ,
106+ ...others
76107} : ImagePickerProps ) => {
77108 const theme = useTheme < Theme > ( ) ;
78109 const styles = createStyles ( {
@@ -84,7 +115,7 @@ const ImagePicker = ({
84115
85116 const {
86117 currentImgSource,
87- previewSrc ,
118+ current ,
88119 loading,
89120 launchLibrary,
90121 launchCamera,
@@ -106,6 +137,7 @@ const ImagePicker = ({
106137 onGrantFail,
107138 cameraRationale,
108139 libraryRationale,
140+ selectionLimit,
109141 } ) ;
110142
111143 const pictureList = useMemo ( ( ) => {
@@ -136,9 +168,14 @@ const ImagePicker = ({
136168 return null ;
137169 } , [ showUploadImg , JSON . stringify ( currentImgSource ) ] ) ;
138170
171+ const previewImages = useMemo ( ( ) => {
172+ return currentImgSource . map ( ( item ) => ( { uri : item } ) ) ;
173+ } , [ JSON . stringify ( currentImgSource ) , current ] ) ;
174+
139175 return (
140176 < View >
141177 < Flex justify = "start" wrap = "wrap" >
178+ { pictureList }
142179 < Flex . Item >
143180 < View style = { styles . box } >
144181 < TouchableOpacity
@@ -147,21 +184,22 @@ const ImagePicker = ({
147184 disabled = { loading }
148185 style = { { justifyContent : 'center' , alignItems : 'center' , width, height } }
149186 >
150- < Icon name = "plus-square-o" color = " #A9A9A9" size = { 20 } />
187+ < Icon name = "plus-square-o" color = { theme . colors . text || ' #A9A9A9' } size = { 20 } />
151188 </ TouchableOpacity >
152189 </ View >
153190 </ Flex . Item >
154- { pictureList }
155191 </ Flex >
156- < ActionSheet onCancel = { setLaunchVisibleFalse } visible = { launchVisible } style = { { zIndex : 99 } } >
192+ < ActionSheet onCancel = { setLaunchVisibleFalse } visible = { launchVisible } >
157193 < ActionSheetItem onPress = { launchLibrary } > { launchLibraryText } </ ActionSheetItem >
158194 < ActionSheetItem onPress = { launchCamera } > { launchCameraText } </ ActionSheetItem >
159195 </ ActionSheet >
160- < MaskLayer visible = { previewVisible } style = { { zIndex : 999 } } onDismiss = { closePreviewImage } opacity = { 0.9 } >
161- < View style = { styles . content } >
162- < Image style = { styles . image } source = { { uri : previewSrc } } />
163- </ View >
164- </ MaskLayer >
196+ < ImageView
197+ visible = { previewVisible }
198+ onRequestClose = { closePreviewImage }
199+ imageIndex = { current || 0 }
200+ images = { previewImages }
201+ { ...others }
202+ />
165203 </ View >
166204 ) ;
167205} ;
@@ -180,15 +218,6 @@ function createStyles({ width = 100, height = 100, borderColor = '#CCCCCC', back
180218 backgroundColor : backgroundColor ,
181219 margin : 4 ,
182220 } ,
183- content : {
184- marginTop : Dimensions . get ( 'window' ) . width / 3 - 20 ,
185- height : Dimensions . get ( 'window' ) . height / 3 - 20 ,
186- } ,
187- image : {
188- width : '100%' ,
189- height : '100%' ,
190- resizeMode : 'contain' ,
191- } ,
192221 previewBox : {
193222 position : 'absolute' ,
194223 left : 0 ,
0 commit comments