diff --git a/doc/debugging.md b/doc/debugging.md index c8ad669244..ff8806f4b0 100644 --- a/doc/debugging.md +++ b/doc/debugging.md @@ -99,3 +99,38 @@ Also to inspect logs in a more flexible manner, instead of the strict output fro adb logcat | grep 'ReactNativeJS\|StatusModule\|GoLog' ``` +### From @clauxx (visual debugging): + +When building/fixing/refactoring components, it can be annoying to set-up the component for instant visual feedback (i.e. finding it in the UI when fixing/refactoring; finding a place for it when building from scratch). Very often if the location of the screen containing your component nested deeply in the app, you might have to do a lot of repeated navigation, nevermind logging in every time the app reloads (even with fast refresh disabled this happens quite often). + +To alleviate this discomfort and make the development cycle more *pleasant*, you can use one of the following options (*_both of which involve the ... REPL ༼ つ ╹ ╹ ༽つ, so make sure you have that set-up with your IDE/editor_*) + +#### REPL-ing to a screen + +This one is straightforward, just evaluate a navigation dispatch form from anywhere: + +```cljs +(comment (rf/dispatch [:navigate-to :your-favorite-buggy-screen])) +``` + +> TIP: you can run this from an untracked user namespace `(ns user)`, from which you can experiment or interact with the REPL. This is where I usually keep my development navigation forms. + +#### REPL-ing a component + +This is also straighforward, but there are some small differences. Just like above, we only have to evaluate a dispatch form, as follows: + +```cljs +;; example debugging a quo component, although it could be any other component e.g. from the `status-im2` ns. +(comment (re-frame/dispatch [:dev/preview-component + [quo/slide-button + {:track-icon :face-id + :track-text "preview component example" + :customization-color :blue + :on-complete identity}]])) +``` + +When evaluated, a full-screen bottom sheet will appear with your component inside. You can make changes to the props or the component internals and re-evaluate the changed forms, after which the component will be re-mounted without running a reload (unless you save the file). Other times it's quicker to just hit save and the component will be reloaded as usual (except for the props you evaluated, which have to be re-evaluated when changed). + +> TIP: You can have multiple versions of the component as separate comments to check for the component variations + +> TIP: You can leave `comment` blocks at the end of component files (other than quo, since can be previewed in other ways) with usages of components, which other developers can use for visualisation/testing. diff --git a/src/dev/component_preview/events.cljs b/src/dev/component_preview/events.cljs new file mode 100644 index 0000000000..97ccfe5826 --- /dev/null +++ b/src/dev/component_preview/events.cljs @@ -0,0 +1,25 @@ +(ns dev.component-preview.events + (:require + [quo.core :as quo] + [re-frame.core :as re-frame])) + +(def preview-screen-name :dev-component-preview) + +(when js/goog.DEBUG + (re-frame/reg-event-fx :dev/preview-component + (fn [{:keys [db]} [[component-tag props & args]]] + (let [view-id (:view-id db) + ;; NOTE: re-render on every evaluation e.g. reset component state without changes + component (into [component-tag (assoc props :key (random-uuid))] args) + navigate? (not= view-id preview-screen-name)] + (cond-> {:db (assoc db :dev/previewed-component component)} + navigate? (assoc :fx [[:dispatch [:navigate-to preview-screen-name]]])))))) + +;; Usage example +(comment + (re-frame/dispatch [:dev/preview-component + [quo/slide-button + {:track-icon :face-id + :track-text ":debug-component example" + :customization-color :blue + :on-complete identity}]])) diff --git a/src/dev/component_preview/view.cljs b/src/dev/component_preview/view.cljs new file mode 100644 index 0000000000..790f0a1dea --- /dev/null +++ b/src/dev/component_preview/view.cljs @@ -0,0 +1,16 @@ +(ns dev.component-preview.view + (:require + [react-native.core :as rn] + [utils.re-frame :as rf])) + +(def ^:private container-style + {:flex 1 + :padding-horizontal 20 + :padding-top 80 + :align-items :center}) + +(defn view + [] + (let [component (rf/sub [:dev/previewed-component])] + [rn/view {:style container-style} + (when component component)])) diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index e808835ca0..dd41448132 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -1,5 +1,6 @@ (ns status-im2.navigation.screens (:require + [dev.component-preview.view :as component-preview] [status-im.ui.screens.screens :as old-screens] [status-im2.config :as config] [status-im2.contexts.add-new-contact.views :as add-new-contact] @@ -272,6 +273,11 @@ {:modalPresentationStyle :overCurrentContext}) :component scan-address/view}] + (when js/goog.DEBUG + [{:name :dev-component-preview + :options {:sheet? true} + :component component-preview/view}]) + (when config/quo-preview-enabled? quo.preview/screens) diff --git a/src/status_im2/subs/root.cljs b/src/status_im2/subs/root.cljs index 83e30994c8..66f314383a 100644 --- a/src/status_im2/subs/root.cljs +++ b/src/status_im2/subs/root.cljs @@ -147,3 +147,7 @@ ;;wallet (reg-root-key-sub :wallet/scanned-address :wallet/scanned-address) (reg-root-key-sub :wallet/create-account :wallet/create-account) + +;;debug +(when js/goog.DEBUG + (reg-root-key-sub :dev/previewed-component :dev/previewed-component))