• Stars
    star
    125
  • Rank 286,335 (Top 6 %)
  • Language
    Clojure
  • License
    MIT License
  • Created over 2 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Flutter + ClojureDart, with Matrix Inside(tm)

Flutter/MX

Programming Flutter with ClojureDart and Matrix, a generic, fine-grained, transparent, reactive state manager.

Warning

I just upgraded to Mac OS X Sonoma, forcing an upgrade of XCode and Simulator. At least one package, flutter_tts stopped producing audio, and upgrading to the latest did not work. Googling revealed that flutter_tts has a fix in Beta, and that sims built to run on iOS 16.4 will work. That requires going into XCode settings/Platforms to add iOS 16.4, then in the Simulator app we get iOS 16 as an option when making a "New Simulator...".

Documentation

Please see our WIP Wiki, or just ping @kennytilton on the #clojurians or #fluttercommunity Slacks and we can pair to get you rolling.

Quick Start

If you just want to run the thing...

0. Prepare your Clojure and ClojureDart environments, on Mac OS X

Clojure installation is documented here. tl;dr:

brew install clojure/tools/clojure

Next, execute the ClojureDart "Flutter Quick Start". Help with that can be had in the #ClojureDart channel on the #Clojurians Slack. Or ping @kennytilton on that Slack or the Flutter Community Slack.

1. Clone and initialize this repo

git clone https://github.com/kennytilton/flutter-mx
cd flutter-mx
clj -M:cljd init

2. You now have three delightful options

You can run on an iOS simulator, an iOS device, your browser, or your Mac desktop. Let us explore your options. (Is it not great having this problem?)

Device options

We develop on a Mac, and have not explored other platforms. We usually test on an iOS sim, though lately also iPad and iPhone. But we do enjoy developing on a mobile simulator, so we usually launch one. It is not required, but to do the same:

open -a Simulator

Check the Mac menu bar and it should show the Simulator app, and all sorts of options to choose and control the device. Android SIMs left as an exercise. After changing the options, we will not see a different device until we quite the Simulator app and restart it.

Flutter devices

Now to see what devices Flutter thinks are available, in a terminal enter:

flutter devices

My output as we speak:


Kenneth’s iPad (mobile)                        • 00008020-0006021A02F1402E            • ios            • iOS 16.5.1 20F75
iPad Pro (12.9-inch) (6th generation) (mobile) • 46B3E45C-52BB-4534-86B4-3BE15D296EF1 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-16-4 (simulator)
macOS (desktop)                                • macos                                • darwin-arm64   • macOS 13.4.1 22F770820d darwin-arm64 (Rosetta)
Chrome (web)                                   • chrome                               • web-javascript • Google Chrome 115.0.5790.114

No wireless devices were found.

• Error: Kenneth’s iPad is busy: Fetching debug symbols for Kenneth’s iPad. Xcode will continue when Kenneth’s iPad is finished. (code -10)

n.b. We will ignore the "iPad is busy" error. It seems benign.

OK, made your choice? Make note of the second column, and follow one of the three sets of instructions below.

Running on the iOS sim

In a terminal:

clj -M:cljd flutter -d 46B3E45C-52BB-4534-86B4-3BE15D296EF1 # <---!!!!! change the ID to your ID as shown in the device list

After a while you should see the legendary Flutter Counter app on the sim, as shown above.

Note that the build/run command does not return. Hit Control-C when done, or quit the Simulator app. Then continue below.

Running on a phyical iOS device connected via USB cable

Our first task is to get the device capable of running in developer mode:

  • Open the device "Settings" app;
  • select "Privacy & Security";
  • scroll to the end to "Security" options;
  • turn "Developer mode" on;
  • connect the iOS device to your laptop with a USB cable;
  • give permissions as requested when prompted on the device or computer;
  • in terminal, enter flutter devices, confirm the device appears in the listing, and note the ID.

Now:

clj -M:cljd flutter -d ACTUAL-ID-HERE # <---!!!!! change ACTUAL-ID-HERE to the numeric ID as shown in the device list

Now we have to wait several minutes, not panicking when the device puts up a blank screen for an eternity, and ignore several fatal-sounding errors. Edited output:

