Fork me on GitHub
#cljsrn
<
2016-08-17
>
kitofr08:08:52

what do you guys use for logging? need to get some rudimentary logging done and can't find that much info. using re-natal

pesterhazy11:08:12

@kitofr: what are your requirements?

pesterhazy11:08:25

In cljs I mainly use a my.project.logging namespace like this:

(defn log [& s] (apply println s))

     (def debug (fn [& _])) ;; no-op for now
     (def info log)
     (def warn log)
     (def error log)

pesterhazy11:08:08

this basically just uses println, bute when a need arises for better logging, I'll be able to replace it with something more granular

pesterhazy11:08:03

(hat tip to @martinklepsch)

pesterhazy11:08:37

@shader: animations work just like in react-native proper

pesterhazy11:08:42

(def animated-view (r/adapt-react-class (.-View js/Animated))); you'll need to use js interop to use js/Animated.Value.

pesterhazy11:08:58

(set! js/Animated (.-Animated js/React))

kitofr11:08:26

well... i just realised that I mainly need to configure my xcode-env to output things in a decent format

pesterhazy11:08:50

interesting, how do you do that?

pesterhazy11:08:33

when I look at my simulator log (`react-native log-ios`), I see a bunch of useless crap, besides the interesting app logs

pesterhazy11:08:00

a lot of noise essentially

pesterhazy11:08:14

XCode's debug window is better, but I really don't want to have XCode open all the time

macroz11:08:22

how do you guys mix shared and platform specific code?

macroz11:08:49

looking at luno exampe there's a lot of passing of functions or components that are platform specific into and out of shared code

macroz11:08:00

thought that multimethods might make more sense

pesterhazy11:08:04

I'm curious about that

pesterhazy11:08:27

what kind of differences between ios and android are you thinking of?

macroz11:08:39

well button for eaxmple

macroz11:08:48

should be easy to add in a shared view also

macroz11:08:00

but need to abstract away the platform differences in exact prop names etc.

vikeri11:08:04

@macroz: I use the env library and a macro like this:

(defmacro pcomp
  "Gets platform dependent component"
  [c]
  (symbol (str "pilloxa." env/PLATFORM ".components") c))

macroz11:08:41

referencing the component is not exactly a problem but the slightly different usage

pesterhazy11:08:47

I use (def platform (.. js/React -Platform -OS))

macroz11:08:50

I think buttons should not behave differently

macroz11:08:04

a toolbar etc., those are platform specific

macroz11:08:56

I'd like to share a bit more of my code but how does the shared code access the platform specific components in an abstracted manner

pesterhazy11:08:58

why not (defn toolbar [] (if (= "android" platform) [toolbar-android] [toolbar-ios])) ?

macroz11:08:43

so you would implement a generic component library on top of the platform specific ones?

vikeri11:08:01

@macroz I do that

macroz11:08:16

react native tries hard to expose the platform specific stuff so you can get the UX perfect, not a hybrid experience

macroz11:08:31

it's not write once, run anywhere, right? 🙂

macroz11:08:05

a game, or some app with a lot of custom UX might get away with just having the same thing on all platforms but a "regular app" would not

pesterhazy11:08:25

well a lot of code can be shared

macroz11:08:42

my problem is in the interaction between native and shared components

macroz11:08:47

how specifically should I go about that

pesterhazy11:08:58

can you name an example?

macroz11:08:10

let's say you wrap a text and like button inside a card list

macroz11:08:21

text is probable shared

macroz11:08:26

button is native

macroz11:08:31

card probably native

macroz11:08:35

scene should be shared

macroz11:08:39

root is probably native

macroz11:08:07

root needs to bootstrap the native experience

macroz11:08:15

then it can add the shared scene

macroz11:08:26

scene needs to display a list of cards but the card components are native

macroz11:08:40

so how does the scene refer to the native components without depending on them?

macroz11:08:51

those ifs pollute your code

macroz11:08:56

