Promote WenWe/Accelerate utilities: paging de-dupe, serialization-safe Compose state, clipboard copier (1.6.3) - #101
Merged
Conversation
Capture two generic utilities written in WenWe (fixing Sentry WENWE-ANDROID-5H and 5G) as a proposed-features TODO, ready to lift in: - Flow<PagingData<T>>.distinctBy → :PagingExtensions - SerializableMutableState / TransientMutableState → :ComposeExtensions Includes copy-paste-ready source (repackaged), placement, a note that the library must not rely on BuildConfig.DEBUG for the fail-fast guard, tests to add, and a checklist to migrate WenWe onto the lib versions once released. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tions Docs/proposed wenwe utility promotions
…opier Promote three generic utilities out of WenWe and Accelerate into the toolbox (see docs/proposed/paging-dedupe-and-serializable-compose-state.md): - :PagingExtensions — Flow<PagingData<T>>.distinctBy(selector) guards LazyColumn/ LazyRow against duplicate keys when an offset-paged endpoint returns the same item id on more than one page. - :ComposeExtensions — SerializableMutableState / TransientMutableState (+ factories), Serializable MutableState holders for Voyager Screens. Fixed the release-only NPE the WenWe originals risked: consumer R8 stripped the reflective writeObject/readObject so the value restored as null. Added scoped consumer keep rules, plus fail-fast require() on construction and assignment (writeObject throw kept as a backstop). - :ComposeExtensions — ClipboardCopier + rememberClipboardCopier() + copyX extensions, wrapping the suspend LocalClipboard API and gating the confirmation toast to Android < 13 (API 33+ shows its own). Tests: 21 new unit/Robolectric tests (all green). The consumer keep rules are regression-guarded by :app:verifyConsumerKeepRules via a new ComposeExtensionsDemoScreen that exercises the holders in the minified demo app (27 -> 29 protected classes). Version bumped to 1.6.3; README versions synced. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The three utilities shipped in 1.6.3 and WenWe + Accelerate have been migrated to the library versions per the doc's instructions, so the proposal scaffolding is no longer needed. History remains on develop (commits 4f7e3b8, f4e5dcf). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jakeeilbeck
approved these changes
Jul 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotes three fully-generic utilities out of WenWe Android and Accelerate Android into the toolbox, per
docs/proposed/paging-dedupe-and-serializable-compose-state.md(the proposal doc that specified this work is removed in this PR now that it is implemented and WenWe + Accelerate have been migrated).What's added
Flow<PagingData<T>>.distinctBy(selector):PagingExtensionsuk.co.appoly.droid.util.pagingSerializableMutableState/TransientMutableState(+ factories):ComposeExtensionsuk.co.appoly.droid.compose.extensionsClipboardCopier+rememberClipboardCopier()+copyXextensions:ComposeExtensionsuk.co.appoly.droid.compose.extensionsdistinctBy— guardsLazyColumn/LazyRowagainstIllegalArgumentException: Key "…" was already usedwhen an offset-paged endpoint returns the same item id on more than one page. De-dupes by an arbitrary key, first occurrence wins,seenset resets perPagingDatageneration.SerializableMutableStatefor VoyagerScreens (which are Java-serialized across process death). Drop-in forby/.value/destructuring.SerializableMutableStatepersists & restores;TransientMutableStateresets toinitialon restore.ClipboardCopier— wraps the suspendLocalClipboardAPI (theLocalClipboardManagerreplacement): remembered scope, confirmation fires only after the write returns, and the app's own toast is gated to Android < 13 (API 33+ shows its own).The release-only crash this fixes
The WenWe originals risked a release-only NPE after process death: consumer R8 strips the reflectively-invoked
writeObject/readObject, default serialization then persists nothing (the only field is@Transient), and the value restores asnull. Fixes applied for the library:ComposeExtensions/consumer-rules.pro(package-scoped, notclass *).require(Serializable-or-null)at construction and on assignment, with thewriteObjectthrow kept as a backstop.BuildConfig.DEBUGgate and internal ticket IDs from published KDoc.Testing
asSnapshot), 7 + 4 state-holder round-trip, 7 clipboard (Robolectric SDK-gating +CompletableDeferred-gated ordering).ComposeExtensionsDemoScreenexercises the holders in the minified demo app so:app:verifyConsumerKeepRulesproves the rule fires against a real R8 consumer — protected-class count 27 → 29. ✓Notes
UpdateReadmeVersions.ComposeExtensions/README.md; root README module entries added for ComposeExtensions & PagingExtensions.develop).🤖 Generated with Claude Code