diff --git a/android/build.gradle b/android/build.gradle index 16571d741..a34caeec6 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -27,7 +27,7 @@ buildscript { jcenter() } dependencies { - classpath('com.android.tools.build:gradle:3.5.2') + classpath('com.android.tools.build:gradle:4.0.1') classpath 'com.google.gms:google-services:4.3.3' classpath 'com.bugsnag:bugsnag-android-gradle-plugin:4.+' diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index e0c4de36d..4e1cc9db6 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/ios/Ecency.xcodeproj/project.pbxproj b/ios/Ecency.xcodeproj/project.pbxproj index 3ce5ee0e5..43297c5af 100644 --- a/ios/Ecency.xcodeproj/project.pbxproj +++ b/ios/Ecency.xcodeproj/project.pbxproj @@ -43,7 +43,7 @@ 05B6C4B024C306CE00B7FA60 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 980BC9BC0D3B4AC69645C842 /* Zocial.ttf */; }; 0A1D279E0D3CD306C889592E /* libPods-Ecency-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7093E51BBC0EE2F41AB19EBA /* libPods-Ecency-tvOS.a */; }; 1CD0B89E258019B600A7D78E /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1CD0B89B258019B600A7D78E /* GoogleService-Info.plist */; }; - 2B3CF3607B7CB9B7296FD5EF /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + 2B3CF3607B7CB9B7296FD5EF /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; @@ -55,7 +55,7 @@ CFAA2A599FD65F360D9B3E1E /* libPods-EcencyTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B344CAA24725C973F48BE81E /* libPods-EcencyTests.a */; }; D71EB20EDB9B987C0574BAFE /* libPods-EcencyTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C97456BE898C00B5EDA21C2E /* libPods-EcencyTests.a */; }; DC0E25610BB5F49AFF4514AD /* libPods-Ecency.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 388DF3FF85F08109F722083B /* libPods-Ecency.a */; }; - F77F6C7E54F3C783A2773E9D /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + F77F6C7E54F3C783A2773E9D /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -204,8 +204,8 @@ buildActionMask = 2147483647; files = ( 05B6C49424C306CE00B7FA60 /* StoreKit.framework in Frameworks */, - F77F6C7E54F3C783A2773E9D /* (null) in Frameworks */, - 2B3CF3607B7CB9B7296FD5EF /* (null) in Frameworks */, + F77F6C7E54F3C783A2773E9D /* BuildFile in Frameworks */, + 2B3CF3607B7CB9B7296FD5EF /* BuildFile in Frameworks */, DC0E25610BB5F49AFF4514AD /* libPods-Ecency.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -752,7 +752,7 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Ecency/Pods-Ecency-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController/QBImagePicker.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle", "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf", "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf", "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf", @@ -769,7 +769,7 @@ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf", "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf", "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf", - "${PODS_ROOT}/RSKImageCropper/RSKImageCropper/RSKImageCropperStrings.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -790,7 +790,7 @@ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RSKImageCropperStrings.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6f64d5060..afcb83b21 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -145,7 +145,6 @@ PODS: - nanopb/encode (1.30905.0) - PromisesObjC (1.2.9) - Protobuf (3.12.0) - - QBImagePickerController (3.4.0) - RCTRequired (0.61.5) - RCTTypeSafety (0.61.5): - FBLazyVector (= 0.61.5) @@ -400,11 +399,15 @@ PODS: - React - RNIap (3.4.15): - React - - RNImageCropPicker (0.26.2): - - QBImagePickerController + - RNImageCropPicker (0.35.2): - React-Core - React-RCTImage - - RSKImageCropper + - RNImageCropPicker/QBImagePickerController (= 0.35.2) + - TOCropViewController + - RNImageCropPicker/QBImagePickerController (0.35.2): + - React-Core + - React-RCTImage + - TOCropViewController - RNReanimated (1.13.2): - React-Core - RNScreens (2.10.1): @@ -413,13 +416,13 @@ PODS: - React - RNVectorIcons (6.7.0): - React - - RSKImageCropper (2.2.3) - SDWebImage (5.8.4): - SDWebImage/Core (= 5.8.4) - SDWebImage/Core (5.8.4) - SDWebImageWebPCoder (0.6.1): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.7) + - TOCropViewController (2.6.0) - toolbar-android (0.1.0-rc.2): - React - Yoga (1.14.0) @@ -509,10 +512,9 @@ SPEC REPOS: - nanopb - PromisesObjC - Protobuf - - QBImagePickerController - - RSKImageCropper - SDWebImage - SDWebImageWebPCoder + - TOCropViewController EXTERNAL SOURCES: appcenter-analytics: @@ -666,7 +668,6 @@ SPEC CHECKSUMS: nanopb: c43f40fadfe79e8b8db116583945847910cbabc9 PromisesObjC: b48e0338dbbac2207e611750777895f7a5811b75 Protobuf: 2793fcd0622a00b546c60e7cbbcc493e043e9bb9 - QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022 RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1 RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320 React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78 @@ -707,17 +708,17 @@ SPEC CHECKSUMS: RNFBMessaging: 3bb7dcf398789ce359a9f6b97b83472a3090f65a RNGestureHandler: b6b359bb800ae399a9c8b27032bdbf7c18f08a08 RNIap: b4c77c8bc4501203f4b743126a05da23f10f40b4 - RNImageCropPicker: 9d1a7eea4f8368fc479cbd2bf26459bd3c74d9aa + RNImageCropPicker: 9e0bf18cf4184a846fed55747c8e622208b39947 RNReanimated: e03f7425cb7a38dcf1b644d680d1bfc91c3337ad RNScreens: b748efec66e095134c7166ca333b628cd7e6f3e2 RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f RNVectorIcons: 368d6d8b8301224e5ffb6254191f4f8876c2be0d - RSKImageCropper: a446db0e8444a036b34f3c43db01b2373baa4b2a SDWebImage: cf6922231e95550934da2ada0f20f2becf2ceba9 SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21 + TOCropViewController: 3105367e808b7d3d886a74ff59bf4804e7d3ab38 toolbar-android: 85f3ef4d691469f2d304e7dee4bca013aa1ba1ff Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b PODFILE CHECKSUM: 1f30c7da5061dbc47185442a6ab4a3c95ac48c04 -COCOAPODS: 1.10.0 +COCOAPODS: 1.9.3 diff --git a/package.json b/package.json index cedd8f300..1e42ab03b 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ }, "dependencies": { "@babel/runtime": "^7.5.5", - "@ecency/render-helper": "^2.0.11", + "@ecency/render-helper": "^2.0.15", "@esteemapp/dhive": "0.15.0", "@esteemapp/react-native-autocomplete-input": "^4.2.1", "@esteemapp/react-native-modal-popover": "^0.0.15", @@ -75,7 +75,8 @@ "react-native-fast-image": "^8.3.2", "react-native-gesture-handler": "^1.4.1", "react-native-iap": "3.4.15", - "react-native-image-crop-picker": "^0.26.1", + "react-native-image-crop-picker": "^0.35.2", + "react-native-image-size": "^1.1.3", "react-native-image-zoom-viewer": "^2.2.27", "react-native-keyboard-aware-scroll-view": "^0.9.1", "react-native-linear-gradient": "^2.4.2", diff --git a/src/assets/animations/empty_screen.json b/src/assets/animations/empty_screen.json new file mode 100644 index 000000000..985e23c13 --- /dev/null +++ b/src/assets/animations/empty_screen.json @@ -0,0 +1 @@ +{"v":"4.10.1","fr":30,"ip":0,"op":300,"w":1600,"h":800,"nm":"Sorry","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 4","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p667_1_0p167_0"],"t":0,"s":[0],"e":[0]},{"i":{"x":[0.601],"y":[1]},"o":{"x":[0.402],"y":[0]},"n":["0p601_1_0p402_0"],"t":35,"s":[0],"e":[22]},{"i":{"x":[0.601],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p601_1_0p333_0"],"t":66,"s":[22],"e":[22]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p833_1_0p333_0"],"t":85,"s":[22],"e":[13]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":104,"s":[13],"e":[13]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":122,"s":[13],"e":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":144,"s":[0],"e":[0]},{"t":299.00001217852}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":0.167,"y":0.167},"n":"0p667_0p667_0p167_0p167","t":0,"s":[85.563,200.782,0],"e":[85.563,200.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.601,"y":1},"o":{"x":0.402,"y":0},"n":"0p601_1_0p402_0","t":35,"s":[85.563,200.782,0],"e":[44.563,200.782,0],"to":[-6.83333349227905,0,0],"ti":[6.83333349227905,0,0]},{"i":{"x":0.601,"y":0.601},"o":{"x":0.333,"y":0.333},"n":"0p601_0p601_0p333_0p333","t":66,"s":[44.563,200.782,0],"e":[44.563,200.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.544,"y":1},"o":{"x":0.333,"y":0},"n":"0p544_1_0p333_0","t":85,"s":[44.563,200.782,0],"e":[85.563,200.782,0],"to":[6.83333349227905,0,0],"ti":[-6.83333349227905,0,0]},{"i":{"x":0.544,"y":0.544},"o":{"x":0.167,"y":0.167},"n":"0p544_0p544_0p167_0p167","t":104,"s":[85.563,200.782,0],"e":[85.563,200.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.544,"y":0.544},"o":{"x":0.167,"y":0.167},"n":"0p544_0p544_0p167_0p167","t":122,"s":[85.563,200.782,0],"e":[85.563,200.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.544,"y":0.544},"o":{"x":0.167,"y":0.167},"n":"0p544_0p544_0p167_0p167","t":144,"s":[85.563,200.782,0],"e":[85.563,200.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.544,"y":0.544},"o":{"x":0.167,"y":0.167},"n":"0p544_0p544_0p167_0p167","t":165,"s":[85.563,200.782,0],"e":[85.563,200.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.544,"y":1},"o":{"x":0.167,"y":0},"n":"0p544_1_0p167_0","t":180,"s":[85.563,200.782,0],"e":[85.563,140.782,0],"to":[0,-10,0],"ti":[0,10,0]},{"i":{"x":0.544,"y":0.544},"o":{"x":0.167,"y":0.167},"n":"0p544_0p544_0p167_0p167","t":195,"s":[85.563,140.782,0],"e":[85.563,140.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.544,"y":1},"o":{"x":0.167,"y":0},"n":"0p544_1_0p167_0","t":210,"s":[85.563,140.782,0],"e":[85.563,264.782,0],"to":[0,20.6666660308838,0],"ti":[0,-20.6666660308838,0]},{"i":{"x":0.544,"y":0.544},"o":{"x":0.167,"y":0.167},"n":"0p544_0p544_0p167_0p167","t":230,"s":[85.563,264.782,0],"e":[85.563,264.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0},"n":"0p833_0p833_0p167_0","t":260,"s":[85.563,264.782,0],"e":[85.563,200.782,0],"to":[0,-10.6666669845581,0],"ti":[0,10.6666669845581,0]},{"t":299.00001217852}],"ix":2},"a":{"a":0,"k":[12,164,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.725,0.333,0.333],"y":[0,0,0]},"n":["0p833_1_0p725_0","0p833_1_0p333_0","0p833_1_0p333_0"],"t":66,"s":[100,100,100],"e":[100,100,100]},{"i":{"x":[0.244,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.725,0.333,0.333],"y":[0,0,0]},"n":["0p244_1_0p725_0","0p667_1_0p333_0","0p667_1_0p333_0"],"t":85,"s":[100,100,100],"e":[73,100,100]},{"i":{"x":[0.244,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"n":["0p244_1_0p167_0","0p667_1_0p167_0","0p667_1_0p167_0"],"t":104,"s":[73,100,100],"e":[73,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"n":["0p833_1_0p167_0","0p833_1_0p167_0","0p833_1_0p167_0"],"t":122,"s":[73,100,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"n":["0p833_1_0p167_0","0p833_1_0p167_0","0p833_1_0p167_0"],"t":144,"s":[100,100,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"n":["0p833_1_0p167_0","0p833_1_0p167_0","0p833_1_0p167_0"],"t":165,"s":[100,100,100],"e":[39,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"n":["0p833_1_0p167_0","0p833_1_0p167_0","0p833_1_0p167_0"],"t":195,"s":[39,100,100],"e":[39,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"n":["0p833_1_0p167_0","0p833_1_0p167_0","0p833_1_0p167_0"],"t":240,"s":[39,100,100],"e":[24,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"n":["0p833_1_0p167_0","0p833_1_0p167_0","0p833_1_0p167_0"],"t":260,"s":[24,100,100],"e":[100,100,100]},{"t":299.00001217852}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-48,167],[60,167]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.9647058823529412,0.9647058823529412,0.9647058823529412,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":15,"ix":5},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":305.000012422905,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"rast3","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":1,"y":1},"n":"0p667_0p667_1_1","t":179,"s":[155.563,88.782,0],"e":[155.563,88.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.505,"y":1},"o":{"x":0.506,"y":0},"n":"0p505_1_0p506_0","t":180,"s":[155.563,88.782,0],"e":[155.563,31.782,0],"to":[0,-9.5,0],"ti":[0,9.5,0]},{"i":{"x":0.505,"y":0.505},"o":{"x":0.333,"y":0.333},"n":"0p505_0p505_0p333_0p333","t":195,"s":[155.563,31.782,0],"e":[155.563,31.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"n":"0p667_1_0p333_0","t":210,"s":[155.563,31.782,0],"e":[155.563,88.782,0],"to":[0,9.5,0],"ti":[0,-9.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.506,"y":0.506},"n":"0p667_0p667_0p506_0p506","t":231,"s":[155.563,88.782,0],"e":[155.563,88.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.506,"y":0},"n":"0p667_1_0p506_0","t":240,"s":[155.563,88.782,0],"e":[155.563,200,0],"to":[0,18.53639793396,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.506,"y":0},"n":"0p667_1_0p506_0","t":260,"s":[155.563,200,0],"e":[155.563,88.782,0],"to":[0,0,0],"ti":[0,18.53639793396,0]},{"t":299.00001217852}],"ix":2},"a":{"a":0,"k":[-86,42,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":20,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":23,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":26,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":70,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":73,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":76,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":131,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":134,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":137,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":142,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":145,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":148,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":172,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":175,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":178,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":260,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"t":299.00001217852}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[56,56],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9647058823529412,0.9647058823529412,0.9647058823529412,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-86,42],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":305.000012422905,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"rast2","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":1,"y":1},"n":"0p667_0p667_1_1","t":179,"s":[155.563,88.782,0],"e":[155.563,88.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.505,"y":1},"o":{"x":0.506,"y":0},"n":"0p505_1_0p506_0","t":180,"s":[155.563,88.782,0],"e":[155.563,32.782,0],"to":[0,-9.33333301544189,0],"ti":[0,9.33333301544189,0]},{"i":{"x":0.505,"y":0.505},"o":{"x":0.333,"y":0.333},"n":"0p505_0p505_0p333_0p333","t":195,"s":[155.563,32.782,0],"e":[155.563,32.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"n":"0p667_1_0p333_0","t":210,"s":[155.563,32.782,0],"e":[155.563,88.782,0],"to":[0,9.33333301544189,0],"ti":[0,-9.33333301544189,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.506,"y":0.506},"n":"0p667_0p667_0p506_0p506","t":231,"s":[155.563,88.782,0],"e":[155.563,88.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.506,"y":0},"n":"0p667_1_0p506_0","t":240,"s":[155.563,88.782,0],"e":[155.563,200,0],"to":[0,18.53639793396,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.506,"y":0},"n":"0p667_1_0p506_0","t":260,"s":[155.563,200,0],"e":[155.563,88.782,0],"to":[0,0,0],"ti":[0,18.53639793396,0]},{"t":299.00001217852}],"ix":2},"a":{"a":0,"k":[-86,42,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":20,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":23,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":26,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":70,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":73,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":76,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":131,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":134,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":137,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":142,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":145,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":148,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":172,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":175,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":178,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":260,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"t":299.00001217852}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[56,56],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-86,42],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":305.000012422905,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"chap3","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.667},"o":{"x":1,"y":1},"n":"0p667_0p667_1_1","t":179,"s":[-16.437,88.782,0],"e":[-16.437,88.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.505,"y":1},"o":{"x":0.506,"y":0},"n":"0p505_1_0p506_0","t":180,"s":[-16.437,88.782,0],"e":[-16.437,31.782,0],"to":[0,-9.5,0],"ti":[0,9.5,0]},{"i":{"x":0.505,"y":0.505},"o":{"x":0.333,"y":0.333},"n":"0p505_0p505_0p333_0p333","t":195,"s":[-16.437,31.782,0],"e":[-16.437,31.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"n":"0p667_1_0p333_0","t":210,"s":[-16.437,31.782,0],"e":[-16.437,88.782,0],"to":[0,9.5,0],"ti":[0,-9.5,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.506,"y":0.506},"n":"0p667_0p667_0p506_0p506","t":231,"s":[-16.437,88.782,0],"e":[-16.437,88.782,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.506,"y":0},"n":"0p667_1_0p506_0","t":240,"s":[-16.437,88.782,0],"e":[-16.437,200,0],"to":[0,18.53639793396,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.506,"y":0},"n":"0p667_1_0p506_0","t":260,"s":[-16.437,200,0],"e":[-16.437,88.782,0],"to":[0,0,0],"ti":[0,18.53639793396,0]},{"t":299.00001217852}],"ix":2},"a":{"a":0,"k":[-86,42,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":20,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":23,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":26,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":70,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":73,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":76,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":131,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":134,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":137,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":142,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":145,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":148,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":172,"s":[71.429,71.429,100],"e":[71.429,27.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":175,"s":[71.429,27.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":178,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":260,"s":[71.429,71.429,100],"e":[71.429,71.429,100]},{"t":299.00001217852}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[56,56],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9647058823529412,0.9647058823529412,0.9647058823529412,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-86,42],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":305.000012422905,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"face","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.321],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p321_1_0p167_0"],"t":0,"s":[0],"e":[0]},{"i":{"x":[0.321],"y":[1]},"o":{"x":[0.508],"y":[0]},"n":["0p321_1_0p508_0"],"t":30,"s":[0],"e":[19]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p833_1_0p333_0"],"t":60,"s":[19],"e":[19]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":85,"s":[19],"e":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":108,"s":[0],"e":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"n":["0p833_1_0p167_0"],"t":261,"s":[0],"e":[0]},{"t":299.00001217852}],"ix":10},"p":{"a":0,"k":[797.701,478.16099999999994,0],"ix":2},"a":{"a":0,"k":[71.264,114.943,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[409.195,409.195],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.9647058823529412,0.9647058823529412,0.9647058823529412,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":8,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.20784313725490197,0.48627450980392156,0.9019607843137255,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[71.264,114.943],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[94.157,94.157],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":305.000012422905,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"shadow","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[800,400,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[380,26],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9647058823529412,0.9647058823529412,0.9647058823529412,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4,329],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[74.737,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300.00001221925,"st":0,"bm":0}]} \ No newline at end of file diff --git a/src/components/basicUIElements/index.js b/src/components/basicUIElements/index.js index 5e4c700e9..91f72be8f 100644 --- a/src/components/basicUIElements/index.js +++ b/src/components/basicUIElements/index.js @@ -11,6 +11,7 @@ import UserListItem from './view/userListItem/userListItem'; import WalletLineItem from './view/walletLineItem/walletLineItemView'; import CommunityListItem from './view/communityListItem/communityListItem'; import Separator from './view/separator/separatorView'; +import EmptyScreen from './view/emptyScreen/emptyScreenView'; // Placeholders import ListItemPlaceHolder from './view/placeHolder/listItemPlaceHolderView'; @@ -48,4 +49,5 @@ export { WalletUnclaimedPlaceHolder, CommunitiesPlaceHolder, Separator, + EmptyScreen, }; diff --git a/src/components/basicUIElements/view/emptyScreen/emptyScreenView.js b/src/components/basicUIElements/view/emptyScreen/emptyScreenView.js new file mode 100644 index 000000000..3747d066b --- /dev/null +++ b/src/components/basicUIElements/view/emptyScreen/emptyScreenView.js @@ -0,0 +1,18 @@ +import React from 'react'; +import { View, Text } from 'react-native'; +import LottieView from 'lottie-react-native'; +import globalStyles from '../../../../globalStyles'; + +const EmptyScreenView = ({ style, textStyle }) => ( + + + Nothing found! + +); + +export default EmptyScreenView; diff --git a/src/components/communitiesList/index.js b/src/components/communitiesList/index.js new file mode 100644 index 000000000..e5b3872fe --- /dev/null +++ b/src/components/communitiesList/index.js @@ -0,0 +1,3 @@ +import CommunitiesList from './view/communitiesList'; + +export default CommunitiesList; diff --git a/src/screens/searchResult/screen/communitiesList.js b/src/components/communitiesList/view/communitiesList.js similarity index 75% rename from src/screens/searchResult/screen/communitiesList.js rename to src/components/communitiesList/view/communitiesList.js index a581b768e..155dab441 100644 --- a/src/screens/searchResult/screen/communitiesList.js +++ b/src/components/communitiesList/view/communitiesList.js @@ -2,23 +2,22 @@ import React from 'react'; import { SafeAreaView, FlatList } from 'react-native'; // Components -import CommunitiesListItem from './CommunitiesListItem'; -import { CommunitiesPlaceHolder } from '../../../components/basicUIElements'; +import { CommunitiesPlaceHolder } from '../../basicUIElements'; +import CommunitiesListItem from './communitiesListItem'; // Styles import styles from './communitiesListStyles'; const CommunitiesList = ({ - votes, + data, + subscribingCommunities, handleOnPress, handleSubscribeButtonPress, - allSubscriptions, isLoggedIn, noResult, + screen, }) => { const _renderItem = ({ item, index }) => { - const isSubscribed = allSubscriptions.some((sub) => sub[0] === item.name); - return ( ); }; @@ -57,8 +61,8 @@ const CommunitiesList = ({ {!noResult && ( item.id && item.id.toString()} + data={data} + keyExtractor={(item, index) => index.toString()} renderItem={_renderItem} ListEmptyComponent={_renderEmptyContent} /> diff --git a/src/components/communitiesList/view/communitiesListItem/index.js b/src/components/communitiesList/view/communitiesListItem/index.js new file mode 100644 index 000000000..3f85e9387 --- /dev/null +++ b/src/components/communitiesList/view/communitiesListItem/index.js @@ -0,0 +1,3 @@ +import CommunitiesListItem from './view/CommunitiesListItem'; + +export default CommunitiesListItem; diff --git a/src/screens/searchResult/screen/CommunitiesListItem.js b/src/components/communitiesList/view/communitiesListItem/view/CommunitiesListItem.js similarity index 54% rename from src/screens/searchResult/screen/CommunitiesListItem.js rename to src/components/communitiesList/view/communitiesListItem/view/CommunitiesListItem.js index 0a70871c3..7669ff6a8 100644 --- a/src/screens/searchResult/screen/CommunitiesListItem.js +++ b/src/components/communitiesList/view/communitiesListItem/view/CommunitiesListItem.js @@ -1,12 +1,12 @@ import React, { useState } from 'react'; -import { View, Text, TouchableOpacity } from 'react-native'; +import { View, Text, TouchableOpacity, ActivityIndicator } from 'react-native'; import { useIntl } from 'react-intl'; import styles from './communitiesListItemStyles'; -import { Tag } from '../../../components/basicUIElements'; +import { Tag } from '../../../../basicUIElements'; -const UserListItem = ({ +const CommunitiesListItem = ({ index, handleOnPress, handleOnLongPress, @@ -22,14 +22,13 @@ const UserListItem = ({ handleSubscribeButtonPress, isSubscribed, isLoggedIn, + loading, + screen, }) => { - const [subscribed, setSubscribed] = useState(isSubscribed); const intl = useIntl(); const _handleSubscribeButtonPress = () => { - handleSubscribeButtonPress({ subscribed: !subscribed, communityId: name }).then(() => { - setSubscribed(!subscribed); - }); + handleSubscribeButtonPress({ isSubscribed: isSubscribed, communityId: name }, screen); }; return ( @@ -41,24 +40,29 @@ const UserListItem = ({ {title} - {isLoggedIn && ( - - )} + {isLoggedIn && + (loading ? ( + + + + ) : ( + + ))} {!!about && {about}} @@ -77,4 +81,4 @@ const UserListItem = ({ ); }; -export default UserListItem; +export default CommunitiesListItem; diff --git a/src/screens/searchResult/screen/communitiesListItemStyles.js b/src/components/communitiesList/view/communitiesListItem/view/communitiesListItemStyles.js similarity index 92% rename from src/screens/searchResult/screen/communitiesListItemStyles.js rename to src/components/communitiesList/view/communitiesListItem/view/communitiesListItemStyles.js index 19880705c..a616827d6 100644 --- a/src/screens/searchResult/screen/communitiesListItemStyles.js +++ b/src/components/communitiesList/view/communitiesListItem/view/communitiesListItemStyles.js @@ -59,4 +59,9 @@ export default EStyleSheet.create({ flexDirection: 'row', justifyContent: 'space-between', }, + indicatorView: { + width: 65, + alignItems: 'center', + justifyContent: 'center', + }, }); diff --git a/src/screens/searchResult/screen/communitiesListStyles.js b/src/components/communitiesList/view/communitiesListStyles.js similarity index 100% rename from src/screens/searchResult/screen/communitiesListStyles.js rename to src/components/communitiesList/view/communitiesListStyles.js diff --git a/src/components/index.js b/src/components/index.js index 716410820..18b6e7eaa 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -34,6 +34,7 @@ import { PostForm } from './postForm'; import { PostHeaderDescription, PostBody, Tags } from './postElements'; import { PostListItem } from './postListItem'; import { ProfileSummary } from './profileSummary'; +import { ProgressiveImage } from './progressiveImage'; import { SearchInput } from './searchInput'; import { SearchModal } from './searchModal'; @@ -64,6 +65,8 @@ import ScaleSlider from './scaleSlider/scaleSliderView'; import { ProductItemLine } from './productItemLine/productItemLineView'; import { HorizontalIconList } from './horizontalIconList/horizontalIconListView'; import { PopoverWrapper } from './popoverWrapper/popoverWrapperView'; +import CommunitiesList from './communitiesList'; +import SubscribedCommunitiesList from './subscribedCommunitiesList'; // View import { Comment } from './comment'; @@ -104,6 +107,7 @@ import { WalletLineItem, WalletUnclaimedPlaceHolder, Separator, + EmptyScreen, } from './basicUIElements'; export { @@ -207,6 +211,9 @@ export { WalletLineItem, WalletUnclaimedPlaceHolder, Separator, + EmptyScreen, HorizontalIconList, PopoverWrapper, + CommunitiesList, + SubscribedCommunitiesList, }; diff --git a/src/components/markdownEditor/view/markdownEditorStyles.js b/src/components/markdownEditor/view/markdownEditorStyles.js index 0286b6ea1..0bdb64731 100644 --- a/src/components/markdownEditor/view/markdownEditorStyles.js +++ b/src/components/markdownEditor/view/markdownEditorStyles.js @@ -14,7 +14,7 @@ export default EStyleSheet.create({ color: '$primaryBlack', backgroundColor: '$primaryBackgroundColor', // fontFamily: '$editorFont', - //textAlignVertical: 'top', + // textAlignVertical: 'top', }, previewContainer: { flex: 1, diff --git a/src/components/markdownEditor/view/markdownEditorView.js b/src/components/markdownEditor/view/markdownEditorView.js index 7a86fc73b..59c3c8644 100644 --- a/src/components/markdownEditor/view/markdownEditorView.js +++ b/src/components/markdownEditor/view/markdownEditorView.js @@ -44,6 +44,7 @@ const MarkdownEditorView = ({ const [text, setText] = useState(draftBody || ''); const [selection, setSelection] = useState({ start: 0, end: 0 }); const [editable, setEditable] = useState(true); + const [height, setHeight] = useState(0); const inputRef = useRef(null); const galleryRef = useRef(null); @@ -260,7 +261,7 @@ const MarkdownEditorView = ({ { const [rebloggedBy, setRebloggedBy] = useState(get(content, 'reblogged_by[0]', null)); const [activeVot, setActiveVot] = useState(activeVotes); + const [calcImgHeight, setCalcImgHeight] = useState(300); //console.log(activeVotes); // Component Functions @@ -62,11 +68,16 @@ const PostCardView = ({ const _getPostImage = (content, isNsfwPost) => { if (content && content.image) { if (isNsfwPost && content.nsfw) { - return NSFW_IMAGE; + return { image: NSFW_IMAGE, thumbnail: NSFW_IMAGE }; } - return { uri: content.image, priority: FastImage.priority.high }; + //console.log(content) + ImageSize.getSize(content.image).then((size) => { + setCalcImgHeight((size.height / size.width) * dim.width); + }); + return { image: content.image, thumbnail: content.thumbnail }; + } else { + return { image: DEFAULT_IMAGE, thumbnail: DEFAULT_IMAGE }; } - return DEFAULT_IMAGE; }; useEffect(() => { @@ -102,11 +113,13 @@ const PostCardView = ({ {!isHideImage && ( - )} diff --git a/src/components/postListItem/view/postListItemStyles.js b/src/components/postListItem/view/postListItemStyles.js index e5b03ca79..57fd8d534 100644 --- a/src/components/postListItem/view/postListItemStyles.js +++ b/src/components/postListItem/view/postListItemStyles.js @@ -18,8 +18,8 @@ export default EStyleSheet.create({ margin: 0, alignItems: 'center', alignSelf: 'center', - height: 200, - width: '$deviceWidth - 16', + //height: 200, + //width: '$deviceWidth - 16', borderRadius: 8, backgroundColor: '$primaryLightGray', // paddingVertical: 10, diff --git a/src/components/postListItem/view/postListItemView.js b/src/components/postListItem/view/postListItemView.js index 9a6be15d4..cfe1fff07 100644 --- a/src/components/postListItem/view/postListItemView.js +++ b/src/components/postListItem/view/postListItemView.js @@ -1,8 +1,8 @@ -import React, { useRef, Fragment } from 'react'; +import React, { useRef, useState, useEffect, Fragment } from 'react'; import ActionSheet from 'react-native-actionsheet'; -import { View, Text, TouchableOpacity } from 'react-native'; +import { View, Text, TouchableOpacity, Dimensions } from 'react-native'; import { injectIntl } from 'react-intl'; -import FastImage from 'react-native-fast-image'; +import ImageSize from 'react-native-image-size'; // Utils import { getTimeFromNow } from '../../../utils/time'; @@ -10,13 +10,17 @@ import { getTimeFromNow } from '../../../utils/time'; // Components import { PostHeaderDescription } from '../../postElements'; import { IconButton } from '../../iconButton'; - -// Defaults -import DEFAULT_IMAGE from '../../../assets/no_image.png'; +import ProgressiveImage from '../../progressiveImage'; // Styles import styles from './postListItemStyles'; +// Defaults +const DEFAULT_IMAGE = + 'https://images.ecency.com/DQmT8R33geccEjJfzZEdsRHpP3VE8pu3peRCnQa1qukU4KR/no_image_3x.png'; + +const dim = Dimensions.get('window'); + const PostListItemView = ({ title, summary, @@ -25,6 +29,7 @@ const PostListItemView = ({ reputation, created, image, + thumbnail, handleOnPressItem, handleOnRemoveItem, id, @@ -32,9 +37,21 @@ const PostListItemView = ({ isFormatedDate, }) => { const actionSheet = useRef(null); - + const [calcImgHeight, setCalcImgHeight] = useState(300); // Component Life Cycles - + useEffect(() => { + let _isMounted = false; + if (image) { + if (!_isMounted) { + ImageSize.getSize(image.uri).then((size) => { + setCalcImgHeight((size.height / size.width) * dim.width); + }); + } + } + return () => { + _isMounted = true; + }; + }, []); // Component Functions return ( @@ -60,7 +77,14 @@ const PostListItemView = ({ handleOnPressItem(id)}> - + {title} {summary} diff --git a/src/components/posts/container/postsContainer.js b/src/components/posts/container/postsContainer.js index 322a3da61..6437f3341 100644 --- a/src/components/posts/container/postsContainer.js +++ b/src/components/posts/container/postsContainer.js @@ -462,7 +462,9 @@ const PostsContainer = ({ }); } - dispatch(subscribeAction(currentAccount, pinCode, data, successToastText, failToastText)); + dispatch( + subscribeAction(currentAccount, pinCode, data, successToastText, failToastText, 'feedScreen'), + ); }; return ( diff --git a/src/components/progressiveImage/index.js b/src/components/progressiveImage/index.js new file mode 100644 index 000000000..734fc9afa --- /dev/null +++ b/src/components/progressiveImage/index.js @@ -0,0 +1,57 @@ +import React from 'react'; +import { View, StyleSheet, Animated } from 'react-native'; + +const styles = StyleSheet.create({ + imageOverlay: { + position: 'absolute', + left: 0, + right: 0, + bottom: 0, + top: 0, + }, + container: { + backgroundColor: '#f6f6f6', + }, +}); + +class ProgressiveImage extends React.Component { + thumbnailAnimated = new Animated.Value(0); + + imageAnimated = new Animated.Value(0); + + handleThumbnailLoad = () => { + Animated.timing(this.thumbnailAnimated, { + toValue: 1, + }).start(); + }; + + onImageLoad = () => { + Animated.timing(this.imageAnimated, { + toValue: 1, + }).start(); + }; + + render() { + const { thumbnailSource, source, style, ...props } = this.props; + + return ( + + + + + ); + } +} + +export default ProgressiveImage; diff --git a/src/components/subscribedCommunitiesList/index.js b/src/components/subscribedCommunitiesList/index.js new file mode 100644 index 000000000..fb0354c95 --- /dev/null +++ b/src/components/subscribedCommunitiesList/index.js @@ -0,0 +1,4 @@ +import SubscribedCommunitiesListView from './view/subscribedCommunitiesListView'; +import SubscribedCommunitiesList from './view/subscribedCommunitiesListView'; + +export default SubscribedCommunitiesList; diff --git a/src/components/subscribedCommunitiesList/view/subscribedCommunitiesListStyles.js b/src/components/subscribedCommunitiesList/view/subscribedCommunitiesListStyles.js new file mode 100644 index 000000000..7b3d00622 --- /dev/null +++ b/src/components/subscribedCommunitiesList/view/subscribedCommunitiesListStyles.js @@ -0,0 +1,51 @@ +import EStyleSheet from 'react-native-extended-stylesheet'; + +export default EStyleSheet.create({ + container: { + flex: 1, + backgroundColor: '$primaryBackgroundColor', + }, + itemWrapper: { + paddingHorizontal: 16, + paddingTop: 16, + paddingBottom: 8, + borderRadius: 8, + backgroundColor: '$primaryBackgroundColor', + flexDirection: 'row', + alignItems: 'center', + }, + itemWrapperGray: { + backgroundColor: '$primaryLightBackground', + }, + username: { + marginLeft: 10, + color: '$primaryBlack', + }, + communityWrapper: { + paddingHorizontal: 16, + paddingTop: 10, + paddingBottom: 10, + borderRadius: 8, + backgroundColor: '$primaryBackgroundColor', + flexDirection: 'row', + alignItems: 'center', + flex: 1, + }, + subscribeButton: { + maxWidth: 75, + borderWidth: 1, + borderColor: '$primaryBlue', + }, + subscribeButtonText: { + textAlign: 'center', + color: '$primaryBlue', + }, + community: { + justifyContent: 'center', + marginLeft: 15, + color: '$primaryBlack', + }, + tabbarItem: { + flex: 1, + }, +}); diff --git a/src/components/subscribedCommunitiesList/view/subscribedCommunitiesListView.js b/src/components/subscribedCommunitiesList/view/subscribedCommunitiesListView.js new file mode 100644 index 000000000..43b7aef8d --- /dev/null +++ b/src/components/subscribedCommunitiesList/view/subscribedCommunitiesListView.js @@ -0,0 +1,82 @@ +import React from 'react'; +import { View, FlatList, TouchableOpacity, Text, ActivityIndicator } from 'react-native'; +import { useIntl } from 'react-intl'; + +import { Tag, UserAvatar } from '../../index'; +import { ListPlaceHolder } from '../../basicUIElements'; + +import DEFAULT_IMAGE from '../../../assets/no_image.png'; + +import styles from './subscribedCommunitiesListStyles'; + +const SubscribedCommunitiesListView = ({ + data, + subscribingCommunities, + handleOnPress, + handleSubscribeButtonPress, +}) => { + const intl = useIntl(); + + const _renderEmptyContent = () => { + return ( + <> + + + ); + }; + + return ( + index.toString()} + renderItem={({ item, index }) => ( + + + handleOnPress(item[0])}> + + + handleOnPress(item[0])}> + {item[1]} + + + + {subscribingCommunities.hasOwnProperty(item[0]) && + subscribingCommunities[item[0]].loading ? ( + + + + ) : ( + + handleSubscribeButtonPress( + { + isSubscribed: item[4], + communityId: item[0], + }, + 'communitiesScreenJoinedTab', + ) + } + /> + )} + + + )} + ListEmptyComponent={_renderEmptyContent} + /> + ); +}; + +export default SubscribedCommunitiesListView; diff --git a/src/components/upvote/container/upvoteContainer.js b/src/components/upvote/container/upvoteContainer.js index 497528403..d8ffaeaa3 100644 --- a/src/components/upvote/container/upvoteContainer.js +++ b/src/components/upvote/container/upvoteContainer.js @@ -87,23 +87,22 @@ class UpvoteContainer extends PureComponent { const quote = get(globalProps, 'quote', 0); const sbdPrintRate = get(globalProps, 'sbdPrintRate', 0); const SBD_PRINT_RATE_MAX = 10000; - const percent_steem_dollars = - (content.percent_hbd || content.percent_steem_dollars || 10000) / 20000; + const percent_steem_dollars = (content.percent_hbd || 10000) / 20000; - const pending_payout_sbd = pendingPayout * percent_steem_dollars; + const pending_payout_hbd = pendingPayout * percent_steem_dollars; const price_per_steem = base / quote; - const pending_payout_sp = (pendingPayout - pending_payout_sbd) / price_per_steem; - const pending_payout_printed_sbd = pending_payout_sbd * (sbdPrintRate / SBD_PRINT_RATE_MAX); - const pending_payout_printed_steem = - (pending_payout_sbd - pending_payout_printed_sbd) / price_per_steem; + const pending_payout_hp = (pendingPayout - pending_payout_hbd) / price_per_steem; + const pending_payout_printed_hbd = pending_payout_hbd * (sbdPrintRate / SBD_PRINT_RATE_MAX); + const pending_payout_printed_hive = + (pending_payout_hbd - pending_payout_printed_hbd) / price_per_steem; const breakdownPayout = - pending_payout_printed_sbd.toFixed(3) + + pending_payout_printed_hbd.toFixed(3) + ' HBD, ' + - pending_payout_printed_steem.toFixed(3) + + pending_payout_printed_hive.toFixed(3) + ' HIVE, ' + - pending_payout_sp.toFixed(3) + + pending_payout_hp.toFixed(3) + ' HP'; return ( diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index fa301490e..7bd7a12c4 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -252,6 +252,7 @@ "schedules": "Schedules", "gallery": "Gallery", "settings": "Settings", + "communities": "Communities", "add_account": "Add Account", "logout": "Logout", "cancel": "Cancel", @@ -549,7 +550,7 @@ "title": "Topics" }, "communities": { - "title": "Communities", + "title": "Groups", "subscribe": "Join", "unsubscribe": "Leave", "subscribers": "Members", @@ -580,5 +581,9 @@ "user": { "follow": "Follow", "unfollow": "Unfollow" + }, + "communities": { + "joined": "Membership", + "discover": "Discover" } } diff --git a/src/constants/routeNames.js b/src/constants/routeNames.js index 8089bdf38..3225fad91 100644 --- a/src/constants/routeNames.js +++ b/src/constants/routeNames.js @@ -29,6 +29,7 @@ export default { COMMENTS: `Comments${SCREEN_SUFFIX}`, ACCOUNT_BOOST: `AccountBoost${SCREEN_SUFFIX}`, COMMUNITY: `Community${SCREEN_SUFFIX}`, + COMMUNITIES: `Communities${SCREEN_SUFFIX}`, }, DRAWER: { MAIN: `Main${DRAWER_SUFFIX}`, diff --git a/src/constants/sideMenuItems.js b/src/constants/sideMenuItems.js index 929dc8acb..0d38e56dc 100644 --- a/src/constants/sideMenuItems.js +++ b/src/constants/sideMenuItems.js @@ -25,6 +25,12 @@ const authMenuItems = [ // icon: 'photo-library', // id: 'gallery', // }, + { + name: 'Communities', + route: ROUTES.SCREENS.COMMUNITIES, + icon: 'people', + id: 'communities', + }, { name: 'Settings', route: ROUTES.SCREENS.SETTINGS, diff --git a/src/containers/steemWalletContainer.js b/src/containers/steemWalletContainer.js index ffda1d76a..3714ec5be 100644 --- a/src/containers/steemWalletContainer.js +++ b/src/containers/steemWalletContainer.js @@ -144,9 +144,9 @@ const WalletContainer = ({ const _isHasUnclaimedRewards = (account) => { return ( - parseToken(get(account, 'reward_steem_balance', account.reward_hive_balance)) > 0 || - parseToken(get(account, 'reward_sbd_balance', account.reward_hbd_balance)) > 0 || - parseToken(get(account, 'reward_vesting_steem', account.reward_vesting_hive)) > 0 + parseToken(get(account, 'reward_hive_balance')) > 0 || + parseToken(get(account, 'reward_hbd_balance')) > 0 || + parseToken(get(account, 'reward_vesting_hive')) > 0 ); }; diff --git a/src/navigation/routes.js b/src/navigation/routes.js index 01fc7ce9f..a789eb0f7 100644 --- a/src/navigation/routes.js +++ b/src/navigation/routes.js @@ -37,6 +37,7 @@ import { AccountBoost, TagResult, Community, + Communities, } from '../screens'; const bottomTabNavigator = createBottomTabNavigator( @@ -148,6 +149,7 @@ const stackNavigator = createStackNavigator( [ROUTES.SCREENS.SPIN_GAME]: { screen: SpinGame }, [ROUTES.SCREENS.ACCOUNT_BOOST]: { screen: AccountBoost }, [ROUTES.SCREENS.COMMUNITY]: { screen: Community }, + [ROUTES.SCREENS.COMMUNITIES]: { screen: Communities }, }, { headerMode: 'none', diff --git a/src/providers/hive/dhive.js b/src/providers/hive/dhive.js index df187e969..4f719deee 100644 --- a/src/providers/hive/dhive.js +++ b/src/providers/hive/dhive.js @@ -86,12 +86,10 @@ export const fetchGlobalProps = async () => { } const steemPerMVests = - (parseToken( - get(globalDynamic, 'total_vesting_fund_steem', globalDynamic.total_vesting_fund_hive), - ) / + (parseToken(get(globalDynamic, 'total_vesting_fund_hive')) / parseToken(get(globalDynamic, 'total_vesting_shares'))) * 1e6; - const sbdPrintRate = get(globalDynamic, 'sbd_print_rate', globalDynamic.hbd_print_rate); + const sbdPrintRate = get(globalDynamic, 'hbd_print_rate'); const base = parseAsset(get(feedHistory, 'current_median_history.base')).amount; const quote = parseAsset(get(feedHistory, 'current_median_history.quote')).amount; const fundRecentClaims = get(rewardFund, 'recent_claims'); @@ -216,17 +214,17 @@ export const getUser = async (user, loggedIn = true) => { _account.steem_power = await vestToSteem( _account.vesting_shares, globalProperties.total_vesting_shares, - globalProperties.total_vesting_fund_steem || globalProperties.total_vesting_fund_hive, + globalProperties.total_vesting_fund_hive, ); _account.received_steem_power = await vestToSteem( get(_account, 'received_vesting_shares'), get(globalProperties, 'total_vesting_shares'), - get(globalProperties, 'total_vesting_fund_steem', globalProperties.total_vesting_fund_hive), + get(globalProperties, 'total_vesting_fund_hive'), ); _account.delegated_steem_power = await vestToSteem( get(_account, 'delegated_vesting_shares'), get(globalProperties, 'total_vesting_shares'), - get(globalProperties, 'total_vesting_fund_steem', globalProperties.total_vesting_fund_hive), + get(globalProperties, 'total_vesting_fund_hive'), ); if (has(_account, 'posting_json_metadata')) { @@ -316,7 +314,8 @@ export const getCommunities = async ( resolve({}); } } catch (error) { - reject(error); + console.log(error); + resolve({}); } }); @@ -459,7 +458,7 @@ export const getRankedPosts = async (query, currentUserName, filterNsfw) => { let posts = await client.call('bridge', 'get_ranked_posts', query); if (posts) { - posts = parsePosts(posts, currentUserName, true); + posts = parsePosts(posts, currentUserName); if (filterNsfw !== '0') { const updatedPosts = filterNsfwPost(posts, filterNsfw); @@ -477,7 +476,7 @@ export const getAccountPosts = async (query, currentUserName, filterNsfw) => { let posts = await client.call('bridge', 'get_account_posts', query); if (posts) { - posts = parsePosts(posts, currentUserName, true); + posts = parsePosts(posts, currentUserName); if (filterNsfw !== '0') { const updatedPosts = filterNsfwPost(posts, filterNsfw); @@ -1140,9 +1139,9 @@ export const lookupAccounts = async (username) => { } }; -export const getTrendingTags = async (tag) => { +export const getTrendingTags = async (tag, number = 20) => { try { - const tags = await client.database.call('get_trending_tags', [tag, 20]); + const tags = await client.database.call('get_trending_tags', [tag, number]); return tags; } catch (error) { return []; diff --git a/src/redux/actions/communitiesAction.js b/src/redux/actions/communitiesAction.js index e07c37de4..3ae39cfc2 100644 --- a/src/redux/actions/communitiesAction.js +++ b/src/redux/actions/communitiesAction.js @@ -61,19 +61,26 @@ export const fetchSubscribedCommunitiesFail = (payload) => ({ }); // Subscribe Community -export const subscribeCommunity = (currentAccount, pin, data, successToastText, failToastText) => { +export const subscribeCommunity = ( + currentAccount, + pin, + data, + successToastText, + failToastText, + screen, +) => { return (dispatch) => { - dispatch({ type: SUBSCRIBE_COMMUNITY, payload: data }); + dispatch({ type: SUBSCRIBE_COMMUNITY, payload: { ...data, screen } }); subscribeCommunityReq(currentAccount, pin, data) - .then((res) => dispatch(subscribeCommunitySuccess(data, successToastText))) - .catch((err) => dispatch(subscribeCommunityFail(err, data, failToastText))); + .then((res) => dispatch(subscribeCommunitySuccess(data, successToastText, screen))) + .catch((err) => dispatch(subscribeCommunityFail(err, data, failToastText, screen))); }; }; -export const subscribeCommunitySuccess = (data, successToastText) => { +export const subscribeCommunitySuccess = (data, successToastText, screen) => { return (dispatch) => [ dispatch({ - payload: data, + payload: { ...data, screen }, type: SUBSCRIBE_COMMUNITY_SUCCESS, }), dispatch({ @@ -83,10 +90,10 @@ export const subscribeCommunitySuccess = (data, successToastText) => { ]; }; -export const subscribeCommunityFail = (error, data, failToastText) => { +export const subscribeCommunityFail = (error, data, failToastText, screen) => { return (dispatch) => [ dispatch({ - payload: data, + payload: { ...data, screen }, type: SUBSCRIBE_COMMUNITY_FAIL, }), dispatch({ @@ -97,19 +104,26 @@ export const subscribeCommunityFail = (error, data, failToastText) => { }; // Leave Community -export const leaveCommunity = (currentAccount, pin, data, successToastText, failToastText) => { +export const leaveCommunity = ( + currentAccount, + pin, + data, + successToastText, + failToastText, + screen, +) => { return (dispatch) => { - dispatch({ type: LEAVE_COMMUNITY, payload: data }); + dispatch({ type: LEAVE_COMMUNITY, payload: { ...data, screen } }); subscribeCommunityReq(currentAccount, pin, data) - .then((res) => dispatch(leaveCommunitySuccess(data, successToastText))) - .catch((err) => dispatch(leaveCommunityFail(err, data, failToastText))); + .then((res) => dispatch(leaveCommunitySuccess(data, successToastText, screen))) + .catch((err) => dispatch(leaveCommunityFail(err, data, failToastText, screen))); }; }; -export const leaveCommunitySuccess = (data, successToastText) => { +export const leaveCommunitySuccess = (data, successToastText, screen) => { return (dispatch) => [ dispatch({ - payload: data, + payload: { ...data, screen }, type: LEAVE_COMMUNITY_SUCCESS, }), dispatch({ @@ -119,10 +133,10 @@ export const leaveCommunitySuccess = (data, successToastText) => { ]; }; -export const leaveCommunityFail = (error, data, failToastText) => { +export const leaveCommunityFail = (error, data, failToastText, screen) => { return (dispatch) => [ dispatch({ - payload: data, + payload: { ...data, screen }, type: LEAVE_COMMUNITY_FAIL, }), dispatch({ diff --git a/src/redux/reducers/communitiesReducer.js b/src/redux/reducers/communitiesReducer.js index 7d9c682ed..2c850659d 100644 --- a/src/redux/reducers/communitiesReducer.js +++ b/src/redux/reducers/communitiesReducer.js @@ -31,6 +31,27 @@ const initialState = { // error: false, //} }, + subscribingCommunitiesInCommunitiesScreenDiscoverTab: { + //['name']: { + // isSubscribed: false, + // loading: false, + // error: false, + //} + }, + subscribingCommunitiesInCommunitiesScreenJoinedTab: { + //['name']: { + // isSubscribed: false, + // loading: false, + // error: false, + //} + }, + subscribingCommunitiesInSearchResultsScreen: { + //['name']: { + // isSubscribed: false, + // loading: false, + // error: false, + //} + }, }; export default function (state = initialState, action) { @@ -90,77 +111,323 @@ export default function (state = initialState, action) { }, }; case SUBSCRIBE_COMMUNITY: - return { - ...state, - subscribingCommunitiesInFeedScreen: { - ...state.subscribingCommunitiesInFeedScreen, - [action.payload.communityId]: { - isSubscribed: false, - loading: true, - error: false, - }, - }, - }; + switch (action.payload.screen) { + case 'communitiesScreenDiscoverTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenDiscoverTab: { + ...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab, + [action.payload.communityId]: { + isSubscribed: false, + loading: true, + error: false, + }, + }, + }; + case 'communitiesScreenJoinedTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenJoinedTab: { + ...state.subscribingCommunitiesInCommunitiesScreenJoinedTab, + [action.payload.communityId]: { + isSubscribed: false, + loading: true, + error: false, + }, + }, + }; + case 'feedScreen': + return { + ...state, + subscribingCommunitiesInFeedScreen: { + ...state.subscribingCommunitiesInFeedScreen, + [action.payload.communityId]: { + isSubscribed: false, + loading: true, + error: false, + }, + }, + }; + case 'searchResultsScreen': + return { + ...state, + subscribingCommunitiesInSearchResultsScreen: { + ...state.subscribingCommunitiesInSearchResultsScreen, + [action.payload.communityId]: { + isSubscribed: false, + loading: true, + error: false, + }, + }, + }; + default: + return state; + } case SUBSCRIBE_COMMUNITY_SUCCESS: - return { - ...state, - subscribingCommunitiesInFeedScreen: { - ...state.subscribingCommunitiesInFeedScreen, - [action.payload.communityId]: { - isSubscribed: true, - loading: false, - error: false, - }, - }, - }; + switch (action.payload.screen) { + case 'communitiesScreenDiscoverTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenDiscoverTab: { + ...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab, + [action.payload.communityId]: { + isSubscribed: true, + loading: false, + error: false, + }, + }, + }; + case 'communitiesScreenJoinedTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenJoinedTab: { + ...state.subscribingCommunitiesInCommunitiesScreenJoinedTab, + [action.payload.communityId]: { + isSubscribed: true, + loading: false, + error: false, + }, + }, + }; + case 'feedScreen': + return { + ...state, + subscribingCommunitiesInFeedScreen: { + ...state.subscribingCommunitiesInFeedScreen, + [action.payload.communityId]: { + isSubscribed: true, + loading: false, + error: false, + }, + }, + }; + case 'searchResultsScreen': + return { + ...state, + subscribingCommunitiesInSearchResultsScreen: { + ...state.subscribingCommunitiesInSearchResultsScreen, + [action.payload.communityId]: { + isSubscribed: true, + loading: false, + error: false, + }, + }, + }; + default: + return state; + } case SUBSCRIBE_COMMUNITY_FAIL: - return { - ...state, - subscribingCommunitiesInFeedScreen: { - ...state.subscribingCommunitiesInFeedScreen, - [action.payload.communityId]: { - isSubscribed: false, - loading: false, - error: true, - }, - }, - }; + switch (action.payload.screen) { + case 'communitiesScreenDiscoverTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenDiscoverTab: { + ...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab, + [action.payload.communityId]: { + isSubscribed: false, + loading: false, + error: true, + }, + }, + }; + case 'communitiesScreenJoinedTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenJoinedTab: { + ...state.subscribingCommunitiesInCommunitiesScreenJoinedTab, + [action.payload.communityId]: { + isSubscribed: false, + loading: false, + error: true, + }, + }, + }; + case 'feedScreen': + return { + ...state, + subscribingCommunitiesInFeedScreen: { + ...state.subscribingCommunitiesInFeedScreen, + [action.payload.communityId]: { + isSubscribed: false, + loading: false, + error: true, + }, + }, + }; + case 'searchResultsScreen': + return { + ...state, + subscribingCommunitiesInSearchResultsScreen: { + ...state.subscribingCommunitiesInSearchResultsScreen, + [action.payload.communityId]: { + isSubscribed: false, + loading: false, + error: true, + }, + }, + }; + default: + return state; + } case LEAVE_COMMUNITY: - return { - ...state, - subscribingCommunitiesInFeedScreen: { - ...state.subscribingCommunitiesInFeedScreen, - [action.payload.communityId]: { - isSubscribed: true, - loading: true, - error: false, - }, - }, - }; + switch (action.payload.screen) { + case 'communitiesScreenDiscoverTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenDiscoverTab: { + ...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab, + [action.payload.communityId]: { + isSubscribed: true, + loading: true, + error: false, + }, + }, + }; + case 'communitiesScreenJoinedTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenJoinedTab: { + ...state.subscribingCommunitiesInCommunitiesScreenJoinedTab, + [action.payload.communityId]: { + isSubscribed: true, + loading: true, + error: false, + }, + }, + }; + case 'feedScreen': + return { + ...state, + subscribingCommunitiesInFeedScreen: { + ...state.subscribingCommunitiesInFeedScreen, + [action.payload.communityId]: { + isSubscribed: true, + loading: true, + error: false, + }, + }, + }; + case 'searchResultsScreen': + return { + ...state, + subscribingCommunitiesInSearchResultsScreen: { + ...state.subscribingCommunitiesInSearchResultsScreen, + [action.payload.communityId]: { + isSubscribed: true, + loading: true, + error: false, + }, + }, + }; + default: + return state; + } case LEAVE_COMMUNITY_SUCCESS: - return { - ...state, - subscribingCommunitiesInFeedScreen: { - ...state.subscribingCommunitiesInFeedScreen, - [action.payload.communityId]: { - isSubscribed: false, - loading: false, - error: false, - }, - }, - }; + switch (action.payload.screen) { + case 'communitiesScreenDiscoverTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenDiscoverTab: { + ...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab, + [action.payload.communityId]: { + isSubscribed: false, + loading: false, + error: false, + }, + }, + }; + case 'communitiesScreenJoinedTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenJoinedTab: { + ...state.subscribingCommunitiesInCommunitiesScreenJoinedTab, + [action.payload.communityId]: { + isSubscribed: false, + loading: false, + error: false, + }, + }, + }; + case 'feedScreen': + return { + ...state, + subscribingCommunitiesInFeedScreen: { + ...state.subscribingCommunitiesInFeedScreen, + [action.payload.communityId]: { + isSubscribed: false, + loading: false, + error: false, + }, + }, + }; + case 'searchResultsScreen': + return { + ...state, + subscribingCommunitiesInSearchResultsScreen: { + ...state.subscribingCommunitiesInSearchResultsScreen, + [action.payload.communityId]: { + isSubscribed: false, + loading: false, + error: false, + }, + }, + }; + default: + return state; + } case LEAVE_COMMUNITY_FAIL: - return { - ...state, - subscribingCommunitiesInFeedScreen: { - ...state.subscribingCommunitiesInFeedScreen, - [action.payload.communityId]: { - isSubscribed: true, - loading: false, - error: true, - }, - }, - }; + switch (action.payload.screen) { + case 'communitiesScreenDiscoverTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenDiscoverTab: { + ...state.subscribingCommunitiesInCommunitiesScreenDiscoverTab, + [action.payload.communityId]: { + isSubscribed: true, + loading: false, + error: true, + }, + }, + }; + case 'communitiesScreenJoinedTab': + return { + ...state, + subscribingCommunitiesInCommunitiesScreenJoinedTab: { + ...state.subscribingCommunitiesInCommunitiesScreenJoinedTab, + [action.payload.communityId]: { + isSubscribed: true, + loading: false, + error: true, + }, + }, + }; + case 'feedScreen': + return { + ...state, + subscribingCommunitiesInFeedScreen: { + ...state.subscribingCommunitiesInFeedScreen, + [action.payload.communityId]: { + isSubscribed: true, + loading: false, + error: true, + }, + }, + }; + case 'searchResultsScreen': + return { + ...state, + subscribingCommunitiesInSearchResultsScreen: { + ...state.subscribingCommunitiesInSearchResultsScreen, + [action.payload.communityId]: { + isSubscribed: true, + loading: false, + error: true, + }, + }, + }; + default: + return state; + } default: return state; } diff --git a/src/screens/communities/container/communitiesContainer.js b/src/screens/communities/container/communitiesContainer.js new file mode 100644 index 000000000..162a05e83 --- /dev/null +++ b/src/screens/communities/container/communitiesContainer.js @@ -0,0 +1,153 @@ +import { useState, useEffect } from 'react'; +import { withNavigation } from 'react-navigation'; +import { useSelector, useDispatch } from 'react-redux'; +import { shuffle } from 'lodash'; +import { useIntl } from 'react-intl'; + +import ROUTES from '../../../constants/routeNames'; + +import { getCommunities, getSubscriptions } from '../../../providers/hive/dhive'; + +import { toastNotification } from '../../../redux/actions/uiAction'; +import { subscribeCommunity, leaveCommunity } from '../../../redux/actions/communitiesAction'; + +const CommunitiesContainer = ({ children, navigation }) => { + const dispatch = useDispatch(); + const intl = useIntl(); + + const [discovers, setDiscovers] = useState([]); + const [subscriptions, setSubscriptions] = useState([]); + + const currentAccount = useSelector((state) => state.account.currentAccount); + const pinCode = useSelector((state) => state.application.pin); + const subscribingCommunitiesInDiscoverTab = useSelector( + (state) => state.communities.subscribingCommunitiesInCommunitiesScreenDiscoverTab, + ); + const subscribingCommunitiesInJoinedTab = useSelector( + (state) => state.communities.subscribingCommunitiesInCommunitiesScreenJoinedTab, + ); + + useEffect(() => { + getSubscriptions(currentAccount.username).then((subs) => { + subs.forEach((item) => item.push(true)); + getCommunities('', 50, '', 'rank').then((communities) => { + communities.forEach((community) => + Object.assign(community, { + isSubscribed: subs.some( + (subscribedCommunity) => subscribedCommunity[0] === community.name, + ), + }), + ); + + setSubscriptions(subs); + setDiscovers(shuffle(communities)); + }); + }); + }, []); + + useEffect(() => { + const discoversData = [...discovers]; + + Object.keys(subscribingCommunitiesInDiscoverTab).map((communityId) => { + if (!subscribingCommunitiesInDiscoverTab[communityId].loading) { + if (!subscribingCommunitiesInDiscoverTab[communityId].error) { + if (subscribingCommunitiesInDiscoverTab[communityId].isSubscribed) { + discoversData.forEach((item) => { + if (item.name === communityId) { + item.isSubscribed = true; + } + }); + } else { + discoversData.forEach((item) => { + if (item.name === communityId) { + item.isSubscribed = false; + } + }); + } + } + } + }); + + setDiscovers(discoversData); + }, [subscribingCommunitiesInDiscoverTab]); + + useEffect(() => { + const subscribedsData = [...subscriptions]; + + Object.keys(subscribingCommunitiesInJoinedTab).map((communityId) => { + if (!subscribingCommunitiesInJoinedTab[communityId].loading) { + if (!subscribingCommunitiesInJoinedTab[communityId].error) { + if (subscribingCommunitiesInJoinedTab[communityId].isSubscribed) { + subscribedsData.forEach((item) => { + if (item[0] === communityId) { + item[4] = true; + } + }); + } else { + subscribedsData.forEach((item) => { + if (item[0] === communityId) { + item[4] = false; + } + }); + } + } + } + }); + + setSubscriptions(subscribedsData); + }, [subscribingCommunitiesInJoinedTab]); + + // Component Functions + const _handleOnPress = (name) => { + navigation.navigate({ + routeName: ROUTES.SCREENS.COMMUNITY, + params: { + tag: name, + }, + }); + }; + + const _handleSubscribeButtonPress = (data, screen) => { + let subscribeAction; + let successToastText = ''; + let failToastText = ''; + + if (!data.isSubscribed) { + subscribeAction = subscribeCommunity; + + successToastText = intl.formatMessage({ + id: 'alert.success_subscribe', + }); + failToastText = intl.formatMessage({ + id: 'alert.fail_subscribe', + }); + } else { + subscribeAction = leaveCommunity; + + successToastText = intl.formatMessage({ + id: 'alert.success_leave', + }); + failToastText = intl.formatMessage({ + id: 'alert.fail_leave', + }); + } + + dispatch( + subscribeAction(currentAccount, pinCode, data, successToastText, failToastText, screen), + ); + }; + + return ( + children && + children({ + subscriptions, + discovers, + subscribingCommunitiesInDiscoverTab, + subscribingCommunitiesInJoinedTab, + handleOnPress: _handleOnPress, + handleSubscribeButtonPress: _handleSubscribeButtonPress, + }) + ); +}; + +export default withNavigation(CommunitiesContainer); diff --git a/src/screens/communities/index.js b/src/screens/communities/index.js new file mode 100644 index 000000000..0cb5f7260 --- /dev/null +++ b/src/screens/communities/index.js @@ -0,0 +1,3 @@ +import Communities from './view/communitiesScreen'; + +export default Communities; diff --git a/src/screens/communities/view/communitiesScreen.js b/src/screens/communities/view/communitiesScreen.js new file mode 100644 index 000000000..4d95259ff --- /dev/null +++ b/src/screens/communities/view/communitiesScreen.js @@ -0,0 +1,106 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; +import { FlatList, View, Text, TouchableOpacity } from 'react-native'; +import get from 'lodash/get'; +import { SafeAreaView } from 'react-navigation'; +import ScrollableTabView from 'react-native-scrollable-tab-view'; + +// Components +import { + FilterBar, + UserAvatar, + TabBar, + BasicHeader, + CommunitiesList, + SubscribedCommunitiesList, +} from '../../../components'; +import { CommunitiesPlaceHolder } from '../../../components/basicUIElements'; + +import CommunitiesContainer from '../container/communitiesContainer'; +import DEFAULT_IMAGE from '../../../assets/no_image.png'; +import Tag from '../../../components/basicUIElements/view/tag/tagView'; + +import styles from './communitiesScreenStyles'; +import globalStyles from '../../../globalStyles'; + +const CommunitiesScreen = ({ navigation, searchValue }) => { + const intl = useIntl(); + + const _renderEmptyContent = () => { + return ( + <> + + + + + ); + }; + + const _renderTabbar = () => ( + + ); + + return ( + + {({ + subscriptions, + discovers, + handleOnPress, + handleSubscribeButtonPress, + subscribingCommunitiesInDiscoverTab, + subscribingCommunitiesInJoinedTab, + }) => { + return ( + + + + + + + + + + + + + + ); + }} + + ); +}; + +export default CommunitiesScreen; diff --git a/src/screens/communities/view/communitiesScreenStyles.js b/src/screens/communities/view/communitiesScreenStyles.js new file mode 100644 index 000000000..7b3d00622 --- /dev/null +++ b/src/screens/communities/view/communitiesScreenStyles.js @@ -0,0 +1,51 @@ +import EStyleSheet from 'react-native-extended-stylesheet'; + +export default EStyleSheet.create({ + container: { + flex: 1, + backgroundColor: '$primaryBackgroundColor', + }, + itemWrapper: { + paddingHorizontal: 16, + paddingTop: 16, + paddingBottom: 8, + borderRadius: 8, + backgroundColor: '$primaryBackgroundColor', + flexDirection: 'row', + alignItems: 'center', + }, + itemWrapperGray: { + backgroundColor: '$primaryLightBackground', + }, + username: { + marginLeft: 10, + color: '$primaryBlack', + }, + communityWrapper: { + paddingHorizontal: 16, + paddingTop: 10, + paddingBottom: 10, + borderRadius: 8, + backgroundColor: '$primaryBackgroundColor', + flexDirection: 'row', + alignItems: 'center', + flex: 1, + }, + subscribeButton: { + maxWidth: 75, + borderWidth: 1, + borderColor: '$primaryBlue', + }, + subscribeButtonText: { + textAlign: 'center', + color: '$primaryBlue', + }, + community: { + justifyContent: 'center', + marginLeft: 15, + color: '$primaryBlack', + }, + tabbarItem: { + flex: 1, + }, +}); diff --git a/src/screens/community/screen/communityScreen.js b/src/screens/community/screen/communityScreen.js index 1af6dc00e..f319f669f 100644 --- a/src/screens/community/screen/communityScreen.js +++ b/src/screens/community/screen/communityScreen.js @@ -13,7 +13,7 @@ import styles from './communityStyles'; import { GLOBAL_POST_FILTERS, GLOBAL_POST_FILTERS_VALUE } from '../../../constants/options/filters'; -const TagResultScreen = ({ navigation }) => { +const CommunityScreen = ({ navigation }) => { const tag = navigation.getParam('tag', ''); const filter = navigation.getParam('filter', ''); @@ -114,4 +114,4 @@ const TagResultScreen = ({ navigation }) => { ); }; -export default TagResultScreen; +export default CommunityScreen; diff --git a/src/screens/drafts/screen/draftsScreen.js b/src/screens/drafts/screen/draftsScreen.js index 247b38a24..4c2ba126d 100644 --- a/src/screens/drafts/screen/draftsScreen.js +++ b/src/screens/drafts/screen/draftsScreen.js @@ -47,6 +47,7 @@ const DraftsScreen = ({ const tags = item.tags ? item.tags.split(/[ ,]+/) : []; const tag = tags[0] || ''; const image = catchDraftImage(item.body); + const thumbnail = catchDraftImage(item.body, 'match', true); const summary = postBodySummary({ item, last_update: item.created }, 100); const isSchedules = type === 'schedules'; @@ -57,7 +58,8 @@ const DraftsScreen = ({ title={item.title} summary={summary} isFormatedDate={isSchedules} - image={image ? { uri: catchDraftImage(item.body) } : null} + image={image ? { uri: image } : null} + thumbnail={thumbnail ? { uri: thumbnail } : null} username={currentAccount.name} reputation={currentAccount.reputation} handleOnPressItem={() => (isSchedules ? setSelectedId(item._id) : editDraft(item._id))} diff --git a/src/screens/index.js b/src/screens/index.js index 577231806..2d37b40f8 100755 --- a/src/screens/index.js +++ b/src/screens/index.js @@ -24,6 +24,7 @@ import AccountBoost from './accountBoost/screen/accountBoostScreen'; import Register from './register/registerScreen'; import TagResult from './tagResult'; import { Community } from './community'; +import Communities from './communities'; export { Bookmarks, @@ -52,4 +53,5 @@ export { Wallet, TagResult, Community, + Communities, }; diff --git a/src/screens/searchResult/container/communitiesContainer.js b/src/screens/searchResult/container/communitiesContainer.js deleted file mode 100644 index fee665812..000000000 --- a/src/screens/searchResult/container/communitiesContainer.js +++ /dev/null @@ -1,111 +0,0 @@ -import { useState, useEffect } from 'react'; -import { withNavigation } from 'react-navigation'; -import { connect } from 'react-redux'; -import isEmpty from 'lodash/isEmpty'; - -import ROUTES from '../../../constants/routeNames'; - -import { - subscribeCommunity, - getCommunities, - getSubscriptions, -} from '../../../providers/hive/dhive'; - -const CommunitiesContainer = ({ - children, - navigation, - searchValue, - currentAccount, - pinCode, - isLoggedIn, -}) => { - const [data, setData] = useState(); - const [filterIndex, setFilterIndex] = useState(1); - const [query, setQuery] = useState(''); - const [sort, setSort] = useState('rank'); - const [allSubscriptions, setAllSubscriptions] = useState([]); - const [noResult, setNoResult] = useState(false); - - useEffect(() => { - let isCancelled = false; - setData([]); - if (sort === 'my') { - setNoResult(true); - } else { - getCommunities('', 100, query, sort).then((res) => { - if (!isCancelled) { - if (!isEmpty(res)) { - setData(res); - setNoResult(false); - } else { - setNoResult(true); - } - } - }); - } - return () => { - isCancelled = true; - }; - }, [query, sort]); - - useEffect(() => { - setData([]); - setQuery(searchValue); - setNoResult(false); - }, [searchValue]); - - useEffect(() => { - let isCancelled = false; - if (data && !isCancelled) { - getSubscriptions(currentAccount.username).then((result) => { - if (result) { - setAllSubscriptions(result); - } - }); - } - return () => { - isCancelled = true; - }; - }, [data]); - - // Component Functions - const _handleOnVotersDropdownSelect = (index, value) => { - setFilterIndex(index); - setSort(value); - }; - - const _handleOnPress = (name) => { - navigation.navigate({ - routeName: ROUTES.SCREENS.COMMUNITY, - params: { - tag: name, - }, - }); - }; - - const _handleSubscribeButtonPress = (_data) => { - return subscribeCommunity(currentAccount, pinCode, _data); - }; - - return ( - children && - children({ - data, - filterIndex, - allSubscriptions, - handleOnVotersDropdownSelect: _handleOnVotersDropdownSelect, - handleOnPress: _handleOnPress, - handleSubscribeButtonPress: _handleSubscribeButtonPress, - isLoggedIn, - noResult, - }) - ); -}; - -const mapStateToProps = (state) => ({ - currentAccount: state.account.currentAccount, - pinCode: state.application.pin, - isLoggedIn: state.application.isLoggedIn, -}); - -export default connect(mapStateToProps)(withNavigation(CommunitiesContainer)); diff --git a/src/screens/searchResult/container/otherResultContainer.js b/src/screens/searchResult/container/otherResultContainer.js deleted file mode 100644 index 9ee3cbd6c..000000000 --- a/src/screens/searchResult/container/otherResultContainer.js +++ /dev/null @@ -1,84 +0,0 @@ -import { useState, useEffect } from 'react'; -import get from 'lodash/get'; -import { withNavigation } from 'react-navigation'; -import { connect } from 'react-redux'; - -import ROUTES from '../../../constants/routeNames'; - -import { lookupAccounts, getTrendingTags } from '../../../providers/hive/dhive'; -import { getLeaderboard } from '../../../providers/ecency/ecency'; - -const OtherResultContainer = (props) => { - const [users, setUsers] = useState([]); - const [tags, setTags] = useState([]); - const [filterIndex, setFilterIndex] = useState(0); - - const { children, navigation, searchValue, username } = props; - - useEffect(() => { - setUsers([]); - setTags([]); - - if (searchValue) { - lookupAccounts(searchValue.replace(/\s+/g, '')).then((res) => { - setUsers(res); - }); - getTrendingTags(searchValue.replace(/\s+/g, '')).then((res) => { - setTags(res); - }); - } else { - getLeaderboard().then((result) => { - const sos = result.map((item) => item._id); - setUsers(sos); - }); - } - }, [searchValue]); - - // Component Functions - - const _handleOnPress = (item) => { - switch (filterIndex) { - case 0: - navigation.navigate({ - routeName: item === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE, - params: { - username: item, - }, - key: item.text, - }); - break; - case 1: - navigation.navigate({ - routeName: ROUTES.SCREENS.TAG_RESULT, - params: { - tag: get(item, 'name', ''), - }, - }); - break; - - default: - break; - } - }; - - const _handleFilterChanged = (index, value) => { - setFilterIndex(index); - }; - - return ( - children && - children({ - users, - tags, - filterIndex, - handleOnPress: _handleOnPress, - handleFilterChanged: _handleFilterChanged, - }) - ); -}; - -const mapStateToProps = (state) => ({ - username: state.account.currentAccount.name, -}); - -export default connect(mapStateToProps)(withNavigation(OtherResultContainer)); diff --git a/src/screens/searchResult/container/postResultContainer.js b/src/screens/searchResult/container/postResultContainer.js deleted file mode 100644 index 064251b81..000000000 --- a/src/screens/searchResult/container/postResultContainer.js +++ /dev/null @@ -1,91 +0,0 @@ -import { useState, useEffect } from 'react'; -import get from 'lodash/get'; -import { withNavigation } from 'react-navigation'; -import { connect } from 'react-redux'; - -import ROUTES from '../../../constants/routeNames'; - -import { search, getPromotePosts } from '../../../providers/ecency/ecency'; -import { getPost } from '../../../providers/hive/dhive'; - -const PostResultContainer = ({ children, navigation, searchValue, currentAccountUsername }) => { - const [data, setData] = useState([]); - const [filterIndex, setFilterIndex] = useState(0); - const [sort, setSort] = useState('relevance'); - const [scrollId, setScrollId] = useState(''); - - useEffect(() => { - setData([]); - - if (searchValue) { - search({ q: searchValue, sort }).then((res) => { - setScrollId(res.scroll_id); - setData(res.results); - }); - } else { - getPromotePosts() - .then((result) => { - return Promise.all( - result.map((item) => - getPost( - get(item, 'author'), - get(item, 'permlink'), - currentAccountUsername, - true, - ).then((post) => { - post.author_rep = post.author_reputation; - post.body = (post.summary && post.summary.substring(0, 130)) || ''; - return post; - }), - ), - ); - }) - .then((result) => { - setData(result); - }); - } - }, [searchValue, sort]); - - // Component Functions - - const _handleOnPress = (item) => { - navigation.navigate({ - routeName: ROUTES.SCREENS.POST, - params: { - author: get(item, 'author'), - permlink: get(item, 'permlink'), - }, - key: get(item, 'permlink'), - }); - }; - - const _handleFilterChanged = (index, value) => { - setFilterIndex(index); - setSort(value); - }; - - const _loadMore = (index, value) => { - if (scrollId) { - search({ q: searchValue, sort, scroll_id: scrollId }).then((res) => { - setData([...data, ...res.results]); - }); - } - }; - - return ( - children && - children({ - data, - filterIndex, - handleOnPress: _handleOnPress, - handleFilterChanged: _handleFilterChanged, - loadMore: _loadMore, - }) - ); -}; - -const mapStateToProps = (state) => ({ - currentAccountUsername: state.account.currentAccount.username, -}); - -export default connect(mapStateToProps)(withNavigation(PostResultContainer)); diff --git a/src/screens/searchResult/screen/communities.js b/src/screens/searchResult/screen/communities.js deleted file mode 100644 index b3a615e29..000000000 --- a/src/screens/searchResult/screen/communities.js +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react'; -import { useIntl } from 'react-intl'; -import { FlatList, View, Text, TouchableOpacity } from 'react-native'; -import get from 'lodash/get'; - -// Components -import { FilterBar, UserAvatar } from '../../../components'; -import CommunitiesList from './communitiesList'; -import { CommunitiesPlaceHolder } from '../../../components/basicUIElements'; - -import CommunitiesContainer from '../container/communitiesContainer'; -import styles from './otherResultsStyles'; -import DEFAULT_IMAGE from '../../../assets/no_image.png'; -import Tag from '../../../components/basicUIElements/view/tag/tagView'; - -const filterOptions = ['my', 'rank', 'subs', 'new']; - -const CommunitiesScreen = ({ navigation, searchValue }) => { - const intl = useIntl(); - - const activeVotes = get(navigation, 'state.params.activeVotes'); - - const _renderEmptyContent = () => { - return ( - <> - - - - - ); - }; - - return ( - - {({ - data, - filterIndex, - allSubscriptions, - handleOnVotersDropdownSelect, - handleOnPress, - handleSubscribeButtonPress, - isLoggedIn, - noResult, - }) => ( - <> - - intl.formatMessage({ - id: `search_result.communities_filter.${item}`, - }), - )} - defaultText={intl.formatMessage({ - id: `search_result.communities_filter.${filterOptions[filterIndex]}`, - })} - selectedOptionIndex={filterIndex} - onDropdownSelect={(index) => handleOnVotersDropdownSelect(index, filterOptions[index])} - /> - {filterIndex !== 0 && ( - - )} - {filterIndex === 0 && allSubscriptions && allSubscriptions.length > 0 && ( - `${item}-${ind}`} - renderItem={({ item, index }) => ( - - - handleOnPress(item[0])}> - - - handleOnPress(item[0])}> - {item[1]} - - - - - handleSubscribeButtonPress({ isSubscribed: true, communityId: item[0] }) - } - /> - - - )} - ListEmptyComponent={_renderEmptyContent} - /> - )} - - )} - - ); -}; - -export default CommunitiesScreen; diff --git a/src/screens/searchResult/screen/otherResults.js b/src/screens/searchResult/screen/otherResults.js deleted file mode 100644 index 41e7eef3f..000000000 --- a/src/screens/searchResult/screen/otherResults.js +++ /dev/null @@ -1,107 +0,0 @@ -import React from 'react'; -import { SafeAreaView, FlatList, View, Text, TouchableOpacity } from 'react-native'; -import { useIntl } from 'react-intl'; - -// Components -import { FilterBar, UserAvatar } from '../../../components'; -import { CommunitiesPlaceHolder } from '../../../components/basicUIElements'; -import OtherResultContainer from '../container/otherResultContainer'; - -import styles from './otherResultsStyles'; - -import DEFAULT_IMAGE from '../../../assets/no_image.png'; - -const filterOptions = ['user', 'tag']; - -const OtherResult = ({ navigation, searchValue }) => { - const intl = useIntl(); - - const _renderUserItem = (item, index) => ( - - - {item} - - ); - - const _renderTagItem = (item, index) => ( - - {`#${item.name}`} - - ); - - const _renderEmptyContent = () => { - return ( - <> - - - - - - - - - ); - }; - - const _renderList = (users, tags, filterIndex, handleOnPress) => { - switch (filterIndex) { - case 0: - if (users && users.length > 0) { - return ( - `${item}-${ind}`} - renderItem={({ item, index }) => ( - handleOnPress(item)}> - {_renderUserItem(item, index)} - - )} - ListEmptyComponent={_renderEmptyContent} - /> - ); - } - case 1: - if (tags && tags.length > 0) { - return ( - `${item.name}-${item.comments}`} - renderItem={({ item, index }) => ( - handleOnPress(item)}> - {_renderTagItem(item, index)} - - )} - ListEmptyComponent={_renderEmptyContent} - /> - ); - } - default: - break; - } - }; - - return ( - - {({ users, tags, filterIndex, handleFilterChanged, handleOnPress, loadMore }) => ( - - - intl.formatMessage({ - id: `search_result.other_result_filter.${item}`, - }), - )} - defaultText={intl.formatMessage({ - id: `search_result.other_result_filter.${filterOptions[filterIndex]}`, - })} - selectedOptionIndex={filterIndex} - onDropdownSelect={(index) => handleFilterChanged(index, filterOptions[index])} - /> - {_renderList(users, tags, filterIndex, handleOnPress)} - - )} - - ); -}; - -export default OtherResult; diff --git a/src/screens/searchResult/screen/searchResultScreen.js b/src/screens/searchResult/screen/searchResultScreen.js index d174bfbca..7f388cc3a 100644 --- a/src/screens/searchResult/screen/searchResultScreen.js +++ b/src/screens/searchResult/screen/searchResultScreen.js @@ -2,12 +2,14 @@ import React, { useState, useEffect } from 'react'; import { View, SafeAreaView } from 'react-native'; import ScrollableTabView from 'react-native-scrollable-tab-view'; import { useIntl } from 'react-intl'; +import { debounce } from 'lodash'; // Components -import { SearchInput, TabBar } from '../../../components'; -import Communities from './communities'; -import PostResult from './postResult'; -import OtherResult from './otherResults'; +import { SearchInput, TabBar, IconButton } from '../../../components'; +import Communities from './tabs/communities/view/communitiesResults'; +import PostsResults from './tabs/best/view/postsResults'; +import TopicsResults from './tabs/topics/view/topicsResults'; +import PeopleResults from './tabs/people/view/peopleResults'; // Styles import styles from './searchResultStyles'; @@ -15,17 +17,8 @@ import globalStyles from '../../../globalStyles'; const SearchResultScreen = ({ navigation }) => { const [searchValue, setSearchValue] = useState(''); - const [text, setText] = useState(''); const intl = useIntl(); - useEffect(() => { - const delayDebounceFn = setTimeout(() => { - setSearchValue(text); - }, 100); - - return () => clearTimeout(delayDebounceFn); - }, [text]); - const _navigationGoBack = () => { navigation.goBack(); }; @@ -36,38 +29,64 @@ const SearchResultScreen = ({ navigation }) => { tabUnderlineDefaultWidth={80} tabUnderlineScaleX={2} tabBarPosition="overlayTop" + textStyle={styles.tabBarText} /> ); + const _handleChangeText = debounce((value) => { + setSearchValue(value); + }, 250); + return ( - + + + + + + + + + + + + + + + + + - - - - - - ); diff --git a/src/screens/searchResult/screen/searchResultStyles.js b/src/screens/searchResult/screen/searchResultStyles.js index 0ef7bc05b..3b1d96f37 100644 --- a/src/screens/searchResult/screen/searchResultStyles.js +++ b/src/screens/searchResult/screen/searchResultStyles.js @@ -5,6 +5,11 @@ export default EStyleSheet.create({ flex: 1, backgroundColor: '$primaryBackgroundColor', }, + headerContainer: { + flexDirection: 'row', + alignItems: 'center', + paddingRight: 12, + }, buttonContainer: { width: '50%', alignItems: 'center', @@ -28,4 +33,12 @@ export default EStyleSheet.create({ tabs: { flex: 1, }, + tabBarText: { + fontSize: 14, + }, + backIcon: { + fontSize: 24, + color: '$iconColor', + justifyContent: 'center', + }, }); diff --git a/src/screens/searchResult/screen/tabs/best/container/postsResultsContainer.js b/src/screens/searchResult/screen/tabs/best/container/postsResultsContainer.js new file mode 100644 index 000000000..26692c24e --- /dev/null +++ b/src/screens/searchResult/screen/tabs/best/container/postsResultsContainer.js @@ -0,0 +1,106 @@ +import { useState, useEffect } from 'react'; +import get from 'lodash/get'; +import { withNavigation } from 'react-navigation'; +import { connect } from 'react-redux'; + +import ROUTES from '../../../../../../constants/routeNames'; + +import { search, getPromotePosts } from '../../../../../../providers/ecency/ecency'; +import { getPost, getAccountPosts } from '../../../../../../providers/hive/dhive'; + +const PostsResultsContainer = ({ children, navigation, searchValue, currentAccountUsername }) => { + const [data, setData] = useState([]); + const [sort, setSort] = useState('newest'); + const [scrollId, setScrollId] = useState(''); + const [noResult, setNoResult] = useState(false); + + useEffect(() => { + setNoResult(false); + setData([]); + + if (searchValue) { + search({ q: `${searchValue} type:post`, sort }) + .then((res) => { + setScrollId(res.scroll_id); + setData(res.results); + if (res.results.length === 0) { + setNoResult(true); + } + }) + .catch((err) => console.log(err, 'search error')); + } else { + getInitialPosts(); + } + }, [searchValue]); + + const getInitialPosts = async () => { + // const promoteds = await getPromotePosts(); + // return await Promise.all( + // promoteds.map(async (item) => { + // const post = await getPost( + // get(item, 'author'), + // get(item, 'permlink'), + // currentAccountUsername, + // true, + // ); + // post.author_rep = post.author_reputation; + // post.body = (post.summary && post.summary.substring(0, 130)) || ''; + // // return await call to your function + // return post; + // }), + // ); + try { + const options = { + observer: currentAccountUsername, + account: 'ecency', + limit: 7, + sort: 'blog', + }; + const _data = await getAccountPosts(options); + + if (_data.length === 0) { + setNoResult(true); + } + setData(_data); + } catch (err) { + console.log(err); + } + }; + + // Component Functions + + const _handleOnPress = (item) => { + navigation.navigate({ + routeName: ROUTES.SCREENS.POST, + params: { + author: get(item, 'author'), + permlink: get(item, 'permlink'), + }, + key: get(item, 'permlink'), + }); + }; + + const _loadMore = (index, value) => { + if (scrollId) { + search({ q: `${searchValue} type:post`, sort, scroll_id: scrollId }).then((res) => { + setData([...data, ...res.results]); + }); + } + }; + + return ( + children && + children({ + data, + handleOnPress: _handleOnPress, + loadMore: _loadMore, + noResult, + }) + ); +}; + +const mapStateToProps = (state) => ({ + currentAccountUsername: state.account.currentAccount.username, +}); + +export default connect(mapStateToProps)(withNavigation(PostsResultsContainer)); diff --git a/src/screens/searchResult/screen/postResult.js b/src/screens/searchResult/screen/tabs/best/view/postsResults.js similarity index 56% rename from src/screens/searchResult/screen/postResult.js rename to src/screens/searchResult/screen/tabs/best/view/postsResults.js index 83c5f67cd..9045546b6 100644 --- a/src/screens/searchResult/screen/postResult.js +++ b/src/screens/searchResult/screen/tabs/best/view/postsResults.js @@ -6,28 +6,35 @@ import FastImage from 'react-native-fast-image'; import { useIntl } from 'react-intl'; // Components -import { PostHeaderDescription, FilterBar } from '../../../components'; -import { TextWithIcon, CommunitiesPlaceHolder } from '../../../components/basicUIElements'; -import PostResultContainer from '../container/postResultContainer'; +import { PostHeaderDescription, FilterBar } from '../../../../../../components'; +import { + TextWithIcon, + CommunitiesPlaceHolder, + EmptyScreen, +} from '../../../../../../components/basicUIElements'; +import PostsResultsContainer from '../container/postsResultsContainer'; -import { getTimeFromNow } from '../../../utils/time'; +import { getTimeFromNow } from '../../../../../../utils/time'; -import styles from './postResultStyles'; +import styles from './postsResultsStyles'; -import DEFAULT_IMAGE from '../../../assets/no_image.png'; +import DEFAULT_IMAGE from '../../../../../../assets/no_image.png'; const filterOptions = ['relevance', 'popularity', 'newest']; -const PostResult = ({ navigation, searchValue }) => { +const PostsResults = ({ navigation, searchValue }) => { const intl = useIntl(); const _renderItem = (item, index) => { + const reputation = + get(item, 'author_rep', undefined) || get(item, 'author_reputation', undefined); + return ( @@ -78,38 +85,29 @@ const PostResult = ({ navigation, searchValue }) => { }; return ( - - {({ data, filterIndex, handleFilterChanged, handleOnPress, loadMore }) => ( + + {({ data, handleOnPress, loadMore, noResult }) => ( - - intl.formatMessage({ - id: `search_result.post_result_filter.${item}`, - }), - )} - defaultText={intl.formatMessage({ - id: `search_result.post_result_filter.${filterOptions[filterIndex]}`, - })} - selectedOptionIndex={filterIndex} - onDropdownSelect={(index) => handleFilterChanged(index, filterOptions[index])} - /> - item.id && item.id.toString()} - renderItem={({ item, index }) => ( - handleOnPress(item)}> - {_renderItem(item, index)} - - )} - onEndReached={loadMore} - ListEmptyComponent={_renderEmptyContent} - ListFooterComponent={} - /> + {noResult ? ( + + ) : ( + index.toString()} + renderItem={({ item, index }) => ( + handleOnPress(item)}> + {_renderItem(item, index)} + + )} + onEndReached={loadMore} + ListEmptyComponent={_renderEmptyContent} + ListFooterComponent={} + /> + )} )} - + ); }; -export default PostResult; +export default PostsResults; diff --git a/src/screens/searchResult/screen/postResultStyles.js b/src/screens/searchResult/screen/tabs/best/view/postsResultsStyles.js similarity index 100% rename from src/screens/searchResult/screen/postResultStyles.js rename to src/screens/searchResult/screen/tabs/best/view/postsResultsStyles.js diff --git a/src/screens/searchResult/screen/tabs/communities/container/communitiesResultsContainer.js b/src/screens/searchResult/screen/tabs/communities/container/communitiesResultsContainer.js new file mode 100644 index 000000000..d1373f3f5 --- /dev/null +++ b/src/screens/searchResult/screen/tabs/communities/container/communitiesResultsContainer.js @@ -0,0 +1,150 @@ +import { useState, useEffect } from 'react'; +import { withNavigation } from 'react-navigation'; +import { useSelector, useDispatch } from 'react-redux'; +import { useIntl } from 'react-intl'; +import { shuffle } from 'lodash'; + +import ROUTES from '../../../../../../constants/routeNames'; + +import { getCommunities, getSubscriptions } from '../../../../../../providers/hive/dhive'; + +import { + subscribeCommunity, + leaveCommunity, +} from '../../../../../../redux/actions/communitiesAction'; + +// const DEFAULT_COMMUNITIES = [ +// 'hive-125125', +// 'hive-174301', +// 'hive-140217', +// 'hive-179017', +// 'hive-160545', +// 'hive-194913', +// 'hive-166847', +// 'hive-176853', +// 'hive-183196', +// 'hive-163772', +// 'hive-106444', +// ]; + +const CommunitiesResultsContainer = ({ children, navigation, searchValue }) => { + const intl = useIntl(); + const dispatch = useDispatch(); + + const [data, setData] = useState([]); + const [noResult, setNoResult] = useState(false); + + const pinCode = useSelector((state) => state.application.pin); + const currentAccount = useSelector((state) => state.account.currentAccount); + const isLoggedIn = useSelector((state) => state.application.isLoggedIn); + const subscribingCommunities = useSelector( + (state) => state.communities.subscribingCommunitiesInSearchResultsScreen, + ); + + useEffect(() => { + setData([]); + setNoResult(false); + + getSubscriptions(currentAccount.username).then((subs) => { + getCommunities('', searchValue ? 100 : 20, searchValue, 'rank').then((communities) => { + communities.forEach((community) => + Object.assign(community, { + isSubscribed: subs.some( + (subscribedCommunity) => subscribedCommunity[0] === community.name, + ), + }), + ); + + if (searchValue) { + setData(communities); + } else { + setData(shuffle(communities)); + } + + if (communities.length === 0) { + setNoResult(true); + } + }); + }); + }, [searchValue]); + + useEffect(() => { + const communitiesData = [...data]; + + Object.keys(subscribingCommunities).map((communityId) => { + if (!subscribingCommunities[communityId].loading) { + if (!subscribingCommunities[communityId].error) { + if (subscribingCommunities[communityId].isSubscribed) { + communitiesData.forEach((item) => { + if (item.name === communityId) { + item.isSubscribed = true; + } + }); + } else { + communitiesData.forEach((item) => { + if (item.name === communityId) { + item.isSubscribed = false; + } + }); + } + } + } + }); + + setData(communitiesData); + }, [subscribingCommunities]); + + // Component Functions + const _handleOnPress = (name) => { + navigation.navigate({ + routeName: ROUTES.SCREENS.COMMUNITY, + params: { + tag: name, + }, + }); + }; + + const _handleSubscribeButtonPress = (_data, screen) => { + let subscribeAction; + let successToastText = ''; + let failToastText = ''; + + if (!_data.isSubscribed) { + subscribeAction = subscribeCommunity; + + successToastText = intl.formatMessage({ + id: 'alert.success_subscribe', + }); + failToastText = intl.formatMessage({ + id: 'alert.fail_subscribe', + }); + } else { + subscribeAction = leaveCommunity; + + successToastText = intl.formatMessage({ + id: 'alert.success_leave', + }); + failToastText = intl.formatMessage({ + id: 'alert.fail_leave', + }); + } + + dispatch( + subscribeAction(currentAccount, pinCode, _data, successToastText, failToastText, screen), + ); + }; + + return ( + children && + children({ + data, + subscribingCommunities, + handleOnPress: _handleOnPress, + handleSubscribeButtonPress: _handleSubscribeButtonPress, + isLoggedIn, + noResult, + }) + ); +}; + +export default withNavigation(CommunitiesResultsContainer); diff --git a/src/screens/searchResult/screen/tabs/communities/view/communitiesResults.js b/src/screens/searchResult/screen/tabs/communities/view/communitiesResults.js new file mode 100644 index 000000000..c1af842cd --- /dev/null +++ b/src/screens/searchResult/screen/tabs/communities/view/communitiesResults.js @@ -0,0 +1,40 @@ +import React from 'react'; +import get from 'lodash/get'; + +// Components +import { CommunitiesList, EmptyScreen } from '../../../../../../components'; + +import CommunitiesResultsContainer from '../container/communitiesResultsContainer'; + +const CommunitiesResultsScreen = ({ navigation, searchValue }) => { + const activeVotes = get(navigation, 'state.params.activeVotes'); + + return ( + + {({ + data, + subscribingCommunities, + handleOnPress, + handleSubscribeButtonPress, + isLoggedIn, + noResult, + }) => + noResult ? ( + + ) : ( + + ) + } + + ); +}; + +export default CommunitiesResultsScreen; diff --git a/src/screens/searchResult/screen/tabs/people/container/peopleResultsContainer.js b/src/screens/searchResult/screen/tabs/people/container/peopleResultsContainer.js new file mode 100644 index 000000000..2edc0fd76 --- /dev/null +++ b/src/screens/searchResult/screen/tabs/people/container/peopleResultsContainer.js @@ -0,0 +1,65 @@ +import { useState, useEffect } from 'react'; +import get from 'lodash/get'; +import { withNavigation } from 'react-navigation'; +import { connect } from 'react-redux'; + +import ROUTES from '../../../../../../constants/routeNames'; + +import { lookupAccounts } from '../../../../../../providers/hive/dhive'; +import { getLeaderboard } from '../../../../../../providers/ecency/ecency'; + +const PeopleResultsContainer = (props) => { + const [users, setUsers] = useState([]); + const [noResult, setNoResult] = useState(false); + + const { children, navigation, searchValue, username } = props; + + useEffect(() => { + setNoResult(false); + setUsers([]); + + if (searchValue) { + lookupAccounts(searchValue).then((res) => { + if (res.length === 0) { + setNoResult(true); + } + setUsers(res); + }); + } else { + getLeaderboard().then((result) => { + const sos = result.map((item) => item._id); + if (sos.length === 0) { + setNoResult(true); + } + setUsers(sos); + }); + } + }, [searchValue]); + + // Component Functions + + const _handleOnPress = (item) => { + navigation.navigate({ + routeName: item === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE, + params: { + username: item, + }, + key: item.text, + }); + }; + + return ( + children && + children({ + users, + handleOnPress: _handleOnPress, + noResult, + }) + ); +}; + +const mapStateToProps = (state) => ({ + username: state.account.currentAccount.name, +}); + +export default connect(mapStateToProps)(withNavigation(PeopleResultsContainer)); diff --git a/src/screens/searchResult/screen/tabs/people/view/peopleResults.js b/src/screens/searchResult/screen/tabs/people/view/peopleResults.js new file mode 100644 index 000000000..5268b44d8 --- /dev/null +++ b/src/screens/searchResult/screen/tabs/people/view/peopleResults.js @@ -0,0 +1,52 @@ +import React from 'react'; +import { SafeAreaView, FlatList } from 'react-native'; +import { useIntl } from 'react-intl'; + +// Components +import { + ListPlaceHolder, + EmptyScreen, + UserListItem, +} from '../../../../../../components/basicUIElements'; +import PeopleResultsContainer from '../container/peopleResultsContainer'; + +import styles from './peopleResultsStyles'; + +const PeopleResults = ({ navigation, searchValue }) => { + const intl = useIntl(); + + const _renderEmptyContent = () => { + return ( + <> + + + ); + }; + + return ( + + {({ users, handleOnPress, noResult }) => ( + + {noResult ? ( + + ) : ( + index.toString()} + renderItem={({ item, index }) => ( + handleOnPress(item)} + index={index} + username={item} + /> + )} + ListEmptyComponent={_renderEmptyContent} + /> + )} + + )} + + ); +}; + +export default PeopleResults; diff --git a/src/screens/searchResult/screen/otherResultsStyles.js b/src/screens/searchResult/screen/tabs/people/view/peopleResultsStyles.js similarity index 100% rename from src/screens/searchResult/screen/otherResultsStyles.js rename to src/screens/searchResult/screen/tabs/people/view/peopleResultsStyles.js diff --git a/src/screens/searchResult/screen/tabs/topics/container/topicsResultsContainer.js b/src/screens/searchResult/screen/tabs/topics/container/topicsResultsContainer.js new file mode 100644 index 000000000..5b3c45517 --- /dev/null +++ b/src/screens/searchResult/screen/tabs/topics/container/topicsResultsContainer.js @@ -0,0 +1,57 @@ +import { useState, useEffect } from 'react'; +import get from 'lodash/get'; +import { withNavigation } from 'react-navigation'; +import { connect } from 'react-redux'; + +import ROUTES from '../../../../../../constants/routeNames'; + +import { getTrendingTags } from '../../../../../../providers/hive/dhive'; +import { getLeaderboard } from '../../../../../../providers/ecency/ecency'; +import { isCommunity } from '../../../../../../utils/communityValidation'; + +const OtherResultContainer = (props) => { + const [tags, setTags] = useState([]); + const [noResult, setNoResult] = useState(false); + + const { children, navigation, searchValue } = props; + + useEffect(() => { + if (searchValue.length <= 10) { + setNoResult(false); + setTags([]); + getTrendingTags(searchValue.trim(), 100).then((res) => { + const data = res?.filter((item) => !isCommunity(item.name)); + if (data.length === 0) { + setNoResult(true); + } + setTags(data); + }); + } + }, [searchValue]); + + // Component Functions + + const _handleOnPress = (item) => { + navigation.navigate({ + routeName: ROUTES.SCREENS.TAG_RESULT, + params: { + tag: get(item, 'name', ''), + }, + }); + }; + + return ( + children && + children({ + tags, + handleOnPress: _handleOnPress, + noResult, + }) + ); +}; + +const mapStateToProps = (state) => ({ + username: state.account.currentAccount.name, +}); + +export default connect(mapStateToProps)(withNavigation(OtherResultContainer)); diff --git a/src/screens/searchResult/screen/tabs/topics/view/topicsResults.js b/src/screens/searchResult/screen/tabs/topics/view/topicsResults.js new file mode 100644 index 000000000..39d0844ed --- /dev/null +++ b/src/screens/searchResult/screen/tabs/topics/view/topicsResults.js @@ -0,0 +1,54 @@ +import React from 'react'; +import { SafeAreaView, FlatList, View, Text, TouchableOpacity } from 'react-native'; +import { useIntl } from 'react-intl'; + +// Components +import { ListPlaceHolder, EmptyScreen } from '../../../../../../components/basicUIElements'; +import TopicsResultsContainer from '../container/topicsResultsContainer'; + +import styles from './topicsResultsStyles'; + +const filterOptions = ['user', 'tag']; + +const TopicsResults = ({ navigation, searchValue }) => { + const intl = useIntl(); + + const _renderTagItem = (item, index) => ( + + {`#${item.name}`} + + ); + + const _renderEmptyContent = () => { + return ( + <> + + + ); + }; + + return ( + + {({ tags, handleOnPress, noResult }) => ( + + {noResult ? ( + + ) : ( + index.toString()} + renderItem={({ item, index }) => ( + handleOnPress(item)}> + {_renderTagItem(item, index)} + + )} + ListEmptyComponent={_renderEmptyContent} + /> + )} + + )} + + ); +}; + +export default TopicsResults; diff --git a/src/screens/searchResult/screen/tabs/topics/view/topicsResultsStyles.js b/src/screens/searchResult/screen/tabs/topics/view/topicsResultsStyles.js new file mode 100644 index 000000000..6fe3db675 --- /dev/null +++ b/src/screens/searchResult/screen/tabs/topics/view/topicsResultsStyles.js @@ -0,0 +1,48 @@ +import EStyleSheet from 'react-native-extended-stylesheet'; + +export default EStyleSheet.create({ + container: { + flex: 1, + backgroundColor: '$primaryBackgroundColor', + }, + itemWrapper: { + paddingHorizontal: 16, + paddingTop: 16, + paddingBottom: 8, + borderRadius: 8, + backgroundColor: '$primaryBackgroundColor', + flexDirection: 'row', + alignItems: 'center', + }, + itemWrapperGray: { + backgroundColor: '$primaryLightBackground', + }, + username: { + marginLeft: 10, + color: '$primaryBlack', + }, + communityWrapper: { + paddingHorizontal: 16, + paddingTop: 10, + paddingBottom: 10, + borderRadius: 8, + backgroundColor: '$primaryBackgroundColor', + flexDirection: 'row', + alignItems: 'center', + flex: 1, + }, + subscribeButton: { + maxWidth: 75, + borderWidth: 1, + borderColor: '$primaryBlue', + }, + subscribeButtonText: { + textAlign: 'center', + color: '$primaryBlue', + }, + community: { + justifyContent: 'center', + marginLeft: 15, + color: '$primaryBlack', + }, +}); diff --git a/src/utils/communityValidation.js b/src/utils/communityValidation.js index 52ccf9f3e..d8c57c688 100644 --- a/src/utils/communityValidation.js +++ b/src/utils/communityValidation.js @@ -1,5 +1,7 @@ +import { isNumber } from 'lodash'; + export const isCommunity = (text) => { - if (/^hive-\d+/.test(text) && text.length === 11) { + if (/hive-[1-3]\d{4,6}$/.test(text) && isNumber(Number(text.split('-')[1]))) { return true; } diff --git a/src/utils/image.js b/src/utils/image.js index a71b1d7b7..a9f91540a 100644 --- a/src/utils/image.js +++ b/src/utils/image.js @@ -63,14 +63,16 @@ export const catchEntryImage = (entry, width = 0, height = 0, format = 'match') return null; }; -export const catchDraftImage = (body, format = 'match') => { +export const catchDraftImage = (body, format = 'match', thumbnail = false) => { const imgRegex = /(https?:\/\/.*\.(?:tiff?|jpe?g|gif|png|svg|ico|PNG|GIF|JPG))/g; format = whatOs === 'android' ? 'webp' : 'match'; if (body && imgRegex.test(body)) { const imageMatch = body.match(imgRegex); - - return proxifyImageSrc(imageMatch[0], 0, 0, format); + if (thumbnail) { + return proxifyImageSrc(imageMatch[0], 60, 50, format); + } + return proxifyImageSrc(imageMatch[0], 600, 500, format); } return null; }; diff --git a/src/utils/postParser.js b/src/utils/postParser.js index e633cce4f..8aad0576d 100644 --- a/src/utils/postParser.js +++ b/src/utils/postParser.js @@ -13,13 +13,13 @@ const webp = Platform.OS === 'ios' ? false : true; export const parsePosts = (posts, currentUserName) => { if (posts) { - const formattedPosts = posts.map((post) => parsePost(post, currentUserName)); + const formattedPosts = posts.map((post) => parsePost(post, currentUserName, false, true)); return formattedPosts; } return null; }; -export const parsePost = (post, currentUserName, isPromoted) => { +export const parsePost = (post, currentUserName, isPromoted, isList = false) => { if (!post) { return null; } @@ -33,10 +33,12 @@ export const parsePost = (post, currentUserName, isPromoted) => { post.json_metadata = {}; } post.image = catchPostImage(post.body, 600, 500, webp ? 'webp' : 'match'); + post.thumbnail = catchPostImage(post.body, 60, 50, webp ? 'webp' : 'match'); post.author_reputation = getReputation(post.author_reputation); post.avatar = getResizedAvatar(get(post, 'author')); - - post.body = renderPostBody(post, true, webp); + if (!isList) { + post.body = renderPostBody(post, true, webp); + } post.summary = postBodySummary(post, 150); post.is_declined_payout = parseAsset(post.max_accepted_payout).amount === 0; diff --git a/src/utils/wallet.js b/src/utils/wallet.js index c9d5b833a..c6f6d5f09 100644 --- a/src/utils/wallet.js +++ b/src/utils/wallet.js @@ -81,11 +81,7 @@ export const groomingTransactionData = (transaction, steemPerMVests) => { } break; case 'claim_reward_balance': - let { - reward_sbd: rewardSdb = opData.reward_hbd, - reward_steem: rewardSteem = opData.reward_hive, - reward_vests: rewardVests, - } = opData; + let { reward_hbd: rewardSdb, reward_hive: rewardSteem, reward_vests: rewardVests } = opData; rewardSdb = parseToken(rewardSdb).toFixed(3).replace(',', '.'); rewardSteem = parseToken(rewardSteem).toFixed(3).replace(',', '.'); @@ -192,15 +188,9 @@ export const groomingWalletData = async (user, globalProps, userCurrency) => { const [userdata] = state; // TODO: move them to utils these so big for a lifecycle function - walletData.rewardSteemBalance = parseToken( - userdata.reward_hive_balance || userdata.reward_steem_balance, - ); - walletData.rewardSbdBalance = parseToken( - userdata.reward_hbd_balance || userdata.reward_sbd_balance, - ); - walletData.rewardVestingSteem = parseToken( - userdata.reward_vesting_hive || userdata.reward_vesting_steem, - ); + walletData.rewardSteemBalance = parseToken(userdata.reward_hive_balance); + walletData.rewardSbdBalance = parseToken(userdata.reward_hbd_balance); + walletData.rewardVestingSteem = parseToken(userdata.reward_vesting_hive); walletData.hasUnclaimedRewards = walletData.rewardSteemBalance > 0 || walletData.rewardSbdBalance > 0 || @@ -211,11 +201,9 @@ export const groomingWalletData = async (user, globalProps, userCurrency) => { walletData.vestingSharesReceived = parseToken(userdata.received_vesting_shares); walletData.vestingSharesTotal = walletData.vestingShares - walletData.vestingSharesDelegated + walletData.vestingSharesReceived; - walletData.sbdBalance = parseToken(userdata.hbd_balance || userdata.sbd_balance); + walletData.sbdBalance = parseToken(userdata.hbd_balance); walletData.savingBalance = parseToken(userdata.savings_balance); - walletData.savingBalanceSbd = parseToken( - userdata.savings_hbd_balance || userdata.savings_sbd_balance, - ); + walletData.savingBalanceSbd = parseToken(userdata.savings_hbd_balance); const feedHistory = await getFeedHistory(); const base = parseToken(feedHistory.current_median_history.base); diff --git a/yarn.lock b/yarn.lock index a41ed955a..99229b11b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -698,10 +698,10 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@ecency/render-helper@^2.0.11": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@ecency/render-helper/-/render-helper-2.0.11.tgz#faa140a318aa6c2a693cfb3d21f3e8b1821cdb8e" - integrity sha512-g9lDtdB3yrta3pHQodPQQbFIkg3kCrVvcKhrqUrl2JY0hYreKUlmRzGWobJFphyAoXnUubrTW/l8p4N3hUwteg== +"@ecency/render-helper@^2.0.15": + version "2.0.15" + resolved "https://registry.yarnpkg.com/@ecency/render-helper/-/render-helper-2.0.15.tgz#8e78a2d771d44dc6e77bf63bbf786589cf11a772" + integrity sha512-II3TAdSy3pCqcuWgL81ZJ8N8jVrQR5rosxA8kGc40/vHeoDPhgLmUUxmykJVZUubejOTtowyIpjSu8g7sJkXRg== dependencies: he "^1.2.0" lru-cache "^5.1.1" @@ -7574,16 +7574,21 @@ react-native-iap@3.4.15: dependencies: dooboolab-welcome "^1.1.1" -react-native-image-crop-picker@^0.26.1: - version "0.26.2" - resolved "https://registry.yarnpkg.com/react-native-image-crop-picker/-/react-native-image-crop-picker-0.26.2.tgz#c70985ff6740e63569f90b185be0516d83f5933b" - integrity sha512-KnPtSJklwXr/BNdcyAlDp9xkDCQyJ5ZA4dM10elBc2aIXac/4CndbiPFZrwu4GlAYYYKlkiTTwTYW+h4RyGLaw== +react-native-image-crop-picker@^0.35.2: + version "0.35.2" + resolved "https://registry.yarnpkg.com/react-native-image-crop-picker/-/react-native-image-crop-picker-0.35.2.tgz#21e085e40cb5724e1e986b8eba59ef23df19598c" + integrity sha512-4nHAYwnemFJLzVJPl5dhNB+WQgNp41MLJjyYCypatMZl2GJD+EVXnu5eSUQE+UOpaIEhSVtqK5Y3OQ93hMhosQ== react-native-image-pan-zoom@^2.1.9: version "2.1.12" resolved "https://registry.yarnpkg.com/react-native-image-pan-zoom/-/react-native-image-pan-zoom-2.1.12.tgz#eb98bf56fb5610379bdbfdb63219cc1baca98fd2" integrity sha512-BF66XeP6dzuANsPmmFsJshM2Jyh/Mo1t8FsGc1L9Q9/sVP8MJULDabB1hms+eAoqgtyhMr5BuXV3E1hJ5U5H6Q== +react-native-image-size@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/react-native-image-size/-/react-native-image-size-1.1.3.tgz#7d69c2cd4e1d1632947867e47643ed8cabb9de27" + integrity sha512-jJvN6CjXVAm69LAVZNV7m7r50Qk9vuPZwLyrbs/k31/3Xs8bZyVCdvfP44FuBisITn/yFsiOo6i8NPrFBPH20w== + react-native-image-zoom-viewer@^2.2.27: version "2.2.27" resolved "https://registry.yarnpkg.com/react-native-image-zoom-viewer/-/react-native-image-zoom-viewer-2.2.27.tgz#fb3314c5dc86ac33da48cb31bf4920d97eecb6eb"