Add pinch to zoom deps

Add image interactions

Add image preview to timeline

Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
This commit is contained in:
Gheorghe Pinzaru 2020-10-21 14:28:24 +03:00
parent fbb606b859
commit 13c81a34b3
No known key found for this signature in database
GPG Key ID: C9A094959935A952
8 changed files with 152 additions and 100 deletions

View File

@ -47,6 +47,7 @@
"react-native-haptic-feedback": "^1.9.0", "react-native-haptic-feedback": "^1.9.0",
"react-native-image-crop-picker": "^0.31.1", "react-native-image-crop-picker": "^0.31.1",
"react-native-image-resizer": "^1.2.3", "react-native-image-resizer": "^1.2.3",
"react-native-image-viewing": "git+https://github.com/Ferossgp/react-native-image-viewing.git#v0.2.1",
"react-native-keychain": "git+https://github.com/status-im/react-native-keychain.git#v.3.0.0-5-status", "react-native-keychain": "git+https://github.com/status-im/react-native-keychain.git#v.3.0.0-5-status",
"react-native-languages": "^3.0.2", "react-native-languages": "^3.0.2",
"react-native-linear-gradient": "^2.5.6", "react-native-linear-gradient": "^2.5.6",

View File

@ -121,7 +121,7 @@
{:font-scale (.-fontScale window) {:font-scale (.-fontScale window)
:height (.-height ^js window) :height (.-height ^js window)
:scale (.-scale ^js window) :scale (.-scale ^js window)
:width (.-window ^js window)})) :width (.-width ^js window)}))
(def use-back-handler (.-useBackHandler hooks)) (def use-back-handler (.-useBackHandler hooks))

View File

@ -1,39 +1,79 @@
(ns status-im.ui.screens.chat.image.preview.views (ns status-im.ui.screens.chat.image.preview.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [status-im.ui.components.colors :as colors] (:require [status-im.ui.components.colors :as colors]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[reagent.core :as reagent]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[quo.core :as quo] [quo.core :as quo]
[quo.platform :as platform]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.components.icons.vector-icons :as icons] [status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.screens.chat.sheets :as sheets] [status-im.ui.screens.chat.sheets :as sheets]
[quo.components.safe-area :as safe-area])) [quo.components.safe-area :as safe-area]
["react-native-image-viewing" :default image-viewing]))
(defview preview-image [] (defn footer-options []
(letsubs [{:keys [content] :as message} [:get-screen-params] (let [show-sheet (reagent/atom false)]
{:keys [width height]} [:dimensions/window]] (fn [{:keys [message on-close]}]
;; FIXME(Ferossgp): Bottom sheet doesn't work on Android because of https://github.com/software-mansion/react-native-gesture-handler/issues/139
(if platform/android?
[:<>
[react/touchable-opacity
{:on-press (fn []
(on-close)
(re-frame/dispatch [:chat.ui/save-image-to-gallery (get-in message [:content :image])]))
:style {:background-color colors/black-transparent-86
:border-radius 44
:padding 8
:position :absolute
:bottom 0
:right 0}}
[icons/icon :main-icons/download {:container-style {:width 24
:height 24}
:color colors/white-persist}]]]
[:<>
[react/touchable-opacity
{:on-press #(reset! show-sheet true)
:style {:background-color colors/black-transparent-86
:border-radius 44
:padding 8
:position :absolute
:bottom 0
:right 0}}
[icons/icon :main-icons/more {:container-style {:width 24
:height 24}
:color colors/white-persist}]]
;; NOTE(Ferossgp): If we use global bottom sheet, then it is rendered under the preview
[quo/bottom-sheet {:visible? @show-sheet
:on-cancel #(reset! show-sheet false)}
[sheets/image-long-press message #(do (reset! show-sheet false)
(on-close))]]]))))
(defn footer [{:keys [on-close] :as props}]
[safe-area/consumer [safe-area/consumer
(fn [insets] (fn [insets]
[react/view {:style {:flex 1 :justify-content :flex-end [react/view {:style {:padding-horizontal 24
:padding-top (:top insets) :padding-bottom (:bottom insets) :padding-bottom (+ (:bottom insets) 8)}}
:background-color colors/black-persist}} [react/view {:style {:justify-content :center
[react/view {:flex 1 :align-items :center :justify-content :center} :align-items :center}}
[react/image {:style (merge {:width width [react/touchable-opacity {:on-press on-close
:height (- height 200) :style {:background-color colors/black-transparent-86
:background-color :black}) :padding-horizontal 24
:resize-mode :contain :padding-vertical 11
:source {:uri (:image content)}}]] :border-radius 44}}
[react/view {:flex-direction :row :padding-horizontal 8 [quo/text {:style {:color colors/white-persist}}
:justify-content :space-between :align-items :center} (i18n/label :t/close)]]
[react/view {:width 64}] [footer-options props]]])])
[quo/button {:on-press #(re-frame/dispatch [:navigate-back])
:type :secondary (defn preview-image [{{:keys [content] :as message} :message
:text-style {:color colors/white-persist}} visible :visible
(i18n/label :t/close)] on-close :on-close}]
[react/touchable-highlight [:> image-viewing {:images #js [#js {:uri (:image content)}]
{:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet :on-request-close on-close
{:content (sheets/image-long-press message true) :hide-header-on-zoom false
:height 64}])} :hide-footer-on-zoom false
[icons/icon :main-icons/more {:container-style {:width 24 :height 24 :swipe-to-close-enabled platform/ios?
:margin 20} :presentation-style "overFullScreen"
:color colors/white-persist}]]]])])) :HeaderComponent #(reagent/as-element [:<>]) ; NOTE: Keep it to remove default header
:FooterComponent #(reagent/as-element [footer {:on-close on-close
:message message}])
:visible visible}])

