From 4c4fb6bbe9e341104d1b8147028101e7ca746567 Mon Sep 17 00:00:00 2001 From: Andrey Shovkoplyas Date: Mon, 4 Feb 2019 10:07:41 +0100 Subject: [PATCH] [#5584] Implement Manage permissions screen and option for web3 provider Opt-in access Signed-off-by: Andrey Shovkoplyas --- resources/icons/dapp.svg | 4 ++ src/status_im/browser/permissions.cljs | 10 ++- .../data_store/dapp_permissions.cljs | 8 ++- src/status_im/events.cljs | 5 ++ .../ui/components/common/common.cljs | 6 ++ .../ui/components/icons/vector_icons.cljs | 6 +- .../ui/components/list_item/styles.cljs | 35 +++++++++++ .../ui/components/list_item/views.cljs | 46 ++++++++++++++ .../ui/components/toolbar/styles.cljs | 1 + .../ui/screens/browser/permissions/views.cljs | 5 +- src/status_im/ui/screens/chat/photos.cljs | 12 +--- .../ui/screens/dapps_permissions/styles.cljs | 10 +++ .../ui/screens/dapps_permissions/views.cljs | 61 +++++++++++++++++++ src/status_im/ui/screens/db.cljs | 4 +- .../ui/screens/profile/user/views.cljs | 5 ++ src/status_im/ui/screens/views.cljs | 3 + src/status_im/utils/image.cljs | 11 ++++ .../status_im/test/chat/views/photos.cljs | 6 +- translations/en.json | 4 +- 19 files changed, 221 insertions(+), 21 deletions(-) create mode 100755 resources/icons/dapp.svg create mode 100644 src/status_im/ui/components/list_item/styles.cljs create mode 100644 src/status_im/ui/components/list_item/views.cljs create mode 100644 src/status_im/ui/screens/dapps_permissions/styles.cljs create mode 100644 src/status_im/ui/screens/dapps_permissions/views.cljs create mode 100644 src/status_im/utils/image.cljs diff --git a/resources/icons/dapp.svg b/resources/icons/dapp.svg new file mode 100755 index 0000000000..981a044b0b --- /dev/null +++ b/resources/icons/dapp.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/status_im/browser/permissions.cljs b/src/status_im/browser/permissions.cljs index 1e930b9d77..f60f1e5af5 100644 --- a/src/status_im/browser/permissions.cljs +++ b/src/status_im/browser/permissions.cljs @@ -5,7 +5,8 @@ [status-im.utils.ethereum.core :as ethereum] [status-im.utils.fx :as fx] [status-im.qr-scanner.core :as qr-scanner] - [status-im.extensions.registry :as extensions.registry])) + [status-im.extensions.registry :as extensions.registry] + [status-im.ui.screens.navigation :as navigation])) (declare process-next-permission) (declare send-response-to-bridge) @@ -77,6 +78,13 @@ {:db (assoc-in db [:dapps/permissions dapp-name] allowed-permissions) :data-store/tx [(dapp-permissions/save-dapp-permissions allowed-permissions)]})) +(fx/defn revoke-dapp-permissions + [{:keys [db] :as cofx} dapp] + (fx/merge cofx + {:db (update-in db [:dapps/permissions] dissoc dapp) + :data-store/tx [(dapp-permissions/remove-dapp-permissions dapp)]} + (navigation/navigate-back))) + (fx/defn process-next-permission "Process next permission by removing it from pending permissions and prompting user if there is no pending permissions left, save all granted permissions diff --git a/src/status_im/data_store/dapp_permissions.cljs b/src/status_im/data_store/dapp_permissions.cljs index 2bb5270d95..73e3625f8d 100644 --- a/src/status_im/data_store/dapp_permissions.cljs +++ b/src/status_im/data_store/dapp_permissions.cljs @@ -13,4 +13,10 @@ "Returns tx function for saving dapp permissions" [permissions] (fn [realm] - (core/create realm :dapp-permissions permissions true))) \ No newline at end of file + (core/create realm :dapp-permissions permissions true))) + +(defn remove-dapp-permissions + "Returns tx function for removing dapp permissions" + [dapp] + (fn [realm] + (core/delete realm (core/single (core/get-by-field realm :dapp-permissions :dapp dapp))))) diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index bb76f9119e..5575ab0495 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -1382,6 +1382,11 @@ (fn [cofx [_ host]] (browser/open-chat-from-browser cofx host))) +(handlers/register-handler-fx + :dapps/revoke-access + (fn [cofx [_ dapp]] + (browser.permissions/revoke-dapp-permissions cofx dapp))) + ;; group-chats module (handlers/register-handler-fx diff --git a/src/status_im/ui/components/common/common.cljs b/src/status_im/ui/components/common/common.cljs index 0fedcf0a2a..70c8b40031 100644 --- a/src/status_im/ui/components/common/common.cljs +++ b/src/status_im/ui/components/common/common.cljs @@ -95,6 +95,12 @@ :style (merge styles/button-label label-style)} label]]]) +(defn red-button [props] + [react/view {:align-items :center} + [button (merge props + {:label-style {:color colors/red :font-size 15} + :button-style {:padding-horizontal 32 :background-color colors/red-light}})]]) + (defn counter ([value] (counter nil value)) ([{:keys [size accessibility-label] :or {size 18}} value] diff --git a/src/status_im/ui/components/icons/vector_icons.cljs b/src/status_im/ui/components/icons/vector_icons.cljs index dbf8aaa5b5..09a47b6955 100644 --- a/src/status_im/ui/components/icons/vector_icons.cljs +++ b/src/status_im/ui/components/icons/vector_icons.cljs @@ -108,7 +108,8 @@ :icons/indicator-big (js/require "./resources/icons/indicator-big.svg") :icons/indicator-middle (js/require "./resources/icons/indicator-middle.svg") :icons/indicator-small (js/require "./resources/icons/indicator-small.svg") - :icons/stickers (js/require "./resources/icons/stickers.svg")} + :icons/stickers (js/require "./resources/icons/stickers.svg") + :icons/dapp (js/require "./resources/icons/dapp.svg")} {:main-icons/add (components.svg/slurp-svg "./resources/icons/main/add.svg") :main-icons/cancel (components.svg/slurp-svg "./resources/icons/main/cancel.svg") :main-icons/group-chat (components.svg/slurp-svg "./resources/icons/main/group_chat.svg") @@ -195,7 +196,8 @@ :icons/indicator-small (components.svg/slurp-svg "./resources/icons/indicator-small.svg") :icons/stickers (components.svg/slurp-svg "./resources/icons/stickers.svg") :icons/stickers-big (components.svg/slurp-svg "./resources/icons/stickers_big.svg") - :icons/clock (components.svg/slurp-svg "./resources/icons/clock.svg")})) + :icons/clock (components.svg/slurp-svg "./resources/icons/clock.svg") + :icons/dapp (components.svg/slurp-svg "./resources/icons/dapp.svg")})) (defn normalize-property-name [n] (if (= n :icons/options) diff --git a/src/status_im/ui/components/list_item/styles.cljs b/src/status_im/ui/components/list_item/styles.cljs new file mode 100644 index 0000000000..f536cffba4 --- /dev/null +++ b/src/status_im/ui/components/list_item/styles.cljs @@ -0,0 +1,35 @@ +(ns status-im.ui.components.list-item.styles + (:require [status-im.ui.components.colors :as colors])) + +(defn container [small?] + {:height (if small? 52 64) + :align-items :center + :flex-direction :row + :padding-right 8 + :background-color :white}) + +(defn title [small? subtitle] + (cond-> (if small? + {:line-height 22 :font-size 15} + {:line-height 20 :font-size 17}) + subtitle + (assoc :font-weight 500 :font-size 15))) + +(def subtitle + {:margin-top 4 + :line-height 22 + :font-size 15 + :color colors/gray}) + +(def accessory-text + {:line-height 22 + :font-size 15 + :color colors/gray + :margin-right 8}) + +(defn radius [size] (/ size 2)) + +(defn photo [size] + {:border-radius (radius size) + :width size + :height size}) \ No newline at end of file diff --git a/src/status_im/ui/components/list_item/views.cljs b/src/status_im/ui/components/list_item/views.cljs new file mode 100644 index 0000000000..0497020721 --- /dev/null +++ b/src/status_im/ui/components/list_item/views.cljs @@ -0,0 +1,46 @@ +(ns status-im.ui.components.list-item.views + (:require [status-im.ui.components.colors :as colors] + [status-im.ui.components.icons.vector-icons :as icons] + [status-im.ui.components.react :as react] + [status-im.ui.components.list-item.styles :as styles] + [status-im.utils.image :as utils.image])) + +; type - optional :default , :small + +; accessories - optional vector of :chevron, :check or component or string + +; theme - optional :default, :wallet + +(defn list-item [{:keys [title subtitle accessories image image-path type theme on-press] :or {type :default theme :default}}] + (let [small? (= :small type)] + [react/touchable-highlight {:on-press on-press :disabled (not on-press)} + [react/view {:style (styles/container small?)} + ;;Image + (when image + [react/view {:margin-left 16} + [image]]) + (when image-path + [react/view {:margin-left 16} + [react/image {:source (utils.image/source image-path) + :style (styles/photo 40)}]]) + ;;Title + [react/view {:style {:margin-left 16 :flex 1}} + [react/text {:style (styles/title small? subtitle)} + title] + ;;Subtitle + (when subtitle + [react/text {:style styles/subtitle} + subtitle])] + ;;Accessories + (for [accessory accessories] + (with-meta + (cond + (string? accessory) + [react/text {:style styles/accessory-text} + accessory] + (= :chevron accessory) + [icons/icon :icons/forward {:color colors/gray-transparent-40}] + (= :check accessory) + [icons/icon :icons/ok {:color colors/gray}] + :else accessory) + {:key accessory}))]])) \ No newline at end of file diff --git a/src/status_im/ui/components/toolbar/styles.cljs b/src/status_im/ui/components/toolbar/styles.cljs index 312cf769cb..b7404d5d34 100644 --- a/src/status_im/ui/components/toolbar/styles.cljs +++ b/src/status_im/ui/components/toolbar/styles.cljs @@ -36,6 +36,7 @@ {:color colors/black :letter-spacing -0.2 :font-size 17 + :font-weight :bold :ios {:text-align :center :margin-left 15 :margin-right 15} diff --git a/src/status_im/ui/screens/browser/permissions/views.cljs b/src/status_im/ui/screens/browser/permissions/views.cljs index dc5f136b0e..8549806bbb 100644 --- a/src/status_im/ui/screens/browser/permissions/views.cljs +++ b/src/status_im/ui/screens/browser/permissions/views.cljs @@ -8,7 +8,8 @@ [status-im.ui.components.common.common :as components.common] [status-im.ui.components.icons.vector-icons :as icons] [status-im.ui.components.react :as react] - [status-im.ui.screens.browser.styles :as styles]) + [status-im.ui.screens.browser.styles :as styles] + [status-im.ui.components.colors :as colors]) (:require-macros [status-im.utils.views :as views])) (defn hide-panel-anim @@ -79,7 +80,7 @@ (if dapp? [chat-icon.screen/dapp-icon-permission dapp 48] [react/view styles/permissions-panel-dapp-icon-container - [react/text {:style styles/permissions-panel-d-label} "Ð"]]) + [icons/icon :icons/dapp {:color colors/gray}]]) [react/view {:margin-left 3 :margin-right 3} [react/view styles/dot]] [react/view {:margin-right 3} diff --git a/src/status_im/ui/screens/chat/photos.cljs b/src/status_im/ui/screens/chat/photos.cljs index 460b3c16d7..8e4b0a8fa8 100644 --- a/src/status_im/ui/screens/chat/photos.cljs +++ b/src/status_im/ui/screens/chat/photos.cljs @@ -4,20 +4,12 @@ [status-im.ui.screens.chat.styles.photos :as style] [status-im.utils.identicon :as identicon] [clojure.string :as string] - [status-im.react-native.resources :as resources])) - -(defn- source [photo-path] - (if (and (not (string/blank? photo-path)) - (string/starts-with? photo-path "contacts://")) - (->> (string/replace photo-path #"contacts://" "") - (keyword) - (get resources/contacts)) - {:uri photo-path})) + [status-im.utils.image :as utils.image])) (defn photo [photo-path {:keys [size accessibility-label]}] [react/view {:style (style/photo-container size)} - [react/image {:source (source photo-path) + [react/image {:source (utils.image/source photo-path) :style (style/photo size) :accessibility-label (or accessibility-label :chat-icon)}] [react/view {:style (style/photo-border size)}]]) diff --git a/src/status_im/ui/screens/dapps_permissions/styles.cljs b/src/status_im/ui/screens/dapps_permissions/styles.cljs new file mode 100644 index 0000000000..606110fc9b --- /dev/null +++ b/src/status_im/ui/screens/dapps_permissions/styles.cljs @@ -0,0 +1,10 @@ +(ns status-im.ui.screens.dapps-permissions.styles + (:require [status-im.ui.components.colors :as colors])) + +(def icon-container + {:width 40 + :height 40 + :border-radius 20 + :background-color colors/gray-lighter + :align-items :center + :justify-content :center}) \ No newline at end of file diff --git a/src/status_im/ui/screens/dapps_permissions/views.cljs b/src/status_im/ui/screens/dapps_permissions/views.cljs new file mode 100644 index 0000000000..67ad9671ef --- /dev/null +++ b/src/status_im/ui/screens/dapps_permissions/views.cljs @@ -0,0 +1,61 @@ +(ns status-im.ui.screens.dapps-permissions.views + (:require-macros [status-im.utils.views :as views]) + (:require [re-frame.core :as re-frame] + [status-im.i18n :as i18n] + [status-im.ui.components.react :as react] + [status-im.ui.components.status-bar.view :as status-bar] + [status-im.ui.components.toolbar.view :as toolbar] + [status-im.ui.components.list-item.views :as list-item] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.colors :as colors] + [status-im.ui.screens.dapps-permissions.styles :as styles] + [status-im.constants :as constants] + [status-im.ui.components.common.common :as components.common] + [status-im.ui.components.icons.vector-icons :as icons])) + +(defn d-icon [] + [react/view styles/icon-container + [icons/icon :icons/dapp {:color colors/gray}]]) + +(defn prepare-items [dapps] + (fn [{:keys [dapp permissions]}] + (merge + {:title dapp + :accessories [:chevron] + :on-press #(re-frame/dispatch [:navigate-to :manage-dapps-permissions {:dapp dapp :permissions permissions}])} + (let [path (get-in dapps [dapp :photo-path])] + (if path + {:image-path path} + {:image d-icon}))))) + +(defn prepare-items-manage [permission] + {:title (case permission + constants/dapp-permission-web3 (i18n/label :t/wallet) + constants/dapp-permission-contact-code (i18n/label :t/contact-code)) + :type :small + :accessories [:check]}) + +(views/defview dapps-permissions [] + (views/letsubs [permissions [:get :dapps/permissions] + dapps [:contacts/dapps-by-name]] + [react/view {:flex 1 :background-color colors/white} + [status-bar/status-bar] + [toolbar/simple-toolbar + (i18n/label :t/dapps-permissions)] + [list/flat-list + {:data (map (prepare-items dapps) (vals permissions)) + :key-fn (fn [_ i] (str i)) + :render-fn list-item/list-item}]])) + +(views/defview manage [] + (views/letsubs [{:keys [dapp permissions]} [:get-screen-params]] + [react/view {:flex 1 :background-color colors/white} + [status-bar/status-bar] + [toolbar/simple-toolbar dapp] + [list/flat-list + {:data (map prepare-items-manage permissions) + :key-fn (fn [_ i] (str i)) + :render-fn list-item/list-item}] + [react/view {:padding-vertical 16} + [components.common/red-button {:label (i18n/label :t/revoke-access) + :on-press #(re-frame/dispatch [:dapps/revoke-access dapp])}]]])) \ No newline at end of file diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index 600e8a8820..dccac4b2e5 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -138,6 +138,7 @@ (spec/def :navigation.screen-params/show-extension map?) (spec/def :navigation.screen-params/selection-modal-screen map?) +(spec/def :navigation.screen-params/manage-dapps-permissions map?) (spec/def :navigation/screen-params (spec/nilable (spec/keys :opt-un [:navigation.screen-params/network-details :navigation.screen-params/browser @@ -148,7 +149,8 @@ :navigation.screen-params/dapp-description :navigation.screen-params/collectibles-list :navigation.screen-params/show-extension - :navigation.screen-params/selection-modal-screen]))) + :navigation.screen-params/selection-modal-screen + :navigation.screen-params/manage-dapps-permissions]))) (spec/def :desktop/desktop (spec/nilable any?)) (spec/def ::tooltips (spec/nilable any?)) diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs index 4c364c6579..e14c61182f 100644 --- a/src/status_im/ui/screens/profile/user/views.cljs +++ b/src/status_im/ui/screens/profile/user/views.cljs @@ -140,6 +140,11 @@ :value (or (nil? (:web3-opt-in? settings)) (:web3-opt-in? settings)) :action-fn #(re-frame/dispatch [:accounts.ui/web3-opt-in-mode-switched %])}] [profile.components/settings-item-separator] + [profile.components/settings-item + {:label-kw :t/dapps-permissions + :accessibility-label :dapps-permissions-button + :action-fn #(re-frame/dispatch [:navigate-to :dapps-permissions])}] + [profile.components/settings-item-separator] [profile.components/settings-item {:label-kw :t/need-help :accessibility-label :help-button diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index 5851442c76..8441b901d8 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -67,6 +67,7 @@ [status-im.ui.screens.profile.seed.views :refer [backup-seed]] [status-im.ui.screens.about-app.views :as about-app] [status-im.ui.screens.stickers.views :as stickers] + [status-im.ui.screens.dapps-permissions.views :as dapps-permissions] [status-im.utils.navigation :as navigation] [reagent.core :as reagent] [cljs-react-navigation.reagent :as nav-reagent] @@ -329,6 +330,8 @@ :offline-messaging-settings offline-messaging-settings :edit-mailserver edit-mailserver :help-center help-center + :dapps-permissions dapps-permissions/dapps-permissions + :manage-dapps-permissions dapps-permissions/manage :extensions-settings extensions-settings :edit-extension edit-extension :show-extension show-extension diff --git a/src/status_im/utils/image.cljs b/src/status_im/utils/image.cljs new file mode 100644 index 0000000000..967b57613f --- /dev/null +++ b/src/status_im/utils/image.cljs @@ -0,0 +1,11 @@ +(ns status-im.utils.image + (:require [clojure.string :as string] + [status-im.react-native.resources :as resources])) + +(defn source [photo-path] + (if (and (not (string/blank? photo-path)) + (string/starts-with? photo-path "contacts://")) + (->> (string/replace photo-path #"contacts://" "") + (keyword) + (get resources/contacts)) + {:uri photo-path})) \ No newline at end of file diff --git a/test/cljs/status_im/test/chat/views/photos.cljs b/test/cljs/status_im/test/chat/views/photos.cljs index 2724310502..24f376d18e 100644 --- a/test/cljs/status_im/test/chat/views/photos.cljs +++ b/test/cljs/status_im/test/chat/views/photos.cljs @@ -1,13 +1,13 @@ (ns status-im.test.chat.views.photos (:require [cljs.test :refer [deftest testing is]] [status-im.react-native.resources :as resources] - [status-im.ui.screens.chat.photos :as photos])) + [status-im.utils.image :as utils.image])) (deftest photos-test (testing "a normal string" - (let [actual (photos/source "some-string")] + (let [actual (utils.image/source "some-string")] (is (= {:uri "some-string"} actual)))) (testing "a contact string" (with-redefs [resources/contacts {:test "something"}] - (let [actual (photos/source "contacts://test")] + (let [actual (utils.image/source "contacts://test")] (is (= "something" actual)))))) diff --git a/translations/en.json b/translations/en.json index 0a0c0a218e..593a9b880f 100644 --- a/translations/en.json +++ b/translations/en.json @@ -917,5 +917,7 @@ "mailserver-retry": "Retry", "mailserver-pick-another": "Pick another mailserver", "mailserver-error-title": "Error connecting to mailserver", - "mailserver-error-content": "The mailserver you selected couldn't be reached." + "mailserver-error-content": "The mailserver you selected couldn't be reached.", + "dapps-permissions": "Dapps permissions", + "revoke-access": "Revoke access" }