@plusscommunities/pluss-core-app 8.0.0 → 8.0.1-auth.0

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 (320) hide show
  1. package/dist/module/actions/FollowerActions.js +4 -4
  2. package/dist/module/actions/FollowerActions.js.map +1 -1
  3. package/dist/module/actions/MediaActions.js +1 -1
  4. package/dist/module/actions/MediaActions.js.map +1 -1
  5. package/dist/module/actions/ResidentActions.js +1 -1
  6. package/dist/module/actions/ResidentActions.js.map +1 -1
  7. package/dist/module/actions/UserActions.js +1 -1
  8. package/dist/module/actions/UserActions.js.map +1 -1
  9. package/dist/module/actions/UserSettingsActions.js +1 -1
  10. package/dist/module/actions/UserSettingsActions.js.map +1 -1
  11. package/dist/module/actions/index.js +5 -5
  12. package/dist/module/actions/index.js.map +1 -1
  13. package/dist/module/actions/types.js +16 -16
  14. package/dist/module/actions/types.js.map +1 -1
  15. package/dist/module/apis/analyticsActions.js +5 -5
  16. package/dist/module/apis/analyticsActions.js.map +1 -1
  17. package/dist/module/apis/contactActions.js +6 -6
  18. package/dist/module/apis/contactActions.js.map +1 -1
  19. package/dist/module/apis/eventActions.js +28 -28
  20. package/dist/module/apis/eventActions.js.map +1 -1
  21. package/dist/module/apis/fileActions.js +15 -15
  22. package/dist/module/apis/fileActions.js.map +1 -1
  23. package/dist/module/apis/followerActions.js +8 -8
  24. package/dist/module/apis/followerActions.js.map +1 -1
  25. package/dist/module/apis/index.js +12 -12
  26. package/dist/module/apis/index.js.map +1 -1
  27. package/dist/module/apis/notificationActions.js +17 -17
  28. package/dist/module/apis/notificationActions.js.map +1 -1
  29. package/dist/module/apis/profileActions.js +4 -4
  30. package/dist/module/apis/profileActions.js.map +1 -1
  31. package/dist/module/apis/reactionActions.js +15 -15
  32. package/dist/module/apis/reactionActions.js.map +1 -1
  33. package/dist/module/apis/settingActions.js +6 -6
  34. package/dist/module/apis/settingActions.js.map +1 -1
  35. package/dist/module/apis/stringActions.js +8 -8
  36. package/dist/module/apis/stringActions.js.map +1 -1
  37. package/dist/module/apis/typeActions.js +4 -4
  38. package/dist/module/apis/typeActions.js.map +1 -1
  39. package/dist/module/apis/userActions.js +8 -8
  40. package/dist/module/apis/userActions.js.map +1 -1
  41. package/dist/module/assets/icons/fontawesome/fa-brands-400.ttf +0 -0
  42. package/dist/module/assets/icons/fontawesome/fa-light-300.ttf +0 -0
  43. package/dist/module/assets/icons/fontawesome/fa-regular-400.ttf +0 -0
  44. package/dist/module/assets/icons/fontawesome/fa-solid-900.ttf +0 -0
  45. package/dist/module/assets/icons/fontawesome/fa-thin-100.ttf +0 -0
  46. package/dist/module/assets/icons/fontawesome/fa7-glyphmap.json +4205 -0
  47. package/dist/module/colours.js +26 -29
  48. package/dist/module/colours.js.map +1 -1
  49. package/dist/module/components/AddButton.js +8 -8
  50. package/dist/module/components/AddButton.js.map +1 -1
  51. package/dist/module/components/AddToCalendarButton.js +30 -29
  52. package/dist/module/components/AddToCalendarButton.js.map +1 -1
  53. package/dist/module/components/Attachment.js +10 -9
  54. package/dist/module/components/Attachment.js.map +1 -1
  55. package/dist/module/components/AudienceSelectorLauncher.js +11 -11
  56. package/dist/module/components/AudienceSelectorLauncher.js.map +1 -1
  57. package/dist/module/components/AudienceSelectorPage.js +45 -44
  58. package/dist/module/components/AudienceSelectorPage.js.map +1 -1
  59. package/dist/module/components/AutoOffsetImage.js +13 -13
  60. package/dist/module/components/AutoOffsetImage.js.map +1 -1
  61. package/dist/module/components/BackButton.js +10 -10
  62. package/dist/module/components/BackButton.js.map +1 -1
  63. package/dist/module/components/CalendarPopup.js +21 -21
  64. package/dist/module/components/CalendarPopup.js.map +1 -1
  65. package/dist/module/components/CategoryTabs.js +30 -29
  66. package/dist/module/components/CategoryTabs.js.map +1 -1
  67. package/dist/module/components/CommentReply.js +43 -37
  68. package/dist/module/components/CommentReply.js.map +1 -1
  69. package/dist/module/components/CommentSection.js +74 -74
  70. package/dist/module/components/CommentSection.js.map +1 -1
  71. package/dist/module/components/ConfirmPopup.js +21 -20
  72. package/dist/module/components/ConfirmPopup.js.map +1 -1
  73. package/dist/module/components/ConfirmationPopup.js +11 -11
  74. package/dist/module/components/ConfirmationPopup.js.map +1 -1
  75. package/dist/module/components/DocumentUploader.js +50 -50
  76. package/dist/module/components/DocumentUploader.js.map +1 -1
  77. package/dist/module/components/DropDownItem.js +14 -13
  78. package/dist/module/components/DropDownItem.js.map +1 -1
  79. package/dist/module/components/DropDownMenu.js +5 -5
  80. package/dist/module/components/DropDownMenu.js.map +1 -1
  81. package/dist/module/components/EmptyStateMain.js +10 -9
  82. package/dist/module/components/EmptyStateMain.js.map +1 -1
  83. package/dist/module/components/EmptyStateWidget.js +7 -6
  84. package/dist/module/components/EmptyStateWidget.js.map +1 -1
  85. package/dist/module/components/FontScaleButton.js +5 -4
  86. package/dist/module/components/FontScaleButton.js.map +1 -1
  87. package/dist/module/components/FontScalePopup.js +11 -10
  88. package/dist/module/components/FontScalePopup.js.map +1 -1
  89. package/dist/module/components/Forbidden.js +13 -13
  90. package/dist/module/components/Forbidden.js.map +1 -1
  91. package/dist/module/components/FormCard.js +4 -4
  92. package/dist/module/components/FormCard.js.map +1 -1
  93. package/dist/module/components/FormCardSection.js +20 -18
  94. package/dist/module/components/FormCardSection.js.map +1 -1
  95. package/dist/module/components/FormCardSectionOptionLauncher.js +13 -12
  96. package/dist/module/components/FormCardSectionOptionLauncher.js.map +1 -1
  97. package/dist/module/components/FormattedText.js +18 -16
  98. package/dist/module/components/FormattedText.js.map +1 -1
  99. package/dist/module/components/GenericInput.js +24 -21
  100. package/dist/module/components/GenericInput.js.map +1 -1
  101. package/dist/module/components/GenericInputSection.js +27 -26
  102. package/dist/module/components/GenericInputSection.js.map +1 -1
  103. package/dist/module/components/Header.js +70 -69
  104. package/dist/module/components/Header.js.map +1 -1
  105. package/dist/module/components/Icon.js +109 -0
  106. package/dist/module/components/Icon.js.map +1 -0
  107. package/dist/module/components/ImagePopup.js +211 -73
  108. package/dist/module/components/ImagePopup.js.map +1 -1
  109. package/dist/module/components/ImageUploadProgress.js +10 -9
  110. package/dist/module/components/ImageUploadProgress.js.map +1 -1
  111. package/dist/module/components/ImageUploader.js +116 -96
  112. package/dist/module/components/ImageUploader.js.map +1 -1
  113. package/dist/module/components/InlineButton.js +9 -8
  114. package/dist/module/components/InlineButton.js.map +1 -1
  115. package/dist/module/components/Input.js +28 -26
  116. package/dist/module/components/Input.js.map +1 -1
  117. package/dist/module/components/LoadingCircles.js +20 -20
  118. package/dist/module/components/LoadingCircles.js.map +1 -1
  119. package/dist/module/components/LoadingIndicator.js +11 -11
  120. package/dist/module/components/LoadingIndicator.js.map +1 -1
  121. package/dist/module/components/LoadingStateWidget.js +5 -5
  122. package/dist/module/components/LoadingStateWidget.js.map +1 -1
  123. package/dist/module/components/MediaPlayer.js +31 -31
  124. package/dist/module/components/MediaPlayer.js.map +1 -1
  125. package/dist/module/components/MiddlePopup.js +17 -11
  126. package/dist/module/components/MiddlePopup.js.map +1 -1
  127. package/dist/module/components/PDFPopup.js +52 -39
  128. package/dist/module/components/PDFPopup.js.map +1 -1
  129. package/dist/module/components/PlussChat.js +168 -149
  130. package/dist/module/components/PlussChat.js.map +1 -1
  131. package/dist/module/components/PlussChatMessage.js +42 -42
  132. package/dist/module/components/PlussChatMessage.js.map +1 -1
  133. package/dist/module/components/PlussChatTime.js +18 -17
  134. package/dist/module/components/PlussChatTime.js.map +1 -1
  135. package/dist/module/components/Popup.js +20 -19
  136. package/dist/module/components/Popup.js.map +1 -1
  137. package/dist/module/components/PopupMenu.js +15 -14
  138. package/dist/module/components/PopupMenu.js.map +1 -1
  139. package/dist/module/components/PositionedImage.js +20 -20
  140. package/dist/module/components/PositionedImage.js.map +1 -1
  141. package/dist/module/components/ProfilePic.js +10 -10
  142. package/dist/module/components/ProfilePic.js.map +1 -1
  143. package/dist/module/components/RadioButton.js +10 -9
  144. package/dist/module/components/RadioButton.js.map +1 -1
  145. package/dist/module/components/Reaction.js +18 -17
  146. package/dist/module/components/Reaction.js.map +1 -1
  147. package/dist/module/components/Reactions.js +7 -7
  148. package/dist/module/components/Reactions.js.map +1 -1
  149. package/dist/module/components/SharingTools.js +78 -43
  150. package/dist/module/components/SharingTools.js.map +1 -1
  151. package/dist/module/components/Spinner.js +5 -5
  152. package/dist/module/components/Spinner.js.map +1 -1
  153. package/dist/module/components/StickyFooter.js +6 -6
  154. package/dist/module/components/StickyFooter.js.map +1 -1
  155. package/dist/module/components/Text.js +57 -0
  156. package/dist/module/components/Text.js.map +1 -0
  157. package/dist/module/components/TickIcon.js +6 -6
  158. package/dist/module/components/TickIcon.js.map +1 -1
  159. package/dist/module/components/Toggle.js +10 -9
  160. package/dist/module/components/Toggle.js.map +1 -1
  161. package/dist/module/components/TouchableSearchBar.js +18 -17
  162. package/dist/module/components/TouchableSearchBar.js.map +1 -1
  163. package/dist/module/components/UserListPopup.js +20 -19
  164. package/dist/module/components/UserListPopup.js.map +1 -1
  165. package/dist/module/components/UserListing.js +41 -40
  166. package/dist/module/components/UserListing.js.map +1 -1
  167. package/dist/module/components/VideoPopup.js +20 -20
  168. package/dist/module/components/VideoPopup.js.map +1 -1
  169. package/dist/module/components/WarningPopup.js +21 -20
  170. package/dist/module/components/WarningPopup.js.map +1 -1
  171. package/dist/module/components/expo-image-picker-multiple/ImageBrowser.js +13 -13
  172. package/dist/module/components/expo-image-picker-multiple/ImageBrowser.js.map +1 -1
  173. package/dist/module/components/expo-image-picker-multiple/ImageTile.js +24 -23
  174. package/dist/module/components/expo-image-picker-multiple/ImageTile.js.map +1 -1
  175. package/dist/module/components/index.js +59 -58
  176. package/dist/module/components/index.js.map +1 -1
  177. package/dist/module/components/react-native-expo-image-cropper/ExpoImageManipulator.js +94 -64
  178. package/dist/module/components/react-native-expo-image-cropper/ExpoImageManipulator.js.map +1 -1
  179. package/dist/module/components/react-native-expo-image-cropper/ImageCropOverlay.js +64 -64
  180. package/dist/module/components/react-native-expo-image-cropper/ImageCropOverlay.js.map +1 -1
  181. package/dist/module/config.js +15 -10
  182. package/dist/module/config.js.map +1 -1
  183. package/dist/module/constants.js +3 -4
  184. package/dist/module/constants.js.map +1 -1
  185. package/dist/module/helper.js +83 -82
  186. package/dist/module/helper.js.map +1 -1
  187. package/dist/module/index.js +12 -12
  188. package/dist/module/index.js.map +1 -1
  189. package/dist/module/js/images/detectFaces.js +11 -10
  190. package/dist/module/js/images/detectFaces.js.map +1 -1
  191. package/dist/module/js/images/findLandmarkRange.js +8 -8
  192. package/dist/module/js/images/findLandmarkRange.js.map +1 -1
  193. package/dist/module/js/images/getScaledOffset.js.map +1 -1
  194. package/dist/module/js/site/getSiteLevelFromState.js +2 -2
  195. package/dist/module/js/site/getSiteLevelFromState.js.map +1 -1
  196. package/dist/module/js/site/isTVEnabled.js +2 -2
  197. package/dist/module/js/site/isTVEnabled.js.map +1 -1
  198. package/dist/module/session.js +6 -6
  199. package/dist/module/session.js.map +1 -1
  200. package/dist/module/styles.js +17 -17
  201. package/dist/module/styles.js.map +1 -1
  202. package/dist/module/withNavigationFocus.js +30 -0
  203. package/dist/module/withNavigationFocus.js.map +1 -0
  204. package/package.json +71 -68
  205. package/src/actions/FollowerActions.js +36 -32
  206. package/src/actions/MediaActions.js +25 -20
  207. package/src/actions/ResidentActions.js +26 -21
  208. package/src/actions/UserActions.js +22 -22
  209. package/src/actions/UserSettingsActions.js +11 -11
  210. package/src/actions/index.js +5 -5
  211. package/src/actions/types.js +16 -16
  212. package/src/apis/analyticsActions.js +17 -17
  213. package/src/apis/contactActions.js +20 -20
  214. package/src/apis/eventActions.js +153 -144
  215. package/src/apis/fileActions.js +96 -86
  216. package/src/apis/followerActions.js +29 -29
  217. package/src/apis/index.js +12 -12
  218. package/src/apis/notificationActions.js +44 -44
  219. package/src/apis/profileActions.js +8 -8
  220. package/src/apis/reactionActions.js +81 -73
  221. package/src/apis/settingActions.js +15 -15
  222. package/src/apis/stringActions.js +29 -25
  223. package/src/apis/typeActions.js +10 -10
  224. package/src/apis/userActions.js +93 -93
  225. package/src/assets/icons/fontawesome/fa-brands-400.ttf +0 -0
  226. package/src/assets/icons/fontawesome/fa-light-300.ttf +0 -0
  227. package/src/assets/icons/fontawesome/fa-regular-400.ttf +0 -0
  228. package/src/assets/icons/fontawesome/fa-solid-900.ttf +0 -0
  229. package/src/assets/icons/fontawesome/fa-thin-100.ttf +0 -0
  230. package/src/assets/icons/fontawesome/fa7-glyphmap.json +4205 -0
  231. package/src/colours.js +116 -96
  232. package/src/components/AddButton.js +32 -27
  233. package/src/components/AddToCalendarButton.js +236 -202
  234. package/src/components/Attachment.js +59 -36
  235. package/src/components/AudienceSelectorLauncher.js +52 -48
  236. package/src/components/AudienceSelectorPage.js +353 -311
  237. package/src/components/AutoOffsetImage.js +237 -196
  238. package/src/components/BackButton.js +57 -41
  239. package/src/components/CalendarPopup.js +127 -97
  240. package/src/components/CategoryTabs.js +208 -163
  241. package/src/components/CommentReply.js +370 -309
  242. package/src/components/CommentSection.js +974 -781
  243. package/src/components/ConfirmPopup.js +141 -110
  244. package/src/components/ConfirmationPopup.js +80 -69
  245. package/src/components/DocumentUploader.js +245 -215
  246. package/src/components/DropDownItem.js +70 -60
  247. package/src/components/DropDownMenu.js +31 -27
  248. package/src/components/EmptyStateMain.js +51 -44
  249. package/src/components/EmptyStateWidget.js +47 -38
  250. package/src/components/FontScaleButton.js +29 -25
  251. package/src/components/FontScalePopup.js +67 -56
  252. package/src/components/Forbidden.js +48 -46
  253. package/src/components/FormCard.js +21 -17
  254. package/src/components/FormCardSection.js +284 -233
  255. package/src/components/FormCardSectionOptionLauncher.js +72 -46
  256. package/src/components/FormattedText.js +128 -111
  257. package/src/components/GenericInput.js +168 -136
  258. package/src/components/GenericInputSection.js +209 -161
  259. package/src/components/Header.js +620 -474
  260. package/src/components/Icon.js +119 -0
  261. package/src/components/ImagePopup.js +425 -221
  262. package/src/components/ImageUploadProgress.js +49 -41
  263. package/src/components/ImageUploader.js +968 -797
  264. package/src/components/InlineButton.js +79 -69
  265. package/src/components/Input.js +190 -156
  266. package/src/components/LoadingCircles.js +233 -233
  267. package/src/components/LoadingIndicator.js +87 -76
  268. package/src/components/LoadingStateWidget.js +47 -37
  269. package/src/components/MediaPlayer.js +416 -387
  270. package/src/components/MiddlePopup.js +62 -33
  271. package/src/components/PDFPopup.js +212 -159
  272. package/src/components/PlussChat.js +1224 -1025
  273. package/src/components/PlussChatMessage.js +329 -298
  274. package/src/components/PlussChatTime.js +57 -53
  275. package/src/components/Popup.js +138 -116
  276. package/src/components/PopupMenu.js +140 -110
  277. package/src/components/PositionedImage.js +281 -237
  278. package/src/components/ProfilePic.js +122 -113
  279. package/src/components/RadioButton.js +76 -52
  280. package/src/components/Reaction.js +134 -96
  281. package/src/components/Reactions.js +65 -63
  282. package/src/components/SharingTools.js +185 -134
  283. package/src/components/Spinner.js +13 -13
  284. package/src/components/StickyFooter.js +36 -26
  285. package/src/components/Text.js +62 -0
  286. package/src/components/TickIcon.js +20 -20
  287. package/src/components/Toggle.js +74 -73
  288. package/src/components/TouchableSearchBar.js +68 -50
  289. package/src/components/UserListPopup.js +161 -124
  290. package/src/components/UserListing.js +273 -238
  291. package/src/components/VideoPopup.js +110 -96
  292. package/src/components/WarningPopup.js +92 -71
  293. package/src/components/expo-image-picker-multiple/ImageBrowser.js +288 -256
  294. package/src/components/expo-image-picker-multiple/ImageTile.js +108 -84
  295. package/src/components/index.js +59 -58
  296. package/src/components/react-native-expo-image-cropper/ExpoImageManipulator.js +444 -359
  297. package/src/components/react-native-expo-image-cropper/ImageCropOverlay.js +420 -324
  298. package/src/config.js +26 -21
  299. package/src/constants.js +8 -10
  300. package/src/helper.js +469 -438
  301. package/src/index.js +24 -12
  302. package/src/js/images/detectFaces.js +28 -21
  303. package/src/js/images/findLandmarkRange.js +97 -90
  304. package/src/js/images/getScaledOffset.js +80 -75
  305. package/src/js/site/getSiteLevelFromState.js +26 -26
  306. package/src/js/site/isTVEnabled.js +10 -10
  307. package/src/session.js +32 -32
  308. package/src/styles.js +61 -61
  309. package/src/withNavigationFocus.js +28 -0
  310. package/dist/module/components/TextStyle.js +0 -45
  311. package/dist/module/components/TextStyle.js.map +0 -1
  312. package/dist/module/fonts/index.js +0 -2
  313. package/dist/module/fonts/index.js.map +0 -1
  314. package/dist/module/fonts/pluss60-icons.js +0 -5
  315. package/dist/module/fonts/pluss60-icons.js.map +0 -1
  316. package/dist/module/fonts/pluss60-icons.json +0 -1097
  317. package/src/components/TextStyle.js +0 -48
  318. package/src/fonts/index.js +0 -1
  319. package/src/fonts/pluss60-icons.js +0 -7
  320. package/src/fonts/pluss60-icons.json +0 -1097