View File

@ -15,6 +15,7 @@
[status-im.utils.contenthash :as contenthash] [status-im.utils.contenthash :as contenthash]
[status-im.utils.security :as security] [status-im.utils.security :as security]
[status-im.ui.screens.chat.message.reactions :as reactions] [status-im.ui.screens.chat.message.reactions :as reactions]
[status-im.ui.screens.chat.image.preview.views :as preview]
[quo.core :as quo] [quo.core :as quo]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.ui.screens.chat.components.reply :as components.reply] [status-im.ui.screens.chat.components.reply :as components.reply]
@ -226,6 +227,7 @@
(defn message-content-image [{:keys [content outgoing] :as message} {:keys [on-long-press]}] (defn message-content-image [{:keys [content outgoing] :as message} {:keys [on-long-press]}]
(let [dimensions (reagent/atom [260 260]) (let [dimensions (reagent/atom [260 260])
visible (reagent/atom false)
uri (:image content)] uri (:image content)]
(react/image-get-size (react/image-get-size
uri uri
@ -236,9 +238,13 @@
style-opts {:outgoing outgoing style-opts {:outgoing outgoing
:width (/ (first @dimensions) k) :width (/ (first @dimensions) k)
:height (/ (second @dimensions) k)}] :height (/ (second @dimensions) k)}]
[:<>
[preview/preview-image {:message message
:visible @visible
:on-close #(do (reset! visible false)
(reagent/flush))}]
[react/touchable-highlight {:on-press (fn [] [react/touchable-highlight {:on-press (fn []
(when (:image content) (reset! visible true)
(re-frame/dispatch [:navigate-to :image-preview message]))
(react/dismiss-keyboard!)) (react/dismiss-keyboard!))
:on-long-press on-long-press} :on-long-press on-long-press}
[react/view {:style (style/image-message style-opts)} [react/view {:style (style/image-message style-opts)}
@ -246,7 +252,7 @@
:height (/ (second @dimensions) k)} :height (/ (second @dimensions) k)}
:resize-mode :contain :resize-mode :contain
:source {:uri uri}}] :source {:uri uri}}]
[react/view {:style (style/image-message-border style-opts)}]]])))) [react/view {:style (style/image-message-border style-opts)}]]]]))))
(defmulti ->message :content-type) (defmulti ->message :content-type)