same problem for the card and button

pesterhazy11:08:57

you only refer to the abstract components

pesterhazy11:08:33

the abstract component then include conditionals, yes, but that seems fine

macroz11:08:42

there's a bunch of ways you can go about referring to the abstract components

pesterhazy11:08:50

for simple things I'd say a quick (when (android? ...) is fine here and there

macroz11:08:04

and we all know that type case and ifs are bad, ok for a quick hack but tech debt

pesterhazy11:08:32

I don't agree about that, honestly

macroz11:08:35

seems like the case for the components needs something more than the occasional hac

pesterhazy11:08:54

it's much easier to go overboard with multimethods etc as a premature abstraction

macroz11:08:16

also because there is only ever going to be a number of platforms that you can count by your fingers

macroz11:08:54

I don't see multimethod as an abstraction in that sense

macroz11:08:06

it's just one option

pesterhazy11:08:24

I'd only go down the garden path of picking a specific abstraction once you know much more about how the conditional paths in your app are going to look like

vikeri11:08:27

I don’t think that conditionals are that ugly of a hack, I will use it until I the code is so big that I can come up with some smarter way of doing it.

pesterhazy11:08:40

exactly, @vikeri

macroz11:08:58

well I'm at that point now

macroz11:08:23

writing components should be simple and not bloated with the ifs or passing native component constructors around

pesterhazy11:08:24

it's an interesting architecture topic

pesterhazy11:08:47

in these discussions I always tend towards the naive solution

macroz11:08:51

and clojure offers many options for doing the thing

macroz11:08:10

I think this kind of option is mostly static

macroz11:08:30

i.e. if the set of options was dynamic and could be extended by someone else, I'd prefer multiple dispatch

macroz11:08:42

now there really is going to be only 2 platforms for this app and never more

pesterhazy11:08:43

how would you use a multimethod?

macroz11:08:11

use multimethod as the constructor for the component

pesterhazy11:08:23

what do you mean by constructor?

macroz11:08:34

[multimethod-function @platform {:my :args} and-something-else]

macroz11:08:41

something like that

macroz11:08:58

but since the set of platforms is not going to expand I think this is not the best possible solution

macroz12:08:09

but also don't think it's the ifs

macroz12:08:19

thought that maybe there are other cool options

pesterhazy12:08:43

might be an interesting topic for a blog post

macroz12:08:55

platform also is not changed during runtime so subscription is not the way I think

pesterhazy12:08:18

important thing is that it's simple to reason about

macroz12:08:23

so maybe in the very root component use dynamic scope and bind the ui components to their native implementations

macroz12:08:41

then it is trivial to refer to them statically

pesterhazy12:08:45

why not just a simple global def, as in my example above?

pesterhazy12:08:07

as you say, the platform is static

macroz12:08:15

I'll have to try and see

pesterhazy12:08:41

yeah the proof is in the pudding

pesterhazy12:08:49

please report back!

pesterhazy12:08:09

I'm getting to the point where I need to make these decisions myself

vikeri12:08:18

Yeah, very interesting. I think I will parametrize my builds with env so that I can have android/ios hardcoded in each js-bundle. Hopefully slightly better performance + I got some error just from having DatePickerIOS required when running in Android...

pesterhazy12:08:37

you can easily do (def date-picker-ios (when-not (android?) (js/require "date-picker-ios")))

pesterhazy12:08:20

that seems like something a macro may help with

pesterhazy12:08:31

(rn-import view image text touchable-highlight)

macroz12:08:50

yeah sure I'll report back

macroz12:08:59

possibly this thing will be open source at some point

pesterhazy12:08:08

that'd be awesome

pesterhazy12:08:21

we need more cookbook-style cljsrn example code

macroz12:08:43

yeah, but it's also difficult since everything is a moving target so the example code goes stale pretty quickly

pesterhazy12:08:20

actually, most of the code we wrote 1 year ago still works exactly as it is

