Skip to content

Instantly share code, notes, and snippets.

@puppybits
Created February 21, 2018 00:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save puppybits/e4a71e016f1ec3ed76308cf5b23b4fe8 to your computer and use it in GitHub Desktop.
Save puppybits/e4a71e016f1ec3ed76308cf5b23b4fe8 to your computer and use it in GitHub Desktop.
ClojureScript fix for ReactNative.NavigationIOS
(ns ios.navigation
"Translation for ReactNative.NavigatorIOS API. The core
issues this addresses is the previous stack item doesn't
re-render on pop and each component inside a navigation
stack needs to read it's props differently. This wrapper
keeps all the props the same and only assoc in a `react/navigation`
prop to push, pop, popToRoot."
(:require [om.next :as om :refer-macros [defui]]
[cljs.spec.alpha :as s]
[fskl.ui :as ui]))
(declare style)
(declare render)
(declare StackWrapper)
; ---- navigation event fixes -----
(defn- route-wrapper
"Wraps a route in a Component wrapper and props wrapper.
Component wraps store previos state and provides a normal
React interface. Props need to be wrapper b/c React Native
is removing non-js objects."
([route] (route-wrapper route nil))
([route pre-route]
(let [js-props
#js{:om_props
(merge
(dissoc route :_previous-route)
(when pre-route {:_previous-route pre-route}))}]
#js{:component StackWrapper
:title (get route :title "")
:passProps js-props})))
(defn- _replacePreviousAndPop
"Wrappee component can pass props that go back to the parent."
([nav] ((:pop nav)))
([nav pre-route] ((:pop nav)))
([nav pre-route props]
((:replacePreviousAndPop nav)
(route-wrapper
(assoc pre-route :passProps
(merge (:passProps pre-route) props))))))
(defn- _push
[nav current-route new-route]
((:push nav)
(route-wrapper new-route current-route)))
(defn- _replace
[nav new-route]
((:replace nav)
(route-wrapper new-route)))
;; ----- Wrapper -----
(defui StackWrapper
"Wrap and unwrap props to remove NavigatorIOS weirdness."
Object
(shouldComponentUpdate [this] true)
(render [this]
(let [{:keys [navigator
push
pop
popN
replace
replaceAtIndex
replacePrevious
replacePreviousAndPop
resetTo
popToRoute
popToTop
route
om_props]
:as nav-props} (js->clj (aget this "props") :keywordize-keys true)
{:keys [component _previous-route]} om_props
current-route (select-keys om_props [:component :title :passProps])]
(component
(merge
(get om_props :passProps)
{:react/navigation
#js{:push (partial _push navigator current-route)
:pop (partial _replacePreviousAndPop navigator _previous-route)
:popToTop (fn [] ((:popToTop navigator)))
:replace (partial _replace navigator)}})))))
(def stack-wrapper (om/factory StackWrapper))
;; ------ Navigation -----
(defui Navigation
"Navigation"
Object
(render [this]
(ui/el ui/ReactNative.NavigatorIOS
((:nav-root style)
{:initialRoute
(route-wrapper
(:initialRoute (om/props this)))}))))
(def navigator (om/factory Navigation))
; ----- style -----
(def style
{:nav-root
(partial merge-with into
{:navigationBarHidden true
:shadowHidden true
:translucent true
:style {:flex 1
:marginTop -1}})}) ; hack-fix for nav jumping
(def fnc? nil?)
(s/def ::component fnc?)
(s/def ::title string?)
(s/def ::titleImage (partial instance? js/Object))
(s/def ::passProps map?)
(s/def ::backButtonIcon string?)
(s/def ::backButtonTitle string?)
(s/def ::leftButtonIcon string?)
(s/def ::leftButtonTitle string?)
(s/def ::leftButtonSystemIcon string?)
(s/def ::onLeftButtonPress fnc?)
(s/def ::rightButtonIcon string?)
(s/def ::rightButtonTitle string?)
(s/def ::rightButtonSystemIcon string?)
(s/def ::onRightButtonPress string?)
(s/def ::wrapperStyle map?)
(s/def ::barStyle #{"default" "black"})
(s/def ::barTintColor string?)
(s/def ::interactivePopGestureEnabled boolean?)
(s/def ::itemWrapperStyle map?)
(s/def ::navigationBarHidden boolean?)
(s/def ::shadowHidden boolean?)
(s/def ::tintColor string?)
(s/def ::titleTextColor string?)
(s/def ::translucent boolean?)
(s/def ::initialRoute
(s/keys :req [::component]
:opt [::title ::titleImage ::passProps ::backButtonIcon
::backButtonTitle ::leftButtonIcon ::leftButtonTitle
::leftButtonSystemIcon ::onLeftButtonPress
::rightButtonIcon ::rightButtonTitle ::rightButtonSystemIcon
::onRightButtonPress ::wrapperStyle
::barStyle ::barTintColor
::interactivePopGestureEnabled ::itemWrapperStyle
::navigationBarHidden ::shadowHidden ::tintColor
::titleTextColor ::translucent]))
(s/def ::navigation
(s/keys :req [::initialRoute]
:opt [::barStyle ::barTintColor ::interactivePopGestureEnabled
::itemWrapperStyle ::navigationBarHidden
::shadowHidden ::tintColor ::titleTextColor
::translucent]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment