[#5260] Implement web3 provider Opt-in access

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
Andrey Shovkoplyas 2018-08-14 15:04:22 +03:00
parent d354da6cb9
commit 42abd16e9a
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
14 changed files with 330 additions and 77 deletions

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill="" fill-rule="evenodd" clip-rule="evenodd" d="M10.7803 3C10.9365 3.00012 11.0809 3.07953 11.159 3.20831L13.9414 7.79169C14.0196 7.92059 14.0196 8.07941 13.9414 8.20831L11.159 12.7917C11.0809 12.9205 10.9365 12.9999 10.7803 13H5.21978C5.06353 12.9999 4.91922 12.9205 4.84106 12.7917L2.05865 8.20831C1.98045 8.07941 1.98045 7.92059 2.05865 7.79169L4.84106 3.20831C4.91922 3.07953 5.06353 3.00012 5.21978 3H10.7803ZM6 8C6 9.10455 6.89541 10 8 10C8.53042 10 9.03915 9.78931 9.41421 9.41418C9.78927 9.03912 10 8.53046 10 8C10 6.89545 9.10458 6 8 6C6.89541 6 6 6.89545 6 8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 689 B

View File

@ -9,10 +9,17 @@ WebViewBridge.onMessage = function (message) {
window.location.href = "about:blank";
else if (data.type === "status-api-success")
{
if (data.keys == 'WEB3')
{
window.dispatchEvent(new CustomEvent('ethereumprovider', { detail: { ethereum: new StatusHttpProvider("")} }));
}
else
{
window.STATUS_API = data.data;
window.postMessage({ type: 'STATUS_API_SUCCESS', permissions: data.keys }, "*");
}
}
else if (data.type === "web3-send-async-callback")
{

View File

@ -24,5 +24,12 @@
host: window.location.hostname
});
}
else if (event.data.type === 'ETHEREUM_PROVIDER_REQUEST') {
bridgeSend({
type: 'status-api-request',
permissions: ['WEB3'],
host: window.location.hostname
});
}
});
}());

View File

