Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .openhands/memory/2026-11-14.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 2026-11-14

## Task: remove the legacy UI (screens/mod menu/splash/tabs/rail/buttons) for a new UI drop-in

### Toolchain (this container had none)
Reinstalled per `docs/agents/recovering-the-build-toolchain-in-a-fresh-container.md`:
`/workspace/tools/jdk-21.0.13+9` (Temurin 21.0.13+9) + `/workspace/android-sdk`
(platform-tools, android-35/36, build-tools 35/36, ndk 28.2.13676358, cmake 3.22.1).
`local.properties` -> `sdk.dir=/workspace/android-sdk`.
**`assembleDebug` additionally needs the NESTED submodules** — plain `git submodule update --init`
leaves `libHttpClient/External/zlib` empty and CMake fails at
`libHttpClient.Android/CMakeLists.txt:127` ("Cannot find source file: .../External/zlib/adler32.c",
"No SOURCES given to target: libHttpClient.Android"). Fix: `git submodule update --init --recursive`.

### Baseline at HEAD 6b83ec5 (green)
`:app:testDebugUnitTest` = 3456 tests, 0 failures, 1 skipped. `:app:assembleDebug` SUCCESSFUL (~4 min).

### Coupling finding (the crux of this task)
- The manifest lists `org.chimeramc.client.ui.activities.*`, but those files physically live in
`app/src/main/java/org/chimeramc/client/launcher/ui/activities/` — i.e. **the directory tree does
not match the package tree** for the whole `launcher/ui` tree (package decls are
`org.chimeramc.client.ui.*`). Operate on FILES, never assume dir==package.
- `client.ui` + `client.launcher.ui` = 144 files across 21 packages (~40k LOC), 94 layouts.
- **No engine/core package imports the UI**, but **41 kept files reference deleted UI symbols**
(DynamicAnim, CustomAlertDialog, UiTokens, MainViewModel, the Activity classes as Intent targets,
etc.). Those are the rewiring surface.

## In-game Mod Menu deletion (task 2)
The in-game menu had **three layers**; all three are now cut:
1. **Native ImGui** in the sweetloader submodule: `src/pl/menu/` (MenuTheme/Widgets/Render/Filter/
Host/Jni, ~1900 LOC). It was self-contained — the ONLY external consumer was
`src/pl/render/PresentFrameEffect.cpp::OnPresentBoundary` (`pl::menu::IsOpen/IsMenuLive/Frame`).
Removed: the six `src/pl/menu/*.cpp` from `CMakeLists.txt`, the `add_library(imgui …)` target +
its `target_link_libraries(sweetloader … imgui)`, the present-hook call, `third_party/imgui/`
(2.8 MB, vendored, only consumer was the menu) and its NOTICE attribution, and
`tests/cosmetics/MenuFilterTest.cpp` + its `run_tests.sh` block.
Submodule gates that must stay green: `scripts/check_sources_listed.py` (CMake sources ↔
`src/**/*.cpp` ↔ `run_tests.sh`), `scripts/check_pinned_deps.py` (NOTICE ↔ fetched pins; the
vendored imgui block is NOT checked by it, but remove it anyway for honesty), host suite
`bash tests/cosmetics/run_tests.sh`.
2. **Java bridge**: `launcher.preloader.PreloaderMenu` + `core.mods.inbuilt.overlay.InGameMenuController`
(both already deleted).
3. **Launcher overlay widgets** (content panels behind the native menu): deleted
`MoreButtonsEditor`, `VoicePanel`, `VoiceUiKit`, `CosmeticsPanel` + their tests
(`PauseMenuActionsTest`, `QuickSettingsTest`, `ModMenuMetricsTest`, `ModMenuPaletteTest`,
`ModMenuSettingsTest`, `CursorControllerTest`, `CursorRouterTest`, `ModMenuNavLayoutTest`,
`ModUnavailableReasonResourcesTest`).
Rewiring done to keep the systems compiling:
- `MinecraftActivity.kt`: dropped `InGameMenuController.install/release/getInstance().handleTouch/
drainAndApply` and the `MoreButtonsEditor.onActivityResult/closeEditor/onResume` hooks.
- `InbuiltModuleProvider.java`: `ModIds.MORE_BUTTONS` no longer opens an editor (null action).
- `InbuiltModManager.java`: removed `get/setModMenuSettings` (they referenced the deleted
`ModMenuSettings`). Kept the appearance prefs/keys and `getModMenuButtonOpacity`.
- `InbuiltOverlayManager.java`: removed `modMenuButton`/`pauseMenuRow`/`DebugMenuOverlay`… (DebugMenu
is the F3 overlay MOD, NOT the menu — it stays).

