From 5a107aa06943f9da48a56af9e06782bfdba35d20 Mon Sep 17 00:00:00 2001 From: Michael Chavinda Date: Thu, 4 Jun 2026 01:43:35 -0700 Subject: [PATCH] feat: Update native FFI to new API and port geoquiz example --- .github/workflows/ci.yml | 37 ++ .gitignore | 22 +- README.md | 151 ++++++-- build/META-INF/MANIFEST.MF | 3 - compile | 97 ----- compile.ps1 | 47 --- examples/counter/build.gradle.kts | 32 ++ examples/counter/src/frege/app/Counter.fr | 27 ++ examples/counter/src/main/AndroidManifest.xml | 21 ++ .../counter/src/main/res/values/strings.xml | 4 + .../counter/src/main/res/values/themes.xml | 6 + examples/geoquiz/build.gradle.kts | 32 ++ examples/geoquiz/src/frege/app/GeoQuiz.fr | 57 +++ examples/geoquiz/src/main/AndroidManifest.xml | 21 ++ .../geoquiz/src/main/res/values/strings.xml | 4 + .../geoquiz/src/main/res/values/themes.xml | 4 + froid-gradle-plugin/build.gradle.kts | 31 ++ froid-gradle-plugin/settings.gradle.kts | 1 + .../mchav/froid/gradle/FregeAndroidPlugin.kt | 115 ++++++ .../github/mchav/froid/gradle/FregeCompile.kt | 75 ++++ froid.gradle | 65 ---- froid/build.gradle.kts | 42 +++ froid/src/frege/froid/app/Activity.fr | 19 + froid/src/frege/froid/content/Context.fr | 4 + froid/src/frege/froid/frp/Signal.fr | 95 +++++ froid/src/frege/froid/ui/App.fr | 195 ++++++++++ froid/src/frege/froid/ui/Widget.fr | 70 ++++ froid/src/frege/froid/view/View.fr | 44 +++ froid/src/frege/froid/widget/Widgets.fr | 88 +++++ froid/src/main/AndroidManifest.xml | 2 + .../main/java/froid/app/FregeActivity.java | 42 +++ gradle.properties | 3 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43504 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 252 +++++++++++++ gradlew.bat | 94 +++++ libs/frege-compiler-snapshot.jar | Bin 0 -> 12265557 bytes package | 3 - package.bat | 3 - settings.gradle.kts | 35 ++ src/frege/froid/Types.fr | 16 - src/frege/froid/animation/Animator.fr | 39 -- src/frege/froid/app/ActionBar.fr | 14 - src/frege/froid/app/Activity.fr | 30 -- src/frege/froid/app/Dialog.fr | 10 - src/frege/froid/app/java/NativeActivity.fr | 107 ------ src/frege/froid/content/Context.fr | 13 - src/frege/froid/content/Intent.fr | 24 -- src/frege/froid/content/res/AssetManager.fr | 10 - src/frege/froid/content/res/Configuration.fr | 10 - src/frege/froid/graphics/Typeface.fr | 13 - src/frege/froid/java/nio/ByteBuffer.fr | 20 - src/frege/froid/java/nio/CharBuffer.fr | 10 - src/frege/froid/java/nio/DoubleBuffer.fr | 10 - src/frege/froid/java/nio/IntBuffer.fr | 12 - src/frege/froid/java/nio/LongBuffer.fr | 10 - src/frege/froid/java/nio/ShortBuffer.fr | 10 - .../froid/java/util/concurrent/TimeUnit.fr | 10 - .../microedition/khronos/egl/EGLConfig.fr | 10 - .../microedition/khronos/opengles/GL10.fr | 65 ---- src/frege/froid/media/MediaPlayer.fr | 16 - src/frege/froid/opengl/GLSurfaceView.fr | 128 ------- .../froid/opengl/glSurfaceView/Delegator.fr | 17 - .../froid/opengl/glSurfaceView/Renderer.fr | 15 - .../glSurfaceView/java/NativeRenderer.fr | 56 --- .../glSurfaceView/renderer/Delegator.fr | 17 - src/frege/froid/os/AsyncTask.fr | 14 - src/frege/froid/os/Build.fr | 12 - src/frege/froid/os/Bundle.fr | 20 - src/frege/froid/os/Handler.fr | 12 - src/frege/froid/text/Editable.fr | 14 - src/frege/froid/text/Spannable.fr | 11 - src/frege/froid/text/TextWatcher.fr | 72 ---- src/frege/froid/text/format/DateFormat.fr | 12 - .../froid/text/style/ForegroundColorSpan.fr | 11 - src/frege/froid/util/Log.fr | 13 - src/frege/froid/view/ContextMenu.fr | 12 - src/frege/froid/view/InputDevice.fr | 10 - src/frege/froid/view/InputEvent.fr | 10 - src/frege/froid/view/LayoutInflator.fr | 16 - src/frege/froid/view/Menu.fr | 10 - src/frege/froid/view/MenuInflater.fr | 13 - src/frege/froid/view/MenuItem.fr | 11 - src/frege/froid/view/MotionEvent.fr | 14 - src/frege/froid/view/View.fr | 43 --- src/frege/froid/view/ViewAnimationUtils.fr | 14 - src/frege/froid/view/ViewGroup.fr | 10 - src/frege/froid/view/animation/Animation.fr | 10 - src/frege/froid/widget/Button.fr | 38 -- src/frege/froid/widget/CheckBox.fr | 31 -- src/frege/froid/widget/CompoundButton.fr | 33 -- src/frege/froid/widget/EditText.fr | 37 -- src/frege/froid/widget/ImageView.fr | 11 - src/frege/froid/widget/LineNumberEditText.fr | 37 -- src/frege/froid/widget/ScrollView.fr | 29 -- src/frege/froid/widget/SeekBar.fr | 27 -- src/frege/froid/widget/TextView.fr | 38 -- src/frege/froid/widget/Toast.fr | 16 - src/frege/froid/widget/Toolbar.fr | 10 - src/java/LineNumberEditText.java | 126 ------- src/java/LineNumberTextView.java | 343 ------------------ tools/build-frege-snapshot.sh | 58 +++ 102 files changed, 1667 insertions(+), 2073 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 build/META-INF/MANIFEST.MF delete mode 100755 compile delete mode 100644 compile.ps1 create mode 100644 examples/counter/build.gradle.kts create mode 100644 examples/counter/src/frege/app/Counter.fr create mode 100644 examples/counter/src/main/AndroidManifest.xml create mode 100644 examples/counter/src/main/res/values/strings.xml create mode 100644 examples/counter/src/main/res/values/themes.xml create mode 100644 examples/geoquiz/build.gradle.kts create mode 100644 examples/geoquiz/src/frege/app/GeoQuiz.fr create mode 100644 examples/geoquiz/src/main/AndroidManifest.xml create mode 100644 examples/geoquiz/src/main/res/values/strings.xml create mode 100644 examples/geoquiz/src/main/res/values/themes.xml create mode 100644 froid-gradle-plugin/build.gradle.kts create mode 100644 froid-gradle-plugin/settings.gradle.kts create mode 100644 froid-gradle-plugin/src/main/kotlin/io/github/mchav/froid/gradle/FregeAndroidPlugin.kt create mode 100644 froid-gradle-plugin/src/main/kotlin/io/github/mchav/froid/gradle/FregeCompile.kt delete mode 100644 froid.gradle create mode 100644 froid/build.gradle.kts create mode 100644 froid/src/frege/froid/app/Activity.fr create mode 100644 froid/src/frege/froid/content/Context.fr create mode 100644 froid/src/frege/froid/frp/Signal.fr create mode 100644 froid/src/frege/froid/ui/App.fr create mode 100644 froid/src/frege/froid/ui/Widget.fr create mode 100644 froid/src/frege/froid/view/View.fr create mode 100644 froid/src/frege/froid/widget/Widgets.fr create mode 100644 froid/src/main/AndroidManifest.xml create mode 100644 froid/src/main/java/froid/app/FregeActivity.java create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 libs/frege-compiler-snapshot.jar delete mode 100755 package delete mode 100644 package.bat create mode 100644 settings.gradle.kts delete mode 100644 src/frege/froid/Types.fr delete mode 100644 src/frege/froid/animation/Animator.fr delete mode 100644 src/frege/froid/app/ActionBar.fr delete mode 100644 src/frege/froid/app/Activity.fr delete mode 100644 src/frege/froid/app/Dialog.fr delete mode 100644 src/frege/froid/app/java/NativeActivity.fr delete mode 100644 src/frege/froid/content/Context.fr delete mode 100644 src/frege/froid/content/Intent.fr delete mode 100644 src/frege/froid/content/res/AssetManager.fr delete mode 100644 src/frege/froid/content/res/Configuration.fr delete mode 100644 src/frege/froid/graphics/Typeface.fr delete mode 100644 src/frege/froid/java/nio/ByteBuffer.fr delete mode 100644 src/frege/froid/java/nio/CharBuffer.fr delete mode 100644 src/frege/froid/java/nio/DoubleBuffer.fr delete mode 100644 src/frege/froid/java/nio/IntBuffer.fr delete mode 100644 src/frege/froid/java/nio/LongBuffer.fr delete mode 100644 src/frege/froid/java/nio/ShortBuffer.fr delete mode 100644 src/frege/froid/java/util/concurrent/TimeUnit.fr delete mode 100644 src/frege/froid/javax/microedition/khronos/egl/EGLConfig.fr delete mode 100644 src/frege/froid/javax/microedition/khronos/opengles/GL10.fr delete mode 100644 src/frege/froid/media/MediaPlayer.fr delete mode 100644 src/frege/froid/opengl/GLSurfaceView.fr delete mode 100644 src/frege/froid/opengl/glSurfaceView/Delegator.fr delete mode 100644 src/frege/froid/opengl/glSurfaceView/Renderer.fr delete mode 100644 src/frege/froid/opengl/glSurfaceView/java/NativeRenderer.fr delete mode 100644 src/frege/froid/opengl/glSurfaceView/renderer/Delegator.fr delete mode 100644 src/frege/froid/os/AsyncTask.fr delete mode 100644 src/frege/froid/os/Build.fr delete mode 100644 src/frege/froid/os/Bundle.fr delete mode 100644 src/frege/froid/os/Handler.fr delete mode 100644 src/frege/froid/text/Editable.fr delete mode 100644 src/frege/froid/text/Spannable.fr delete mode 100644 src/frege/froid/text/TextWatcher.fr delete mode 100644 src/frege/froid/text/format/DateFormat.fr delete mode 100644 src/frege/froid/text/style/ForegroundColorSpan.fr delete mode 100644 src/frege/froid/util/Log.fr delete mode 100644 src/frege/froid/view/ContextMenu.fr delete mode 100644 src/frege/froid/view/InputDevice.fr delete mode 100644 src/frege/froid/view/InputEvent.fr delete mode 100644 src/frege/froid/view/LayoutInflator.fr delete mode 100644 src/frege/froid/view/Menu.fr delete mode 100644 src/frege/froid/view/MenuInflater.fr delete mode 100644 src/frege/froid/view/MenuItem.fr delete mode 100644 src/frege/froid/view/MotionEvent.fr delete mode 100644 src/frege/froid/view/View.fr delete mode 100644 src/frege/froid/view/ViewAnimationUtils.fr delete mode 100644 src/frege/froid/view/ViewGroup.fr delete mode 100644 src/frege/froid/view/animation/Animation.fr delete mode 100644 src/frege/froid/widget/Button.fr delete mode 100644 src/frege/froid/widget/CheckBox.fr delete mode 100644 src/frege/froid/widget/CompoundButton.fr delete mode 100644 src/frege/froid/widget/EditText.fr delete mode 100644 src/frege/froid/widget/ImageView.fr delete mode 100644 src/frege/froid/widget/LineNumberEditText.fr delete mode 100644 src/frege/froid/widget/ScrollView.fr delete mode 100644 src/frege/froid/widget/SeekBar.fr delete mode 100644 src/frege/froid/widget/TextView.fr delete mode 100644 src/frege/froid/widget/Toast.fr delete mode 100644 src/frege/froid/widget/Toolbar.fr delete mode 100644 src/java/LineNumberEditText.java delete mode 100644 src/java/LineNumberTextView.java create mode 100755 tools/build-frege-snapshot.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3048b3d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # JDK 17 satisfies both the Frege source build (-source 1.8) and AGP 8. + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "17" + + - name: Cache Frege snapshot + id: frege-cache + uses: actions/cache@v4 + with: + path: libs/frege-compiler-snapshot.jar + # Bump when tools/build-frege-snapshot.sh pins a new commit. + key: frege-067cad05 + + - name: Build Frege compiler from pinned master + if: steps.frege-cache.outputs.cache-hit != 'true' + run: tools/build-frege-snapshot.sh + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Assemble debug APK + run: ./gradlew :app:assembleDebug --stacktrace diff --git a/.gitignore b/.gitignore index 23a7cdc..a66088d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,21 @@ -build/* -lib/* +# Gradle / build outputs (any depth: froid/, examples/*/, froid-gradle-plugin/) +**/build/ +**/.gradle/ +.gradle/ +.kotlin/ + +# Android Studio / IntelliJ +.idea/ +*.iml +local.properties +captures/ +.cxx/ + +# OS +.DS_Store +Thumbs.db + +# Jars are ignored by default, EXCEPT the vendored Frege snapshot + the wrapper. *.jar +!libs/frege-compiler-snapshot.jar +!gradle/wrapper/gradle-wrapper.jar diff --git a/README.md b/README.md index c13cb61..9a5aa31 100644 --- a/README.md +++ b/README.md @@ -2,40 +2,149 @@ -A library for using the Frege programming language in Android development. +Write Android apps in the **Frege** programming language (Haskell on the JVM) — +pure Frege, no Kotlin, with much less ceremony than the original thanks to +Frege's new [automated FFI](https://github.com/Frege/frege/pull/400). -## Usage and examples +froid is two things: -To get/setup froid read the instructions on the [froid Wiki](https://github.com/mchav/froid/wiki). To write a simple application from scratch follow [this step-by-step tutorial](https://github.com/mchav/froid/wiki/Tutorial). +1. **A general Frege-on-Android library** — thin handles over `android.view` / + `android.widget` / `android.app`, with the boilerplate erased by auto-FFI and + the irreducible glue (the Activity, callbacks) hidden in the library. App code + writes no Java and no Kotlin. +2. **A declarative UI in the Elm Architecture, backed by FRP** — built on the + View system. You write `update :: Msg -> Model -> Model` and + `view :: Signal Model -> Ui Msg`; froid keeps the views in sync. + +## A counter, in full -Simple Activity ---------------- ```frege -module io.github.mchav.fregeandroid.FregeActivity where +module app.Counter where import froid.app.Activity -import froid.content.Context -import froid.os.Bundle -import froid.widget.TextView +import froid.ui.App +import froid.frp.Signal + +native module type Activity where {} -- the one line that makes this an Activity + +data Msg = Increment + +update :: Msg -> Int -> Int +update Increment n = n + 1 + +view :: Signal Int -> Ui Msg +view model = column + [ dynText (fmap (\n -> "Count: " ++ show n) model) + , button "Increment" Increment + ] + +counter :: App Int Msg +counter = App { initial = 0, update = update, view = view } + +onCreate :: Activity -> IO () +onCreate this = runApp this counter +``` + +No `findViewById`, no listeners by hand, no XML, no Kotlin. Buttons carry the +`Msg` they dispatch; state evolves in one place (`update`). + +## The Elm Architecture (`froid.ui.App`) + +- `App { initial, update, view }` — your whole program. +- `runApp :: Activity -> App model msg -> IO ()` — installs it. +- Widgets: `text` / `dynText` / `headline` / `button` / `primaryButton` / + `flatButton` / `column` / `row` / `gap` / `flexSpacer`. `view` takes a + `Signal model`, so only the labels whose text changed are redrawn. + +## The FRP core (`froid.frp.Signal`) + +A small, discrete, push-based FRP — the natural Frege idiom for reactive UIs: + +- `Event a` — a stream of occurrences: `newEvent`, `fmap`, `never`, `mergeE`, + `filterE`, `snapshot`/`tag`. +- `Signal a` — a value over time: `accumS` (Elm's `foldp`), `stepper`, `react`, + `fmap`. The accumulator is strict (no `foldl` leak); the UI thread is + single-threaded so cells need no locking. + +The Elm `App` layer funnels every `Msg` through one event, so app authors rarely +touch these directly — they're there when you want raw reactive wiring. + +## How an Activity works (no glue in app code) + +A module becomes an Android Activity with one line, `native module type Activity +where {}` — its generated class extends `froid.app.FregeActivity` (plain Java in +the library), which bridges Android's `onCreate` to your +`onCreate :: Activity -> IO ()`. The manifest points at the module class +(e.g. `app.Counter`). + +## Repository layout + +``` +froid/ the library (pure Frege + a tiny Java Activity base) + src/frege/froid/… frp/Signal, ui/App, view, widget, content, app + src/main/java/… froid.app.FregeActivity (the only Java; precompiled) +froid-gradle-plugin/ the publishable Gradle plugin (id "io.github.mchav.froid"), + included as a build; wires Frege compilation into AGP +examples/ + counter/ minimal counter + geoquiz/ GeoQuiz — true/false quiz with color-coded feedback +libs/ vendored Frege compiler snapshot +``` + +The top level holds no Android config — `android { … }` lives only in the module +build files, not at the root. + +### Using froid in your own app + +```kotlin +plugins { + id("com.android.application") + id("io.github.mchav.froid") // wires Frege compilation +} +dependencies { implementation("io.github.mchav:froid:…") } +// write your UI in src/frege/, point the manifest at your module class +``` + +## Building + +### 1. Build the Frege compiler (one-time) + +froid needs the auto-FFI compiler from Frege `master` (PR #400; no release has it +yet). The script pins a known-good commit and vendors the jar to `libs/`. + +**Requirements:** a JDK in the **8–17** range (17 recommended), `make`, `curl`, +`jar`. `byacc` is not needed. + +```bash +JAVA_HOME=/path/to/jdk17 tools/build-frege-snapshot.sh +``` -native module type Activity where {} +### 2. Build and run a sample -onCreate :: Activity -> Maybe Bundle -> IO () -onCreate this bundle = do - tv <- TextView.new this - tv.setText "Hello, Android - Love, Frege" - this.setContentView tv +```bash +./gradlew :geoquiz:assembleDebug +./gradlew :geoquiz:installDebug # onto a running emulator/device +# or open in Android Studio and press Run ``` -## Example +`compileFrege` (from `froid-gradle-plugin`) runs the Frege compiler over +each module's `src/frege`, generating Java that AGP compiles and dexes. -You can find a more involved example [here](https://github.com/mchav/GeoQuiz-Frege). More will be available soon. +## Status +**Builds and runs.** `:geoquiz` and `:counter` assemble to APKs and run on an +emulator (AGP 8.13, compileSdk 36): the question renders, True/False checks the +answer with color-coded feedback, and Prev/Next navigate — all driven by the +Frege FRP. -## Building froid +**Roadmap:** more widgets (EditText, images, lists with stable keys); the deeper +FRP correctness items (subscription disposal for rotation, transactional +glitch-freedom) are noted but not needed by the current static view tree; folding +more of the original View bindings back in where useful (they remain in git +history on `master`). -Run `compile` and then `package`. +Frege `master` is pinned at commit `067cad057385d36134812bde3fc1b453e5274855`. -## Contributing +## License -A lot of what there is to do is create the bindings for the other types in `android`. For classes such as adapters/fragments read [this](http://mchav.github.io/functional-inheritance-in-android/) to learn about the design philosophy for subclassing. Any PRs of this nature are welcome. +Apache License 2.0. froid is © Michael Chavinda and contributors. diff --git a/build/META-INF/MANIFEST.MF b/build/META-INF/MANIFEST.MF deleted file mode 100644 index b24b53d..0000000 --- a/build/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Created-By: 1.7.0_65 (Oracle Corporation) - diff --git a/compile b/compile deleted file mode 100755 index aa50de0..0000000 --- a/compile +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash - -mkdir -p ./lib - -if [ ! -e ./lib/frege.jar ] -then - echo "Downloading Frege version 3.24..." - wget -O ./lib/frege.jar https://github.com/Frege/frege/releases/download/3.24alpha/frege3.24-7.100.jar -fi - -# default to Linux installation. -ANDROID_SDK=$HOME"/Android/Sdk" - -unamestr=`uname` -if [[ "$unamestr" == 'Darwin' ]]; then - ANDROID_SDK=$HOME"/Library/Android/sdk" -fi - -ANDROID_PLATFORMS=$ANDROID_SDK"/platforms" - -# get latest Android Version Number -function get_latest_android_version() { - versions=() - - for filename in $ANDROID_PLATFORMS/*; do - version=${filename: -2} - versions+=($version) - done - - IFS=$'\n' - echo "${versions[*]}" | sort -nr | head -n1 - -} - -ANDROID_JAR_PATH=$ANDROID_PLATFORMS"/android-"$(get_latest_android_version) - -# echo $ANDROID_SDK - -rtjar=$(java -verbose 2>/dev/null | head -n 1 | cut -c 9- | rev | cut -c 2- | rev) - -# compile vanilla Java Source files. -javac -cp "./lib/*:$ANDROID_JAR_PATH/*" -bootclasspath $rtjar -source 1.7 -target 1.7 -d ./build ./src/java/* - -fregec="java -Xmx6072m -Xss10M -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xverify:none -cp \"./lib/*:$ANDROID_JAR_PATH/*\" frege.compiler.Main -target 1.7 -d ./build" - -# takes a list of files and compiles each of them. -function compile_files { - arr=("$@") - for f in "${arr[@]}"; do - eval $fregec "$f" - done -} - -# modules with no dependencies. -declare -a no_deps=( -"./src/frege/froid/view/View.fr" -"./src/frege/froid/view/ViewGroup.fr" -"./src/frege/froid/widget/CompoundButton.fr" -"./src/frege/froid/view/Menu.fr" -"./src/frege/froid/Types.fr" -"./src/frege/froid/content/res" -"./src/frege/froid/java/nio/IntBuffer.fr" -"./src/frege/froid/animation" -"./src/frege/froid/text/style" -"./src/frege/froid/util" -) - -# compile modules with no dependencies. -compile_files "${no_deps[@]}" - -# modules with dependencies -declare -a with_deps=( -"./src/frege/froid/text/Editable.fr" -"./src/frege/froid/text" -"./src/frege/froid/content/Context.fr" -"./src/frege/froid/content/Intent.fr" -"./src/frege/froid/media" -"./src/frege/froid/graphics" -"./src/frege/froid/os" -"./src/frege/froid/widget" -"./src/frege/froid/view" -"./src/frege/froid/content/res" -"./src/frege/froid/app/java" -"./src/frege/froid/app" -"./src/frege/froid/app/Activity.fr" -"./src/frege/froid/java" -"./src/frege/froid/javax" -"./src/frege/froid/opengl/glSurfaceView/renderer" -"./src/frege/froid/opengl/glSurfaceView/java" -"./src/frege/froid/opengl/glSurfaceView" -"./src/frege/froid/opengl/GLSurfaceView.fr" -) - -# compile modules with dependencies. -compile_files "${with_deps[@]}" - - diff --git a/compile.ps1 b/compile.ps1 deleted file mode 100644 index b0a2e94..0000000 --- a/compile.ps1 +++ /dev/null @@ -1,47 +0,0 @@ -(mkdir build\froid\app) 2>&1> $null - -$jars = Get-ChildItem -File -Attributes !ReadOnly -path ".\lib" | % { $_.FullName } -$cpJars = [string]::Join(";", $jars) - -($runtime = java -verbose) 2>&1> $null - -$s = ($runtime -split '\n')[0] -$rtjar = $s.Substring(8, $s.length - 9) - -# compile frege -$fregec = "java -Xmx6072m -Xss10M -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xverify:none -cp `"$cpJars`" frege.compiler.Main -target 1.7 -d .\build" - -# compile java files -javac -cp """$cpJars""" -bootclasspath """$rtjar""" -source 1.7 -target 1.7 -d .\build .\src\java\* - -# compile modules with no dependencies -# Invoke-Expression "$fregec .\src\frege\froid\view\View.fr" -# Invoke-Expression "$fregec .\src\frege\froid\view\ViewGroup.fr" -# Invoke-Expression "$fregec .\src\frege\froid\widget\CompoundButton.fr" -# Invoke-Expression "$fregec .\src\frege\froid\view\Menu.fr" -# Invoke-Expression "$fregec .\src\frege\froid\Types.fr" -# Invoke-Expression "$fregec .\src\frege\froid\content\res" -# Invoke-Expression "$fregec .\src\frege\froid\java\nio\IntBuffer.fr" -# Invoke-Expression "$fregec .\src\frege\froid\animation" -# Invoke-Expression "$fregec .\src\frege\froid\text\style" -# Invoke-Expression "$fregec .\src\frege\froid\util" - -# compile modules with already compiled dependencies -Invoke-Expression "$fregec .\src\frege\froid\media" -# Invoke-Expression "$fregec .\src\frege\froid\text\Editable.fr" -# Invoke-Expression "$fregec .\src\frege\froid\text" -# Invoke-Expression "$fregec .\src\frege\froid\content\Context.fr" -# Invoke-Expression "$fregec .\src\frege\froid\content\Intent.fr" -# Invoke-Expression "$fregec .\src\frege\froid\graphics" -# Invoke-Expression "$fregec .\src\frege\froid\os" -# Invoke-Expression "$fregec .\src\frege\froid\widget" -# Invoke-Expression "$fregec .\src\frege\froid\view" -# Invoke-Expression "$fregec .\src\frege\froid\content\res" -# Invoke-Expression "$fregec .\src\frege\froid\app\java" -# Invoke-Expression "$fregec .\src\frege\froid\app" -# Invoke-Expression "$fregec .\src\frege\froid\app\Activity.fr" -# Invoke-Expression "$fregec .\src\frege\froid\java" -# Invoke-Expression "$fregec .\src\frege\froid\javax" -# Invoke-Expression "$fregec .\src\frege\froid\opengl\glSurfaceView\java" -# Invoke-Expression "$fregec .\src\frege\froid\opengl\glSurfaceView" -# Invoke-Expression "$fregec .\src\frege\froid\opengl\GLSurfaceView.fr" diff --git a/examples/counter/build.gradle.kts b/examples/counter/build.gradle.kts new file mode 100644 index 0000000..4196880 --- /dev/null +++ b/examples/counter/build.gradle.kts @@ -0,0 +1,32 @@ +plugins { + id("com.android.application") + id("io.github.mchav.froid") +} + +android { + namespace = "io.github.mchav.froid.sample" + compileSdk = 36 + + defaultConfig { + applicationId = "io.github.mchav.froid.sample" + minSdk = 24 + targetSdk = 36 + versionCode = 1 + versionName = "0.1.0" + } + + buildTypes { + release { + isMinifyEnabled = false + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } +} + +dependencies { + implementation(project(":froid")) +} diff --git a/examples/counter/src/frege/app/Counter.fr b/examples/counter/src/frege/app/Counter.fr new file mode 100644 index 0000000..311a7b6 --- /dev/null +++ b/examples/counter/src/frege/app/Counter.fr @@ -0,0 +1,27 @@ +{- + A counter, in froid's Elm-architecture API. +-} +module app.Counter where + +import froid.app.Activity +import froid.ui.App +import froid.frp.Signal + +native module type Activity where {} + +data Msg = Increment + +update :: Msg -> Int -> Int +update Increment n = n + 1 + +view :: Signal Int -> Ui Msg +view model = column + [ dynText (fmap (\n -> "Count: " ++ show n) model) + , button "Increment" Increment + ] + +counter :: App Int Msg +counter = App { initial = 0, update = update, view = view } + +onCreate :: Activity -> IO () +onCreate this = runApp this counter diff --git a/examples/counter/src/main/AndroidManifest.xml b/examples/counter/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ec32ed8 --- /dev/null +++ b/examples/counter/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/examples/counter/src/main/res/values/strings.xml b/examples/counter/src/main/res/values/strings.xml new file mode 100644 index 0000000..914d46a --- /dev/null +++ b/examples/counter/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + froid + diff --git a/examples/counter/src/main/res/values/themes.xml b/examples/counter/src/main/res/values/themes.xml new file mode 100644 index 0000000..9453d5d --- /dev/null +++ b/examples/counter/src/main/res/values/themes.xml @@ -0,0 +1,6 @@ + + + +