-
Notifications
You must be signed in to change notification settings - Fork 992
/
Copy pathviews.cljs
280 lines (267 loc) · 13.6 KB
/
views.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
(ns status-im.ui.screens.browser.views
(:require
[quo.core :as quo]
[quo.design-system.colors :as colors]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.browser.core :as browser]
[status-im.browser.webview-ref :as webview-ref]
[utils.i18n :as i18n]
[status-im.qr-scanner.core :as qr-scanner]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.connectivity.view :as connectivity]
[status-im.ui.components.icons.icons :as icons]
[react-native.permissions :as components.permissions]
[status-im.ui.components.react :as react]
[status-im.ui.components.tooltip.views :as tooltip]
[status-im.ui.components.webview :as components.webview]
[status-im.ui.screens.browser.accounts :as accounts]
[status-im.ui.screens.browser.options.views :as options]
[status-im.ui.screens.browser.permissions.views :as permissions.views]
[status-im.ui.screens.browser.site-blocked.views :as site-blocked.views]
[status-im.ui.screens.browser.styles :as styles]
[status-im.ui.screens.wallet.components.views :as components]
[utils.url :as url]
[status-im.utils.js-resources :as js-res]
[utils.debounce :as debounce])
(:require-macros [status-im.utils.views :as views]))
(defn toolbar-content
[url url-original secure? url-editing? unsafe?]
(let [url-text (atom url)]
[react/view (styles/toolbar-content)
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:browser.ui/lock-pressed secure?])
:accessibility-label :security-icon}
(if secure?
[icons/tiny-icon :tiny-icons/tiny-lock {:color colors/green}]
[icons/tiny-icon :tiny-icons/tiny-lock-broken {:color colors/black}])]
(if url-editing?
[react/text-input
{:on-change-text #(reset! url-text %)
:on-blur #(re-frame/dispatch [:browser.ui/url-input-blured])
:on-submit-editing #(re-frame/dispatch [:browser.ui/url-submitted @url-text])
:placeholder (i18n/label :t/enter-url)
:auto-capitalize :none
:auto-correct false
:auto-focus true
:default-value url
:ellipsize :end
:style styles/url-input
:accessibility-label :browser-input}]
[react/touchable-highlight
{:style styles/url-text-container
:on-press #(re-frame/dispatch [:browser.ui/url-input-pressed])}
[react/text {:number-of-lines 1} (url/url-host url-original)]])
(when-not unsafe?
[react/touchable-highlight
{:on-press #(.reload ^js @webview-ref/webview-ref)
:accessibility-label :refresh-page-button}
[icons/icon :main-icons/refresh]])]))
(defn- web-view-error
[_ _ desc]
(reagent/as-element
[react/view styles/web-view-error
[react/image
{:style {:width 140 :height 140 :margin-bottom 16}
:source {:uri
"https://bafybeiabxprplp52amc2hpocar753rd64wk2len55zq54yca77bekzre4e.ipfs.cf-ipfs.com"}}]
[react/i18n-text {:style styles/web-view-error-text :key :web-view-error}]
[react/text {:style styles/web-view-error-text}
(str desc)]]))
(views/defview navigation
[{:keys [url can-go-back? can-go-forward? dapps-account empty-tab browser-id name]}]
(views/letsubs [accounts [:visible-accounts-without-watch-only]]
[react/view (styles/navbar)
[react/touchable-highlight
{:on-press #(if can-go-back?
(re-frame/dispatch [:browser.ui/previous-page-button-pressed])
(do
(re-frame/dispatch [:browser.ui/remove-browser-pressed browser-id])
(re-frame/dispatch [:browser.ui/open-empty-tab])))
:disabled empty-tab
:style (when empty-tab styles/disabled-button)
:accessibility-label :previous-page-button}
[icons/icon :main-icons/arrow-left {:color colors/black}]]
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:browser.ui/next-page-button-pressed])
:disabled (not can-go-forward?)
:style (when-not can-go-forward? styles/disabled-button)
:accessibility-label :next-page-button}
[icons/icon :main-icons/arrow-right {:color colors/black}]]
[react/touchable-highlight
{:accessibility-label :select-account
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
{:content (accounts/accounts-list accounts
dapps-account)}])}
[chat-icon/custom-icon-view-list (:name dapps-account) (:color dapps-account) 32]]
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:browser.ui/open-browser-tabs])
:accessibility-label :browser-open-tabs}
[icons/icon :main-icons/tabs {:color colors/black}]]
(if empty-tab
[react/touchable-highlight
{:accessibility-label :universal-qr-scanner
:on-press #(re-frame/dispatch
[::qr-scanner/scan-code
{:handler ::qr-scanner/on-scan-success}])}
[icons/icon :main-icons/qr {:color colors/black}]]
[react/touchable-highlight
{:on-press #(re-frame/dispatch
[:bottom-sheet/show-sheet-old
{:content (options/browser-options
url
dapps-account
empty-tab
name)}])
:accessibility-label :browser-options}
[icons/icon :main-icons/more {:color colors/black}]])]))
(def resources-to-permissions-map
{"android.webkit.resource.VIDEO_CAPTURE" :camera
"android.webkit.resource.AUDIO_CAPTURE" :record-audio})
(views/defview request-resources-panel
[resources url webview-ref]
[react/view styles/blocked-access-container
[react/view styles/blocked-access-icon-container
[icons/icon :main-icons/camera styles/blocked-access-camera-icon]]
[react/view styles/blocked-access-text-container
[react/text {:style styles/blocked-access-text}
(str url " " (i18n/label :t/page-would-like-to-use-camera))]]
[react/view styles/blocked-access-buttons-container
[react/view styles/blocked-access-button-wrapper
[quo/button
{:theme :positive
:style styles/blocked-access-button
:on-press (fn []
(components.permissions/request-permissions
{:permissions (map resources-to-permissions-map resources)
:on-allowed #(.answerPermissionRequest ^js webview-ref true resources)
:on-denied #(.answerPermissionRequest ^js webview-ref false)})
(re-frame/dispatch [:bottom-sheet/hide-old]))}
(i18n/label :t/allow)]]
[react/view styles/blocked-access-button-wrapper
[quo/button
{:theme :negative
:style styles/blocked-access-button
:on-press (fn []
(.answerPermissionRequest ^js webview-ref false)
(re-frame/dispatch [:bottom-sheet/hide-old]))}
(i18n/label :t/deny)]]]])
(views/defview block-resources-panel
[url]
[react/view styles/blocked-access-container
[react/view styles/blocked-access-icon-container
[icons/icon :main-icons/camera styles/blocked-access-camera-icon]]
[react/view styles/blocked-access-text-container
[react/text {:style styles/blocked-access-text}
(str url " " (i18n/label :t/page-camera-request-blocked))]]])
(defn request-resources-access-for-page
[resources url webview-ref]
(re-frame/dispatch
[:bottom-sheet/show-sheet-old
{:content (fn [] [request-resources-panel resources url webview-ref])
:show-handle? false
:backdrop-dismiss? false
:disable-drag? true
:back-button-cancel false}]))
(defn block-resources-access-and-notify-user
[url]
(.answerPermissionRequest ^js @webview-ref/webview-ref false)
(re-frame/dispatch [:bottom-sheet/show-sheet-old
{:content (fn [] [block-resources-panel url])}]))
;; should-component-update is called only when component's props are changed,
;; that's why it can't be used in `browser`, because `url` comes from subs
(views/defview browser-component
[{:keys [error? url browser-id unsafe? can-go-back? ignore-unsafe
can-go-forward? resolving? network-id url-original dapp? dapp
show-permission show-tooltip name dapps-account resources-permission?]}]
{:should-component-update (fn [_ _ args]
(let [[_ props] args]
(not (nil? (:url props)))))}
[react/view
{:flex 1
:elevation -10}
[react/view {:flex 1}
(if (and unsafe? (not= (url/url-host url) ignore-unsafe))
[site-blocked.views/view
{:can-go-back? can-go-back?
:site browser-id}]
[components.webview/webview
{:dapp? dapp?
:dapp-name name
:ref #(reset! webview-ref/webview-ref %)
:source (when (and url (not resolving?)) {:uri url})
:java-script-enabled true
:bounces false
:local-storage-enabled true
:set-support-multiple-windows false
:render-error web-view-error
:on-navigation-state-change #(do
(re-frame/dispatch [:set-in
[:ens/registration :state]
:searching])
(debounce/debounce-and-dispatch
[:browser/navigation-state-changed % error?]
500))
:on-permission-request #(if resources-permission?
(request-resources-access-for-page
(-> ^js % .-nativeEvent .-resources)
url
@webview-ref/webview-ref)
(block-resources-access-and-notify-user url))
;; Extract event data here due to https://reactjs.org/docs/events.html#event-pooling
:on-message #(re-frame/dispatch [:browser/bridge-message-received
(.. ^js % -nativeEvent -data)])
:on-load #(re-frame/dispatch [:browser/loading-started])
:on-error #(re-frame/dispatch [:browser/error-occured])
:injected-java-script-before-content-loaded (js-res/ethereum-provider (str network-id))}])]
[navigation
{:url url-original
:name name
:can-go-back? can-go-back?
:can-go-forward? can-go-forward?
:dapps-account dapps-account
:browser-id browser-id}]
[permissions.views/permissions-panel [dapp? dapp dapps-account] show-permission]
(when show-tooltip
[tooltip/bottom-tooltip-info
(if (= show-tooltip :secure)
(i18n/label :t/browser-secure)
(i18n/label :t/browser-not-secure))
#(re-frame/dispatch [:browser.ui/close-tooltip-pressed])])])
(views/defview browser
[]
(views/letsubs [window-width [:dimensions/window-width]
{:keys [browser-id dapp? dapp name unsafe? ignore-unsafe secure?] :as current-browser}
[:get-current-browser]
{:keys [url error? loading? url-editing? show-tooltip show-permission resolving?]}
[:browser/options]
dapps-account [:dapps-account]
network-id [:chain-id]
{:keys [webview-allow-permission-requests?]} [:profile/profile]]
(let [can-go-back? (browser/can-go-back? current-browser)
can-go-forward? (browser/can-go-forward? current-browser)
url-original (browser/get-current-url current-browser)]
[react/view {:style styles/browser}
[toolbar-content url url-original secure? url-editing? unsafe?]
[components/separator-dark]
[react/view
(when loading?
[connectivity/loading-indicator-anim window-width])]
[browser-component
{:dapp? dapp?
:dapp dapp
:error? error?
:url url
:url-original url-original
:browser-id browser-id
:unsafe? unsafe?
:ignore-unsafe ignore-unsafe
:can-go-back? can-go-back?
:can-go-forward? can-go-forward?
:resolving? resolving?
:network-id network-id
:show-permission show-permission
:show-tooltip show-tooltip
:name name
:dapps-account dapps-account
:resources-permission? webview-allow-permission-requests?}]])))