Skip to content

Integrate the real LUI Kotlin backend (KotlinHost) - #38

Merged
tiensonqin merged 3 commits into
mainfrom
devin/kotlin-host-integration
Oct 7, 2026
Merged

tiensonqin merged 3 commits into
mainfrom
devin/kotlin-host-integration

Conversation

@tiensonqin

@tiensonqin tiensonqin commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Integrates the real LUI Kotlin backend (logseq/lui#135, merged as lui@afeb4cc) and renames the Android host profile FlutterHost → KotlinHost end to end. The vendored android/lui shim is gone; :lui now resolves to ../lui/platform/android/lui as a module include — the same consumption model as lui's examples/components/android and apple/'s path-dep on ../lui/platform/apple.

  • logseq_chat.opam: lui pin bumped a2d1cfa → afeb4cc82c346deddb304248fd74d102b5907863 (feat(android): Kotlin/Jetpack Compose backend lui#135, merged).
  • Host codes (matching components_bridge.ml in lui: 1 Web, 2 SwiftUI, 4 Kotlin, 6 GPUI): Native_bridge.host_kind is now the full table; logseq_chat_lui_initialize call sites use hostCode = 4 on Android (LogseqChatNativeBridge.initialize) and 2 on iOS (LGChatRuntime.start — previously defaulted to 1, which now resolves to WebHost).
  • shared/: every FlutterHost → KotlinHost, android/flutter → android/kotlin in extension profile strings and the fingerprint literals in app_test.ml, apple/ extension fingerprints, and ChatExtensions.kt; all flutter_* identifiers renamed to kotlin_*. rg -il flutter is now zero outside .git/_build/duniverse.
  • shared/ reactive migration: the new lui.ppx expands a bare reactive f s to dyn f s (element position, f : 'a -> t). All bare reactive calls feeding *_signal setters and let bindings are now explicit Signal.map; ~p:(reactive ..) labeled forms are unchanged so the ppx still produces prop signals.
  • LuiDispatch: handles the widened upstream LuiEvent sealed class — PressDetail, Pointer{Down,Up,Enter,Leave}, ContextMenuPress, PressModifiers, Load are dropped because the chat FFI (logseq_chat_core_ffi.h) exports no entries for them, matching upstream dispatchToBridge's treatment of unmapped events.
  • android/settings.gradle.kts: include(":lui") with projectDir = ../../lui/platform/android/lui. :lui test tasks are disabled in this build — its paparazzi suite needs the standalone AGP 8.6.1 platform/android build.

Drift between my vendored dev.lui surface and the real backend

Minimal — every symbol the app imports (LuiBackend, LuiEvent, LuiExtensionContext, LuiExtensionRegistry, LuiIconResolver, LocalLuiThemeDark) exists upstream with the same shape. The only deltas handled:

  1. LuiEvent grew the pointer/context-menu/load variants listed above.
  2. AGP version mismatch (needs upstream attention): platform/android/lui/build.gradle.kts applies org.jetbrains.kotlin.android + plugin.serialization + app.cash.paparazzi under AGP 8.6.1, while this app uses AGP 9.1 (android.builtInKotlin) — Gradle forbids mixed AGP versions in one build, and AGP 9 dropped the kotlin-android plugin. To verify locally I edited the ../lui checkout to drop those three plugin ids (no @Serializable types exist, and paparazzi is only needed by the backend's own tests). That edit is local-only — the lui repo should ship an AGP-9-compatible module build (or the host must stay on AGP 8).

Verification

  • dune build @shared/native/runtest — 719 tests green.
  • cd android && ./gradlew assembleDebug assembleProfile test — green against the real backend (:app unit tests pass; :lui tests disabled as noted).
  • test-android-native-script.sh, test-no-skip-support.sh, test-android-e2e-runner.sh pass.
  • Fresh liblogseq_chat_core.so (x86_64) + profile APK on the chat_test emulator: app launches, take_effect/apply_snapshot/apply_host_update cycle confirmed in logcat, auth screen renders via the real backend:

auth screen via real LUI Kotlin backend

Link to Devin session: https://app.devin.ai/sessions/c2d54f90729342239d4afea72f403e41
Open in Devin Desktop: https://app.devin.ai/desktop/session/c2d54f90729342239d4afea72f403e41?variant=devin
Requested by: @tiensonqin

- Bump the lui pin to 264aa9f67da0d0d3e413f9dfe970785e7286f23c
  (logseq/lui#135; re-pin to the merge SHA once that PR lands).
- Rename every FlutterHost reference in shared/ to KotlinHost and
  android/flutter -> android/kotlin in extension profiles, fingerprints,
  and all flutter_* identifiers/comments; host code 4 now maps to
  KotlinHost (matching lui's components_bridge.ml table: 1 Web,
  2 SwiftUI, 4 Kotlin, 6 GPUI), so iOS passes host code 2 and Android 4.
- shared/: bare 'reactive' calls rewritten to Signal.map — the new
  lui.ppx expands bare reactive to dyn in element position while
  ~p:(reactive ..) labeled forms are kept for prop signals.
- Delete the vendored android/lui module; :lui now resolves to
  ../lui/platform/android/lui via module include, the same consumption
  model as lui's examples/components/android.
- LuiDispatch handles the widened LuiEvent sealed class (pointer,
  context-menu, load events have no chat FFI export and are dropped,
  matching upstream dispatchToBridge).
- Disable :lui test tasks in this build; the backend's paparazzi
  tests need its standalone AGP 8.6.1 build.

Verification: dune build @shared/native/runtest (719 tests),
./gradlew assembleDebug assembleProfile test all green against the
real backend; profile APK runs on the chat_test emulator with a fresh
x86_64 liblogseq_chat_core.so and renders the auth screen.
@devin-ai-integration

Copy link
Copy Markdown

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

The minimal LuiExtensionRegistry.register overload defaults to an empty
properties list, so every set-extension-prop op was rejected (e.g.
native-navigation-stack.depth), leaving the retained tree wedged after
the first navigation patch. Declare the schemas matching each fingerprint.
@tiensonqin
tiensonqin merged commit 075ca02 into main Oct 7, 2026
@tiensonqin
tiensonqin deleted the devin/kotlin-host-integration branch October 7, 2026 04:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant