Skip to content

Finish replay implementation#94

Merged
diegurrio merged 1 commit into
feature/android_appfrom
feature/replay_from_app_shell
May 31, 2026
Merged

Finish replay implementation#94
diegurrio merged 1 commit into
feature/android_appfrom
feature/replay_from_app_shell

Conversation

@diegurrio
Copy link
Copy Markdown
Collaborator

@diegurrio diegurrio commented May 31, 2026

Summary

Completes the in-app Replay experience for the Android app. The app no longer depends on sharing a .ulg into it through Android intents. Instead it has an in-app library you import logs into, a recents shortcut on Home, and touch controls for playback on the renderer.

What's included

In-app log library (feature:replay)

  • Import .ulg files with the system document picker (ACTION_OPEN_DOCUMENT). Each file is copied into app storage (filesDir/library/<id>.ulg) with metadata in Room, so playback works offline and keeps working even if the original file goes away.
  • Recents list showing name, size, and import date. Long press a row to delete it (with a confirmation).
  • Empty state with an "Open file" call to action.

Home recents peek

  • The Home screen shows the three most recent flights below the mode cards. Tapping one plays it directly.

Touch transport overlay on the renderer

  • Play/pause, drag to seek, and a speed control (0.5x / 1x / 2x / 4x), with current and total time.
  • Driven from Compose through a small replay_* JNI control surface into the native engine. The bar lives in a dedicated full width overlay window so it composites above the GL surface and spans the screen edge to edge.

Renderer process isolation

  • The native renderer (HawkeyeActivity) now runs in its own :renderer process and exits cleanly on teardown. This fixes a freeze (ANR) and a rotation crash that could occur after returning from a replay, and guarantees a clean start for every playback.

Cleanup

  • Removed the old share/VIEW intent path (IntentRouterActivity, its intent filters, and the trampoline theme) now that importing happens in app.

Architecture

  • Feature first modules following the project's MVI conventions: presentation (State/Action/Event/ViewModel plus a stateless Screen), domain contracts, and data implementations.
  • Shared contracts (LibraryEntry, ReplayLibraryRepository) live in core:domain and the playback launch seam lives in core:presentation, so the feature modules stay decoupled.
  • Room and KSP were added for the library metadata. The native side gained a thread safe control surface that the render loop applies each frame.

Testing

  • 60 unit tests (ViewModels, repository coordination, file store and staging, formatters) and 8 instrumented tests (navigation and rotation across every screen, plus multi item library behavior).
  • Verified on a Pixel 6 Pro: import, recents, playback with the transport controls, and returning to the shell.

Demo

hawkeye_tour.mp4

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR replaces the inbound share/VIEW/SEND flow on Android with an in-app replay library (Room-backed metadata + on-disk payloads), adds a Compose touch transport overlay above the native renderer driven via a new JNI control surface, and surfaces recent flights on Home. The native HUD gains a show_transport flag so Android can suppress the built-in transport bar in favor of the overlay. The renderer (HawkeyeActivity) is moved into a separate :renderer process, and the dead IntentRouterActivity/ReplayViewModel/feature:replay:domain module are removed.

Changes:

  • Add ReplayLibraryRepository in core:domain, Room+LibraryFileStore implementation in feature:replay:data, and Compose library + Home recents UIs.
  • Add native replay_control (atomic request/snapshot bridge) and replay_jni so Kotlin NativeReplayController can pause/seek/speed the engine; Compose TransportRoot polls status at 10 Hz and renders in a TYPE_APPLICATION_PANEL window above raylib.
  • Switch Android to run HawkeyeActivity in :renderer (Koin skipped there, hard-exit on destroy); HUD gets show_transport plumbed into layout and hud_bar_height for desktop/WASM compatibility.

Reviewed changes

Copilot reviewed 86 out of 86 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/hud.h, src/hud.c Add show_transport flag; gate transport row + bar height on it.
android/app/src/main/cpp/{android_main.c,replay_jni.c,replay_control.h,CMakeLists.txt} Atomic JNI bridge applied/published each frame; Android disables native HUD transport.
android/app/src/main/java/.../HawkeyeActivity.kt Edge-to-edge, transport panel overlay, hard-halt on destroy, ditches RenderSession extras.
android/app/src/main/java/.../HawkeyeApp.kt Skip Koin in :renderer process.
android/app/src/main/java/.../render/{NativeReplayController.kt,RendererLauncher.kt} + transport/* New ReplayController, TransportViewModel/State/Action/Screen.
android/app/src/main/java/.../replay/AndroidReplayPlaybackLauncher.kt, di/AppModule.kt, shell/AppShell.kt App-provided ReplayPlaybackLauncher and shell wiring.
android/app/src/main/AndroidManifest.xml, res/values/{themes,strings}.xml Drop IntentRouterActivity/share filters/trampoline theme; add :renderer process and transport strings.
android/app/src/main/java/.../IntentRouterActivity.kt, render/RenderSession.kt (+ test) Removed.
android/app/src/test/.../render/transport/*, androidTest/.../{ShellNavigationTest,LibraryRecentsMultiItemTest}.kt New transport unit tests and instrumented shell/library tests.
android/core/domain/{build.gradle.kts,LibraryEntry.kt,ReplayLibraryRepository.kt} New shared library entry + repository contract; expose coroutines-core as api.
android/core/presentation/.../ReplayPlaybackLauncher.kt Seam so features don't depend on :app.
android/feature/replay/data/** Room DB/DAO/entity, RoomReplayLibraryRepository, LibraryFileStore, AndroidReplayFileManager, schema JSON, DI, tests; replaces AndroidUlogInboxDataSource.
android/feature/replay/presentation/** New ReplayLibraryScreen/ViewModel/State/Action/Event + mapper + strings + tests; removes ReplayScreen/ViewModel/... and stale tests.
android/feature/replay/domain/** Module removed; types moved to core:domain.
android/feature/home/presentation/** Home depends on ReplayLibraryRepository, exposes ≤3 recents, stages and launches playback; tests updated.
android/{settings,build}.gradle.kts, gradle/libs.versions.toml, gradle.properties Add KSP + Room versions, drop feature:replay:domain, AGP 9 / KSP source-set opt-in.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@diegurrio diegurrio merged commit 5132d82 into feature/android_app May 31, 2026
1 check passed
@diegurrio diegurrio deleted the feature/replay_from_app_shell branch May 31, 2026 14:49
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.

2 participants