roy_casual_kit library
Stable public entrypoint for the Roy Casual Kit package.
Consumers should prefer this library for supported APIs. Internal files
under core/ and presentation/ remain available for advanced migration
cases, but are not part of the recommended import surface.
Classes
- AccessibilityPreviewPanel
- In-app accessibility preview. Text scaling and target outlines are confined to the preview subtree; this panel never changes app-wide settings.
- AchievementRoadmapCard
- Long-term achievement roadmap with caller-owned progress and reward claims.
- AchievementRoadmapItem
- Caller-provided progress for one long-term achievement milestone.
- AchievementService
- Local achievement/badge progress tracker (no Game Center/Play Games integration — that's a later, separate task).
- AchievementSyncCoordinator
-
Pulls remote progress, merges it into service with
max(local, remote)per achievement, then pushes the merged map back. Progress only grows, so two devices converge without losing either side's data. Resetting or lowering progress is not supported by this merge. - AchievementSyncSeam
-
Platform-neutral achievement-sync seam — the package ships no Play Games /
Game Center client. The consuming app registers its own adapter via
Get.put<AchievementSyncSeam>(myAdapter, permanent: true), same pattern as LeaderboardSyncSeam-style seams. Progress is a plainachievementId -> progressmap; thresholds stay in the app. - AchievementUnlockListener
-
Wraps child and shows a ToastBanner every time
AchievementService.onUnlockfires (IDEA-43) — the ready-to-use on-screen counterpart toAchievementService, which the rest of the kit had no widget consuming at all before this. - AdaptiveGameHud
-
Places HUD content (HudSlot.topStart/
topCenter/topEnd/bottom/side/overlay) so a game doesn't have to hand-roll safe-area, notch, keyboard-inset, text-scale, RTL, and orientation handling itself every time it adds a HUD element (FEAT-52). - AdRewardSeam
-
Platform-neutral rewarded ad seam — this package ships no third-party ads SDK.
A consuming app registers its own adapter (e.g. backed by
applovin_admob_sdk) viaGet.put<AdRewardSeam>(myAdapter, permanent: true), mirroring PurchaseSeam/CrashReporter/AnalyticsProvider. - AnalyticsProvider
-
Platform-neutral analytics/event-tracking seam — the package pulls in
no analytics SDK (no Firebase Analytics, no Amplitude, …); a consuming
app registers its own adapter via
Get.put<AnalyticsProvider>(myAdapter, permanent: true). - AnalyticsQueueAudit
- AnalyticsQueueSnapshot
- AnalyticsQueueStatusCard
- Aggregate-only analytics queue status. The caller maps queue audit counts to snapshot and runs onFlush; this card never accepts events, event names, parameters or a queue instance.
- AnalyticsSamplingAudit
- Bounded, always-consistent counters — never resets on its own, so a health/debug surface can read cumulative drop counts for the process lifetime.
- AnimatedInventoryGrid
- Animated variant of InventoryGrid with pop-in scale for newly added items and smooth sliding transitions on slot reorders.
- AnnouncementPreviewCard
-
Shows the exact, already-resolved announcement text a screen reader would
receive. The caller resolves it (locale, interpolation) and triggers the
real announcement through its own
GameAccessibilityAnnouncer; this widget never takes the event bus, announcer or translation map. - AppSessionTracker
- Session id, install/session counters, and foreground duration — one place every feature reads instead of each hand-rolling its own "first open"/"session count" bookkeeping.
- AppTranslations
-
Minimal seed translations for the base project — 2 locales with key parity.
Copy this file's pattern (one
Map<String,String>per locale code) when a new game needs more languages or more keys. - AppVersionGateConfig
- Immutable version-gate policy — from a bundled asset default, a remote override (via AppVersionGateController), or built directly for a pure evaluateVersionGate call/test.
- AppVersionGateController
-
Reads version-gate policy from a RemoteConfigService (which already
gives "asset default, remote merges in, remote fail/corrupt keeps
last-good" for free — see
ENH-58) and evaluates it — no separate cache of its own, since RemoteConfigService already is the last-known-good cache. Keys read:appVersionMinimum,appVersionRecommended,appVersionMaintenanceActive,appVersionMaintenanceMessage,appVersionStoreUrl. - AppVersionGateOverlay
-
Wraps child with a blocking/dismissible overlay driven by
decision — takes plain data (same "widgets take data, caller owns the
service" convention as
EnergyBar/LevelSelectGrid), never readsAppVersionGateControlleritself. - AssetLicenseEntry
-
One tracked asset's provenance. All 5 string fields are required —
empty-string is treated the same as missing by validateAssetLicenses
(an entry that exists but has an empty
licenseis exactly as unpublishable as no entry at all). - AssetLicenseIssue
- AssetLicenseManifest
-
A parsed
asset/LICENSES.json-shaped document —{schemaVersion, entries: [...]}. - AssetManifestItem
- One entry in a scene's asset manifest.
- AssetPreloadCoordinator
- Preloads a scene's assets against a typed, dependency-aware manifest — no concrete Flame/audio/Flutter-asset/shader API baked in; a consuming app injects loader (dispatching on AssetManifestItem.kind) and optionally unloader.
- AsyncActionGuard
- Coordinates asynchronous actions by logical key.
- AsyncCommonButton
-
A CommonButton wrapper that drives itself through
AsyncButtonStatus.loading/
success/erroraround an async onPressed callback — the state machine BackupRestorePanel and similar hand-rolled per-widget before this existed (FEAT-50). Ignores a tap while not AsyncButtonStatus.idle (a rapid double-tap can't start a second onPressed call, and a tap during the success/error cooldown is ignored too, not queued). - AudioManager
-
Manages the background music: a single track (
asset/audio/bkg.ogg) + mute. - AuditBaseline
- A parsed baseline file — every AuditViolation this baseline suppresses is dropped from a scan's reported results, but never silently: AuditSuppression.reason stays readable in the baseline source file itself as the paper trail for "why this one's accepted".
- AuditRule
-
One heuristic: if triggerPattern matches a file's source, the file
is expected to also match requiredPattern somewhere — if it
doesn't, that's a violation.
nullrequiredPattern means any triggerPattern match is itself always a violation (no "opt out" companion pattern makes sense for that rule). - AuditSuppression
- One pre-approved exception — reason must be non-empty (enforced by AuditBaseline.fromJson, which silently drops any entry missing one rather than let a reason-less suppression through).
- AuditViolation
- One reported violation — file is whatever path the caller passed in (typically repo-relative), not validated against the filesystem by this pure function.
- AuroraBgLayer
-
I16: dải aurora phủ lên nền, chỉ world cuối. Cùng hạ tầng
FragmentProgram.fromAsset+ fallback ẩn hẳn khi load lỗi nhưneon_aura_layer.dart(không viết lại logic phát hiện hỗ trợ shader). - AvatarFrame
-
Circular avatar wrapping an arbitrary child (typically an
Image,Icon, or initialsText) with a decorative colored ring around it — for player profile displays. - AvatarFrameOption
- One selectable avatar frame. Ownership and unlock rules stay with the caller.
- AvatarFrameSelector
- Lazy grid of avatar frames to pick from, each previewed on the caller's own avatar. Presentation-only: the caller owns the option list, unlock state and persistence of the choice.
- BackupRestorePanel
-
UI for the save-backup flow
StorageService.exportAll()/importAll()andsave_integrity.dart's HMAC sign/verify already support at the core layer but have no widget to drive them from. - BadgeDot
- Small round dot signaling "something's new"/"unclaimed reward" — placed inside a Stack wrapping the caller's own icon/widget. Does not position itself. Animation is opt-in through pulse and radar.
- BadgeShowcaseItem
- Caller-supplied badge content to showcase on a player profile.
- BadgeShowcaseStrip
- Fixed number of badge showcase slots. Empty slots let the caller open a badge picker; ownership and persistence remain outside this widget.
- BatterySaverCoordinator
- Proactively forces performanceTier down to PerformanceTier.low when the device's battery drops below lowBatteryThreshold — unlike PerformanceTierService's own FPS hysteresis (which only reacts AFTER frame times already suffer), this acts on battery level directly, so a device that's still rendering smoothly but running low still backs off decorative shader/ticker work before it gets hot or the OS throttles it.
- BatterySaverIndicator
-
Presentation-only banner shown while the caller holds performance reduced
for low battery (for example
BatterySaverCoordinator.isForcingLow). Renders nothing when active is false. - BattlePassMilestone
- BattlePassMilestoneStatusView
- BattlePassRoad
- BattlePassRoadState
- BoosterSlot
- Single booster slot definition (FEAT-129).
- BoosterSlotBar
- A compact casual game power-up bar showing 1 to 5 booster slots (FEAT-129).
- BottomSheetPanel
- Candy-styled panel for the bottom of a sheet: rounded top corners, a drag handle bar, NeonTheme.card background. Pure visual container — pair it with showCommonBottomSheet to actually present it.
- BouncingOrb
-
Bounces around the viewport and reverses off its edges — the
collision-detection counterpart (IDEA-65) to SparkleParticle's
pooling demo: on touching TappableCircle, both components flash
NeonTheme.gold, proving Flame's
CollisionCallbacks/hitbox wiring actually fires through a realGameWidget, not just a unit test constructingCircleHitboxin isolation. - BoundedFrameSamples
- BudgetPolicy
- One budget rule a named metric must satisfy.
- CandyCheckboxTile
-
CandyFilter<
T> -
CandyRadioGroup<
T> -
CandyRadioOption<
T> - CandySearchBar
- CandySlider
- CandyTextField
-
Candy-styled text input — NeonTheme.card background, rounded border,
glow when focused — for player-name entry, redeem codes, feedback forms,
etc. Fills the "Buttons & Interactive" category's one remaining gap
(every other control there has a candy-styled equivalent; text entry
previously had none, forcing a bare Material
TextField). - CandyToggleSwitch
-
A candy-styled on/off switch: pill track + a round thumb that slides
left/right, replacing Material's default
Switch/SwitchListTilewhen visual style needs to match the candy widget kit. - CardFlip3D
- 3D Card flip with perspective transformation, automatic face switching, and optional gleam sweep effect on reward reveal.
- CardFlip3DController
- Controller to trigger card flip imperatively.
- ChallengeMilestone
- A reward milestone on a WeeklyChallengeCard progress track (FEAT-136). The caller supplies display data; the widget does not grant rewards.
- CharacterCollectionGrid
- Lazy three-column character collection grid with caller-owned unlock and selection state.
- CharacterCollectionItem
- Caller-supplied character presentation and unlock/selection state.
- CheckpointCoordinator
- Coalesces multiple game systems' state into one atomic, versioned save checkpoint on top of StorageService — one JSON blob under one key, so a commit is never observably "half applied" across participants (unlike each participant writing its own separate key, where a kill between 2 writes leaves a mixed save).
- CheckpointResumeCard
- CheckpointSummary
- CircleTappedEvent
-
Fires whenever TappableCircle is tapped — the one demo GameEvent
this starter template ships, so
GameDemoScreenhas something concrete to subscribe to (FEAT-88). A real game defines its own event types (EntityDefeated,LevelCompleted, ...) the same way, outside this package. - CircularProgressRing
- Ring-shaped progress indicator (custom-painted, not the default CircularProgressIndicator) — used for a countdown timer / daily quest ring, with a label/icon centered inside it. Animates the arc when progress changes via TweenAnimationBuilder.
- ClanChatPreviewBar
- ClockSample
- A wall-clock reading paired with a monotonic, boot/process-relative reading taken at the same instant — see TrustedClockService for why TrustedClockService.nowMsTrusted needs both together, not just one.
- CloudSaveProvider
-
Platform-neutral cloud save/account-linking seam. Without this,
StorageServiceis 100% localSharedPreferences— a lost/reinstalled device loses all progress. The package pulls in no cloud SDK; a consuming app implements this against Google Play Games Services / Game Center / Firebase Auth+Firestore and passes it to VersionedJsonStore.syncWith. - CloudSaveStatusCard
- CoinFlyOverlay
-
N icon "coins" fly from a source point to a target's current on-screen
position — read from a GlobalKey via
RenderBox.localToGlobal, the same technique used elsewhere in Flutter for this — staggered slightly so they read as individual coins instead of one blob. FEAT-12's "coin fly toCurrencyCounter" reward juice. - CoinMultiplierWheel
- Symmetrical victory multiplier needle wheel (FEAT-132).
- CoinMultiplierWheelController
- Controller to drive CoinMultiplierWheel externally from buttons (e.g. "Stop" or "Spin again") (FEAT-132).
- CollectionAlbumItem
- Caller-provided view of one collectible in a collection album.
- CollectionAlbumPanel
- Collection album with caller-owned item/quantity state and a lazy 3-column grid.
- ComboHeatBackground
-
Reactive background that lerps between a "cool" and "hot" color as
heat rises (IDEA-08) — the caller computes heat from whatever combo/
streak mechanic it has (e.g.
min(1.0, comboCount / 10)); this widget has no idea what a "combo" is, matching VictoryCardTemplate's convention of taking caller-computed values rather than inventing game-specific mechanics. - ComboMeterBar
- A compact, dynamic combo HUD meter (FEAT-128).
- ComebackBundleCard
- Presentation-only return-player offer with caller-supplied rewards and eligibility/expiry state (FEAT-151).
- CommonButton
-
Shared button widget, with more variants than NeonButton (NeonButton
stays as-is, this doesn't replace it).
primary/secondary/dangerare rounded pills with a label (secondary = outline/light background instead of a solid gradient, danger = red tone);iconis a round icon-only button (settings/close/...). - CommonListTile
- Styled list row for a settings row / leaderboard row / etc — candy-themed replacement for the default Material ListTile. When filled is true the row gets a NeonTheme.card background + rounded corners (a standalone "card row"); when false the background is transparent (for rows already inside a PanelCard or other container, e.g. a divided list).
- CommunityLeaderboardCard
- Caller-ordered community leaderboard with optional current-player highlight.
- CommunityLeaderboardEntry
- One caller-ordered community leaderboard entry.
-
CompiledWeightedTable<
T> - Pre-validates a weighted loot table ONCE at construction — compiling it into cumulative weights so repeated pick calls (e.g. every enemy spawn, every loot roll) don't re-validate and re-sum the whole table every time the way a bare weightedRandomPick call does.
- ConfettiOverlay
-
Full-screen confetti burst — N colored paper pieces rain down from the
top, sway, spin, and fade out; the effect stops and hides itself after
duration (unlike
NeonBg/AuroraBgLayer, which run forever). Drop it in aStackover a win/level-complete screen; give it a fresh key each time you want to retrigger it (a new key mounts a fresh particle set and ticker instead of reusing a finished one). - ConfettiParticle
-
One confetti piece's fixed randomized traits, generated once at spawn.
Motion at any time
tis a pure function of these traits (see confettiOffsetAt/confettiRotationAt/confettiOpacityAt) so the simulation is deterministic and unit-testable without building a widget. - ConformanceReport
-
Result of running one adapter's checklist — a plain Dart report (same
shape as
RoyCasualKitContractReport) so a consumer can use it from any test runner and turn failures into their own preferred matcher. - ConnectivityCoordinator
- Reactive Internet-reachability coordinator with a bounded, idempotent retry queue for tasks an app wants to run once back online.
- ConnectivitySignal
- Raw OS-level "does a network interface exist" signal (WiFi/cellular up) — deliberately separate from actual Internet reachability. An interface can be up with zero real connectivity (captive portal, DNS failure), which is exactly what ReachabilityProbe below is for.
- ConnectivityStatusCard
- Read-only connectivity summary. The coordinator owns the retry queue and drains automatically once reachability is online; this card never receives queued tasks or claims that work has drained.
- ConsentBanner
-
Wraps child and shows a one-time GDPR/CCPA-style consent banner
(IDEA-69) before any ConsentCategory the app might gate analytics or
personalization behind is ever decided —
ConsentStateServicehas the state (grant/deny/reset) andConsentGatedAnalyticsProviderhas the enforcement, but nothing in the kit actually asked the player until this widget. - ConsentGatedAnalyticsProvider
-
Decorator over a real AnalyticsProvider that only forwards
logEvent while
ConsentCategory.analyticsis ConsentStatus.granted — a consuming app registers this instead of its real provider (Get.putwithConsentGatedAnalyticsProvider(realProvider),permanent: true) so every call site automatically respects consent without individually checking it. - ConsentPreferenceItem
- ConsentPreferencesPanel
-
Presentation-only, ongoing consent preferences (the first-run prompt is
ConsentBanner). Allow and Don't allow have equal visual weight; the button matching the current choice is disabled. The caller applies the change (for exampleConsentStateService.grant/deny). A callback that returns without throwing is shown as saved, so throw when it did not apply. - ConsentRecord
- Immutable point-in-time read of one category's consent.
- ConsentStateService
- SSOT for privacy consent, gating which providers (analytics, personalization) are allowed to run.
- ContentPackHistoryEntry
-
One verified, previously-applied content revision (ENH-96) — metadata
only, by design: never the content body itself. Exposed via
RemoteContentPack.history / RemoteContentPack.diagnosticsSummary so a
support/live-ops investigation can answer "which content version was
active when this happened" without ever handing back a player's actual
game data (a level layout, a shop catalog, whatever
Trepresents). - ContentPackStatusCard
- ContentRevisionHistoryPanel
- ContentRevisionSummary
- ContrastCheck
- One pair to check — pure data, no NeonTheme dependency, so a caller (or a widget-fixture test, see this file's test) can validate arbitrary colors, not just the live theme.
- ContrastIssue
-
A ContrastCheck that failed its threshold — ratio is either a
WCAG contrast ratio (text/uiComponent/disabled) or an RGB Euclidean
distance (gemPalette); both share the same "lower is worse" direction
so a single
< thresholdcomparison produces every issue. - ContrastPreviewCard
- Reusable contrast preview for one caller-supplied foreground/background pair. It does not change NeonTheme, save colors or run a global audit.
- CooldownActionButton
-
Button gated by a caller-read cooldown. While remaining is positive the
button is disabled and a countdown chip is shown; when the chip reaches
zero onReady fires so the caller re-reads the service and passes
Duration.zero. The caller still re-checks the service inside onTap: this gate is UI only, not an anti-cheat boundary. - CooldownCountdownChip
-
Adapter over CountdownChip for a keyed cooldown read from
PersistentCooldownService— takes plain remaining data rather than reaching into the service directly (same convention asEnergyBar/LevelSelectGrid: widgets take data, callers own the GetX service). - CooldownSnapshot
- Immutable point-in-time read of one cooldown's state.
- CountdownChip
-
Chip that live-counts down to target, formatted through the shared
fmtDur (no reimplemented duration formatting). Ticks every second via
an internal
Timer.periodic, cancels it indispose(and on reaching zero) so it never lingers past unmount, and calls onDone exactly once when the countdown reaches zero. - CraftingIngredient
- Caller-provided ingredient status for one recipe.
- CraftingRecipeCard
- Presentation-only crafting recipe card. Caller owns inventory mutation, recipe eligibility beyond ingredient counts, and crafted-item granting.
- CrashReporter
-
Platform-neutral crash/error reporting seam —
dlog()is debug-only (tree-shaken out of release builds), so without this, every runtime error in production is silent. The package itself pulls in no crash SDK; a consuming app registers its own adapter (Crashlytics, Sentry, …) viaGet.put<CrashReporter>(myAdapter, permanent: true). - CurrencyCounter
-
Icon + a currency amount, smoothly counting up/down when value changes
(instead of jumping instantly) — a generic replacement for the old
CoinChip(removed because it was tightly bound to specific game state). Doesn't know what coins/gems are itself, it just displays a number. - CurrencyCounterState
- DailyLoginCalendarWidget
-
Read-only 7-day (configurable via cycleLength) login-streak calendar —
a pure display widget, it holds no streak state of its own. The caller
reads
DailyLoginServiceand hands in currentStreakDay/ claimedDaysInCycle/canClaimToday, matching this kit's convention (seeLevelSelectGrid) of widgets taking plain data rather than reaching into a GetX service directly. - DailyLoginClaimResult
- Result of a DailyLoginService.claimToday call.
- DailyLoginService
- Tracks the daily-login streak: last claimed day, current position (1..7, cycling) in the reward cycle, and which days of the current cycle have already been claimed.
- DailyOffer
- Data for one daily/live-ops offer (presentation-only).
- DailyOfferStack
- Caller-ordered stack of daily/live-ops offers.
- DailyQuestService
-
Caller-declared daily/weekly quest tracker — the third reset-cadence
mechanism alongside AchievementService (permanent, never resets) and
DailyLoginService(fixed login-streak calendar, not arbitrary objectives). Quests ("win 3 matches", "use 1 booster") are declared up front via register (id, target, reset period), same "caller owns the declaration, service only tracks progress" convention as AchievementService.register. - DataErasureReceipt
- Result of PlayerDataRightsService.requestErasure — confirms the local storage wipe completed, plus which best-effort erasure hooks (if any were registered) succeeded or failed, so a support/compliance flow has a concrete receipt to show or log rather than just "trust me, it's deleted".
- DataExportReceipt
- Result of PlayerDataRightsService.requestExport — everything currently in StorageService plus metadata identifying when/what schema it was captured under, ready to hand to a player who asked "give me my data" (GDPR/CCPA-style export request).
- DebugQaOverlay
-
Hidden debug/QA overlay — a small long-press trigger in a screen corner
that opens a panel with 2 tabs: a read-only dump of live internal
package state (every
StorageServicekey/value, audio mute, current locale, clock diagnostics), and a Playground tab (IDEA-39) that lets a QA tester/designer live-preview aCommonButtonwith adjustable label/variant/color right on-device — no rebuild needed to answer "what would this button look like in red with this label?". - DeepLinkCommand
- Immutable, already-validated deep link — path params and query params merged into one map (a query key never overrides a path param of the same name, since path params are captured first).
- DeepLinkCommandRouter
-
Parses deep links into typed DeepLinkCommands and dispatches them to
registered handlers — no concrete deep-link plugin dependency (
app_links,uni_links, ...); a consuming app feeds its own URI stream into handleUri. - DeepLinkHandleResult
- DeepLinkHandlerResult
- One handler's result for a single dispatch — diagnostic only, never aborts the rest of the dispatch loop.
- DeepLinkResultCard
-
Generic deep-link outcome card. It never receives or renders the URI,
query parameters, router rejection message or handler exception, since
those can carry user data or tokens. Map
DeepLinkHandleResultto status in caller code:dispatchedwith all handlers succeeded -> DeepLinkResultStatus.dispatched;dispatchedwith a failed handler -> DeepLinkResultStatus.handlerFailed;queuedUntilReady-> queued;duplicateIgnored-> duplicate;rejected-> rejected. - DeepLinkRoute
-
One allowlisted route:
scheme/host/path shape → a typed command. A path segment starting with:captures that segment as a param (e.g.['level', ':id']matches/level/42and capturesid: '42'). - DependencyEntry
-
One resolved package from
pubspec.lock. - DeprecatedApi
-
A single deprecated public API entry: pairs with a real
@Deprecated(...)annotation on the code itself, but adds the structured, machine-checkable removal-version/grace-period data a plain annotation string can't carry. - DeprecationCheckResult
- DeprecationRegistry
- Immutable registry of an SDK's deprecated APIs, checked against a released version to find which ones are past their removal version.
- DiagnosticsBundleView
-
Read-only parsed view of an exported bundle. Parsing NEVER writes to
StorageServiceor any registered service — this is FEAT-70's "import chỉ read-only" contract: opening a diagnostics bundle a player/QA sent you can never mutate your own app's state, unlikeVersionedJsonStoreimport (which is meant to restore state) orStorageService.importAll. - DiagnosticsExportBundle
-
Packages an SdkHealthReport snapshot (FEAT-39), a ReplayCapsule
(IDEA-42), a redacted config slice, and recent log lines into one
support-artifact JSON
Map—{schemaVersion, generatedAtMs, appVersion, sections, errors, truncated}. - DisasterRecoverySaveExport
-
Multi-slot disaster-recovery export/restore, composing 3 already-
shipped primitives rather than inventing new ones:
SaveSlotManager (which slots exist, and SaveSlotManager.keyFor's
per-slot key prefix), StorageService.exportWithPrefix/
StorageService.importWithPrefix (the actual data movement — whose
existing rollback-on-failure guarantee, see
storage_service.dart'simportAll, is exactly what makes applyRestore crash-safe: aSharedPreferenceswrite has no transaction primitive, soimportAllsnapshots the WHOLE store first and re-applies that snapshot if the replace throws, meaning a slot that never got reached keeps its pre-restore data, and a slot whose own import failed mid-way rolls back to what IT had before that one call, not a half-written mix), andsave_integrity.dart's HMAC sign/verify (the same conventionReplayCapsule.exportSignedalready uses). - DisposedWatchdogEntry
- A WatchdogEntry that was properly released, kept in a short bounded history for debugging ("did X actually get disposed, and when") — separate from MemoryWatchdog.orphans, which only ever looks at still-live entries.
- EconomyCertificate
-
Combines a save-integrity signature (
save_integrity.dart'ssignExport/verifyAndStrip), a TrustedClockService judgement, and an EconomyWallet/PurchaseLedgerService snapshot into 1 "certificate" a backend (or another device) can verify with a single call, instead of re-implementing all 3 checks itself (FEAT-91). - EconomyCertificateStatusCard
-
Verification result only. It never accepts balances, certificate JSON,
signatures or secrets; the caller maps
EconomyCertificateVerificationto status and supplies any safe summary text. - EconomyCertificateVerification
- Typed result of EconomyCertificate.verify.
- EconomyWallet
- EmptyStatePlaceholder
-
Centered icon + message for "no data yet" states (empty leaderboard, no
achievements unlocked, ...). Icon sits in a soft circular badge, mirroring
the icon treatment in NeonDialog.panel (
neon_dialog.dart). - EnergyBar
-
Row of
maxEnergyheart pips (filled up tocurrentEnergy, dimmed beyond), plus a live-tickingmm:sscountdown to the next regen point — a pure display widget, it holds no energy state of its own. The caller readsEnergyServiceand hands in currentEnergy/maxEnergy/ timeUntilNextEnergy/hasInfiniteLives, matching this kit's convention (seeLevelSelectGrid/DailyLoginCalendarWidget) of widgets taking plain data rather than reaching into a GetX service directly. - EnergyRegenResult
- Result of one regenEnergy tick computation.
- EnergyService
- Energy/lives system that refills over time (Candy Crush-style "hearts").
- EventAuditRecord
-
One SdkEventSchemaRegistry.validate call's outcome, kept in a
bounded history — same ring-buffer convention
MemoryWatchdog/RemoteKillSwitchControlleralready use in this package. - EventCalendarCard
- Week event calendar with caller-supplied labels, status and ordering.
- EventCalendarItem
- One event on a caller-authored calendar.
- EventParamSchema
-
One declared param — pii means "this key, if present, is ALWAYS
stripped before the event reaches a real AnalyticsProvider," full
stop, independent of required/type (see EventSchema's
constructor for why a param can never be both
requiredandpii). - EventSchema
-
One event's contract — name, param shape, and how to handle an
unrecognized field. migrate upgrades an older client's raw params to
what THIS (current) schema version expects, applied before validation
— same "migrate on read" convention
VersionedJsonStore.migratealready uses in this package, so an app that can't ship a client update immediately still has its old-shaped events validated correctly against the newest schema. - EventSchemaAuditCard
- Aggregate schema-validation diagnostics only. The caller maps registry results to counts; this card never accepts event or parameter details.
- EventSchemaAuditSnapshot
- EventValidationResult
-
The outcome of validating one
logEventcall — sanitizedParams is what's actually safe to forward to a real provider (empty when accepted isfalse: a rejected event is never partially sent). - ExpandablePanel
- ExpandablePanelState
- ExperimentBucketingService
-
Stable A/B-test variant assignment on top of
RemoteConfigService's flat key/value remote config — that service has no notion of "always put this same player in the same bucket for this experiment", which is exactly what a real A/B test needs. Getting this wrong (re-rolling the bucket every session instead of once per device) silently invalidates every measurement an experiment collects. - ExperimentVariantAssignmentCard
-
Read-only experiment assignments. The caller maps
variantForresults to rows; the per-device anonymous id never enters or leaves this widget. The override controls only appear in debug or profile builds, matchingExperimentBucketingService.debugSetVariantOverride, which is a no-op in release; in release the card stays read-only even ifonSelectOverrideis passed. - ExperimentVariantRow
- FakeAdRewardSeam
- Minimal, correct in-memory reference AdRewardSeam — showRewardedAd always completes successfully with reward earned.
- FakeCloudSaveProvider
- Minimal, correct in-memory reference CloudSaveProvider — passes its own conformance suite and doubles as an example implementation.
- FakeConnectivitySignal
- In-memory test double — a consuming app's own tests (or this kit's) can push interface transitions directly via setHasInterface instead of depending on a real platform channel.
- FakeCrashReporter
- Minimal, correct in-memory reference CrashReporter — records every call instead of actually reporting anywhere, for tests/examples.
- FakePurchaseSeam
- Minimal, correct in-memory reference PurchaseSeam — buy always succeeds and marks the product owned, for tests/examples.
- FakeSecureStorageAdapter
-
In-memory SecureStorageAdapter for consumer contract tests — never
touches a real keystore/Keychain. Register it with
Get.put<SecureStorageAdapter>(FakeSecureStorageAdapter())in a test that needs SecureStorage to actually succeed instead of failing with "no adapter registered". -
FilterChipRow<
T> - FlameTrackedOverlay
-
Bridges a Flame
FlameGame's world-space entity position to a Flutter widget that lives in the sameStackas the game'sGameWidget— aTooltipBubble, a damage-numberText, an HP-bar-style widget that should visually track a moving/resizing/panning entity. - FlashSaleOfferCard
- A high-urgency Flash Sale / Starter Pack offer card (FEAT-127).
- FloatingComboText
- Combo/score text ("+10", "Combo x3") that floats up and fades out in place, then removes itself — the FEAT-12 coin-fly widget flies to a target, this one just pops where it appears (cheap but effective "game-feel" juice).
- FloatingEmojiBurst
- FloatingEmojiBurstState
- FloatingEmojiParticle
- FocusTrapScope
-
Standard "modal focus trap" for an in-tree overlay panel — wraps
child (the modal's own content) in a FocusScope that
autofocuses as soon as this widget mounts (i.e. exactly when the
overlay it belongs to appears, matching this package's "always
mounted, panel nullable" convention —
NeonDialog.overlaySlot,PauseOverlay), and restores focus to whatever had it right BEFORE this widget mounted, the moment it's removed from the tree again (the overlay closing). - FrameBudgetTracker
-
Pure FPS tracker: no dependency on
SchedulerBinding/Flutter bindings at all, so it can be driven with synthetic frame durations in a plain unit test. Keeps a rolling window of the last windowSize frame durations (ms); once the window fills, averages it into an FPS figure and applies hysteresis — a lower downgradeFpsThreshold and a higher upgradeFpsThreshold — so a device hovering right around one cutoff doesn't flap between tiers every window. - FriendInviteMilestone
- Caller-owned view of a referral reward milestone.
- FriendInviteProgressCard
- Referral progress card. Eligibility, invite attribution and reward grants remain caller-owned; this widget only presents supplied state and callbacks.
- FriendRequestItem
- FriendRequestTile
- GameAccessibilityAnnouncer
-
Bridges GameAccessibilityEvents from a GameEventBus to a screen
reader — the piece this kit was missing (widgets carry their own
Semantics, but nothing announced a fast state CHANGE like "level up" or "+50 gems"). - GameAccessibilityEvent
- A gameplay moment worth announcing to a screen reader — fired on a GameEventBus like any other GameEvent (FEAT-88's pattern), so a consumer's own service (progression, reward pipeline, energy) emits one of these at the point it already changes that state, without needing to know GameAccessibilityAnnouncer exists.
- GameClock
-
Pure gameplay clock: no dependency on Flutter/Flame bindings, wall clock,
or any timer — every advance is driven by a caller-supplied delta, so the
exact same sequence of advance calls always produces the exact same
elapsed/step count (see
PerformanceTierService'sFrameBudgetTrackerfor the same "pure core, thin binding-aware wrapper" split this mirrors). - GameEvent
-
Base type for every event flowing through a GameEventBus. Extend this
to add a new gameplay event — the bus itself never needs to change.
Deliberately a plain abstract class, not
sealed: asealedhierarchy must live entirely inside this package, but a consuming game needs to define its own event subtypes (e.g.EntityDefeated,LevelCompleted) outside it. - GameEventBus
-
Lightweight typed pub/sub bus bridging gameplay events (fired from a
Flame
Component/game loop) to business-logic services (EconomyWallet,AchievementService,AnalyticsProvider, ...) that want to react to them — without every new event type requiring a manual wire-up at each interested service. - GameJoystick
- Caller-owned virtual joystick. Direction and unit vector reset to neutral on pointer release or cancellation.
- GameOverCardTemplate
-
Pre-built "game over" card — the loss/retry counterpart to
PanelCard-based
VictoryCardTemplatefor a level-complete moment. Deliberately smaller: no avatar/QR/share wiring (a losing moment has no invite-link/share use case), just a headline, optional message and stat lines, plus one or two action buttons (typically "Retry" and "Home"). - GameSessionController
- Single source of truth for a game's session lifecycle.
- GameSessionSnapshot
- GameSessionTimelineEntry
-
ENH-96: one recorded phase transition in a GameSessionController's
timeline — offsetMs is elapsed time since the session's own
Stopwatch started (see GameSessionController.withTimeline's doc),
never a wall-clock timestamp, so a recorded/exported timeline never
leaks when (in real-world time) a session was played, only its
internal pacing — same anti-fingerprinting posture
ReplayRecorderalready documents for its own offsets. - GameSessionTimelineExport
- ENH-96: a full, exportable snapshot of one session's recorded GameSessionTimelineEntry list — see GameSessionController.exportTimeline.
- GameTimeController
-
Bridges GameClock to Flame's per-frame
update(dt)loop (via tick) and to Flutter via elapsed (Rx, safe to read fromObxfor a countdown/HUD timer) — both sides observe the exact same clock instance, so there's no separate synchronization step for them to drift apart on. - GiftLivesRequest
- Caller-supplied life request; the widget never owns inventory or cooldowns.
- GiftLivesRequestCard
- One friend/clan "send me a life" row with a guarded Send action.
- GoalItem
- Single level goal model representing one objective in a level HUD (FEAT-125).
- GoldenShimmerText
- Golden highlight sweep over StrokeText. Honors Reduced Motion and inherited TickerMode so scrolling/offstage routes can pause the ticker.
- GuardrailDefinition
-
A min/max threshold on 1 named metric — a violation of either bound is
what ShadowActivationController treats as "this shadow-activated
feature/event is misbehaving, roll it back now". Either bound can be
null(no lower/upper check) — but not BOTH; that invariant is enforced by ShadowActivationController.registerGuardrail (ENH-89), not here — a runtimeasserton thisconst-constructible class would be stripped from release builds anyway, and a genuineif/throwhere would force everyconstguardrail list in consumers offconst. - GuardrailStatusPanel
-
Read-only guardrail status.
ShadowActivationControllerexposes no read API, so the caller supplies rows from its own definitions and readings. - GuardrailStatusRow
- GuildContributionCard
- Guild goal progress with member contribution and caller-owned actions.
- GuildContributionMilestone
- One community contribution milestone supplied by the caller.
- HapticChoreographer
-
Schedules and plays back a HapticPattern pulse by pulse, through
fireHaptic (so every existing
hapticsEnabled/hapticSoftModecontract already applies to every pulse, for free — this never callsHapticFeedback.*directly). - HapticPattern
- A small, caller-declarable haptic sequence — "1 buzz then a pause then 2 buzzes" instead of a consumer wiring up individual fireHaptic calls by hand for every combo/reward/error moment.
- HapticPatternOption
- One named, caller-supplied haptic pattern.
- HapticPatternPicker
- Select and preview a short haptic pattern. The caller owns preference state and playback; the widget never constructs a HapticChoreographer.
- HapticPulse
- One step of a HapticPattern: fire level, then wait delayAfter before the next pulse (ignored on the pattern's last pulse).
- HealthCollectorSpec
-
One named section of an SdkHealthReport — collect gathers whatever
diagnostic data this section wants, and allowedKeys is the ONLY thing
that actually reaches the report: any key collect returns that isn't
in allowedKeys is silently dropped, never the other way around
(default-deny, not default-allow) — a collector that starts returning
one extra field by mistake (or a copy-pasted
token/secretkey) can't leak it into a report a QA/support person might screenshot or paste into a ticket. - HoldToConfirmButton
- A button that only fires onConfirm after being held down for duration — for a reset/delete/purchase action a stray tap shouldn't be able to trigger.
- IconBadgeButton
-
Round icon button (e.g. settings/shop) that can carry a small badge in
its corner — a plain notification dot (
showBadge), or a count (badgeCount) when a number is needed. - InboxAttachment
- One reward attached to an inbox message (presentation-only).
- InboxMessageCard
- Presentation-only system/event mail card (FEAT-146): unread badge, attachments, self-ticking expiry countdown and a Claim action.
- InventoryGrid
-
A data-driven grid over an InventorySnapshot — like QuestViewModel/
LeaderboardEntry, this widget holds no game logic or catalog of its own; itemBuilder is the caller's own renderer (item icon, rarity frame, stack count, equipped badge — this package doesn't ship a concrete item catalog, seeItemDefinition's doc), and a tap never mutates anything here — the caller's own tap handler is expected to callInventoryService.consume/setEquipped/moveSlotitself. - InventoryLine
-
One
{itemId, quantity}request line inside a InventoryService.grant/ InventoryService.consume call — several lines under one call apply atomically (see those methods' doc). - InventoryService
-
Generic slot-based inventory (consumables + equipment) — item stack
rules and rarity live in the caller-supplied
itemCatalog; this service only knows about slots/quantities/equipped flags and the invariants around them. grant/consume follow the same idempotent-ledger pattern asEconomyWallet(FEAT-31)/RewardTransactionPipeline(FEAT-42): atransactionIdrepeated (even across a restart) is a no-op, and every mutating call runs under AsyncActionGuard.runExclusive so concurrent calls serialize instead of racing. - InventorySlot
-
One stack inside an inventory. slotId is a stable identity assigned
once at creation — it's what InventoryService.setEquipped/
moveSlottarget, so it survives a grant/consume elsewhere in the inventory changing the list's indices. - InventorySnapshot
- Immutable view of one inventory — display order is slots' list order.
- InviteFriendCoordinator
-
(IDEA-70) Ties together 3 pieces of already-existing kit infrastructure
into a referral/invite-friend loop: fnv1aHash (a stable per-player
invite code),
share_helper.dart's shareText (sending it), and DeepLinkCommandRouter (recognizing a friend opening the invite link). - ItemDefinition
- Static catalog entry for one item id — InventoryService is generic over whatever catalog a consumer app supplies; it has no concrete item list of its own.
- ItemFlyOverlay
- JuicyFeedback
- Starts a consumer-owned SFX and its matching haptic as one feedback event. Audio stays optional until the consuming app registers AudioManager, while haptics continue to honor the player's stored haptic preferences.
- KillSwitchItem
- KillSwitchState
-
One feature's current kill-switch decision — reason/version are
the audit trail ("why was this killed, and which rollout"), populated
from the remote payload when it's the richer
{killed, reason, version}shape (a bareboolleaves them at their defaults,''/0). - LeaderboardEntry
-
One caller-supplied leaderboard row — rank, name and score are already
formatted/localized strings (same convention as
VictoryCardTemplate'sstatLines: this widget never invents ranking or number formatting). - LeaderboardList
-
Pure, data-driven leaderboard display (rank + name + score + optional
avatar), candy-styled to match the rest of
common/. Composes AvatarFrame for the avatar slot; ranking/scoring logic and data all come from the consumer app. - LeaderboardSyncCoordinator
- Optional orchestrator wiring LocalScoreboardService (always-on, local cache) together with a LeaderboardSyncSeam (a real backend, when registered). Neither service has to be used directly — this exists for the common case of "submit to both, read from the backend but never go blank when it's unreachable".
- LeaderboardSyncSeam
-
Platform-neutral leaderboard-sync seam — mirrors PurchaseSeam/
CloudSaveProvider's design: the package pulls in no leaderboard SDK (no
Play Games Services, no Game Center, no custom backend client); a
consuming app registers its own adapter via
Get.put<LeaderboardSyncSeam>(myAdapter, permanent: true). - LevelDefinition
-
One rung of the XP curve. level is 1-based; the LAST entry in a curve
must have xpToNext
== 0— that's what marks it the max level (nothing further to grind toward). Every other entry needsxpToNext > 0, and the curve must be non-decreasing (a later level never costs less XP to clear than an earlier one) — see validateLevelCurve. - LevelGoalTracker
- A compact, candy-styled HUD showing 1–4 level goals (FEAT-125).
- LevelNodeButton
-
One round level node — the world-map/level-select building block. Shows
the level number, or a lock glyph (and blocks tap) when state is
locked, plus a mini StarRating badge underneath oncecompleted. - LevelPathMap
- S-curve winding saga path container holding 1 to N LevelPathNodes (FEAT-133).
- LevelPathMapTile
- A single level map node representing a level button on a saga path (FEAT-133).
- LevelPathNode
- Data model for one level node along a LevelPathMap (FEAT-133).
- LevelSelectGrid
-
Read-only grid of LevelNodeButtons for a world-map/level-select screen
— a pure display widget, it holds no progress state itself. states
gives each level's LevelState in order (level 1 at index 0);
starsEarnedByLevel optionally maps a 1-based level number to its
earned star count. onLevelTap fires with the 1-based level number of
whichever
unlocked/completednode was tapped —lockednodes never fire it. - LevelUpCelebration
-
One LevelUpEvent plus the extra presentation detail
LevelUpOverlayController needs that LevelUpEvent itself doesn't
carry: where its XP bar starts filling FROM. Every level after the
first in a queue starts a fresh bar at 0 — only the very first queued
event might start partway through (wherever the player's bar actually
was right before the
grantXpcall that crossed it). - LevelUpEvent
- Fired once per level actually crossed by a PlayerProgressionService.grantXp call — a single call that jumps several levels at once fires one of these per level, in ascending order.
- LevelUpOverlay
-
Renders LevelUpOverlayController's sequence over child — same
in-tree-overlay pattern as
NeonDialog/SceneTransitionOverlay(seeCLAUDE.md's "Dialog pattern" note), so it also works over a full-screen FlameGameWidget. - LevelUpOverlayController
-
Pure state machine driving LevelUpOverlay — no
Animation/BuildContexthere, so it's unit-testable without pumping a widget tree (same shape asSceneTransitionController, FEAT-58). - LiveFrameGraph
- Live, bounded frame-time graph for a debug/profile QA panel.
- LoadingOverlay
- Full-screen dimmed barrier + centered candy-styled spinner.
- LocaleService
- Manages the current language + persists the user's choice.
- LocalScoreboardService
- Local, single-device high-score table — a cache/offline-first precursor to a real backend/Game Center leaderboard, and useful on its own even without one. Unlike LeaderboardList (pure display, ranking data always supplied by the caller), this service actually ranks a new submitScore against every previous submission on this device.
- MemoryWatchdog
- Debug-only tracker for disposable resources (tickers, controllers, overlay entries, stream subscriptions, Flame components) that are easy to forget to dispose — a widget/service calls track when it CREATES one and release when it properly disposes it; anything still tracked when orphans is called (typically at the end of a test, or from a debug overlay/health report during a real session) is a leak candidate.
- MemoryWatchdogPanel
-
Read-only view of caller-built memory watchdog rows. It never reads
MemoryWatchdog. The watchdog is a debug-only leak detector, not leak prevention, and reports nothing in release builds. - MilestoneCelebrationDialog
- Celebration panel for a major level milestone (25/50/100/500) — gold badge with the level number and a slow rotating light sweep, the commemorative reward list, and a Claim button (FEAT-135).
- MilestoneReward
- One commemorative reward row shown in MilestoneCelebrationDialog (FEAT-135).
- MoveHintPopup
- In-tree puzzle hint panel. Caller owns hint selection, board logic, and optional refill/purchase flow; this widget only presents provided content.
- MysteryChestOpening
- MysteryChestOpeningState
- NeonAppBar
- Thanh tiêu đề (action bar) neon dùng chung cho mọi màn phụ. Là widget cố định trên cùng — nội dung cuộn nằm dưới, không bị đè.
- NeonAuraLayer
-
G5: aura bloom động sau bàn, dùng shader
shaders/neon_glow.frag(đã có sẵn trong repo). Load lỗi (thiết bị không hỗ trợ) → ẩn hẳn, không crash. - NeonBackButton
- Nút back neon dùng chung cho mọi màn phụ (mặc định quay lại màn trước).
- NeonBg
- Background neon ĐỘNG dùng chung cho mọi màn: gradient nền + nebula trôi + sao lấp lánh + tia sweep xoay + vignette. Hiệu năng tốt: dùng RadialGradient/shader, không MaskFilter.
- NeonButton
- Nút bấm phong cách neon: viền sáng + glow + chữ phát sáng.
- NeonDialog
- NeonDialogAction
- Một nút hành động trong dialog. onTap tự chịu trách nhiệm đóng (route/overlay).
- NeonDialogButton
-
Nút hành động dùng chung trong NeonDialog.panel — public để các dialog
tự viết (login streak, weekly goal...) nhúng lại 1 nút reactive đơn lẻ vào
content:khi cần label/onTap đổi theo state mà không thể dùngactions:tĩnh của NeonDialog.show. - NeonIcon
- Icon phong cách neon: lõi trắng + glow màu (dùng chung toàn app).
- NeonIconButton
- Nút icon neon bấm được (glow + vùng chạm rộng). boxed = chip tròn viền neon + glow (dùng cho lối vào chính ở Home); mặc định icon trần (back/appbar).
- NeonTheme
- Shared color palette & styles. Bright-casual (Candy-Crush-style) revamp: warm light background, candy palette, white cards, bold ink text. Keeps the old constant names (cyan/magenta/…) to avoid a mass callsite rename — the values themselves have been retuned to a "candy" tone.
- NetworkStatusBanner
- Thin banner pinned to the top of the screen, shown while connected is false (e.g. so a silent cloud-save failure isn't a confusing "why didn't my progress save?" moment).
- Short "next reward" nudge: reward name, caller-formatted remaining text and optional progress. Presentation-only: the caller owns progress and the destination screen.
- NoopAnalyticsProvider
- Default no-op implementation so a consuming app doesn't have to wire a real analytics adapter immediately.
-
ObjectPool<
T> -
Generic acquire/release object pool (FEAT-48) — reuses instances of
T(a Flame particle/projectile component, or any other allocation-heavy object) instead of letting a hot gameplay loop allocate and immediately discard one every frame. - OfflineEarningsPopup
-
A presentation-only popup showing coins earned while the player was away
(FEAT-140). The caller gets the actual earnings from
OfflineProgressionService.claim()and grants them through its own wallet. - OfflineOutboxService
- Persisted, priority-drained outbox for syncing local changes to a remote authority once back online — built on RetryExecutor (FEAT-35) for transient-failure backoff and, when connectivity is supplied, driven automatically by ConnectivityCoordinator (FEAT-62)'s online transitions the same way that service drains its own internal task queue.
- OfflineProgressionService
-
Calculates idle/offline earnings accrued while the player was away:
earnings = min(elapsed, maxOfflineCap) * productionRatePerSecond, whereelapsedis time since the last claim. - OnboardingCoordinatorService
-
Decides WHICH onboarding/tutorial flow should run next and WHETHER a
given one has already been seen — the coordination layer this package's
tutorial widgets (
TutorialSequence,SpotlightOverlay, IDEA-35's JSON-authored flows) never had. Those widgets only know how to RENDER one flow once told to; this service never renders anything itself, has noBuildContext/GlobalKey/Navigatordependency, and doesn't call into those widgets — a caller still owns showing the actual UI, this only answers "whichflowId, if any, should run right now". - OnboardingFlowQueueCard
-
Read-only onboarding queue. The caller maps
isFlowSeenandnextEligibleFlowto rows; this card never receives the coordinator. - OnboardingFlowRow
- OutboxConflictSummary
- OutboxConflictSummaryPanel
- OutboxItem
-
One queued, not-yet-synced unit of work. payload is plain,
caller-defined JSON data — same "never put a secret in it, it's
persisted locally in plain JSON" caveat as
RewardTransactionRecord.receiptMeta(FEAT-42). - OutboxQueueStatusCard
- PaginatedDotsIndicator
-
N dots for a paginated carousel/onboarding flow — the dot at
currentIndex renders bigger/brighter than the rest. Pure presentation:
does not own a
PageControlleritself, the caller wires it up viaPageView.onPageChangedand passes the resulting index in. - PanelCard
- Generic rounded card/panel — the building-block container most screens wrap content in. Background is NeonTheme.card (or NeonTheme.cardAlt via alt), with a NeonTheme.drop shadow and an optional colored borderColor accent ring.
- PauseOverlay
-
Pause panel wired directly to GameSessionController — the pause
button/system-lifecycle-pause round trip this repo already has (see
game_session_controller.dart's own RoyLifecycleCoordinator hook) gets exactly one visible UI on top of it. Caller mounts this unconditionally inside their ownStack(same "always mounted,NeonDialog.overlaySlotanimates the panel in/out" convention as every other in-tree overlay in this kit) — it decides on its own, from session, whether to show: - PerformanceBudgetMetric
-
One measured value — e.g. an allocation-reduction percentage from
tool/object_pool_benchmark.dart, or a real-device app-boot wall time. - PerformanceBudgetResult
- PerformanceBudgetViolation
- PerformanceTierService
- Runtime, live-reactive FPS gate for decorative shader/ticker layers.
- PersistentCooldownService
- Keyed cooldown tracker (reward claim timers, booster reuse delays, PvP action gates, ...) that survives app restart and resists clock-rewind cheating.
- PiggyBankVault
- PlatformCapabilityMatrix
-
Read-only platform capability list. Support is shown by icon and text, not
colour alone. The caller maps
PlatformCapabilitySnapshotto rows; those values are the registry's policy defaults, not a live platform probe. - PlatformCapabilityRegistry
- SSOT for PlatformCapabilitySnapshot — computed (or injected) exactly once at construction and cached for the lifetime of the instance, so every read is free and no code path re-queries platform state.
- PlatformCapabilityRow
- PlatformCapabilitySnapshot
-
Immutable, already-resolved capability snapshot for the 4 domains this
kit actually integrates with: haptics (
haptics.dart), shaders (AuroraBgLayer/NeonAuraLayer), local notifications (ReminderService), and background audio (AudioManager). - PlayableCharacter
- A playable character moving in 8 directions with attack action.
- PlayerAttackedEvent
- PlayerDataRightsPanel
-
Presentation-only export/erase panel for
PlayerDataRightsService. - PlayerDataRightsService
- A complete "player requested their data" workflow (GDPR/CCPA-style) built on top of StorageService.exportAll/StorageService.eraseAll — those give the low-level mechanism, this gives the business workflow: a clear export receipt with metadata, and an erasure receipt confirming completion + which other seams got a chance to clean up their own side.
- PlayerProgressionService
-
Single source of truth for one player's XP/level — persists
PlayerProgressionSnapshot.totalXpEarned (never level/xpIntoLevel
directly, both are always re-derived from it and the curve) plus a
bounded idempotency ledger, same pattern as
EconomyWallet/RewardTransactionPipeline(FEAT-31/FEAT-42): a corrupt save resets to a fresh, never-exploitable state instead of throwing or trusting a partially-decoded value. - PlayerProgressionSnapshot
- Reactive snapshot of one player's progression — level/xpIntoLevel/ xpToNextLevel are always derived fresh from totalXpEarned against the curve (never persisted directly), so they can never drift out of sync with it.
- PluginAdapterConformanceSuite
- Vendor-neutral conformance checks for the kit's platform adapters.
- PooledParticleBurst
- Reusable radial particle burst. Call PooledParticleBurstState.burst to replay; the pool is prewarmed to particleCount so later bursts reuse every particle object instead of allocating another batch.
- PooledParticleBurstState
- PressableScale
- Bọc 1 nút bấm để co nhẹ (scale) lúc nhấn xuống — micro-bounce dùng chung cho mọi nút (A3). Tái dùng 1 chỗ thay vì lặp GestureDetector+AnimatedScale ở từng widget nút.
- PrestigeConfirmationCard
- Confirmation card shown before prestiging (resetting short-term progress for permanent multiplier boosts and rewards).
- PrestigeReadinessCard
-
Presentation-only prestige progress: balance toward the threshold, the
permanent multiplier and a CTA enabled only when ready. It never performs
a prestige; onPrestige should open a confirmation (for example
PrestigeConfirmationCard.show) before the caller invokes the service. - PrestigeReward
- One reward earned on prestige (presentation-only).
- PrestigeService
-
The classic idle/incremental-game "prestige"/"ascension" loop (Cookie
Clicker, Adventure Capitalist, ...): once primaryCurrency reaches
prestigeThreshold, the player can soft-reset softResetCurrencies
(wiped back to 0) in exchange for relicsPerPrestige of
metaCurrency — a currency that's NEVER soft-reset, and permanently
raises currentMultiplier via prestigeMultiplier (
economy_math.dart, the pure formula this andtool/economy_sim.dart's balancing simulator both call, so they can't silently drift apart). - PrivacyAwareAnalyticsQueue
- Consent-first, schema-redacted, deterministic-sampled persistent FIFO.
- PrivacyAwareAnalyticsSampler
- Decorator over a real AnalyticsProvider (FEAT-83) combining 3 privacy/ volume controls, each independently audit-countable via auditSnapshot:
- ProfileLevel
- Caller-supplied progression data; no service lookup or XP calculation.
- ProfileStat
- One caller-formatted profile statistic.
- ProfileStatsCard
- Player profile summary: avatar/frame, identity, optional level and caller- formatted stats. It stores no profile state and owns no external actions.
- ProgressBarStars
- Rounded pill-shaped progress bar with 1-3 star markers along the track — a marker the fill has passed lights up (filled), otherwise it stays a dim outline. Used for world progress / event tracks like "reach 33%/66%/100% to unlock a star".
- PseudoLocaleTranslations
-
A GetX
Translationsthat wraps baseKeys (typically a real locale's map, e.g.AppTranslations().keys['en']!) with pseudoLocalize on every value — every key baseKeys has is covered by construction (thekeysgetter maps every entry, never a subset). - PurchaseLedgerService
-
Thin local cache on top of
PurchaseSeamfor the 2 purchase shapes almost every game needs and would otherwise re-implement per project: a consumable with a remaining balance ("5 hint tokens left") and a permanent one-time unlock ("remove ads", "premium skin pack"). - PurchaseSeam
-
Platform-neutral in-app-purchase seam — the package pulls in no IAP SDK
(no
in_app_purchase, no RevenueCat, …); a consuming app registers its own adapter viaGet.put<PurchaseSeam>(myAdapter, permanent: true), same pattern as CrashReporter/AnalyticsProvider/CloudSaveProvider/ RemoteConfigService. - QuestBoardPanel
-
Displays a list of QuestViewModels — progress bar + a Claim button
that's only enabled once a quest is completed and unclaimed — the
ready-to-use on-screen counterpart to
DailyQuestService(IDEA-29), which previously had no widget consuming it at all. - QuestProgressPill
- Compact "completed/total quests" entry with a claimable-reward badge. Presentation-only: the caller reads quest state and opens the board.
- QuestViewModel
-
One caller-supplied quest row — label/progress/target/claimed are
already resolved by the caller (typically read straight off
DailyQuestService.progressOf/targetOf/isClaimedfor id); this widget never talks to that service directly, same "pure/data-driven, caller owns the source of truth" convention as LeaderboardEntry. - QueuedAnalyticsEvent
- QueuedTask
- One retryable, idempotent unit of work queued while offline.
- RadialActionItem
- RadialActionMenu
- RadialActionMenuState
- RandomSnapshot
- Opaque, versioned snapshot of a SeededRandom's internal state — serializable so a caller (e.g. a save file, or IDEA-42's replay capsule) can persist an RNG stream and later resume it at the exact point it left off, via SeededRandom.fromSnapshot.
- RankPromotionDialog
- Presentation-only modal celebrating promotion between leaderboard tiers (FEAT-147).
- ReactiveEnergyBar
- Service-bound freshness wrapper for EnergyBar (BUG-95).
- ReminderIntervalOption
- ReminderPreferencesPanel
- Caller-owned reminder preference control. Callback completion means the caller accepted the request, not that the OS scheduled or will deliver it. The platform may delay delivery or suppress it when notification permission is unavailable.
- ReminderService
- One local notification, scheduled a fixed delay out. Games that need several reminder kinds/priorities should extend this, not add branches here — keep the base's default path to exactly one notification.
- RemoteConfigHealthCard
- Safe remote-config diagnostics only: this card never accepts key/value data, schema-violation strings, or a service instance.
- RemoteConfigKeySchema
-
One remote-config key's expected shape — registered via
RemoteConfigService's
schemaconstructor param (ENH-84). Reuses EventParamType (SdkEventSchemaRegistry's own 4 primitive kinds) — remote config values are the exact same string/int/double/bool shapes, no need for a parallel type enum. - RemoteConfigService
-
Remote config / feature-flag seam. The package pulls in no HTTP/Firebase
SDK — a consuming app injects its own network call via fetchRemote
(e.g. wrapping
dio/http/Firebase Remote Config). init always loads the bundled asset fallback first so typed getters have something valid to return even before (or if) the network attempt resolves, then tries fetchRemote and MERGES its entries on top of the asset defaults key-by-key (ENH-58) — a partial response only overrides the keys it actually sends, every other key keeps its already-validated asset value. Anullvalue for a key in the remote response is treated as "no override" (skipped) rather than "set this key to null", so a server that echoes back unset fields asnullcan't wipe a working default. A missing asset or a failing/absent fetchRemote is swallowed silently — this never throws, it just falls back to defaults. -
RemoteContentPack<
T> -
A typed, signed remote content slot — live-ops content (a level
definition, a shop catalog page, an event schedule) pushed from a
server without an app-store review cycle, built on the same 3 pieces
RemoteConfigService, VersionedJsonStore and
save_integrity.dartalready provide separately (IDEA-37): asset-fallback-then-fetch, schema-version migration, and HMAC signing. - RemoteKillSwitchController
- Emergency remote kill switch for a feature/event/shop/animation — built on top of RemoteConfigService (FEAT-39/ENH-58 already give it asset-fallback + partial-merge + last-known-good semantics at the config-value level; this controller adds the kill-switch-specific safety policy ON TOP: an invalid or missing remote value can never flip a feature from killed back to enabled — see KillSwitchSource for the exact resolution order).
- RemoteKillSwitchPanel
- Safe local-control panel for kill-switch state. The caller maps service state to KillSwitchItem, sanitizing any remote reason before passing it. This widget cannot enable a remotely killed feature; it only offers a confirmed client-local kill and a clear action for an existing local override.
- RemoteSchemaDef
- Validated, immutable definition of one remote content pack's schema across its version history. See library doc for the safety guarantee its factory constructor provides.
- RemoteSchemaField
- One field in one RemoteSchemaVersion's shape.
- RemoteSchemaVersion
- One version's full field shape.
- ReplayCapsule
-
A versioned, signable envelope capturing everything needed to replay 1
recording session: the RNG seed (feed straight into
SeededRandom(seed)/SeededRandomService(seed)), the appVersion it was captured under, and the ordered events. - ReplayDivergence
-
The first index at which expected and actual differ —
nullif they're identical throughout. Reported with both values so a caller (e.g. a replay-divergence debug view) has enough context to see exactly where and how a replay diverged from what was originally recorded, per-event or per-checkpoint (whatever unit the caller compares). - ReplayEvent
-
1 recorded input/decision event — offsetMs is a monotonic offset from
the moment ReplayRecorder.start was called (never wall-clock time, so
a replay run doesn't need to happen at the same real-world moment).
payload is entirely caller-defined — this class never inspects or
interprets it, same "pure envelope, caller owns the shape" convention as
LeaderboardEntry/VictoryCardTemplate.statLines. - ReplayRecorder
- Records gameplay/input events into a bounded ring buffer during a QA session, then packages them (plus the session's RNG seed) into a ReplayCapsule a developer can import elsewhere to reproduce a bug that was hard to describe from a screen recording alone.
- ReplayVerificationResultCard
- Only caller-mapped status and safe copy; never raw replay data or secrets.
- ReproductionCapsule
- Combines ReplayRecorder (recorded input/decision events), SeededRandomService (per-namespace RNG state), and TrustedClockService (clock-tamper judgement) into 1 redacted, signed artifact serving 2 purposes: (a) support — a dev imports it to reproduce exactly the event sequence that led to a bug; (b) anti-cheat — verify a played session wasn't tampered with, by replaying it and comparing outcomes (and, independently, RNG state) against what was recorded.
- ReproductionReplayResult
- Result of ReproductionCapsule.replay — 2 independent signals a captured session was reproduced faithfully.
- RestoreLogEntry
- One step of an DisasterRecoverySaveExport.applyRestore run — the recovery log a crash/interruption mid-restore leaves behind, so "which slots actually got restored before it broke" is answerable afterward instead of guessed.
- RestorePreview
- A validated, NOT-YET-APPLIED export — DisasterRecoverySaveExport.previewRestore returns this so a UI/support agent can review exactly what a backup contains (slot names, when each was last played, how many keys) before DisasterRecoverySaveExport.applyRestore ever touches real storage. Building this never writes anything — see that method's own doc.
- RestoreSlotPreview
- RetryAttemptEvent
- RetryErrorState
-
Data-driven "this failed, here's why, try again" panel — composed from
EmptyStatePlaceholder (same icon-badge/title/message chrome every other
empty/error state in this kit already uses) plus an optional
AsyncCommonButton retry action, which is what actually gives "rapid tap
doesn't run the retry twice" for free (see
async_common_button.dart's own re-entry guard) — this widget adds no tap-guarding of its own. - RetryExecutor
-
Runs an action against a RetryPolicy.
delayFn/randomFnare injectable (default to realFuture.delayed/Random().nextDouble()) so a test drives the whole retry loop deterministically and instantly, never actually waiting real backoff delays — same seam-injection convention asHapticChoreographer'screateTimer. - RetryPolicy
- Immutable exponential-backoff-with-jitter configuration — no timers, no randomness of its own, just the math. RetryExecutor is what actually runs a retry loop against it.
- ReviewPromptTrigger
-
Wraps child and calls maybeRequestReview every time
winStreakEvents fires (ENH-87) — the ready-to-use widget counterpart
to
in_app_review_helper.dart's decision logic, which the rest of the kit had no widget consuming at all before this. Same "core service has timing logic → widget listener wired to it" pattern asAchievementUnlockListener/AchievementService. - RewardAuditRow
- RewardAuditTrailPanel
- RewardChoiceOption
- One choosable reward option in a RewardChoicePanel. Immutable — the panel never mutates these, only tracks which ids are selected/claimed separately.
- RewardChoicePanel
-
Lets a player pick one (or, with multiSelect, several) reward from
options, then confirm — this panel only ever hands back the chosen
ids via onConfirm; actually granting the reward is the caller's
job (typically a
RewardTransactionPipeline.grant()call keyed off those ids), matching this repo's "widgets don't self-grant" convention (see CLAUDE.md). - RewardedAdResultCard
-
Rewarded-ad state and watch button. It never calls
AdRewardSeamand never grants anything. The caller mapsisReadyand theshowRewardedAdresult to status and grants the reward once, with its own idempotent transaction id, only after the seam returnedtrue. The "rewarded" copy is shown only when the caller sets RewardedAdStatus.rewarded. - RewardLine
- One currency amount inside a RewardTransactionRecord. A single reward event (e.g. a rewarded ad) commonly grants more than one currency at once ("+50 coin, +1 energy"), which is why a transaction is a list of these rather than a single currency/amount pair.
- RewardPlan
- Immutable dry-run result from RewardTransactionPipeline.preview — what RewardTransactionPipeline.executePlan would grant, validated against the state at preview time, WITHOUT having mutated or persisted anything yet (FEAT-96). Only RewardTransactionPipeline.preview can construct one.
- RewardPlanPreviewCard
- RewardPlanPreviewLine
- RewardPopup
-
Celebration popup (level-up, reward unlocked, ...) — a panel layout like
NeonDialog.panel(roundedNeonTheme.cardcard, colored border, glow+drop shadow, title/message) but a standalone widget that doesn't route throughNeonDialog, since it needs the confetti burst effect radiating around the panel, whichNeonDialogdoesn't support. content is a free slot — the caller drops in aStarRating/CurrencyCounter/... - RewardSequenceController
- RewardSequenceCoordinator
- Sequences reward slots, with optional tap-to-skip and Reduce Motion support.
- RewardTrackRoad
- Horizontally scrollable XP reward track with free and optional premium lanes.
- RewardTrackTier
- A tier on a horizontal XP reward track (FEAT-150).
- RewardTransactionPipeline
-
Orchestrates a reward grant (ad/IAP/quest/daily-login) across multiple
currency lines on top of EconomyWallet, which already guarantees
per-line idempotency (same derived transaction id → applied once, even
across a restart or a concurrent duplicate callback — see
economy_wallet.dart). This pipeline adds what the wallet alone can't: - RewardTransactionRecord
- One reward grant attempt — RewardTransactionPipeline's audit-trail entry. receiptMeta is caller-supplied bookkeeping (e.g. a store product id) for reconciliation/support — never put a secret in it, it's persisted locally in plain JSON.
- RibbonBadge
-
Diagonal corner-ribbon overlay (e.g. "NEW"/"SALE"/"BEST VALUE") wrapping
any child — shop/IAP item badge. Draws into its own internal Stack
sized to child, independent of any Stack the caller might have
(avoids the caller-owned-
Stackcoupling problem noted for LoadingOverlay/ENH-03 — just wrap:RibbonBadge(text: 'SALE', child: myCard)). - RoyCasualKit
- Idempotent GetX service bootstrap for consumer apps.
- RoyCasualKitConfig
- Immutable SDK bootstrap configuration.
- RoyCasualKitContractReport
- Result of the standard consumer bootstrap contract checks.
- RoyCasualKitContractTestKit
- Reusable assertions expressed as a plain Dart report so consumers can use it from any test runner and turn failures into their preferred matcher.
- RoyCasualKitResult
- Result of bootstrap. A degraded result still reports successful modules so a host can decide whether to continue or show its own fallback UI.
- RoyCasualKitTestFixture
- Deterministic, vendor-neutral fixture for consumer contract tests.
- RoyGame
-
Minimal Flame starter template (FEAT-14): proves
FlameGame/Component/GameWidgetactually wire up end-to-end in this package — theflamedependency existed but nothing used the game-loop engine before this. Deliberately not a real game: one background color + one tappable TappableCircle. A consumer app building a real game should extend this rather than reading it as a template to copy-paste from scratch. - RoyLifecycleCoordinator
- Ordered, isolated lifecycle dispatcher shared by SDK modules and consumers.
- RoyLifecycleHookFailure
- SaveConflictPicker
- SaveConflictSummary
- SaveHealthCard
- A small self-contained diagnostic card (IDEA-59) for "is the player's save currently healthy" — the question support/QA gets asked after a "I lost my progress" report, without needing a dev to pull device logs.
- SaveHealthCardState
- SaveMigrationRegistry
- Immutable, validated multi-hop save migration registry.
- SaveMigrationStep
- SaveRestorePreviewPanel
-
Per-slot summary shown before a destructive restore. The caller maps a
validated
RestorePreviewto slots and runsapplyRestoreitself in onConfirmRestore. The widget never receives slot data, the signed bundle, the secret or the recovery-log detail, and never renders a slot id. Restoring needs an explicit inline confirmation. - SaveSlotManager
- Manages multiple independent save slots (separate characters/profiles) on the same device — the classic "3 save files, pick a character on the home screen" casual/mid-core game pattern.
- SaveSlotMeta
- Metadata for one save slot — SaveSlotManager never sees or owns the actual player-profile data inside a slot, only bookkeeping about the slot itself.
- SaveSlotPicker
- Presentation-only UI picker for browsing, selecting, creating, and deleting save slots (FEAT-143).
- SbomDocument
-
A reproducible bill-of-materials document —
toJson()'sentrieslist is always in the same (name-sorted) order parsePubspecLock already guarantees, so hashing/diffing 2 SBOMs of the same lock file is meaningful. - SbomIssue
- SbomSuppression
-
A pre-approved exception — owner and
expiresAtMsAfterEpochare both required (not optional) because an unowned or permanent suppression is exactly the "false positive with no accountability and no forced re-review" this task's acceptance criteria calls out. OnceexpiresAtMsAfterEpochhas passed (checked against auditDependencies's ownnowMs), the suppression simply stops applying — no special "expired" state to handle, the issue just reappears in the next audit. - ScenePreloadStatusPanel
- SceneTransitionController
-
Pure state machine driving SceneTransitionOverlay — no
Animation/BuildContexthere, so it's unit-testable without pumping a widget tree. - SceneTransitionOverlay
- Fades or shape-wipes a full-screen barrier over child while a controller-driven transition runs. The underlying scene cannot receive pointers or semantics while the transition is active.
- SchemaValidatedAnalyticsProvider
-
Decorator over a real AnalyticsProvider — validates every event
through registry first, forwarding only EventValidationResult.sanitizedParams
when accepted, dropping it silently otherwise (never partially, never
raw). Same decorator shape
ConsentGatedAnalyticsProvideralready uses, so it composes:SchemaValidatedAnalyticsProvider(ConsentGatedAnalyticsProvider(real), registry). - ScoreEntry
-
One row of a synced leaderboard — the seam's own data shape, deliberately
simpler than the widget-facing
LeaderboardEntry(presentation/widgets/common/leaderboard_list.dart): a rawintscore instead of a locale-formatted display string, since a sync adapter round-trips raw numbers with a real backend. - ScratchCard
- ScratchCardState
- ScratchCoverageGrid
- ScreenShake
-
Wraps child in a
Transform.translatedriven by controller. Ticks aTickeronly while a shake is actually decaying (stops oncecontroller.offsetAt(...)returns Offset.zero, not left running forever). Respects NeonTheme.reducedMotion — when on, renders child unchanged regardless of what controller does, same as the decorative shader layers (ShaderTickerLayerState). - ScreenShakeController
-
Per-screen/per-widget-tree shake controller (IDEA-08) — a plain
ChangeNotifierthe caller creates and owns (like aTextEditingController), not a globalGetxServicesingleton, since screen-shake state is local to whatever's shaking (a board, a card, a whole screen), not app-wide. - SdkEventSchemaRegistry
- Validates event name/params against registered EventSchemas before anything reaches a real AnalyticsProvider — default-deny at 2 levels: an unregistered event name is rejected outright, and a registered event's own unknown/pii fields are handled per the schema's own policy rather than passed through untouched.
-
SdkFailure<
T> - SdkHealthReport
-
Collects a QA/support-facing diagnostic snapshot from whichever
HealthCollectorSpecs are registered — a missing or throwing collector
never breaks the rest of the report (its section just reports
_errorinstead), and every value is redacted to its own allowlist and size- capped, so this is safe to export/copy/share by default (no secret, raw save data, token, or PII shows up unless a collector's own allowlist explicitly names that key — which none of this package's own defaultHealthCollectors do). -
SdkResult<
T> -
SdkSuccess<
T> - SeasonEventBanner
- A prominent live-ops banner for seasonal events and tournaments (FEAT-130).
- SeasonEventService
-
Repeating, has-a-time-window event/season schedule — the piece
CountdownChipneeds a caller to compute by hand today. UnlikeDailyLoginService's fixed calendar-day cycle, an event here repeats on its own caller-declared cadence (lengthactive, thencooldownidle, then repeats), anchored to whenever currentWindow is first called for thateventId— not to a calendar boundary. - SeasonEventWindow
- One event's active window, as returned by SeasonEventService.currentWindow.
- SectionHeader
- Bold section title + optional trailing action (e.g. a "See all" button) — for grouping sections of a screen ("Daily Rewards", "Leaderboard", ...).
- SecureStorage
- The actual call surface for secure values — wraps SecureStorageAdapter with the typed SdkResult contract, key validation, and a clear, typed failure (never a silent fallback to regular storage) when no adapter is registered.
- SecureStorageAdapter
-
Platform-neutral secure-storage seam — the package pulls in no concrete
secure-storage SDK (no
flutter_secure_storage, no Keychain/Keystore wrapper); a consuming app registers its own adapter viaGet.put<SecureStorageAdapter>(myAdapter, permanent: true), same pattern as PurchaseSeam/CloudSaveProvider/AnalyticsProvider. A typical real implementation just forwards these 4 methods toflutter_secure_storage'sFlutterSecureStorage(Keychain on iOS, EncryptedSharedPreferences/Keystore on Android) — this seam doesn't pick that dependency for you. - SeededChallengeReplayResult
-
Outcome of SeededChallengeService.replay —
nulldivergence means the replay reproduced every checked outcome exactly. - SeededChallengeService
- FEAT-97: ties together this kit's existing deterministic-replay primitives — SeededRandomService (RNG snapshot/resume), ReplayRecorder/ReplayCapsule (recorded event replay + divergence detection), and LocalScoreboardService (on-device ranking) — into one "same challenge, reproducible run, fully offline" building block, so a consuming game doesn't have to wire all 3 together itself and risk a seed/clock/replay mismatch doing it.
- SeededRandom
-
Deterministic, cross-platform-stable pseudo-random generator —
implements Random so it's a drop-in source for weightedRandomPick,
List.shuffle, or anywhere else adart:mathRandomis accepted. - SeededRandomService
-
Manages independent, deterministically-derived SeededRandom streams
keyed by a caller-chosen namespace (e.g.
"loot","enemy_spawn") — so one gameplay system calling its own stream an extra time never shifts another system's sequence, the classic shared-RNG replay-determinism trap. - SegmentedTabBar
- A 2-4 item pill tab bar (e.g. mode selection) — the active item is highlighted by an animated sliding background pill, the rest are plain text.
- SessionInfo
-
Immutable snapshot of the current process's session — a fresh one is
created at construction (cold start) and again on any
RoyLifecycleEvent .resumedthat arrives after longer than AppSessionTracker.sessionTimeout in the background. - SessionTimelineInspector
- Read-only, bounded session timeline. The caller decides which metadata is safe to include in each row; this widget never accepts a controller or raw timeline entry.
- SessionTimelineRow
-
ShaderTickerLayerState<
T extends StatefulWidget> -
Hạ tầng dùng chung cho các layer full-screen chạy 1
FragmentShader(AuroraBgLayer,NeonAuraLayer): loadFragmentProgram.fromAssetvới try/catch (ẩn hẳn hiệu ứng nếu load lỗi, không crash), throttle ticker repaint xuống ~30fps, và dispose đúng cả ticker lẫn shader. - ShadowActivationController
- Watches caller-reported metrics for a feature/event that's been shadow-activated (rolled out to a small cohort ahead of a full release) and auto-rolls-back — CLIENT-SIDE, without waiting for an operator — the instant a registered GuardrailDefinition is violated (FEAT-90).
- ShimmerPlaceholder
- Skeleton-loading block for list/grid content that hasn't finished loading yet (a shop item row, a level list waiting on a cloud-save sync) — unlike LoadingOverlay (a full-screen barrier), this sits in-place as a stand-in for the real content.
- ShopItemCard
-
Ready-made shop/IAP grid item: icon + title + price pill, composed from
PanelCard + CommonButton (and optionally RibbonBadge) rather than
every app re-assembling those by hand. Pure presentation — priceLabel
is a caller-formatted string (e.g.
"$0.99"), and onBuy is just a callback; this widget never calls intoin_app_purchaseitself (that's FEAT-01's job). - SlotExportEntry
-
One save slot's exported data — meta mirrors SaveSlotMeta (plain
fields, this class never holds a live reference to it), data is the
raw
StorageService.exportWithPrefixresult for that slot's key range. - SoundToggleFab
-
Small floating round button toggling AudioManager's mute state —
speaker icon flips on/off, tap calls
toggleMute(). Uses AudioManager.maybe (the null-safe accessor): renders nothing if audio hasn't been registered instead of throwing, so a gameplay screen can drop this in unconditionally. - SparkleParticle
-
One decaying particle in a tap-triggered burst (ENH-81) — shrinks and
fades over
_lifetimeSeconds, then removes itself; PooledComponent then returns it to RoyGame.sparklePool automatically. reset (not the constructor) sets per-spawn state, since a pooled instance is reused across many bursts instead of being constructed fresh each time. - SpotlightHolePainter
-
Cuts a rounded-rect hole out of a full-screen dim scrim using
Path.combine'sdifferenceop. Public (rather than the usual underscore-private painter convention in this file's siblings) so a widget test can pull.holeback off the mounted CustomPaint and assert it against the target's realRenderBoxbounds. - SpotlightOverlay
- Onboarding/tutorial coach-mark: dims the whole screen except a highlighted "hole" cut around a target widget's actual on-screen bounds, plus a guidance callout with a dismiss button.
- SpringScaleTransition
- SpringSimulationController
- SquashStretch
-
Non-uniform "squash" wrapper (IDEA-08) — unlike PressableScale's
uniform scale-down, this squishes horizontally (scaleX up, scaleY down)
on tap-down, then a real SpringSimulation (not a fixed
Curve) bounces it back to(1.0, 1.0)on release, carrying over whatever velocity the spring already had (so a quick re-tap doesn't reset to a dead stop). - StackedAvatarGroup
- StackedAvatarItem
- StaggeredAnimatedGrid
- StarChestProgressHud
- A compact horizontal capsule HUD displaying accumulated stars toward unlocking a Star Chest (FEAT-134).
- StarRating
- A row of N stars (usually 3) — the first earned stars are lit/glowing, the rest are a dim outline. The classic "level complete, got 2/3 stars" look. animate = true makes each star pop in with a staggered delay after the previous one (used right after earning the reward); false draws it statically (already earned earlier, shown again without replaying the animation).
- StorageKeys
- StorageService
-
Shared local storage service (wraps SharedPreferences).
Registered once in main:
Get.put(StorageService(prefs), permanent: true). - StreakCounter
-
Fire icon + a streak day count (consecutive logins, ...). Same
layout/spacing as CurrencyCounter, but instead of counting up it pops
(scale bounce) whenever days increases — a reward moment, same spirit
as
StarRating's pop-in. - StreakMilestone
- One long-term streak reward threshold (e.g. day 7, day 30).
- StreakMilestoneStrip
- Horizontal strip of long-term streak milestones with claim state. Presentation-only: the caller owns the streak, time and reward granting.
- StreakRepairDialog
- StreakShieldCard
- Presentation-only card showing streak protection status, available freeze shields, and action buttons to use a shield or repair streak (FEAT-144).
- StrokeText
- Chữ có viền (stroke) — dễ đọc trên nền candy nhiều màu. Vẽ 1 lớp stroke phía sau + 1 lớp fill phía trước (kỹ thuật outline chuẩn cho casual game).
- SunburstGodRays
- SupportDiagnosticsCard
- Displays a safe diagnostics summary and asks for explicit consent before invoking the caller's share callback. It never receives the payload itself.
- SupportDiagnosticsSummary
- Safe summary only; raw storage, bundle JSON and log contents are not accepted by this widget. The caller keeps the actual diagnostics payload.
- SwipeableAction
- SwipeableActionTile
- SwipeableActionTileState
- SyncAck
- The remote authority accepted the payload as-is.
- SyncConflict
- The remote authority's state for this OutboxItem.idempotencyKey has diverged from what was queued — remotePayload is its current value, handled per ConflictPolicy.
- SyncOutcome
- Result of one OutboxUploader call.
- SyncStatusCard
-
Presentation-only sync status with a manual sync/retry button, for the
achievement or leaderboard seams. The caller runs the sync (for example
AchievementSyncCoordinator.sync) and maps its result to status; this widget never reads a service or shows an exception. A callback that returns without throwing is not shown as success: only status is. - TapHintPointer
-
Non-blocking animated hand that shows the player where to tap or swipe
(FEAT-131). Complements
SpotlightOverlay/TutorialSequence, which dim and explain but do not demonstrate the gesture. - TappableCircle
-
A circle that flips between two
NeonThemeaccents on tap — the single piece of interactive state this starter template proves works through a realGameWidget(seeneon_dialog.dart's overlay pattern doc comment, which this template's demo screen also exercises). - TeamMemberItem
- Caller-supplied member item presentation model.
- TeamRosterList
- Lazy list of clan or team members with caller-owned promote/kick actions and capacity counting.
- ThemeContrastConfig
-
Thresholds — defaults are WCAG 2.1 AA. Pass a stricter
ThemeContrastConfig (e.g.
normalTextThreshold: 7.0for AAA) to tighten the bar without touching validator code. - TieredLeaderboardRow
- One tiered leaderboard competitor row (FEAT-139).
- TieredRewardChest
- Chest that visually upgrades Wood -> Silver -> Gold -> Diamond as the caller raises currentTier, then opens with tier-colored rays and the caller-supplied reward for that tier (FEAT-124).
- TitleChipPicker
- Wrap-layout title selector with caller-owned unlock and selection state.
- TitleOption
- One caller-owned player title.
- ToastBanner
- Small candy-styled toast banner + a static ToastBanner.show helper.
- TooltipBubble
- Small candy-styled speech-bubble container for coach-mark/hint use cases.
- TrustedClockService
-
A rewind-proof clock that RECOVERS from a suspicious forward jump
instead of permanently locking onto it (IDEA-40) — the failure mode
utils/clamped_clock.dart's plain watermark clamp has: once a forward jump (deliberate or an honest clock misconfiguration) bumps the watermark to some far-future instant, every time-gated system it backs stays locked until the REAL wall clock naturally catches up to that instant — which, for a big jump, can be months or years. - TrustedTimeSource
- Optional seam for a caller-supplied trusted time source (e.g. an NTP round-trip, or a server timestamp from any authenticated request the app already makes) — deliberately not implemented by this package (no network dependency baked in, same reasoning as every other seam here: AnalyticsProvider/CrashReporter/PurchaseSeam).
- TutorialSequence
- Orchestrates a multi-step onboarding tutorial by showing one SpotlightOverlay at a time for whatever step controller is currently on — composes SpotlightOverlay rather than reimplementing its highlight/callout logic; this widget is purely the step-advancing state machine around it.
- TutorialSequenceController
-
Plain
ChangeNotifierthe caller creates and owns (like aTextEditingController, same pattern as ScreenShakeController inscreen_shake.dart) — drives which step of a TutorialSequence is showing, if any. - TutorialStep
- One step of a TutorialSequence — same fields as SpotlightOverlay (which this composes, not reimplements), minus SpotlightOverlay.onDismiss (the sequence supplies that itself, wired to advance to the next step).
- UpgradeCost
- One caller-formatted upgrade cost row.
- UpgradePreviewPanel
- Presentation-only upgrade preview comparing supplied stats/costs.
- UpgradeStatChange
- One caller-formatted before/after stat preview.
-
VersionedJsonStore<
T> - A thin, versioned JSON object store on top of StorageService's plain key-value strings — for save data with actual shape (player profile, level progress) that needs to survive a schema change between game versions without losing old players' data.
-
VersionedSyncConflict<
T> - Both sides of a genuine VersionedJsonStore.syncWith conflict — local and cloud both have DIFFERENT data (see VersionedJsonStore.syncWith's own doc for exactly when this is raised), so picking a winner by timestamp alone risks silently discarding real progress from whichever device loses.
-
VersionedSyncConflictResolution<
T> -
What an
onConflicthandler decided to do about a VersionedSyncConflict — built via one of the 3 named constructors, never directly. -
VersionedSyncConflictSide<
T> -
One side (local or cloud) of a VersionedSyncConflict — the parsed value plus
the
syncedAtMstimestamp it was saved under. - VictoryCardTemplate
-
Pre-built "victory card" a game can drop straight in for a level-complete
/ result screen, then screenshot + share via the existing pipeline in
share_helper.dart. This widget only renders — it has no idea a share pipeline exists. - VipPerk
- Single loyalty/VIP benefit (presentation-only).
- VipPerkProgressRow
- Presentation-only card/row displaying current VIP tier, point progress toward the next tier, and unlocked perks (FEAT-145).
- VulnerabilityAdvisory
- One vulnerability advisory — supplied by the CALLER (see this file's doc comment), never produced by this file itself.
- WakeLockService
-
Keeps the screen from auto-locking while enabled — wraps
wakelock_pluswith a persisted on/off preference (StorageKeys.wakeLockEnabled), the same shape as AudioManager'smutedflag, so a consuming app can expose its own settings toggle instead of the kit unconditionally forcing the screen to stay on. - WatchdogEntry
-
One still-live tracked resource — owner is free text (typically a
runtimeType.toString()or a widget's debug label), not a live reference to the resource itself: this class never holds the actualTicker/AnimationController/etc, only metadata about it, so tracking something can never itself keep it alive or leak it further. - WatchdogRow
- WeeklyChallengeCard
- A weekly live-ops challenge card showing event progress and milestone rewards.
- WheelPointerClicker
- The fixed pointer of a WheelSpinner: flicks about its top anchor by angle (radians), which the wheel derives from its own rotation — this widget owns no timer or controller.
- WheelSegment
-
One slice of a WheelSpinner — caller-supplied, same convention as
LeaderboardEntry/VictoryCardTemplate.statLines: this widget never invents reward values or odds, it only renders and animates. - WheelSpinner
- A candy-styled "wheel of fortune" — draws its own pie-slice wheel via CustomPaint (no extra package dependency), spins to whatever index controller requests, and reports the landed WheelSegment via onSpinEnd. A fixed pointer marks the winning slice at the top; the wheel itself is the only thing that rotates.
- WheelSpinnerController
-
Plain
ChangeNotifierthe caller creates and owns (like aTextEditingController, same pattern asScreenShakeControllerinscreen_shake.dart) — triggers a spin on the WheelSpinner it's attached to. - WheelSpinnerPainter
-
Public (rather than the usual underscore-private painter convention in
this file's siblings) so a widget test can pull
.segmentsback off the mounted CustomPaint — same testability reason asSpotlightOverlay'sSpotlightHolePainter. - WinStreakFlameHud
- Win streak HUD with escalating flame tiers and caller-owned reward multiplier (FEAT-137).
- WorkloadPerformanceBudget
- Evaluates integration test frame workload reports against configurable budgets (ENH-102).
- XpLevelHeader
- Compact player level badge with an XP bar toward the next level. Presentation-only: the caller computes XP, persists it and detects level-ups.
Enums
- AdvisorySeverity
- AnalyticsDropReason
-
Why one
logEventcall never reached the real AnalyticsProvider. - AnalyticsQueueDropReason
- AssetKind
- Which loader path an item needs — the coordinator itself never touches Flame/audio/Flutter asset APIs directly; a consumer's injected AssetLoaderFn dispatches on this.
- AssetLicenseIssueKind
- AsyncButtonStatus
- AsyncCommonButton's current phase.
- AuditRuleId
- AuditSeverity
- BattlePassMilestoneStatus
- BattlePassTrack
- BudgetDirection
- Whether a budget's BudgetPolicy.limit is a ceiling or a floor.
- ChallengePeriod
-
How often SeededChallengeService.currentSeed's
periodKeyrolls over —dailyties to todayEpochDayClamped,weeklyto that same day number floor-divided by 7 (same ISO-ish "group of 7 epoch days" conventionDailyQuestService/SeasonEventService's own period keys already use elsewhere in this package). - CharacterCollectionFilter
- ChestTier
- Upgrade ladder for TieredRewardChest (FEAT-124).
- ClockJudgement
- How a new ClockSample compares to the previously recorded one.
- CloudSaveStatus
- CollectionAlbumFilter
- CommonButtonVariant
- Button style: 3 labeled pill variants + 1 icon-only round variant.
- ConfettiShape
- Confetti piece shape — mixed randomly so a burst isn't visually uniform.
- ConflictPolicy
- What to do when OfflineOutboxService uploads an item and the remote authority reports its state has diverged from what was queued locally.
- ConnectivityCardState
- ConnectivityState
- ConsentCategory
- A privacy-relevant capability gated by consent. Deliberately does not include "ads" — this kit ships no ads mediation seam by product decision (see FEAT-02's rejection), so there is nothing here to gate for that category.
- ConsentSource
- ConsentStatus
- ContentPackStatus
- ContrastCheckKind
- What a ContrastCheck/ContrastIssue is checking — each kind has its own natural threshold (WCAG normal text is stricter than a UI component's border, which is stricter than "disabled state must at least not be the exact same color as its background").
- CooldownStatus
- DeepLinkOutcome
- DeepLinkResultStatus
- DependencySource
- DependencyType
- DeprecationStatus
- EconomyCertificateCardStatus
- EconomyCertificateStatus
- Result of EconomyCertificate.verify — a single typed status a backend or another device can branch on, instead of re-deriving "is this really trustworthy" from raw HMAC/clock plumbing itself.
- EventCalendarStatus
- Lifecycle state supplied by the caller; the widget does not derive dates or convert timezones.
- EventParamType
- FrameTimingClass
- FriendRequestAction
- GameAccessibilityCategory
- Broad bucket a GameAccessibilityEvent falls into — used only to rate- limit/coalesce a burst (several level-ups from one big XP grant, several reward lines from one combined claim) so a screen reader isn't spammed with overlapping announcements. Not tied to any specific kit service — GameAccessibilityCategory.custom covers anything a consumer app wants to announce that isn't one of the 3 common casual-game moments.
- GameJoystickDirection
- Eight-way direction emitted by GameJoystick.
- GamePauseReason
- GameSessionPhase
- GateDecision
- What an app should show for the current version/maintenance state. Ordered by severity: maintenance and forceUpdate block play, softUpdate is dismissible, ok shows nothing.
- GiftLivesRequestState
- GuardrailRowState
- HapticLevel
-
Haptic feedback — every call site in the app using
HapticFeedback.*must go through here to respect theStorageKeys.hapticsEnabledflag (disabled from Settings). - HoldToConfirmShape
-
Visual style of the fill-progress indicator while HoldToConfirmButton
is being held.
radialdraws a ring around a circular icon button (the classic "hold to delete" shape);linearfills a pill from the left, like CommonButton's shape. - HudBreakpoint
- Coarse layout mode AdaptiveGameHud switches between — compact hides HudSlot.side (no room for it), expanded shows every slot. Driven by width alone (see AdaptiveGameHud.compactBreakpointWidth) rather than orientation, since an orientation change on the same device already changes width — a separate orientation check would just be a second source of truth for the same decision.
- HudSlot
- Named regions AdaptiveGameHud arranges HUD content into (FEAT-52).
- ItemRarity
- JuicyPreset
- KillSwitchSource
- Where a KillSwitchState decision actually came from — surfaced so a debug overlay/health report can tell "ops explicitly killed this" apart from "we couldn't reach a fresh answer and fell back".
- LeaderboardTier
- Competitive league for a TieredLeaderboardRow (FEAT-139).
- LevelState
- Progress state of a single level node in a LevelSelectGrid — the grid holds no progress logic of its own, this is what the caller's own save/progress system hands in per level.
- LevelUpPhase
- Lifecycle of one queued level-up celebration: idle (no overlay) → xpFill (bar animates to full) → levelPop (level number bounces in) → rewardReveal (reward lines fade in) → back to idle once the whole queue is done, or xpFill again for the next queued level.
- LicenseCategory
-
A
LICENSEfile's text, reduced to one of 3 buckets — deliberately coarse (not "is this exact SPDX id compatible with our own license"): this is a policy GATE flagging "needs a human to look," not a legal compatibility engine. - ManualResolution
- What a caller decided for an item sitting in OfflineOutboxService.manualReviewItems.
- MeasurementSource
- Where a PerformanceBudgetMetric's value actually came from.
- MoveHintType
- Categories for caller-supplied puzzle-move hints (FEAT-138).
- MysteryChestPhase
- NotificationPermissionPrimerChoice
- Which branch showNotificationPermissionPrimer resolved to.
- OutboxConflictResolution
- OutboxQueueStatus
- PerformanceBudgetViolationKind
- PerformanceTier
-
Coarse runtime performance bucket a decorative shader/ticker layer
(
AuroraBgLayer,NeonAuraLayer— seeShaderTickerLayerState) checks to decide whether to keep animating. - PlatformKind
-
This kit's classification of the running platform — coarser than
TargetPlatform (folds "on the web" in as its own kind regardless of
the underlying OS, since web capability differs from native regardless
of
TargetPlatform). - QuestPeriod
- How often a quest's progress/claim state resets.
- RemoteConfigHealthSource
- RemoteConfigSource
- Where RemoteConfigService's current config actually came from — exposed alongside RemoteConfigService.snapshot so a caller/test can tell "still asset-only" apart from "remote merged in" without having to diff key values (ENH-58).
- RemoteSchemaFieldType
- ReplayRngCheckStatus
- ReplayVerificationStatus
- RetryOutcome
-
Why a single attempt/the whole RetryExecutor.run call ended the way it
did — passed to
onAttemptfor observability (logging, a debug overlay, ...). - RewardAuditStatus
- RewardedAdStatus
- RewardPlanPreviewStatus
- RewardSequenceStep
- RewardSource
- Where a RewardTransactionRecord originated — purely descriptive, used for the audit trail/reconciliation, not for any behavior branch inside RewardTransactionPipeline itself.
- RewardTrackClaimState
- RewardTrackLane
- RewardTransactionStatus
-
RewardTransactionRecord.status lifecycle:
pending(reserved, no line applied yet) →partial(some lines applied, one failed — resumable, never rolled back) →committed(all lines applied). There is no terminal "failed" state: a request that fails validation is rejected before a record is ever created, so every persisted record is always resumable via RewardTransactionPipeline.resumePending. - RoyCasualKitModule
- Optional modules that RoyCasualKit.initialize can register.
- RoyCasualKitStatus
- RoyLifecycleEvent
- RoyLifecycleState
- SaveConflictChoice
- SaveHealthResult
- Outcome of SaveHealthCard's most recent self-check.
- SbomIssueKind
- ScenePreloadStatus
- SceneTransitionPhase
- Lifecycle of one scene transition: idle (no overlay, old/new scene interactive) → covering (fading a barrier in over the old scene) → loading (barrier up, showing progress) → revealing (fading the barrier back out over the new scene) → back to idle; or error instead of revealing if the load failed.
- SceneWipeShape
- SdkErrorKind
- SmartReviewFunnelChoice
- Which branch showSmartReviewFunnel resolved to.
- SpringMotionPreset
- SwipeSide
- SyncStatus
- TapHintGesture
- Gesture a TapHintPointer demonstrates (FEAT-131).
- TeamRole
- Role of a team or clan member.
- TierZone
- Competition zone based on weekly league rank — caller computes it (FEAT-139).
- TooltipPointerDirection
-
Which edge of the bubble the triangular pointer nub sits on — i.e. which
side points at the thing being called out.
up= nub on the top edge (bubble sits below its target),down= nub on the bottom edge (bubble sits above its target). - UnknownFieldPolicy
- What to do with a param key an EventSchema doesn't declare.
- VersionedSyncConflictStrategy
- Which side VersionedSyncConflictResolution picked.
- WatchdogKind
-
What kind of disposable resource a WatchdogEntry tracks — the 5
categories this task's own user story names (ticker/controller/
overlay/subscription/Flame component);
customcovers anything else a consumer app wants to track through the same mechanism.
Mixins
- PooledComponent
-
Mixin for a Flame
Componentthat automatically returns itself to whatever pool acquired it once Flame removes it from the component tree (FEAT-48) — pairsObjectPool(core/utils/object_pool.dart) with Flame's own removal lifecycle so a caller never has to remember to callpool.release(this)manually alongsideremoveFromParent().
Extensions
Constants
- assetLicenseManifestSchemaVersion → const int
-
Current on-disk schema version for
asset/LICENSES.json— bump this (and add a migration in whatever reads an older one) on a breaking shape change. - checksumKey → const String
-
HMAC checksum layer sitting on top of StorageService's
exportAll()/importAll()— sign a save file on export, verify it on import, so a consuming game can detect a save that was hand-edited (e.g. someone bumped their coin count with an external tool). -
defaultDisallowedLicenses
→ const Set<
String> - Default license-string denylist — free-text placeholders/none-of-the- above values a manifest entry should never actually carry into a publish. An SPDX id not on this list is NOT thereby assumed safe to distribute — this is a denylist (catches known-bad), not an allowlist (an unrecognized but genuinely permissive license, e.g. a public- domain audio track's own custom wording, still passes through).
- isE2eTest → const bool
- Build-time switches used only to make device automation deterministic.
- kAppName → const String
- App info (shown on Home / About).
- kCopyright → const String
- kDailyLoginCycleLength → const int
-
Length of the repeating daily-login-streak cycle: day 1..7, then wraps
back to day 1 (see
doc/task/todo/FEAT-07-daily-login-streak-calendar.md). - kEnergyReminderNotificationId → const int
-
ReminderService.scheduleNext/ReminderService.cancel
idfor the energy-full reminder scheduled by rescheduleEnergyReminder — distinct from ReminderService's own defaultid: 0slot and from kStreakReminderNotificationId, so all 3 coexist as independent notifications. - kStreakReminderNotificationId → const int
-
ReminderService.scheduleNext/ReminderService.cancel
idfor the streak-expiring reminder scheduled by rescheduleStreakReminder.
Properties
- clockRewindBlockedCount ↔ int
-
A "never goes backward" clock — a monotonic day/ms clock shared by every
time-based reward system (daily reward, streaks, season...). It's a
standalone helper here, rather than logic scattered across each place
that needs it, so every date-based reward system goes through the same
protection layer.
getter/setter pair
- debugTimeOffsetMs → int
-
The debug-only offset currently added to the real wall clock by every
nowMsClamped/todayEpochDayClamped read — always
0unless setDebugTimeOffsetMs was called. Exposed read-only for a debug/QA panel to show the current "time travel" state.no setter -
defaultAuditRules
→ List<
AuditRule> -
The 3 rules this audit actually runs — see this file's doc comment for
why there are only 3, not 6.
final
- kAppBuildNumber ↔ String
-
getter/setter pair
- kAppVersion ↔ String
-
Displayed version + build number — read AUTOMATICALLY from pubspec at
startup (see
loadAppVersioninmain.dart), so it never drifts frompubspec.yaml. The default value is only a fallback for when package_info hasn't loaded yet (e.g. widget tests).getter/setter pair - kPackageName ↔ String
-
Package/bundle id — read AUTOMATICALLY from
loadAppVersionjust like kAppVersion, used for store links (rate/share) instead of a hardcoded string.getter/setter pair
Functions
-
asBoolOr(
Object? v, bool fallback) → bool -
Reads
vas abool. -
asDoubleOr(
Object? v, double fallback) → double -
Reads
vas adouble, accepting a JSON integer for it too (see asIntOr for whydart:convertcan hand back either). -
asIntOr(
Object? v, int fallback) → int -
Reads
vas anint.dart:convertdecodes a whole-number JSON value asintbut a value with.0may come back asdouble(or vice versa depending on the source) — both are accepted here. -
asStringOr(
Object? v, String fallback) → String -
Reads
vas aString(empty string is a valid value, not a miss). -
auditDependencies(
{required List< DependencyEntry> entries, required Map<String, LicenseCategory> licenseByPackage, required int nowMs, List<VulnerabilityAdvisory> advisories = const [], List<SbomSuppression> suppressions = const [], Set<String> unpinnedPackages = const {}}) → List<SbomIssue> -
Cross-checks
entriesagainst license classifications, an optionaladvisorieslist, andpinnedOnlypolicy, returning every issue not covered by an unexpired SbomSuppression. -
battlePassMilestoneStatuses(
{required BattlePassMilestone milestone, required int progress, required bool vipEnabled, required Set< String> claimedFreeIds, required Set<String> claimedVipIds}) → List<BattlePassMilestoneStatusView> -
buildMigrationRegistry(
RemoteSchemaDef schema, {required Map< int, Map< stepMigrations}) → SaveMigrationRegistryString, Object?> Function(Map<String, Object?> input)> -
Wires
schema's version history into a SaveMigrationRegistry — onestepMigrationsentry per consecutive(fromVersion, toVersion)hop is required (this compiler cannot safely synthesize field-transform logic from a declarative schema alone). Throws RemoteSchemaCompilerException if a hop's migrate function is missing; SaveMigrationRegistry's own constructor still re-validates the resulting chain. -
captureBoardPng(
GlobalKey< State< boundaryKey, {double pixelRatio = 2.0, String? overlayText}) → Future<StatefulWidget> >Uint8List?> -
Captures
boundaryKey(must be aRepaintBoundary) as a PNG, overlayingoverlayText(if any) on a translucent bar at the bottom of the image — so the image carries its own level/score/date info even if the recipient only views/saves the picture, independent of the share caption. Returns null if the widget hasn't built yet (context is null). Kept separate from shareBoardImage so it's testable without touching share_plus's platform channel. -
cardFlipTransform(
{required double angle, double perspective = 0.0015, Axis axis = Axis.horizontal}) → Matrix4 - Calculates the 3D perspective transform matrix for card flipping.
-
checkPerformanceBudgets(
{required List< PerformanceBudgetMetric> measurements, required List<BudgetPolicy> policies, List<PerformanceBudgetMetric> baseline = const [], int? nowMs}) → PerformanceBudgetResult -
Checks
measurementsagainstpolicies. Each policy fails on at most one PerformanceBudgetViolation (checked in the order: missing, wrong source, stale, over budget, regression) — stops at the first that applies rather than piling up redundant complaints about one metric. -
classifyClockSample(
{required ClockSample previous, required ClockSample current, Duration normalTolerance = const Duration(seconds: 5), Duration suspiciousJumpThreshold = const Duration(hours: 1)}) → ClockJudgement -
Pure classifier — no storage, no singletons — comparing
currentagainst thepreviousrecorded sample. Exposed directly (not just through TrustedClockService) so a test can drive the full normal/rewind/jump/reboot matrix without touching StorageService. -
classifyFrameDuration(
Duration duration) → FrameTimingClass -
classifyLicenseText(
String? licenseFileContent) → LicenseCategory -
Classifies a
LICENSEfile's raw text by matching well-known license header text — case-sensitive on purpose (a license file's own actual wording is what a legal reviewer would look at too, a lowercase substring match risks matching unrelated prose). -
coinArcOffsetAt(
Offset from, Offset to, double t, {required double arcHeight}) → Offset -
Position along a quadratic Bézier arc from
fromtotoat progresst(0..1) — IDEA-22, replaces a straight-lineOffset.lerpso a coin visibly arcs up then down instead of sliding on a dead-straight line. The control point sits above the midpoint byarcHeightpixels. Pure function (no widget involved) so the curve shape is unit-testable on its own. -
coinScaleAt(
double t) → double -
Scale at progress
t(0..1): pops up to 1.2x over the first half of the flight, then eases down to a 0.9x "squash" by the time it lands — IDEA-22, replaces a constant 1.0 scale for the whole flight. -
comboSyncHapticPattern(
{required int steps, required Duration stepInterval, HapticLevel levelForStep(int step)?}) → HapticPattern -
Builds a HapticPattern synced to a combo/SFX sequence whose timing is
already known ahead of time (IDEA-67) — e.g. a pitch-escalating combo
SFX that steps every
stepInterval. No real-time audio analysis: this is a pure data-driven mapping from "N steps, M ms apart" straight onto HapticPattern's own pulse/delay shape, played via HapticChoreographer.play exactly like any other pattern — the caller is responsible for actually starting the SFX at the same moment. -
comboTierColor(
int multiplier) → Color -
Returns the theme color for a combo
multiplierlevel (FEAT-128). -
compareAppVersions(
String a, String b) → int? -
Compares
atobas semver strings, per this policy: -
confettiOffsetAt(
ConfettiParticle particle, double t) → Offset -
Offset from its spawn point at
tseconds since the burst started: falls straight down at ConfettiParticle.fallSpeed while swaying side-to-side on a sine wave. Pure function of(particle, t)— no widget/render state involved, so it's unit-testable on its own. -
confettiOpacityAt(
double t, double totalSeconds) → double -
Opacity at
tseconds into atotalSecondseffect: fully opaque until 70% elapsed, then fades linearly to 0 so the burst doesn't cut off abruptly.totalSeconds <= 0is treated as already-finished (0). -
confettiRotationAt(
ConfettiParticle particle, double t) → double -
Rotation (radians) at
tseconds since the burst started. -
contrastRatio(
Color a, Color b) → double - WCAG contrast ratio between 2 colors, always >= 1.0 regardless of argument order (https://www.w3.org/TR/WCAG21/#dfn-contrast-ratio).
-
currentBattlePassMilestoneIndex(
List< BattlePassMilestone> milestones, int progress) → int -
defaultHealthCollectors(
) → List< HealthCollectorSpec> -
This package's own built-in collectors — one per module named in
FEAT-39's sprint slice (app version, FPS/performance tier, audio,
config source, replay buffer). Each reports
registered: false(never an error) when its module isn'tGet.putin this app, since "not wired up" isn't a health PROBLEM this report should flag. -
detectPlatformCapabilities(
{bool? isWeb, TargetPlatform? targetPlatform}) → PlatformCapabilitySnapshot -
Pure detection — no platform channel, no plugin, just the 2 primitives
Flutter itself already resolves at process start
(
kIsWeb/defaultTargetPlatform).isWeb/targetPlatformare injectable so a device-matrix test can fixture every combination without needing a real device per platform. Never throws. -
dlog(
String msg) → void - Debug log prefixed 'roy93~' — prints ONLY in debug builds, no-op (tree-shaken away) in release. Funnels every on-device debug trace through one place, without cluttering release logs.
-
durationToLocalMidnight(
DateTime now, int daysLeft) → Duration -
Time remaining until DEVICE-LOCAL midnight
daysLeftdays from today. -
energyFullReminderDelay(
EnergyService energy) → Duration? -
How long until
energy's bar is completely full (nullif it already is, or EnergyService.hasInfiniteLives is active — no reminder is useful in either case). Pure function ofenergy's own already-tested getters (EnergyService.currentEnergy/EnergyService.timeUntilNextEnergy), not a new regen formula — EnergyService.timeUntilNextEnergy alone only answers "until the NEXT point", so this adds the remaining whole ticks after that on top. -
evaluateVersionGate(
{required String currentVersion, required AppVersionGateConfig config}) → GateDecision - Pure decision function — no I/O, no singletons, easy to fixture-test.
-
eventSchemaAuditHealthCollector(
SdkEventSchemaRegistry registry) → HealthCollectorSpec -
Opt-in
SdkHealthReport(FEAT-39) section reporting recent event validation activity — a consumer registers this itself, same reasoningmemoryWatchdogHealthCollector(FEAT-74) isn't part ofdefaultHealthCollectors(): it needs a specificregistryinstance, not a module a consumer either has or hasn't registered. -
findFirstDivergence(
List< Object?> expected, List<Object?> actual) → ReplayDivergence? - Compares 2 ordered outcome lists (e.g. a recorded session's outcomes vs a fresh replay's outcomes) and returns the FIRST point they differ — including a length mismatch, treated as the shorter list "missing" the longer one's extra entries starting there.
-
fireHaptic(
HapticLevel level) → void -
fitFontSizeForLongestWord(
String label, double maxWidth, {List< double> candidates = const [11, 10, 9, 8], FontWeight fontWeight = FontWeight.w700, String? fontFamily = 'packages/roy_casual_kit/Baloo2', double measureWord(String word, double fontSize)?}) → double -
The largest font size in
candidatesfor which every word oflabelstill fits withinmaxWidth. -
floatingEmojiOffsetAt(
FloatingEmojiParticle particle, Size bounds, double elapsedSeconds, {double riseDistance = 260}) → Offset -
floatingEmojiOpacityAt(
FloatingEmojiParticle particle, double elapsedSeconds) → double -
fmtDur(
Duration d) → String - Formats a Duration as "mm:ss" (minutes:seconds, each part 2 digits). Used for the reconnect countdown on Home / Level Select / World Map.
-
fmtDurDays(
Duration d) → String - Formats Duration as "Xd Yh" when 24 hours or longer (e.g. "3d 4h"), or delegates to fmtDurLong when under 24 hours (FEAT-130).
-
fmtDurLong(
Duration d) → String - Formats Duration as "mm:ss" when under an hour (same as fmtDur), or "hh:mm:ss" once it reaches an hour — for longer timers (energy/lives refill, boss events) where fmtDur would wrap and understate the time left. fmtDur itself is untouched (kept for its existing short-timer contract); use this one for anything that can run past 60 minutes.
-
fmtNum(
int n) → String -
Formats a large integer (coins, score, price, boss HP…) with a THOUSANDS
SEPARATOR matching the CURRENT LANGUAGE: vi → "10.000", en → "10,000",
de → "10.000"… Uses
NumberFormat(intl) keyed onGet.locale; if the locale is unknown/has no data, falls back to manual grouping with '.' (Vietnamese-style) so it NEVER throws. -
fmtNumCompact(
num n) → String -
Abbreviates large numbers (idle/tycoon-scale coin balances) as
1.5K/2.4M/10.8B/1T, one decimal place, trailing.0dropped. Below 1000 falls back to fmtNum (locale-aware thousands separator). -
fnv1aHash(
String input) → int -
FNV-1a, 32-bit — a small, dependency-free string hash. Deterministic by
construction (no reliance on Dart's
String.hashCode, which is explicitly NOT guaranteed stable across Dart versions/runs) — any code that needs a hash to stay the same across app rebuilds/SDK upgrades (an experiment bucket assignment, a namespaced RNG seed, ...) must use this instead. -
generateConfettiParticles(
int count, List< Color> colors, {Random? random}) → List<ConfettiParticle> -
Generates
countparticles with randomized traits drawn fromcolors. Pure aside fromrandom(pass a seededRandomfor deterministic tests) — kept separate from the widget so "did we spawn the right number of particles, with colors from the given palette" is a plain unit test. -
generateModelSource(
RemoteSchemaDef schema) → String -
Generates a self-contained (zero-import) immutable Dart model class for
schema's RemoteSchemaDef.current version — value-equal (==/hashCode),fromJson/toJson, never-throwing field readers (a wrong-typed field falls back to a type-appropriate default, same tolerant-parsing contractlib/core/utils/safe_json.dartfollows, re-implemented inline here instead of imported so the output has no dependency on this package at all). -
goldenShimmerOffsetAt(
double progress) → double -
hapticLevelForGroupSize(
int size) → HapticLevel - Maps a just-popped group's size to a haptic level (pure, testable) — use this once real group/pop matching rules exist.
-
hapticLevelForJuicyPreset(
JuicyPreset preset) → HapticLevel -
inventoryGridCellDelta(
{required int oldIndex, required int newIndex, required int crossAxisCount, required double cellSize, required double spacing}) → Offset -
Calculates the layout translation delta between
oldIndexandnewIndex. -
inventoryGridCellOffset(
{required int index, required int crossAxisCount, required double cellSize, required double spacing}) → Offset - Calculates the top-left offset of a grid cell relative to the grid origin.
-
isCardFrontVisible(
double angle) → bool - Returns true when the front face of a 3D flip card is oriented toward the camera.
-
itemArcOffsetAt(
Offset from, Offset to, double t, {Offset curveOffset = const Offset(0, -60)}) → Offset -
itemScaleAt(
double t) → double -
levelForTotalXp(
List< LevelDefinition> curve, int totalXp) → int -
Level reached at
totalXpagainstcurve(already validated, sorted by level ascending). Caps at the curve's last (max) level regardless of how fartotalXpexceeds it. -
levelPathNodeCenter(
int index, double width, {double rowHeight = 96, double amplitude = 0.62}) → Offset -
Pure math helper: computes center position of node
indexalong an S-curve saga path (FEAT-133). -
levelStateBorderColor(
LevelState state) → Color -
Node border color for
state. -
levelStateFillColor(
LevelState state) → Color -
Node fill color for
state— dim gray for locked, card white for unlocked, gold for completed. -
levelStateIcon(
LevelState state) → IconData? -
Icon shown over a LevelNodeButton for
state— onlylockedgets one (a lock glyph instead of the level number);unlocked/completedjust show the number, distinguished from each other by fill/border color. -
levelStateTappable(
LevelState state) → bool -
Whether a node in
statecan be tapped at all. -
maybeRequestReview(
{required int recentWinStreak, required Future< void> showReview(), int minWinStreak = 3, bool everDeclined = false, Duration cooldown = const Duration(days: 30)}) → Future<bool> - Decision logic for "should we ask for a store review right now" — the classic casual-game pattern of prompting right after a happy moment (e.g. a win streak), without asking too often.
-
memoryWatchdogHealthCollector(
) → HealthCollectorSpec -
Opt-in
SdkHealthReport(FEAT-39) section reporting the current orphan count/kinds — a consumer app registers this itself (report ..register(memoryWatchdogHealthCollector())), it's not part ofdefaultHealthCollectors()since, unlike audio/performance/ remoteConfig, this isn't a runtime module a consumer "has registered or not" — it's always available, opt-in by nature of being a debug diagnostic. -
milestoneProgressRatio(
{required int progress, required int previousThreshold, required int nextThreshold}) → double -
multiplierIndexAtNormalizedProgress(
double progress, int count) → int -
Pure math helper: maps normalized progress
0.0..1.0across an arc to a sector index0..count-1(FEAT-132). -
multiplierNeedleAngleAtProgress(
double t, {double maxAngle = 0.38 * math.pi}) → double -
Pure math helper: computes the oscillating needle angle in radians for animation progress
tin0.0..1.0(FEAT-132). -
mysteryChestPhaseAt(
double progress) → MysteryChestPhase -
nowMsClamped(
[StorageService? storage]) → int - Current millisecond timestamp, clamped to never go below the largest value seen so far.
-
offlineEarnings(
{required int lastClaimedMs, required int nowMs, required int maxOfflineCapMs, required double productionRatePerSecond}) → double -
Same formula as
OfflineProgressionService._earningsAt(): earnings accrued betweenlastClaimedMsandnowMs, capped atmaxOfflineCapMselapsed, atproductionRatePerSecond. -
parseDeepLink(
Uri uri, List< DeepLinkRoute> routes, {int maxLength = 2048}) → SdkResult<DeepLinkCommand> -
Pure parser — no I/O, no singletons — matches
uriagainstroutesin order, first match wins. Rejects (never throws) on: a URI longer thanmaxLength(guards against an oversized query string), a scheme/host not in any route, or a path that doesn't match any route's shape. -
parsePubspecLock(
String content) → List< DependencyEntry> -
Parses a
pubspec.lockfile's content into every resolved package, sorted by name — this ordering is what makes the resulting SbomDocument reproducible: the same lock file always produces byte-identical JSON, regardless of the lock file's own key order or anyMapiteration order. -
piggyBankFillRatio(
{required int amount, required int capacity}) → double -
piggyBankIsFull(
{required int amount, required int capacity}) → bool -
pooledParticleOffsetAt(
{required Offset center, required double angle, required double travelDistance, required double progress}) → Offset -
pooledParticleOpacityAt(
double progress) → double -
prestigeMultiplier(
{required int relics, required double bonusPerRelic}) → double -
Same formula as
PrestigeService.currentMultiplier: the permanent earn-rate multiplier a player's accumulated prestige meta-currency (relics) grants —1 + relics * bonusPerRelic, sorelics == 0(never prestiged) is exactly1(no change), and each relic owned adds a flatbonusPerRelicon top, forever (relics are never soft-reset by a prestige, only the low-tier currencies are). -
pseudoLocalize(
String value) → String -
Deterministically transforms
valueinto a "pseudo-localized" string: every vowel becomes its accented look-alike (see_accentMap's doc), the string is padded to roughly 40% longer (the commonly-cited average real-world translation expansion factor — stress-tests overflow before a real translator ever touches the key), and the whole thing is wrapped in[[...]]so a truncated render (a missing closing]]) is visually obvious too. -
radialActionOffsetForIndex(
{required int index, required int itemCount, required double radius, required double startAngleDegrees, required double sweepAngleDegrees}) → Offset -
regenEnergy(
{required int count, required int maxEnergy, required int lastMs, required int nowMs, required int intervalMs}) → EnergyRegenResult -
Same formula as
EnergyService._regen(): credits wholeintervalMsticks earned betweenlastMsandnowMs, capped atmaxEnergy. A no-op (returnscount/lastMsunchanged) when already full or when no whole tick has elapsed yet. -
relativeLuminance(
Color color) → double - WCAG relative luminance (https://www.w3.org/TR/WCAG21/#dfn-relative-luminance).
-
replayCapsule(
ReplayCapsule capsule, Object? handler(ReplayEvent event, SeededRandomService rng), {SeededRandomService? rng}) → ReplayDivergence? -
Replays
capsule's events throughhandler— invoked once per event with a fresh SeededRandomService seeded from the capsule (so the SAME namespace-fork behaviour a live session got, FEAT-45, is exactly what a replay gets too) — and reports the first point the produced outcomes diverge from what was originally recorded, ornullif the replay reproduced the session exactly. -
rescheduleEnergyReminder(
{required EnergyService energy, required ReminderService reminder, String title = 'Năng lượng đã đầy!', String body = 'Quay lại chơi ngay để không lãng phí năng lượng.'}) → Future< void> -
Re-derives the energy-full reminder from
energy's CURRENT state and (re)schedules it viareminderat kEnergyReminderNotificationId — or cancels that slot if no reminder is currently useful (already full, or infinite lives active). Call this again any time energy state changes (afterconsumeEnergy, aftergrantInfiniteLives, on app resume) so a stale schedule never outlives the state it was computed from (IDEA-62's AC3) — this coordinator has no way to observe those changes on its own, by design (no new cross-service event bus for something a caller can just call directly at the right hooks). -
rescheduleStreakReminder(
{required DailyLoginService dailyLogin, required ReminderService reminder, Duration warnBefore = const Duration(hours: 4), String title = 'Đừng để mất streak!', String body = 'Streak điểm danh của bạn sắp hết hạn hôm nay.'}) → Future< void> -
Re-derives the streak-expiring reminder from
dailyLogin's CURRENT state and (re)schedules it viareminderat kStreakReminderNotificationId — or cancels that slot if today's reward is already claimed. Call this again any time login-streak state changes (afterclaimToday, on app resume) for the same reason rescheduleEnergyReminder's own doc explains. -
rewardTrackClaimState(
{required RewardTrackTier tier, required int currentXp, required Set< String> claimedFreeIds, required Set<String> claimedPremiumIds, required RewardTrackLane lane}) → RewardTrackClaimState -
scanAccessibility(
{required Map< String, String> fileContents, List<AuditRule> rules = const [], AuditBaseline baseline = AuditBaseline.empty}) → List<AuditViolation> -
Scans
fileContents(path → source text) againstrules, dropping anythingbaselinesuppresses. A file present infileContentswith no violations contributes nothing — this function never reports "clean" files, only actual findings. -
sceneWipeMaxRadius(
Size size, Offset center) → double -
Farthest screen-corner distance from
center, enough to cover full viewport. -
sceneWipePath(
{required Size size, required Offset center, required double progress, required SceneWipeShape shape}) → Path -
scratchThresholdReached(
double ratio, {double threshold = 0.6}) → bool -
setDebugTimeOffsetMs(
int offsetMs) → void -
Sets the debug-only offset nowMsClamped/todayEpochDayClamped add to
the real wall clock before every read — FEAT-93's DebugQaOverlay "Time
Travel" tab, letting a QA tester see a time-gated system (Daily Login/
Quest/Energy/Season Event) react to +2h/+24h/+7d without touching the
OS clock (which routinely causes unwanted side effects elsewhere on the
device). A no-op outside
kDebugMode/kProfileMode— same posture as dlog (debug_log.dart) — so nothing outside an already debug-gated UI can ever move this, and it's always exactly0in a release build. -
Captures the board then opens the share sheet with
text. No-op if the capture fails. - Opens the share sheet with an already-captured journey card PNG.
-
Captures a result widget (built temporarily in a hidden overlay right
before calling this) then opens the share sheet with
levelText— same pattern as shareBoardImage but with a separate file/caption because this is a result card, not a board screenshot. Wire this toVictoryCardTemplate(presentation/widgets/common/victory_card_template.dart) — wrap it in aRepaintBoundary(key: ...)and pass that key here. - One shared share pipeline used by every call site in the app — text-only (e.g. inviting friends) or with a captured screenshot (e.g. a level result). Don't create a separate share function/plugin call elsewhere.
-
showCommonBottomSheet<
T> (BuildContext context, {required Widget child, Color? color, bool isDismissible = true, bool enableDrag = true, Color? barrierColor}) → Future< T?> -
Presents
childwrapped in a BottomSheetPanel via Flutter's nativeshowModalBottomSheet. -
showConfirmDialog(
BuildContext context, {required String title, String? message, String? confirmLabel, String? cancelLabel, Color? color, IconData? icon}) → Future< bool> -
Thin convenience wrapper over NeonDialog.show for the common
"are you sure?" confirm/cancel case. Delegates all rendering to
NeonDialog.show (which already handles the Flame-
GameWidget-safe routing per this repo's Dialog pattern) — this just supplies the two actions and resolves totrue/falsebased on which one was tapped. -
showNotificationPermissionPrimer(
BuildContext context, {required Future< void> onAccept(), Future<void> onDecline()?, String title = 'Bật thông báo để không bỏ lỡ phần thưởng?', String? message, String acceptLabel = 'Bật thông báo', String declineLabel = 'Để sau'}) → Future<NotificationPermissionPrimerChoice> -
(IDEA-68) A soft "ask before you ask" primer shown BEFORE
ReminderService's first
scheduleNext()/cancel()call triggers the real native OS notification-permission dialog — same "soft-ask first" pattern showSmartReviewFunnel (IDEA-61) already uses for store reviews. -
showSmartReviewFunnel(
BuildContext context, {required Future< void> showReview(), Future<void> onFeedback(String feedback)?, String title = 'Bạn có thích game không?', String likeLabel = 'Thích ❤️', String dislikeLabel = 'Chưa thích 💔', String feedbackTitle = 'Điều gì khiến bạn chưa hài lòng?', String feedbackHint = 'Góp ý của bạn (không bắt buộc)', String feedbackSubmitLabel = 'Gửi góp ý'}) → Future<SmartReviewFunnelChoice> - (IDEA-61) A 2-step "Bạn có thích game không?" micro-survey shown BEFORE opening the real store review — routes a dissatisfied player to an internal feedback step instead of straight to a public store review, where a 1-star rating would otherwise be likely.
-
signExport(
Map< String, Object?> data, String secret) → Map<String, Object?> -
Signs
data(the output ofStorageService.exportAll()) with an HMAC-SHA256 keyed bysecret, returning a new map equal todataplus one reserved checksumKey entry holding the hex-encoded digest. -
springDescriptionFor(
SpringMotionPreset preset) → SpringDescription -
staggerGridDelayForIndex(
{required int index, required int crossAxisCount, Duration stagger = const Duration(milliseconds: 40)}) → Duration -
starChestProgressFraction(
int current, int target) → double -
Pure math helper: computes the clamped progress fraction
0.0..1.0for star chest collection (FEAT-134). -
streakExpiringReminderDelay(
DailyLoginService dailyLogin, {Duration warnBefore = const Duration(hours: 4)}) → Duration -
How long until a reminder should fire warning the player their
dailyLoginstreak is about to lapse —nullif today's reward is already claimed (the streak is safe, no reminder needed). -
tapHintPointerOffsetAt(
{required TapHintGesture gesture, required double t, required Offset start, Offset? end, double bob = 8}) → Offset -
Pointer position along a tap/swipe hint at animation
t(0..1). -
throttled(
VoidCallback fn, {Duration window = const Duration(milliseconds: 600)}) → VoidCallback -
Wraps
fnso repeated calls withinwindowof the last one that ran are dropped — guards a button/action callback against rage-tap causing a double purchase, double navigation, double submit. Only blocks double-firing; a throw fromfnstill propagates (never swallowed). -
todayEpochDayClamped(
) → int - Days since epoch (UTC), clamped to never go below the largest value seen so far.
-
validateAssetLicenses(
{required List< String> assetPaths, required AssetLicenseManifest manifest, Set<String> disallowedLicenses = defaultDisallowedLicenses}) → List<AssetLicenseIssue> -
Cross-checks every path in
assetPaths(a directory walk of the asset/font/shader roots a game actually ships) againstmanifest, returning every mismatch found — an empty list means "clean, safe to publish" as far as asset licensing goes. -
validateLevelCurve(
List< LevelDefinition> levels) → SdkFailure<void> ? - Checks a level curve's structural invariants before it's ever used to grant XP — a broken curve is rejected loudly at construction time (PlayerProgressionService's constructor throws) rather than producing silently-wrong level math later.
-
validateNeonThemeContrast(
{ThemeContrastConfig config = const ThemeContrastConfig()}) → List< ContrastIssue> -
Validates the live NeonTheme across every state a consumer app can
actually put it in — light/dark (
NeonTheme.dark) crossed with the color-vision-deficiency-safe gem palette (NeonTheme.colorBlindSafe, seeIDEA-38) — without leaving it mutated: both flags are restored to whatever they were before this call, in afinally, even if a caller passes aconfigthat throws (it can't, but the guarantee holds either way). -
validateNeonThemeContrastPairs(
List< ContrastCheck> checks, {String state = 'default'}) → List<ContrastIssue> -
Runs a fixed list of
checks(each already carrying its own colors and threshold) and returns only the ones that failed, tagged withstatefor the report. Pure — no NeonTheme dependency; this is what a widget-fixture test or a caller with its own reskinned colors calls directly instead of validateNeonThemeContrast. -
verifyAndStrip(
Map< String, Object?> signed, String secret) → Map<String, Object?> -
Verifies a map produced by signExport and, if the checksum matches,
returns the original data with checksumKey removed — ready to pass
straight into
StorageService.importAll(). -
verifySignedFixture(
RemoteSchemaDef schema, Map< String, Object?> signedEnvelope, String secret) → SdkResult<Map< String, Object?> > -
Verifies a fetched/authored
signedEnvelopethe same way RemoteContentPack does at runtime: HMAC signature viasave_integrity.dart'sverifyAndStrip, then rejects aschemaVersionnewer thanschema's RemoteSchemaDef.current — a downgraded compiler run must never bake content shaped for a future schema into generated fixtures. Returns SdkFailure (never throws) on any problem so a CLI caller can report it and refuse to generate anything from it. -
weightedRandomPick<
T> (List< T> items, List<double> weights, {Random? random}) → T -
Picks 1 item from
itemswith probability proportional to the matching entry inweights— the shared loot-table/gacha-reward primitive so each new reward system (achievements, offline earnings, …) doesn't reimplement this. Pass a seededrandomin tests for determinism. -
wheelPointerBounceAngle(
{required double velocity, required double secondsSinceCrossing, required int segmentCount}) → double -
Pointer deflection (radians) shortly after a segment crossing: a damped
sine kick opposing the wheel's motion, scaled by angular
velocity(radians/second) and capped to a fraction of one segment so the pointer never swings past the neighbouring slice. -
wheelSegmentCrossingCount(
{required double previousRotation, required double currentRotation, required int segmentCount}) → int -
Number of segment boundaries a wheel passed between two unwrapped
rotations (radians). Boundaries sit every
2π / segmentCount; the previous rotation is exclusive and the current one inclusive, so a frame resting exactly on a boundary neither double-counts nor misses it. -
winStreakFlameColor(
int streakCount) → Color -
Returns the flame tint for the current win
streakCounttier (FEAT-137). -
worldToScreenOffset(
{required CameraComponent camera, required Vector2 worldPosition, required Offset gameWidgetTopLeft}) → Offset -
Converts a Flame world-space
worldPosition(e.g. a component'sposition) into an on-screen Flutter Offset, viacamera's ownlocalToGlobal(which already accounts for viewfinder pan/zoom and viewport scaling — seecamera_component.dartin theflamepackage). -
xpIntoLevelForTotalXp(
List< LevelDefinition> curve, int totalXp) → int -
XP progress within the current level at
totalXp— always0once the max level is reached.
Typedefs
-
AnalyticsBatchUploader
= Future<
void> Function(List<QueuedAnalyticsEvent> batch) -
AssetLoaderFn
= Future<
void> Function(AssetManifestItem item) - AssetUnloaderFn = void Function(AssetManifestItem item)
-
BatteryLevelProvider
= Future<
int?> Function() -
Battery level reading seam, 0–100, or
nullif unavailable/unknown right now (e.g. a platform channel hiccup, or a desktop target with no battery at all) — this package stays neutral of a concrete battery-reading plugin (same convention ascrash_reporter.dart/analytics_provider.dart/connectivity_coordinator.dart's ownReachabilityProbe): a consuming app injects() async => (await Battery().batteryLevel)(or whatever plugin it already uses) rather than this kit adding a new runtime dependency every consumer pays for, even ones that never want battery-based throttling. -
ConflictMerger
= Map<
String, Object?> Function(Map<String, Object?> local, Map<String, Object?> remote) - A ConflictPolicy.merge resolution: given the payload that was queued locally and the authority's current payload for the same key, return the payload to re-upload. Must be pure/deterministic — same inputs, same output — since a crash between the merge and the retry may run it again.
-
DeepLinkHandler
= FutureOr<
void> Function(DeepLinkCommand command) - InventoryItemBuilder = Widget Function(BuildContext context, InventorySlot slot, bool isSelected)
-
Renders one filled cell —
isSelectedreflects InventoryGrid.selectedSlotId so the caller decides how to highlight it (this widget holds no selection state of its own, see class doc). - InventoryPlaceholderBuilder = Widget Function(BuildContext context, int cellIndex)
-
Renders one non-item cell (empty or locked) at
cellIndex(0-based, stable across rebuilds as long as InventoryGrid.unlockedCapacity doesn't change). - LivesHeartHud = EnergyBar
- Semantic alias for EnergyBar matching the Lives/Heart HUD pattern (FEAT-126).
-
OutboxUploader
= Future<
SyncOutcome> Function(Map<String, Object?> payload, String idempotencyKey) -
Attempts to sync one item with whatever remote authority a consumer app
wires up (a REST endpoint, a cloud function, ...) — this service knows
nothing about the transport. Throwing (a network error, a timeout) is
treated as transient and retried per OfflineOutboxService.retryPolicy;
returning a SyncOutcome is the only way to report a definitive
accept/conflict.
idempotencyKeyis passed on every attempt (including retries after a crash) specifically so the remote side can dedupe a request it already applied. -
ReachabilityProbe
= Future<
bool> Function() - Actual reachability probe an app injects (e.g. a HEAD request to a known-good endpoint) — returns true only when the Internet is genuinely usable, not just "an interface exists".
- ReactiveLivesHeartHud = ReactiveEnergyBar
- Semantic alias for ReactiveEnergyBar matching the Lives/Heart HUD pattern (FEAT-126).
-
RoyLifecycleHook
= Future<
void> Function(RoyLifecycleEvent event) -
SceneTransitionLoad
= Future<
SdkResult< Function(void onProgress(double progress))void> > -
A transition's load step: does the real work (asset preload, screen
setup, ...) and reports progress via
onProgress(0.0–1.0) as it goes. -
VersionedSyncConflictHandler<
T> = VersionedSyncConflictResolution< T> Function(VersionedSyncConflict<T> conflict) - Caller-supplied conflict handler for VersionedJsonStore.syncWith — see that method's doc for exactly when this is invoked, and its exception-safety contract.