Extract the config and asset update-result resources from local/talkback-all-10 in all nine supported locales. Describe completed updates instead of an update command, and select singular or plural forms using the actual config or successful asset count.
Route both subscription update entry points through the existing localized ViewModel context and use activity resources for asset results. Preserve update execution, counts, partial-failure summaries, error handling, and toast delivery; no accessibility announcement infrastructure is included.
Store the pending member key instead of its list position and resolve that key when deletion is confirmed. Remove the member and its corresponding row key together; if the target no longer exists, leave the draft unchanged.
Extract the deletion fix from the accessibility assembly without importing accessibility actions, dialog wording changes, or drag refactors. Reuse the same key-based removal for blank members.
Validation: 75 JVM tests passed, including five deletion regressions; Play Store debug Kotlin compilation and x86_64 assembly passed. Emulator smoke check covered confirmation across rotation and immediate blank-member removal. Keyboard/D-pad and runtime reorder-during-confirmation scenarios were not run.
Use a builtin: filename-based ID instead of generating a fresh UUID each time the asset list is rebuilt. This lets the existing GUID-keyed list and file-metadata map recognize the same built-in asset after reloads and download-source changes.
Extract the fix and its two JVM regression tests from local/talkback-all-10. Preserve stored asset GUIDs, matching built-in replacement, locked flags, and URL behavior. No persisted IDs, accessibility semantics, metadata formatting, or editor behavior are changed.
Extract the visible asset metadata formatting from local/talkback-all-10. Use Android file-size formatting and derive the date/time pattern from the app configuration locale and the device 12/24-hour preference, without seconds.
Remove the metadata-only remember cache so recomposition uses the current formatting context. Preserve the existing size/date separator, missing-file message, row layout, action buttons, and accessibility semantics. No update-result or asset-editor changes are included.
Move subscription QR bitmap generation from the synchronous share callback into the existing ViewModel, running CPU-bound encoding on Dispatchers.Default and exposing the completed bitmap through StateFlow.
Cancel pending result delivery when the dialog is dismissed, a newer share request replaces it, or the ViewModel is cleared. Keep dialog rendering lifecycle-aware and reuse the existing localized failure message when generation returns no bitmap.
Extract only QR generation and dialog-state wiring from local/talkback-all-10. Leave subscription row accessibility, custom actions, update handling, and clipboard sharing unchanged.
* Preserve asset-editor drafts and handle the keyboard
Keep the asset name, URL, and delete-confirmation visibility in saveable Compose state so activity recreation does not discard an unfinished edit. Key the state by asset identity and initial field values.
Make the form vertically scrollable, consume the Scaffold padding, and apply IME padding so its fields remain reachable when the keyboard reduces the available height. Extract these presentation changes from local/talkback-all-10 without changing accessibility labels, deletion wording, or asset-save validation order.
* Resize the asset editor when the keyboard opens
Declare stateUnchanged|adjustResize for UserAssetUrlActivity, matching the other editor activities. Without an explicit resize policy, opening the IME in landscape pans the entire window and moves the toolbar Save action off-screen despite the scrollable Compose form.
Verified on Android 13 Pixel 6a: rotate with an unsaved draft, reopen the landscape keyboard, scroll between fields, edit the first field, save without hiding the keyboard, and reopen persisted values. Portrait keyboard and Save also pass. Debug assembly succeeded.
Replace the short-lived info toast with the existing titleless confirmation dialog and a single OK button so users can read the routing explanation at their own pace. Keep dialog visibility in saveable screen state and reuse the existing localized help and action strings.
Extract only the help-dialog presentation from local/talkback-all-10; leave app-row semantics, switches, routing descriptions, and notification infrastructure in the accessibility branches.
Reject duplicate names and empty names or URLs before invalidating the existing asset cache. Previously a rejected save left the stored source unchanged but deleted its downloaded file.
Preserve the validation messages and their order, duplicate-name exclusion by asset ID, and successful-save behavior. Renames still invalidate the old filename before updating the asset record.
Standardizes manifest process names by replacing the long `:RunSoLibV2RayDaemon` suffix with `:daemon` for shortcut activities, VPN/proxy services, and related receivers. It also moves `CoreTestService` and `SubscriptionUpdateService` to a separate `:tasks` process to isolate task-oriented work from the main daemon process.
A saved SUB_IDS array can contain the same GUID more than once. Loading
it verbatim creates repeated subscription rows with identical Compose
and reorderable-list keys, which can crash the subscription screen.
Deduplicate IDs in the shared reader while preserving the first-seen
order and mutable-list contract. This protects every index consumer
without changing subscription records, generating replacement IDs, or
adding writes during reads. Different subscriptions with identical or
blank names remain separate.
Add six regression tests for duplicate rows, stable ordering, read-only
decoding, mutable round trips, repeated names, and existing empty/invalid
input behavior. Three assertions fail on unchanged upstream; all six
pass with the fix. The full 63-test suite and Play Store debug build pass.
On the API 37.1 Pixel 9 Pro emulator, a deliberately duplicated saved
index loaded each subscription once, retained first-occurrence order,
reopened safely, and edited the correct record. The raw index remained
duplicated throughout the check; no app crash was observed.
Logcat used the complete log text as a Compose lazy-list key after 258de2097. Identical timestamped messages and repeated stack frames are valid log output, but collide as keys and crash the main thread while browsing logs.
Give each occurrence its own key in a small ViewModel-owned presentation model. Count oldest-first so prepending newer logs and filtering unrelated lines retain existing occurrence keys. Build the projection off the main thread and keep raw text, duplicates, ordering, copy and share behavior unchanged.
Add six regression tests covering duplicate messages, repeated frames, filtering, refresh, empty input and key-like text. All 63 Play Store unit tests pass; the debug APK was checked on the API 37.1 emulator with duplicate-line scrolling, filtering, refresh, reopening and lossless export. The original failure is documented by the user-provided physical-device crash log.
Switch routing ruleset lookup, save, and delete flows from list index to stable ruleset ID. Routing edit intents now pass `ruleset_id`, editing reloads by ID, and list item edit actions use each rule’s ID. This avoids index mismatch bugs when list order changes and keeps update/delete targeting the correct ruleset.
* docs: refresh agent guidelines
* docs: add agent harness adapters
* Update local-only block markers in AGENTS.md
DO NOT COMMIT phrase was confusing most LLMs and preventing them from committing anything without an additional explicit permission.
Build presentation-ready server row models in the ViewModel and publish each group's raw data and row data as one atomic state.
This removes storage and description work from composition, reduces the server-row API, and keeps reordering consistent across both representations.
Disabling traffic statistics removed the whole policy section from the
generated config, including the levels block (uplinkOnly, downlinkOnly,
connIdle, handshake) from the template or from a user's custom config.
Only the stats-related policy.system block should be stripped; keep
policy.levels intact in both the unified and the custom config paths.
Load asset metadata on Dispatchers.IO and publish the asset list and file details as one lifecycle-aware UI state.
Remove refresh-key workarounds, await reloads before downloads, and keep the content composable stateless.
Clear visible delays immediately, but move the per-profile MMKV reset to the existing I/O coroutine. Finish the reset before starting the test service so newly reported results cannot be erased.