Fork me on GitHub
#clojurescript
<
2020-03-03
>
kaffein09:03:09

Hi folks! has anyone here have experience with code reloading in a Cordova + cljs using shadow-cljs please? I would really be interested in knowing how to make it work right on the device!thanks in adv

thheller10:03:19

whats the issue? I'd assume a regular :browser build would do the trick?

kaffein10:03:50

at the moment this is what we are doing : we develop in the browser with all the advantages of having it refresh automatically etc. but we were wondering whether there were some way of having the app deployed right on a device (Android/iOS or emulators) and still have the code reload right on the device (without redeploying using cordova CLI again) when we change stuff

thheller11:03:49

I just did a quick test and after some manual tuning it works as expected

mccraigmccraig11:03:23

@U0DTAJS3Y there is - you need to have your app container page redirect to your shadow watch-build, and you need to copy these files into the directory shadow is serving from

šŸ‘ 4
mccraigmccraig11:03:32

["^cordova.js$",
                       "^cordova_plugins.js$",
                       "^plugins$",
                       "^plugins/.*$"]

thheller11:03:49

maybe this helps

mccraigmccraig11:03:16

does that do the redirect for hot-reloading on-device @U05224H0W ?

thheller11:03:58

I only tested windows though ... so "device" is my windows machine

thheller11:03:04

no clue about other platforms

thheller11:03:14

requires too much setup I don't have time for

mccraigmccraig11:03:01

sure - i've done it for both ios and android, simulator and hardware - the same approach works for all combos

kaffein11:03:33

hey guys @U05224H0W @U0524B4UW thanks a lot for your help ...I will give it a shot on my side

mccraigmccraig11:03:43

here are our shadow build config overrides for ios and android watch builds @U0DTAJS3Y.... we're using gulp for our build-system, so we've got EDN for the overrides jammed into js literals, but you should get the idea: https://gist.github.com/mccraigmccraig/ac07e9354d44c35f9866e3d811515d34

šŸ’Æ 4
šŸ‘ 4
kaffein11:03:34

wow awesome šŸ‘Œ again thanks

deep-symmetry13:03:30

I just realized I should probably announce that as part of building the byte field diagram generator Iā€™m creating to port a big LaTeX document to Asciidoctor/Antora, I have ported Analemma (https://github.com/liebke/analemma) to .cljc so it works in ClojureScript as well as Clojure, and (with David Liebkeā€™s permission) posted a canonical release to Clojars.

p-himik14:03:24

That may be worth posting at #announcements

deep-symmetry15:03:19

Ah, I wasnā€™t even aware of that channel, I see #admin-announcements but hadnā€™t yet joined the other one, thanks!

folcon19:03:47

Any equivalent of extends? in cljs? Or at least better than:

#(satisfies? protocol (new %))
Iā€™ve been digging around and I canā€™t seem to find anything, other than perhaps sticking the above in a macro.

lilactown19:03:07

what are you trying to do?

lilactown19:03:59

AFAIK in general, you canā€™t know that a type or record implements a protocol without constructing it, because under the hood a type / record is just a constructor function which returns an object

lilactown19:03:54

this is different than the JVM, where a class is an actual concrete concept in the runtime

lilactown19:03:44

I think itā€™s usually best practice to pass around instances of types/records rather than the type/record itself

folcon19:03:45

Iā€™ve got something thatā€™s really similar to an ECS style system, so Iā€™m using protocols to group together related functionality. I donā€™t want a situation where adding a new type of record (which is just a map after all) requires me to change a bunch of calls sites when what Iā€™m interested in is stuff like, now call all the physics stuff, now call all the render stuffā€¦

folcon19:03:50

Let me know if Iā€™ve been unclear =)ā€¦

lilactown19:03:16

protocols should solve that, yes

lilactown19:03:50

itā€™s unclear to me why you would pass the Record constructor in rather than an instance of the record into a call site

lilactown19:03:37

> a new type of record (which is just a map after all) a ā€œtype of recordā€ is not a map though, itā€™s a function. an instance of a record is the one that implements all of the same protocols as a map

lilactown19:03:51

(defprotocol IRenderable
  (-render [this]))

(defrecord Player []
  IRenderable
  (-render [this]
    ,,,))

(defn render [renderable]
  {:pre [(satisfies? IRenderable renderable)]}
  (-render renderable))

(render (->Player))

folcon19:03:22

So I have :entities which is a collection of different records that all implement the IEntity protocol, however certain functions, like ai, will only want to loop through stuff with IMonster. Now finding all the records which implement a protocol by looping through the entities list is expensive, so I have a :entities-with-component, which is a map of types of entities to a collection of entity idā€™s of that type, then I can quickly get by the type Iā€™m interested in and then do a get to turn the entity-ids into entities. Now Iā€™m going a step beyond that, by using extends I can say give me all the entities that implement this protocol. But I canā€™t do that in cljs without doing #(satisfies? protocol (new %)).

folcon19:03:18

I mean if I could take a record and get the protocols it implements that might work too? But it feels a little bit more messyā€¦

bfabry19:03:26

"Now finding all the records which implement a protocol by looping through the entities list is expensive" is it? if that's really true then I'd suggest creating a second map of protocol->entities (there's no real reason to use id's with persistent data structures). I'm ever so slightly skeptical of this performance issue though šŸ™‚

lilactown19:03:01

it sounds like youā€™re trying to create a mapping on top of the component->entity mapping, behavior->component->entity . but why not behavior->entity?

bfabry19:03:31

oh it's a game and your entities probably have some sort of state associated with them, that explains the id thing

lilactown19:03:01

youā€™re losing out on all the goodness of protocols by trying to map behavior to concrete types

folcon20:03:54

@lilactown As in for every behaviour create a reference to the entity? Not thought it about it. Will give it a try.

colinkahn21:03:18

Are there any safe ways to redef functions when using core.async go blocks in ClojureScript? I ran into the same issue found here https://clojure.atlassian.net/browse/CLJS-884 which doesnā€™t provide any alternatives. I ended up making a test fixture that resets the values after each test but wondering how other people are doing this.

dnolen21:03:41

I do it with fixtures as well

lilactown21:03:55

depending on what level of abstraction you are operating at, you can create a macro or function that re-binds the values at each async barrier.

(let [dynamic-var *dynamic-var*]
  (go
    (binding [*dynamic-var* dynamic-var]
      ,,,))
Iā€™ve used this to similar effect when creating a data fetching framework that worked with server-side rendering, isolating the cache between requests

lilactown21:03:16

this doesnā€™t work as a general way to redef/rebind things you donā€™t control that use core.async

colinkahn21:03:49

@lilactown right, I can introduce some code specific things, I was considering just making a version of the function that got passed all deps so I could just provide them.

colinkahn21:03:29

the fixtures method definitely works, gives me some confidence if youā€™re doing the same @dnolen šŸ˜„