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-image-crop-picker": "^0.31.1",
"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-languages": "^3.0.2",
"react-native-linear-gradient": "^2.5.6",

View File

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

View File

@ -1,39 +1,79 @@
(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]
[status-im.ui.components.react :as react]
[reagent.core :as reagent]
[re-frame.core :as re-frame]
[quo.core :as quo]
[quo.platform :as platform]
[status-im.i18n :as i18n]
[status-im.ui.components.icons.vector-icons :as icons]
[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 []
(letsubs [{:keys [content] :as message} [:get-screen-params]
{:keys [width height]} [:dimensions/window]]
[safe-area/consumer
(fn [insets]
[react/view {:style {:flex 1 :justify-content :flex-end
:padding-top (:top insets) :padding-bottom (:bottom insets)
:background-color colors/black-persist}}
[react/view {:flex 1 :align-items :center :justify-content :center}
[react/image {:style (merge {:width width
:height (- height 200)
:background-color :black})
:resize-mode :contain
:source {:uri (:image content)}}]]
[react/view {:flex-direction :row :padding-horizontal 8
:justify-content :space-between :align-items :center}
[react/view {:width 64}]
[quo/button {:on-press #(re-frame/dispatch [:navigate-back])
:type :secondary
:text-style {:color colors/white-persist}}
(i18n/label :t/close)]
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content (sheets/image-long-press message true)
:height 64}])}
[icons/icon :main-icons/more {:container-style {:width 24 :height 24
:margin 20}
:color colors/white-persist}]]]])]))
(defn footer-options []
(let [show-sheet (reagent/atom false)]
(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
(fn [insets]
[react/view {:style {:padding-horizontal 24
:padding-bottom (+ (:bottom insets) 8)}}
[react/view {:style {:justify-content :center
:align-items :center}}
[react/touchable-opacity {:on-press on-close
:style {:background-color colors/black-transparent-86
:padding-horizontal 24
:padding-vertical 11
:border-radius 44}}
[quo/text {:style {:color colors/white-persist}}
(i18n/label :t/close)]]
[footer-options props]]])])
(defn preview-image [{{:keys [content] :as message} :message
visible :visible
on-close :on-close}]
[:> image-viewing {:images #js [#js {:uri (:image content)}]
:on-request-close on-close
:hide-header-on-zoom false
:hide-footer-on-zoom false
:swipe-to-close-enabled platform/ios?
:presentation-style "overFullScreen"
: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.security :as security]
[status-im.ui.screens.chat.message.reactions :as reactions]
[status-im.ui.screens.chat.image.preview.views :as preview]
[quo.core :as quo]
[reagent.core :as reagent]
[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]}]
(let [dimensions (reagent/atom [260 260])
visible (reagent/atom false)
uri (:image content)]
(react/image-get-size
uri
@ -236,17 +238,21 @@
style-opts {:outgoing outgoing
:width (/ (first @dimensions) k)
:height (/ (second @dimensions) k)}]
[react/touchable-highlight {:on-press (fn []
(when (:image content)
(re-frame/dispatch [:navigate-to :image-preview message]))
(react/dismiss-keyboard!))
:on-long-press on-long-press}
[react/view {:style (style/image-message style-opts)}
[react/image {:style {:width (/ (first @dimensions) k)
:height (/ (second @dimensions) k)}
:resize-mode :contain
:source {:uri uri}}]
[react/view {:style (style/image-message-border style-opts)}]]]))))
[:<>
[preview/preview-image {:message message
:visible @visible
:on-close #(do (reset! visible false)
(reagent/flush))}]
[react/touchable-highlight {:on-press (fn []
(reset! visible true)
(react/dismiss-keyboard!))
:on-long-press on-long-press}
[react/view {:style (style/image-message style-opts)}
[react/image {:style {:width (/ (first @dimensions) k)
:height (/ (second @dimensions) k)}
:resize-mode :contain
:source {:uri uri}}]
[react/view {:style (style/image-message-border style-opts)}]]]]))))
(defmulti ->message :content-type)

View File

@ -141,52 +141,50 @@
:accessibility-label :delete-transaccent-button
: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?]
(fn []
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
[react/view
(when-not outgoing
[quo/list-item
{:theme :accent
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo {:identicon identicon
:public-key from})]
:title contact-name
:subtitle (i18n/label :t/view-profile)
:accessibility-label :view-chat-details-button
:chevron true
:on-press #(do
(when from-preview?
(re-frame/dispatch [:navigate-back]))
(hide-sheet-and-dispatch [:chat.ui/show-profile from]))}])
(when-not cant-be-replied
[quo/list-item
{:theme :accent
:title (i18n/label :t/message-reply)
:icon :main-icons/reply
:on-press #(do
(when from-preview?
(re-frame/dispatch [:navigate-back]))
(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
#_[quo/list-item
{:theme :accent
:title :t/sharing-copy-to-clipboard
:icon :main-icons/copy
:on-press (fn []
(re-frame/dispatch [:bottom-sheet/hide])
(react/copy-to-clipboard (:image content)))}]
(defn image-long-press [{:keys [content identicon from outgoing cant-be-replied] :as message} hide]
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
[react/view
(when-not outgoing
[quo/list-item
{:theme :accent
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo {:identicon identicon
:public-key from})]
:title contact-name
:subtitle (i18n/label :t/view-profile)
:accessibility-label :view-chat-details-button
:chevron true
:on-press #(do
(hide)
(re-frame/dispatch [:chat.ui/show-profile from]))}])
(when-not cant-be-replied
[quo/list-item
{:theme :accent
:title (i18n/label :t/save)
:icon :main-icons/download
:title (i18n/label :t/message-reply)
:icon :main-icons/reply
:on-press #(do
(hide)
(re-frame/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
#_[quo/list-item
{:theme :accent
:title :t/sharing-copy-to-clipboard
:icon :main-icons/copy
:on-press (fn []
(hide-sheet-and-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
#_[quo/list-item
{:theme :accent
:title :t/sharing-share
:icon :main-icons/share
:on-press (fn []
(re-frame/dispatch [:bottom-sheet/hide])
(list-selection/open-share {:message (:image content)}))}]])))
(re-frame/dispatch [:bottom-sheet/hide])
(react/copy-to-clipboard (:image content)))}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/save)
:icon :main-icons/download
:on-press (fn []
(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
#_[quo/list-item
{:theme :accent
:title :t/sharing-share
:icon :main-icons/share
:on-press (fn []
(re-frame/dispatch [:bottom-sheet/hide])
(list-selection/open-share {:message (:image content)}))}]]))

View File

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

View File

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

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"
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:
version "1.2.1"
resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.2.1.tgz#645e2ffbbb49e80844bb4cbbe34a126fda1e6772"