@@ -1,375 +1,460 @@
1
- import React, { Component } from 'react';
1
+ import React, { Component } from "react";
2
+ import { Text } from "@plusscommunities/pluss-core-app/components";
2
3
  import {
3
- Dimensions,
4
- Image,
5
- ScrollView,
6
- Modal,
7
- View,
8
- Text,
9
- SafeAreaView,
10
- TouchableOpacity,
11
- StyleSheet,
12
- Platform,
13
- LogBox,
14
- } from 'react-native';
15
- import * as ImageManipulator from 'expo-image-manipulator';
16
- import PropTypes from 'prop-types';
17
- import AutoHeightImage from 'react-native-auto-height-image';
18
- import { isIphoneX, getStatusBarHeight } from 'react-native-iphone-x-helper';
19
- import ImageCropOverlay from './ImageCropOverlay';
20
-
21
- const { width } = Dimensions.get('window');
22
- const topMargin = getStatusBarHeight() + (Platform.OS === 'ios' ? 50 : 20);
23
-
24
- LogBox.ignoreLogs(['componentWillReceiveProps', 'componentWillUpdate', 'componentWillMount']);
4
+ Dimensions,
5
+ Image,
6
+ ScrollView,
7
+ Modal,
8
+ View,
9
+ TouchableOpacity,
10
+ StyleSheet,
11
+ Platform,
12
+ LogBox,
13
+ Alert,
14
+ } from "react-native";
15
+ import * as ImageManipulator from "expo-image-manipulator";
16
+ import * as MediaLibrary from "expo-media-library";
17
+ import { File, Paths } from "expo-file-system";
18
+ import PropTypes from "prop-types";
19
+ import AutoHeightImage from "react-native-auto-height-image";
20
+ import {
21
+ withSafeAreaInsets,
22
+ SafeAreaView,
23
+ } from "react-native-safe-area-context";
24
+ import ImageCropOverlay from "./ImageCropOverlay";
25
+
26
+ const { width } = Dimensions.get("window");
27
+
28
+ LogBox.ignoreLogs([
29
+ "componentWillReceiveProps",
30
+ "componentWillUpdate",
31
+ "componentWillMount",
32
+ ]);
25
33
  LogBox.ignoreLogs([
26
- 'Warning: componentWillMount is deprecated',
27
- 'Warning: componentWillReceiveProps is deprecated',
28
- 'Module RCTImageLoader requires',
34
+ "Warning: componentWillMount is deprecated",
35
+ "Warning: componentWillReceiveProps is deprecated",
36
+ "Module RCTImageLoader requires",
29
37
  ]);
