From e33c8779894b833da97567272d45e6652df132d7 Mon Sep 17 00:00:00 2001 From: Omar Basem Date: Mon, 24 Jul 2023 16:46:43 +0400 Subject: [PATCH] feat: camera screen (1/2) (#16569) * feat: camera screen (1/2) --- .env | 1 - .env.e2e | 1 - .env.jenkins | 1 - .env.nightly | 1 - .../images/icons2/24x24/flash-camera@2x.png | Bin 0 -> 1196 bytes .../images/icons2/24x24/flash-camera@3x.png | Bin 0 -> 1912 bytes .../images/icons2/48x48/rotate-camera@2x.png | Bin 0 -> 2126 bytes .../images/icons2/48x48/rotate-camera@3x.png | Bin 0 -> 3104 bytes src/quo2/components/icons/icons.clj | 3 +- src/quo2/foundations/colors.cljs | 4 + src/react_native/camera_kit.cljs | 10 +- src/status_im/chat/models/images.cljs | 6 +- src/status_im2/common/device_permissions.cljs | 18 ++++ src/status_im2/config.cljs | 1 - .../contexts/chat/camera/style.cljs | 97 +++++++++++++++++ src/status_im2/contexts/chat/camera/view.cljs | 101 ++++++++++++++++++ .../contexts/chat/composer/actions/view.cljs | 32 ++++-- .../contexts/chat/photo_selector/events.cljs | 4 +- .../contexts/syncing/scan_sync_code/view.cljs | 17 +-- src/status_im2/navigation/options.cljs | 5 +- src/status_im2/navigation/screens.cljs | 5 + translations/en.json | 5 +- 22 files changed, 277 insertions(+), 35 deletions(-) create mode 100644 resources/images/icons2/24x24/flash-camera@2x.png create mode 100644 resources/images/icons2/24x24/flash-camera@3x.png create mode 100644 resources/images/icons2/48x48/rotate-camera@2x.png create mode 100644 resources/images/icons2/48x48/rotate-camera@3x.png create mode 100644 src/status_im2/common/device_permissions.cljs create mode 100644 src/status_im2/contexts/chat/camera/style.cljs create mode 100644 src/status_im2/contexts/chat/camera/view.cljs diff --git a/.env b/.env index 53c6aeaf6f..5b8f7d0b8d 100644 --- a/.env +++ b/.env @@ -22,7 +22,6 @@ KEYCARD_TEST_MENU=0 QR_READ_TEST_MENU=1 ENABLE_ROOT_ALERT=1 ENABLE_QUO_PREVIEW=1 -MAX_IMAGES_BATCH=5 APN_TOPIC=im.status.ethereum.pr COMMUNITIES_ENABLED=1 DATABASE_MANAGEMENT_ENABLED=1 diff --git a/.env.e2e b/.env.e2e index 6a0fa064dd..fb3b958e39 100644 --- a/.env.e2e +++ b/.env.e2e @@ -21,7 +21,6 @@ COMMANDS_ENABLED=1 KEYCARD_TEST_MENU=1 QR_READ_TEST_MENU=1 ENABLE_ROOT_ALERT=0 -MAX_IMAGES_BATCH=5 APN_TOPIC=im.status.ethereum.pr VERIFY_TRANSACTION_CHAIN_ID=5 VERIFY_ENS_CHAIN_ID=5 diff --git a/.env.jenkins b/.env.jenkins index ec06cda656..37663ce1e8 100644 --- a/.env.jenkins +++ b/.env.jenkins @@ -26,7 +26,6 @@ VERIFY_TRANSACTION_CHAIN_ID=5 VERIFY_ENS_CHAIN_ID=5 TEST_STATEOFUS=1 BLANK_PREVIEW=0 -MAX_IMAGES_BATCH=5 DATABASE_MANAGEMENT_ENABLED=1 COMMUNITIES_ENABLED=1 COMMUNITIES_MANAGEMENT_ENABLED=1 diff --git a/.env.nightly b/.env.nightly index a81b1fa797..15e3adcb35 100644 --- a/.env.nightly +++ b/.env.nightly @@ -17,7 +17,6 @@ RPC_NETWORKS_ONLY=0 PARTITIONED_TOPIC=0 CONTRACT_NODES=1 ENABLE_ROOT_ALERT=1 -MAX_IMAGES_BATCH=5 BLANK_PREVIEW=0 COMMUNITIES_ENABLED=1 DATABASE_MANAGEMENT_ENABLED=1 diff --git a/resources/images/icons2/24x24/flash-camera@2x.png b/resources/images/icons2/24x24/flash-camera@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c5c139b46ad6d1e1e6ee980044d292327148095a GIT binary patch literal 1196 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 (.capture camera-ref) + (.then #(on-success (oops/oget % :uri))) + (.catch #(log/warn "couldn't capture photo" {:error %})))) diff --git a/src/status_im/chat/models/images.cljs b/src/status_im/chat/models/images.cljs index ec9e45ed90..31a5161de5 100644 --- a/src/status_im/chat/models/images.cljs +++ b/src/status_im/chat/models/images.cljs @@ -4,8 +4,8 @@ [react-native.share :as share] [react-native.cameraroll :as cameraroll] [status-im.ui.components.react :as react] - [status-im2.config :as config] [react-native.fs :as fs] + [status-im2.constants :as constants] [utils.re-frame :as rf] [status-im.utils.platform :as platform] [taoensso.timbre :as log])) @@ -48,7 +48,7 @@ [{:keys [db]} chat-id uri] (let [current-chat-id (or chat-id (:current-chat-id db)) images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])] - (when (and (< (count images) config/max-images-batch) + (when (and (< (count images) constants/max-album-photos) (not (get images uri))) {::image-selected [uri current-chat-id]}))) @@ -68,5 +68,5 @@ [{:keys [db]} chat-id] (let [current-chat-id (or chat-id (:current-chat-id db)) images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])] - (when (< (count images) config/max-images-batch) + (when (< (count images) constants/max-album-photos) {::chat-open-image-picker-camera current-chat-id}))) diff --git a/src/status_im2/common/device_permissions.cljs b/src/status_im2/common/device_permissions.cljs new file mode 100644 index 0000000000..0df5c80b5c --- /dev/null +++ b/src/status_im2/common/device_permissions.cljs @@ -0,0 +1,18 @@ +(ns status-im2.common.device-permissions + (:require + [quo2.foundations.colors :as colors] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn camera + [on-allowed] + (rf/dispatch + [:request-permissions + {:permissions [:camera] + :on-allowed on-allowed + :on-denied #(rf/dispatch + [:toasts/upsert + {:icon :i/info + :icon-color colors/danger-50 + :override-theme :light + :text (i18n/label :t/camera-permission-denied)}])}])) diff --git a/src/status_im2/config.cljs b/src/status_im2/config.cljs index 2674e4ea64..e54787279e 100644 --- a/src/status_im2/config.cljs +++ b/src/status_im2/config.cljs @@ -26,7 +26,6 @@ (def snoopy-enabled? (enabled? (get-config :SNOOPY 0))) (def dev-build? (enabled? (get-config :DEV_BUILD 0))) (def max-message-delivery-attempts (js/parseInt (get-config :MAX_MESSAGE_DELIVERY_ATTEMPTS "6"))) -(def max-images-batch (js/parseInt (get-config :MAX_IMAGES_BATCH "1"))) ;; NOTE: only disabled in releases (def local-notifications? (enabled? (get-config :LOCAL_NOTIFICATIONS "1"))) (def blank-preview? (enabled? (get-config :BLANK_PREVIEW "1"))) diff --git a/src/status_im2/contexts/chat/camera/style.cljs b/src/status_im2/contexts/chat/camera/style.cljs new file mode 100644 index 0000000000..4e340a0209 --- /dev/null +++ b/src/status_im2/contexts/chat/camera/style.cljs @@ -0,0 +1,97 @@ +(ns status-im2.contexts.chat.camera.style + (:require [quo2.foundations.colors :as colors] + [react-native.platform :as platform] + [react-native.reanimated :as reanimated])) + +(def screen-container + {:flex 1 + :background-color colors/black}) + +(def flash-container + {:position :absolute + :top 50 + :left 25}) + +(defn camera-window + [width height top] + {:width width + :height height + :top top}) + +(def zoom-button-container + {:width 37 + :height 37 + :justify-content :center + :align-items :center}) + +(defn zoom-container + [top insets] + {:width 157 + :height 43 + :border-radius 100 + :position :absolute + :background-color colors/black-opa-60 + :align-self :center + :justify-content :space-around + :align-items :center + :flex-direction :row + :bottom (+ top (:bottom insets) (when platform/android? (:top insets)) 18)}) + +(defn zoom-button + [size] + (reanimated/apply-animations-to-style + {:width size + :height size} + {:background-color colors/black-opa-30 + :justify-content :center + :align-items :center + :border-radius 50})) + +(defn bottom-area + [top insets] + {:left 20 + :right 20 + :position :absolute + :height (+ top (when platform/android? (:top insets))) + :bottom (:bottom insets)}) + +(def photo-text + {:color colors/system-yellow + :margin-top 18 + :font-size 14 + :align-self :center}) + +(def actions-container + {:flex-direction :row + :margin-top 20 + :align-items :center + :justify-content :space-between}) + +(def outer-circle + {:width 69 + :height 69 + :background-color colors/black + :border-radius 69 + :border-width 6 + :border-color colors/white + :justify-content :center + :align-items :center}) + +(def inner-circle + {:width 53 + :height 53 + :border-radius 53 + :background-color colors/white}) + +(defn confirmation-container + [insets] + {:position :absolute + :bottom 0 + :left 0 + :right 0 + :background-color "#131313" + :height (+ 69 (:bottom insets)) + :flex-direction :row + :padding-horizontal 20 + :justify-content :space-between + :padding-top 18}) diff --git a/src/status_im2/contexts/chat/camera/view.cljs b/src/status_im2/contexts/chat/camera/view.cljs new file mode 100644 index 0000000000..68f1558db3 --- /dev/null +++ b/src/status_im2/contexts/chat/camera/view.cljs @@ -0,0 +1,101 @@ +(ns status-im2.contexts.chat.camera.view + (:require + [quo2.core :as quo] + [quo2.foundations.colors :as colors] + [react-native.camera-kit :as camera-kit] + [react-native.core :as rn] + [react-native.reanimated :as reanimated] + [react-native.safe-area :as safe-area] + [reagent.core :as reagent] + [utils.i18n :as i18n] + [status-im2.contexts.chat.camera.style :as style] + [utils.re-frame :as rf])) + +(defn- f-zoom-button + [{:keys [value current-zoom]}] + (let [selected? (= @current-zoom value) + size (reanimated/use-shared-value (if selected? 37 25))] + (rn/use-effect #(reanimated/animate size (if selected? 37 25)) [@current-zoom]) + [rn/touchable-opacity + {:on-press #(reset! current-zoom value) + :style style/zoom-button-container + :accessibility-label (str "zoom-" value)} + [reanimated/view {:style (style/zoom-button size)} + [quo/text + {:size (if selected? :paragraph-2 :label) + :weight :semi-bold + :style {:color (if selected? + colors/system-yellow + colors/white)}} + (str value (when selected? "x"))]]])) + +(defn zoom-button + [args] + [:f> f-zoom-button args]) + +(defn snap-button + [camera-ref uri] + [rn/view + {:style style/outer-circle + :accessibility-label :snap} + [rn/touchable-opacity + {:on-press (fn [] + (camera-kit/capture @camera-ref #(reset! uri %))) + :style style/inner-circle}]]) + +(defn camera-screen + [] + (let [camera-ref (atom nil) + uri (reagent/atom nil) + current-zoom (reagent/atom "1")] + (fn [] + (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)] + [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}]]])])))) diff --git a/src/status_im2/contexts/chat/composer/actions/view.cljs b/src/status_im2/contexts/chat/composer/actions/view.cljs index d42f32333d..c1062437d2 100644 --- a/src/status_im2/contexts/chat/composer/actions/view.cljs +++ b/src/status_im2/contexts/chat/composer/actions/view.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.chat.composer.actions.view (:require [quo2.core :as quo] + [quo2.foundations.colors :as colors] [react-native.core :as rn] [react-native.permissions :as permissions] [react-native.platform :as platform] @@ -9,6 +10,7 @@ [status-im2.common.alert.events :as alert] [status-im2.contexts.chat.composer.constants :as comp-constants] [status-im2.contexts.chat.messages.list.view :as messages.list] + [status-im2.common.device-permissions :as device-permissions] [utils.i18n :as i18n] [utils.re-frame :as rf] [status-im2.contexts.chat.composer.actions.style :as style] @@ -148,16 +150,32 @@ 50)}])) :max-duration-ms constants/audio-max-duration-ms}]])) +(defn images-limit-toast + [] + (rf/dispatch [:toasts/upsert + {:id :random-id + :icon :info + :icon-color colors/danger-50-opa-40 + :container-style {:top (when platform/ios? 20)} + :text (i18n/label :t/only-6-images)}])) + + +(defn go-to-camera + [images-count] + (device-permissions/camera #(if (>= images-count constants/max-album-photos) + (images-limit-toast) + (rf/dispatch [:navigate-to :camera-screen])))) (defn camera-button [] - [quo/button - {:on-press #(js/alert "to be implemented") - :icon true - :type :outline - :size 32 - :style {:margin-right 12}} - :i/camera]) + (let [images-count (count (vals (rf/sub [:chats/sending-image])))] + [quo/button + {:on-press #(go-to-camera images-count) + :icon true + :type :outline + :size 32 + :style {:margin-right 12}} + :i/camera])) (defn open-photo-selector [{:keys [input-ref]} diff --git a/src/status_im2/contexts/chat/photo_selector/events.cljs b/src/status_im2/contexts/chat/photo_selector/events.cljs index 320f181e70..b6cb8b2367 100644 --- a/src/status_im2/contexts/chat/photo_selector/events.cljs +++ b/src/status_im2/contexts/chat/photo_selector/events.cljs @@ -2,9 +2,9 @@ (:require [react-native.cameraroll :as cameraroll] [clojure.string :as string] [re-frame.core :as re-frame] + [status-im2.constants :as constants] [utils.i18n :as i18n] [react-native.permissions :as permissions] - [status-im2.config :as config] [utils.re-frame :as rf] [status-im.utils.image-processing :as image-processing] [taoensso.timbre :as log] @@ -141,6 +141,6 @@ [{:keys [db]} image chat-id] (let [current-chat-id (or chat-id (:current-chat-id db)) images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])] - (when (and (< (count images) config/max-images-batch) + (when (and (< (count images) constants/max-album-photos) (not (some #(= (:uri image) (:uri %)) images))) {:camera-roll-image-selected [image current-chat-id]}))) diff --git a/src/status_im2/contexts/syncing/scan_sync_code/view.cljs b/src/status_im2/contexts/syncing/scan_sync_code/view.cljs index 85d54ca6a4..69b3683ba7 100644 --- a/src/status_im2/contexts/syncing/scan_sync_code/view.cljs +++ b/src/status_im2/contexts/syncing/scan_sync_code/view.cljs @@ -12,6 +12,7 @@ [react-native.reanimated :as reanimated] [react-native.safe-area :as safe-area] [reagent.core :as reagent] + [status-im2.common.device-permissions :as device-permissions] [status-im2.constants :as constants] [status-im2.contexts.syncing.scan-sync-code.style :as style] [status-im2.contexts.syncing.utils :as sync-utils] @@ -27,19 +28,6 @@ (defonce dismiss-animations (atom nil)) (defonce navigate-back-fn (atom nil)) -(defn request-camera-permission - [] - (rf/dispatch - [:request-permissions - {:permissions [:camera] - :on-allowed #(reset! camera-permission-granted? true) - :on-denied #(rf/dispatch - [:toasts/upsert - {:icon :i/info - :icon-color colors/danger-50 - :override-theme :light - :text (i18n/label :t/camera-permission-denied)}])}])) - (defn perform-preflight-check "Performing the check for the first time will trigger local network access permission in iOS. @@ -140,7 +128,8 @@ :button-icon :i/camera :button-label :t/enable-camera :accessibility-label :request-camera-permission - :on-press request-camera-permission})) + :on-press (fn [] + (device-permissions/camera #(reset! camera-permission-granted? true)))})) (defn- camera-and-local-network-access-permission-view [] diff --git a/src/status_im2/navigation/options.cljs b/src/status_im2/navigation/options.cljs index e176dcaa29..07a0419ac5 100644 --- a/src/status_im2/navigation/options.cljs +++ b/src/status_im2/navigation/options.cljs @@ -114,7 +114,7 @@ :animate true :drawBehind true :translucent true} - :navigationBar {:backgroundColor colors/black} + :navigationBar {:backgroundColor colors/neutral-100} :layout {:componentBackgroundColor :transparent :backgroundColor :transparent ;; issue: https://github.com/wix/react-native-navigation/issues/7726 @@ -129,6 +129,9 @@ :decelerate :factor 1.5}}]}}}) +(def camera-screen + {:navigationBar {:backgroundColor colors/black}}) + (defn merge-top-bar [root-options options] (let [options (:topBar options)] diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index 942ed1a9cb..c0d2ad1be1 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -6,6 +6,7 @@ [status-im2.contexts.chat.lightbox.view :as lightbox] [status-im2.contexts.chat.messages.view :as chat] [status-im2.contexts.chat.photo-selector.view :as photo-selector] + [status-im2.contexts.chat.camera.view :as camera-screen] [status-im2.contexts.communities.discover.view :as communities.discover] [status-im2.contexts.communities.overview.view :as communities.overview] [status-im2.contexts.onboarding.intro.view :as intro] @@ -107,6 +108,10 @@ :options {:sheet? true} :component photo-selector/photo-selector} + {:name :camera-screen + :options options/camera-screen + :component camera-screen/camera-screen} + {:name :new-contact :options {:sheet? true} :component add-new-contact/new-contact} diff --git a/translations/en.json b/translations/en.json index 9869aff834..9fca77bf26 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2245,5 +2245,8 @@ "chat-unmuted-successfully": "Chat unmuted successfully! ", "channel-unmuted-successfully": "Channel unmuted successfully! ", "photo-saved": "Photo saved to your device", - "community-unmuted": "Community unmuted" + "community-unmuted": "Community unmuted", + "retake": "Retake", + "use-photo": "Use Photo", + "PHOTO": "PHOTO" }