|
4 | 4 | [quo2.foundations.colors :as colors]
|
5 | 5 | [react-native.camera-kit :as camera-kit]
|
6 | 6 | [react-native.core :as rn]
|
| 7 | + [react-native.fast-image :as fast-image] |
| 8 | + [react-native.orientation :as orientation] |
| 9 | + [react-native.platform :as platform] |
7 | 10 | [react-native.reanimated :as reanimated]
|
8 | 11 | [react-native.safe-area :as safe-area]
|
9 | 12 | [reagent.core :as reagent]
|
10 | 13 | [utils.i18n :as i18n]
|
11 | 14 | [status-im2.contexts.chat.camera.style :as style]
|
12 | 15 | [utils.re-frame :as rf]))
|
13 | 16 |
|
| 17 | +(defn retake |
| 18 | + [flash uri] |
| 19 | + (let [current-flash @flash] |
| 20 | + (when platform/android? |
| 21 | + (reset! flash false) ; On Android, setting flash needs to be delayed until camera has initialized |
| 22 | + (js/setTimeout #(reset! flash current-flash) 300)) |
| 23 | + (reset! uri nil))) |
| 24 | + |
| 25 | +(defn handle-orientation |
| 26 | + [current-orientation rotate] |
| 27 | + (orientation/use-device-orientation-change (fn [result] |
| 28 | + (reset! current-orientation result) |
| 29 | + (cond |
| 30 | + (= result orientation/landscape-left) |
| 31 | + (reanimated/animate rotate "90deg") |
| 32 | + (= result orientation/landscape-right) |
| 33 | + (reanimated/animate rotate "-90deg") |
| 34 | + :else |
| 35 | + (reanimated/animate rotate "0deg"))))) |
| 36 | + |
14 | 37 | (defn- f-zoom-button
|
15 |
| - [{:keys [value current-zoom]}] |
| 38 | + [{:keys [value current-zoom rotate]}] |
16 | 39 | (let [selected? (= @current-zoom value)
|
17 | 40 | size (reanimated/use-shared-value (if selected? 37 25))]
|
18 | 41 | (rn/use-effect #(reanimated/animate size (if selected? 37 25)) [@current-zoom])
|
19 | 42 | [rn/touchable-opacity
|
20 | 43 | {:on-press #(reset! current-zoom value)
|
21 | 44 | :style style/zoom-button-container
|
22 | 45 | :accessibility-label (str "zoom-" value)}
|
23 |
| - [reanimated/view {:style (style/zoom-button size)} |
| 46 | + [reanimated/view {:style (style/zoom-button size rotate)} |
24 | 47 | [quo/text
|
25 |
| - {:size (if selected? :paragraph-2 :label) |
26 |
| - :weight :semi-bold |
27 |
| - :style {:color (if selected? |
28 |
| - colors/system-yellow |
29 |
| - colors/white)}} |
| 48 | + {:size (if selected? :paragraph-2 :label) |
| 49 | + :weight :semi-bold |
| 50 | + :number-of-lines 1 |
| 51 | + :style {:color (if selected? |
| 52 | + colors/system-yellow |
| 53 | + colors/white)}} |
30 | 54 | (str value (when selected? "x"))]]]))
|
31 | 55 |
|
32 | 56 | (defn zoom-button
|
|
43 | 67 | (camera-kit/capture @camera-ref #(reset! uri %)))
|
44 | 68 | :style style/inner-circle}]])
|
45 | 69 |
|
| 70 | +(defn zoom-buttons |
| 71 | + [] |
| 72 | + (let [current-zoom (reagent/atom 1)] |
| 73 | + (fn [top insets rotate] |
| 74 | + [rn/view {:style (style/zoom-container top insets)} |
| 75 | + [zoom-button {:value 0.5 :current-zoom current-zoom :rotate rotate}] |
| 76 | + [zoom-button {:value 1 :current-zoom current-zoom :rotate rotate}] |
| 77 | + [zoom-button {:value 2 :current-zoom current-zoom :rotate rotate}] |
| 78 | + [zoom-button {:value 3 :current-zoom current-zoom :rotate rotate}]]))) |
| 79 | + |
| 80 | + |
| 81 | +(defn- f-bottom-area |
| 82 | + [{:keys [top insets uri camera-ref rotate]} back flip-camera] |
| 83 | + [rn/view {:style (style/bottom-area top insets @uri)} |
| 84 | + [quo/text {:style style/photo-text} (i18n/label :t/photo-caps)] |
| 85 | + [rn/view {:style style/actions-container} |
| 86 | + [quo/text |
| 87 | + {:on-press back |
| 88 | + :style {:font-size 17 |
| 89 | + :color colors/white} |
| 90 | + :accessibility-label :cancel} |
| 91 | + (i18n/label :t/cancel)] |
| 92 | + [snap-button camera-ref uri] |
| 93 | + [reanimated/touchable-opacity |
| 94 | + {:style (reanimated/apply-animations-to-style {:transform [{:rotate rotate}]} {}) |
| 95 | + :on-press flip-camera} |
| 96 | + [quo/icon :i/rotate-camera |
| 97 | + {:size 48 :color colors/white :accessibility-label :flip-camera}]]]]) |
| 98 | + |
| 99 | +(defn bottom-area |
| 100 | + [{:keys [flash camera-type] :as args}] |
| 101 | + (let [back #(rf/dispatch [:navigate-back]) |
| 102 | + flip-camera (fn [] |
| 103 | + (reset! flash false) |
| 104 | + (reset! camera-type (if (= @camera-type camera-kit/camera-type-back) |
| 105 | + camera-kit/camera-type-front |
| 106 | + camera-kit/camera-type-back)))] |
| 107 | + [:f> f-bottom-area args back flip-camera])) |
| 108 | + |
| 109 | +(defn- f-camera-screen |
| 110 | + [{:keys [camera-ref uri camera-type current-orientation flash toggle-flash]}] |
| 111 | + (let [window (rn/get-window) |
| 112 | + {:keys [width height]} window |
| 113 | + camera-window-height (* width 1.33) |
| 114 | + insets (safe-area/get-insets) |
| 115 | + top (/ (- height camera-window-height (:bottom insets)) 2) |
| 116 | + top-landscape (/ (- height (* width 0.75) (:bottom insets)) 2) |
| 117 | + portrait? (= @current-orientation orientation/portrait) |
| 118 | + rotate (reanimated/use-shared-value "0deg") |
| 119 | + retake #(retake flash uri) |
| 120 | + use-photo (fn [] |
| 121 | + (rf/dispatch [:photo-selector/camera-roll-pick {:uri @uri}]) |
| 122 | + (rf/dispatch [:navigate-back]))] |
| 123 | + (handle-orientation current-orientation rotate) |
| 124 | + [rn/view {:style style/screen-container} |
| 125 | + [reanimated/touchable-opacity |
| 126 | + {:active-opacity 1 |
| 127 | + :on-press toggle-flash |
| 128 | + :style (style/flash-container rotate @uri)} |
| 129 | + (when-not @flash |
| 130 | + [rn/view {:style style/cancel-dash}]) |
| 131 | + [quo/icon :i/flash-camera |
| 132 | + {:color colors/white |
| 133 | + :size 24}]] |
| 134 | + (if @uri |
| 135 | + [fast-image/fast-image |
| 136 | + {:style (style/image width camera-window-height (if portrait? top top-landscape) portrait?) |
| 137 | + :source {:uri @uri}}] |
| 138 | + [camera-kit/camera |
| 139 | + {:ref #(reset! camera-ref %) |
| 140 | + :style (style/camera-window width camera-window-height top) |
| 141 | + :flash-mode (if @flash :on :off) |
| 142 | + :camera-type @camera-type}]) |
| 143 | + (when-not @uri |
| 144 | + [zoom-buttons top insets rotate]) |
| 145 | + [rn/view {:style (style/confirmation-container insets @uri)} |
| 146 | + [quo/text |
| 147 | + {:on-press retake |
| 148 | + :style {:font-size 17 |
| 149 | + :color colors/white}} |
| 150 | + (i18n/label :t/retake)] |
| 151 | + [quo/text |
| 152 | + {:on-press use-photo |
| 153 | + :style {:font-size 17 |
| 154 | + :color colors/white}} |
| 155 | + (i18n/label :t/use-photo)]] |
| 156 | + [bottom-area |
| 157 | + {:top top |
| 158 | + :insets insets |
| 159 | + :uri uri |
| 160 | + :camera-type camera-type |
| 161 | + :camera-ref camera-ref |
| 162 | + :flash flash |
| 163 | + :rotate rotate}]])) |
| 164 | + |
46 | 165 | (defn camera-screen
|
47 | 166 | []
|
48 |
| - (let [camera-ref (atom nil) |
49 |
| - uri (reagent/atom nil) |
50 |
| - current-zoom (reagent/atom "1")] |
51 |
| - (fn [] |
52 |
| - (let [window (rn/get-window) |
53 |
| - {:keys [width height]} window |
54 |
| - camera-window-height (* width 1.33) |
55 |
| - insets (safe-area/get-insets) |
56 |
| - top (/ (- height camera-window-height (:bottom insets)) 2)] |
57 |
| - [rn/view {:style style/screen-container} |
58 |
| - (when-not @uri |
59 |
| - [rn/view {:style style/flash-container} |
60 |
| - [quo/icon :i/flash-camera |
61 |
| - {:color colors/white |
62 |
| - :size 24}]]) |
63 |
| - (if @uri |
64 |
| - [rn/image |
65 |
| - {:style (style/camera-window width camera-window-height top) |
66 |
| - :source {:uri @uri}}] |
67 |
| - [camera-kit/camera |
68 |
| - {:ref #(reset! camera-ref %) |
69 |
| - :style (style/camera-window width camera-window-height top)}]) |
70 |
| - (when-not @uri |
71 |
| - [rn/view {:style (style/zoom-container top insets)} |
72 |
| - [zoom-button {:value "0.5" :current-zoom current-zoom}] |
73 |
| - [zoom-button {:value "1" :current-zoom current-zoom}] |
74 |
| - [zoom-button {:value "2" :current-zoom current-zoom}] |
75 |
| - [zoom-button {:value "3" :current-zoom current-zoom}]]) |
76 |
| - (if @uri |
77 |
| - [rn/view {:style (style/confirmation-container insets)} |
78 |
| - [quo/text |
79 |
| - {:on-press #(reset! uri nil) |
80 |
| - :style {:font-size 17 |
81 |
| - :color colors/white}} |
82 |
| - (i18n/label :t/retake)] |
83 |
| - [quo/text |
84 |
| - {:on-press (fn [] |
85 |
| - (rf/dispatch [:photo-selector/camera-roll-pick {:uri @uri}]) |
86 |
| - (rf/dispatch [:navigate-back])) |
87 |
| - :style {:font-size 17 |
88 |
| - :color colors/white}} |
89 |
| - (i18n/label :t/use-photo)]] |
90 |
| - [rn/view {:style (style/bottom-area top insets)} |
91 |
| - [quo/text {:style style/photo-text} (i18n/label :t/PHOTO)] |
92 |
| - [rn/view {:style style/actions-container} |
93 |
| - [quo/text |
94 |
| - {:on-press #(rf/dispatch [:navigate-back]) |
95 |
| - :style {:font-size 17 |
96 |
| - :color colors/white} |
97 |
| - :accessibility-label :cancel} |
98 |
| - (i18n/label :t/cancel)] |
99 |
| - [snap-button camera-ref uri] |
100 |
| - [quo/icon :i/rotate-camera |
101 |
| - {:size 48 :color colors/white :accessibility-label :flip-camera}]]])])))) |
| 167 | + (let [flash (reagent/atom false) |
| 168 | + args {:camera-ref (atom nil) |
| 169 | + :uri (reagent/atom nil) |
| 170 | + :camera-type (reagent/atom camera-kit/camera-type-back) |
| 171 | + :current-orientation (atom orientation/portrait) |
| 172 | + :flash flash |
| 173 | + :toggle-flash #(swap! flash not)}] |
| 174 | + [:f> f-camera-screen args])) |
0 commit comments