30
38
 
31
39
  class ExpoImageManipulator extends Component {
32
- constructor(props) {
33
- super(props);
34
- const { squareAspect } = this.props;
35
- this.state = {
36
- cropMode: false,
37
- processing: false,
38
- squareAspect,
39
- };
40
-
41
- this.scrollOffset = 0;
42
- this.currentPos = { left: 0, top: 0 };
43
- this.currentSize = { width: 0, height: 0 };
44
- this.maxSizes = { width: 0, height: 0 };
45
- this.actualSize = { width: 0, height: 0 };
46
- }
47
-
48
- async componentDidMount() {
49
- await this.onConvertImageToEditableSize();
50
-
51
- // Set cropping by default
52
- this.setState({ cropMode: true });
53
- }
54
-
55
- async onConvertImageToEditableSize() {
56
- const {
57
- photo: { uri: rawUri },
58
- } = this.props;
59
- const { uri, width, height } = await ImageManipulator.manipulateAsync(rawUri, [{ resize: { width: 1080 } }]);
60
- this.setState({ uri });
61
- this.actualSize.width = width;
62
- this.actualSize.height = height;
63
- }
64
-
65
- onToggleModal = () => {
66
- this.props.onToggleModal();
67
- this.setState({ cropMode: false });
68
- };
69
-
70
- onCropImage = (callback = null) => {
71
- this.setState({ processing: true });
72
- const { uri } = this.state;
73
- Image.getSize(uri, async (actualWidth, actualHeight) => {
74
- let cropObj = this.getCropBounds(actualWidth, actualHeight);
75
- if (cropObj.height > 0 && cropObj.width > 0) {
76
- let uriToCrop = uri;
77
- const { uri: uriCroped, base64, width: croppedWidth, height: croppedHeight } = await this.crop(cropObj, uriToCrop);
78
-
79
- this.actualSize.width = croppedWidth;
80
- this.actualSize.height = croppedHeight;
81
-
82
- this.setState(
83
- {
84
- uri: uriCroped,
85
- base64,
86
- cropMode: false,
87
- processing: false,
88
- },
89
- () => {
90
- if (callback) callback();
91
- },
92
- );
93
- } else {
94
- this.setState({ cropMode: false, processing: false }, () => {
95
- if (callback) callback();
96
- });
97
- }
98
- });
99
- };
100
-
101
- onHandleScroll = event => {
102
- this.scrollOffset = event.nativeEvent.contentOffset.y;
103
- };
104
-
105
- getCropBounds = (actualWidth, actualHeight) => {
106
- let imageRatio = actualHeight / actualWidth;
107
- var originalHeight = Dimensions.get('window').height - 64;
108
- if (isIphoneX()) {
109
- originalHeight = Dimensions.get('window').height - 122;
110
- }
111
- let renderedImageWidth = imageRatio < originalHeight / width ? width : originalHeight / imageRatio;
112
- let renderedImageHeight = imageRatio < originalHeight / width ? width * imageRatio : originalHeight;
113
-
114
- let renderedImageY = (originalHeight - renderedImageHeight) / 2.0;
115
- let renderedImageX = (width - renderedImageWidth) / 2.0;
116
-
117
- const renderImageObj = {
118
- left: renderedImageX,
119
- top: renderedImageY,
120
- width: renderedImageWidth,
121
- height: renderedImageHeight,
122
- };
123
- const cropOverlayObj = {
124
- left: this.currentPos.left,
125
- top: this.currentPos.top,
126
- width: this.currentSize.width,
127
- height: this.currentSize.height,
128
- };
129
-
130
- var intersectAreaObj = {};
131
-
132
- let x = Math.max(renderImageObj.left, cropOverlayObj.left);
133
- let num1 = Math.min(renderImageObj.left + renderImageObj.width, cropOverlayObj.left + cropOverlayObj.width);
134
- let y = Math.max(renderImageObj.top, cropOverlayObj.top);
135
- let num2 = Math.min(renderImageObj.top + renderImageObj.height, cropOverlayObj.top + cropOverlayObj.height);
136
- if (num1 >= x && num2 >= y)
137
- intersectAreaObj = {
138
- originX: (x - renderedImageX) * (actualWidth / renderedImageWidth),
139
- originY: (y - renderedImageY) * (actualWidth / renderedImageWidth),
140
- width: (num1 - x) * (actualWidth / renderedImageWidth),
141
- height: (num2 - y) * (actualWidth / renderedImageWidth),
142
- };
143
- else {
144
- intersectAreaObj = {
145
- originX: x - renderedImageX,
146
- originY: y - renderedImageY,
147
- width: 0,
148
- height: 0,
149
- };
150
- }
151
- return intersectAreaObj;
152
- };
153
-
154
- crop = async (cropObj, uri) => {
155
- const { saveOptions } = this.props;
156
- if (cropObj.height > 0 && cropObj.width > 0) {
157
- const manipResult = await ImageManipulator.manipulateAsync(
158
- uri,
159
- [
160
- {
161
- crop: cropObj,
162
- },
163
- ],
164
- saveOptions,
165
- );
166
- return manipResult;
167
- }
168
- return {
169
- uri: null,
170
- base64: null,
171
- };
172
- };
173
-
174
- calculateMaxSizes = event => {
175
- let w1 = event.nativeEvent.layout.width || 100;
176
- let h1 = event.nativeEvent.layout.height || 100;
177
- if (this.state.squareAspect) {
178
- if (w1 < h1) h1 = w1;
179
- else w1 = h1;
180
- }
181
- this.maxSizes.width = w1;
182
- this.maxSizes.height = h1;
183
- };
184
-
185
- // eslint-disable-next-line camelcase
186
- async UNSAFE_componentWillReceiveProps() {
187
- await this.onConvertImageToEditableSize();
188
- }
189
-
190
- render() {
191
- const { isVisible, onPictureChoosed } = this.props;
192
- const { uri, base64, cropMode, processing } = this.state;
193
-
194
- let imageRatio = this.actualSize.height / this.actualSize.width;
195
- var originalHeight = Dimensions.get('window').height - 64;
196
- if (isIphoneX()) {
197
- originalHeight = Dimensions.get('window').height - 122;
198
- }
199
-
200
- let cropRatio = originalHeight / width;
201
-
202
- let cropWidth = imageRatio < cropRatio ? width : originalHeight / imageRatio;
203
- let cropHeight = imageRatio < cropRatio ? width * imageRatio : originalHeight;
204
-
205
- let cropInitialTop = (originalHeight - cropHeight) / 2.0;
206
- let cropInitialLeft = (width - cropWidth) / 2.0;
207
-
208
- if (this.currentSize.width == 0 && cropMode) {
209
- this.currentSize.width = cropWidth;
210
- this.currentSize.height = cropHeight;
211
-
212
- this.currentPos.top = cropInitialTop;
213
- this.currentPos.left = cropInitialLeft;
214
- }
215
-
216
- return (
217
- <Modal
218
- animationType="slide"
219
- transparent={true}
220
- visible={isVisible}
221
- hardwareAccelerated
222
- onRequestClose={() => {
223
- this.onToggleModal();
224
- }}
225
- >
226
- {uri !== undefined ? (
227
- <View style={styles.container}>
228
- <SafeAreaView style={[{ width }, styles.headerContainer]}>
229
- {!cropMode ? (
230
- <View style={[styles.headerButtonContainer, { justifyContent: 'flex-end' }]}>
231
- <TouchableOpacity
232
- onPress={() => {
233
- onPictureChoosed({ uri, base64 });
234
- this.onToggleModal();
235
- }}
236
- style={styles.headerButton}
237
- >
238
- <Text style={styles.headerButtonText}>{'Done'}</Text>
239
- </TouchableOpacity>
240
- </View>
241
- ) : (
242
- <View style={styles.headerButtonContainer}>
243
- <TouchableOpacity onPress={this.onToggleModal} style={styles.headerButton}>
244
- <Text style={styles.headerButtonText}>{'Cancel'}</Text>
245
- </TouchableOpacity>
246
- <TouchableOpacity
247
- onPress={() => {
248
- this.onCropImage(() => {
249
- onPictureChoosed({ uri: this.state.uri, base64: this.state.base64 });
250
- this.onToggleModal();
251
- });
252
- }}
253
- style={styles.headerButton}
254
- >
255
- <Text style={styles.headerButtonText}>{processing ? 'Processing' : 'Done'}</Text>
256
- </TouchableOpacity>
257
- </View>
258
- )}
259
- </SafeAreaView>
260
- <View style={[styles.contentContainer, { width: Dimensions.get('window').width }]}>
261
- <ScrollView
262
- style={{ position: 'relative', flex: 1 }}
263
- contentContainerStyle={{ backgroundColor: 'black' }}
264
- maximumZoomScale={5}
265
- minimumZoomScale={0.5}
266
- onScroll={this.onHandleScroll}
267
- bounces={false}
268
- showsHorizontalScrollIndicator={false}
269
- showsVerticalScrollIndicator={false}
270
- ref={c => (this.scrollView = c)}
271
- scrollEventThrottle={16}
272
- scrollEnabled={false}
273
- pinchGestureEnabled={false}
274
- >
275
- <AutoHeightImage
276
- style={{ backgroundColor: 'black', marginTop: cropInitialTop }}
277
- source={{ uri }}
278
- resizeMode={imageRatio >= 1 ? 'contain' : 'contain'}
279
- width={width}
280
- height={originalHeight}
281
- onLayout={this.calculateMaxSizes}
282
- />
283
- {!!cropMode && (
284
- <ImageCropOverlay
285
- onLayoutChanged={(top, left, width, height) => {
286
- this.currentSize.width = width;
287
- this.currentSize.height = height;
288
- this.currentPos.top = top;
289
- this.currentPos.left = left;
290
- }}
291
- initialWidth={cropWidth}
292
- initialHeight={cropHeight}
293
- initialTop={cropInitialTop}
294
- initialLeft={cropInitialLeft}
295
- minHeight={100}
296
- minWidth={100}
297
- topMargin={topMargin}
298
- />
299
- )}
300
- </ScrollView>
301
- </View>
302
- </View>
303
- ) : (
304
- <View style={styles.container}>
305
- <Text style={styles.prepareMessageText}>Preparing...</Text>
306
- </View>
307
- )}
308
- </Modal>
309
- );
310
- // }
311
- }
40
+ constructor(props) {
41
+ super(props);
42
+ const { squareAspect } = this.props;
43
+ this.state = {
44
+ cropMode: false,
45
+ processing: false,
46
+ squareAspect,
47
+ };
48
+
49
+ this.scrollOffset = 0;
50
+ this.currentPos = { left: 0, top: 0 };
51
+ this.currentSize = { width: 0, height: 0 };
52
+ this.maxSizes = { width: 0, height: 0 };
53
+ this.actualSize = { width: 0, height: 0 };
54
+ }
55
+
56
+ async componentDidMount() {
57
+ await this.onConvertImageToEditableSize();
58
+
59
+ // Set cropping by default
60
+ this.setState({ cropMode: true });
61
+ }
62
+
63
+ async onConvertImageToEditableSize() {
64
+ try {
65
+ const {
66
+ photo: { uri: rawUri },
67
+ } = this.props;
68
+
69
+ // expo-image-manipulator only works with file:// URIs.
70
+ // Resolve ph:// (iOS Photo Library) and https:// (remote/stock images) first.
71
+ let resolvedUri = rawUri;
72
+ if (rawUri?.startsWith("ph://")) {
73
+ const assetId = rawUri.replace("ph://", "");
74
+ const assetInfo = await MediaLibrary.getAssetInfoAsync(assetId, {
75
+ shouldDownloadFromNetwork: true,
76
+ });
77
+ resolvedUri = assetInfo.localUri || rawUri;
78
+ } else if (rawUri?.startsWith("http")) {
79
+ const ext = rawUri.split(".").pop()?.split("?")[0] || "jpg";
80
+ const file = await File.downloadFileAsync(
81
+ rawUri,
82
+ new File(Paths.cache, `crop_${Date.now()}.${ext}`),
83
+ { idempotent: true },
84
+ );
85
+ resolvedUri = file.uri;
86
+ }
87
+
88
+ const manipulatePromise = ImageManipulator.manipulateAsync(resolvedUri, [
89
+ { resize: { width: 1080 } },
90
+ ]);
91
+ // manipulateAsync can hang forever on non-file:// URIs (promise never settles).
92
+ // Promise.race with a timeout ensures the catch block fires.
93
+ const timeoutPromise = new Promise((_, reject) =>
94
+ setTimeout(
95
+ () => reject(new Error("Image processing timed out")),
96
+ 15000,
97
+ ),
98
+ );
99
+ const { uri, width, height } = await Promise.race([
100
+ manipulatePromise,
101
+ timeoutPromise,
102
+ ]);
103
+ this.setState({ uri });
104
+ this.actualSize.width = width;
105
+ this.actualSize.height = height;
106
+ } catch (e) {
107
+ console.log("onConvertImageToEditableSize error", e);
108
+ this.onToggleModal();
109
+ Alert.alert(
110
+ "Error",
111
+ "Unable to prepare this image for editing. Please try a different image.",
112
+ );
113
+ }
114
+ }
115
+
116
+ onToggleModal = () => {
117
+ this.props.onToggleModal();
118
+ this.setState({ cropMode: false });
119
+ };
120
+
121
+ onCropImage = (callback = null) => {
122
+ this.setState({ processing: true });
123
+ const { uri } = this.state;
124
+ Image.getSize(uri, async (actualWidth, actualHeight) => {
125
+ let cropObj = this.getCropBounds(actualWidth, actualHeight);
126
+ if (cropObj.height > 0 && cropObj.width > 0) {
127
+ let uriToCrop = uri;
128
+ const {
129
+ uri: uriCroped,
130
+ base64,
131
+ width: croppedWidth,
132
+ height: croppedHeight,
133
+ } = await this.crop(cropObj, uriToCrop);
134
+
135
+ this.actualSize.width = croppedWidth;
136
+ this.actualSize.height = croppedHeight;
137
+
138
+ this.setState(
139
+ {
140
+ uri: uriCroped,
141
+ base64,
142
+ cropMode: false,
143
+ processing: false,
144
+ },
145
+ () => {
146
+ if (callback) callback();
147
+ },
148
+ );
149
+ } else {
150
+ this.setState({ cropMode: false, processing: false }, () => {
151
+ if (callback) callback();
152
+ });
153
+ }
154
+ });
155
+ };
156
+
157
+ onHandleScroll = (event) => {
158
+ this.scrollOffset = event.nativeEvent.contentOffset.y;
159
+ };
160
+
161
+ getCropBounds = (actualWidth, actualHeight) => {
162
+ let imageRatio = actualHeight / actualWidth;
163
+ const topInset = this.props.insets?.top ?? 0;
164
+ const bottomInset = this.props.insets?.bottom ?? 0;
165
+ var originalHeight =
166
+ Dimensions.get("window").height - topInset - bottomInset - 44;
167
+ let renderedImageWidth =
168
+ imageRatio < originalHeight / width ? width : originalHeight / imageRatio;
169
+ let renderedImageHeight =
170
+ imageRatio < originalHeight / width ? width * imageRatio : originalHeight;
171
+
172
+ let renderedImageY = (originalHeight - renderedImageHeight) / 2.0;
173
+ let renderedImageX = (width - renderedImageWidth) / 2.0;
174
+
175
+ const renderImageObj = {
176
+ left: renderedImageX,
177
+ top: renderedImageY,
178
+ width: renderedImageWidth,
179
+ height: renderedImageHeight,
180
+ };
181
+ const cropOverlayObj = {
182
+ left: this.currentPos.left,
183
+ top: this.currentPos.top,
184
+ width: this.currentSize.width,
185
+ height: this.currentSize.height,
186
+ };
187
+
188
+ var intersectAreaObj = {};
189
+
190
+ let x = Math.max(renderImageObj.left, cropOverlayObj.left);
191
+ let num1 = Math.min(
192
+ renderImageObj.left + renderImageObj.width,
193
+ cropOverlayObj.left + cropOverlayObj.width,
194
+ );
195
+ let y = Math.max(renderImageObj.top, cropOverlayObj.top);
196
+ let num2 = Math.min(
197
+ renderImageObj.top + renderImageObj.height,
198
+ cropOverlayObj.top + cropOverlayObj.height,
199
+ );
200
+ if (num1 >= x && num2 >= y)
201
+ intersectAreaObj = {
202
+ originX: (x - renderedImageX) * (actualWidth / renderedImageWidth),
203
+ originY: (y - renderedImageY) * (actualWidth / renderedImageWidth),
204
+ width: (num1 - x) * (actualWidth / renderedImageWidth),
205
+ height: (num2 - y) * (actualWidth / renderedImageWidth),
206
+ };
207
+ else {
208
+ intersectAreaObj = {
209
+ originX: x - renderedImageX,
210
+ originY: y - renderedImageY,
211
+ width: 0,
212
+ height: 0,
213
+ };
214
+ }
215
+ return intersectAreaObj;
216
+ };
217
+
218
+ crop = async (cropObj, uri) => {
219
+ const { saveOptions } = this.props;
220
+ if (cropObj.height > 0 && cropObj.width > 0) {
221
+ const manipResult = await ImageManipulator.manipulateAsync(
222
+ uri,
223
+ [
224
+ {
225
+ crop: cropObj,
226
+ },
227
+ ],
228
+ saveOptions,
229
+ );
230
+ return manipResult;
231
+ }
232
+ return {
233
+ uri: null,
234
+ base64: null,
235
+ };
236
+ };
237
+
238
+ calculateMaxSizes = (event) => {
239
+ let w1 = event.nativeEvent.layout.width || 100;
240
+ let h1 = event.nativeEvent.layout.height || 100;
241
+ if (this.state.squareAspect) {
242
+ if (w1 < h1) h1 = w1;
243
+ else w1 = h1;
244
+ }
245
+ this.maxSizes.width = w1;
246
+ this.maxSizes.height = h1;
247
+ };
248
+
249
+ // eslint-disable-next-line camelcase
250
+ async UNSAFE_componentWillReceiveProps() {
251
+ await this.onConvertImageToEditableSize();
252
+ }
253
+
254
+ render() {
255
+ const { isVisible, onPictureChoosed } = this.props;
256
+ const { uri, base64, cropMode, processing } = this.state;
257
+
258
+ let imageRatio = this.actualSize.height / this.actualSize.width;
259
+ const topInset = this.props.insets?.top ?? 0;
260
+ const bottomInset = this.props.insets?.bottom ?? 0;
261
+ var originalHeight =
262
+ Dimensions.get("window").height - topInset - bottomInset - 44;
263
+ const topMargin = topInset + (Platform.OS === "ios" ? 50 : 20);
264
+
265
+ let cropRatio = originalHeight / width;
266
+
267
+ let cropWidth =
268
+ imageRatio < cropRatio ? width : originalHeight / imageRatio;
269
+ let cropHeight =
270
+ imageRatio < cropRatio ? width * imageRatio : originalHeight;
271
+
272
+ let cropInitialTop = (originalHeight - cropHeight) / 2.0;
273
+ let cropInitialLeft = (width - cropWidth) / 2.0;
274
+
275
+ if (this.currentSize.width == 0 && cropMode) {
276
+ this.currentSize.width = cropWidth;
277
+ this.currentSize.height = cropHeight;
278
+
279
+ this.currentPos.top = cropInitialTop;
280
+ this.currentPos.left = cropInitialLeft;
281
+ }
282
+
283
+ return (
284
+ <Modal
285
+ animationType="slide"
286
+ transparent={true}
287
+ visible={isVisible}
288
+ hardwareAccelerated
289
+ onRequestClose={() => {
290
+ this.onToggleModal();
291
+ }}
292
+ >
293
+ {uri !== undefined ? (
294
+ <View style={styles.container}>
295
+ <SafeAreaView style={[{ width }, styles.headerContainer]}>
296
+ {!cropMode ? (
297
+ <View
298
+ style={[
299
+ styles.headerButtonContainer,
300
+ { justifyContent: "flex-end" },
301
+ ]}
302
+ >
303
+ <TouchableOpacity
304
+ onPress={() => {
305
+ onPictureChoosed({ uri, base64 });
306
+ this.onToggleModal();
307
+ }}
308
+ style={styles.headerButton}
309
+ >
310
+ <Text style={styles.headerButtonText}>{"Done"}</Text>
311
+ </TouchableOpacity>
312
+ </View>
313
+ ) : (
314
+ <View style={styles.headerButtonContainer}>
315
+ <TouchableOpacity
316
+ onPress={this.onToggleModal}
317
+ style={styles.headerButton}
318
+ >
319
+ <Text style={styles.headerButtonText}>{"Cancel"}</Text>
320
+ </TouchableOpacity>
321
+ <TouchableOpacity
322
+ onPress={() => {
323
+ this.onCropImage(() => {
324
+ onPictureChoosed({
325
+ uri: this.state.uri,
326
+ base64: this.state.base64,
327
+ });
328
+ this.onToggleModal();
329
+ });
330
+ }}
331
+ style={styles.headerButton}
332
+ >
333
+ <Text style={styles.headerButtonText}>
334
+ {processing ? "Processing" : "Done"}
335
+ </Text>
336
+ </TouchableOpacity>
337
+ </View>
338
+ )}
339
+ </SafeAreaView>
340
+ <View
341
+ style={[
342
+ styles.contentContainer,
343
+ { width: Dimensions.get("window").width },
344
+ ]}
345
+ >
346
+ <ScrollView
347
+ style={{ position: "relative", flex: 1 }}
348
+ contentContainerStyle={{ backgroundColor: "black" }}
349
+ maximumZoomScale={5}
350
+ minimumZoomScale={0.5}
351
+ onScroll={this.onHandleScroll}
352
+ bounces={false}
353
+ showsHorizontalScrollIndicator={false}
354
+ showsVerticalScrollIndicator={false}
355
+ ref={(c) => (this.scrollView = c)}
356
+ scrollEventThrottle={16}
357
+ scrollEnabled={false}
358
+ pinchGestureEnabled={false}
359
+ >
360
+ <AutoHeightImage
361
+ style={{ backgroundColor: "black" }}
362
+ source={{ uri }}
363
+ resizeMode={imageRatio >= 1 ? "contain" : "contain"}
364
+ width={width}
365
+ height={originalHeight}
366
+ onLayout={this.calculateMaxSizes}
367
+ />
368
+ {!!cropMode && (
369
+ <ImageCropOverlay
370
+ onLayoutChanged={(top, left, width, height) => {
371
+ this.currentSize.width = width;
372
+ this.currentSize.height = height;
373
+ this.currentPos.top = top;
374
+ this.currentPos.left = left;
375
+ }}
376
+ initialWidth={cropWidth}
377
+ initialHeight={cropHeight}
378
+ initialTop={cropInitialTop}
379
+ initialLeft={cropInitialLeft}
380
+ minHeight={100}
381
+ minWidth={100}
382
+ topMargin={topMargin}
383
+ />
384
+ )}
385
+ </ScrollView>
386
+ </View>
387
+ </View>
388
+ ) : (
389
+ <View style={styles.container}>
390
+ <Text style={styles.prepareMessageText}>Preparing...</Text>
391
+ </View>
392
+ )}
393
+ </Modal>
394
+ );
395
+ // }
396
+ }
312
397
  }
313
398
 
314
399
  const styles = StyleSheet.create({
315
- headerContainer: {
316
- flexDirection: 'row',
317
- backgroundColor: 'black',
318
- justifyContent: 'space-between',
319
- },
320
- headerButtonContainer: {
321
- flex: 1,
322
- flexDirection: 'row',
323
- justifyContent: 'space-between',
324
- },
325
- headerButton: {
326
- marginHorizontal: 10,
327
- width: 60,
328
- height: 40,
329
- alignItems: 'center',
330
- justifyContent: 'center',
331
- },
332
- headerButtonText: {
333
- fontWeight: '500',
334
- color: 'white',
335
- fontSize: 18,
336
- },
337
- contentContainer: {
338
- flex: 1,
339
- backgroundColor: 'black',
340
- },
341
- container: {
342
- flex: 1,
343
- backgroundColor: '#000d',
344
- alignItems: 'center',
345
- justifyContent: 'center',
346
- },
347
- prepareMessageText: {
348
- fontFamily: 'sf-bold',
349
- fontSize: 20,
350
- color: '#fff',
351
- },
400
+ headerContainer: {
401
+ flexDirection: "row",
402
+ backgroundColor: "black",
403
+ justifyContent: "space-between",
404
+ },
405
+ headerButtonContainer: {
406
+ flex: 1,
407
+ flexDirection: "row",
408
+ justifyContent: "space-between",
409
+ },
410
+ headerButton: {
411
+ marginHorizontal: 10,
412
+ width: 60,
413
+ height: 40,
414
+ alignItems: "center",
415
+ justifyContent: "center",
416
+ },
417
+ headerButtonText: {
418
+ fontWeight: "500",
419
+ color: "white",
420
+ fontSize: 18,
421
+ },
422
+ contentContainer: {
423
+ flex: 1,
424
+ backgroundColor: "black",
425
+ },
426
+ container: {
427
+ flex: 1,
428
+ backgroundColor: "#000d",
429
+ alignItems: "center",
430
+ justifyContent: "center",
431
+ },
432
+ prepareMessageText: {
433
+ fontFamily: "sf-bold",
434
+ fontSize: 20,
435
+ color: "#fff",
436
+ },
352
437
  });