pesterhazy12:08:30

the tooling has changed quite a lot though

macroz12:08:37

basic clojurescript and re-frame is quite stable indeed

pesterhazy12:08:48

yes and most of this also goes for react-native

macroz12:08:59

and the platforms themselves

pesterhazy12:08:17

there was a big change in 0.25 (react-dom/react-native split)

pesterhazy12:08:27

but mostly they are good about backward compatiblity

pesterhazy12:08:43

I'm pretty impressed with the RN team's work in general

pesterhazy12:08:56

(the RN packager is a different story)

macroz12:08:31

yeah, it's just the small cuts that hurt a lot because they cost a lot of time compared to the ease of implementing stuff these days

macroz12:08:42

and polish requires a lot of work, as always

pesterhazy12:08:26

the thing is we can alleviate a lot of this by sharing workarounds, warnings and performance improvements

pesterhazy12:08:44

I feel that the community is very important in this "wild west" of cljsrn app dev

vikeri15:08:40

I see that the output of the dist task in boot-react-native seems to have global.__DEV__ = true. Can that be modified somehow?

pesterhazy18:08:55

it's a hack, but it works

pesterhazy18:08:45

again, a github issue would be great so we can track the issue

vikeri20:08:29

Haha yet another scripting language introduced. Guess it was faster to script than a boot task? I'll file an issue. Also realized brn ignores :closure-defines will file an issue for that as well.

vikeri20:08:18

And how does the full release process looks like. What do I do with the created bundle?

pesterhazy20:08:08

hmm it shouldn't ignore closure-defines -- we use that option successfully

pesterhazy20:08:22

yeah, it was just a quick hack, easier to do in python

pesterhazy20:08:50

you need to add the js bundle to the app bundle (in xcode you can drag it into your project)

pesterhazy20:08:44

I'm sure the react-native guys have a way for that now, might be worth checking (I build my own bash script that runs in an xcode build phase)

pesterhazy20:08:29

I've implemented automatic patching of node_modules/react-native in master

pesterhazy20:08:47

the new task, patch-rn, is idempotent 🙂

artemyarulin20:08:53

>you need to add the js bundle to the app bundle (in xcode you can drag it into your project) As you are discussing other languages let me introduce Ruby and https://github.com/CocoaPods/Xcodeproj project, because it’s not enough troll

require 'xcodeproj'
project = Xcodeproj::Project.open('app.xcodeproj')
bundle = project.main_group.groups.first.files.first
project.targets.first.add_resources([bundle])  # RN default project doesn’t include js bundle in target
testTarget = project.targets[1]

# Dynamically add new test files to project
Dir["appTests/*.m"].select{ |f| 
  f != "appTests/appTests.m"
}.map{ |f|
  testTarget.add_file_references([project.new_file(f)])
}
project.save

artemyarulin20:08:25

I’m actually using this for testing RN + CLJS, so in case you need to do a lot of changes in xcodeproj often - consider this project

shader20:08:46

so what's the right way to make a new app using boot-react-native? Is it just adding the two boot tasks mentioned in the readme?

shader20:08:04

it looks like there might be a lot of extra boiler plate required, based on the example app, but I'm not sure that forking boot-react-native to use it is the right idea either

pesterhazy21:08:28

yeah so a bit of logic in build.boot is required, and some other stuff, like https://github.com/mjmeintjes/boot-react-native/blob/master/example/app/init.js

pesterhazy21:08:57

your best bet at the moment is to copy SimpleExampleApp

pesterhazy21:08:56

however, we should start moving logic into boot-react-native proper, so that less boilerplate in apps is required

pesterhazy21:08:51

there's also https://github.com/jellea/react-native-boot-template but it hasn't been updated in a while

pesterhazy21:08:16

I hope @jellea will update it soon, once things settle down a bit with BRN

pesterhazy21:08:49

though using a project generator is also not a perfect solution, as you need to keep things updated as BRN changes