Skip to content

Commit 68ffddb

Browse files
Add ability to Share image from Status
Signed-off-by: Brian Sztamfater <brian@status.im>
1 parent 8534830 commit 68ffddb

File tree

11 files changed

+100
-58
lines changed

11 files changed

+100
-58
lines changed

android/app/src/main/java/im/status/ethereum/MainApplication.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import com.aakashns.reactnativedialogs.ReactNativeDialogsPackage;
1111
import com.facebook.react.ReactApplication;
12+
import cl.json.RNSharePackage;
1213
import com.facebook.react.ReactNativeHost;
1314
import com.reactnativenavigation.NavigationApplication;
1415
import com.reactnativenavigation.react.NavigationReactNativeHost;

android/settings.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
pluginManagement {
2+
include ':react-native-share'
3+
project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android')
24
repositories {
35
mavenLocal() // Let's prioritize local Maven repos so that Nix can provide them offline
46
gradlePluginPortal()

ios/Podfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ abstract_target 'Status' do
2525
pod 'secp256k1', git: "https://github.com/status-im/secp256k1.swift.git", submodules: true
2626

2727
target 'StatusIm' do
28+
pod 'RNShare', :path => '../node_modules/react-native-share'
29+
2830
target 'StatusImTests' do
2931
inherit! :complete
3032
# Pods for testing

ios/Podfile.lock

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ PODS:
22
- boost-for-react-native (1.63.0)
33
- BVLinearGradient (2.5.6):
44
- React
5-
- CryptoSwift (1.3.8)
5+
- CryptoSwift (1.4.1)
66
- DoubleConversion (1.1.6)
77
- FBLazyVector (0.63.4)
88
- FBReactNativeSpec (0.63.4):
@@ -224,7 +224,7 @@ PODS:
224224
- react-native-status-keycard (2.5.35):
225225
- Keycard
226226
- React
227-
- react-native-webview (10.9.2):
227+
- react-native-webview (11.3.0):
228228
- React-Core
229229
- React-RCTActionSheet (0.63.4):
230230
- React-Core/RCTActionSheetHeaders (= 0.63.4)
@@ -359,6 +359,8 @@ PODS:
359359
- React-RCTVibration
360360
- ReactCommon/turbomodule/core
361361
- Yoga
362+
- RNShare (7.0.1):
363+
- React-Core
362364
- RNSVG (9.13.6):
363365
- React
364366
- secp256k1 (0.1.6)
@@ -367,7 +369,7 @@ PODS:
367369
- SQLCipher/common (3.4.2)
368370
- SQLCipher/standard (3.4.2):
369371
- SQLCipher/common
370-
- SSZipArchive (2.2.3)
372+
- SSZipArchive (2.4.2)
371373
- TOCropViewController (2.6.0)
372374
- TouchID (4.4.1):
373375
- React
@@ -435,6 +437,7 @@ DEPENDENCIES:
435437
- RNPermissions (from `../node_modules/react-native-permissions`)
436438
- RNReactNativeHapticFeedback (from `../node_modules/react-native-haptic-feedback`)
437439
- RNReanimated (from `../node_modules/react-native-reanimated`)
440+
- RNShare (from `../node_modules/react-native-share`)
438441
- RNSVG (from `../node_modules/react-native-svg`)
439442
- secp256k1 (from `https://github.com/status-im/secp256k1.swift.git`)
440443
- SQLCipher (~> 3.0)
@@ -569,6 +572,8 @@ EXTERNAL SOURCES:
569572
:path: "../node_modules/react-native-haptic-feedback"
570573
RNReanimated:
571574
:path: "../node_modules/react-native-reanimated"
575+
RNShare:
576+
:path: "../node_modules/react-native-share"
572577
RNSVG:
573578
:path: "../node_modules/react-native-svg"
574579
secp256k1:
@@ -591,7 +596,7 @@ CHECKOUT OPTIONS:
591596
SPEC CHECKSUMS:
592597
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
593598
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
594-
CryptoSwift: 01b0f0cba1d5c212e5a335ff6c054fb75a204f00
599+
CryptoSwift: 0bc800a7e6a24c4fc9ebeab97d44b0d5f73a78bd
595600
DoubleConversion: cde416483dac037923206447da6e1454df403714
596601
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
597602
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
@@ -623,7 +628,7 @@ SPEC CHECKSUMS:
623628
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
624629
react-native-status: 45dbf1302ce3c258b459dfab137cd1c2c68c295d
625630
react-native-status-keycard: de55c01648d24ff7c17a77f3aa29a0421f44143c
626-
react-native-webview: 4e96d493f9f90ba4f03b28933f30b2964df07e39
631+
react-native-webview: af9990b21a9aeafa8e8347746eb4116c0de086af
627632
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
628633
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
629634
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0
@@ -650,14 +655,15 @@ SPEC CHECKSUMS:
650655
RNPermissions: ad71dd4f767ec254f2cd57592fbee02afee75467
651656
RNReactNativeHapticFeedback: 2566b468cc8d0e7bb2f84b23adc0f4614594d071
652657
RNReanimated: 70f662b5232dd5d19ccff581e919a54ea73df51c
658+
RNShare: 2dc2fcac3f7321cfd6b60a23ed4bf4d549f86f5f
653659
RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f
654660
secp256k1: f61d67e6fdcb85fd727acf1bf35ace6036db540c
655661
SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990
656-
SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9
662+
SSZipArchive: e7b4f3d9e780c2acc1764cd88fbf2de28f26e5b2
657663
TOCropViewController: 3105367e808b7d3d886a74ff59bf4804e7d3ab38
658664
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
659665
Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6
660666

661-
PODFILE CHECKSUM: 27b3929c4d7f0b5afd76276d0bd4ae289ec11f18
667+
PODFILE CHECKSUM: 2769eb02c836ad1eaddf5f34a0c61153c4c5fbec
662668

663669
COCOAPODS: 1.10.1

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"react-native-redash": "^16.0.11",
5757
"react-native-safe-area-context": "^2.0.0",
5858
"react-native-shake": "^3.3.1",
59+
"react-native-share": "^7.0.1",
5960
"react-native-splash-screen": "^3.2.0",
6061
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.5.35",
6162
"react-native-svg": "^9.8.4",
442 Bytes
Loading
647 Bytes
Loading

src/status_im/ui/screens/chat/image/preview/views.cljs

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,66 +3,75 @@
33
[status-im.ui.components.react :as react]
44
[reagent.core :as reagent]
55
[re-frame.core :as re-frame]
6-
[quo.core :as quo]
76
[quo.platform :as platform]
8-
[status-im.i18n.i18n :as i18n]
97
[status-im.ui.components.icons.icons :as icons]
10-
[status-im.ui.screens.chat.sheets :as sheets]
118
[quo.components.safe-area :as safe-area]
12-
["react-native-image-viewing" :default image-viewing]))
9+
["react-native-image-viewing" :default image-viewing]
10+
[status-im.utils.share :as share]
11+
[taoensso.timbre :as log]
12+
[status-im.utils.fs :as fs]
13+
[clojure.string :as string]))
1314