353
438
 
354
- export default ExpoImageManipulator;
439
+ export default withSafeAreaInsets(ExpoImageManipulator);
355
440
 
356
441
  ExpoImageManipulator.defaultProps = {
357
- onPictureChoosed: ({ uri, base64 }) => console.log('URI:', uri, base64),
358
- dragVelocity: 100,
359
- resizeVelocity: 50,
360
- saveOptions: {
361
- compress: 1,
362
- format: ImageManipulator.SaveFormat.PNG,
363
- base64: false,
364
- },
442
+ onPictureChoosed: ({ uri, base64 }) => console.log("URI:", uri, base64),
443
+ dragVelocity: 100,
444
+ resizeVelocity: 50,
445
+ saveOptions: {
446
+ compress: 1,
447
+ format: ImageManipulator.SaveFormat.PNG,
448
+ base64: false,
449
+ },
365
450
  };
366
451
 
367
452
  ExpoImageManipulator.propTypes = {
368
- isVisible: PropTypes.bool.isRequired,
369
- onPictureChoosed: PropTypes.func,
370
- saveOptions: PropTypes.object,
371
- photo: PropTypes.object.isRequired,
372
- onToggleModal: PropTypes.func.isRequired,
373
- dragVelocity: PropTypes.number,
374
- resizeVelocity: PropTypes.number,
453
+ isVisible: PropTypes.bool.isRequired,
454
+ onPictureChoosed: PropTypes.func,
455
+ saveOptions: PropTypes.object,
456
+ photo: PropTypes.object.isRequired,
457
+ onToggleModal: PropTypes.func.isRequired,
458
+ dragVelocity: PropTypes.number,
459
+ resizeVelocity: PropTypes.number,
375
460
  };