## Legacy visual-asset cleanup (task 1 tail)
Deleted 29 dead legacy drawables (splash art, launch/dock buttons, nav rail): `splash_bg_*` (8),
`launch_bg_*` (3), `splash_scrim`, `bg_logo_glow`, `bg_launch_button`, `bg_split_launch`,
`bg_mod_menu_fab/toggle`, `bg_vip_icon_button`, `ic_nav_*` (3), `nav_active_indicator`,
`nav_rail_background`, `nav_tab_dot`, `bg_dock_play`, `bg_dock_version_chip`, `bg_launch_dock`,
`bg_launch_quickdock`, `bg_vip_surface`. Also removed the dead `Widget.Caramel.NavTab/NavRailTab/
QuickDock*` styles (86 lines). Kept 60+ generic drawables + the whole token/style system a new UI
would reuse (bg_*, ic_*, glass_card, Widget.Caramel.Card*, TextAppearance.Caramel.*).
Two tests pinned the removed button drawables — trimmed both (not deleted): `ButtonPressDrawableTest`
(now only `button_accent.xml`) and `RadiusScaleTest`'s surface list (dropped the 3 gone surfaces).

## TRAP: regex `</style>` removal over-matched
Removing `Widget.Caramel.QuickDock` (a **self-closing** `<style name="…" parent="" />`) with a
`re.search(r'<style name="X".*?</style>')` pattern ran PAST it to the next real `</style>` and ate
the `TextAppearance.Caramel` base style + its doc comment. Recovered by restoring the block from
`git show HEAD:…`. Lesson: match self-closing styles explicitly (`/>` vs `</style>`).

## Final verification (both repos)
- Parent: `:app:testDebugUnitTest` = **3164 tests, 0 failures**, `:app:lintDebug` clean,
`:app:assembleDebug` SUCCESSFUL (clean `app/.cxx` rebuild included, produces
`libsweetloader.so`). `scripts/check_ui_hygiene.py` clean (findViewById baseline 32→29 after
`--update`). Layouts 94→20; drawables ~167→161 distinct names.
- Submodule: host suite passes; `check_sources_listed.py` + `check_pinned_deps.py` green.
- Parent diff: **286 files, +13 / −57496**. Submodule diff: **30 files, −54879**.
- Note: `git status` counts differ from `diff --stat` because many deletions were staged with
`git rm` (staged) while others were plain `rm` (unstaged) — use `git diff --stat HEAD` for the
true total.
22 changes: 22 additions & 0 deletions .openhands/memory/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@ Index only. Detail and session notes live in the daily logs (`YYYY-MM-DD.md`).

The repo was called **GlowberryClient** before; the package is `org.chimeramc.client` either way.

### UI skeleton state (2026-11-14: the whole legacy UI was deleted for a new one)
The launcher UI + the in-game Mod Menu UI were removed in one sweep, keeping every system. Do not
re-add the old UI; a new one is being dropped in. See the 2026-11-14 daily log for the full list.
- **`ui.activities` files live under `launcher/ui/activities/`** (dir ≠ package for the whole
`launcher/ui` tree — package decls are `org.chimeramc.client.ui.*`). Operate on FILES, not dirs.
- 7 placeholder Activities remain (`BaseActivity` + `MainActivity`/`SplashActivity`/`LibraryActivity`/
`SettingsActivity`/`ModsFullscreenActivity`/`CrashActivity`); they draw nothing but are manifest
targets. `MainActivity.setTextMinecraftVersion()` and `LibraryActivity.EXTRA_INITIAL_TAB`/`TAB_*`
are kept no-op API other code still calls. Layouts 94→20; the kept 20 are the game-host/HUD ones.
- **The in-game menu was 3 layers, all cut**: native ImGui (`sweetloader/src/pl/menu/` + vendored
`third_party/imgui/`, consumed only by `PresentFrameEffect.cpp`), the Java bridge
(`PreloaderMenu`/`InGameMenuController`), and the launcher overlay widgets (`MoreButtonsEditor`,
`VoicePanel`/`VoiceUiKit`, `CosmeticsPanel`). `DebugMenuOverlay` is the F3 overlay MOD — keep it.
- **Kept (a new UI will reuse them)**: `UiTokens`, `Widget.Caramel.Card*`, `TextAppearance.Caramel.*`,
`GlowDimens`, generic `bg_*`/`ic_*` drawables, `PersonalizationManager`, all `core.*` systems.
Removed only the dead legacy chrome (`splash_bg_*`, `launch_bg_*`, dock/nav drawables + styles).
- Gate that catches dead drawables: `LayoutResourceTest` (unreferenced layout) fails the build —
delete the layout. Hygiene: `scripts/check_ui_hygiene.py --update` retires stale findViewById
baseline rows and shrinks the baseline when a file is deleted.
- **Trap**: a regex `<style name="X".*?</style>` over-matches a self-closing `<style …/>` and eats
the next real style. Match `/>` explicitly.

### Native engine (git submodule `app/src/main/cpp/sweetloader`)
- Submodule repo is `ChimeraAnt-DEV/SweetLoader` (the old `preloader-android` name 301-redirects).
**The parent must pin a commit that is on the submodule's `main`** — a `feat/*` tip can be
Expand Down
167 changes: 0 additions & 167 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,6 @@
The first-run wizard (U13). Not exported and not a launcher entry: the splash opens it
only when the launcher has no installed instance, so an existing user never sees it.
-->
<activity
android:name="org.chimeramc.client.ui.activities.SetupWizardActivity"
android:exported="false"
android:label="@string/setup_step_import_title"
android:screenOrientation="sensorLandscape"
android:theme="@style/SetupWizardTheme" />

