From 3241d3273e9d51fbf27b3742cd239fe5693cf27e Mon Sep 17 00:00:00 2001 From: andrey Date: Wed, 9 Dec 2020 16:08:21 +0100 Subject: [PATCH] [#11469] Browser bookmarks Signed-off-by: andrey --- resources/images/icons/tabs@2x.png | Bin 0 -> 487 bytes resources/images/icons/tabs@3x.png | Bin 0 -> 861 bytes src/quo/previews/icons.cljs | 13 ++ src/quo/previews/main.cljs | 8 +- src/status_im/browser/core.cljs | 59 +++++--- src/status_im/browser/core_test.cljs | 18 +-- src/status_im/browser/permissions.cljs | 12 +- src/status_im/ethereum/json_rpc.cljs | 4 + src/status_im/events.cljs | 5 - src/status_im/multiaccounts/login/core.cljs | 11 ++ src/status_im/subs.cljs | 3 +- .../ui/components/connectivity/view.cljs | 3 +- src/status_im/ui/components/tabbar/core.cljs | 2 +- .../ui/screens/browser/bookmarks/views.cljs | 49 +++++++ .../{open_dapp => empty_tab}/styles.cljs | 24 ++-- .../ui/screens/browser/empty_tab/views.cljs | 136 ++++++++++++++++++ .../ui/screens/browser/open_dapp/views.cljs | 111 -------------- .../ui/screens/browser/options/views.cljs | 97 +++++++++++++ src/status_im/ui/screens/browser/styles.cljs | 5 +- .../ui/screens/browser/tabs/views.cljs | 75 ++++++++++ src/status_im/ui/screens/browser/views.cljs | 93 ++++++------ .../ui/screens/routing/browser_stack.cljs | 14 +- src/status_im/ui/screens/routing/main.cljs | 5 + .../ui/screens/wallet/components/styles.cljs | 6 +- .../ui/screens/wallet/components/views.cljs | 5 +- src/status_im/utils/http.cljs | 13 ++ translations/en.json | 15 +- 27 files changed, 566 insertions(+), 220 deletions(-) create mode 100644 resources/images/icons/tabs@2x.png create mode 100644 resources/images/icons/tabs@3x.png create mode 100644 src/quo/previews/icons.cljs create mode 100644 src/status_im/ui/screens/browser/bookmarks/views.cljs rename src/status_im/ui/screens/browser/{open_dapp => empty_tab}/styles.cljs (65%) create mode 100644 src/status_im/ui/screens/browser/empty_tab/views.cljs delete mode 100644 src/status_im/ui/screens/browser/open_dapp/views.cljs create mode 100644 src/status_im/ui/screens/browser/options/views.cljs create mode 100644 src/status_im/ui/screens/browser/tabs/views.cljs diff --git a/resources/images/icons/tabs@2x.png b/resources/images/icons/tabs@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5a76be6f79a7df3bb76fa21778510f0cbfe70fb1 GIT binary patch literal 487 zcmV(vqc!ZANQMw6i5N|+M=md8&`exz#&=0mM5`M?_Ubc;_eFAEnfy*2futM?wV? z6dEAM5ahN{;7kgPkY^(K9TcF?zJ)xNa|lJ++;i3#{3?H=-cl6JO$7#6>WOj1OT<99#|_Plh#MI+L8 zXWe@36y)S=C)omO`>c|*GTsU}K)mw~{M9Wa^j}gB5w&=yEDWCS dof?gQ!w*JcgZ9IAwqXDO002ovPDHLkV1lV_$29-| literal 0 HcmV?d00001 diff --git a/resources/images/icons/tabs@3x.png b/resources/images/icons/tabs@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..76e04ec49383c63e5e88b02bf544954440d34d49 GIT binary patch literal 861 zcmV-j1ETziP) z+b|HtUxE&h4a`oEY|wOrZculErW2T%Al<<32F(IBIzih78fJmSSs)G%vH^qQhb)Uc zecTVYKPbsI^F&g-M=F3I2!bF?jSCwK8*3X6Hnttd^X|L9+E5q}3RT6og=2{U2t{|3 z?(CK+=(lgsQx@P8#*GCEa@OD)YB}En=QcKe+IU2_T-vxoxLbXT)Tt;6{%%FbJ|jPK z_#Xn#=*gJ0LcMZSVTE!i_(fWS83lfE4(sA;$roVc2K5S+=vE=-sMkk>ku~bAha0yQ zW$$L^k#kp0`5*YXcghNxi3#NP@4w*3IAw**oI{8r0woZE5{N(vM4$v?5NLsnj6ooc zxQ9fO$=1%~*t;0b<*rd#Ba{g&aimaF8-wOH{@@5_a*BgAwW>Qb9J}6O_!t{M0_S4R zq_**b6P(FjSqnQf>h)3$J~u~8XL1Z(%rv-WW#gmgTIz1g*axRH1{qW$ZJguRh&Yo| z8>9`Y6%m)*68o%g(cdf(UCw3 z{!If^;S$|#j_~#yh4yGP6ewkP7#p{!{F6fzsu`(9HBffFEImW@PzdEnw`i867DJ=m zcDWp(aXK0ub+JPzp&QF4PK^u#5eoiYXSrjIZXXO9nFQLSP%WiU#dEZ(huwE;~0 zky)TqDnfs}0xud314PjomoyjNk`1SHV3gw+iYBj$w!2jgX#+iI= n82?d;qQU%rs~`x1Ae83~A%kY>>WZBf00000NkvXXu0mjf(W-Zx literal 0 HcmV?d00001 diff --git a/src/quo/previews/icons.cljs b/src/quo/previews/icons.cljs new file mode 100644 index 00000000000..37e8350ed40 --- /dev/null +++ b/src/quo/previews/icons.cljs @@ -0,0 +1,13 @@ +(ns quo.previews.icons + (:require [quo.design-system.colors :as colors] + [quo.react-native :as rn] + [status-im.ui.components.icons.icons :as icons] + [status-im.ui.components.icons.vector-icons :as vector-icons])) + +(defn preview [] + [rn/scroll-view {:background-color (:ui-background @colors/theme) + :flex 1} + (for [i (keys icons/icons)] + [rn/view {:flex-direction :row} + [vector-icons/icon (keyword i)] + [rn/text i]])]) \ No newline at end of file diff --git a/src/quo/previews/main.cljs b/src/quo/previews/main.cljs index 2dd1ca34c14..8e72588a9b1 100644 --- a/src/quo/previews/main.cljs +++ b/src/quo/previews/main.cljs @@ -12,7 +12,8 @@ [reagent.core :as reagent] [quo.design-system.colors :as colors] [quo.theme :as theme] - [status-im.ui.screens.routing.core :as navigation])) + [status-im.ui.screens.routing.core :as navigation] + [quo.previews.icons :as icons])) (def screens [{:name :texts :insets {:top false} @@ -37,7 +38,10 @@ :component bottom-sheet/preview} {:name :controls :insets {:top false} - :component controls/preview}]) + :component controls/preview} + {:name :icons + :insets {:top false} + :component icons/preview}]) (defn theme-switcher [] [rn/view {:style {:flex-direction :row diff --git a/src/status_im/browser/core.cljs b/src/status_im/browser/core.cljs index dbb2aeea60c..034e40f8c49 100644 --- a/src/status_im/browser/core.cljs +++ b/src/status_im/browser/core.cljs @@ -24,7 +24,8 @@ [status-im.multiaccounts.update.core :as multiaccounts.update] [status-im.ui.components.bottom-sheet.core :as bottom-sheet] [status-im.browser.webview-ref :as webview-ref] - ["eth-phishing-detect" :as eth-phishing-detect])) + ["eth-phishing-detect" :as eth-phishing-detect] + [status-im.utils.debounce :as debounce])) (fx/defn update-browser-option [{:keys [db]} option-key option-value] @@ -114,9 +115,9 @@ :cb resolve-ens-contenthash-callback}})) (fx/defn update-browser - [{:keys [db now]} + [{:keys [db]} {:keys [browser-id] :as browser}] - (let [updated-browser (-> (assoc browser :timestamp now) + (let [updated-browser (-> browser (update-dapp-name) (check-if-phishing-url))] {:db (update-in db @@ -126,6 +127,35 @@ :params [(select-keys updated-browser [:browser-id :timestamp :name :dapp? :history :history-index])] :on-success #()}]})) +(fx/defn store-bookmark + {:events [:browser/store-bookmark]} + [{:keys [db]} + {:keys [url] :as bookmark}] + {:db (assoc-in db [:bookmarks/bookmarks url] bookmark) + ::json-rpc/call [{:method "browsers_storeBookmark" + :params [bookmark] + :on-success #()}]}) + +(fx/defn update-bookmark + {:events [:browser/update-bookmark]} + [{:keys [db]} + {:keys [url] :as bookmark}] + {:db (update-in db + [:bookmarks/bookmarks url] + merge bookmark) + ::json-rpc/call [{:method "browsers_updateBookmark" + :params [url bookmark] + :on-success #()}]}) + +(fx/defn delete-bookmark + {:events [:browser/delete-bookmark]} + [{:keys [db]} + url] + {:db (update db :bookmarks/bookmarks dissoc url) + ::json-rpc/call [{:method "browsers_deleteBookmark" + :params [url] + :on-success #()}]}) + (defn can-go-back? [{:keys [history-index]}] (pos? history-index)) @@ -221,7 +251,7 @@ (let [browser (get-current-browser (:db cofx)) options (get-in cofx [:db :browser/options]) current-url (:url options)] - (when (and (not= "about:blank" url) (not= current-url url) (not= (str current-url "/") url)) + (when (and (not (string/blank? url)) (not= "about:blank" url) (not= current-url url) (not= (str current-url "/") url)) (let [resolved-ens (first (filter (fn [v] (not= (.indexOf ^js url (second v)) -1)) (:resolved-ens options))) @@ -417,21 +447,6 @@ (= type constants/api-request) (browser.permissions/process-permission cofx dapp-name permission messageId params)))) -(defn filter-letters-numbers-and-replace-dot-on-dash - [^js value] - (let [cc (.charCodeAt value 0)] - (cond (or (and (> cc 96) (< cc 123)) - (and (> cc 64) (< cc 91)) - (and (> cc 47) (< cc 58))) - value - (= cc 46) - "-"))) - -(fx/defn open-chat-from-browser - [cofx host] - (let [topic (string/lower-case (apply str (map filter-letters-numbers-and-replace-dot-on-dash host)))] - {:dispatch [:chat.ui/start-public-chat topic nil]})) - (re-frame/reg-fx :browser/resolve-ens-content (fn [{:keys [registry ens-name cb]}] @@ -495,3 +510,9 @@ #(when (= (:view-id db) :browser) (merge (navigation/navigate-back %) {:dispatch [:browser.ui/browser-item-selected (get-in db [:browser/options :browser-id])]})))) + +(fx/defn open-empty-tab + {:events [:browser.ui/open-empty-tab]} + [cofx] + (debounce/clear :browser/navigation-state-changed) + (navigation/navigate-to-cofx cofx :empty-tab nil)) \ No newline at end of file diff --git a/src/status_im/browser/core_test.cljs b/src/status_im/browser/core_test.cljs index 2b0adedfc54..34cf4bfb6ac 100644 --- a/src/status_im/browser/core_test.cljs +++ b/src/status_im/browser/core_test.cljs @@ -33,8 +33,7 @@ :history-index 0 :history ["https://cryptokitties.co"] :dapp? false - :name "Browser" - :timestamp 1})) + :name "Browser"})) "some properties of the browser are not correct") (testing "then a second dapp" @@ -49,8 +48,7 @@ {:browser-id dapp2-id :history-index 0 :history ["http://test2.com"] - :dapp? false - :timestamp 2})) + :dapp? false})) "some properties of the browser are not correct") (testing "then removes the second dapp" @@ -70,8 +68,7 @@ :history-index 0 :history ["https://cryptokitties.co"] :dapp? false - :name "Browser" - :timestamp 2})) + :name "Browser"})) "some properties of the browser are not correct") (is (nil? (browser/navigate-to-next-page result-open-existing)) "nothing should happen if user tries to navigate to next page") @@ -91,8 +88,7 @@ :history-index 1 :history ["https://cryptokitties.co" dapp1-url2] :dapp? false - :name "Browser" - :timestamp 4})) + :name "Browser"})) "some properties of the browser are not correct") (testing "then navigates to previous page" @@ -104,8 +100,7 @@ :history-index 0 :history ["https://cryptokitties.co" dapp1-url2] :dapp? false - :name "Browser" - :timestamp 5})) + :name "Browser"})) "some properties of the browser are not correct") (testing "then navigates to next page") @@ -117,6 +112,5 @@ :history-index 1 :history ["https://cryptokitties.co" dapp1-url2] :dapp? false - :name "Browser" - :timestamp 6})) + :name "Browser"})) "some properties of the browser are not correct")))))))))))) diff --git a/src/status_im/browser/permissions.cljs b/src/status_im/browser/permissions.cljs index 38b052f87e5..6da715c457a 100644 --- a/src/status_im/browser/permissions.cljs +++ b/src/status_im/browser/permissions.cljs @@ -70,13 +70,19 @@ :params [allowed-permissions] :on-success #()}]})) -(fx/defn revoke-dapp-permissions +(fx/defn revoke-permissions + {:events [:browser/revoke-dapp-permissions]} [{:keys [db] :as cofx} dapp] (fx/merge cofx - {:db (update-in db [:dapps/permissions] dissoc dapp) + {:db (update-in db [:dapps/permissions] dissoc dapp) ::json-rpc/call [{:method "permissions_deleteDappPermissions" :params [dapp] - :on-success #()}]} + :on-success #()}]})) + +(fx/defn revoke-dapp-permissions + [cofx dapp] + (fx/merge cofx + (revoke-permissions dapp) (navigation/navigate-back))) (fx/defn clear-dapps-permissions diff --git a/src/status_im/ethereum/json_rpc.cljs b/src/status_im/ethereum/json_rpc.cljs index 7a0340bfedb..f5bd1106382 100644 --- a/src/status_im/ethereum/json_rpc.cljs +++ b/src/status_im/ethereum/json_rpc.cljs @@ -127,6 +127,10 @@ "browsers_getBrowsers" {} "browsers_addBrowser" {} "browsers_deleteBrowser" {} + "browsers_getBookmarks" {} + "browsers_storeBookmark" {} + "browsers_updateBookmark" {} + "browsers_deleteBookmark" {} "mailservers_getMailserverRequestGaps" {} "mailservers_addMailserverRequestGaps" {} "mailservers_deleteMailserverRequestGaps" {} diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 89840906919..29ed5310188 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -724,11 +724,6 @@ (fn [cofx [_ url]] (browser/open-url cofx url))) -(handlers/register-handler-fx - :browser.ui/open-modal-chat-button-pressed - (fn [cofx [_ host]] - (browser/open-chat-from-browser cofx host))) - (handlers/register-handler-fx :dapps/revoke-access (fn [cofx [_ dapp]] diff --git a/src/status_im/multiaccounts/login/core.cljs b/src/status_im/multiaccounts/login/core.cljs index a92c772f3c2..c3918dafef4 100644 --- a/src/status_im/multiaccounts/login/core.cljs +++ b/src/status_im/multiaccounts/login/core.cljs @@ -115,6 +115,15 @@ all-stored-browsers)] {:db (assoc db :browser/browsers browsers)})) +(fx/defn initialize-bookmarks + {:events [::initialize-bookmarks]} + [{:keys [db]} stored-bookmarks] + (let [bookmarks (reduce (fn [acc {:keys [url] :as bookmark}] + (assoc acc url bookmark)) + {} + stored-bookmarks)] + {:db (assoc db :bookmarks/bookmarks bookmarks)})) + (fx/defn initialize-invitations {:events [::initialize-invitations]} [{:keys [db]} invitations] @@ -245,6 +254,8 @@ :on-success #(re-frame/dispatch [::protocol/initialize-protocol {:mailserver-ranges (or % {})}])} {:method "browsers_getBrowsers" :on-success #(re-frame/dispatch [::initialize-browsers %])} + {:method "browsers_getBookmarks" + :on-success #(re-frame/dispatch [::initialize-bookmarks %])} {:method "permissions_getDappPermissions" :on-success #(re-frame/dispatch [::initialize-dapp-permissions %])} {:method "mailservers_getMailservers" diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 408d36e31c2..e87727191ec 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -130,6 +130,7 @@ (reg-root-key-sub :browsers :browser/browsers) (reg-root-key-sub :browser/options :browser/options) (reg-root-key-sub :dapps/permissions :dapps/permissions) +(reg-root-key-sub :bookmarks :bookmarks/bookmarks) ;;stickers (reg-root-key-sub :stickers/selected-pack :stickers/selected-pack) @@ -1033,7 +1034,7 @@ :browser/browsers-vals :<- [:browser/browsers] (fn [browsers] - (sort-by :timestamp > (vals browsers)))) + (vals browsers))) (re-frame/reg-sub :get-current-browser diff --git a/src/status_im/ui/components/connectivity/view.cljs b/src/status_im/ui/components/connectivity/view.cljs index 4db305ab77c..21a9be37785 100644 --- a/src/status_im/ui/components/connectivity/view.cljs +++ b/src/status_im/ui/components/connectivity/view.cljs @@ -64,7 +64,8 @@ :top -3 :z-index 3 :height 3 - :background-color colors/white}} + :background-color colors/white} + :accessibility-label :loading-indicator} [react/animated-view {:style (animated-bar-style blue-bar-left-margin parent-width colors/blue)}] diff --git a/src/status_im/ui/components/tabbar/core.cljs b/src/status_im/ui/components/tabbar/core.cljs index 879215a6a2e..0934af88f8c 100644 --- a/src/status_im/ui/components/tabbar/core.cljs +++ b/src/status_im/ui/components/tabbar/core.cljs @@ -18,7 +18,7 @@ (defn main-tab? [view-id] (contains? #{:chat-stack :browser-stack :wallet-stack :profile-stack :status-stack - :status :home :wallet :open-dapp :my-profile :wallet-onboarding-setup} + :status :home :wallet :empty-tab :my-profile :wallet-onboarding-setup} view-id)) (def tabs-list-data diff --git a/src/status_im/ui/screens/browser/bookmarks/views.cljs b/src/status_im/ui/screens/browser/bookmarks/views.cljs new file mode 100644 index 00000000000..b246e4f6c8d --- /dev/null +++ b/src/status_im/ui/screens/browser/bookmarks/views.cljs @@ -0,0 +1,49 @@ +(ns status-im.ui.screens.browser.bookmarks.views + (:require [status-im.ui.components.keyboard-avoid-presentation :as kb-presentation] + [status-im.ui.components.react :as react] + [status-im.ui.components.topbar :as topbar] + [status-im.i18n :as i18n] + [status-im.ui.components.toolbar :as toolbar] + [quo.core :as quo] + [status-im.ui.components.colors :as colors] + [reagent.core :as reagent] + [clojure.string :as string] + [re-frame.core :as re-frame])) + +(defn screen [{:keys [url name new]}] + (let [input-name (reagent/atom name)] + (fn [] + (let [edit? (not new)] + [kb-presentation/keyboard-avoiding-view {:style {:flex 1}} + [react/view {:flex 1} + [topbar/topbar + {:modal? true + :border-bottom true + :title (if edit? (i18n/label :t/edit-favourite) (i18n/label :t/new-favourite))}] + [react/view {:style {:flex 1}} + [quo/text-input + {:container-style {:margin 16 :margin-top 10} + :accessibility-label :bookmark-input + :max-length 100 + :auto-focus true + :show-cancel false + :label (i18n/label :t/name) + :default-value name + :on-change-text #(reset! input-name %)}] + [react/text {:style {:margin 16 :color colors/gray}} + url]] + [toolbar/toolbar + {:show-border? true + :center + [quo/button + {:accessibility-label :save-bookmark + :type :secondary + :disabled (string/blank? @input-name) + :on-press #(do (if edit? + (re-frame/dispatch [:browser/update-bookmark {:url url :name @input-name}]) + (re-frame/dispatch [:browser/store-bookmark {:url url :name @input-name}])) + (re-frame/dispatch [:navigate-back]))} + (if edit? (i18n/label :t/save) (i18n/label :t/add-favourite))]}]]])))) + +(defn new-bookmark [] + [screen @(re-frame/subscribe [:get-screen-params])]) \ No newline at end of file diff --git a/src/status_im/ui/screens/browser/open_dapp/styles.cljs b/src/status_im/ui/screens/browser/empty_tab/styles.cljs similarity index 65% rename from src/status_im/ui/screens/browser/open_dapp/styles.cljs rename to src/status_im/ui/screens/browser/empty_tab/styles.cljs index 4207f31547d..63a021add05 100644 --- a/src/status_im/ui/screens/browser/open_dapp/styles.cljs +++ b/src/status_im/ui/screens/browser/empty_tab/styles.cljs @@ -1,17 +1,13 @@ -(ns status-im.ui.screens.browser.open-dapp.styles - (:require [status-im.ui.components.colors :as colors] - [status-im.ui.components.styles :as components.styles] - [status-im.utils.styles :as styles])) +(ns status-im.ui.screens.browser.empty-tab.styles + (:require [status-im.ui.components.colors :as colors])) -(styles/defn input [] - {:border-radius components.styles/border-radius - :background-color colors/gray-lighter - :margin-horizontal 16 - :margin-bottom 9 - :margin-top 24 - :height 36 - :padding-horizontal 14 - :android {:padding 0}}) +(def input + {:height 36 + :padding 0}) + +(def input-container-style + {:margin-horizontal 16 + :margin-vertical 10}) (defn browser-icon-container [] {:width 40 @@ -24,7 +20,7 @@ (defn dapp-store-container [] {:margin 16 :border-color colors/gray-lighter - :margin-top 8 + :margin-top 18 :border-width 1 :border-radius 12 :padding-vertical 16 diff --git a/src/status_im/ui/screens/browser/empty_tab/views.cljs b/src/status_im/ui/screens/browser/empty_tab/views.cljs new file mode 100644 index 00000000000..b9ca3956b4c --- /dev/null +++ b/src/status_im/ui/screens/browser/empty_tab/views.cljs @@ -0,0 +1,136 @@ +(ns status-im.ui.screens.browser.empty-tab.views + (:require [re-frame.core :as re-frame] + [status-im.i18n :as i18n] + [status-im.react-native.resources :as resources] + [status-im.ui.components.colors :as colors] + [status-im.ui.components.common.common :as components.common] + [status-im.ui.components.icons.vector-icons :as icons] + [quo.core :as quo] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.react :as react] + [status-im.ui.screens.browser.accounts :as accounts] + [status-im.ui.screens.browser.empty-tab.styles :as styles] + [status-im.ui.screens.wallet.components.views :as components] + [status-im.ui.screens.browser.views :as browser] + [status-im.utils.http :as http] + [reagent.core :as reagent]) + (:require-macros [status-im.utils.views :as views])) + +(defn hide-sheet-and-dispatch [event] + (re-frame/dispatch [:bottom-sheet/hide]) + (js/setTimeout #(re-frame/dispatch event) 200)) + +(defn list-item [_] + (let [loaded (reagent/atom nil)] + (fn [{:keys [name url] :as bookmark}] + [quo/list-item + {:accessibility-label (keyword (str "fav-item" name)) + :on-press #(re-frame/dispatch [:browser.ui/open-url url]) + :on-long-press (fn [] + (re-frame/dispatch + [:bottom-sheet/show-sheet + {:content (fn [] + [react/view {:flex 1} + [quo/list-item + {:theme :accent + :title (i18n/label :t/open-in-new-tab) + :accessibility-label :remove-dapp-from-list + :icon :main-icons/tabs + :on-press #(hide-sheet-and-dispatch [:browser.ui/open-url url])}] + [quo/list-item + {:theme :accent + :title (i18n/label :t/edit) + :accessibility-label :remove-dapp-from-list + :icon :main-icons/edit + :on-press #(hide-sheet-and-dispatch [:navigate-to :new-bookmark bookmark])}] + [quo/list-item + {:theme :negative + :title (i18n/label :t/delete) + :accessibility-label :clear-all-dapps + :icon :main-icons/delete + :on-press #(hide-sheet-and-dispatch [:browser/delete-bookmark url])}]])}])) + :title name + :subtitle (or url (i18n/label :t/dapp)) + :icon [react/view {:width 40 + :height 40 + :align-items :center + :justify-content :center} + (when (or (nil? @loaded) @loaded) + [react/image {:onLoad #(reset! loaded true) + :style {:width 32 :height 32 :position :absolute :top 4 :left 4} + :source {:uri (str "https://" (http/url-host url) "/favicon.ico")}}]) + (when-not @loaded + [react/view {:width 40 + :height 40 + :border-radius 20 + :background-color colors/gray-lighter + :align-items :center + :justify-content :center} + [icons/icon :main-icons/browser {:color colors/gray}]])]}]))) + +(def dapp-image-data {:image (resources/get-image :dapp-store) :width 768 :height 333}) +(defn dapp-image [] [components.common/image-contain nil dapp-image-data]) + +(defn list-header [empty?] + [react/view + [react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/open-url "https://dap.ps"])} + [react/view (styles/dapp-store-container) + [dapp-image nil dapp-image-data] + [react/text {:style styles/open-dapp-store} (i18n/label :t/open-dapp-store)] + [react/text {:style {:color colors/blue :font-size 13 :line-height 22}} "https://dap.ps ->"]]] + (when-not empty? + [react/view {:margin-top 14 :margin-left 16 :margin-bottom 4} + [react/text {:style {:line-height 22 :font-size 15 :color colors/gray}} + (i18n/label :t/favourites)]])]) + +(views/defview select-account [] + (views/letsubs [accounts [:accounts-without-watch-only] + {:keys [name color] :as dapps-account} [:dapps-account]] + [react/view {:position :absolute + :z-index 2 + :align-items :center + :bottom 16 + :left 0 + :right 0 + :padding-horizontal 32} + [quo/button + {:accessibility-label :select-account + :type :scale + :on-press #(re-frame/dispatch [:bottom-sheet/show-sheet + {:content (accounts/accounts-list accounts dapps-account)}])} + [react/view (styles/dapps-account color) + [icons/icon :main-icons/account {:color colors/white-persist}] + [react/view {:flex-shrink 1} + [react/text {:numberOfLines 1 + :style {:margin-horizontal 6 :color colors/white-persist + :typography :main-medium}} + name]] + [icons/icon :main-icons/dropdown {:color colors/white-transparent-persist}]]]])) + +(views/defview empty-tab [] + (views/letsubs [bookmarks [:bookmarks] + dapps-account [:dapps-account] + url-text (atom nil)] + (let [bookmarks (vals bookmarks)] + [react/keyboard-avoiding-view {:style {:flex 1}} + [quo/text-input {:on-change-text #(reset! url-text %) + :on-submit-editing #(re-frame/dispatch [:browser.ui/open-url @url-text]) + :placeholder (i18n/label :t/enter-url) + :auto-capitalize :none + :auto-correct false + :style styles/input + :container-style styles/input-container-style + :accessibility-label :dapp-url-input + :return-key-type :go}] + [components/separator-dark] + [list/flat-list {:header [list-header (empty? bookmarks)] + :data bookmarks + :key-fn :browser-id + :empty-component [react/view {:align-items :center :margin-top 20} + [icons/icon :main-icons/favourite {:color colors/gray}] + [react/text {:style {:color colors/gray :margin-top 4}} + (i18n/label :t/favourite-description)]] + :render-fn list-item}] + [browser/navigation + {:dapps-account dapps-account + :empty-tab true}]]))) diff --git a/src/status_im/ui/screens/browser/open_dapp/views.cljs b/src/status_im/ui/screens/browser/open_dapp/views.cljs deleted file mode 100644 index 0479778473c..00000000000 --- a/src/status_im/ui/screens/browser/open_dapp/views.cljs +++ /dev/null @@ -1,111 +0,0 @@ -(ns status-im.ui.screens.browser.open-dapp.views - (:require [re-frame.core :as re-frame] - [status-im.i18n :as i18n] - [status-im.react-native.resources :as resources] - [status-im.ui.components.colors :as colors] - [status-im.ui.components.common.common :as components.common] - [status-im.ui.components.icons.vector-icons :as icons] - [quo.core :as quo] - [status-im.ui.components.list.views :as list] - [status-im.ui.components.react :as react] - [status-im.ui.screens.browser.accounts :as accounts] - [status-im.ui.screens.browser.open-dapp.styles :as styles] - [status-im.ui.screens.wallet.components.views :as components]) - (:require-macros [status-im.utils.views :as views])) - -(defn hide-sheet-and-dispatch [event] - (re-frame/dispatch [:bottom-sheet/hide]) - (re-frame/dispatch event)) - -(defn list-item [{:keys [browser-id name url]}] - [quo/list-item - {:on-press #(re-frame/dispatch [:browser.ui/browser-item-selected browser-id]) - :on-long-press (fn [] - (re-frame/dispatch - [:bottom-sheet/show-sheet - {:content (fn [] - [react/view {:flex 1} - [quo/list-item - {:theme :accent - :title (i18n/label :t/remove) - :accessibility-label :remove-dapp-from-list - :icon :main-icons/delete - :on-press #(hide-sheet-and-dispatch [:browser.ui/remove-browser-pressed browser-id])}] - [quo/list-item - {:theme :negative - :title (i18n/label :t/clear-all) - :accessibility-label :clear-all-dapps - :icon :main-icons/delete - :on-press #(hide-sheet-and-dispatch [:browser.ui/clear-all-browsers-pressed])}]]) - :content-height 128}])) - :title name - :subtitle (or url (i18n/label :t/dapp)) - :icon [react/view (styles/browser-icon-container) - [icons/icon :main-icons/browser {:color colors/gray}]]}]) - -(def dapp-image-data {:image (resources/get-image :dapp-store) :width 768 :height 333}) -(defn dapp-image [] [components.common/image-contain nil dapp-image-data]) - -(defn list-header [empty?] - [react/view (when empty? {:flex 1}) - [react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/open-url "https://dap.ps"])} - [react/view (styles/dapp-store-container) - [dapp-image nil dapp-image-data] - [react/text {:style styles/open-dapp-store} (i18n/label :t/open-dapp-store)] - [react/text {:style {:color colors/blue :font-size 13 :line-height 22}} "https://dap.ps ->"]]] - (if empty? - [react/view {:flex 1 :align-items :center :justify-content :center} - [react/text {:style {:color colors/gray :font-size 15}} (i18n/label :t/browsed-websites)]] - [react/view {:margin-top 14 :margin-left 16 :margin-bottom 4} - [react/text {:style {:line-height 22 :font-size 15 :color colors/gray}} - (i18n/label :t/recent)]])]) - -(views/defview select-account [] - (views/letsubs [accounts [:accounts-without-watch-only] - {:keys [name color] :as dapps-account} [:dapps-account]] - [react/view {:position :absolute - :z-index 2 - :align-items :center - :bottom 16 - :left 0 - :right 0 - :padding-horizontal 32} - [quo/button - {:accessibility-label :select-account - :type :scale - :on-press #(re-frame/dispatch [:bottom-sheet/show-sheet - {:content (accounts/accounts-list accounts dapps-account)}])} - [react/view (styles/dapps-account color) - [icons/icon :main-icons/account {:color colors/white-persist}] - [react/view {:flex-shrink 1} - [react/text {:numberOfLines 1 - :style {:margin-horizontal 6 :color colors/white-persist - :typography :main-medium}} - name]] - [icons/icon :main-icons/dropdown {:color colors/white-transparent-persist}]]]])) - -(views/defview open-dapp [] - (views/letsubs [browsers [:browser/browsers-vals] - url-text (atom nil)] - [react/keyboard-avoiding-view {:style {:flex 1}} - [react/text-input {:on-change-text #(reset! url-text %) - :on-submit-editing #(re-frame/dispatch [:browser.ui/open-url @url-text]) - :placeholder (i18n/label :t/enter-url) - :auto-capitalize :none - :auto-correct false - :style (styles/input) - :accessibility-label :dapp-url-input - :return-key-type :go}] - [components/separator] - (if (empty? browsers) - [list-header true] - [react/scroll-view - [list-header false] - [list/flat-list {:data browsers - :footer [react/view - {:style {:height 64 - :align-self :stretch}}] - :key-fn :browser-id - :end-fill-color colors/white - :render-fn list-item}]]) - [select-account]])) diff --git a/src/status_im/ui/screens/browser/options/views.cljs b/src/status_im/ui/screens/browser/options/views.cljs new file mode 100644 index 00000000000..15475ce17e0 --- /dev/null +++ b/src/status_im/ui/screens/browser/options/views.cljs @@ -0,0 +1,97 @@ +(ns status-im.ui.screens.browser.options.views + (:require [status-im.ui.components.react :as react] + [quo.core :as quo] + [status-im.i18n :as i18n] + [re-frame.core :as re-frame] + [status-im.ui.components.chat-icon.screen :as chat-icon] + [status-im.ui.components.colors :as colors] + [status-im.ui.screens.wallet.components.views :as components] + [status-im.browser.core :as browser] + [status-im.utils.http :as http] + [status-im.utils.utils :as utils] + [status-im.ui.components.icons.vector-icons :as icons] + [status-im.constants :as constants])) + +(defn hide-sheet-and-dispatch [event] + (re-frame/dispatch [:bottom-sheet/hide]) + (re-frame/dispatch event)) + +(defn wallet-connection [host account] + (fn [] + [react/view {:flex 1} + [react/text {:style {:align-self :center :margin-horizontal 16 :margin-vertical 8}} + (str "“" host "” " (i18n/label :t/has-permissions))] + [quo/list-item + {:icon [chat-icon/custom-icon-view-list (:name account) (:color account)] + :title (:name account) + :subtitle (utils/get-shortened-checksum-address (:address account)) + :accessory [icons/icon :main-icons/check {:color colors/gray}]}] + [react/view {:padding-vertical 8} + [components/separator]] + [quo/list-item + {:theme :negative + :title (i18n/label :t/revoke-access) + :accessibility-label :revoke-access + :icon :main-icons/cancel + :on-press #(hide-sheet-and-dispatch [:browser/revoke-dapp-permissions host])}]])) + +(defn browser-options [url account empty-tab name] + (fn [] + (let [topic (http/topic-from-url url) + bookmarks @(re-frame/subscribe [:bookmarks]) + permissions @(re-frame/subscribe [:dapps/permissions]) + fav? (get bookmarks url) + connected? (some #{constants/dapp-permission-web3} (get-in permissions [(http/url-host url) :permissions]))] + [react/view {:flex 1} + (when-not empty-tab + [:<> + [quo/list-item + {:theme :accent + :title (i18n/label :t/new-tab) + :accessibility-label :new-tab + :icon :main-icons/add + :on-press #(hide-sheet-and-dispatch [:browser.ui/open-empty-tab])}] + [quo/list-item + {:theme :accent + :title (if fav? (i18n/label :t/remove-favourite) (i18n/label :t/add-favourite)) + :accessibility-label :add-remove-fav + :icon (if fav? :main-icons/delete :main-icons/favourite) + :on-press #(hide-sheet-and-dispatch (if fav? + [:browser/delete-bookmark url] + [:navigate-to :new-bookmark {:url url :name name :new true}]))}] + [quo/list-item + {:theme :accent + :title (i18n/label :t/share) + :accessibility-label :share + :icon :main-icons/share + :on-press (fn [] + (re-frame/dispatch-sync [:bottom-sheet/hide]) + (js/setTimeout + #(browser/share-link url) + 200))}] + [quo/list-item + {:icon [chat-icon/custom-icon-view-list + topic + (rand-nth colors/chat-colors)] + :accessibility-label :open-chat + :title (str "#" topic) + :subtitle (i18n/label :t/open-chat) + :on-press #(hide-sheet-and-dispatch [:chat.ui/start-public-chat topic nil]) + :chevron true}] + [components/separator]]) + (if connected? + [quo/list-item + {:icon [chat-icon/custom-icon-view-list (:name account) (:color account)] + :title (:name account) + :subtitle (i18n/label :t/connected) + :accessibility-label :connected-account + :chevron true + :on-press #(hide-sheet-and-dispatch [:bottom-sheet/show-sheet + {:content (wallet-connection (http/url-host url) account)}])}] + [quo/list-item + {:theme :accent + :title (i18n/label :t/connect-wallet) + :accessibility-label :connect-account + :icon :main-icons/wallet + :on-press #(hide-sheet-and-dispatch [:browser/bridge-message-received + "{\"type\":\"api-request\",\"permission\":\"web3\"}"])}])]))) diff --git a/src/status_im/ui/screens/browser/styles.cljs b/src/status_im/ui/screens/browser/styles.cljs index c142c4dfeba..b3809da4f39 100644 --- a/src/status_im/ui/screens/browser/styles.cljs +++ b/src/status_im/ui/screens/browser/styles.cljs @@ -11,7 +11,7 @@ :justify-content :space-between :border-top-color colors/gray-lighter :border-top-width 1 - :padding-horizontal 32}) + :padding-horizontal 24}) (def disabled-button {:opacity 0.4}) @@ -41,7 +41,8 @@ :padding-horizontal 10 :align-items :center :align-self :center - :margin-top 10}) + :margin-horizontal 16 + :margin-vertical 10}) (def url-input {:flex 1 diff --git a/src/status_im/ui/screens/browser/tabs/views.cljs b/src/status_im/ui/screens/browser/tabs/views.cljs new file mode 100644 index 00000000000..2e02e7ddc46 --- /dev/null +++ b/src/status_im/ui/screens/browser/tabs/views.cljs @@ -0,0 +1,75 @@ +(ns status-im.ui.screens.browser.tabs.views + (:require-macros [status-im.utils.views :as views]) + (:require [status-im.ui.components.react :as react] + [status-im.ui.components.topbar :as topbar] + [status-im.i18n :as i18n] + [status-im.ui.components.colors :as colors] + [status-im.ui.components.plus-button :as components.plus-button] + [status-im.ui.components.list.views :as list] + [quo.core :as quo] + [status-im.ui.components.icons.vector-icons :as icons] + [status-im.ui.screens.wallet.components.views :as components] + [re-frame.core :as re-frame] + [status-im.utils.http :as http] + [reagent.core :as reagent])) + +(defn list-item [_] + (let [loaded (reagent/atom nil)] + (fn [{:keys [browser-id name url empty-tab]}] + [react/view {:flex-direction :row :flex 1} + [react/view {:flex 1} + [quo/list-item + {:on-press #(if empty-tab + (re-frame/dispatch [:browser.ui/open-empty-tab]) + (re-frame/dispatch [:browser.ui/browser-item-selected browser-id])) + :title name + :subtitle (when-not empty-tab (or url (i18n/label :t/dapp))) + :accessibility-label (keyword (str "tab-item" name)) + :icon [react/view {:width 40 + :height 40 + :align-items :center + :justify-content :center} + (when (or (nil? @loaded) @loaded) + [react/image {:onLoad #(reset! loaded true) + :style {:width 32 :height 32 :position :absolute :top 4 :left 4} + :source {:uri (str "https://" (http/url-host url) "/favicon.ico")}}]) + (when-not @loaded + [react/view {:width 40 + :height 40 + :border-radius 20 + :background-color colors/gray-lighter + :align-items :center + :justify-content :center} + [icons/icon :main-icons/browser {:color colors/gray}]])]}]] + (when-not empty-tab + [react/touchable-highlight + {:style {:width 60 :justify-content :center :align-items :center} + :accessibility-label :empty-tab + :on-press #(re-frame/dispatch [:browser.ui/remove-browser-pressed browser-id])} + [icons/icon :main-icons/close-circle {:color colors/gray}]])]))) + +(views/defview tabs [] + (views/letsubs [browsers [:browser/browsers-vals]] + [react/view {:flex 1} + [topbar/topbar + {:modal? true + :border-bottom false + :navigation :none + :right-accessories + [{:label (i18n/label :t/close-all) + :accessibility-label :close-all + :on-press #(do (re-frame/dispatch [:browser.ui/clear-all-browsers-pressed]) + (re-frame/dispatch [:browser.ui/open-empty-tab]))}] + :title (i18n/label :t/tabs)}] + [components/separator-dark] + [list/flat-list {:data (conj browsers {:empty-tab true + :name (i18n/label :t/empty-tab) + :url ""}) + :footer [react/view + {:style {:height 64 + :align-self :stretch}}] + :key-fn :browser-id + :render-fn list-item}] + + [components.plus-button/plus-button + {:on-press #(re-frame/dispatch [:browser.ui/open-empty-tab])}]])) \ No newline at end of file diff --git a/src/status_im/ui/screens/browser/views.cljs b/src/status_im/ui/screens/browser/views.cljs index cc228febf6d..ccdad9b64f7 100644 --- a/src/status_im/ui/screens/browser/views.cljs +++ b/src/status_im/ui/screens/browser/views.cljs @@ -10,7 +10,6 @@ [status-im.ui.components.icons.vector-icons :as icons] [status-im.ui.components.react :as react] [status-im.ui.components.styles :as components.styles] - [status-im.ui.components.topbar :as topbar] [status-im.ui.components.tooltip.views :as tooltip] [status-im.ui.components.webview :as components.webview] [status-im.ui.screens.browser.accounts :as accounts] @@ -22,13 +21,16 @@ [status-im.utils.js-resources :as js-res] [status-im.utils.contenthash :as contenthash] [status-im.ui.components.permissions :as components.permissions] - [quo.core :as quo]) + [quo.core :as quo] + [status-im.ui.screens.wallet.components.views :as components] + [status-im.ui.screens.browser.options.views :as options]) (:require-macros [status-im.utils.views :as views])) -(defn toolbar-content [url url-original {:keys [secure?]} url-editing? unsafe?] +(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?])} + [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/dark}])] @@ -42,7 +44,8 @@ :auto-focus true :default-value url :ellipsize :end - :style styles/url-input}] + :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} (http/url-host url-original)]]) @@ -51,19 +54,6 @@ :accessibility-label :refresh-page-button} [icons/icon :main-icons/refresh]])])) -(defn toolbar [error? url url-original browser browser-id url-editing? unsafe?] - [topbar/topbar - {:navigation {:icon :main-icons/close - :on-press (fn [] - (debounce/clear :browser/navigation-state-changed) - (re-frame/dispatch [:navigate-back]) - (when error? - (re-frame/dispatch [:browser.ui/remove-browser-pressed browser-id])))} - :title-align :left - :title-component - [react/view {:flex 1} - [toolbar-content url url-original browser url-editing? unsafe?]]}]) - (defn- web-view-error [_ _ desc] (reagent/as-element [react/view styles/web-view-error @@ -74,13 +64,16 @@ [react/text {:style styles/web-view-error-text} (str desc)]])) -(views/defview navigation [url can-go-back? can-go-forward? dapps-account] - (views/letsubs [height [:dimensions/window-height] - accounts [:accounts-without-watch-only]] +(views/defview navigation [{:keys [url can-go-back? can-go-forward? dapps-account empty-tab browser-id name]}] + (views/letsubs [accounts [:accounts-without-watch-only]] [react/view (styles/navbar) - [react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/previous-page-button-pressed]) - :disabled (not can-go-back?) - :style (when-not can-go-back? styles/disabled-button) + [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} [react/view [icons/icon :main-icons/arrow-left]]] @@ -90,20 +83,32 @@ :accessibility-label :next-page-button} [react/view [icons/icon :main-icons/arrow-right]]] - [react/touchable-highlight - {:on-press #(browser/share-link url) - :accessibility-label :modal-share-link-button} - [icons/icon :main-icons/share]] [react/touchable-highlight {:accessibility-label :select-account :on-press #(re-frame/dispatch [:bottom-sheet/show-sheet - {:content (accounts/accounts-list accounts dapps-account) - :content-height (/ height 2)}])} + {: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 #(do + (when empty-tab + (re-frame/dispatch [:navigate-to :browser])) + (re-frame/dispatch [:navigate-to :browser-tabs])) + :accessibility-label :browser-open-tabs} + [icons/icon :main-icons/tabs]] + [react/touchable-highlight - {:on-press #(re-frame/dispatch [:browser.ui/open-modal-chat-button-pressed (http/url-host url)]) - :accessibility-label :modal-chat-button} - [icons/icon :main-icons/message]]])) + {:on-press #(when-not empty-tab + (re-frame/dispatch + [:bottom-sheet/show-sheet + {:content (options/browser-options + url + dapps-account + empty-tab + name)}])) + :style (when empty-tab styles/disabled-button) + :accessibility-label :browser-options} + [icons/icon :main-icons/more]]])) (def resources-to-permissions-map {"android.webkit.resource.VIDEO_CAPTURE" :camera "android.webkit.resource.AUDIO_CAPTURE" :record-audio}) @@ -161,9 +166,9 @@ ;; 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 browser-id unsafe? can-go-back? ignore-unsafe - can-go-forward? resolving? network-id url-original - show-permission show-tooltip dapp? name dapps-account resources-permission?]}] + [{: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)))))} @@ -197,8 +202,13 @@ :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-original can-go-back? can-go-forward? dapps-account] - [permissions.views/permissions-panel [(:dapp? browser) (:dapp browser) dapps-account] show-permission] + [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) @@ -208,7 +218,7 @@ (views/defview browser [] (views/letsubs [window-width [:dimensions/window-width] - {:keys [browser-id dapp? name unsafe? ignore-unsafe] :as browser} [:get-current-browser] + {:keys [browser-id dapp? dapp name unsafe? ignore-unsafe secure?] :as 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] @@ -217,15 +227,16 @@ can-go-forward? (browser/can-go-forward? browser) url-original (browser/get-current-url browser)] [react/view {:style styles/browser} - [toolbar error? url url-original browser browser-id url-editing? unsafe?] + [toolbar-content url url-original secure? url-editing? unsafe?] + [components/separator-dark] [react/view (when loading? [connectivity/loading-indicator window-width])] [browser-component {:dapp? dapp? + :dapp dapp :error? error? :url url :url-original url-original - :browser browser :browser-id browser-id :unsafe? unsafe? :ignore-unsafe ignore-unsafe diff --git a/src/status_im/ui/screens/routing/browser_stack.cljs b/src/status_im/ui/screens/routing/browser_stack.cljs index 3c9fec61e36..d8e1e053808 100644 --- a/src/status_im/ui/screens/routing/browser_stack.cljs +++ b/src/status_im/ui/screens/routing/browser_stack.cljs @@ -1,19 +1,23 @@ (ns status-im.ui.screens.routing.browser-stack (:require [status-im.ui.screens.routing.core :as navigation] - [status-im.ui.screens.browser.open-dapp.views :as open-dapp] + [status-im.ui.screens.browser.empty-tab.views :as empty-tab] [status-im.ui.screens.browser.views :as browser] + [status-im.ui.screens.browser.tabs.views :as browser.tabs] [status-im.ui.components.tabbar.styles :as tabbar.styles])) (defonce stack (navigation/create-stack)) (defn browser-stack [] - [stack {:initial-route-name :open-dapp + [stack {:initial-route-name :empty-tab :header-mode :none} - [{:name :open-dapp + [{:name :empty-tab :insets {:top true} :style {:padding-bottom tabbar.styles/tabs-diff} - :component open-dapp/open-dapp} + :component empty-tab/empty-tab} {:name :browser :back-handler :noop :options {:animationEnabled false} - :component browser/browser}]]) + :component browser/browser} + {:name :browser-tabs + :insets {:top true} + :component browser.tabs/tabs}]]) diff --git a/src/status_im/ui/screens/routing/main.cljs b/src/status_im/ui/screens/routing/main.cljs index 004f6fd4c24..3de1e13c9c7 100644 --- a/src/status_im/ui/screens/routing/main.cljs +++ b/src/status_im/ui/screens/routing/main.cljs @@ -26,6 +26,7 @@ [status-im.ui.screens.wallet.send.views :as wallet] [status-im.ui.screens.link-previews-settings.views :as link-previews] [status-im.ui.screens.status.new.views :as status.new] + [status-im.ui.screens.browser.bookmarks.views :as bookmarks] [status-im.ui.screens.routing.status-stack :as status-stack])) (defonce main-stack (navigation/create-stack)) @@ -145,6 +146,10 @@ :transition :presentation-ios :insets {:bottom true} :component status.new/my-status} + {:name :new-bookmark + :transition :presentation-ios + :insets {:bottom true} + :component bookmarks/new-bookmark} {:name :profile :transition :presentation-ios :insets {:bottom true} diff --git a/src/status_im/ui/screens/wallet/components/styles.cljs b/src/status_im/ui/screens/wallet/components/styles.cljs index 1d3b25d734f..3fa8dd4712e 100644 --- a/src/status_im/ui/screens/wallet/components/styles.cljs +++ b/src/status_im/ui/screens/wallet/components/styles.cljs @@ -3,4 +3,8 @@ (defn separator [] {:height 1 - :background-color colors/gray-lighter}) \ No newline at end of file + :background-color colors/gray-lighter}) + +(defn separator-dark [] + {:height 1 + :background-color colors/black-transparent}) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/components/views.cljs b/src/status_im/ui/screens/wallet/components/views.cljs index c6e77a1e178..46c3cfb42a0 100644 --- a/src/status_im/ui/screens/wallet/components/views.cljs +++ b/src/status_im/ui/screens/wallet/components/views.cljs @@ -3,4 +3,7 @@ [status-im.ui.screens.wallet.components.styles :as styles])) (defn separator [] - [react/view (styles/separator)]) \ No newline at end of file + [react/view (styles/separator)]) + +(defn separator-dark [] + [react/view (styles/separator-dark)]) \ No newline at end of file diff --git a/src/status_im/utils/http.cljs b/src/status_im/utils/http.cljs index 1fa7d3f8a4b..a04741e10e5 100644 --- a/src/status_im/utils/http.cljs +++ b/src/status_im/utils/http.cljs @@ -156,3 +156,16 @@ (mapcat split-param) (map url-decode) (apply hash-map)))) + +(defn filter-letters-numbers-and-replace-dot-on-dash + [^js value] + (let [cc (.charCodeAt value 0)] + (cond (or (and (> cc 96) (< cc 123)) + (and (> cc 64) (< cc 91)) + (and (> cc 47) (< cc 58))) + value + (= cc 46) + "-"))) + +(defn topic-from-url [url] + (string/lower-case (apply str (map filter-letters-numbers-and-replace-dot-on-dash (url-host url))))) \ No newline at end of file diff --git a/translations/en.json b/translations/en.json index 50b305aa66a..26b2d937400 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1292,8 +1292,12 @@ "membership-description": "Group membership requires you to be accepted by the group admin", "group-membership-request": "Group membership request", "members-limit-reached": "Members limit reached", + "favourite": "Favourite", "favourites": "Favourites", "new-favourite": "New favourite", + "edit-favourite": "Edit favourite", + "remove-favourite": "Remove favourite", + "add-favourite": "Add favourite", "add-to-favourites": "Add to favourites", "favourites-empty": "Addresses added to favourites will appear here", "contacts-empty": "Contacts with ENS names will appear here", @@ -1331,5 +1335,14 @@ "default-assets": "Default ERC20 and ERC721", "increase-gas": "Increase Gas", "cancelling": "Cancelling", - "refresh": "Refresh" + "refresh": "Refresh", + "close-all": "Close all", + "tabs": "Tabs", + "new-tab": "New tab", + "empty-tab": "Empty tab", + "open-in-new-tab": "Open in new tab", + "has-permissions": "has permission to access", + "connect-wallet": "Connect wallet", + "open-chat": "Open chat", + "favourite-description": "Your favourite websites will appear here" }