@ -246,6 +246,7 @@
(def regx-emoji #"^((?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC69\uDC6E\uDC70-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD18-\uDD1C\uDD1E\uDD1F\uDD26\uDD30-\uDD39\uDD3D\uDD3E\uDDD1-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])?|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDEEB\uDEEC\uDEF4-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])\uFE0F|[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF])+$")
(def ^:const dapp-permission-contact-code "CONTACT_CODE")
(def ^:const dapp-permission-web3 "WEB3")
(def ^:const status-api-success "status-api-success")
(def ^:const status-api-request "status-api-request")
(def ^:const history-state-changed "history-state-changed")

View File

@ -50,16 +50,23 @@
(merge (update-browser-fx cofx browser)
{:dispatch [:navigate-to :browser (:browser-id browser)]}))
(def permissions {constants/dapp-permission-contact-code {:label (i18n/label :t/your-contact-code)}})
(def permissions {constants/dapp-permission-contact-code {:title (i18n/label :t/wants-to-access-profile)
:description (i18n/label :t/your-contact-code)
:icon :icons/profile-active}
constants/dapp-permission-web3 {:title (i18n/label :t/dapp-would-like-to-connect-wallet)
:description (i18n/label :t/allowing-authorizes-this-dapp)
:icon :icons/wallet-active}})
(defn update-dapp-permissions-fx [{:keys [db]} permissions]
{:db (assoc-in db [:dapps/permissions (:dapp permissions)] permissions)
{:db (-> db
(assoc-in [:browser/options :show-permission] nil)
(assoc-in [:dapps/permissions (:dapp permissions)] permissions))
:data-store/tx [(dapp-permissions/save-dapp-permissions permissions)]})
(defn request-permission [cofx
{:keys [dapp-name index requested-permissions permissions-allowed user-permissions
permissions-data webview]
:as params}]
(defn request-permission [{:keys [dapp-name index requested-permissions permissions-allowed user-permissions
permissions-data]
:as params}
{:keys [db] :as cofx}]
;; iterate all requested permissions
(if (< index (count requested-permissions))
(let [requested-permission (get requested-permissions index)]
@ -68,7 +75,8 @@
;; if permission already allowed go to next, if not, show confirmation dialog
(if ((set user-permissions) requested-permission)
{:dispatch [:next-dapp-permission params requested-permission permissions-data]}
{:show-dapp-permission-confirmation-fx [requested-permission params]})
{:db (assoc-in db [:browser/options :show-permission] {:requested-permission requested-permission
:params params})})
{:dispatch [:next-dapp-permission params]}))
(assoc (update-dapp-permissions-fx cofx {:dapp dapp-name
:permissions (vec (set (concat (keys permissions-allowed)
@ -76,19 +84,20 @@
:send-to-bridge-fx [{:type constants/status-api-success
:data permissions-allowed
:keys (keys permissions-allowed)}
webview])))
(:webview-bridge db)]
:dispatch [:check-permissions-queue])))
(defn next-permission [cofx params & [permission permissions-data]]
(defn next-permission [{:keys [params permission permissions-data]} cofx]
(request-permission
cofx
(cond-> params
true
(update :index inc)
(and permission permissions-data)
(assoc-in [:permissions-allowed permission] (get permissions-data permission)))))
(assoc-in [:permissions-allowed permission] (get permissions-data permission)))
cofx))
(defn web3-send-async [{:keys [db]} {:keys [method] :as payload} message-id]
(defn web3-send-async [{:keys [method] :as payload} message-id {:keys [db]}]
(if (or (= method constants/web3-send-transaction)
(= method constants/web3-personal-sign))
{:db (update-in db [:wallet :transactions-queue] conj {:message-id message-id :payload payload})

View File

@ -720,5 +720,10 @@
:browser-secure "Connection is secure. Make sure you really trust this site before signing transactions or entering personal data."
:browser-not-secure "Connection is not secure! Do not sign transactions or send personal data on this site."
:make-sure-you-trust-dapp "Make sure that you trust this DApp"
:would-like-to-access "Would like to Access"
:your-contact-code "Your Contact Code"})
:wants-to-access-profile "wants to access to your profile"
:your-contact-code "Granting access authorizes this DApp to retrieve your contact code"
:dapp-would-like-to-connect-wallet "would like\n to connect to your wallet"
:allowing-authorizes-this-dapp "Allowing authorizes this DApp to retrieve your wallet address and enable Web3"
:manage-permissions "Manage permissions"
:deny "Deny"
:allow "Allow"})

View File

