Compare commits

...
6 changed files with 186 additions and 77 deletions
@@ -7,6 +7,7 @@
status-im.contexts.shell.jump-to.effects status-im.contexts.shell.jump-to.effects
[status-im.contexts.shell.jump-to.utils :as shell.utils] [status-im.contexts.shell.jump-to.utils :as shell.utils]
[status-im.navigation.state :as navigation.state] [status-im.navigation.state :as navigation.state]
[status-im.navigation.utils :as navigation.utils]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
;;;; Events ;;;; Events
@@ -149,10 +150,12 @@
(not hidden-screen?) (not hidden-screen?)
(:current-chat-id db)) (:current-chat-id db))
(conj [:chat/close]))}) (conj [:chat/close]))})
{:db (-> db (let [modal-view-ids (navigation.utils/remove-current-modal-stack (:modal-view-ids db))]
(assoc :view-id go-to-view-id) {:navigate-to go-to-view-id
(dissoc :modal-view-ids)) :db (cond-> db
:navigate-to go-to-view-id})) true (assoc :view-id go-to-view-id)
(seq modal-view-ids) (assoc :modal-view-ids modal-view-ids)
(not (seq modal-view-ids)) (dissoc :modal-view-ids))})))
(rf/defn shell-navigate-back (rf/defn shell-navigate-back
{:events [:shell/navigate-back]} {:events [:shell/navigate-back]}
@@ -176,8 +179,11 @@
shell.constants/close-screen-with-slide-to-right-animation))} shell.constants/close-screen-with-slide-to-right-animation))}
(when (and current-chat-id community-id) (when (and current-chat-id community-id)
{:dispatch [:shell/add-switcher-card shell.constants/community-screen community-id]})) {:dispatch [:shell/add-switcher-card shell.constants/community-screen community-id]}))
{:navigate-back nil (let [modal-view-ids (navigation.utils/remove-current-modal-stack (:modal-view-ids db))]
:db (dissoc db :modal-view-ids)}))) {:navigate-back nil
:db (if (seq modal-view-ids)
(assoc db :modal-view-ids modal-view-ids)
(dissoc db :modal-view-ids))}))))
(rf/defn floating-screen-opened (rf/defn floating-screen-opened
{:events [:shell/floating-screen-opened]} {:events [:shell/floating-screen-opened]}
@@ -23,47 +23,52 @@
(defn- address-input (defn- address-input
[input-value input-focused?] [input-value input-focused?]
(fn [] (let [set-value-fn (atom nil)]
(let [current-screen-id (rf/sub [:navigation/current-screen-id]) (fn []
scanned-address (rf/sub [:wallet/scanned-address]) (let [current-screen-id (rf/sub [:navigation/current-screen-id])
send-address (rf/sub [:wallet/wallet-send-to-address]) scanned-address (rf/sub [:wallet/scanned-address])
recipient (rf/sub [:wallet/wallet-send-recipient]) send-address (rf/sub [:wallet/wallet-send-to-address])
recipient-plain-address? (= send-address recipient) recipient (rf/sub [:wallet/wallet-send-recipient])
valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?]) recipient-plain-address? (= send-address recipient)
chain-id (rf/sub [:chain-id]) valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?])
contacts (rf/sub [:contacts/active])] chain-id (rf/sub [:chain-id])
[quo/address-input contacts (rf/sub [:contacts/active])]
{:on-focus #(reset! input-focused? true) (when (and @set-value-fn scanned-address)
:on-blur #(reset! input-focused? false) (@set-value-fn scanned-address)
:on-scan (fn [] (reset! set-value-fn nil))
(rn/dismiss-keyboard!) [quo/address-input
(rf/dispatch [:wallet/clean-scanned-address]) {:on-focus #(reset! input-focused? true)
(rf/dispatch [:open-modal :scan-address])) :on-blur #(reset! input-focused? false)
:ens-regex constants/regx-ens :on-scan (fn [set-value]
:scanned-value (or (when recipient-plain-address? send-address) scanned-address) (reset! set-value-fn set-value)
:address-regex constants/regx-multichain-address (rn/dismiss-keyboard!)
:on-detect-address #(when (or (= current-screen-id :wallet-select-address) (rf/dispatch [:wallet/clean-scanned-address])
(= current-screen-id :scan-address)) (rf/dispatch [:open-modal :scan-address]))
; ^ this check is to prevent effect being triggered when screen is :ens-regex constants/regx-ens
; loaded but not being shown to the user (deep in the navigation :default-value (when recipient-plain-address? send-address)
; stack) and avoid undesired behaviors :address-regex constants/regx-multichain-address
(debounce/debounce-and-dispatch :on-detect-address #(when (or (= current-screen-id :wallet-select-address)
[:wallet/validate-address %] (= current-screen-id :scan-address))
300)) ; ^ this check is to prevent effect being triggered when screen
:on-detect-ens (fn [text cb] ; is loaded but not being shown to the user (deep in the
(when (or (= current-screen-id :wallet-select-address) ; navigation stack) and avoid undesired behaviors
(= current-screen-id :scan-address)) (debounce/debounce-and-dispatch
; ^ this check is to prevent effect being triggered when screen [:wallet/validate-address %]
; is loaded but not being shown to the user (deep in the 300))
; navigation stack) and avoid undesired behaviors :on-detect-ens (fn [text cb]
(debounce/debounce-and-dispatch (when (or (= current-screen-id :wallet-select-address)
[:wallet/find-ens text contacts chain-id cb] (= current-screen-id :scan-address))
300))) ; ^ this check is to prevent effect being triggered when screen
:on-change-text (fn [text] ; is loaded but not being shown to the user (deep in the
(when (empty? text) ; navigation stack) and avoid undesired behaviors
(rf/dispatch [:wallet/clean-local-suggestions])) (debounce/debounce-and-dispatch
(reset! input-value text)) [:wallet/find-ens text contacts chain-id cb]
:valid-ens-or-address? valid-ens-or-address?}]))) 300)))
:on-change-text (fn [text]
(when (empty? text)
(rf/dispatch [:wallet/clean-local-suggestions]))
(reset! input-value text))
:valid-ens-or-address? valid-ens-or-address?}]))))
(defn- ens-linked-address (defn- ens-linked-address
[{:keys [address networks theme]}] [{:keys [address networks theme]}]
+13 -29
View File
@@ -4,6 +4,7 @@
[status-im.contexts.shell.jump-to.events :as shell.events] [status-im.contexts.shell.jump-to.events :as shell.events]
[status-im.contexts.shell.jump-to.state :as shell.state] [status-im.contexts.shell.jump-to.state :as shell.state]
[status-im.contexts.shell.jump-to.utils :as shell.utils] [status-im.contexts.shell.jump-to.utils :as shell.utils]
[status-im.navigation.utils :as navigation.utils]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn- all-screens-params (defn- all-screens-params
@@ -24,23 +25,17 @@
:dispatch-n [[:hide-bottom-sheet]]} :dispatch-n [[:hide-bottom-sheet]]}
(shell.events/shell-navigate-to go-to-view-id screen-params nil nil))) (shell.events/shell-navigate-to go-to-view-id screen-params nil nil)))
(defn- add-view-to-modals
[modal-view-ids new-id]
(if (seq modal-view-ids)
(conj modal-view-ids new-id)
modal-view-ids))
(rf/defn navigate-to-within-stack (rf/defn navigate-to-within-stack
{:events [:navigate-to-within-stack]} {:events [:navigate-to-within-stack]}
[{:keys [db]} comp-id] [{:keys [db]} comp-id]
{:db (update db :modal-view-ids add-view-to-modals (first comp-id)) {:db (update db :modal-view-ids navigation.utils/add-view-to-modal-stack (first comp-id))
:fx [[:navigate-to-within-stack comp-id]]}) :fx [[:navigate-to-within-stack comp-id]]})
(re-frame/reg-event-fx :open-modal (re-frame/reg-event-fx :open-modal
(fn [{:keys [db]} [component screen-params]] (fn [{:keys [db]} [component screen-params]]
{:db (-> db {:db (-> db
(assoc :view-id component) (assoc :view-id component)
(assoc :modal-view-ids [component]) (update :modal-view-ids navigation.utils/add-stack-to-modal-stacks component)
(all-screens-params component screen-params)) (all-screens-params component screen-params))
:fx [[:dispatch [:hide-bottom-sheet]] :fx [[:dispatch [:hide-bottom-sheet]]
[:open-modal-fx component]]})) [:open-modal-fx component]]}))
@@ -48,7 +43,7 @@
(rf/defn dismiss-modal (rf/defn dismiss-modal
{:events [:dismiss-modal]} {:events [:dismiss-modal]}
[{:keys [db]} comp-id] [{:keys [db]} comp-id]
{:db (dissoc db :modal-view-ids) {:db (update db :modal-view-ids navigation.utils/remove-current-modal-stack)
:dismiss-modal comp-id}) :dismiss-modal comp-id})
(rf/defn navigate-back (rf/defn navigate-back
@@ -56,30 +51,17 @@
[cofx] [cofx]
(shell.events/shell-navigate-back cofx nil)) (shell.events/shell-navigate-back cofx nil))
(defn- remove-last-view-to-modals
[modal-view-ids]
(if (seq modal-view-ids)
(pop modal-view-ids)
modal-view-ids))
(rf/defn navigate-back-within-stack (rf/defn navigate-back-within-stack
{:events [:navigate-back-within-stack]} {:events [:navigate-back-within-stack]}
[{:keys [db]} comp-id] [{:keys [db]} comp-id]
{:db (update db :modal-view-ids remove-last-view-to-modals) {:db (update db :modal-view-ids navigation.utils/remove-last-view-from-current-modal-stack)
:fx [[:navigate-back-within-stack comp-id]]}) :fx [[:navigate-back-within-stack comp-id]]})
(defn- remove-modal-views-until-comp-id
[modal-view-ids comp-id]
(let [comp-id-index (.indexOf (or modal-view-ids []) comp-id)
modal-view-ids (if (> comp-id-index -1)
(subvec modal-view-ids 0 (inc comp-id-index))
modal-view-ids)]
modal-view-ids))
(rf/defn navigate-back-to (rf/defn navigate-back-to
{:events [:navigate-back-to]} {:events [:navigate-back-to]}
[{:keys [db]} comp-id] [{:keys [db]} comp-id]
(let [modal-view-ids (remove-modal-views-until-comp-id (:modal-view-ids db) comp-id)] (let [modal-view-ids (navigation.utils/remove-views-from-modal-stack-until-comp-id (:modal-view-ids db)
comp-id)]
(assoc {:navigate-back-to comp-id} (assoc {:navigate-back-to comp-id}
:db :db
(if modal-view-ids (if modal-view-ids
@@ -99,13 +81,15 @@
(rf/defn init-root (rf/defn init-root
{:events [:init-root]} {:events [:init-root]}
[_ root-id] [{:keys [db]} root-id]
{:set-root root-id}) {:set-root root-id
:db (dissoc db :modal-view-ids)})
(rf/defn set-stack-root (rf/defn set-stack-root
{:events [:set-stack-root]} {:events [:set-stack-root]}
[_ stack root] [{:keys [db]} stack root]
{:set-stack-root-fx [stack root]}) {:set-stack-root-fx [stack root]
:db (dissoc db :modal-view-ids)})
(rf/defn change-tab (rf/defn change-tab
{:events [:navigate-change-tab]} {:events [:navigate-change-tab]}
+44
View File
@@ -0,0 +1,44 @@
(ns status-im.navigation.utils)
(defn add-view-to-modal-stack
[modal-view-ids new-id]
(if-let [current-stack (and (seq modal-view-ids) (last modal-view-ids))]
(let [updated-stack (conj current-stack new-id)
without-last (vec (butlast modal-view-ids))]
(conj without-last updated-stack))
modal-view-ids))
(defn remove-last-view-from-current-modal-stack
[modal-view-ids]
(if (empty? modal-view-ids)
modal-view-ids
(let [last-stack (last modal-view-ids)
updated-last-stack (vec (butlast last-stack))
without-last-stack (vec (butlast modal-view-ids))]
(if (empty? updated-last-stack)
without-last-stack
(conj without-last-stack updated-last-stack)))))
(defn add-stack-to-modal-stacks
[modal-view-ids first-view-id]
(if (seq modal-view-ids)
(conj modal-view-ids [first-view-id])
[[first-view-id]]))
(defn remove-current-modal-stack
[modal-view-ids]
(if (seq modal-view-ids)
(vec (butlast modal-view-ids))
[]))
(defn remove-views-from-modal-stack-until-comp-id
[modal-view-ids comp-id]
(let [found-index (first (keep-indexed (fn [idx stack]
(when (some #{comp-id} stack) idx))
modal-view-ids))]
(if found-index
(let [target-stack (nth modal-view-ids found-index)
comp-id-index (.lastIndexOf target-stack comp-id)
updated-stack (take (inc comp-id-index) target-stack)]
(assoc modal-view-ids found-index updated-stack))
modal-view-ids)))
+67
View File
@@ -0,0 +1,67 @@
(ns status-im.navigation.utils-test
(:require [cljs.test :refer [deftest is testing]]
[status-im.navigation.utils :as utils]))
(deftest test-add-view-to-modal-stack
(testing "Add view ID to an empty modal stack"
(is (= (utils/add-view-to-modal-stack [] 1)
[])))
(testing "Add view ID to a non-empty modal stack"
(is (= (utils/add-view-to-modal-stack [[1 2]] 3)
[[1 2 3]])))
(testing "Add view ID when multiple modal stacks exist"
(is (= (utils/add-view-to-modal-stack [[1 2] [3 4]] 5)
[[1 2] [3 4 5]]))))
(deftest test-remove-last-view-from-current-modal-stack
(testing "Remove last view ID from a single-element stack"
(is (= (utils/remove-last-view-from-current-modal-stack [[1]])
[])))
(testing "Remove last view ID from the current modal stack"
(is (= (utils/remove-last-view-from-current-modal-stack [[1 2 3] [4 5 6]])
[[1 2 3] [4 5]])))
(testing "Handle empty modal stacks"
(is (= (utils/remove-last-view-from-current-modal-stack [])
[])))
(testing "Ensure unchanged stack when nested stack is a single element"
(is (= (utils/remove-last-view-from-current-modal-stack [[1 2] [3]])
[[1 2]]))))
(deftest test-add-stack-to-modal-stacks
(testing "Add a new stack to an empty list of modal stacks"
(is (= (utils/add-stack-to-modal-stacks [] 1)
[[1]])))
(testing "Add a new stack to existing modal stacks"
(is (= (utils/add-stack-to-modal-stacks [[1 2]] 3)
[[1 2] [3]])))
(testing "Add a new stack when existing stacks are varied"
(is (= (utils/add-stack-to-modal-stacks [[1 2] [3 4]] 5)
[[1 2] [3 4] [5]]))))
(deftest test-remove-current-modal-stack
(testing "Remove the only modal stack"
(is (= (utils/remove-current-modal-stack [[1 2]])
[])))
(testing "Remove the last modal stack from multiple"
(is (= (utils/remove-current-modal-stack [[1 2] [3 4] [5 6]])
[[1 2] [3 4]])))
(testing "Handle removal when modal stacks are empty"
(is (= (utils/remove-current-modal-stack [])
[])))
(testing "Ensure unchanged when nested stacks have varied lengths"
(is (= (utils/remove-current-modal-stack [[1] [2 3] [4 5 6]])
[[1] [2 3]]))))
(deftest test-remove-views-from-modal-stack-until-comp-id
(testing "Remove views until comp-id, including multiple occurrences"
(is (= (utils/remove-views-from-modal-stack-until-comp-id [[1 2 3] [4 5 5 6]] 5)
[[1 2 3] [4 5 5]])))
(testing "comp-id at the beginning of a stack"
(is (= (utils/remove-views-from-modal-stack-until-comp-id [[1 2] [3 4] [5 6 7]] 5)
[[1 2] [3 4] [5]])))
(testing "comp-id not found, no removal"
(is (= (utils/remove-views-from-modal-stack-until-comp-id [[1 2 3] [4 5 6]] 7)
[[1 2 3] [4 5 6]])))
(testing "comp-id is the last element in a stack"
(is (= (utils/remove-views-from-modal-stack-until-comp-id [[1 2 3] [4 5 6] [7 8 9]] 9)
[[1 2 3] [4 5 6] [7 8 9]]))))
+4 -1
View File
@@ -7,4 +7,7 @@
:<- [:view-id] :<- [:view-id]
:<- [:modal-view-ids] :<- [:modal-view-ids]
(fn [[view-id modal-view-ids]] (fn [[view-id modal-view-ids]]
(or (peek modal-view-ids) view-id))) (or (some-> modal-view-ids
last
last)
view-id)))