Launching flutter run -d 00008020-0006021A02F1402E
Launching lib/main.dart on Kenneth’s iPad in debug mode...
...snip...
(lldb) warning: libobjc.A.dylib is being read from process memory. This indicates that LLDB could not find the on-disk shared cache for this device. This will likely reduce debugging performance.
The Dart VM Service was not discovered after 30 seconds. This is taking much longer than expected...
process interrupt
error: Failed to halt process: Halt timed out. State = running
* thread #1, stop reason = signal SIGSTOP
    frame #0: 0x00000001e68b7164 dyld`_dyld_debugger_notification
dyld`:
->  0x1e68b7164 <+0>: ret    
dyld`dyld4::Atlas::Bitmap::Bitmap:
    0x1e68b7168 <+0>: pacibsp 
    0x1e68b716c <+4>: sub    sp, sp, #0x50
    0x1e68b7170 <+8>: stp    x24, x23, [sp, #0x10]
Target 0: (Runner) stopped.
(lldb) 2023-08-07 12:22:43.227037-0400 Runner[2785:2662306] [VERBOSE-2:FlutterDarwinContextMetalImpeller.mm(35)] Using the Impeller rendering backend.
...snip...
A Dart VM Service on Kenneth’s iPad is available at: http://127.0.0.1:65178/sbCSDP_TpSo=/
The Flutter DevTools debugger and profiler on Kenneth’s iPad is available at: http://127.0.0.1:9100?uri=http://127.0.0.1:65178/sbCSDP_TpSo=/

We should now see the legendary Flutter Counter app on the device, as shown above.

Note that the build/run command does not return. Hit Control-C when done. Then continue below.

Running on the desktop

In a terminal:

clj -M:cljd flutter -d macos

After a while you should see the legendary Flutter Counter app running in a desktop app!

Note that the build/run command does not return. Hit Control-C when done, or quit the desktop app. Then continue below.

Running in the Google Chrome browser

In a terminal:

clj -M:cljd flutter -d chrome

After a while you should see the legendary Flutter Counter app running in the Chrome browser!

Note that the build/run command does not return. Hit Control-C when done, or close the web page. Then continue to next.

Running everywhere

In a terminal:

open -a Simulator # iff necessary
clj -M:cljd flutter -d all

The app should load in the Simulator and a desktop app.

In a second terminal:

clj -M:cljd flutter -d chrome

That ^^ is our other demo app, a true "Hello, world."! How cool is that?!

3. Diagnostics

We rely exclusively on print debugging, but Flutter offers extensive debugging support you might like. Looking at the terminal window where we started the simulator version, we see:

Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).

A Dart VM Service on iPhone 14 Pro Max is available at: http://127.0.0.1:50022/9iEGXsRelsg=/
The Flutter DevTools debugger and profiler on iPhone 14 Pro Max is available at: http://127.0.0.1:9100?uri=http://127.0.0.1:50022/9iEGXsRelsg=/

Enter the Flutter DevTools URL offered in our browser, http://127.0.0.1:9100?uri=http://127.0.0.1:50022/9iEGXsRelsg=/, we see a serious debugging tool!

The Counter app, using Flutter/MX

The code for our Counter app is here. Yes, just two dozen lines. Lisp can hide a lot.

4. Running other examples.

To try a different example:

  1. kill (^C) any watch you have running;
  2. Switch to the example branch:
git checkout example
  1. start another build/watch as explained above; and
  2. the latest example app should appear in your chosen device.

5. The Flutter/MX version of TodoMVC

To run the f/mx version of TodoMVC:

  1. If not on the example branch, git checkout example;
  2. Edit examples/example/driver.cljc;
  3. Change the function select to be:
    (defn select []
       (todo/make-app))
    
  4. Run as described above.

Here is a TodoMVC screenshot:

f/mx TodoMVC screenshot

Our TodoMVC extends the official spec to include a bit of async handling, in the form of an XHR request: we require an async XHR lookup of the text of a ToDo against the OpenFDA Adverse Events registry. If the lookup succeeds, the text color of the Todo must be set to red. There is no point to this, except as a demonstration of how to make a non-reactive API such as XHR reactive, thus handling async gracefully.

Well, it also demonstrates the power of reactive programming: if we change a ToDo item, a new lookup is triggered automatically, and the text color gets reconsidered automatically once the new lookup responds.

Workflow