@ -149,6 +149,18 @@
:default-chat-icon (styles/default-chat-icon-chat-list components.styles/default-chat-color)
:default-chat-icon-text styles/default-chat-icon-text}])
(defn dapp-icon-permission [contact size]
[contact-icon-view contact
{:container {:width size :height size}
:online-view-wrapper styles/online-view-wrapper
:online-view styles/online-view
:online-dot-left styles/online-dot-left
:online-dot-right styles/online-dot-right
:size size
:chat-icon (styles/custom-size-icon size)
:default-chat-icon (styles/default-chat-icon-profile components.styles/default-chat-color size)
:default-chat-icon-text styles/default-chat-icon-text}])
(defn profile-icon-view [photo-path name color edit? size]
(let [styles {:container {:width size :height size}
:online-view styles/online-view-profile

View File

@ -151,7 +151,8 @@
:icons/camera (components.svg/slurp-svg "./resources/icons/camera.svg")
:icons/check (components.svg/slurp-svg "./resources/icons/check.svg")
:icons/dots (components.svg/slurp-svg "./resources/icons/dots.svg")
:icons/warning (components.svg/slurp-svg "./resources/icons/warning.svg")}))
:icons/warning (components.svg/slurp-svg "./resources/icons/warning.svg")
:icons/settings (components.svg/slurp-svg "./resources/icons/settings.svg")}))
(defn normalize-property-name [n]
(if (= n :icons/options)

View File

@ -12,6 +12,8 @@
(spec/def :browser/loading? (spec/nilable boolean?))
(spec/def :browser/url-editing? (spec/nilable boolean?))
(spec/def :browser/show-tooltip (spec/nilable keyword?))
(spec/def :browser/show-permission (spec/nilable map?))
(spec/def :browser/permissions-queue (spec/nilable any?))
(spec/def :browser/options
(allowed-keys
@ -19,6 +21,8 @@
:browser/loading?
:browser/url-editing?
:browser/show-tooltip
:browser/show-permission
:browser/permissions-queue
:browser/error?]))
(spec/def :browser/browser

View File

@ -3,18 +3,19 @@
[status-im.utils.handlers :as handlers]
[re-frame.core :as re-frame]
[status-im.utils.random :as random]
[status-im.i18n :as i18n]
[status-im.ui.components.list-selection :as list-selection]
[status-im.utils.universal-links.core :as utils.universal-links]
[status-im.data-store.browser :as browser-store]
[status-im.utils.http :as http]
[status-im.models.browser :as model]
[status-im.utils.platform :as platform]
[status-im.utils.utils :as utils]
[status-im.constants :as constants]
[status-im.native-module.core :as status]
[taoensso.timbre :as log]
[status-im.utils.types :as types]))
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.utils.types :as types]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.constants :as constants]))
(re-frame/reg-fx
:browse
@ -40,18 +41,6 @@
(fn [[message webview]]
(.sendToBridge webview (types/clj->json message))))
(re-frame/reg-fx
:show-dapp-permission-confirmation-fx
(fn [[permission {:keys [dapp-name permissions-data] :as params}]]
(utils/show-confirmation
{:ios-confirm-style "default"}
(str "\"" dapp-name "\" " (i18n/label :t/would-like-to-access) " " (:label (get model/permissions permission)))
(i18n/label :t/make-sure-you-trust-dapp)
nil
#(re-frame/dispatch [:next-dapp-permission params permission permissions-data])
#(re-frame/dispatch [:next-dapp-permission params])
(i18n/label :t/dont-allow))))
(handlers/register-handler-fx
:initialize-browsers
[(re-frame/inject-cofx :data-store/all-browsers)]
@ -132,7 +121,7 @@
:on-bridge-message
[re-frame/trim-v]
(fn [{:keys [db] :as cofx} [message]]
(let [{:browser/keys [options browsers] :keys [webview-bridge]} db
(let [{:browser/keys [options browsers]} db
{:keys [browser-id]} options
browser (get browsers browser-id)
data (types/json->clj message)
@ -143,23 +132,38 @@
(model/update-browser-history-fx cofx browser url false)
(= type constants/web3-send-async)
(model/web3-send-async cofx payload messageId)
(model/web3-send-async payload messageId cofx)
(= type constants/status-api-request)
(let [{:account/keys [account]} db
{:keys [dapp? name]} browser
(let [{:keys [dapp? name]} browser
dapp-name (if dapp? name host)]
(model/request-permission
{:db (update-in db [:browser/options :permissions-queue] conj {:dapp-name dapp-name
:permissions permissions})
:dispatch [:check-permissions-queue]})))))
(handlers/register-handler-fx
:check-permissions-queue
[re-frame/trim-v]
(fn [{:keys [db] :as cofx} _]
(let [{:keys [show-permission permissions-queue]} (:browser/options db)]
(when (and (nil? show-permission) (last permissions-queue))
(let [{:keys [dapp-name permissions]} (last permissions-queue)
{:account/keys [account]} db]
(handlers-macro/merge-fx
cofx
{:db (update-in db [:browser/options :permissions-queue] drop-last)}
(model/request-permission
{:dapp-name dapp-name
:webview webview-bridge
:index 0
:user-permissions (get-in db [:dapps/permissions dapp-name :permissions])
:requested-permissions permissions
:permissions-data {constants/dapp-permission-contact-code (:public-key account)}}))))))
:permissions-data {constants/dapp-permission-contact-code (:public-key account)}})))))))
(handlers/register-handler-fx
:next-dapp-permission
[re-frame/trim-v]
(fn [cofx [params permission permissions-data]]
(model/next-permission cofx params permission permissions-data)))
(model/next-permission {:params params
:permission permission
:permissions-data permissions-data}
cofx)))

