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