Here is how I work. We will extend this section greatly as we help others get started on Matrix:

  • start with the above;
  • edit this project in IntelliJ+Cursive, with the Flutter plug-in installed;
    • IMPORTANT: tell IntelliJ to use clj formatting for .cljd files; more Cursive support is on the way;
  • after making changes, I save in IntelliJ and check the "build" terminal for errors;
  • if all is well, the app will have also done a hot reload. so I check the sim;
  • if I do not see my changes, I switch to the launch terminal and hit return, which does a hot restart;
  • if I am curious about some CLJD issue, such as how to run the Math abs method, I do this:
    • add snippets of code to the main function, after the test suite runner;
    • save;
    • check the "build" for errors;
    • switch to the build terminal and hit Return to trigger a sim reload;
    • check the Flutter console for print output.

Ping @kennytilton on #clojurians or #fluttercommunity Slack for help!

More Repositories

1

cells

A Common Lisp implementation of the dataflow programming paradigm
Common Lisp
211
star
2

matrix

Fine-grained, transparent data flow between generative objects.
HTML
178
star
3

qooxlisp

The Last Web App Framework You Will Ever Evaluate: qooxdoo, Lisp, and Cells
JavaScript
46
star
4

whoshiring

A browser for Hacker News's Ask HN: Who's Hiring, with Matrix Inside(tm)
JavaScript
28
star
5

web-mx

A Web Un-Framework, with fine-grained, transparent reactivity all the way down.
Clojure
27
star
6

mxtodomvc

The TodoMVC Classic implemented with mxWeb and Matrix
Clojure
24
star
7

rube

A pure dataflow aka reactive library for building Clojure or ClojureScript models that run by themselves (like Rube Goldberg Machines). Includes Qxia, a mobile app development framewor based on qooxdoo mobile.
JavaScript
22
star
8

its-alive

A Clojure dataflow library for building application models that run by themselves. It's alive!(tm) Starting out as a literal translation of my Common Lisp Cells library.
Common Lisp
21
star
9

utils-kt

Generic hacks used in any project
Common Lisp
15
star
10

celtk

A Common Lisp wrapper of Tcl/Tk, with Cells Inside(tm)
Common Lisp
13
star
11

kennytilton.github.io

Currently just the home for live demos of JS and CLJS variants of sundry Matrix toy apps.
HTML
12
star
12

Cello

A Cells Inside(tm) desktop UI framework rendered by OpenGL
Tcl
9
star
13

MatrixJS

Lightweight yet powerful JS and CLJS frameworks united by a custom dataflow/reactive hack.
JavaScript
8
star
14

SimpleJX

A Web un-framework as simple as HTML with reactive power all the way down.
Clojure
4
star
15

mxweb

The web application un-framework for the Matrix (dataflow library)
Clojure
4
star
16

flutter-mx-sandbox

Flutter/MX examples
Clojure
4
star
17

gui-geometry

Generic layout widget with the same nested thinking as OpenGL
Common Lisp
4
star
18

flutter-mx-starter

A skeleton repo with a sample ClojureDart + Flutter/MX sample app, to help you build your own.
Clojure
4
star
19

kt-opengl

Kenny's rough, incomplete, unfancy OpenGL CFFI bindings because he cannot abide cl-opengl
Common Lisp
4
star
20

cffi-extender

A few tricks to facilitate converting a C header file into CFFI definitions.
Common Lisp
3
star
21

peoplesort

A people database manager app.
Clojure
2
star
22

mxweb-trainer

A learn-by-doing project for Matrix and mxWeb
Clojure
2
star
23

ciWeb

A pure JS web application framework thinly wrapping HTML and CSS, with Cells Inside(tm)
JavaScript
2
star
24

hiringagent

The latest, greatest version of the ClojureScript Reagent version of my AskHN Who's Hiring browser
HTML
2
star
25

learning-datomic

Join me as I learn Datomic by writing code and seeing what happens.
Clojure
2
star
26

qxia

A Clojurescript qooxdoo wrapper with Cells Inside(tm)
JavaScript
2
star
27

cells-npm

Transparent reactive state manager for JS via NPM/Node.js
JavaScript
1
star
28

model-npm

Reactive models for Node
JavaScript
1
star
29

web-mx-workshop

Where one can learn how to Web/MX by following the evolution of Web/MX-based projects.
Clojure
1
star
30

todomx

The TodoMVC Classic implemented with the Matrix (JS and CLJS dataflow projects)
HTML
1
star
31

web-mx-sampler

Web/MX samples and examples under one repo
Clojure
1
star
32

concurtimes

Printing text from five sources in side-by-side columns nicely.
Clojure
1
star
33

spammer

Proof-of-concept full stack CLJS mxWeb front-end and CLJ Matrix+Ring back end wrapping a REST API. Gasp.
Clojure
1
star