Camera extra features (#16781)

feat: camera extra features
This commit is contained in:
Omar Basem 2023-07-31 09:01:30 +04:00 committed by GitHub
parent 82645f5df4
commit 0ee0137c72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 168 additions and 71 deletions

View File

@ -7,10 +7,23 @@
{:flex 1 {:flex 1
:background-color colors/black}) :background-color colors/black})
(def flash-container (defn flash-container
{:position :absolute [rotate uri]
:top 50 (reanimated/apply-animations-to-style
:left 25}) {:transform [{:rotate rotate}]}
{:position :absolute
:top 50
:left (if uri -25 25)}))
(def cancel-dash
{:width 1
:height 32
:top -4
:left 12
:z-index 1
:transform [{:rotate "-45deg"}]
:background-color colors/white
:position :absolute})
(defn camera-window (defn camera-window
[width height top] [width height top]
@ -18,6 +31,12 @@
:height height :height height
:top top}) :top top})
(defn image
[width height top portrait?]
{:width width
:height (if portrait? height (* width 0.75))
:top top})
(def zoom-button-container (def zoom-button-container
{:width 37 {:width 37
:height 37 :height 37
@ -38,19 +57,22 @@
:bottom (+ top (:bottom insets) (when platform/android? (:top insets)) 18)}) :bottom (+ top (:bottom insets) (when platform/android? (:top insets)) 18)})
(defn zoom-button (defn zoom-button
[size] [size rotate]
(reanimated/apply-animations-to-style (reanimated/apply-animations-to-style
{:width size {:width size
:height size} :height size
:transform [{:rotate rotate}]}
{:background-color colors/black-opa-30 {:background-color colors/black-opa-30
:justify-content :center :justify-content :center
:align-items :center :align-items :center
:border-radius 50})) :border-radius 50}))
(defn bottom-area (defn bottom-area
[top insets] [top insets uri]
{:left 20 {:left 20
:right 20 :right 20
:opacity (if uri 0 1)
:z-index (if uri 0 1)
:position :absolute :position :absolute
:height (+ top (when platform/android? (:top insets))) :height (+ top (when platform/android? (:top insets)))
:bottom (:bottom insets)}) :bottom (:bottom insets)})
@ -84,8 +106,10 @@
:background-color colors/white}) :background-color colors/white})
(defn confirmation-container (defn confirmation-container
[insets] [insets uri]
{:position :absolute {:position :absolute
:opacity (if uri 1 0)
:z-index (if uri 1 0)
:bottom 0 :bottom 0
:left 0 :left 0
:right 0 :right 0

View File

@ -4,6 +4,9 @@
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[react-native.camera-kit :as camera-kit] [react-native.camera-kit :as camera-kit]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.fast-image :as fast-image]
[react-native.orientation :as orientation]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[reagent.core :as reagent] [reagent.core :as reagent]
@ -11,8 +14,28 @@
[status-im2.contexts.chat.camera.style :as style] [status-im2.contexts.chat.camera.style :as style]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn retake
[flash uri]
(let [current-flash @flash]
(when platform/android?
(reset! flash false) ; On Android, setting flash needs to be delayed until camera has initialized
(js/setTimeout #(reset! flash current-flash) 300))
(reset! uri nil)))
(defn handle-orientation
[current-orientation rotate]
(orientation/use-device-orientation-change (fn [result]
(reset! current-orientation result)
(cond
(= result orientation/landscape-left)
(reanimated/animate rotate "90deg")
(= result orientation/landscape-right)
(reanimated/animate rotate "-90deg")
:else
(reanimated/animate rotate "0deg")))))
(defn- f-zoom-button (defn- f-zoom-button
[{:keys [value current-zoom]}] [{:keys [value current-zoom rotate]}]
(let [selected? (= @current-zoom value) (let [selected? (= @current-zoom value)
size (reanimated/use-shared-value (if selected? 37 25))] size (reanimated/use-shared-value (if selected? 37 25))]
(rn/use-effect #(reanimated/animate size (if selected? 37 25)) [@current-zoom]) (rn/use-effect #(reanimated/animate size (if selected? 37 25)) [@current-zoom])
@ -20,13 +43,14 @@
{:on-press #(reset! current-zoom value) {:on-press #(reset! current-zoom value)
:style style/zoom-button-container :style style/zoom-button-container
:accessibility-label (str "zoom-" value)} :accessibility-label (str "zoom-" value)}
[reanimated/view {:style (style/zoom-button size)} [reanimated/view {:style (style/zoom-button size rotate)}
[quo/text [quo/text
{:size (if selected? :paragraph-2 :label) {:size (if selected? :paragraph-2 :label)
:weight :semi-bold :weight :semi-bold
:style {:color (if selected? :number-of-lines 1
colors/system-yellow :style {:color (if selected?
colors/white)}} colors/system-yellow
colors/white)}}
(str value (when selected? "x"))]]])) (str value (when selected? "x"))]]]))
(defn zoom-button (defn zoom-button
@ -43,59 +67,108 @@
(camera-kit/capture @camera-ref #(reset! uri %))) (camera-kit/capture @camera-ref #(reset! uri %)))
:style style/inner-circle}]]) :style style/inner-circle}]])
(defn zoom-buttons
[]
(let [current-zoom (reagent/atom 1)]
(fn [top insets rotate]
[rn/view {:style (style/zoom-container top insets)}
[zoom-button {:value 0.5 :current-zoom current-zoom :rotate rotate}]
[zoom-button {:value 1 :current-zoom current-zoom :rotate rotate}]
[zoom-button {:value 2 :current-zoom current-zoom :rotate rotate}]
[zoom-button {:value 3 :current-zoom current-zoom :rotate rotate}]])))
(defn- f-bottom-area
[{:keys [top insets uri camera-ref rotate]} back flip-camera]
[rn/view {:style (style/bottom-area top insets @uri)}
[quo/text {:style style/photo-text} (i18n/label :t/photo-caps)]
[rn/view {:style style/actions-container}
[quo/text
{:on-press back
:style {:font-size 17
:color colors/white}
:accessibility-label :cancel}
(i18n/label :t/cancel)]
[snap-button camera-ref uri]
[reanimated/touchable-opacity
{:style (reanimated/apply-animations-to-style {:transform [{:rotate rotate}]} {})
:on-press flip-camera}
[quo/icon :i/rotate-camera
{:size 48 :color colors/white :accessibility-label :flip-camera}]]]])
(defn bottom-area
[{:keys [flash camera-type] :as args}]
(let [back #(rf/dispatch [:navigate-back])
flip-camera (fn []
(reset! flash false)
(reset! camera-type (if (= @camera-type camera-kit/camera-type-back)
camera-kit/camera-type-front
camera-kit/camera-type-back)))]
[:f> f-bottom-area args back flip-camera]))
(defn- f-camera-screen
[{:keys [camera-ref uri camera-type current-orientation flash toggle-flash]}]
(let [window (rn/get-window)
{:keys [width height]} window
camera-window-height (* width 1.33)
insets (safe-area/get-insets)
top (/ (- height camera-window-height (:bottom insets)) 2)
top-landscape (/ (- height (* width 0.75) (:bottom insets)) 2)
portrait? (= @current-orientation orientation/portrait)
rotate (reanimated/use-shared-value "0deg")
retake #(retake flash uri)
use-photo (fn []
(rf/dispatch [:photo-selector/camera-roll-pick {:uri @uri}])
(rf/dispatch [:navigate-back]))]
(handle-orientation current-orientation rotate)
[rn/view {:style style/screen-container}
[reanimated/touchable-opacity
{:active-opacity 1
:on-press toggle-flash
:style (style/flash-container rotate @uri)}
(when-not @flash
[rn/view {:style style/cancel-dash}])
[quo/icon :i/flash-camera
{:color colors/white
:size 24}]]
(if @uri
[fast-image/fast-image
{:style (style/image width camera-window-height (if portrait? top top-landscape) portrait?)
:source {:uri @uri}}]
[camera-kit/camera
{:ref #(reset! camera-ref %)
:style (style/camera-window width camera-window-height top)
:flash-mode (if @flash :on :off)
:camera-type @camera-type}])
(when-not @uri
[zoom-buttons top insets rotate])
[rn/view {:style (style/confirmation-container insets @uri)}
[quo/text
{:on-press retake
:style {:font-size 17
:color colors/white}}
(i18n/label :t/retake)]
[quo/text
{:on-press use-photo
:style {:font-size 17
:color colors/white}}
(i18n/label :t/use-photo)]]
[bottom-area
{:top top
:insets insets
:uri uri
:camera-type camera-type
:camera-ref camera-ref
:flash flash
:rotate rotate}]]))
(defn camera-screen (defn camera-screen
[] []
(let [camera-ref (atom nil) (let [flash (reagent/atom false)
uri (reagent/atom nil) args {:camera-ref (atom nil)
current-zoom (reagent/atom "1")] :uri (reagent/atom nil)
(fn [] :camera-type (reagent/atom camera-kit/camera-type-back)
(let [window (rn/get-window) :current-orientation (atom orientation/portrait)
{:keys [width height]} window :flash flash
camera-window-height (* width 1.33) :toggle-flash #(swap! flash not)}]
insets (safe-area/get-insets) [:f> f-camera-screen args]))
top (/ (- height camera-window-height (:bottom insets)) 2)]
[rn/view {:style style/screen-container}
(when-not @uri
[rn/view {:style style/flash-container}
[quo/icon :i/flash-camera
{:color colors/white
:size 24}]])
(if @uri
[rn/image
{:style (style/camera-window width camera-window-height top)
:source {:uri @uri}}]
[camera-kit/camera
{:ref #(reset! camera-ref %)
:style (style/camera-window width camera-window-height top)}])
(when-not @uri
[rn/view {:style (style/zoom-container top insets)}
[zoom-button {:value "0.5" :current-zoom current-zoom}]
[zoom-button {:value "1" :current-zoom current-zoom}]
[zoom-button {:value "2" :current-zoom current-zoom}]
[zoom-button {:value "3" :current-zoom current-zoom}]])
(if @uri
[rn/view {:style (style/confirmation-container insets)}
[quo/text
{:on-press #(reset! uri nil)
:style {:font-size 17
:color colors/white}}
(i18n/label :t/retake)]
[quo/text
{:on-press (fn []
(rf/dispatch [:photo-selector/camera-roll-pick {:uri @uri}])
(rf/dispatch [:navigate-back]))
:style {:font-size 17
:color colors/white}}
(i18n/label :t/use-photo)]]
[rn/view {:style (style/bottom-area top insets)}
[quo/text {:style style/photo-text} (i18n/label :t/PHOTO)]
[rn/view {:style style/actions-container}
[quo/text
{:on-press #(rf/dispatch [:navigate-back])
:style {:font-size 17
:color colors/white}
:accessibility-label :cancel}
(i18n/label :t/cancel)]
[snap-button camera-ref uri]
[quo/icon :i/rotate-camera
{:size 48 :color colors/white :accessibility-label :flip-camera}]]])]))))

View File

@ -2264,5 +2264,5 @@
"community-unmuted": "Community unmuted", "community-unmuted": "Community unmuted",
"retake": "Retake", "retake": "Retake",
"use-photo": "Use Photo", "use-photo": "Use Photo",
"PHOTO": "PHOTO" "photo-caps": "PHOTO"
} }