<commit_before>(ns status-im.ui.screens.routing.core
  (:require
   [status-im.ui.components.react :as react]
   [status-im.ui.components.styles :as common-styles]
   [status-im.utils.navigation :as navigation]
   [cljs-react-navigation.reagent :as nav-reagent]
   [re-frame.core :as re-frame]
   [taoensso.timbre :as log]
   [status-im.utils.platform :as platform]
   [status-im.utils.core :as utils]
   [status-im.ui.screens.routing.screens :as screens]
   [status-im.ui.screens.routing.intro-login-stack :as intro-login-stack]
   [status-im.ui.screens.routing.chat-stack :as chat-stack]
   [status-im.ui.screens.routing.wallet-stack :as wallet-stack]
   [status-im.ui.screens.routing.profile-stack :as profile-stack]
   [status-im.ui.screens.routing.browser-stack :as browser-stack]
   [status-im.ui.screens.routing.modals :as modals]
   [status-im.ui.components.bottom-bar.core :as bottom-bar]
   [status-im.ui.components.status-bar.view :as status-bar]
   [status-im.ui.components.bottom-bar.styles :as tabs.styles]
   [status-im.react-native.js-dependencies :as js-dependencies]))

(defonce view-id (reagent.core/atom nil))

(defn navigation-events [current-view-id modal? screen-focused?]
  [:> navigation/navigation-events
   {:on-will-focus
    (fn []
      (reset! screen-focused? true)
      (when (not= @view-id current-view-id)
        (reset! view-id current-view-id))
      (log/debug :on-will-focus current-view-id)
      (when modal?
        (status-bar/set-status-bar current-view-id))
      (re-frame/dispatch [:screens/on-will-focus current-view-id]))
    :on-did-focus
    (fn []
      (when-not modal?
        (status-bar/set-status-bar current-view-id)))
    :on-will-blur
    (fn [] (reset! screen-focused? false))}])

(defn wrap
  "Wraps screen with main view and adds navigation-events component"
  [view-id component]
  (fn [args]
    (let [main-view       (react/create-main-screen-view view-id)
          ;; params passed to :navigate-to
          params          (get-in args [:navigation :state :params])
          screen-focused? (reagent.core/atom true)]
      (if platform/ios?
        [main-view (assoc common-styles/flex
                          :margin-bottom
                          (cond
                            ;; there is no need to show bottom nav bar on
                            ;; `intro-login-stack` screens
                            (contains?
                             intro-login-stack/all-screens
                             view-id)
                            0

                            ;; :wallet-onboarding-setup is the only screen
                            ;; except main tabs which requires maximised
                            ;; bottom nav bar, that's why it requires an extra
                            ;; bottom margin, otherwise bottom nav bar will
                            ;; partially cover the screen
                            (contains?
                             #{:wallet-onboarding-setup}
                             view-id)
                            tabs.styles/tabs-height

                            :else
                            tabs.styles/minimized-tabs-height))
         [component params screen-focused?]
         [navigation-events view-id false screen-focused?]]

        [main-view common-styles/flex
         [component params screen-focused?]
         [navigation-events view-id false screen-focused?]]))))

(defn wrap-modal [modal-view component]
  "Wraps modal screen with necessary styling and adds :on-request-close handler
  on Android"
  (fn [args]
    (let [params  (get-in args [:navigation :state :params])
          active? (reagent.core/atom true)]
      (if platform/android?
        [react/view common-styles/modal
         [(react/modal)
          {:transparent      true
           :animation-type   :slide
           :on-request-close (fn []
                               (cond
                                 (#{:wallet-send-transaction-modal
                                    :wallet-sign-message-modal}
                                  modal-view)
                                 (re-frame/dispatch
                                  [:wallet/discard-transaction-navigate-back])

                                 :else
                                 (re-frame/dispatch [:navigate-back])))}
          [react/main-screen-modal-view modal-view
           [component params active?]]
          [navigation-events modal-view true active?]]]
        [react/main-screen-modal-view modal-view
         [component params active?]
         [navigation-events modal-view true active?]]))))

(defn prepare-config [config]
  (-> config
      (utils/update-if-present :initialRouteName name)
      (utils/update-if-present :mode name)))

(defn stack-navigator [routes config]
  (nav-reagent/stack-navigator
   routes
   (cond->
    (merge {:headerMode        "none"
            :cardStyle         {:backgroundColor :white}
            #_:transitionConfig
            #_(fn []
                #js {:transitionSpec #js{:duration 10}})
            :onTransitionStart (fn [n]
                                 (let [idx    (.. n
                                                  -navigation
                                                  -state
                                                  -index)
                                       routes (.. n
                                                  -navigation
                                                  -state
                                                  -routes)]
                                   (when (and (array? routes) (int? idx))
                                     (let [route      (aget routes idx)
                                           route-name (keyword (.-routeName route))]
                                       (bottom-bar/minimize-bar route-name)))))}
           (prepare-config config)))))

(defn switch-navigator [routes config]
  (nav-reagent/switch-navigator
   routes
   (prepare-config config)))

(defn tab-navigator [routes config]
  (nav-reagent/tab-navigator
   routes
   (prepare-config config)))

(declare stack-screens)