14-
(defn footer-options []
15-
(let [show-sheet (reagent/atom false)]
16-
(fn [{:keys [message on-close]}]
15+
(def temp-image-url (str (fs/cache-dir) "/image.jpeg"))
16+
17+
(defn share []
18+
(share/open {:url (str (when platform/android? "file://") temp-image-url)
19+
:type "image/jpeg"}
20+
#(log/debug "image shared successfully")
21+
#(log/error "could not share image")))
22+
23+
(defn header-options []
24+
(fn [{:keys [message on-close]}]
1725
;; FIXME(Ferossgp): Bottom sheet doesn't work on Android because of https://github.com/software-mansion/react-native-gesture-handler/issues/139
18-
(if platform/android?
19-
[:<>
20-
[react/touchable-opacity
21-
{:on-press (fn []
22-
(on-close)
23-
(re-frame/dispatch [:chat.ui/save-image-to-gallery (get-in message [:content :image])]))
24-
:style {:background-color colors/black-transparent-86
25-
:border-radius 44
26-
:padding 8
27-
:position :absolute
28-
:bottom 0
29-
:right 0}}
30-
[icons/icon :main-icons/download {:container-style {:width 24
31-
:height 24}
32-
:color colors/white-persist}]]]
33-
[:<>
34-
[react/touchable-opacity
35-
{:on-press #(reset! show-sheet true)
36-
:style {:background-color colors/black-transparent-86
37-
:border-radius 44
38-
:padding 8
39-
:position :absolute
40-
:bottom 0
41-
:right 0}}
42-
[icons/icon :main-icons/more {:container-style {:width 24
26+
[react/view {:style {:flex-direction :row
27+
:background-color colors/black-transparent-86
28+
:border-radius 44
29+
:padding-vertical 8
30+
:padding-horizontal 12
31+
:position :absolute
32+
:right 0}}
33+
[react/touchable-opacity
34+
{:on-press (fn []
35+
(on-close)
36+
(re-frame/dispatch [:chat.ui/save-image-to-gallery (get-in message [:content :image])]))
37+
:style {:margin-right 10}
38+
:accessibility-label :save-button}
39+
[icons/icon :main-icons/download {:container-style {:width 24
4340
:height 24}
4441
:color colors/white-persist}]]
45-
;; NOTE(Ferossgp): If we use global bottom sheet, then it is rendered under the preview
46-
[quo/bottom-sheet {:visible? @show-sheet
47-
:on-cancel #(reset! show-sheet false)}
48-
[sheets/image-long-press message #(do (reset! show-sheet false)
49-
(on-close))]]]))))
42+
[react/touchable-opacity
43+
{:on-press (fn []
44+
(fs/write-file
45+
temp-image-url
46+
(last (string/split (get-in message [:content :image]) ",")) "base64"
47+
#(share)
48+
#(log/error "error writing image to cache dir")))
49+
:style {:margin-left 10}
50+
:accessibility-label :share-button}
51+
[icons/icon :main-icons/share-default {:container-style {:width 24
52+
:height 24}
53+
:color colors/white-persist}]]]))
5054

51-
(defn footer [{:keys [on-close] :as props}]
55+
(defn header [{:keys [on-close] :as props}]
5256
[safe-area/consumer
5357
(fn [insets]
54-
[react/view {:style {:padding-horizontal 24
55-
:padding-bottom (+ (:bottom insets) 8)}}
56-
[react/view {:style {:justify-content :center
57-
:align-items :center}}
58+
[react/view {:style {:padding-horizontal 15
59+
:padding-top (+ (:bottom insets) 50)}}
60+
[react/view {:style {:justify-content :center}}
5861
[react/touchable-opacity {:on-press on-close
59-
:style {:background-color colors/black-transparent-86
60-
:padding-horizontal 24
61-
:padding-vertical 11
62-
:border-radius 44}}
63-
[quo/text {:style {:color colors/white-persist}}
64-
(i18n/label :t/close)]]
65-
[footer-options props]]])])
62+
:style {:padding-vertical 11
63+
:border-radius 44}
64+
:accessibility-label :close-button}
65+
[react/view {:style {:background-color colors/black-transparent-86
66+
:border-radius 20
67+
:width 40
68+
:height 40
69+
:justify-content :center
70+
:align-items :center}}
71+
[icons/icon :main-icons/close {:container-style {:width 24
72+
:height 24}
73+
:color colors/white-persist}]]]
74+
[header-options props]]])])
6675

6776
(defn preview-image [{{:keys [content] :as message} :message
6877
visible :visible
@@ -73,7 +82,7 @@
7382
:hide-footer-on-zoom false
7483
:swipe-to-close-enabled platform/ios?
7584
:presentation-style "overFullScreen"
76-
:HeaderComponent #(reagent/as-element [:<>]) ; NOTE: Keep it to remove default header
77-
:FooterComponent #(reagent/as-element [footer {:on-close on-close
85+
:HeaderComponent #(reagent/as-element [header {:on-close on-close
7886
:message message}])
87+
:FooterComponent #(reagent/as-element [:<>])
7988
:visible visible}])

src/status_im/utils/fs.cljs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
(.then on-read)
1515
(.catch on-error)))
1616

17+
(defn write-file [path content encoding on-write on-error]
18+
(-> (.writeFile react-native-fs path content encoding)
19+
(.then on-write)
20+
(.catch on-error)))
21+
1722
(defn read-dir [path]
1823
(.readDir react-native-fs path))
1924

@@ -25,3 +30,6 @@
2530

2631
(defn file-exists? [path]
2732
(.exists react-native-fs path))
33+
34+
(defn cache-dir []
35+
(.-CachesDirectoryPath ^js react-native-fs))

src/status_im/utils/share.cljs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(ns status-im.utils.share
2+
(:require ["react-native-share" :default react-native-share]))
3+
4+
(defn open [options on-success on-error]
5+
(-> ^js react-native-share
6+
(.open (clj->js options))
7+
(.then on-success)
8+
(.catch on-error)))

0 commit comments

Comments
 (0)