View File

@ -141,8 +141,7 @@
:accessibility-label :delete-transaccent-button :accessibility-label :delete-transaccent-button
:on-press #(hide-sheet-and-dispatch [:chat.ui/delete-message chat-id message-id])}]])) :on-press #(hide-sheet-and-dispatch [:chat.ui/delete-message chat-id message-id])}]]))
(defn image-long-press [{:keys [content identicon from outgoing cant-be-replied] :as message} from-preview?] (defn image-long-press [{:keys [content identicon from outgoing cant-be-replied] :as message} hide]
(fn []
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])] (let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
[react/view [react/view
(when-not outgoing (when-not outgoing
@ -156,18 +155,16 @@
:accessibility-label :view-chat-details-button :accessibility-label :view-chat-details-button
:chevron true :chevron true
:on-press #(do :on-press #(do
(when from-preview? (hide)
(re-frame/dispatch [:navigate-back])) (re-frame/dispatch [:chat.ui/show-profile from]))}])
(hide-sheet-and-dispatch [:chat.ui/show-profile from]))}])
(when-not cant-be-replied (when-not cant-be-replied
[quo/list-item [quo/list-item
{:theme :accent {:theme :accent
:title (i18n/label :t/message-reply) :title (i18n/label :t/message-reply)
:icon :main-icons/reply :icon :main-icons/reply
:on-press #(do :on-press #(do
(when from-preview? (hide)
(re-frame/dispatch [:navigate-back])) (re-frame/dispatch [:chat.ui/reply-to-message message]))}])
(hide-sheet-and-dispatch [:chat.ui/reply-to-message message]))}])
;; we have only base64 string for image, so we need to find a way how to copy it ;; we have only base64 string for image, so we need to find a way how to copy it
#_[quo/list-item #_[quo/list-item
{:theme :accent {:theme :accent
@ -181,7 +178,8 @@
:title (i18n/label :t/save) :title (i18n/label :t/save)
:icon :main-icons/download :icon :main-icons/download
:on-press (fn [] :on-press (fn []
(hide-sheet-and-dispatch [:chat.ui/save-image-to-gallery (:image content)]))}] (hide)
(re-frame/dispatch [:chat.ui/save-image-to-gallery (:image content)]))}]
;; we have only base64 string for image, so we need to find a way how to share it ;; we have only base64 string for image, so we need to find a way how to share it
#_[quo/list-item #_[quo/list-item
{:theme :accent {:theme :accent
@ -189,4 +187,4 @@
:icon :main-icons/share :icon :main-icons/share
:on-press (fn [] :on-press (fn []
(re-frame/dispatch [:bottom-sheet/hide]) (re-frame/dispatch [:bottom-sheet/hide])
(list-selection/open-share {:message (:image content)}))}]]))) (list-selection/open-share {:message (:image content)}))}]]))

View File

