Releases: AverageConsumer/R-Shop
🚀 v1.1.0 — The "Native SMB" Update
Native SMB via Kotlin MethodChannel, folder downloads, redesigned onboarding, and 1,069 tests.
Highlights
- Native SMB — Replaced the
smb_connectDart library with a Kotlin MethodChannel service (SmbService.kt), enabling folder downloads, progress reporting, and reliable timeout handling on Android. - Folder downloads — Games stored as multi-file directories (bin/cue, m3u) can now be downloaded as complete folders via SMB and FTP.
- Onboarding rework — Redesigned setup wizard with streamlined console configuration, local folder detection, and RomM integration.
- Gamepad button icons — SVG icon set (Xbox, PlayStation, Nintendo Switch) for context-aware controller hints.
Change Log
Added:
- Native SMB — Kotlin MethodChannel service replacing smb_connect library, with folder downloads, progress reporting, and 30s timeouts.
- Folder downloads — multi-file directory downloads (bin/cue, m3u) via SMB and FTP protocols.
- Gamepad button icons — SVG icon set (Xbox, PlayStation, Nintendo Switch) for controller hints.
- RomM config screen — full server management (add/edit/remove) with connection test, accessible from settings.
- Network constants — centralized timeout values (
NetworkTimeouts) shared across all providers. - File utilities — crash-safe atomic file move (
moveFile) with staging and cleanup.
Improved:
- Onboarding rework — redesigned setup wizard with streamlined console configuration, local folder detection, and RomM integration.
- FTP provider — host validation (hostname, IPv4, IPv6), injection protection, configurable timeouts.
- Web provider — security hardened directory parsing (path traversal, control chars, oversized hrefs filtered).
- Download service — folder-aware downloads for SMB and FTP with per-file progress.
- Friendly errors — expanded user-facing error mapping for network, auth, and provider failures.
- Console HUD / Quick Menu / Control Button — simplified rendering with gamepad icon integration.
Internal:
- 1,069 tests (up from 970) — new suites: SMB provider (14), FTP provider (8), Web provider (12), FocusSyncManager (32), OverlayPriorityManager (14), file_utils (5), friendly_error expansions.
smb_connectdependency removed (replaced by native Kotlin implementation).NativeSmbServiceDart wrapper forcom.retro.rshop/smbMethodChannel.NativeSmbDownloadHandle/NativeSmbFolderDownloadHandledownload handle types.
🚀 v1.0.0 — The "Stable" Release
R-Shop exits beta. After 10 beta releases, 950+ tests, and 8 security audits — this is the stable 1.0.
Highlights
- Stable release — R-Shop is production-ready. Zero TODO/FIXME markers, zero silent catches, all error paths logged.
- SVG platform icons — All 29 system icons migrated from PNG to crisp SVG format for sharp rendering at any resolution.
- Android package restructure — Migrated from
com.example.r_shoptocom.retro.rshopwith dedicated network security config.
Change Log
Improved:
- Test coverage — 950+ tests covering controllers, services, models, and utilities.
- Code quality — zero silent catches, all error paths logged, all
debugPrintcalls verified. - Dependency hygiene — all dependencies pinned to exact versions for reproducible builds.
Internal:
- New test suites: GameListController (43 tests), GameMergeHelper (12 tests), ImageHelper (19 tests).
- 8 additional test files covering app config, audio manager, config parser, onboarding, providers, and cover preload.
🚀 v0.9.9 Beta — The "Shelves" Update
Note: This release introduces custom game shelves, adaptive memory tiering, and a major codebase refactoring pass. Upgrading from
<= 0.9.3still requires a fresh install.
Highlights
- Custom Shelves — Create personal game collections with manual curation, filter rules (by system, region, language), or hybrid mode. Supports reordering, renaming, and per-shelf sort modes.
- Device Info Service — Adaptive memory tiering (low/standard/high RAM) auto-tunes image cache sizes, grid cache extents, and cover preload pools for low-end handhelds.
- Major Refactoring — Five mega-files split into focused widget modules, reducing the largest files by 40-90% (settings, download overlay, shelf edit, onboarding, library).
Change Log
Added:
- Custom Shelves — create personal game collections with manual curation, filter rules (by system, region, language), or hybrid mode; supports reordering, renaming, and per-shelf sort modes.
- Device Info Service — adaptive memory tiering (low/standard/high RAM) that auto-tunes image cache sizes, grid cache extents, and cover preload pools for low-end handhelds.
- Shelf Picker Dialog — quick-add games to shelves from library and game detail screens.
- System Selector Overlay — filter library view by system with visual system badges.
Improved:
- Settings screen refactored — split into Preferences, System, and About tabs with extracted
DeviceInfoCardwidget (1048→604 lines). - Download overlay refactored — extracted 7 widgets to
lib/widgets/download/(1477→793 lines). - Shelf edit screen refactored — extracted GameListOverlay, TextInputDialog to shared library widgets (1108→631 lines).
- RomM onboarding refactored — extracted RommConnectView, RommSelectView, RommFolderView, RommActionButton (1405→122 lines); state classes moved to
onboarding_state.dart(1713→1362 lines). - Library screen refactored — extracted ReorderableCardWrapper, LibraryEntry to dedicated widgets (1490→1386 lines).
- Dependency pinning — all 16 remaining caret-range dependencies pinned to exact resolved versions for reproducible builds.
Internal:
- New models:
CustomShelf,ShelfFilterRulewith JSON serialization. - New providers:
CustomShelvesNotifier/customShelvesProviderfor shelf CRUD. DeviceInfoServicewithMemoryTierclassification.- ~20 new test files covering download queue manager, unified game service, library sync, thumbnail service, custom shelves, database service, config storage, image cache, storage service, and widget tests.
🚀 v0.9.8 Beta — The "Stability" Update
Note: This release focuses on stability, crash diagnostics, and eliminating runtime errors. Upgrading from
<= 0.9.3still requires a fresh install.
Highlights
- Crash Log Service — Local ring-buffer error log (~500KB) captures all uncaught errors with timestamps and stack traces. Persists across sessions in app cache for post-mortem debugging.
- Export Error Log — New Settings entry shares the crash log via the system share sheet for easy bug reporting. Only visible when the log contains data.
- Overlay Priority Fix — All overlay scope classes now defer token release via
Future(), eliminating the Riverpod "cannot modify provider during widget tree build" crash that occurred on screen transitions. - Zone Alignment — Binding initialization and
runAppnow execute in the samerunZonedGuardedzone, eliminating the "Zone mismatch" startup warning.
Change Log
Added:
- Crash log service — local ring-buffer log file (~500KB) captures all uncaught errors with timestamps and stack traces; persists across sessions in app cache.
- Export Error Log — new Settings entry (under System) shares the crash log via the system share sheet for easy bug reporting; only visible when log contains data.
- Disk space pre-check — downloads are rejected with a clear error when device storage drops below 1 GB.
Improved:
- HTTP download depth guard — the resume-restart path now enforces a single-retry limit, preventing infinite recursion if the server keeps returning mismatched content lengths.
- FocusSyncManager index safety —
ensureFocusNodes()clamps_selectedIndexafter pruning disposed nodes;validateState()clamps_targetColumnwhen column count changes. - Zone alignment —
WidgetsFlutterBinding.ensureInitialized()andrunApp()now execute inside the samerunZonedGuardedzone. - Overlay priority release — all scope classes defer
release()viaFuture()indispose(), fixing the Riverpod state modification crash. - Detail screen layout — system name badge wrapped in
Flexiblewith ellipsis overflow, fixingRenderFlexoverflow on narrow screens. - ConfigModeScreen dispose — audio manager cached in
initStateto avoidref.read()after widget is disposed. - Download queue lookup —
getDownloadById()uses a simple loop instead offirstWhere+ try/catch, eliminating noisy log spam during queue restore.
Bug Fixes:
- Overlay priority crash — releasing overlay tokens during widget unmount no longer throws Riverpod state modification errors.
- FocusSyncManager focus loss — selected index could point to a disposed FocusNode after the item count decreased.
- RenderFlex overflow — system badge Row on game detail screen no longer overflows on narrow layouts.
- Zone mismatch warning — binding and app now share the same error zone.
- ConfigModeScreen "ref after disposed" — no longer crashes when navigating away quickly.
Technical Internal:
- New
CrashLogServicesingleton withlog(),logError(),getLogFile(),clearLog(),getLogContent(). crashLogServiceProviderinapp_providers.dart, overridden inmain.dart.- Global error handlers now write to crash log in addition to
debugPrint. - Removed spammy
debugPrintinFocusSyncManager._enforceFocus()for deferred focus.
🚀 v0.9.7 Beta — The "Thumbnail" Update
Note: This release introduces a persistent thumbnail pipeline for instant cover art, real-time ROM status tracking, and an About section in Settings. Upgrading from
<= 0.9.3still requires a fresh install.
Highlights
- Thumbnail Pipeline — Persistent isolate-based thumbnail generator produces 400px JPEG covers with background migration on startup and proactive preloading during library scans. Game cards display thumbnails instantly with no network round-trip.
- ROM Status Providers — Real-time ROM installation tracking via filesystem watchers and download-completion listeners. No more manual polling — cards update the moment a download finishes or a ROM is deleted.
- Smart Cover Loading — Thumbnail-first display with magic-byte validation, JPEG re-encoding for corrupt cache entries, and scroll-suppressed loading to reduce jank during fast scrolling.
- About Section — New Settings section showing app version, GitHub/Issues links, and an Easter Egg tagline.
Change Log
Added:
- Thumbnail pipeline — persistent isolate-based thumbnail generator (400px JPEG) with background migration and proactive cover preloading during library scans.
- ROM status providers — real-time ROM installation tracking via filesystem watchers and download-completion listeners.
- Installed files provider — central isolate-scanned index of all installed ROM files across every system.
- Cover preload — new Settings entry to batch-generate thumbnails for all games.
- About section — app version, GitHub/Issues links, and Easter Egg tagline in Settings.
- Zip extraction limit — increased from 2 GB to 8 GB.
Improved:
- Smart cover loading — thumbnail-first display with magic-byte validation, JPEG re-encoding for corrupt entries, and scroll-suppressed loading.
- Controller button styling — pill-shaped shoulder/trigger buttons, per-layout face button colors (Xbox green/red/blue/yellow, PlayStation palette), and shape painters for Nintendo +/− buttons.
- Quick menu hints — face button hints now show layout-correct color palettes.
- Game card performance — replaced
AnimatedScale/AnimatedContainerwith staticTransform.scale/Container;SelectionAwareItemusesValueNotifierto rebuild only affected cards. - Search overlay — extracted
SearchableScreenMixinand movedSearchOverlaytowidgets/for cross-screen reuse. FocusSyncManagermoved tocore/input/for use by Library and Scan screens.- Library screen — now uses
SearchableScreenMixin,SelectionAwareItem,FocusSyncManager, and scroll suppression. - Image cache rate limiter — cancellable pending requests, increased concurrent fetch limit (50), and host-level rate-limit detection.
- Database schema v4 — adds
thumb_hashandhas_thumbnailcolumns; thumbnail flags preserved across refreshes. OverlayGuardedAction— generic reusable guarded action replaces per-screen private action classes.
Bug Fixes:
- Zip bomb protection — extracted archive size capped at 8 GB; extraction aborts with clear error if limit exceeded.
- Web provider path traversal — directory listing parser rejects absolute URLs and
../href values. - Overlay priority teardown —
OverlayFocusScope,DialogFocusScope, andSearchFocusScopeuseaddPostFrameCallbackwith try/catch, preventing "disposed notifier" crashes on fast screen transitions. - Android backup disabled —
android:allowBackup="false"prevents unintended data restore. - Grid navigation guard —
_GridNavigateActionnow checksoverlayPriorityProviderinisEnabled. - Focus restoration —
mainFocusRequestProvidernow set centrally inConsoleScreenMixin.initState.
Technical Internal:
- New dependencies:
image: ^4.3.0,crypto: ^3.0.6,package_info_plus,url_launcher,url_launcher_linux. GameItem.hasThumbnailfield added;copyWithextended accordingly.adjustColumnCount()helper extracted toConsoleScreenMixin.- Deleted 4 obsolete files:
animated_background.dart,radial_glow.dart,folder_analysis_view.dart,search_overlay.dart(game_list copy).
🚀 v0.9.6 Beta — The "Smart Scan" Update
Note: This release adds smart local scanning, a revamped onboarding flow with auto-detection, and cache-first game loading for instant list display. Upgrading from
<= 0.9.3still requires a fresh install.
Highlights
- Scan Library — Full-library scan from Settings with animated per-system progress, game count badges, and a completion summary showing total games discovered across all consoles.
- Smart Onboarding — Local Setup now auto-detects existing ROM folders at common paths. Choose to scan a found folder, create standard folders with a system picker, pick an existing folder manually, or skip for later.
- Cache-First Loading — Game lists load instantly from local cache, then silently refresh from remote providers in the background. The UI only updates if the list actually changed.
- Expanded ROM Support — 27 systems, 200+ file formats. Added support for GameCube (ISO/GCM/CISO), Wii (WBFS/WIA/CISO), PS2 (CSO), PS3 (PKG), and many more across all systems.
- Library-Based Search — Y button on home now navigates directly to Library with search open, replacing the standalone global search overlay.
Change Log
Added:
- Scan Library screen — Settings entry opens animated console grid with per-system scan progress and result badges.
- Smart onboarding auto-detection — detects ROM folders at
/storage/emulated/0/ROMs,/Roms,/romswith scan, create, or pick options. - Cache-first game list loading with silent background refresh and filename-diffed updates.
- Offline indicator — amber "Offline — cached data" toast when sync fails; sync badge shows failure state.
- Provider reordering — D-pad or arrow buttons to change provider priority in console config.
- Test & Save — single button press tests provider connection and auto-saves on success.
- User Guide (
docs/USER_GUIDE.md) — comprehensive 582-line guide covering all features, controls, and troubleshooting.
Improved:
- ROM format coverage expanded across 10+ systems (GameCube, Wii, PS2, PS3, PSP, Mega Drive, Dreamcast, Saturn, Arcade, N64, SNES).
- Isolate-based local scanning — filesystem scanning offloaded to a Dart isolate for smoother UI.
- Library sync freshness — 5-minute cache prevents redundant re-syncs;
clearFreshness()forces refresh after config changes. - Sync now covers local-only systems, not just remote ones.
- Batched install-status checks (20-game parallel batches).
- Games with no region/language metadata now pass through filters instead of being excluded.
- Console grid shows blue folder badge for local-only systems (distinct from green provider checkmark).
- Post-settings navigation re-syncs config and clears freshness.
- Library installed detection matches extracted ROM files (e.g.,
Game.zip→Game.iso).
Bug Fixes:
- GameDetail variant index clamped to valid range (prevents crash on variant list changes).
- Search overlay focus handling improved.
Technical Internal:
GlobalSearchOverlayremoved (675 lines) — replaced by Library withopenSearch: true.RepoManagerandRomHeaderParserremoved (no longer needed).archivedependency removed frompubspec.yaml.GameMergeHelperextracted for dedup logic (remote-vs-local merge, archive expansion, multi-file detection).SystemModelgainsarchiveExtensions,allRomExtensions,allGameExtensions, andisGameFile().- Unused providers cleaned up from
app_providers,config_providers,download_providers. LibrarySyncServiceextended withdiscoverAll(),isFresh(),hadFailuresstate.
🚀 v0.9.5 Beta — The "Library" Update
Note: This is a feature-packed release that adds a unified Library browser, a Quick Menu, and a fully reworked home screen. Upgrading from
<= 0.9.3still requires a fresh install.
✨ Highlights
📚 Library Screen
A brand-new cross-system game browser. Browse All, Installed, or Favorites across every console in one place — with search, sort modes (A-Z / by system), and adjustable grid zoom via LB/RB.
⚡ Quick Menu (Start Button)
Press Start from any screen to open a contextual overlay with instant shortcuts to Search, Settings, Zoom, and Downloads. No more menu-diving.
🏠 Home Grid Layout
Toggle between the classic carousel and a new grid view on the home screen. Grid columns are adjustable with LB/RB, and your preference persists across sessions.
📂 Change Log
➕ Added
- Library Screen 📚 | Unified cross-system browser with All/Installed/Favorites tabs.
- Background Library Sync 🔄 | Automatic provider sync on launch with live progress badge.
- Quick Menu ⚡ | Start button opens contextual shortcuts from any screen.
- Home Grid Layout 🏠 | Toggle carousel ↔ grid view; columns adjustable via LB/RB.
- ROM Header Parser 🧬 | Extracts internal titles from GB, GBC, GBA, NDS, and SNES ROMs.
- Favorite Toggle ⭐ | Select button quick-favorites from the detail screen.
- Tab Switching 🔀 | LB/RB navigates filter tabs in Library and Filter overlay.
- Local-Only Filter 📁 | New toggle in filter overlay to show only installed ROMs.
🔧 Improved
- BaseGameCard | Unified card design with system badge, installed indicator, favorite heart, and provider label.
- Version Card | Significant refactor removing redundant layout logic.
- ConsoleHud | Cleaner slot rendering, consistent spacing, proper embedded vs positioned modes.
- Filter Overlay | Improved layout with local-only toggle and multi-tier filtering.
- Global Search | Results now show provider label and region flags consistently.
- Persistence | Controller layout and home layout preferences saved across sessions.
🛡️ Bug Fixes
- Download Overlay HUD | Button legend was stuck top-left instead of bottom-right.
- Quick Menu Downloads | Now shows whenever queue has any items, not just active+queued.
- Duplicate Library Entries | Multi-file ROMs (bin/cue) no longer appear twice after archive merge.
- Subdirectory ROMs |
scanLocalGames,exists, anddeletenow check subdirectories for all ROM extensions. - Favorite Migration | Legacy favorite name IDs cleaned up on app start.
🛠️ Technical Internal
- QuickMenuOverlay widget with overlay priority and controller-aware shortcut hints.
- AdjustColumnsIntent consolidates zoom controls across screens.
- LibrarySyncService as
StateNotifier<LibrarySyncState>with SyncBadge widget. - New providers:
homeLayoutProvider,homeGridColumnsProvider,controllerLayoutProvider.
v0.9.4-beta
🚀 v0.9.4 Beta — The "Command Center" Update
Note: This is a major architectural release. It transforms R-Shop from a simple downloader into a professional-grade management hub for Android-based retro handhelds. You might need to reinstall the app for all things to load properly!
✨ Highlights
🖥️ RomM Command Center
A radically redesigned configuration screen. You can now monitor which console is linked to which server and synchronize credentials with a single click. No more "silent" auth failures—full transparency across all systems.
🔍 Global Search (Y-Button)
Search across all your connected systems simultaneously from the Home screen. Includes region flags, tag badges, and smooth gamepad navigation.
🛡️ Hardened Security & Stability
Critical fixes for Zip-Slip and Path-Traversal vulnerabilities. We've also implemented Atomic Config Saves to ensure your settings are never corrupted during a crash.
📂 Change Log
➕ Added
- Global Search Activated 🔎 | Cross-system search with region flags and tag badges.
- Local-Only Mode 📁 | Consoles without a provider now show locally scanned ROMs with a banner hint.
- FTP Download Progress 📈 | Real-time per-chunk progress reporting.
- Inactivity Watchdog 🐕 | 60-second stall detection with clear user error messages.
- Gamepad Key Fix 🎮 | Intercepts mismatched logical keys for specific drivers (e.g., AYN Thor).
- Provider Type Badges 🏷️ | Visual indicators on version cards (
RomM,SMB,FTP,WEB). - Sectioned Download Overlay 📥 | Organized lists (Downloading / Queued / Complete) with ID-stable focus.
🔧 Improved
- Settings Rework | Focus-aware glow borders and full D-pad navigation.
- Safe Reset | "Reset App" moved to HUD (X-button) to prevent accidental wipes.
- UI Polish | Compressed platform icons (-70% size) and context-sensitive empty states.
- Network Resilience | Strict timeouts (15s-30s) on all provider calls to prevent app hangs.
- Input Refinement | Shortcuts now ignore repeats to prevent accidental double-triggers.
🛡️ Security & Bug Fixes
- Zip Slip & Path Traversal | Validated canonical paths and enforced safe basenames.
- Atomic Writes | Config is written to
.tmpbefore renaming to prevent corruption. - Race Conditions | Fixed Database initialization and AudioManager re-init loops.
- Memory Hygiene | Resolved timer and connection leaks (Dio, FTP, Retry timers).
- Focus Guards | Fixed focus "leaks" in search and download overlays.
🛠️ Technical Internal
- Database Migration: Schema v3 adds
provider_configcolumn support. - Immutability:
DownloadItemis now fully immutable for predictable state management. - Controller Guards: Added disposed-guards to prevent memory-related crashes.
Full Changelog: v0.9.3-beta...v0.9.4-beta
v0.9.3-beta
🚀 v0.9.3 Beta — The "Persistence & Protocol" Update
Experimental Build: This is an early beta release. Expect active development and occasional rough edges as we harden the core engine.
✨ Highlights
🪄 RomM Onboarding Wizard
A new multi-step configuration wizard that simplifies server connection and platform selection. It features Smart Folder Matching, which automatically maps your local directories to systems using an alias-based matching strategy (e.g., mapping "famicom" to NES).
🔋 Robust Download Engine
We've implemented an Android Foreground Service with persistent notifications. This ensures your downloads survive even when the app is in the background. Additionally, the download queue is now fully persistent—your progress is saved and restored across app restarts.
🌍 Advanced Filtering
Introducing Region & Language filters. You can now filter massive game lists with ease, featuring section jumping via LB/RB and per-system state persistence.
📂 Change Log
➕ Added
- Onboarding Wizard 🧙♂️ | Guided setup for RomM server and platform discovery.
- Smart Folder Matcher 📂 | Automatic local directory mapping via alias-logic.
- Foreground Service 🛡️ | Persistent Android service for uninterrupted background downloads.
- Queue Persistence 💾 | Download tasks now survive app restarts and crashes.
- Concurrency Control ⚙️ | Adjustable download limits (1–3) in the Settings menu.
- Region/Language Filters 🏳️🌈 | Deep-filtering overlay for game lists.
- System-Linked States 🔗 | Filter settings are now saved individually per console.
🔧 Improved
- LB/RB Navigation | Quick-jumping through filter sections for faster gamepad usage.
- Settings Integration | New UI toggles for download concurrency management.
🛡️ Fixed
- HTTP Encoding Fix 🛠️ | Resolved a critical bug where double URL-encoding caused 404 errors on all remote requests.
🛠️ Internal & Architecture
- Serialization: Implemented robust JSON serialization for the download queue.
- Service Lifecycle: Added strict management of Android Service start/stop intents.
Full Changelog: v0.9.2-beta...v0.9.3-beta
v0.9.2-beta
🚀 v0.9.2 Beta — The "Input & Interface" Update
Core Refinement: This update focuses on hardening the input system and establishing a unified UI framework. We've introduced the "Console HUD" standard to ensure a seamless gamepad experience across all screens.
✨ Highlights
🚨 Visual Status Indicators
Game cards now feature an integrated "LED strip" indicator. This visual cue instantly tells you which ROMs are already installed and ready to play on your local storage.
🎮 Unified Console HUD
We’ve completely overhauled how button hints are managed. The new Slot-based HUD API (A, B, X, Y, Start, Select, D-Pad) ensures that every screen feels consistent and provides the same high-quality gamepad feedback.
🏎️ Input Fluidity
No more "skipping" menus! We implemented a 100ms Navigation Cooldown and a refined global Action system. This prevents rapid-fire triggers and ensures that DPAD-hold navigation feels deliberate and smooth.
📂 Change Log
➕ Added
- Installed Indicator LED 🟢 | Visual strip on game cards for downloaded ROMs.
- Slot-based HUD API ⌨️ | New unified system for A, B, X, Y, Start, Select, and D-Pad actions.
- Shared UI Components 🧩 |
ConsoleSetupHudis now shared between onboarding and config modes. - Intelligent Auto-Scroll 📜 |
ConsoleFocusablenow automatically scrolls focused elements into view.
🔧 Improved
- Onboarding Rework 🪄 | Streamlined setup flow with strict guard checks for server tests and saves.
- Input Architecture 🧠 | Global Actions now use centralized
isEnabled()checks for cleaner code. - Navigation Cooldown ⏱️ | 100ms debounce prevents rapid-fire input on DPAD hold.
- Config Simplification |
ConfigModeScreennow utilizes the shared HUD logic for better maintainability.
🛡️ Fixed
- Input Duplication 🛠️ | Resolved an issue where holding the DPAD produced duplicate navigation events.
- Focus Node Stability 🎯 |
ConsoleFocusable.didUpdateWidgetnow correctly handles focus node swaps. - Overlay Priority 🏗️ | Fixed the lifecycle and priority management of the
ExitConfirmationOverlay.
🛠️ Internal & Architecture
- Widget Decoupling: Separated HUD logic from screen-specific code for better reusability.
- Lifecycle Guards: Hardened the overlay entry/exit logic to prevent focus leaks.
Full Changelog: v0.9.1-beta...v0.9.2-beta