<activity
android:name="org.chimeramc.client.ui.activities.MainActivity"
android:exported="true"
Expand All @@ -114,13 +107,6 @@
</intent-filter>
</activity>

<activity
android:name="org.chimeramc.client.ui.activities.ContentManagementActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi" />

<!-- A Quick Settings tile that cycles the performance preset. TileService is
API 24, so at minSdk 28 no fallback is needed. BIND_QUICK_SETTINGS_TILE is the
permission the system uses to bind it; the tile is not exported. -->
Expand Down Expand Up @@ -170,44 +156,6 @@
</intent-filter>
</receiver>

<activity
android:name="org.chimeramc.client.ui.activities.ContentListActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi" />

<activity
android:name="org.chimeramc.client.ui.activities.WorldEditorActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi"
android:label="@string/edit_world" />

<activity
android:name="org.chimeramc.client.ui.activities.OptionsEditorActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi"
android:label="@string/edit_options" />

<activity
android:name="org.chimeramc.client.ui.activities.CustomFlatWorldActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi"
android:label="@string/custom_flat_world" />

<activity
android:name="org.chimeramc.client.ui.activities.AboutActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi" />

<!-- The Library destination (U1/U3): Instances + Install + Replay behind one host. -->
<activity
android:name="org.chimeramc.client.ui.activities.LibraryActivity"
Expand Down Expand Up @@ -235,56 +183,8 @@
android:label="@string/diagnostics_title" />

<!-- The in-app changelog, rendered from the bundled CHANGELOG.md. -->
<activity
android:name="org.chimeramc.client.launcher.ui.activities.ChangelogActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi"
android:label="@string/changelog_screen_title" />

<!-- Hidden UI gallery: reached by tapping the version 7 times in Settings > Updates. -->
<activity
android:name="org.chimeramc.client.launcher.ui.activities.UiGalleryActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi"
android:label="UI gallery" />

<activity
android:name="org.chimeramc.client.ui.activities.CustomizeActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi"
android:label="@string/nav_customize" />


<activity
android:name="org.chimeramc.client.ui.activities.VoiceChatActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi"
android:label="@string/nav_voice" />

<activity
android:name="org.chimeramc.client.ui.activities.InstanceSettingsActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi" />

<!-- Accounts Management -->
<activity
android:name="org.chimeramc.client.ui.activities.AccountsActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
tools:ignore="DiscouragedApi"
android:label="@string/accounts_title" />

<!-- MSAL returns the authorization code to this activity. Its intent-filter is what the
browser hands the msauth:// reply to; without it Microsoft's response has nowhere to
land and the interactive flow hangs.
Expand All @@ -308,14 +208,6 @@
</intent-filter>
</activity>

<activity
android:name="org.chimeramc.client.ui.activities.MsftLoginActivity"
android:exported="false"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
android:windowSoftInputMode="adjustResize"
tools:ignore="DiscouragedApi" />

<activity
android:name=".ui.activities.ModsFullscreenActivity"
android:theme="@style/Base.Theme.FullScreen"
Expand All @@ -324,65 +216,6 @@
android:exported="false"
tools:ignore="DiscouragedApi" />

<activity
android:name=".ui.activities.ModDetailActivity"
android:theme="@style/Base.Theme.FullScreen"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
android:exported="false"
tools:ignore="DiscouragedApi" />

<activity
android:name=".ui.activities.ModConfigActivity"
android:theme="@style/Base.Theme.FullScreen"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
android:exported="false"
tools:ignore="DiscouragedApi" />



<activity
android:name="org.chimeramc.client.ui.activities.CurseForgeActivity"
android:theme="@style/Base.Theme.FullScreen"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
android:exported="false"
tools:ignore="DiscouragedApi" />

<activity
android:name=".ui.activities.ContentDetailsActivity"
android:theme="@style/Base.Theme.FullScreen"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
android:exported="false"
tools:ignore="DiscouragedApi" />

<activity
android:name=".ui.activities.ModHubActivity"
android:theme="@style/Base.Theme.FullScreen"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
android:exported="false"
tools:ignore="DiscouragedApi" />

<activity
android:name=".ui.activities.ModrinthDetailActivity"
android:theme="@style/Base.Theme.FullScreen"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
android:exported="false"
tools:ignore="DiscouragedApi" />

<activity
android:name=".ui.activities.QuickLaunchActivity"
android:theme="@style/Base.Theme.FullScreen"
android:screenOrientation="sensorLandscape"
android:configChanges="fontScale|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|touchscreen|locale|mnc|mcc"
android:exported="false"
android:label="@string/quick_launch_title"
tools:ignore="DiscouragedApi" />

<activity
android:name=".ui.activities.IntentHandler"
android:alwaysRetainTaskState="true"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/sweetloader
Loading
Loading