@ -21,7 +21,6 @@
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[quo.previews.main :as quo.preview] [quo.previews.main :as quo.preview]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.ui.screens.chat.image.preview.views :as image-preview]
[status-im.ui.screens.profile.contact.views :as contact] [status-im.ui.screens.profile.contact.views :as contact]
[status-im.ui.screens.notifications-settings.views :as notifications-settings] [status-im.ui.screens.notifications-settings.views :as notifications-settings]
[status-im.ui.screens.wallet.send.views :as wallet] [status-im.ui.screens.wallet.send.views :as wallet]
@ -122,9 +121,6 @@
{:name :qr-scanner {:name :qr-scanner
:insets {:top false :bottom false} :insets {:top false :bottom false}
:component qr-scanner/qr-scanner} :component qr-scanner/qr-scanner}
{:name :image-preview
:insets {:top false :bottom false}
:component image-preview/preview-image}
{:name :notifications-settings {:name :notifications-settings
:back-handler :noop :back-handler :noop
:insets {:bottom true} :insets {:bottom true}

View File

@ -13,6 +13,7 @@
[status-im.ui.screens.status.styles :as styles] [status-im.ui.screens.status.styles :as styles]
[status-im.ui.screens.chat.views :as chat.views] [status-im.ui.screens.chat.views :as chat.views]
[status-im.ui.components.plus-button :as components.plus-button] [status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.screens.chat.image.preview.views :as preview]
[status-im.ui.screens.chat.photos :as photos] [status-im.ui.screens.chat.photos :as photos]
[status-im.ui.components.tabs :as tabs] [status-im.ui.components.tabs :as tabs]
[status-im.utils.contenthash :as contenthash] [status-im.utils.contenthash :as contenthash]
@ -53,13 +54,19 @@
:justify-content :center} :justify-content :center}
[icons/icon :main-icons/close-circle {:color colors/white-persist}]]])]))) [icons/icon :main-icons/close-circle {:color colors/white-persist}]]])])))
(defn image-message [{:keys [content] :as message}] (defn image-message []
(let [visible (reagent/atom false)]
(fn [{:keys [content] :as message}]
[:<>
[preview/preview-image {:message (assoc message :cant-be-replied true)
:visible @visible
:can-reply false
:on-close #(do (reset! visible false)
(reagent/flush))}]
[react/touchable-highlight {:on-press (fn [_] [react/touchable-highlight {:on-press (fn [_]
(when (:image content) (reset! visible true)
(re-frame/dispatch [:navigate-to :image-preview
(assoc message :cant-be-replied true)]))
(react/dismiss-keyboard!))} (react/dismiss-keyboard!))}
[message-content-image (:image content) false]]) [message-content-image (:image content) false]]])))
(defn message-item [{:keys [content-type content from last-in-group? timestamp identicon outgoing] :as message} timeline? account] (defn message-item [{:keys [content-type content from last-in-group? timestamp identicon outgoing] :as message} timeline? account]
[react/view (when last-in-group? [react/view (when last-in-group?

View File

@ -6613,6 +6613,10 @@ react-native-image-resizer@^1.2.3:
resolved "https://registry.yarnpkg.com/react-native-image-resizer/-/react-native-image-resizer-1.2.3.tgz#21cb2b158ff950e55a0fc01c2cb61375bd5a03ba" resolved "https://registry.yarnpkg.com/react-native-image-resizer/-/react-native-image-resizer-1.2.3.tgz#21cb2b158ff950e55a0fc01c2cb61375bd5a03ba"
integrity sha512-RDPNJglRmWDZ/7hvu+CbpsKYl6AQmseL8cWX4UkLAHxQWNc5ZdYhP/9avC5xCfyiwkRw+Zmkmv78HO0kt0ewhQ== integrity sha512-RDPNJglRmWDZ/7hvu+CbpsKYl6AQmseL8cWX4UkLAHxQWNc5ZdYhP/9avC5xCfyiwkRw+Zmkmv78HO0kt0ewhQ==
"react-native-image-viewing@git+https://github.com/Ferossgp/react-native-image-viewing.git#v0.2.1":
version "0.2.1"
resolved "git+https://github.com/Ferossgp/react-native-image-viewing.git#8ef67cdce7b7c66065a939847e45db71347c678e"
react-native-iphone-x-helper@^1.2.1: react-native-iphone-x-helper@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.2.1.tgz#645e2ffbbb49e80844bb4cbbe34a126fda1e6772" resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.2.1.tgz#645e2ffbbb49e80844bb4cbbe34a126fda1e6772"