* Add bind-component function to `react-native.navigation` * Create helper function to use react-native-navigation lifecycle methods * Fix sync QR code not recognized after trying again & refactor * Add atom to manage callbacks when qr code scan fails
This commit is contained in:
parent
ff1ae2f4aa
commit
79bf4bb8d5
|
@ -89,3 +89,8 @@
|
||||||
(reset! constants {:top-bar-height (.-topBarHeight consts)
|
(reset! constants {:top-bar-height (.-topBarHeight consts)
|
||||||
:bottom-tabs-height (.-bottomTabsHeight consts)
|
:bottom-tabs-height (.-bottomTabsHeight consts)
|
||||||
:status-bar-height (.-statusBarHeight consts)})))
|
:status-bar-height (.-statusBarHeight consts)})))
|
||||||
|
|
||||||
|
(defn bind-component
|
||||||
|
[^js/Object this component-id]
|
||||||
|
(set! (. this -navigationEventListener)
|
||||||
|
(.. Navigation events (bindComponent this component-id))))
|
||||||
|
|
|
@ -14,11 +14,13 @@
|
||||||
{:title (i18n/label :t/sign-in-by-syncing)
|
{:title (i18n/label :t/sign-in-by-syncing)
|
||||||
:show-bottom-view? true
|
:show-bottom-view? true
|
||||||
:background [background/view true]
|
:background [background/view true]
|
||||||
:animated? false}])
|
:animated? false
|
||||||
|
:screen-name "sign-in"}])
|
||||||
|
|
||||||
(defn animated-view
|
(defn animated-view
|
||||||
[]
|
[]
|
||||||
[scan-sync-code/view
|
[scan-sync-code/view
|
||||||
{:title (i18n/label :t/sign-in-by-syncing)
|
{:title (i18n/label :t/sign-in-by-syncing)
|
||||||
:show-bottom-view? true
|
:show-bottom-view? true
|
||||||
:animated? true}])
|
:animated? true
|
||||||
|
:screen-name "sign-in-intro"}])
|
||||||
|
|
|
@ -8,12 +8,7 @@
|
||||||
|
|
||||||
(defn pairing-progress
|
(defn pairing-progress
|
||||||
[status]
|
[status]
|
||||||
(cond
|
(not= status :error))
|
||||||
(= status :error)
|
|
||||||
false
|
|
||||||
|
|
||||||
:else
|
|
||||||
true))
|
|
||||||
|
|
||||||
(defn page-title
|
(defn page-title
|
||||||
[pairing-progress?]
|
[pairing-progress?]
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
(ns status-im2.contexts.syncing.scan-sync-code.animation
|
||||||
|
(:require [react-native.reanimated :as reanimated]
|
||||||
|
[status-im2.constants :as constants]))
|
||||||
|
|
||||||
|
(defn animate-subtitle
|
||||||
|
[subtitle-opacity]
|
||||||
|
(reanimated/animate-shared-value-with-delay
|
||||||
|
subtitle-opacity
|
||||||
|
1
|
||||||
|
constants/onboarding-modal-animation-duration
|
||||||
|
:easing4
|
||||||
|
(/ constants/onboarding-modal-animation-delay 2)))
|
||||||
|
|
||||||
|
(defn animate-title
|
||||||
|
[title-opacity]
|
||||||
|
(reanimated/animate-shared-value-with-delay
|
||||||
|
title-opacity
|
||||||
|
1
|
||||||
|
0
|
||||||
|
:easing4
|
||||||
|
(+ constants/onboarding-modal-animation-duration
|
||||||
|
constants/onboarding-modal-animation-delay)))
|
||||||
|
|
||||||
|
(defn animate-bottom
|
||||||
|
[bottom-view-translate-y]
|
||||||
|
(reanimated/animate-delay
|
||||||
|
bottom-view-translate-y
|
||||||
|
0
|
||||||
|
(+ constants/onboarding-modal-animation-duration
|
||||||
|
constants/onboarding-modal-animation-delay)
|
||||||
|
100))
|
||||||
|
|
||||||
|
(defn animate-content
|
||||||
|
[content-opacity]
|
||||||
|
(reanimated/animate-shared-value-with-delay
|
||||||
|
content-opacity
|
||||||
|
1
|
||||||
|
constants/onboarding-modal-animation-duration
|
||||||
|
:easing4
|
||||||
|
(/ constants/onboarding-modal-animation-delay 2)))
|
||||||
|
|
||||||
|
(defn reset-animations
|
||||||
|
[{:keys [content-opacity subtitle-opacity title-opacity]}]
|
||||||
|
(reanimated/animate-shared-value-with-timing
|
||||||
|
content-opacity
|
||||||
|
0
|
||||||
|
(/ constants/onboarding-modal-animation-duration 8)
|
||||||
|
:easing4)
|
||||||
|
|
||||||
|
(reanimated/animate-shared-value-with-timing
|
||||||
|
subtitle-opacity
|
||||||
|
0
|
||||||
|
(- constants/onboarding-modal-animation-duration
|
||||||
|
constants/onboarding-modal-animation-delay)
|
||||||
|
:easing4)
|
||||||
|
|
||||||
|
(reanimated/animate-shared-value-with-timing
|
||||||
|
title-opacity
|
||||||
|
0
|
||||||
|
0
|
||||||
|
:easing4))
|
|
@ -14,8 +14,10 @@
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im2.common.device-permissions :as device-permissions]
|
[status-im2.common.device-permissions :as device-permissions]
|
||||||
[status-im2.constants :as constants]
|
[status-im2.constants :as constants]
|
||||||
|
[status-im2.contexts.syncing.scan-sync-code.animation :as animation]
|
||||||
[status-im2.contexts.syncing.scan-sync-code.style :as style]
|
[status-im2.contexts.syncing.scan-sync-code.style :as style]
|
||||||
[status-im2.contexts.syncing.utils :as sync-utils]
|
[status-im2.contexts.syncing.utils :as sync-utils]
|
||||||
|
[status-im2.navigation.util :as navigation.util]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
|
@ -37,7 +39,7 @@
|
||||||
(rf/dispatch [:syncing/preflight-outbound-check #(reset! preflight-check-passed? %)]))
|
(rf/dispatch [:syncing/preflight-outbound-check #(reset! preflight-check-passed? %)]))
|
||||||
|
|
||||||
(defn- header
|
(defn- header
|
||||||
[{:keys [active-tab read-qr-once? title title-opacity subtitle-opacity reset-animations-fn animated?]}]
|
[{:keys [active-tab title title-opacity subtitle-opacity reset-animations-fn animated?]}]
|
||||||
(let [subtitle-translate-x (reanimated/interpolate subtitle-opacity [0 1] [-13 0])
|
(let [subtitle-translate-x (reanimated/interpolate subtitle-opacity [0 1] [-13 0])
|
||||||
subtitle-translate-y (reanimated/interpolate subtitle-opacity [0 1] [-85 0])
|
subtitle-translate-y (reanimated/interpolate subtitle-opacity [0 1] [-85 0])
|
||||||
subtitle-scale (reanimated/interpolate subtitle-opacity [0 1] [0.9 1])
|
subtitle-scale (reanimated/interpolate subtitle-opacity [0 1] [0.9 1])
|
||||||
|
@ -106,8 +108,7 @@
|
||||||
:data [{:id 1 :label (i18n/label :t/scan-sync-qr-code)}
|
:data [{:id 1 :label (i18n/label :t/scan-sync-qr-code)}
|
||||||
{:id 2 :label (i18n/label :t/enter-sync-code)}]
|
{:id 2 :label (i18n/label :t/enter-sync-code)}]
|
||||||
:on-change (fn [id]
|
:on-change (fn [id]
|
||||||
(reset! active-tab id)
|
(reset! active-tab id))}]]]))
|
||||||
(reset! read-qr-once? false))}]]]))
|
|
||||||
|
|
||||||
(defn get-labels-and-on-press-method
|
(defn get-labels-and-on-press-method
|
||||||
[]
|
[]
|
||||||
|
@ -225,135 +226,114 @@
|
||||||
[insets translate-y]
|
[insets translate-y]
|
||||||
[:f> f-bottom-view insets translate-y])
|
[:f> f-bottom-view insets translate-y])
|
||||||
|
|
||||||
(defn- check-qr-code-data
|
(defn- check-qr-code-and-navigate
|
||||||
[event]
|
[{:keys [event on-success-scan on-failed-scan]}]
|
||||||
(let [connection-string (string/trim (oops/oget event "nativeEvent.codeStringValue"))
|
(let [connection-string (string/trim (oops/oget event "nativeEvent.codeStringValue"))
|
||||||
valid-connection-string? (sync-utils/valid-connection-string? connection-string)]
|
valid-connection-string? (sync-utils/valid-connection-string? connection-string)]
|
||||||
|
;; debounce-and-dispatch used because the QR code scanner performs callbacks too fast
|
||||||
(if valid-connection-string?
|
(if valid-connection-string?
|
||||||
(debounce/debounce-and-dispatch [:syncing/input-connection-string-for-bootstrapping
|
(do
|
||||||
connection-string]
|
(on-success-scan)
|
||||||
300)
|
(debounce/debounce-and-dispatch
|
||||||
(rf/dispatch [:toasts/upsert
|
[:syncing/input-connection-string-for-bootstrapping connection-string]
|
||||||
{:icon :i/info
|
300))
|
||||||
:icon-color colors/danger-50
|
(do
|
||||||
:theme :dark
|
(on-failed-scan)
|
||||||
:text (i18n/label :t/error-this-is-not-a-sync-qr-code)}]))))
|
(debounce/debounce-and-dispatch
|
||||||
|
[:toasts/upsert
|
||||||
|
{:icon :i/info
|
||||||
|
:icon-color colors/danger-50
|
||||||
|
:theme :dark
|
||||||
|
:text (i18n/label :t/error-this-is-not-a-sync-qr-code)}]
|
||||||
|
300)))))
|
||||||
|
|
||||||
(defn render-camera
|
(defn- render-camera
|
||||||
[show-camera? torch-mode qr-view-finder camera-ref on-read-code]
|
[{:keys [torch-mode qr-view-finder scan-code? set-qr-code-succeeded set-rescan-timeout]}]
|
||||||
(when (and show-camera? (:x qr-view-finder))
|
[:<>
|
||||||
[:<>
|
[rn/view {:style style/camera-container}
|
||||||
[rn/view {:style style/camera-container}
|
[camera-kit/camera
|
||||||
[camera-kit/camera
|
{:style style/camera-style
|
||||||
{:ref #(reset! camera-ref %)
|
:camera-type camera-kit/camera-type-back
|
||||||
:style style/camera-style
|
:zoom-mode :off
|
||||||
:camera-type camera-kit/camera-type-back
|
:torch-mode torch-mode
|
||||||
:zoom-mode :off
|
:scan-barcode true
|
||||||
:torch-mode torch-mode
|
:on-read-code #(when scan-code?
|
||||||
:scan-barcode true
|
(check-qr-code-and-navigate {:event %
|
||||||
:on-read-code on-read-code}]]
|
:on-success-scan set-qr-code-succeeded
|
||||||
[hole-view/hole-view
|
:on-failed-scan set-rescan-timeout}))}]]
|
||||||
{:style style/hole
|
[hole-view/hole-view
|
||||||
:holes [(assoc qr-view-finder :borderRadius 16)]}
|
{:style style/hole
|
||||||
[blur/view
|
:holes [(assoc qr-view-finder :borderRadius 16)]}
|
||||||
{:style style/absolute-fill
|
[blur/view
|
||||||
:blur-amount 10
|
{:style style/absolute-fill
|
||||||
:blur-type :transparent
|
:blur-amount 10
|
||||||
:overlay-color colors/neutral-80-opa-80
|
:blur-type :transparent
|
||||||
:background-color colors/neutral-80-opa-80}]]]))
|
:overlay-color colors/neutral-80-opa-80
|
||||||
|
:background-color colors/neutral-80-opa-80}]]])
|
||||||
|
|
||||||
|
(defn- reset-animations-and-navigate-fn
|
||||||
|
[{:keys [render-camera? show-camera?] :as params}]
|
||||||
|
(letfn [(reset-fn []
|
||||||
|
(rf/dispatch [:navigate-back])
|
||||||
|
(when @dismiss-animations (@dismiss-animations))
|
||||||
|
(animation/reset-animations params))]
|
||||||
|
(fn []
|
||||||
|
(reset! render-camera? false)
|
||||||
|
(js/setTimeout reset-fn (if show-camera? 500 0)))))
|
||||||
|
|
||||||
|
(defn- set-listener-torch-off-on-app-inactive
|
||||||
|
[torch-atm]
|
||||||
|
(let [set-torch-off-fn #(when (not= % "active") (reset! torch-atm false))
|
||||||
|
app-state-listener (.addEventListener rn/app-state "change" set-torch-off-fn)]
|
||||||
|
#(.remove app-state-listener)))
|
||||||
|
|
||||||
(defn f-view
|
(defn f-view
|
||||||
[{:keys [title show-bottom-view? background animated?]}]
|
[_]
|
||||||
(let [insets (safe-area/get-insets)
|
(let [insets (safe-area/get-insets)
|
||||||
active-tab (reagent/atom 1)
|
active-tab (reagent/atom 1)
|
||||||
qr-view-finder (reagent/atom {})
|
qr-view-finder (reagent/atom {})
|
||||||
render-camera? (reagent/atom false)
|
render-camera? (reagent/atom false)
|
||||||
torch? (reagent/atom false)
|
torch? (reagent/atom false)
|
||||||
app-state-listener (atom nil)]
|
scan-code? (reagent/atom true)
|
||||||
(fn []
|
set-rescan-timeout (fn []
|
||||||
(let [camera-ref (atom nil)
|
(reset! scan-code? false)
|
||||||
read-qr-once? (atom false)
|
(js/setTimeout #(reset! scan-code? true) 3000))]
|
||||||
torch-mode (if @torch? :on :off)
|
(fn [{:keys [title show-bottom-view? background animated? qr-code-succeed?
|
||||||
flashlight-icon (if @torch? :i/flashlight-on :i/flashlight-off)
|
set-qr-code-succeeded]}]
|
||||||
;; The below check is to prevent scanning of any QR code
|
(let [torch-mode (if @torch? :on :off)
|
||||||
;; when the user is in syncing progress screen
|
flashlight-icon (if @torch? :i/flashlight-on :i/flashlight-off)
|
||||||
user-in-syncing-progress-screen? (= (rf/sub [:view-id]) :syncing-progress)
|
scan-qr-code-tab? (= @active-tab 1)
|
||||||
on-read-code (fn [data]
|
show-camera? (and scan-qr-code-tab?
|
||||||
(when (and (not @read-qr-once?)
|
@camera-permission-granted?
|
||||||
(not user-in-syncing-progress-screen?))
|
@preflight-check-passed?
|
||||||
(reset! read-qr-once? true)
|
(boolean (not-empty @qr-view-finder)))
|
||||||
(js/setTimeout (fn []
|
camera-ready-to-scan? (and (or (not animated?) @render-camera?)
|
||||||
(reset! read-qr-once? false))
|
show-camera?
|
||||||
3000)
|
(not qr-code-succeed?))
|
||||||
(check-qr-code-data data)))
|
title-opacity (reanimated/use-shared-value (if animated? 0 1))
|
||||||
scan-qr-code-tab? (= @active-tab 1)
|
subtitle-opacity (reanimated/use-shared-value (if animated? 0 1))
|
||||||
show-camera? (and scan-qr-code-tab?
|
content-opacity (reanimated/use-shared-value (if animated? 0 1))
|
||||||
@camera-permission-granted?
|
content-translate-y (reanimated/interpolate subtitle-opacity [0 1] [85 0])
|
||||||
@preflight-check-passed?
|
|
||||||
(boolean (not-empty @qr-view-finder)))
|
|
||||||
title-opacity (reanimated/use-shared-value (if animated? 0 1))
|
|
||||||
subtitle-opacity (reanimated/use-shared-value (if animated? 0 1))
|
|
||||||
content-opacity (reanimated/use-shared-value (if animated? 0 1))
|
|
||||||
content-translate-y (reanimated/interpolate subtitle-opacity [0 1] [85 0])
|
|
||||||
bottom-view-translate-y (reanimated/use-shared-value
|
bottom-view-translate-y (reanimated/use-shared-value
|
||||||
(if animated? (+ 42.2 (:bottom insets)) 0))
|
(if animated? (+ 42.2 (:bottom insets)) 0))
|
||||||
reset-animations-fn
|
reset-animations-fn (reset-animations-and-navigate-fn
|
||||||
(fn []
|
{:render-camera? render-camera?
|
||||||
(reset! render-camera? false)
|
:show-camera? show-camera?
|
||||||
(js/setTimeout
|
:content-opacity content-opacity
|
||||||
(fn []
|
:subtitle-opacity subtitle-opacity
|
||||||
(rf/dispatch [:navigate-back])
|
:title-opacity title-opacity})]
|
||||||
(when @dismiss-animations
|
|
||||||
(@dismiss-animations))
|
|
||||||
(reanimated/animate-shared-value-with-timing
|
|
||||||
content-opacity
|
|
||||||
0
|
|
||||||
(/ constants/onboarding-modal-animation-duration 8)
|
|
||||||
:easing4)
|
|
||||||
(reanimated/animate-shared-value-with-timing
|
|
||||||
subtitle-opacity
|
|
||||||
0
|
|
||||||
(- constants/onboarding-modal-animation-duration
|
|
||||||
constants/onboarding-modal-animation-delay)
|
|
||||||
:easing4)
|
|
||||||
(reanimated/animate-shared-value-with-timing title-opacity
|
|
||||||
0
|
|
||||||
0
|
|
||||||
:easing4))
|
|
||||||
(if show-camera? 500 0)))]
|
|
||||||
(rn/use-effect (fn []
|
|
||||||
(reset! app-state-listener
|
|
||||||
(.addEventListener rn/app-state
|
|
||||||
"change"
|
|
||||||
#(when (and (not= % "active") @torch?)
|
|
||||||
(reset! torch? false))))
|
|
||||||
#(.remove @app-state-listener)))
|
|
||||||
(when animated?
|
|
||||||
(reanimated/animate-shared-value-with-delay subtitle-opacity
|
|
||||||
1 constants/onboarding-modal-animation-duration
|
|
||||||
:easing4
|
|
||||||
(/
|
|
||||||
constants/onboarding-modal-animation-delay
|
|
||||||
2))
|
|
||||||
(reanimated/animate-shared-value-with-delay title-opacity
|
|
||||||
1 0
|
|
||||||
:easing4
|
|
||||||
(+ constants/onboarding-modal-animation-duration
|
|
||||||
constants/onboarding-modal-animation-delay))
|
|
||||||
(reanimated/animate-delay bottom-view-translate-y
|
|
||||||
0
|
|
||||||
(+ constants/onboarding-modal-animation-duration
|
|
||||||
constants/onboarding-modal-animation-delay)
|
|
||||||
100))
|
|
||||||
(rn/use-effect
|
(rn/use-effect
|
||||||
(fn []
|
#(set-listener-torch-off-on-app-inactive torch?))
|
||||||
|
|
||||||
|
(when animated?
|
||||||
|
(animation/animate-subtitle subtitle-opacity)
|
||||||
|
(animation/animate-title title-opacity)
|
||||||
|
(animation/animate-bottom bottom-view-translate-y))
|
||||||
|
|
||||||
|
(rn/use-effect
|
||||||
|
(fn initialize-component []
|
||||||
(when animated?
|
(when animated?
|
||||||
(reanimated/animate-shared-value-with-delay content-opacity
|
(animation/animate-content content-opacity)
|
||||||
1 constants/onboarding-modal-animation-duration
|
|
||||||
:easing4
|
|
||||||
(/
|
|
||||||
constants/onboarding-modal-animation-delay
|
|
||||||
2))
|
|
||||||
(js/setTimeout #(reset! render-camera? true)
|
(js/setTimeout #(reset! render-camera? true)
|
||||||
(+ constants/onboarding-modal-animation-duration
|
(+ constants/onboarding-modal-animation-duration
|
||||||
constants/onboarding-modal-animation-delay
|
constants/onboarding-modal-animation-delay
|
||||||
|
@ -365,12 +345,16 @@
|
||||||
#(reset! camera-permission-granted? false)))))
|
#(reset! camera-permission-granted? false)))))
|
||||||
[:<>
|
[:<>
|
||||||
background
|
background
|
||||||
(when (or (not animated?) @render-camera?)
|
(when camera-ready-to-scan?
|
||||||
[render-camera show-camera? torch-mode @qr-view-finder camera-ref on-read-code])
|
[render-camera
|
||||||
|
{:torch-mode torch-mode
|
||||||
|
:qr-view-finder @qr-view-finder
|
||||||
|
:scan-code? @scan-code?
|
||||||
|
:set-qr-code-succeeded set-qr-code-succeeded
|
||||||
|
:set-rescan-timeout set-rescan-timeout}])
|
||||||
[rn/view {:style (style/root-container (:top insets))}
|
[rn/view {:style (style/root-container (:top insets))}
|
||||||
[:f> header
|
[:f> header
|
||||||
{:active-tab active-tab
|
{:active-tab active-tab
|
||||||
:read-qr-once? read-qr-once?
|
|
||||||
:title title
|
:title title
|
||||||
:title-opacity title-opacity
|
:title-opacity title-opacity
|
||||||
:subtitle-opacity subtitle-opacity
|
:subtitle-opacity subtitle-opacity
|
||||||
|
@ -390,8 +374,10 @@
|
||||||
2 [enter-sync-code-tab]
|
2 [enter-sync-code-tab]
|
||||||
nil)]
|
nil)]
|
||||||
[rn/view {:style style/flex-spacer}]
|
[rn/view {:style style/flex-spacer}]
|
||||||
(when show-bottom-view? [bottom-view insets bottom-view-translate-y])
|
(when show-bottom-view?
|
||||||
(when (and (or (not animated?) @render-camera?) show-camera?)
|
[bottom-view insets bottom-view-translate-y])
|
||||||
|
(when (and (or (not animated?) @render-camera?)
|
||||||
|
show-camera?)
|
||||||
[quo/button
|
[quo/button
|
||||||
{:icon-only? true
|
{:icon-only? true
|
||||||
:type :grey
|
:type :grey
|
||||||
|
@ -403,5 +389,14 @@
|
||||||
flashlight-icon])]]))))
|
flashlight-icon])]]))))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[props]
|
[{:keys [screen-name] :as _props}]
|
||||||
[:f> f-view props])
|
(let [qr-code-succeed? (reagent/atom false)]
|
||||||
|
(navigation.util/create-class-and-bind
|
||||||
|
screen-name
|
||||||
|
{:component-did-appear (fn set-qr-code-failed [_this]
|
||||||
|
(reset! qr-code-succeed? false))}
|
||||||
|
(fn [props]
|
||||||
|
(let [new-pops (assoc props
|
||||||
|
:qr-code-succeed? @qr-code-succeed?
|
||||||
|
:set-qr-code-succeeded #(reset! qr-code-succeed? true))]
|
||||||
|
[:f> f-view new-pops])))))
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
[scan-sync-code/view
|
[scan-sync-code/view
|
||||||
{:title (i18n/label :t/scan-sync-code)
|
{:title (i18n/label :t/scan-sync-code)
|
||||||
:background [rn/view
|
:background [rn/view
|
||||||
{:style style/background} true]}])
|
{:style style/background} true]
|
||||||
|
:screen-name "scan-sync-code-page"}])
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
(ns status-im2.navigation.util
|
||||||
|
(:require [react-native.navigation :as navigation]
|
||||||
|
[reagent.core :as reagent]))
|
||||||
|
|
||||||
|
(defn create-class-and-bind
|
||||||
|
"Creates a React class that allows the use of life-cycle methods added by
|
||||||
|
react-native-navigation:
|
||||||
|
- componentWillAppear
|
||||||
|
- componentDidAppear
|
||||||
|
- componentDidDisappear
|
||||||
|
Receives:
|
||||||
|
- `component-id` - The component-id to subscribe registered in navigation
|
||||||
|
- `react-methods` - A map of React methods (kebab-case) -> function handler
|
||||||
|
- `reagent-render` - A regular reagent function that returns hiccup.
|
||||||
|
Example:
|
||||||
|
(defn view
|
||||||
|
[props & children]
|
||||||
|
;; Bindings executed when component is created
|
||||||
|
(let [qr-code-succeed? (reagent/atom false)]
|
||||||
|
(create-class-and-bind
|
||||||
|
\"sign-in-intro\" ; navigation component-id of the screen to subscribe
|
||||||
|
{:component-did-appear (fn [this]
|
||||||
|
;; Executed when component appeared to the screen
|
||||||
|
)
|
||||||
|
:component-will-appear (fn [this]
|
||||||
|
;; Executed when component will be shown to the screen
|
||||||
|
)
|
||||||
|
:component-did-disappear (fn [this]
|
||||||
|
;; Executed when component disappeared from the screen
|
||||||
|
)}
|
||||||
|
(fn [props & children] ; Must be the same signature as this `view` function
|
||||||
|
;; Regular component call, e.g.:
|
||||||
|
[rn/view {:style {:padding-top 10}}
|
||||||
|
[:f> my-f-component-call (assoc props :on-press identity)]
|
||||||
|
children]))))
|
||||||
|
"
|
||||||
|
[component-id react-methods reagent-render]
|
||||||
|
(reagent/create-class
|
||||||
|
(assoc react-methods
|
||||||
|
:display-name (str component-id "-view")
|
||||||
|
:component-did-mount #(navigation/bind-component % component-id)
|
||||||
|
:reagent-render reagent-render)))
|
Loading…
Reference in New Issue