View File

@ -0,0 +1,83 @@
(ns status-im.ui.screens.browser.permissions.views
(:require-macros [status-im.utils.views :as views])
(:require [status-im.ui.components.animation :as anim]
[status-im.ui.components.react :as react]
[status-im.ui.screens.browser.styles :as styles]
[re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.colors :as colors]
[reagent.core :as reagent]
[status-im.models.browser :as model]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]))
(views/defview permissions-panel [{:keys [dapp? name] :as browser} {:keys [requested-permission params]}]
(views/letsubs [dapp [:get-dapp-by-name name]
bottom-anim-value (anim/create-value -354)
alpha-value (anim/create-value 0)
hide-panel #(anim/start
(anim/parallel
[(anim/spring bottom-anim-value {:toValue -354})
(anim/timing alpha-value {:toValue 0
:duration 500})]))]
{:component-did-mount #(anim/start
(anim/parallel
[(anim/spring bottom-anim-value {:toValue -20})
(anim/timing alpha-value {:toValue 0.6
:duration 500})]))}
(let [_ (when-not requested-permission (js/setTimeout hide-panel 10))
{:keys [dapp-name]} params
{:keys [title description icon]} (get model/permissions requested-permission)]
[react/view styles/permissions-panel-container
[react/animated-view {:style (styles/permissions-panel-background alpha-value)}]
[react/animated-view {:style (styles/permissions-panel bottom-anim-value)}
[react/view styles/permissions-panel-icons-container
(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} "Ð"]])
[react/view {:margin-left 3 :margin-right 3}
[react/view styles/dot]]
[react/view {:margin-right 3}
[react/view styles/dot]]
[react/view styles/permissions-panel-ok-icon-container
[icons/icon :icons/ok styles/permissions-panel-ok-ico]]
[react/view {:margin-left 3 :margin-right 3}
[react/view styles/dot]]
[react/view {:margin-right 3}
[react/view styles/dot]]
[react/view styles/permissions-panel-wallet-icon-container
(when icon
[icons/icon icon {:color :white}])]]
[react/text {:style styles/permissions-panel-title-label}
(str "\"" dapp-name "\" " title)]
[react/text {:style styles/permissions-panel-description-label}
description]
[react/view {:flex-direction :row :margin-top 14}
[components.common/button {:on-press #(re-frame/dispatch [:next-dapp-permission params])
:label (i18n/label :t/deny)}]
[react/view {:width 16}]
[components.common/button {:on-press #(re-frame/dispatch [:next-dapp-permission params requested-permission
(:permissions-data params)])
:label (i18n/label :t/allow)}]]
;; TODO (andrey) will be in next PR
#_[react/view {:flex-direction :row :margin-top 19}
[icons/icon :icons/settings {:color colors/blue}]
[react/text {:style styles/permissions-panel-permissions-label}
(i18n/label :t/manage-permissions)]]]])))
;; NOTE (andrey) we need this complex function, to show animation before component will be unmounted
(defn permissions-anim-panel [browser show-permission]
(let [timeout (atom nil)
render? (reagent/atom false)]
(fn [browser show-permission]
(if show-permission
(do
(when @timeout
(js/clearTimeout @timeout)
(reset! timeout nil))
(when-not @render? (reset! render? true)))
(reset! timeout (js/setTimeout #(reset! render? false) 600)))
(when @render?
[permissions-panel browser show-permission]))))

View File

@ -82,3 +82,92 @@
:letter-spacing -0.2
:margin-horizontal 5})
(def dot
{:height 4
:width 4
:background-color "#E4E6EB"
:border-radius 2})
(def permissions-panel-container
{:position :absolute
:top 0
:bottom 0
:right 0
:left 0})
(defn permissions-panel-background [alpha-value]
{:flex 1
:background-color colors/black
:opacity alpha-value})
(defn permissions-panel [bottom-anim-value]
{:height 354
:position :absolute
:bottom bottom-anim-value
:right 0
:left 0
:align-items :center
:background-color :white
:border-top-left-radius 8
:border-top-right-radius 8})
(def permissions-panel-icons-container
{:margin-top 26
:align-items :center
:justify-content :center
:flex-direction :row})
(def permissions-panel-dapp-icon-container
{:height 48
:width 48
:background-color "#E4E6EB"
:border-radius 24
:align-items :center
:justify-content :center})
(def permissions-panel-d-label
{:font-size 22
:color colors/gray
:font-weight :bold})
(def permissions-panel-ok-icon-container
{:height 24
:width 24
:background-color "#48EA77"
:border-radius 12
:align-items :center
:justify-content :center})
(def permissions-panel-ok-ico
{:color :white
:width 12
:height 12})
(def permissions-panel-wallet-icon-container
{:height 48
:width 48
:background-color colors/blue
:border-radius 24
:align-items :center
:justify-content :center})
(def permissions-panel-title-label
{:margin-horizontal 20
:font-size 22
:line-height 28
:text-align :center
:margin-top 19
:font-weight :bold})
(def permissions-panel-description-label
{:margin-horizontal 20
:color colors/gray
:font-size 15
:line-height 22
:text-align :center
:margin-top 9})
(def permissions-panel-permissions-label
{:color colors/blue
:font-size 14
:margin-left 10})

View File

@ -20,7 +20,8 @@
[status-im.utils.http :as http]
[status-im.ui.components.styles :as components.styles]
[status-im.ui.components.colors :as colors]
[clojure.string :as string]))
[clojure.string :as string]
[status-im.ui.screens.browser.permissions.views :as permissions.views]))
(def browser-config
(reader/read-string (slurp "./src/status_im/utils/browser_config.edn")))
@ -55,6 +56,21 @@
[react/touchable-highlight {:style {:flex 1} :on-press #(re-frame/dispatch [:update-browser-options {:url-editing? true}])}
[react/text {:style styles/url-text} (http/url-host url)]])]]))
(defn toolbar [webview error? url browser browser-id url-editing?]
[toolbar.view/toolbar {}
[toolbar.view/nav-button-with-count
(actions/close (fn []
(when @webview
(.sendToBridge @webview "navigate-to-blank"))
(re-frame/dispatch [:navigate-back])
(when error?
(re-frame/dispatch [:remove-browser browser-id]))))]
[toolbar-content url browser error? url-editing?]
[toolbar.view/actions [{:icon :icons/wallet
:icon-opts {:color :black
:accessibility-label :wallet-modal-button}
:handler #(re-frame/dispatch [:navigate-to-modal :wallet-modal])}]]])
(defn- web-view-error [_ code desc]
(reagent/as-element
[react/view styles/web-view-error
@ -74,11 +90,30 @@
(let [domain-name (nth (re-find #"^\w+://(www\.)?([^/:]+)" url) 2)]
(get (:inject-js browser-config) domain-name)))
(defn navigation [webview browser can-go-back? can-go-forward?]
[react/view styles/toolbar
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser-nav-back browser])
:disabled (not can-go-back?)
:style (when-not can-go-back? styles/disabled-button)
:accessibility-label :previou-page-button}
[react/view
[icons/icon :icons/arrow-left]]]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser-nav-forward browser])
:disabled (not can-go-forward?)
:style (merge styles/forward-button
(when-not can-go-forward? styles/disabled-button))
:accessibility-label :next-page-button}
[react/view
[icons/icon :icons/arrow-right]]]
[react/view {:flex 1}]
[react/touchable-highlight {:on-press #(.reload @webview)}
[icons/icon :icons/refresh]]])
(views/defview browser []
(views/letsubs [webview (atom nil)
{:keys [address]} [:get-current-account]
{:keys [browser-id dapp? name] :as browser} [:get-current-browser]
{:keys [error? loading? url-editing? show-tooltip]} [:get :browser/options]
{:keys [error? loading? url-editing? show-tooltip show-permission]} [:get :browser/options]
rpc-url [:get :rpc-url]
network-id [:get-network-id]]
(let [can-go-back? (model/can-go-back? browser)
@ -86,19 +121,7 @@
url (model/get-current-url browser)]
[react/view styles/browser
[status-bar/status-bar]
[toolbar.view/toolbar {}
[toolbar.view/nav-button-with-count
(actions/close (fn []
(when @webview
(.sendToBridge @webview "navigate-to-blank"))
(re-frame/dispatch [:navigate-back])
(when error?
(re-frame/dispatch [:remove-browser browser-id]))))]
[toolbar-content url browser error? url-editing?]
[toolbar.view/actions [{:icon :icons/wallet
:icon-opts {:color :black
:accessibility-label :wallet-modal-button}
:handler #(re-frame/dispatch [:navigate-to-modal :wallet-modal])}]]]
[toolbar webview error? url browser browser-id url-editing?]
[react/view components.styles/flex
[components.webview-bridge/webview-bridge
{:dapp? dapp?
@ -126,23 +149,8 @@
(when loading?
[react/view styles/web-view-loading
[components/activity-indicator {:animating true}]])]
[react/view styles/toolbar
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser-nav-back browser])
:disabled (not can-go-back?)
:style (when-not can-go-back? styles/disabled-button)
:accessibility-label :previou-page-button}
[react/view
[icons/icon :icons/arrow-left]]]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser-nav-forward browser])
:disabled (not can-go-forward?)
:style (merge styles/forward-button
(when-not can-go-forward? styles/disabled-button))
:accessibility-label :next-page-button}
[react/view
[icons/icon :icons/arrow-right]]]
[react/view {:flex 1}]
[react/touchable-highlight {:on-press #(.reload @webview)}
[icons/icon :icons/refresh]]]
[navigation webview browser can-go-back? can-go-forward?]
[permissions.views/permissions-anim-panel browser show-permission]
(when show-tooltip
[tooltip/bottom-tooltip-info
(if (= show-tooltip :secure)

View File

@ -135,6 +135,12 @@
:permissions ["FAKE_PERMISSION"]})
nil nil])
(re-frame/dispatch [:next-dapp-permission
{:dapp-name dapp-name
:index 0
:requested-permissions ["FAKE_PERMISSION"]
:permissions-data "Data"}])
(is (= {:dapp dapp-name
:permissions []}
(get @dapps-permissions dapp-name)))
@ -144,6 +150,14 @@
:permissions ["CONTACT_CODE"]})
nil nil])
(re-frame/dispatch [:next-dapp-permission
{:dapp-name dapp-name
:index 0
:requested-permissions ["CONTACT_CODE"]
:permissions-data {"CONTACT_CODE" "Data"}}
"CONTACT_CODE"
{"CONTACT_CODE" "Data"}])
(is (= 1 (count @dapps-permissions)))
(is (= {:dapp dapp-name
@ -177,6 +191,12 @@
:permissions ["CONTACT_CODE"]})
nil nil])
(re-frame/dispatch [:next-dapp-permission
{:dapp-name dapp-name2
:index 0
:requested-permissions ["CONTACT_CODE" "FAKE_PERMISSION"]
:permissions-data "Data"}])
(is (= 2 (count @dapps-permissions)))
(is (= {:dapp dapp-name2