github misobadev/neostation-frontend v0.8.0+95
NeoStation Beta 0.8.0+95

latest releases: v0.14.0+130, v0.13.0+129, v0.12.0+128...
5 months ago

What's Changed

feat: add systems update dialog with user consent and auto-scan Silent background updates replaced with explicit dialogs for both app and systems updates. Users can now opt out via two new General settings toggles (auto_update_app, auto_update_systems, default ON).

  • SystemsUpdateInfo separates check from download in the service
  • SystemsUpdateDialog mirrors UpdateDialog UX with gamepad A/B support
  • Update sequence is ordered: app check first, systems only if no app
    update pending
  • After systems update: reloads system/emulator defs then re-scans ROMs
    so new configs take effect immediately

fix(palette): rename theme→palette and fix persistence bug

  • saveConfig() was overwriting user palette selection on every settings save because SqliteConfigProvider._config.paletteName is only loaded once at startup; removed paletteName from saveConfig(), owned exclusively by PaletteProvider via ConfigRepository.updatePaletteName()
    • ThemeProvider → PaletteProvider (file, class, all methods/fields)
    • DB column theme_name → palette_name (migration v81)
    • ConfigModel.themeName → paletteName

perf(lifecycle): suspend background work when app is backgrounded WebSocket and periodic timers kept running on screen-off, preventing
CPU deep sleep and keeping network radio awake.

  • NotificationService.suspend(): close socket, cancel timers, reset
    reconnect counter, auto-reconnect stays enabled for resume
  • MusicPlayerService: replace Stream.periodic getters with
    StreamController.broadcast() backed by cancellable timers;
    appPaused() stops all 3, appResumed() restarts them
  • AppLifecycleHandler: wire paused/hidden → suspend both services;
    resumed already reconnects notification service

fix: prevent video controller crashes during navigation on low-RAM devices - Move VideoPlayerController.dispose() out of setState() to avoid race conditions with child VideoPlayer widget lifecycle.

  • Wrap all controller dispose() calls in try-catch to prevent fatal
    exceptions from propagating out of dispose()/setState().
  • Remove redundant pause() calls before dispose(); dispose() already
    handles playback shutdown and the async pause() was racing native
    fvp threads under memory pressure.
  • Fix ImageStreamListener leak in GameDetailsGameInfoTab that
    accumulated native image resources when rapidly browsing titles.
  • Remove spam-pause logic from _videoListener and build() that
    fired async pause() repeatedly during widget rebuilds.

Fixes crash when navigating away from the title video view on
devices with limited RAM

fix(android): add LEANBACK_LAUNCHER category for Google TV home screen visibility

  • Add android.intent.category.LEANBACK_LAUNCHER to the main activity's
    intent filter so NeoStation appears in the Google TV / Android TV
    home screen app row after sideloading, instead of only being
    accessible via Settings > All apps.

fix(android): cache SAF ROMs locally for RetroArch network sources RetroArch cannot reliably read content:// URIs from network Document Providers (e.g. Round Sync, CIFS) because they often lack proper seek/random-access support, causing a black screen on launch.

When a RetroArch-bound ROM has a content:// URI that cannot be resolved
to a local filesystem path, copy it to the app's external cache and pass
the absolute local path instead.

Features:

  • Smart cache: skips copy if cached file size matches remote
  • Auto-cleanup: removes cache entries older than 7 days
  • Size guard: ignores files larger than 1GB to avoid filling storage
  • Only activates for com.retroarch* packages; standalone emulators
    continue using ClipData + URI permissions as before

Fixes: NAS/SAF black screen issue reported on Anbernic RG557 and
similar Android 14 devices.

feat(l10n): add Traditional Chinese (zh_Hant) translation

  • Add app_locale_zh_hant.dart with full Traditional Chinese localization
  • Register zh_Hant locale in app_locale.dart supportedLanguages map
  • Add MapLocale('zh_Hant', AppLocale.zhHant) in main.dart

fix(android): prevent WebSocket background reconnect and idle battery drain Two root causes of idle battery drain reported across multiple devices:

  • suspend() now sets _shouldAutoReconnect=false before closing the
    socket, blocking the _onDisconnected → _scheduleReconnect loop
    that kept the WebSocket alive in background
  • connect() resets _shouldAutoReconnect=true so reconnection resumes
    normally on app foreground
  • Removed android:keepScreenOn from launcher activity; display can
    now enter deep sleep when idle at the home screen

fix(linux): bundle SoLoud audio deps and enable discrete GPU libFLAC, libogg, libvorbis, libopus are loaded at runtime via
DynamicLibrary.open, ldd on the main binary never sees them,
so they were never bundled. Fix by copying them explicitly and
running ldd over all bundled .so files to catch transitive deps.

AppRun now detects GPU vendor and activates PRIME render offload:
NVIDIA Optimus via __NV_PRIME_RENDER_OFFLOAD, AMD/Intel discrete
via DRI_PRIME=1. Harmless on single-GPU systems.

Applies to both x86_64 and ARM64 build scripts.

feat: configurable user-data storage location Allows selecting where user-data (DB, scraped media, themes) is stored, critical for Android TV boxes and SD card devices with limited internal storage.

  • Setup wizard: new step 0 to pick location before first DB init;
    DB reinitializes in-session via SqliteConfigProvider.reinitialize()
  • Settings → Directories: user-data location at top, ROM folders
    grouped under ROM Directories section, inline migration progress
    (no dialog), source contents deleted after successful copy
  • Android: SAF picker → real path via safUriToRealPath(); TV uses
  • Android: SAF picker → real path via safUriToRealPath(); TV uses
    TvDirectoryPicker; path stored in SharedPreferences so Kotlin
    (MainActivity, NeoDocumentsProvider) reads it before Flutter
  • sqlite_service: fix close() not resetting _initCompleter, causing
    database already closed errors on reinit
  • sfx_service: pre-create SoLoud temp dir to prevent
    SoLoudTemporaryFolderFailedException on Android
  • Removes unused directories_screen.dart (replaced by
    directories_settings_content.dart)

refactor(carousel): move action buttons to shared systems footer Replace per-card settings/enter buttons in carousel view with them same SystemsGridFooter used by grid view. Extract _buildAllSystems() helper to avoid duplicating system list logic between both layouts.

fix(palettes) fix some palettes colors

Don't miss a new neostation-frontend release

NewReleases is sending notifications on new releases.