(defn build-screen [screen]
  "Builds screen from specified configuration. Currently screen can be
  - keyword, which points to some specific route
  - vector of [:modal :screen-key] type when screen should be wrapped as modal
  - map with `name`, `screens`, `config` keys, where `screens` is a vector
    of children and `config` is `stack-navigator` configuration"
  (let [[screen-name screen-config]
        (cond (keyword? screen)<commit_msg>preload main tabs after login<commit_after>(ns status-im.ui.screens.routing.core
  (:require
   [status-im.ui.components.react :as react]
   [status-im.ui.components.styles :as common-styles]
   [status-im.utils.navigation :as navigation]
   [cljs-react-navigation.reagent :as nav-reagent]
   [re-frame.core :as re-frame]
   [taoensso.timbre :as log]
   [status-im.utils.platform :as platform]
   [status-im.utils.core :as utils]
   [status-im.ui.screens.routing.screens :as screens]
   [status-im.ui.screens.routing.intro-login-stack :as intro-login-stack]
   [status-im.ui.screens.routing.chat-stack :as chat-stack]
   [status-im.ui.screens.routing.wallet-stack :as wallet-stack]
   [status-im.ui.screens.routing.profile-stack :as profile-stack]
   [status-im.ui.screens.routing.browser-stack :as browser-stack]
   [status-im.ui.screens.routing.modals :as modals]
   [status-im.ui.components.bottom-bar.core :as bottom-bar]
   [status-im.ui.components.status-bar.view :as status-bar]
   [status-im.ui.components.bottom-bar.styles :as tabs.styles]
   [status-im.react-native.js-dependencies :as js-dependencies]))

(defonce view-id (reagent.core/atom nil))

(defn navigation-events [current-view-id modal? screen-focused?]
  [:> navigation/navigation-events
   {:on-will-focus
    (fn []
      (reset! screen-focused? true)
      (when (not= @view-id current-view-id)
        (reset! view-id current-view-id))
      (log/debug :on-will-focus current-view-id)
      (when modal?
        (status-bar/set-status-bar current-view-id))
      (re-frame/dispatch [:screens/on-will-focus current-view-id]))
    :on-did-focus
    (fn []
      (when-not modal?
        (status-bar/set-status-bar current-view-id)))
    :on-will-blur
    (fn [] (reset! screen-focused? false))}])

(defn wrap
  "Wraps screen with main view and adds navigation-events component"
  [view-id component]
  (fn [args]
    (let [main-view       (react/create-main-screen-view view-id)
          ;; params passed to :navigate-to
          params          (get-in args [:navigation :state :params])
          screen-focused? (reagent.core/atom true)]
      (if platform/ios?
        [main-view (assoc common-styles/flex
                          :margin-bottom
                          (cond
                            ;; there is no need to show bottom nav bar on
                            ;; `intro-login-stack` screens
                            (contains?
                             intro-login-stack/all-screens
                             view-id)
                            0

                            ;; :wallet-onboarding-setup is the only screen
                            ;; except main tabs which requires maximised
                            ;; bottom nav bar, that's why it requires an extra
                            ;; bottom margin, otherwise bottom nav bar will
                            ;; partially cover the screen
                            (contains?
                             #{:wallet-onboarding-setup}
                             view-id)
                            tabs.styles/tabs-height

                            :else
                            tabs.styles/minimized-tabs-height))
         [component params screen-focused?]
         [navigation-events view-id false screen-focused?]]

        [main-view common-styles/flex
         [component params screen-focused?]
         [navigation-events view-id false screen-focused?]]))))

(defn wrap-modal [modal-view component]
  "Wraps modal screen with necessary styling and adds :on-request-close handler
  on Android"
  (fn [args]
    (let [params  (get-in args [:navigation :state :params])
          active? (reagent.core/atom true)]
      (if platform/android?
        [react/view common-styles/modal
         [(react/modal)
          {:transparent      true
           :animation-type   :slide
           :on-request-close (fn []
                               (cond
                                 (#{:wallet-send-transaction-modal
                                    :wallet-sign-message-modal}
                                  modal-view)
                                 (re-frame/dispatch
                                  [:wallet/discard-transaction-navigate-back])

                                 :else
                                 (re-frame/dispatch [:navigate-back])))}
          [react/main-screen-modal-view modal-view
           [component params active?]]
          [navigation-events modal-view true active?]]]
        [react/main-screen-modal-view modal-view
         [component params active?]
         [navigation-events modal-view true active?]]))))

(defn prepare-config [config]
  (-> config
      (utils/update-if-present :initialRouteName name)
      (utils/update-if-present :mode name)))

(defn stack-navigator [routes config]
  (nav-reagent/stack-navigator
   routes
   (cond->
    (merge {:headerMode        "none"
            :cardStyle         {:backgroundColor :white}
            #_:transitionConfig
            #_(fn []
                #js {:transitionSpec #js{:duration 10}})
            :onTransitionStart (fn [n]
                                 (let [idx    (.. n
                                                  -navigation
                                                  -state
                                                  -index)
                                       routes (.. n
                                                  -navigation
                                                  -state
                                                  -routes)]
                                   (when (and (array? routes) (int? idx))
                                     (let [route      (aget routes idx)
                                           route-name (keyword (.-routeName route))]
                                       (bottom-bar/minimize-bar route-name)))))}
           (prepare-config config)))))

(defn switch-navigator [routes config]
  (nav-reagent/switch-navigator
   routes
   (prepare-config config)))

(defn tab-navigator [routes config]
  (nav-reagent/tab-navigator
   routes
   (assoc (prepare-config config) :lazy false)))

(declare stack-screens)

(defn build-screen [screen]
  "Builds screen from specified configuration. Currently screen can be
  - keyword, which points to some specific route
  - vector of [:modal :screen-key] type when screen should be wrapped as modal
  - map with `name`, `screens`, `config` keys, where `screens` is a vector
    of children and `config` is `stack-navigator` configuration"
  (let [[screen-name screen-config]
        (cond (keyword? screen)
{'fraction_non_alphanumeric': 0.11033076574535569, 'fraction_numerical': 0.00045310376076121433, 'mean_word_length': 1.517680608365019, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 56, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6334117', 'n_tokens_mistral': 3591, 'n_tokens_neox': 3536, 'n_words': 830}