Skip to content

commit 8f4c0fd

abduznik edited this page May 23, 2026 · 1 revision

feat: robust platform-aware scanner with bulk matching and UI indicator

Commit: 8f4c0fd0aab2e2bc87da1ca1be7095683774f31f

Author: abduznik

Date: 2026-04-28

Why: Adds a new feature or capability to the application.

Files Changed

lib/core/romm/rom_scanner_service.dart             | 163 +++---
 lib/core/romm/romm_service.dart                    |   3 +-
 test/unit/firmware_service_test.mocks.dart         | 549 +++++++++++---------
 test/unit/paginated_games_provider_test.mocks.dart | 226 +++++----
 test/unit/save_sync_service_test.mocks.dart        | 549 +++++++++++---------
 test/unit/strategy_registry_test.mocks.dart        |  25 +
 test/widgets/library_screen_test.mocks.dart        | 565 +++++++++++----------
 test/widgets/settings_screen_test.mocks.dart       | 517 ++++++++++---------
 8 files changed, 1439 insertions(+), 1158 deletions(-)
  • lib/core/romm/rom_scanner_service.dart
  • lib/core/romm/romm_service.dart
  • test/unit/firmware_service_test.mocks.dart
  • test/unit/paginated_games_provider_test.mocks.dart
  • test/unit/save_sync_service_test.mocks.dart
  • test/unit/strategy_registry_test.mocks.dart
  • test/widgets/library_screen_test.mocks.dart
  • test/widgets/settings_screen_test.mocks.dart

Diff

diff --git a/lib/core/romm/rom_scanner_service.dart b/lib/core/romm/rom_scanner_service.dart
index 6a7a83e..14c463c 100644
--- a/lib/core/romm/rom_scanner_service.dart
+++ b/lib/core/romm/rom_scanner_service.dart
@@ -39,12 +39,15 @@ class RomScannerService {
 
   /// Performs an incremental sync of the ROM directory.
   Stream<RomSyncResult> sync(String romsRoot) async* {
-    final storedMTimes = _mappingService.getMTimes();
     final mappings = _mappingService.getMappings();
     
     final rootDir = Directory(romsRoot);
     if (!await rootDir.exists()) return;
 
+    // 0. Fetch platforms to map slugs to IDs
+    final platforms = await _rommService.getPlatforms();
+    final platformSlugToId = {for (var p in platforms) p.slug.toLowerCase(): p.id.toString()};
+
     final List<Directory> platformDirs = [];
     await for (final entity in rootDir.list()) {
       if (entity is Directory) {
@@ -52,6 +55,7 @@ class RomScannerService {
       }
     }
 
+    final storedMTimes = _mappingService.getMTimes();
     final List<Directory> dirtyDirs = [];
     for (final dir in platformDirs) {
       final storedMTime = storedMTimes[dir.path];
@@ -69,102 +73,97 @@ class RomScannerService {
     }
 
     final dirsToScan = forceFullScan ? platformDirs : dirtyDirs;
-    debugPrint('[RomScanner] Scanning ${dirsToScan.length} directories (Force: $forceFullScan)...');
-
-    final List<String> dirPaths = dirsToScan.map((d) => d.path).toList();
-    final List<String> scannedFiles = await compute(_performIsolatedScan, dirPaths);
+    debugPrint('[RomScanner] Scanning ${dirsToScan.length} directories...');
 
-    final Set<String> existingMappedFiles = mappings.keys.toSet();
-
-    final List<String> newFiles = scannedFiles.where((f) => !existingMappedFiles.contains(f)).toList();
-    
-    // 1. Identify and yield REMOVALS immediately
-    final List<String> removedFiles = [];
-    final List<String> normalizedScannedPaths = scannedFiles.map((f) => p.normalize(f)).toList();
-    final Set<String> normalizedScannedSet = normalizedScannedPaths.toSet();
-
-    for (final mappedPath in existingMappedFiles) {
-      final normalizedMappedPath = p.normalize(mappedPath);
+    for (final dir in dirsToScan) {
+      final platformSlug = p.basename(dir.path).toLowerCase();
+      final platformId = platformSlugToId[platformSlug];
       
-      // Check if this mapped path is inside any of the directories we scanned
-      bool isInsideScannedDir = false;
-      for (final dir in dirsToScan) {
-        final normalizedDir = p.normalize(dir.path);
-        if (p.isWithin(normalizedDir, normalizedMappedPath) || normalizedDir == normalizedMappedPath) {
-          isInsideScannedDir = true;
-          break;
-        }
-      }
-
-      if (isInsideScannedDir && !normalizedScannedSet.contains(normalizedMappedPath)) {
-        removedFiles.add(mappedPath);
+      if (platformId == null) {
+        debugPrint('[RomScanner] Skipping unknown platform folder: $platformSlug');
+        continue;
       }
-    }
 
-    if (removedFiles.isNotEmpty) {
-      debugPrint('[RomScanner] Cleaning up ${removedFiles.length} removed files...');
-      for (final f in removedFiles) {
-        final romId = mappings[f];
-        await _mappingService.removeMapping(f);
-        if (romId != null) {
-          yield RomSyncResult(f, romId, isRemoved: true);
+      debugPrint('[RomScanner] Processing $platformSlug (ID: $platformId)...');
+      
+      // 1. Fetch all games for this platform from RomM (Bulk fetch is much faster)
+      final List<Game> platformGames = [];
+      try {
+        int offset = 0;
+        const int batchSize = 250;
+        while (true) {
+          final result = await _rommService.getGamesPage(
+            offset: offset, 
+            limit: batchSize, 
+            platformId: platformId
+          );
+          platformGames.addAll(result.games);
+          if (platformGames.length >= result.total || result.games.isEmpty) break;
+          offset += batchSize;
         }
+      } catch (e) {
+        debugPrint('[RomScanner] Error fetching platform games for $platformSlug: $e');
+        continue;
       }
-    }
 
-    if (newFiles.isEmpty) {
-      debugPrint('[RomScanner] No new files found.');
-      for (final dir in dirsToScan) {
-        final stat = await dir.stat();
-        await _mappingService.updateMTime(dir.path, stat.modified.millisecondsSinceEpoch);
-      }
-      return;
-    }
-
-    debugPrint('[RomScanner] Matching ${newFiles.length} new files...');
-
-    const int maxConcurrent = 5;
-    for (int i = 0; i < newFiles.length; i += maxConcurrent) {
-      // PERF FIX: Add a tiny pause between batches to reduce system load spikes
-      if (i > 0) await Future.delayed(const Duration(milliseconds: 100));
-
-      final chunk = newFiles.sublist(i, i + maxConcurrent > newFiles.length ? newFiles.length : i + maxConcurrent);
+      // 2. Scan the directory
+      final List<FileSystemEntity> entities = await dir.list().toList();
+      final scannedFiles = entities.whereType<File>().toList();
       
-      final results = await Future.wait(chunk.map((filePath) async {
+      // 3. Match new files
+      for (final file in scannedFiles) {
+        final filePath = file.path;
+        if (mappings.containsKey(filePath)) continue; // Already mapped
+
         final fileName = p.basename(filePath);
-        try {
-          // Try 1: Exact filename match (safest)
-          var searchResult = await _rommService.searchRoms(search: fileName);
-          if (searchResult.isNotEmpty) {
-            final game = searchResult.first;
-            await _mappingService.updateMapping(filePath, game.id);
-            return RomSyncResult(filePath, game.id, game: game);
-          }
-
-          // Try 2: SAFE FALLBACK - Strip extension
-          // This helps with titles like "Marvel: Ultimate Alliance" where the file is "Marvel Ultimate Alliance.cso"
-          final nameWithoutExt = p.basenameWithoutExtension(fileName).trim();
-          if (nameWithoutExt.isNotEmpty && nameWithoutExt != fileName) {
-            debugPrint('[RomScanner] Exact match failed, trying without extension: $nameWithoutExt');
-            searchResult = await _rommService.searchRoms(search: nameWithoutExt);
-            if (searchResult.isNotEmpty) {
-              final game = searchResult.first;
+        final fileNameNoExt = p.basenameWithoutExtension(filePath).toLowerCase();
+        
+        Game? matchedGame;
+
+        // MATCHING STRATEGY 1: Exact Filename match (Very Reliable)
+        matchedGame = platformGames.cast<Game?>().firstWhere(
+          (g) => g?.fileName == fileName || g?.fsName == fileName,
+          orElse: () => null,
+        );
+
+        // MATCHING STRATEGY 2: Clean Name match
+        if (matchedGame == null) {
+          matchedGame = platformGames.cast<Game?>().firstWhere((g) {
+            if (g == null) return false;
+            final gName = g.name.toLowerCase().replaceAll(RegExp(r'[<>:"/\\|?*!\-\(\)\[\]]'), ' ').replaceAll(RegExp(r'\s+'), ' ').trim();
+            final fName = fileNameNoExt.replaceAll(RegExp(r'[<>:"/\\|?*!\-\(\)\[\]]'), ' ').replaceAll(RegExp(r'\s+'), ' ').trim();
+            return gName == fName;
+          }, orElse: () => null);
+        }
+
+        if (matchedGame != null) {
+          await _mappingService.updateMapping(filePath, matchedGame.id);
+          yield RomSyncResult(filePath, matchedGame.id, game: matchedGame);
+        } else {
+          // If bulk match failed, try one last API search specifically for this file on this platform
+          try {
+            final results = await _rommService.searchRoms(search: fileName, platformId: platformId);
+            if (results.isNotEmpty) {
+              final game = results.first;
               await _mappingService.updateMapping(filePath, game.id);
-              return RomSyncResult(filePath, game.id, game: game);
+              yield RomSyncResult(filePath, game.id, game: game);
             }
-          }
-        } catch (e) {
-          debugPrint('[RomScanner] Error matching $fileName: $e');
+          } catch (_) {}
         }
-        return RomSyncResult(filePath, null);
-      }));
+      }
 
-      for (final result in results) {
-        yield result;
+      // 4. Identify REMOVALS for this platform
+      final Set<String> currentFiles = scannedFiles.map((f) => f.path).toSet();
+      final platformMappings = mappings.entries.where((e) => p.isWithin(dir.path, e.key));
+      
+      for (final entry in platformMappings) {
+        if (!currentFiles.contains(entry.key)) {
+          await _mappingService.removeMapping(entry.key);
+          yield RomSyncResult(entry.key, entry.value, isRemoved: true);
+        }
       }
-    }
 
-    for (final dir in dirsToScan) {
+      // Update mtime to mark directory as synced
       final stat = await dir.stat();
       await _mappingService.updateMTime(dir.path, stat.modified.millisecondsSinceEpoch);
     }
diff --git a/lib/core/romm/romm_service.dart b/lib/core/romm/romm_service.dart
index 6b9bcdb..95096f0 100644
--- a/lib/core/romm/romm_service.dart
+++ b/lib/core/romm/romm_service.dart
@@ -261,7 +261,7 @@ class RommService {
     } catch (_) { return []; }
   }
 
-  Future<List<Game>> searchRoms({String? sha1, String? md5, String? search}) async {
+  Future<List<Game>> searchRoms({String? sha1, String? md5, String? search, String? platformId}) async {
     final params = <String, dynamic>{
       'limit': 10,
       'offset': 0,
@@ -271,6 +271,7 @@ class RommService {
     if (sha1 != null) params['sha1'] = sha1;
     if (md5 != null) params['md5'] = md5;
     if (search != null) params['search_term'] = search;
+    if (platformId != null) params['platform_id'] = platformId;
 
     try {
       final response = await _dio.get('/api/roms', queryParameters: params, options: _authOptions);
diff --git a/test/unit/firmware_service_test.mocks.dart b/test/unit/firmware_service_test.mocks.dart
index 2e06c5d..1778509 100644
--- a/test/unit/firmware_service_test.mocks.dart
+++ b/test/unit/firmware_service_test.mocks.dart
@@ -3,20 +3,21 @@
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i7;
-import 'dart:io' as _i9;
-import 'dart:typed_data' as _i10;
+import 'dart:async' as _i8;
+import 'dart:io' as _i10;
+import 'dart:typed_data' as _i11;
 
-import 'package:freegosy/core/emulator/emulator_strategy.dart' as _i12;
+import 'package:flutter/foundation.dart' as _i2;
+import 'package:freegosy/core/emulator/emulator_strategy.dart' as _i13;
 import 'package:freegosy/core/emulator/linux_strategies/linux_environment_strategy.dart'
-    as _i4;
-import 'package:freegosy/core/emulator/strategy_registry.dart' as _i11;
-import 'package:freegosy/core/romm/romm_models.dart' as _i2;
-import 'package:freegosy/core/romm/romm_service.dart' as _i5;
-import 'package:freegosy/core/storage/directory_service.dart' as _i3;
+    as _i5;
+import 'package:freegosy/core/emulator/strategy_registry.dart' as _i12;
+import 'package:freegosy/core/romm/romm_models.dart' as _i3;
+import 'package:freegosy/core/romm/romm_service.dart' as _i6;
+import 'package:freegosy/core/storage/directory_service.dart' as _i4;
 import 'package:mockito/mockito.dart' as _i1;
-import 'package:mockito/src/dummies.dart' as _i6;
-import 'package:shared_preferences/shared_preferences.dart' as _i8;
+import 'package:mockito/src/dummies.dart' as _i7;
+import 'package:shared_preferences/shared_preferences.dart' as _i9;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -33,43 +34,60 @@ import 'package:shared_preferences/shared_preferences.dart' as _i8;
 // ignore_for_file: subtype_of_sealed_class
 // ignore_for_file: invalid_use_of_internal_member
 
-class _FakeRomMConfig_0 extends _i1.SmartFake implements _i2.RomMConfig {
-  _FakeRomMConfig_0(Object parent, Invocation parentInvocation)
+class _FakeValueNotifier_0<T> extends _i1.SmartFake
+    implements _i2.ValueNotifier<T> {
+  _FakeValueNotifier_0(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
-class _FakeStorageStatus_1 extends _i1.SmartFake implements _i3.StorageStatus {
-  _FakeStorageStatus_1(Object parent, Invocation parentInvocation)
+class _FakeRomMConfig_1 extends _i1.SmartFake implements _i3.RomMConfig {
+  _FakeRomMConfig_1(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
-class _FakeLinuxEnvironmentStrategy_2 extends _i1.SmartFake
-    implements _i4.LinuxEnvironmentStrategy {
-  _FakeLinuxEnvironmentStrategy_2(Object parent, Invocation parentInvocation)
+class _FakeStorageStatus_2 extends _i1.SmartFake implements _i4.StorageStatus {
+  _FakeStorageStatus_2(Object parent, Invocation parentInvocation)
+    : super(parent, parentInvocation);
+}
+
+class _FakeLinuxEnvironmentStrategy_3 extends _i1.SmartFake
+    implements _i5.LinuxEnvironmentStrategy {
+  _FakeLinuxEnvironmentStrategy_3(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
 /// A class which mocks [RommService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockRommService extends _i1.Mock implements _i5.RommService {
+class MockRommService extends _i1.Mock implements _i6.RommService {
   MockRommService() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  _i2.RomMConfig get config =>
+  _i2.ValueNotifier<bool> get isOffline =>
+      (super.noSuchMethod(
+            Invocation.getter(#isOffline),
+            returnValue: _FakeValueNotifier_0<bool>(
+              this,
+              Invocation.getter(#isOffline),
+            ),
+          )
+          as _i2.ValueNotifier<bool>);
+
+  @override
+  _i3.RomMConfig get config =>
       (super.noSuchMethod(
             Invocation.getter(#config),
-            returnValue: _FakeRomMConfig_0(this, Invocation.getter(#config)),
+            returnValue: _FakeRomMConfig_1(this, Invocation.getter(#config)),
           )
-          as _i2.RomMConfig);
+          as _i3.RomMConfig);
 
   @override
   String get authHeader =>
       (super.noSuchMethod(
             Invocation.getter(#authHeader),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#authHeader),
             ),
@@ -77,93 +95,107 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  void updateConfig(_i2.RomMConfig? newConfig) => super.noSuchMethod(
+  void updateConfig(_i3.RomMConfig? newConfig) => super.noSuchMethod(
     Invocation.method(#updateConfig, [newConfig]),
     returnValueForMissingStub: null,
   );
 
   @override
-  _i7.Future<void> refreshToken(_i8.SharedPreferences? prefs) =>
+  void startHeartbeat() => super.noSuchMethod(
+    Invocation.method(#startHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  void stopHeartbeat() => super.noSuchMethod(
+    Invocation.method(#stopHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  _i8.Future<void> refreshToken(_i9.SharedPreferences? prefs) =>
       (super.noSuchMethod(
             Invocation.method(#refreshToken, [prefs]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<_i2.Game?> getGame(String? id) =>
+  _i8.Future<_i3.Game?> getGame(String? id) =>
       (super.noSuchMethod(
             Invocation.method(#getGame, [id]),
-            returnValue: _i7.Future<_i2.Game?>.value(),
+            returnValue: _i8.Future<_i3.Game?>.value(),
           )
-          as _i7.Future<_i2.Game?>);
+          as _i8.Future<_i3.Game?>);
 
   @override
-  _i7.Future<List<_i2.Platform>> getPlatforms() =>
+  _i8.Future<List<_i3.Platform>> getPlatforms() =>
       (super.noSuchMethod(
             Invocation.method(#getPlatforms, []),
-            returnValue: _i7.Future<List<_i2.Platform>>.value(<_i2.Platform>[]),
+            returnValue: _i8.Future<List<_i3.Platform>>.value(<_i3.Platform>[]),
           )
-          as _i7.Future<List<_i2.Platform>>);
+          as _i8.Future<List<_i3.Platform>>);
 
   @override
-  _i7.Future<List<Map<String, dynamic>>> getCollections() =>
+  _i8.Future<List<Map<String, dynamic>>> getCollections() =>
       (super.noSuchMethod(
             Invocation.method(#getCollections, []),
-            returnValue: _i7.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i8.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i7.Future<List<Map<String, dynamic>>>);
+          as _i8.Future<List<Map<String, dynamic>>>);
 
   @override
-  String? resolveCoverUrl(_i2.Game? game) =>
+  String? resolveCoverUrl(_i3.Game? game) =>
       (super.noSuchMethod(Invocation.method(#resolveCoverUrl, [game]))
           as String?);
 
   @override
-  _i7.Future<List<_i2.Game>> getGames(String? platformId) =>
+  _i8.Future<List<_i3.Game>> getGames(String? platformId) =>
       (super.noSuchMethod(
             Invocation.method(#getGames, [platformId]),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> getAllGames({String? platformId}) =>
+  _i8.Future<List<_i3.Game>> getAllGames({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getAllGames, [], {#platformId: platformId}),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> getRecentlyPlayed({int? limit = 15}) =>
+  _i8.Future<List<_i3.Game>> getRecentlyPlayed({int? limit = 15}) =>
       (super.noSuchMethod(
             Invocation.method(#getRecentlyPlayed, [], {#limit: limit}),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> searchRoms({
+  _i8.Future<List<_i3.Game>> searchRoms({
     String? sha1,
     String? md5,
     String? search,
+    String? platformId,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#searchRoms, [], {
               #sha1: sha1,
               #md5: md5,
               #search: search,
+              #platformId: platformId,
             }),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<({List<_i2.Game> games, int total})> getGamesPage({
+  _i8.Future<({List<_i3.Game> games, int total})> getGamesPage({
     int? offset = 0,
     int? limit = 50,
     String? platformId,
@@ -192,34 +224,34 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
               #withCharIndex: withCharIndex,
               #withFilterValues: withFilterValues,
             }),
-            returnValue: _i7.Future<({List<_i2.Game> games, int total})>.value((
-              games: <_i2.Game>[],
+            returnValue: _i8.Future<({List<_i3.Game> games, int total})>.value((
+              games: <_i3.Game>[],
               total: 0,
             )),
           )
-          as _i7.Future<({List<_i2.Game> games, int total})>);
+          as _i8.Future<({List<_i3.Game> games, int total})>);
 
   @override
-  _i7.Future<_i2.Game?> getRandomGame() =>
+  _i8.Future<_i3.Game?> getRandomGame() =>
       (super.noSuchMethod(
             Invocation.method(#getRandomGame, []),
-            returnValue: _i7.Future<_i2.Game?>.value(),
+            returnValue: _i8.Future<_i3.Game?>.value(),
           )
-          as _i7.Future<_i2.Game?>);
+          as _i8.Future<_i3.Game?>);
 
   @override
-  _i7.Future<List<_i2.SaveFile>> getSaves(String? gameId) =>
+  _i8.Future<List<_i3.SaveFile>> getSaves(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSaves, [gameId]),
-            returnValue: _i7.Future<List<_i2.SaveFile>>.value(<_i2.SaveFile>[]),
+            returnValue: _i8.Future<List<_i3.SaveFile>>.value(<_i3.SaveFile>[]),
           )
-          as _i7.Future<List<_i2.SaveFile>>);
+          as _i8.Future<List<_i3.SaveFile>>);
 
   @override
-  String getDownloadUrl(_i2.Game? game) =>
+  String getDownloadUrl(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getDownloadUrl, [game]),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.method(#getDownloadUrl, [game]),
             ),
@@ -227,11 +259,11 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  _i7.Future<bool> uploadSave(
+  _i8.Future<bool> uploadSave(
     String? gameId,
-    _i9.File? saveFile, {
+    _i10.File? saveFile, {
     String? slot,
-    _i9.File? screenshotFile,
+    _i10.File? screenshotFile,
     String? overrideFilename,
   }) =>
       (super.noSuchMethod(
@@ -244,73 +276,73 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
                 #overrideFilename: overrideFilename,
               },
             ),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> deleteSaves(List<int>? saveIds) =>
+  _i8.Future<bool> deleteSaves(List<int>? saveIds) =>
       (super.noSuchMethod(
             Invocation.method(#deleteSaves, [saveIds]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
+  _i8.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
       (super.noSuchMethod(
             Invocation.method(
               #pruneOldSaves,
               [gameId],
               {#keepCount: keepCount},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
+  _i8.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSavesList, [gameId]),
-            returnValue: _i7.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i8.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i7.Future<List<Map<String, dynamic>>>);
+          as _i8.Future<List<Map<String, dynamic>>>);
 
   @override
-  _i7.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
+  _i8.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getLatestSave, [gameId]),
-            returnValue: _i7.Future<Map<String, dynamic>?>.value(),
+            returnValue: _i8.Future<Map<String, dynamic>?>.value(),
           )
-          as _i7.Future<Map<String, dynamic>?>);
+          as _i8.Future<Map<String, dynamic>?>);
 
   @override
-  _i7.Future<_i10.Uint8List?> downloadSave(
+  _i8.Future<_i11.Uint8List?> downloadSave(
     String? saveUrl, {
-    _i8.SharedPreferences? prefs,
+    _i9.SharedPreferences? prefs,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#downloadSave, [saveUrl], {#prefs: prefs}),
-            returnValue: _i7.Future<_i10.Uint8List?>.value(),
+            returnValue: _i8.Future<_i11.Uint8List?>.value(),
           )
-          as _i7.Future<_i10.Uint8List?>);
+          as _i8.Future<_i11.Uint8List?>);
 
   @override
-  _i7.Future<List<_i2.Firmware>> getFirmware({String? platformId}) =>
+  _i8.Future<List<_i3.Firmware>> getFirmware({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmware, [], {#platformId: platformId}),
-            returnValue: _i7.Future<List<_i2.Firmware>>.value(<_i2.Firmware>[]),
+            returnValue: _i8.Future<List<_i3.Firmware>>.value(<_i3.Firmware>[]),
           )
-          as _i7.Future<List<_i2.Firmware>>);
+          as _i8.Future<List<_i3.Firmware>>);
 
   @override
-  String getFirmwareDownloadUrl(_i2.Firmware? firmware) =>
+  String getFirmwareDownloadUrl(_i3.Firmware? firmware) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmwareDownloadUrl, [firmware]),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.method(#getFirmwareDownloadUrl, [firmware]),
             ),
@@ -318,8 +350,8 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  _i7.Future<_i10.Uint8List?> downloadFirmware(
-    _i2.Firmware? firmware, {
+  _i8.Future<_i11.Uint8List?> downloadFirmware(
+    _i3.Firmware? firmware, {
     void Function(int, int)? onProgress,
   }) =>
       (super.noSuchMethod(
@@ -328,14 +360,14 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
               [firmware],
               {#onProgress: onProgress},
             ),
-            returnValue: _i7.Future<_i10.Uint8List?>.value(),
+            returnValue: _i8.Future<_i11.Uint8List?>.value(),
           )
-          as _i7.Future<_i10.Uint8List?>);
+          as _i8.Future<_i11.Uint8List?>);
 
   @override
-  _i7.Future<bool> updateRomProps(
+  _i8.Future<bool> updateRomProps(
     String? romId,
-    _i8.SharedPreferences? prefs, {
+    _i9.SharedPreferences? prefs, {
     bool? backlogged,
     bool? nowPlaying,
     int? rating,
@@ -354,43 +386,43 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
                 #completion: completion,
               },
             ),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<List<_i2.RomNote>> getRomNotes(String? romId) =>
+  _i8.Future<List<_i3.RomNote>> getRomNotes(String? romId) =>
       (super.noSuchMethod(
             Invocation.method(#getRomNotes, [romId]),
-            returnValue: _i7.Future<List<_i2.RomNote>>.value(<_i2.RomNote>[]),
+            returnValue: _i8.Future<List<_i3.RomNote>>.value(<_i3.RomNote>[]),
           )
-          as _i7.Future<List<_i2.RomNote>>);
+          as _i8.Future<List<_i3.RomNote>>);
 
   @override
-  _i7.Future<bool> createRomNote(
+  _i8.Future<bool> createRomNote(
     String? romId,
     String? title,
     String? content,
   ) =>
       (super.noSuchMethod(
             Invocation.method(#createRomNote, [romId, title, content]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> deleteRomNote(String? romId, int? noteId) =>
+  _i8.Future<bool> deleteRomNote(String? romId, int? noteId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRomNote, [romId, noteId]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 }
 
 /// A class which mocks [DirectoryService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
+class MockDirectoryService extends _i1.Mock implements _i4.DirectoryService {
   MockDirectoryService() {
     _i1.throwOnMissingStub(this);
   }
@@ -399,7 +431,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get romsRootPath =>
       (super.noSuchMethod(
             Invocation.getter(#romsRootPath),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#romsRootPath),
             ),
@@ -410,7 +442,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get emulatorsRootPath =>
       (super.noSuchMethod(
             Invocation.getter(#emulatorsRootPath),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#emulatorsRootPath),
             ),
@@ -421,7 +453,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get linuxSyncPreset =>
       (super.noSuchMethod(
             Invocation.getter(#linuxSyncPreset),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#linuxSyncPreset),
             ),
@@ -429,12 +461,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as String);
 
   @override
-  _i3.StorageStatus get status =>
+  _i4.StorageStatus get status =>
       (super.noSuchMethod(
             Invocation.getter(#status),
-            returnValue: _FakeStorageStatus_1(this, Invocation.getter(#status)),
+            returnValue: _FakeStorageStatus_2(this, Invocation.getter(#status)),
           )
-          as _i3.StorageStatus);
+          as _i4.StorageStatus);
 
   @override
   bool get isSteamDeck =>
@@ -442,15 +474,15 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as bool);
 
   @override
-  _i4.LinuxEnvironmentStrategy get activeLinuxEnvironment =>
+  _i5.LinuxEnvironmentStrategy get activeLinuxEnvironment =>
       (super.noSuchMethod(
             Invocation.getter(#activeLinuxEnvironment),
-            returnValue: _FakeLinuxEnvironmentStrategy_2(
+            returnValue: _FakeLinuxEnvironmentStrategy_3(
               this,
               Invocation.getter(#activeLinuxEnvironment),
             ),
           )
-          as _i4.LinuxEnvironmentStrategy);
+          as _i5.LinuxEnvironmentStrategy);
 
   @override
   set romsRootPath(String? value) => super.noSuchMethod(
@@ -477,77 +509,77 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   );
 
   @override
-  set status(_i3.StorageStatus? value) => super.noSuchMethod(
+  set status(_i4.StorageStatus? value) => super.noSuchMethod(
     Invocation.setter(#status, value),
     returnValueForMissingStub: null,
   );
 
   @override
-  _i7.Future<String?> detectEmuDeckRoot() =>
+  _i8.Future<String?> detectEmuDeckRoot() =>
       (super.noSuchMethod(
             Invocation.method(#detectEmuDeckRoot, []),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<_i3.StorageStatus> initialize() =>
+  _i8.Future<_i4.StorageStatus> initialize() =>
       (super.noSuchMethod(
             Invocation.method(#initialize, []),
-            returnValue: _i7.Future<_i3.StorageStatus>.value(
-              _FakeStorageStatus_1(this, Invocation.method(#initialize, [])),
+            returnValue: _i8.Future<_i4.StorageStatus>.value(
+              _FakeStorageStatus_2(this, Invocation.method(#initialize, [])),
             ),
           )
-          as _i7.Future<_i3.StorageStatus>);
+          as _i8.Future<_i4.StorageStatus>);
 
   @override
-  _i7.Future<String> getDefaultBase() =>
+  _i8.Future<String> getDefaultBase() =>
       (super.noSuchMethod(
             Invocation.method(#getDefaultBase, []),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getDefaultBase, []),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<void> resetRomsRoot() =>
+  _i8.Future<void> resetRomsRoot() =>
       (super.noSuchMethod(
             Invocation.method(#resetRomsRoot, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> resetEmulatorsRoot() =>
+  _i8.Future<void> resetEmulatorsRoot() =>
       (super.noSuchMethod(
             Invocation.method(#resetEmulatorsRoot, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setLinuxSyncPreset(String? preset) =>
+  _i8.Future<void> setLinuxSyncPreset(String? preset) =>
       (super.noSuchMethod(
             Invocation.method(#setLinuxSyncPreset, [preset]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setEmudeckRoot(String? path) =>
+  _i8.Future<void> setEmudeckRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmudeckRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
   void loadEmulatorPathOverrides() => super.noSuchMethod(
@@ -556,13 +588,30 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   );
 
   @override
-  _i7.Future<void> setEmulatorPathOverride(String? emulatorId, String? path) =>
+  _i8.Future<void> setEmulatorPathOverride(String? emulatorId, String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmulatorPathOverride, [emulatorId, path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
+          )
+          as _i8.Future<void>);
+
+  @override
+  _i8.Future<String?> getEmulatorUrlOverride(String? emulatorId) =>
+      (super.noSuchMethod(
+            Invocation.method(#getEmulatorUrlOverride, [emulatorId]),
+            returnValue: _i8.Future<String?>.value(),
+          )
+          as _i8.Future<String?>);
+
+  @override
+  _i8.Future<void> setEmulatorUrlOverride(String? emulatorId, String? url) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmulatorUrlOverride, [emulatorId, url]),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
   String? getEmulatorPathOverride(String? emulatorId) =>
@@ -572,111 +621,119 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as String?);
 
   @override
-  _i7.Future<void> setRomsRoot(String? path) =>
+  _i8.Future<void> setRomsRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setRomsRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setEmulatorsRoot(String? path) =>
+  _i8.Future<void> setEmulatorsRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmulatorsRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
+          )
+          as _i8.Future<void>);
+
+  @override
+  bool platformSupportsArchive(String? platformSlug) =>
+      (super.noSuchMethod(
+            Invocation.method(#platformSupportsArchive, [platformSlug]),
+            returnValue: false,
           )
-          as _i7.Future<void>);
+          as bool);
 
   @override
-  _i7.Future<String> getRomsDirectory() =>
+  _i8.Future<String> getRomsDirectory() =>
       (super.noSuchMethod(
             Invocation.method(#getRomsDirectory, []),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomsDirectory, []),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<Set<String>> getAllDownloadedFileNames() =>
+  _i8.Future<Set<String>> getAllDownloadedFileNames() =>
       (super.noSuchMethod(
             Invocation.method(#getAllDownloadedFileNames, []),
-            returnValue: _i7.Future<Set<String>>.value(<String>{}),
+            returnValue: _i8.Future<Set<String>>.value(<String>{}),
           )
-          as _i7.Future<Set<String>>);
+          as _i8.Future<Set<String>>);
 
   @override
-  _i7.Future<Map<String, Set<String>>> getAllDownloadedFileNamesByPlatform() =>
+  _i8.Future<Map<String, Set<String>>> getAllDownloadedFileNamesByPlatform() =>
       (super.noSuchMethod(
             Invocation.method(#getAllDownloadedFileNamesByPlatform, []),
-            returnValue: _i7.Future<Map<String, Set<String>>>.value(
+            returnValue: _i8.Future<Map<String, Set<String>>>.value(
               <String, Set<String>>{},
             ),
           )
-          as _i7.Future<Map<String, Set<String>>>);
+          as _i8.Future<Map<String, Set<String>>>);
 
   @override
-  _i7.Future<String> getRomDirectory(_i2.Game? game) =>
+  _i8.Future<String> getRomDirectory(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getRomDirectory, [game]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomDirectory, [game]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getRomFilePath(_i2.Game? game) =>
+  _i8.Future<String> getRomFilePath(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getRomFilePath, [game]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomFilePath, [game]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String?> findExistingRomPath(_i2.Game? game) =>
+  _i8.Future<String?> findExistingRomPath(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#findExistingRomPath, [game]),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<String?> resolveSevenZipPath() =>
+  _i8.Future<String?> resolveSevenZipPath() =>
       (super.noSuchMethod(
             Invocation.method(#resolveSevenZipPath, []),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<String> getEmulatorDirectory(String? emulatorId) =>
+  _i8.Future<String> getEmulatorDirectory(String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#getEmulatorDirectory, [emulatorId]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getEmulatorDirectory, [emulatorId]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorAppSupportDirectory(
+  _i8.Future<String> getEmulatorAppSupportDirectory(
     String? emulatorName, {
     String? platformSlug,
   }) =>
@@ -686,8 +743,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorName],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorAppSupportDirectory,
@@ -697,10 +754,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorBiosDirectory(
+  _i8.Future<String> getEmulatorBiosDirectory(
     String? emulatorId, {
     String? platformSlug,
   }) =>
@@ -710,8 +767,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorBiosDirectory,
@@ -721,10 +778,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorSystemDirectory(
+  _i8.Future<String> getEmulatorSystemDirectory(
     String? emulatorId, {
     String? platformSlug,
   }) =>
@@ -734,8 +791,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorSystemDirectory,
@@ -745,19 +802,19 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<void> deleteEmulator(String? emulatorId) =>
+  _i8.Future<void> deleteEmulator(String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteEmulator, [emulatorId]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<String> getEmulatorExecutable(
+  _i8.Future<String> getEmulatorExecutable(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -766,8 +823,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getEmulatorExecutable, [
                   emulatorId,
@@ -776,10 +833,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String?> findEmulatorExecutable(
+  _i8.Future<String?> findEmulatorExecutable(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -788,12 +845,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<bool> isEmulatorInstalled(
+  _i8.Future<bool> isEmulatorInstalled(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -802,17 +859,17 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> isRomDownloaded(_i2.Game? game) =>
+  _i8.Future<bool> isRomDownloaded(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#isRomDownloaded, [game]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
   bool isEmuLaunchScript(String? path) =>
@@ -823,8 +880,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as bool);
 
   @override
-  _i7.Future<void> launchGame(
-    _i2.Game? game,
+  _i8.Future<void> launchGame(
+    _i3.Game? game,
     String? romPath,
     String? emulatorId,
     String? exePath, {
@@ -836,14 +893,14 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [game, romPath, emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<_i9.Process?> launchGameWithHandle(
-    _i2.Game? game,
+  _i8.Future<_i10.Process?> launchGameWithHandle(
+    _i3.Game? game,
     String? romPath,
     String? emulatorId,
     String? exePath, {
@@ -855,12 +912,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [game, romPath, emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<_i9.Process?>.value(),
+            returnValue: _i8.Future<_i10.Process?>.value(),
           )
-          as _i7.Future<_i9.Process?>);
+          as _i8.Future<_i10.Process?>);
 
   @override
-  _i7.Future<void> launchStandalone(
+  _i8.Future<void> launchStandalone(
     String? emulatorId,
     String? exePath, {
     List<String>? args = const [],
@@ -871,36 +928,36 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> deleteRom(_i2.Game? game) =>
+  _i8.Future<void> deleteRom(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRom, [game]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 }
 
 /// A class which mocks [StrategyRegistry].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockStrategyRegistry extends _i1.Mock implements _i11.StrategyRegistry {
+class MockStrategyRegistry extends _i1.Mock implements _i12.StrategyRegistry {
   MockStrategyRegistry() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  Map<String, List<_i12.EmulatorStrategy>> detectConflicts() =>
+  Map<String, List<_i13.EmulatorStrategy>> detectConflicts() =>
       (super.noSuchMethod(
             Invocation.method(#detectConflicts, []),
-            returnValue: <String, List<_i12.EmulatorStrategy>>{},
+            returnValue: <String, List<_i13.EmulatorStrategy>>{},
           )
-          as Map<String, List<_i12.EmulatorStrategy>>);
+          as Map<String, List<_i13.EmulatorStrategy>>);
 
   @override
   String? getPreferredEmulatorId(String? slug) =>
@@ -908,34 +965,34 @@ class MockStrategyRegistry extends _i1.Mock implements _i11.StrategyRegistry {
           as String?);
 
   @override
-  _i7.Future<void> setPreference(String? canonicalSlug, String? emulatorId) =>
+  _i8.Future<void> setPreference(String? canonicalSlug, String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#setPreference, [canonicalSlug, emulatorId]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> clearPreferences() =>
+  _i8.Future<void> clearPreferences() =>
       (super.noSuchMethod(
             Invocation.method(#clearPreferences, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i12.EmulatorStrategy? getStrategyForSlug(String? platformSlug) =>
+  _i13.EmulatorStrategy? getStrategyForSlug(String? platformSlug) =>
       (super.noSuchMethod(
             Invocation.method(#getStrategyForSlug, [platformSlug]),
           )
-          as _i12.EmulatorStrategy?);
+          as _i13.EmulatorStrategy?);
 
   @override
-  _i12.EmulatorStrategy? getStrategyById(String? id) =>
+  _i13.EmulatorStrategy? getStrategyById(String? id) =>
       (super.noSuchMethod(Invocation.method(#getStrategyById, [id]))
-          as _i12.EmulatorStrategy?);
+          as _i13.EmulatorStrategy?);
 
   @override
   void setNdsCore(String? core) => super.noSuchMethod(
diff --git a/test/unit/paginated_games_provider_test.mocks.dart b/test/unit/paginated_games_provider_test.mocks.dart
index cdd2797..a2138c4 100644
--- a/test/unit/paginated_games_provider_test.mocks.dart
+++ b/test/unit/paginated_games_provider_test.mocks.dart
@@ -3,15 +3,16 @@
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i5;
-import 'dart:io' as _i7;
-import 'dart:typed_data' as _i8;
+import 'dart:async' as _i6;
+import 'dart:io' as _i8;
+import 'dart:typed_data' as _i9;
 
-import 'package:freegosy/core/romm/romm_models.dart' as _i2;
-import 'package:freegosy/core/romm/romm_service.dart' as _i3;
+import 'package:flutter/foundation.dart' as _i2;
+import 'package:freegosy/core/romm/romm_models.dart' as _i3;
+import 'package:freegosy/core/romm/romm_service.dart' as _i4;
 import 'package:mockito/mockito.dart' as _i1;
-import 'package:mockito/src/dummies.dart' as _i4;
-import 'package:shared_preferences/shared_preferences.dart' as _i6;
+import 'package:mockito/src/dummies.dart' as _i5;
+import 'package:shared_preferences/shared_preferences.dart' as _i7;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -28,32 +29,49 @@ import 'package:shared_preferences/shared_preferences.dart' as _i6;
 // ignore_for_file: subtype_of_sealed_class
 // ignore_for_file: invalid_use_of_internal_member
 
-class _FakeRomMConfig_0 extends _i1.SmartFake implements _i2.RomMConfig {
-  _FakeRomMConfig_0(Object parent, Invocation parentInvocation)
+class _FakeValueNotifier_0<T> extends _i1.SmartFake
+    implements _i2.ValueNotifier<T> {
+  _FakeValueNotifier_0(Object parent, Invocation parentInvocation)
+    : super(parent, parentInvocation);
+}
+
+class _FakeRomMConfig_1 extends _i1.SmartFake implements _i3.RomMConfig {
+  _FakeRomMConfig_1(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
 /// A class which mocks [RommService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockRommService extends _i1.Mock implements _i3.RommService {
+class MockRommService extends _i1.Mock implements _i4.RommService {
   MockRommService() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  _i2.RomMConfig get config =>
+  _i2.ValueNotifier<bool> get isOffline =>
+      (super.noSuchMethod(
+            Invocation.getter(#isOffline),
+            returnValue: _FakeValueNotifier_0<bool>(
+              this,
+              Invocation.getter(#isOffline),
+            ),
+          )
+          as _i2.ValueNotifier<bool>);
+
+  @override
+  _i3.RomMConfig get config =>
       (super.noSuchMethod(
             Invocation.getter(#config),
-            returnValue: _FakeRomMConfig_0(this, Invocation.getter(#config)),
+            returnValue: _FakeRomMConfig_1(this, Invocation.getter(#config)),
           )
-          as _i2.RomMConfig);
+          as _i3.RomMConfig);
 
   @override
   String get authHeader =>
       (super.noSuchMethod(
             Invocation.getter(#authHeader),
-            returnValue: _i4.dummyValue<String>(
+            returnValue: _i5.dummyValue<String>(
               this,
               Invocation.getter(#authHeader),
             ),
@@ -61,93 +79,107 @@ class MockRommService extends _i1.Mock implements _i3.RommService {
           as String);
 
   @override
-  void updateConfig(_i2.RomMConfig? newConfig) => super.noSuchMethod(
+  void updateConfig(_i3.RomMConfig? newConfig) => super.noSuchMethod(
     Invocation.method(#updateConfig, [newConfig]),
     returnValueForMissingStub: null,
   );
 
   @override
-  _i5.Future<void> refreshToken(_i6.SharedPreferences? prefs) =>
+  void startHeartbeat() => super.noSuchMethod(
+    Invocation.method(#startHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  void stopHeartbeat() => super.noSuchMethod(
+    Invocation.method(#stopHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  _i6.Future<void> refreshToken(_i7.SharedPreferences? prefs) =>
       (super.noSuchMethod(
             Invocation.method(#refreshToken, [prefs]),
-            returnValue: _i5.Future<void>.value(),
-            returnValueForMissingStub: _i5.Future<void>.value(),
+            returnValue: _i6.Future<void>.value(),
+            returnValueForMissingStub: _i6.Future<void>.value(),
           )
-          as _i5.Future<void>);
+          as _i6.Future<void>);
 
   @override
-  _i5.Future<_i2.Game?> getGame(String? id) =>
+  _i6.Future<_i3.Game?> getGame(String? id) =>
       (super.noSuchMethod(
             Invocation.method(#getGame, [id]),
-            returnValue: _i5.Future<_i2.Game?>.value(),
+            returnValue: _i6.Future<_i3.Game?>.value(),
           )
-          as _i5.Future<_i2.Game?>);
+          as _i6.Future<_i3.Game?>);
 
   @override
-  _i5.Future<List<_i2.Platform>> getPlatforms() =>
+  _i6.Future<List<_i3.Platform>> getPlatforms() =>
       (super.noSuchMethod(
             Invocation.method(#getPlatforms, []),
-            returnValue: _i5.Future<List<_i2.Platform>>.value(<_i2.Platform>[]),
+            returnValue: _i6.Future<List<_i3.Platform>>.value(<_i3.Platform>[]),
           )
-          as _i5.Future<List<_i2.Platform>>);
+          as _i6.Future<List<_i3.Platform>>);
 
   @override
-  _i5.Future<List<Map<String, dynamic>>> getCollections() =>
+  _i6.Future<List<Map<String, dynamic>>> getCollections() =>
       (super.noSuchMethod(
             Invocation.method(#getCollections, []),
-            returnValue: _i5.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i6.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i5.Future<List<Map<String, dynamic>>>);
+          as _i6.Future<List<Map<String, dynamic>>>);
 
   @override
-  String? resolveCoverUrl(_i2.Game? game) =>
+  String? resolveCoverUrl(_i3.Game? game) =>
       (super.noSuchMethod(Invocation.method(#resolveCoverUrl, [game]))
           as String?);
 
   @override
-  _i5.Future<List<_i2.Game>> getGames(String? platformId) =>
+  _i6.Future<List<_i3.Game>> getGames(String? platformId) =>
       (super.noSuchMethod(
             Invocation.method(#getGames, [platformId]),
-            returnValue: _i5.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i6.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i5.Future<List<_i2.Game>>);
+          as _i6.Future<List<_i3.Game>>);
 
   @override
-  _i5.Future<List<_i2.Game>> getAllGames({String? platformId}) =>
+  _i6.Future<List<_i3.Game>> getAllGames({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getAllGames, [], {#platformId: platformId}),
-            returnValue: _i5.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i6.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i5.Future<List<_i2.Game>>);
+          as _i6.Future<List<_i3.Game>>);
 
   @override
-  _i5.Future<List<_i2.Game>> getRecentlyPlayed({int? limit = 15}) =>
+  _i6.Future<List<_i3.Game>> getRecentlyPlayed({int? limit = 15}) =>
       (super.noSuchMethod(
             Invocation.method(#getRecentlyPlayed, [], {#limit: limit}),
-            returnValue: _i5.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i6.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i5.Future<List<_i2.Game>>);
+          as _i6.Future<List<_i3.Game>>);
 
   @override
-  _i5.Future<List<_i2.Game>> searchRoms({
+  _i6.Future<List<_i3.Game>> searchRoms({
     String? sha1,
     String? md5,
     String? search,
+    String? platformId,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#searchRoms, [], {
               #sha1: sha1,
               #md5: md5,
               #search: search,
+              #platformId: platformId,
             }),
-            returnValue: _i5.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i6.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i5.Future<List<_i2.Game>>);
+          as _i6.Future<List<_i3.Game>>);
 
   @override
-  _i5.Future<({List<_i2.Game> games, int total})> getGamesPage({
+  _i6.Future<({List<_i3.Game> games, int total})> getGamesPage({
     int? offset = 0,
     int? limit = 50,
     String? platformId,
@@ -176,34 +208,34 @@ class MockRommService extends _i1.Mock implements _i3.RommService {
               #withCharIndex: withCharIndex,
               #withFilterValues: withFilterValues,
             }),
-            returnValue: _i5.Future<({List<_i2.Game> games, int total})>.value((
-              games: <_i2.Game>[],
+            returnValue: _i6.Future<({List<_i3.Game> games, int total})>.value((
+              games: <_i3.Game>[],
               total: 0,
             )),
           )
-          as _i5.Future<({List<_i2.Game> games, int total})>);
+          as _i6.Future<({List<_i3.Game> games, int total})>);
 
   @override
-  _i5.Future<_i2.Game?> getRandomGame() =>
+  _i6.Future<_i3.Game?> getRandomGame() =>
       (super.noSuchMethod(
             Invocation.method(#getRandomGame, []),
-            returnValue: _i5.Future<_i2.Game?>.value(),
+            returnValue: _i6.Future<_i3.Game?>.value(),
           )
-          as _i5.Future<_i2.Game?>);
+          as _i6.Future<_i3.Game?>);
 
   @override
-  _i5.Future<List<_i2.SaveFile>> getSaves(String? gameId) =>
+  _i6.Future<List<_i3.SaveFile>> getSaves(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSaves, [gameId]),
-            returnValue: _i5.Future<List<_i2.SaveFile>>.value(<_i2.SaveFile>[]),
+            returnValue: _i6.Future<List<_i3.SaveFile>>.value(<_i3.SaveFile>[]),
           )
-          as _i5.Future<List<_i2.SaveFile>>);
+          as _i6.Future<List<_i3.SaveFile>>);
 
   @override
-  String getDownloadUrl(_i2.Game? game) =>
+  String getDownloadUrl(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getDownloadUrl, [game]),
-            returnValue: _i4.dummyValue<String>(
+            returnValue: _i5.dummyValue<String>(
               this,
               Invocation.method(#getDownloadUrl, [game]),
             ),
@@ -211,11 +243,11 @@ class MockRommService extends _i1.Mock implements _i3.RommService {
           as String);
 
   @override
-  _i5.Future<bool> uploadSave(
+  _i6.Future<bool> uploadSave(
     String? gameId,
-    _i7.File? saveFile, {
+    _i8.File? saveFile, {
     String? slot,
-    _i7.File? screenshotFile,
+    _i8.File? screenshotFile,
     String? overrideFilename,
   }) =>
       (super.noSuchMethod(
@@ -228,73 +260,73 @@ class MockRommService extends _i1.Mock implements _i3.RommService {
                 #overrideFilename: overrideFilename,
               },
             ),
-            returnValue: _i5.Future<bool>.value(false),
+            returnValue: _i6.Future<bool>.value(false),
           )
-          as _i5.Future<bool>);
+          as _i6.Future<bool>);
 
   @override
-  _i5.Future<bool> deleteSaves(List<int>? saveIds) =>
+  _i6.Future<bool> deleteSaves(List<int>? saveIds) =>
       (super.noSuchMethod(
             Invocation.method(#deleteSaves, [saveIds]),
-            returnValue: _i5.Future<bool>.value(false),
+            returnValue: _i6.Future<bool>.value(false),
           )
-          as _i5.Future<bool>);
+          as _i6.Future<bool>);
 
   @override
-  _i5.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
+  _i6.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
       (super.noSuchMethod(
             Invocation.method(
               #pruneOldSaves,
               [gameId],
               {#keepCount: keepCount},
             ),
-            returnValue: _i5.Future<void>.value(),
-            returnValueForMissingStub: _i5.Future<void>.value(),
+            returnValue: _i6.Future<void>.value(),
+            returnValueForMissingStub: _i6.Future<void>.value(),
           )
-          as _i5.Future<void>);
+          as _i6.Future<void>);
 
   @override
-  _i5.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
+  _i6.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSavesList, [gameId]),
-            returnValue: _i5.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i6.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i5.Future<List<Map<String, dynamic>>>);
+          as _i6.Future<List<Map<String, dynamic>>>);
 
   @override
-  _i5.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
+  _i6.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getLatestSave, [gameId]),
-            returnValue: _i5.Future<Map<String, dynamic>?>.value(),
+            returnValue: _i6.Future<Map<String, dynamic>?>.value(),
           )
-          as _i5.Future<Map<String, dynamic>?>);
+          as _i6.Future<Map<String, dynamic>?>);
 
   @override
-  _i5.Future<_i8.Uint8List?> downloadSave(
+  _i6.Future<_i9.Uint8List?> downloadSave(
     String? saveUrl, {
-    _i6.SharedPreferences? prefs,
+    _i7.SharedPreferences? prefs,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#downloadSave, [saveUrl], {#prefs: prefs}),
-            returnValue: _i5.Future<_i8.Uint8List?>.value(),
+            returnValue: _i6.Future<_i9.Uint8List?>.value(),
           )
-          as _i5.Future<_i8.Uint8List?>);
+          as _i6.Future<_i9.Uint8List?>);
 
   @override
-  _i5.Future<List<_i2.Firmware>> getFirmware({String? platformId}) =>
+  _i6.Future<List<_i3.Firmware>> getFirmware({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmware, [], {#platformId: platformId}),
-            returnValue: _i5.Future<List<_i2.Firmware>>.value(<_i2.Firmware>[]),
+            returnValue: _i6.Future<List<_i3.Firmware>>.value(<_i3.Firmware>[]),
           )
-          as _i5.Future<List<_i2.Firmware>>);
+          as _i6.Future<List<_i3.Firmware>>);
 
   @override
-  String getFirmwareDownloadUrl(_i2.Firmware? firmware) =>
+  String getFirmwareDownloadUrl(_i3.Firmware? firmware) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmwareDownloadUrl, [firmware]),
-            returnValue: _i4.dummyValue<String>(
+            returnValue: _i5.dummyValue<String>(
               this,
               Invocation.method(#getFirmwareDownloadUrl, [firmware]),
             ),
@@ -302,8 +334,8 @@ class MockRommService extends _i1.Mock implements _i3.RommService {
           as String);
 
   @override
-  _i5.Future<_i8.Uint8List?> downloadFirmware(
-    _i2.Firmware? firmware, {
+  _i6.Future<_i9.Uint8List?> downloadFirmware(
+    _i3.Firmware? firmware, {
     void Function(int, int)? onProgress,
   }) =>
       (super.noSuchMethod(
@@ -312,14 +344,14 @@ class MockRommService extends _i1.Mock implements _i3.RommService {
               [firmware],
               {#onProgress: onProgress},
             ),
-            returnValue: _i5.Future<_i8.Uint8List?>.value(),
+            returnValue: _i6.Future<_i9.Uint8List?>.value(),
           )
-          as _i5.Future<_i8.Uint8List?>);
+          as _i6.Future<_i9.Uint8List?>);
 
   @override
-  _i5.Future<bool> updateRomProps(
+  _i6.Future<bool> updateRomProps(
     String? romId,
-    _i6.SharedPreferences? prefs, {
+    _i7.SharedPreferences? prefs, {
     bool? backlogged,
     bool? nowPlaying,
     int? rating,
@@ -338,35 +370,35 @@ class MockRommService extends _i1.Mock implements _i3.RommService {
                 #completion: completion,
               },
             ),
-            returnValue: _i5.Future<bool>.value(false),
+            returnValue: _i6.Future<bool>.value(false),
           )
-          as _i5.Future<bool>);
+          as _i6.Future<bool>);
 
   @override
-  _i5.Future<List<_i2.RomNote>> getRomNotes(String? romId) =>
+  _i6.Future<List<_i3.RomNote>> getRomNotes(String? romId) =>
       (super.noSuchMethod(
             Invocation.method(#getRomNotes, [romId]),
-            returnValue: _i5.Future<List<_i2.RomNote>>.value(<_i2.RomNote>[]),
+            returnValue: _i6.Future<List<_i3.RomNote>>.value(<_i3.RomNote>[]),
           )
-          as _i5.Future<List<_i2.RomNote>>);
+          as _i6.Future<List<_i3.RomNote>>);
 
   @override
-  _i5.Future<bool> createRomNote(
+  _i6.Future<bool> createRomNote(
     String? romId,
     String? title,
     String? content,
   ) =>
       (super.noSuchMethod(
             Invocation.method(#createRomNote, [romId, title, content]),
-            returnValue: _i5.Future<bool>.value(false),
+            returnValue: _i6.Future<bool>.value(false),
           )
-          as _i5.Future<bool>);
+          as _i6.Future<bool>);
 
   @override
-  _i5.Future<bool> deleteRomNote(String? romId, int? noteId) =>
+  _i6.Future<bool> deleteRomNote(String? romId, int? noteId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRomNote, [romId, noteId]),
-            returnValue: _i5.Future<bool>.value(false),
+            returnValue: _i6.Future<bool>.value(false),
           )
-          as _i5.Future<bool>);
+          as _i6.Future<bool>);
 }
diff --git a/test/unit/save_sync_service_test.mocks.dart b/test/unit/save_sync_service_test.mocks.dart
index a2054bb..b2e14ec 100644
--- a/test/unit/save_sync_service_test.mocks.dart
+++ b/test/unit/save_sync_service_test.mocks.dart
@@ -3,20 +3,21 @@
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i7;
-import 'dart:io' as _i9;
-import 'dart:typed_data' as _i10;
+import 'dart:async' as _i8;
+import 'dart:io' as _i10;
+import 'dart:typed_data' as _i11;
 
-import 'package:freegosy/core/emulator/emulator_strategy.dart' as _i12;
+import 'package:flutter/foundation.dart' as _i2;
+import 'package:freegosy/core/emulator/emulator_strategy.dart' as _i13;
 import 'package:freegosy/core/emulator/linux_strategies/linux_environment_strategy.dart'
-    as _i4;
-import 'package:freegosy/core/emulator/strategy_registry.dart' as _i11;
-import 'package:freegosy/core/romm/romm_models.dart' as _i2;
-import 'package:freegosy/core/romm/romm_service.dart' as _i5;
-import 'package:freegosy/core/storage/directory_service.dart' as _i3;
+    as _i5;
+import 'package:freegosy/core/emulator/strategy_registry.dart' as _i12;
+import 'package:freegosy/core/romm/romm_models.dart' as _i3;
+import 'package:freegosy/core/romm/romm_service.dart' as _i6;
+import 'package:freegosy/core/storage/directory_service.dart' as _i4;
 import 'package:mockito/mockito.dart' as _i1;
-import 'package:mockito/src/dummies.dart' as _i6;
-import 'package:shared_preferences/shared_preferences.dart' as _i8;
+import 'package:mockito/src/dummies.dart' as _i7;
+import 'package:shared_preferences/shared_preferences.dart' as _i9;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -33,43 +34,60 @@ import 'package:shared_preferences/shared_preferences.dart' as _i8;
 // ignore_for_file: subtype_of_sealed_class
 // ignore_for_file: invalid_use_of_internal_member
 
-class _FakeRomMConfig_0 extends _i1.SmartFake implements _i2.RomMConfig {
-  _FakeRomMConfig_0(Object parent, Invocation parentInvocation)
+class _FakeValueNotifier_0<T> extends _i1.SmartFake
+    implements _i2.ValueNotifier<T> {
+  _FakeValueNotifier_0(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
-class _FakeStorageStatus_1 extends _i1.SmartFake implements _i3.StorageStatus {
-  _FakeStorageStatus_1(Object parent, Invocation parentInvocation)
+class _FakeRomMConfig_1 extends _i1.SmartFake implements _i3.RomMConfig {
+  _FakeRomMConfig_1(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
-class _FakeLinuxEnvironmentStrategy_2 extends _i1.SmartFake
-    implements _i4.LinuxEnvironmentStrategy {
-  _FakeLinuxEnvironmentStrategy_2(Object parent, Invocation parentInvocation)
+class _FakeStorageStatus_2 extends _i1.SmartFake implements _i4.StorageStatus {
+  _FakeStorageStatus_2(Object parent, Invocation parentInvocation)
+    : super(parent, parentInvocation);
+}
+
+class _FakeLinuxEnvironmentStrategy_3 extends _i1.SmartFake
+    implements _i5.LinuxEnvironmentStrategy {
+  _FakeLinuxEnvironmentStrategy_3(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
 /// A class which mocks [RommService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockRommService extends _i1.Mock implements _i5.RommService {
+class MockRommService extends _i1.Mock implements _i6.RommService {
   MockRommService() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  _i2.RomMConfig get config =>
+  _i2.ValueNotifier<bool> get isOffline =>
+      (super.noSuchMethod(
+            Invocation.getter(#isOffline),
+            returnValue: _FakeValueNotifier_0<bool>(
+              this,
+              Invocation.getter(#isOffline),
+            ),
+          )
+          as _i2.ValueNotifier<bool>);
+
+  @override
+  _i3.RomMConfig get config =>
       (super.noSuchMethod(
             Invocation.getter(#config),
-            returnValue: _FakeRomMConfig_0(this, Invocation.getter(#config)),
+            returnValue: _FakeRomMConfig_1(this, Invocation.getter(#config)),
           )
-          as _i2.RomMConfig);
+          as _i3.RomMConfig);
 
   @override
   String get authHeader =>
       (super.noSuchMethod(
             Invocation.getter(#authHeader),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#authHeader),
             ),
@@ -77,93 +95,107 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  void updateConfig(_i2.RomMConfig? newConfig) => super.noSuchMethod(
+  void updateConfig(_i3.RomMConfig? newConfig) => super.noSuchMethod(
     Invocation.method(#updateConfig, [newConfig]),
     returnValueForMissingStub: null,
   );
 
   @override
-  _i7.Future<void> refreshToken(_i8.SharedPreferences? prefs) =>
+  void startHeartbeat() => super.noSuchMethod(
+    Invocation.method(#startHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  void stopHeartbeat() => super.noSuchMethod(
+    Invocation.method(#stopHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  _i8.Future<void> refreshToken(_i9.SharedPreferences? prefs) =>
       (super.noSuchMethod(
             Invocation.method(#refreshToken, [prefs]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<_i2.Game?> getGame(String? id) =>
+  _i8.Future<_i3.Game?> getGame(String? id) =>
       (super.noSuchMethod(
             Invocation.method(#getGame, [id]),
-            returnValue: _i7.Future<_i2.Game?>.value(),
+            returnValue: _i8.Future<_i3.Game?>.value(),
           )
-          as _i7.Future<_i2.Game?>);
+          as _i8.Future<_i3.Game?>);
 
   @override
-  _i7.Future<List<_i2.Platform>> getPlatforms() =>
+  _i8.Future<List<_i3.Platform>> getPlatforms() =>
       (super.noSuchMethod(
             Invocation.method(#getPlatforms, []),
-            returnValue: _i7.Future<List<_i2.Platform>>.value(<_i2.Platform>[]),
+            returnValue: _i8.Future<List<_i3.Platform>>.value(<_i3.Platform>[]),
           )
-          as _i7.Future<List<_i2.Platform>>);
+          as _i8.Future<List<_i3.Platform>>);
 
   @override
-  _i7.Future<List<Map<String, dynamic>>> getCollections() =>
+  _i8.Future<List<Map<String, dynamic>>> getCollections() =>
       (super.noSuchMethod(
             Invocation.method(#getCollections, []),
-            returnValue: _i7.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i8.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i7.Future<List<Map<String, dynamic>>>);
+          as _i8.Future<List<Map<String, dynamic>>>);
 
   @override
-  String? resolveCoverUrl(_i2.Game? game) =>
+  String? resolveCoverUrl(_i3.Game? game) =>
       (super.noSuchMethod(Invocation.method(#resolveCoverUrl, [game]))
           as String?);
 
   @override
-  _i7.Future<List<_i2.Game>> getGames(String? platformId) =>
+  _i8.Future<List<_i3.Game>> getGames(String? platformId) =>
       (super.noSuchMethod(
             Invocation.method(#getGames, [platformId]),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> getAllGames({String? platformId}) =>
+  _i8.Future<List<_i3.Game>> getAllGames({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getAllGames, [], {#platformId: platformId}),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> getRecentlyPlayed({int? limit = 15}) =>
+  _i8.Future<List<_i3.Game>> getRecentlyPlayed({int? limit = 15}) =>
       (super.noSuchMethod(
             Invocation.method(#getRecentlyPlayed, [], {#limit: limit}),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> searchRoms({
+  _i8.Future<List<_i3.Game>> searchRoms({
     String? sha1,
     String? md5,
     String? search,
+    String? platformId,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#searchRoms, [], {
               #sha1: sha1,
               #md5: md5,
               #search: search,
+              #platformId: platformId,
             }),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<({List<_i2.Game> games, int total})> getGamesPage({
+  _i8.Future<({List<_i3.Game> games, int total})> getGamesPage({
     int? offset = 0,
     int? limit = 50,
     String? platformId,
@@ -192,34 +224,34 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
               #withCharIndex: withCharIndex,
               #withFilterValues: withFilterValues,
             }),
-            returnValue: _i7.Future<({List<_i2.Game> games, int total})>.value((
-              games: <_i2.Game>[],
+            returnValue: _i8.Future<({List<_i3.Game> games, int total})>.value((
+              games: <_i3.Game>[],
               total: 0,
             )),
           )
-          as _i7.Future<({List<_i2.Game> games, int total})>);
+          as _i8.Future<({List<_i3.Game> games, int total})>);
 
   @override
-  _i7.Future<_i2.Game?> getRandomGame() =>
+  _i8.Future<_i3.Game?> getRandomGame() =>
       (super.noSuchMethod(
             Invocation.method(#getRandomGame, []),
-            returnValue: _i7.Future<_i2.Game?>.value(),
+            returnValue: _i8.Future<_i3.Game?>.value(),
           )
-          as _i7.Future<_i2.Game?>);
+          as _i8.Future<_i3.Game?>);
 
   @override
-  _i7.Future<List<_i2.SaveFile>> getSaves(String? gameId) =>
+  _i8.Future<List<_i3.SaveFile>> getSaves(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSaves, [gameId]),
-            returnValue: _i7.Future<List<_i2.SaveFile>>.value(<_i2.SaveFile>[]),
+            returnValue: _i8.Future<List<_i3.SaveFile>>.value(<_i3.SaveFile>[]),
           )
-          as _i7.Future<List<_i2.SaveFile>>);
+          as _i8.Future<List<_i3.SaveFile>>);
 
   @override
-  String getDownloadUrl(_i2.Game? game) =>
+  String getDownloadUrl(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getDownloadUrl, [game]),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.method(#getDownloadUrl, [game]),
             ),
@@ -227,11 +259,11 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  _i7.Future<bool> uploadSave(
+  _i8.Future<bool> uploadSave(
     String? gameId,
-    _i9.File? saveFile, {
+    _i10.File? saveFile, {
     String? slot,
-    _i9.File? screenshotFile,
+    _i10.File? screenshotFile,
     String? overrideFilename,
   }) =>
       (super.noSuchMethod(
@@ -244,73 +276,73 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
                 #overrideFilename: overrideFilename,
               },
             ),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> deleteSaves(List<int>? saveIds) =>
+  _i8.Future<bool> deleteSaves(List<int>? saveIds) =>
       (super.noSuchMethod(
             Invocation.method(#deleteSaves, [saveIds]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
+  _i8.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
       (super.noSuchMethod(
             Invocation.method(
               #pruneOldSaves,
               [gameId],
               {#keepCount: keepCount},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
+  _i8.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSavesList, [gameId]),
-            returnValue: _i7.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i8.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i7.Future<List<Map<String, dynamic>>>);
+          as _i8.Future<List<Map<String, dynamic>>>);
 
   @override
-  _i7.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
+  _i8.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getLatestSave, [gameId]),
-            returnValue: _i7.Future<Map<String, dynamic>?>.value(),
+            returnValue: _i8.Future<Map<String, dynamic>?>.value(),
           )
-          as _i7.Future<Map<String, dynamic>?>);
+          as _i8.Future<Map<String, dynamic>?>);
 
   @override
-  _i7.Future<_i10.Uint8List?> downloadSave(
+  _i8.Future<_i11.Uint8List?> downloadSave(
     String? saveUrl, {
-    _i8.SharedPreferences? prefs,
+    _i9.SharedPreferences? prefs,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#downloadSave, [saveUrl], {#prefs: prefs}),
-            returnValue: _i7.Future<_i10.Uint8List?>.value(),
+            returnValue: _i8.Future<_i11.Uint8List?>.value(),
           )
-          as _i7.Future<_i10.Uint8List?>);
+          as _i8.Future<_i11.Uint8List?>);
 
   @override
-  _i7.Future<List<_i2.Firmware>> getFirmware({String? platformId}) =>
+  _i8.Future<List<_i3.Firmware>> getFirmware({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmware, [], {#platformId: platformId}),
-            returnValue: _i7.Future<List<_i2.Firmware>>.value(<_i2.Firmware>[]),
+            returnValue: _i8.Future<List<_i3.Firmware>>.value(<_i3.Firmware>[]),
           )
-          as _i7.Future<List<_i2.Firmware>>);
+          as _i8.Future<List<_i3.Firmware>>);
 
   @override
-  String getFirmwareDownloadUrl(_i2.Firmware? firmware) =>
+  String getFirmwareDownloadUrl(_i3.Firmware? firmware) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmwareDownloadUrl, [firmware]),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.method(#getFirmwareDownloadUrl, [firmware]),
             ),
@@ -318,8 +350,8 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  _i7.Future<_i10.Uint8List?> downloadFirmware(
-    _i2.Firmware? firmware, {
+  _i8.Future<_i11.Uint8List?> downloadFirmware(
+    _i3.Firmware? firmware, {
     void Function(int, int)? onProgress,
   }) =>
       (super.noSuchMethod(
@@ -328,14 +360,14 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
               [firmware],
               {#onProgress: onProgress},
             ),
-            returnValue: _i7.Future<_i10.Uint8List?>.value(),
+            returnValue: _i8.Future<_i11.Uint8List?>.value(),
           )
-          as _i7.Future<_i10.Uint8List?>);
+          as _i8.Future<_i11.Uint8List?>);
 
   @override
-  _i7.Future<bool> updateRomProps(
+  _i8.Future<bool> updateRomProps(
     String? romId,
-    _i8.SharedPreferences? prefs, {
+    _i9.SharedPreferences? prefs, {
     bool? backlogged,
     bool? nowPlaying,
     int? rating,
@@ -354,43 +386,43 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
                 #completion: completion,
               },
             ),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<List<_i2.RomNote>> getRomNotes(String? romId) =>
+  _i8.Future<List<_i3.RomNote>> getRomNotes(String? romId) =>
       (super.noSuchMethod(
             Invocation.method(#getRomNotes, [romId]),
-            returnValue: _i7.Future<List<_i2.RomNote>>.value(<_i2.RomNote>[]),
+            returnValue: _i8.Future<List<_i3.RomNote>>.value(<_i3.RomNote>[]),
           )
-          as _i7.Future<List<_i2.RomNote>>);
+          as _i8.Future<List<_i3.RomNote>>);
 
   @override
-  _i7.Future<bool> createRomNote(
+  _i8.Future<bool> createRomNote(
     String? romId,
     String? title,
     String? content,
   ) =>
       (super.noSuchMethod(
             Invocation.method(#createRomNote, [romId, title, content]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> deleteRomNote(String? romId, int? noteId) =>
+  _i8.Future<bool> deleteRomNote(String? romId, int? noteId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRomNote, [romId, noteId]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 }
 
 /// A class which mocks [DirectoryService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
+class MockDirectoryService extends _i1.Mock implements _i4.DirectoryService {
   MockDirectoryService() {
     _i1.throwOnMissingStub(this);
   }
@@ -399,7 +431,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get romsRootPath =>
       (super.noSuchMethod(
             Invocation.getter(#romsRootPath),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#romsRootPath),
             ),
@@ -410,7 +442,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get emulatorsRootPath =>
       (super.noSuchMethod(
             Invocation.getter(#emulatorsRootPath),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#emulatorsRootPath),
             ),
@@ -421,7 +453,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get linuxSyncPreset =>
       (super.noSuchMethod(
             Invocation.getter(#linuxSyncPreset),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#linuxSyncPreset),
             ),
@@ -429,12 +461,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as String);
 
   @override
-  _i3.StorageStatus get status =>
+  _i4.StorageStatus get status =>
       (super.noSuchMethod(
             Invocation.getter(#status),
-            returnValue: _FakeStorageStatus_1(this, Invocation.getter(#status)),
+            returnValue: _FakeStorageStatus_2(this, Invocation.getter(#status)),
           )
-          as _i3.StorageStatus);
+          as _i4.StorageStatus);
 
   @override
   bool get isSteamDeck =>
@@ -442,15 +474,15 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as bool);
 
   @override
-  _i4.LinuxEnvironmentStrategy get activeLinuxEnvironment =>
+  _i5.LinuxEnvironmentStrategy get activeLinuxEnvironment =>
       (super.noSuchMethod(
             Invocation.getter(#activeLinuxEnvironment),
-            returnValue: _FakeLinuxEnvironmentStrategy_2(
+            returnValue: _FakeLinuxEnvironmentStrategy_3(
               this,
               Invocation.getter(#activeLinuxEnvironment),
             ),
           )
-          as _i4.LinuxEnvironmentStrategy);
+          as _i5.LinuxEnvironmentStrategy);
 
   @override
   set romsRootPath(String? value) => super.noSuchMethod(
@@ -477,77 +509,77 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   );
 
   @override
-  set status(_i3.StorageStatus? value) => super.noSuchMethod(
+  set status(_i4.StorageStatus? value) => super.noSuchMethod(
     Invocation.setter(#status, value),
     returnValueForMissingStub: null,
   );
 
   @override
-  _i7.Future<String?> detectEmuDeckRoot() =>
+  _i8.Future<String?> detectEmuDeckRoot() =>
       (super.noSuchMethod(
             Invocation.method(#detectEmuDeckRoot, []),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<_i3.StorageStatus> initialize() =>
+  _i8.Future<_i4.StorageStatus> initialize() =>
       (super.noSuchMethod(
             Invocation.method(#initialize, []),
-            returnValue: _i7.Future<_i3.StorageStatus>.value(
-              _FakeStorageStatus_1(this, Invocation.method(#initialize, [])),
+            returnValue: _i8.Future<_i4.StorageStatus>.value(
+              _FakeStorageStatus_2(this, Invocation.method(#initialize, [])),
             ),
           )
-          as _i7.Future<_i3.StorageStatus>);
+          as _i8.Future<_i4.StorageStatus>);
 
   @override
-  _i7.Future<String> getDefaultBase() =>
+  _i8.Future<String> getDefaultBase() =>
       (super.noSuchMethod(
             Invocation.method(#getDefaultBase, []),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getDefaultBase, []),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<void> resetRomsRoot() =>
+  _i8.Future<void> resetRomsRoot() =>
       (super.noSuchMethod(
             Invocation.method(#resetRomsRoot, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> resetEmulatorsRoot() =>
+  _i8.Future<void> resetEmulatorsRoot() =>
       (super.noSuchMethod(
             Invocation.method(#resetEmulatorsRoot, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setLinuxSyncPreset(String? preset) =>
+  _i8.Future<void> setLinuxSyncPreset(String? preset) =>
       (super.noSuchMethod(
             Invocation.method(#setLinuxSyncPreset, [preset]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setEmudeckRoot(String? path) =>
+  _i8.Future<void> setEmudeckRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmudeckRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
   void loadEmulatorPathOverrides() => super.noSuchMethod(
@@ -556,13 +588,30 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   );
 
   @override
-  _i7.Future<void> setEmulatorPathOverride(String? emulatorId, String? path) =>
+  _i8.Future<void> setEmulatorPathOverride(String? emulatorId, String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmulatorPathOverride, [emulatorId, path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
+          )
+          as _i8.Future<void>);
+
+  @override
+  _i8.Future<String?> getEmulatorUrlOverride(String? emulatorId) =>
+      (super.noSuchMethod(
+            Invocation.method(#getEmulatorUrlOverride, [emulatorId]),
+            returnValue: _i8.Future<String?>.value(),
+          )
+          as _i8.Future<String?>);
+
+  @override
+  _i8.Future<void> setEmulatorUrlOverride(String? emulatorId, String? url) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmulatorUrlOverride, [emulatorId, url]),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
   String? getEmulatorPathOverride(String? emulatorId) =>
@@ -572,111 +621,119 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as String?);
 
   @override
-  _i7.Future<void> setRomsRoot(String? path) =>
+  _i8.Future<void> setRomsRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setRomsRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setEmulatorsRoot(String? path) =>
+  _i8.Future<void> setEmulatorsRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmulatorsRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
+          )
+          as _i8.Future<void>);
+
+  @override
+  bool platformSupportsArchive(String? platformSlug) =>
+      (super.noSuchMethod(
+            Invocation.method(#platformSupportsArchive, [platformSlug]),
+            returnValue: false,
           )
-          as _i7.Future<void>);
+          as bool);
 
   @override
-  _i7.Future<String> getRomsDirectory() =>
+  _i8.Future<String> getRomsDirectory() =>
       (super.noSuchMethod(
             Invocation.method(#getRomsDirectory, []),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomsDirectory, []),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<Set<String>> getAllDownloadedFileNames() =>
+  _i8.Future<Set<String>> getAllDownloadedFileNames() =>
       (super.noSuchMethod(
             Invocation.method(#getAllDownloadedFileNames, []),
-            returnValue: _i7.Future<Set<String>>.value(<String>{}),
+            returnValue: _i8.Future<Set<String>>.value(<String>{}),
           )
-          as _i7.Future<Set<String>>);
+          as _i8.Future<Set<String>>);
 
   @override
-  _i7.Future<Map<String, Set<String>>> getAllDownloadedFileNamesByPlatform() =>
+  _i8.Future<Map<String, Set<String>>> getAllDownloadedFileNamesByPlatform() =>
       (super.noSuchMethod(
             Invocation.method(#getAllDownloadedFileNamesByPlatform, []),
-            returnValue: _i7.Future<Map<String, Set<String>>>.value(
+            returnValue: _i8.Future<Map<String, Set<String>>>.value(
               <String, Set<String>>{},
             ),
           )
-          as _i7.Future<Map<String, Set<String>>>);
+          as _i8.Future<Map<String, Set<String>>>);
 
   @override
-  _i7.Future<String> getRomDirectory(_i2.Game? game) =>
+  _i8.Future<String> getRomDirectory(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getRomDirectory, [game]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomDirectory, [game]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getRomFilePath(_i2.Game? game) =>
+  _i8.Future<String> getRomFilePath(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getRomFilePath, [game]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomFilePath, [game]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String?> findExistingRomPath(_i2.Game? game) =>
+  _i8.Future<String?> findExistingRomPath(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#findExistingRomPath, [game]),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<String?> resolveSevenZipPath() =>
+  _i8.Future<String?> resolveSevenZipPath() =>
       (super.noSuchMethod(
             Invocation.method(#resolveSevenZipPath, []),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<String> getEmulatorDirectory(String? emulatorId) =>
+  _i8.Future<String> getEmulatorDirectory(String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#getEmulatorDirectory, [emulatorId]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getEmulatorDirectory, [emulatorId]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorAppSupportDirectory(
+  _i8.Future<String> getEmulatorAppSupportDirectory(
     String? emulatorName, {
     String? platformSlug,
   }) =>
@@ -686,8 +743,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorName],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorAppSupportDirectory,
@@ -697,10 +754,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorBiosDirectory(
+  _i8.Future<String> getEmulatorBiosDirectory(
     String? emulatorId, {
     String? platformSlug,
   }) =>
@@ -710,8 +767,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorBiosDirectory,
@@ -721,10 +778,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorSystemDirectory(
+  _i8.Future<String> getEmulatorSystemDirectory(
     String? emulatorId, {
     String? platformSlug,
   }) =>
@@ -734,8 +791,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorSystemDirectory,
@@ -745,19 +802,19 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<void> deleteEmulator(String? emulatorId) =>
+  _i8.Future<void> deleteEmulator(String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteEmulator, [emulatorId]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<String> getEmulatorExecutable(
+  _i8.Future<String> getEmulatorExecutable(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -766,8 +823,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getEmulatorExecutable, [
                   emulatorId,
@@ -776,10 +833,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String?> findEmulatorExecutable(
+  _i8.Future<String?> findEmulatorExecutable(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -788,12 +845,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<bool> isEmulatorInstalled(
+  _i8.Future<bool> isEmulatorInstalled(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -802,17 +859,17 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> isRomDownloaded(_i2.Game? game) =>
+  _i8.Future<bool> isRomDownloaded(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#isRomDownloaded, [game]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
   bool isEmuLaunchScript(String? path) =>
@@ -823,8 +880,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as bool);
 
   @override
-  _i7.Future<void> launchGame(
-    _i2.Game? game,
+  _i8.Future<void> launchGame(
+    _i3.Game? game,
     String? romPath,
     String? emulatorId,
     String? exePath, {
@@ -836,14 +893,14 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [game, romPath, emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<_i9.Process?> launchGameWithHandle(
-    _i2.Game? game,
+  _i8.Future<_i10.Process?> launchGameWithHandle(
+    _i3.Game? game,
     String? romPath,
     String? emulatorId,
     String? exePath, {
@@ -855,12 +912,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [game, romPath, emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<_i9.Process?>.value(),
+            returnValue: _i8.Future<_i10.Process?>.value(),
           )
-          as _i7.Future<_i9.Process?>);
+          as _i8.Future<_i10.Process?>);
 
   @override
-  _i7.Future<void> launchStandalone(
+  _i8.Future<void> launchStandalone(
     String? emulatorId,
     String? exePath, {
     List<String>? args = const [],
@@ -871,36 +928,36 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> deleteRom(_i2.Game? game) =>
+  _i8.Future<void> deleteRom(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRom, [game]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 }
 
 /// A class which mocks [StrategyRegistry].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockStrategyRegistry extends _i1.Mock implements _i11.StrategyRegistry {
+class MockStrategyRegistry extends _i1.Mock implements _i12.StrategyRegistry {
   MockStrategyRegistry() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  Map<String, List<_i12.EmulatorStrategy>> detectConflicts() =>
+  Map<String, List<_i13.EmulatorStrategy>> detectConflicts() =>
       (super.noSuchMethod(
             Invocation.method(#detectConflicts, []),
-            returnValue: <String, List<_i12.EmulatorStrategy>>{},
+            returnValue: <String, List<_i13.EmulatorStrategy>>{},
           )
-          as Map<String, List<_i12.EmulatorStrategy>>);
+          as Map<String, List<_i13.EmulatorStrategy>>);
 
   @override
   String? getPreferredEmulatorId(String? slug) =>
@@ -908,34 +965,34 @@ class MockStrategyRegistry extends _i1.Mock implements _i11.StrategyRegistry {
           as String?);
 
   @override
-  _i7.Future<void> setPreference(String? canonicalSlug, String? emulatorId) =>
+  _i8.Future<void> setPreference(String? canonicalSlug, String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#setPreference, [canonicalSlug, emulatorId]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> clearPreferences() =>
+  _i8.Future<void> clearPreferences() =>
       (super.noSuchMethod(
             Invocation.method(#clearPreferences, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i12.EmulatorStrategy? getStrategyForSlug(String? platformSlug) =>
+  _i13.EmulatorStrategy? getStrategyForSlug(String? platformSlug) =>
       (super.noSuchMethod(
             Invocation.method(#getStrategyForSlug, [platformSlug]),
           )
-          as _i12.EmulatorStrategy?);
+          as _i13.EmulatorStrategy?);
 
   @override
-  _i12.EmulatorStrategy? getStrategyById(String? id) =>
+  _i13.EmulatorStrategy? getStrategyById(String? id) =>
       (super.noSuchMethod(Invocation.method(#getStrategyById, [id]))
-          as _i12.EmulatorStrategy?);
+          as _i13.EmulatorStrategy?);
 
   @override
   void setNdsCore(String? core) => super.noSuchMethod(
diff --git a/test/unit/strategy_registry_test.mocks.dart b/test/unit/strategy_registry_test.mocks.dart
index b0c5fc7..8c464e6 100644
--- a/test/unit/strategy_registry_test.mocks.dart
+++ b/test/unit/strategy_registry_test.mocks.dart
@@ -216,6 +216,23 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
           )
           as _i5.Future<void>);
 
+  @override
+  _i5.Future<String?> getEmulatorUrlOverride(String? emulatorId) =>
+      (super.noSuchMethod(
+            Invocation.method(#getEmulatorUrlOverride, [emulatorId]),
+            returnValue: _i5.Future<String?>.value(),
+          )
+          as _i5.Future<String?>);
+
+  @override
+  _i5.Future<void> setEmulatorUrlOverride(String? emulatorId, String? url) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmulatorUrlOverride, [emulatorId, url]),
+            returnValue: _i5.Future<void>.value(),
+            returnValueForMissingStub: _i5.Future<void>.value(),
+          )
+          as _i5.Future<void>);
+
   @override
   String? getEmulatorPathOverride(String? emulatorId) =>
       (super.noSuchMethod(
@@ -241,6 +258,14 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
           )
           as _i5.Future<void>);
 
+  @override
+  bool platformSupportsArchive(String? platformSlug) =>
+      (super.noSuchMethod(
+            Invocation.method(#platformSupportsArchive, [platformSlug]),
+            returnValue: false,
+          )
+          as bool);
+
   @override
   _i5.Future<String> getRomsDirectory() =>
       (super.noSuchMethod(
diff --git a/test/widgets/library_screen_test.mocks.dart b/test/widgets/library_screen_test.mocks.dart
index da8dc18..53764f3 100644
--- a/test/widgets/library_screen_test.mocks.dart
+++ b/test/widgets/library_screen_test.mocks.dart
@@ -3,20 +3,20 @@
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i7;
-import 'dart:io' as _i9;
-import 'dart:typed_data' as _i10;
+import 'dart:async' as _i8;
+import 'dart:io' as _i10;
+import 'dart:typed_data' as _i11;
 
+import 'package:flutter/foundation.dart' as _i2;
 import 'package:freegosy/core/emulator/linux_strategies/linux_environment_strategy.dart'
-    as _i4;
-import 'package:flutter/material.dart' as _i6;
-import 'package:freegosy/core/romm/romm_models.dart' as _i2;
-import 'package:freegosy/core/romm/romm_service.dart' as _i5;
-import 'package:freegosy/core/storage/directory_service.dart' as _i3;
-import 'package:freegosy/core/storage/rom_mapping_service.dart' as _i11;
+    as _i5;
+import 'package:freegosy/core/romm/romm_models.dart' as _i3;
+import 'package:freegosy/core/romm/romm_service.dart' as _i6;
+import 'package:freegosy/core/storage/directory_service.dart' as _i4;
+import 'package:freegosy/core/storage/rom_mapping_service.dart' as _i12;
 import 'package:mockito/mockito.dart' as _i1;
-import 'package:mockito/src/dummies.dart' as _i6;
-import 'package:shared_preferences/shared_preferences.dart' as _i8;
+import 'package:mockito/src/dummies.dart' as _i7;
+import 'package:shared_preferences/shared_preferences.dart' as _i9;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -33,46 +33,60 @@ import 'package:shared_preferences/shared_preferences.dart' as _i8;
 // ignore_for_file: subtype_of_sealed_class
 // ignore_for_file: invalid_use_of_internal_member
 
-class _FakeRomMConfig_0 extends _i1.SmartFake implements _i2.RomMConfig {
-  _FakeRomMConfig_0(Object parent, Invocation parentInvocation)
+class _FakeValueNotifier_0<T> extends _i1.SmartFake
+    implements _i2.ValueNotifier<T> {
+  _FakeValueNotifier_0(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
-class _FakeStorageStatus_1 extends _i1.SmartFake implements _i3.StorageStatus {
-  _FakeStorageStatus_1(Object parent, Invocation parentInvocation)
+class _FakeRomMConfig_1 extends _i1.SmartFake implements _i3.RomMConfig {
+  _FakeRomMConfig_1(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
-class _FakeLinuxEnvironmentStrategy_2 extends _i1.SmartFake
-    implements _i4.LinuxEnvironmentStrategy {
-  _FakeLinuxEnvironmentStrategy_2(Object parent, Invocation parentInvocation)
+class _FakeStorageStatus_2 extends _i1.SmartFake implements _i4.StorageStatus {
+  _FakeStorageStatus_2(Object parent, Invocation parentInvocation)
+    : super(parent, parentInvocation);
+}
+
+class _FakeLinuxEnvironmentStrategy_3 extends _i1.SmartFake
+    implements _i5.LinuxEnvironmentStrategy {
+  _FakeLinuxEnvironmentStrategy_3(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
 /// A class which mocks [RommService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockRommService extends _i1.Mock implements _i5.RommService {
+class MockRommService extends _i1.Mock implements _i6.RommService {
   MockRommService() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  final _i6.ValueNotifier<bool> isOffline = _i6.ValueNotifier(false);
+  _i2.ValueNotifier<bool> get isOffline =>
+      (super.noSuchMethod(
+            Invocation.getter(#isOffline),
+            returnValue: _FakeValueNotifier_0<bool>(
+              this,
+              Invocation.getter(#isOffline),
+            ),
+          )
+          as _i2.ValueNotifier<bool>);
 
   @override
-  _i2.RomMConfig get config =>
+  _i3.RomMConfig get config =>
       (super.noSuchMethod(
             Invocation.getter(#config),
-            returnValue: _FakeRomMConfig_0(this, Invocation.getter(#config)),
+            returnValue: _FakeRomMConfig_1(this, Invocation.getter(#config)),
           )
-          as _i2.RomMConfig);
+          as _i3.RomMConfig);
 
   @override
   String get authHeader =>
       (super.noSuchMethod(
             Invocation.getter(#authHeader),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#authHeader),
             ),
@@ -80,93 +94,107 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  void updateConfig(_i2.RomMConfig? newConfig) => super.noSuchMethod(
+  void updateConfig(_i3.RomMConfig? newConfig) => super.noSuchMethod(
     Invocation.method(#updateConfig, [newConfig]),
     returnValueForMissingStub: null,
   );
 
   @override
-  _i7.Future<void> refreshToken(_i8.SharedPreferences? prefs) =>
+  void startHeartbeat() => super.noSuchMethod(
+    Invocation.method(#startHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  void stopHeartbeat() => super.noSuchMethod(
+    Invocation.method(#stopHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  _i8.Future<void> refreshToken(_i9.SharedPreferences? prefs) =>
       (super.noSuchMethod(
             Invocation.method(#refreshToken, [prefs]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<_i2.Game?> getGame(String? id) =>
+  _i8.Future<_i3.Game?> getGame(String? id) =>
       (super.noSuchMethod(
             Invocation.method(#getGame, [id]),
-            returnValue: _i7.Future<_i2.Game?>.value(),
+            returnValue: _i8.Future<_i3.Game?>.value(),
           )
-          as _i7.Future<_i2.Game?>);
+          as _i8.Future<_i3.Game?>);
 
   @override
-  _i7.Future<List<_i2.Platform>> getPlatforms() =>
+  _i8.Future<List<_i3.Platform>> getPlatforms() =>
       (super.noSuchMethod(
             Invocation.method(#getPlatforms, []),
-            returnValue: _i7.Future<List<_i2.Platform>>.value(<_i2.Platform>[]),
+            returnValue: _i8.Future<List<_i3.Platform>>.value(<_i3.Platform>[]),
           )
-          as _i7.Future<List<_i2.Platform>>);
+          as _i8.Future<List<_i3.Platform>>);
 
   @override
-  _i7.Future<List<Map<String, dynamic>>> getCollections() =>
+  _i8.Future<List<Map<String, dynamic>>> getCollections() =>
       (super.noSuchMethod(
             Invocation.method(#getCollections, []),
-            returnValue: _i7.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i8.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i7.Future<List<Map<String, dynamic>>>);
+          as _i8.Future<List<Map<String, dynamic>>>);
 
   @override
-  String? resolveCoverUrl(_i2.Game? game) =>
+  String? resolveCoverUrl(_i3.Game? game) =>
       (super.noSuchMethod(Invocation.method(#resolveCoverUrl, [game]))
           as String?);
 
   @override
-  _i7.Future<List<_i2.Game>> getGames(String? platformId) =>
+  _i8.Future<List<_i3.Game>> getGames(String? platformId) =>
       (super.noSuchMethod(
             Invocation.method(#getGames, [platformId]),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> getAllGames({String? platformId}) =>
+  _i8.Future<List<_i3.Game>> getAllGames({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getAllGames, [], {#platformId: platformId}),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> getRecentlyPlayed({int? limit = 15}) =>
+  _i8.Future<List<_i3.Game>> getRecentlyPlayed({int? limit = 15}) =>
       (super.noSuchMethod(
             Invocation.method(#getRecentlyPlayed, [], {#limit: limit}),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<List<_i2.Game>> searchRoms({
+  _i8.Future<List<_i3.Game>> searchRoms({
     String? sha1,
     String? md5,
     String? search,
+    String? platformId,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#searchRoms, [], {
               #sha1: sha1,
               #md5: md5,
               #search: search,
+              #platformId: platformId,
             }),
-            returnValue: _i7.Future<List<_i2.Game>>.value(<_i2.Game>[]),
+            returnValue: _i8.Future<List<_i3.Game>>.value(<_i3.Game>[]),
           )
-          as _i7.Future<List<_i2.Game>>);
+          as _i8.Future<List<_i3.Game>>);
 
   @override
-  _i7.Future<({List<_i2.Game> games, int total})> getGamesPage({
+  _i8.Future<({List<_i3.Game> games, int total})> getGamesPage({
     int? offset = 0,
     int? limit = 50,
     String? platformId,
@@ -195,34 +223,34 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
               #withCharIndex: withCharIndex,
               #withFilterValues: withFilterValues,
             }),
-            returnValue: _i7.Future<({List<_i2.Game> games, int total})>.value((
-              games: <_i2.Game>[],
+            returnValue: _i8.Future<({List<_i3.Game> games, int total})>.value((
+              games: <_i3.Game>[],
               total: 0,
             )),
           )
-          as _i7.Future<({List<_i2.Game> games, int total})>);
+          as _i8.Future<({List<_i3.Game> games, int total})>);
 
   @override
-  _i7.Future<_i2.Game?> getRandomGame() =>
+  _i8.Future<_i3.Game?> getRandomGame() =>
       (super.noSuchMethod(
             Invocation.method(#getRandomGame, []),
-            returnValue: _i7.Future<_i2.Game?>.value(),
+            returnValue: _i8.Future<_i3.Game?>.value(),
           )
-          as _i7.Future<_i2.Game?>);
+          as _i8.Future<_i3.Game?>);
 
   @override
-  _i7.Future<List<_i2.SaveFile>> getSaves(String? gameId) =>
+  _i8.Future<List<_i3.SaveFile>> getSaves(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSaves, [gameId]),
-            returnValue: _i7.Future<List<_i2.SaveFile>>.value(<_i2.SaveFile>[]),
+            returnValue: _i8.Future<List<_i3.SaveFile>>.value(<_i3.SaveFile>[]),
           )
-          as _i7.Future<List<_i2.SaveFile>>);
+          as _i8.Future<List<_i3.SaveFile>>);
 
   @override
-  String getDownloadUrl(_i2.Game? game) =>
+  String getDownloadUrl(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getDownloadUrl, [game]),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.method(#getDownloadUrl, [game]),
             ),
@@ -230,11 +258,11 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  _i7.Future<bool> uploadSave(
+  _i8.Future<bool> uploadSave(
     String? gameId,
-    _i9.File? saveFile, {
+    _i10.File? saveFile, {
     String? slot,
-    _i9.File? screenshotFile,
+    _i10.File? screenshotFile,
     String? overrideFilename,
   }) =>
       (super.noSuchMethod(
@@ -247,73 +275,73 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
                 #overrideFilename: overrideFilename,
               },
             ),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> deleteSaves(List<int>? saveIds) =>
+  _i8.Future<bool> deleteSaves(List<int>? saveIds) =>
       (super.noSuchMethod(
             Invocation.method(#deleteSaves, [saveIds]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
+  _i8.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
       (super.noSuchMethod(
             Invocation.method(
               #pruneOldSaves,
               [gameId],
               {#keepCount: keepCount},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
+  _i8.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSavesList, [gameId]),
-            returnValue: _i7.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i8.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i7.Future<List<Map<String, dynamic>>>);
+          as _i8.Future<List<Map<String, dynamic>>>);
 
   @override
-  _i7.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
+  _i8.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getLatestSave, [gameId]),
-            returnValue: _i7.Future<Map<String, dynamic>?>.value(),
+            returnValue: _i8.Future<Map<String, dynamic>?>.value(),
           )
-          as _i7.Future<Map<String, dynamic>?>);
+          as _i8.Future<Map<String, dynamic>?>);
 
   @override
-  _i7.Future<_i10.Uint8List?> downloadSave(
+  _i8.Future<_i11.Uint8List?> downloadSave(
     String? saveUrl, {
-    _i8.SharedPreferences? prefs,
+    _i9.SharedPreferences? prefs,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#downloadSave, [saveUrl], {#prefs: prefs}),
-            returnValue: _i7.Future<_i10.Uint8List?>.value(),
+            returnValue: _i8.Future<_i11.Uint8List?>.value(),
           )
-          as _i7.Future<_i10.Uint8List?>);
+          as _i8.Future<_i11.Uint8List?>);
 
   @override
-  _i7.Future<List<_i2.Firmware>> getFirmware({String? platformId}) =>
+  _i8.Future<List<_i3.Firmware>> getFirmware({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmware, [], {#platformId: platformId}),
-            returnValue: _i7.Future<List<_i2.Firmware>>.value(<_i2.Firmware>[]),
+            returnValue: _i8.Future<List<_i3.Firmware>>.value(<_i3.Firmware>[]),
           )
-          as _i7.Future<List<_i2.Firmware>>);
+          as _i8.Future<List<_i3.Firmware>>);
 
   @override
-  String getFirmwareDownloadUrl(_i2.Firmware? firmware) =>
+  String getFirmwareDownloadUrl(_i3.Firmware? firmware) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmwareDownloadUrl, [firmware]),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.method(#getFirmwareDownloadUrl, [firmware]),
             ),
@@ -321,8 +349,8 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
           as String);
 
   @override
-  _i7.Future<_i10.Uint8List?> downloadFirmware(
-    _i2.Firmware? firmware, {
+  _i8.Future<_i11.Uint8List?> downloadFirmware(
+    _i3.Firmware? firmware, {
     void Function(int, int)? onProgress,
   }) =>
       (super.noSuchMethod(
@@ -331,14 +359,14 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
               [firmware],
               {#onProgress: onProgress},
             ),
-            returnValue: _i7.Future<_i10.Uint8List?>.value(),
+            returnValue: _i8.Future<_i11.Uint8List?>.value(),
           )
-          as _i7.Future<_i10.Uint8List?>);
+          as _i8.Future<_i11.Uint8List?>);
 
   @override
-  _i7.Future<bool> updateRomProps(
+  _i8.Future<bool> updateRomProps(
     String? romId,
-    _i8.SharedPreferences? prefs, {
+    _i9.SharedPreferences? prefs, {
     bool? backlogged,
     bool? nowPlaying,
     int? rating,
@@ -357,43 +385,43 @@ class MockRommService extends _i1.Mock implements _i5.RommService {
                 #completion: completion,
               },
             ),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<List<_i2.RomNote>> getRomNotes(String? romId) =>
+  _i8.Future<List<_i3.RomNote>> getRomNotes(String? romId) =>
       (super.noSuchMethod(
             Invocation.method(#getRomNotes, [romId]),
-            returnValue: _i7.Future<List<_i2.RomNote>>.value(<_i2.RomNote>[]),
+            returnValue: _i8.Future<List<_i3.RomNote>>.value(<_i3.RomNote>[]),
           )
-          as _i7.Future<List<_i2.RomNote>>);
+          as _i8.Future<List<_i3.RomNote>>);
 
   @override
-  _i7.Future<bool> createRomNote(
+  _i8.Future<bool> createRomNote(
     String? romId,
     String? title,
     String? content,
   ) =>
       (super.noSuchMethod(
             Invocation.method(#createRomNote, [romId, title, content]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> deleteRomNote(String? romId, int? noteId) =>
+  _i8.Future<bool> deleteRomNote(String? romId, int? noteId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRomNote, [romId, noteId]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 }
 
 /// A class which mocks [DirectoryService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
+class MockDirectoryService extends _i1.Mock implements _i4.DirectoryService {
   MockDirectoryService() {
     _i1.throwOnMissingStub(this);
   }
@@ -402,7 +430,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get romsRootPath =>
       (super.noSuchMethod(
             Invocation.getter(#romsRootPath),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#romsRootPath),
             ),
@@ -413,7 +441,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get emulatorsRootPath =>
       (super.noSuchMethod(
             Invocation.getter(#emulatorsRootPath),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#emulatorsRootPath),
             ),
@@ -424,7 +452,7 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   String get linuxSyncPreset =>
       (super.noSuchMethod(
             Invocation.getter(#linuxSyncPreset),
-            returnValue: _i6.dummyValue<String>(
+            returnValue: _i7.dummyValue<String>(
               this,
               Invocation.getter(#linuxSyncPreset),
             ),
@@ -432,12 +460,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as String);
 
   @override
-  _i3.StorageStatus get status =>
+  _i4.StorageStatus get status =>
       (super.noSuchMethod(
             Invocation.getter(#status),
-            returnValue: _FakeStorageStatus_1(this, Invocation.getter(#status)),
+            returnValue: _FakeStorageStatus_2(this, Invocation.getter(#status)),
           )
-          as _i3.StorageStatus);
+          as _i4.StorageStatus);
 
   @override
   bool get isSteamDeck =>
@@ -445,15 +473,15 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as bool);
 
   @override
-  _i4.LinuxEnvironmentStrategy get activeLinuxEnvironment =>
+  _i5.LinuxEnvironmentStrategy get activeLinuxEnvironment =>
       (super.noSuchMethod(
             Invocation.getter(#activeLinuxEnvironment),
-            returnValue: _FakeLinuxEnvironmentStrategy_2(
+            returnValue: _FakeLinuxEnvironmentStrategy_3(
               this,
               Invocation.getter(#activeLinuxEnvironment),
             ),
           )
-          as _i4.LinuxEnvironmentStrategy);
+          as _i5.LinuxEnvironmentStrategy);
 
   @override
   set romsRootPath(String? value) => super.noSuchMethod(
@@ -480,77 +508,77 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   );
 
   @override
-  set status(_i3.StorageStatus? value) => super.noSuchMethod(
+  set status(_i4.StorageStatus? value) => super.noSuchMethod(
     Invocation.setter(#status, value),
     returnValueForMissingStub: null,
   );
 
   @override
-  _i7.Future<String?> detectEmuDeckRoot() =>
+  _i8.Future<String?> detectEmuDeckRoot() =>
       (super.noSuchMethod(
             Invocation.method(#detectEmuDeckRoot, []),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<_i3.StorageStatus> initialize() =>
+  _i8.Future<_i4.StorageStatus> initialize() =>
       (super.noSuchMethod(
             Invocation.method(#initialize, []),
-            returnValue: _i7.Future<_i3.StorageStatus>.value(
-              _FakeStorageStatus_1(this, Invocation.method(#initialize, [])),
+            returnValue: _i8.Future<_i4.StorageStatus>.value(
+              _FakeStorageStatus_2(this, Invocation.method(#initialize, [])),
             ),
           )
-          as _i7.Future<_i3.StorageStatus>);
+          as _i8.Future<_i4.StorageStatus>);
 
   @override
-  _i7.Future<String> getDefaultBase() =>
+  _i8.Future<String> getDefaultBase() =>
       (super.noSuchMethod(
             Invocation.method(#getDefaultBase, []),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getDefaultBase, []),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<void> resetRomsRoot() =>
+  _i8.Future<void> resetRomsRoot() =>
       (super.noSuchMethod(
             Invocation.method(#resetRomsRoot, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> resetEmulatorsRoot() =>
+  _i8.Future<void> resetEmulatorsRoot() =>
       (super.noSuchMethod(
             Invocation.method(#resetEmulatorsRoot, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setLinuxSyncPreset(String? preset) =>
+  _i8.Future<void> setLinuxSyncPreset(String? preset) =>
       (super.noSuchMethod(
             Invocation.method(#setLinuxSyncPreset, [preset]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setEmudeckRoot(String? path) =>
+  _i8.Future<void> setEmudeckRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmudeckRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
   void loadEmulatorPathOverrides() => super.noSuchMethod(
@@ -559,13 +587,30 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
   );
 
   @override
-  _i7.Future<void> setEmulatorPathOverride(String? emulatorId, String? path) =>
+  _i8.Future<void> setEmulatorPathOverride(String? emulatorId, String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmulatorPathOverride, [emulatorId, path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
+          )
+          as _i8.Future<void>);
+
+  @override
+  _i8.Future<String?> getEmulatorUrlOverride(String? emulatorId) =>
+      (super.noSuchMethod(
+            Invocation.method(#getEmulatorUrlOverride, [emulatorId]),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<String?>);
+
+  @override
+  _i8.Future<void> setEmulatorUrlOverride(String? emulatorId, String? url) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmulatorUrlOverride, [emulatorId, url]),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
+          )
+          as _i8.Future<void>);
 
   @override
   String? getEmulatorPathOverride(String? emulatorId) =>
@@ -575,111 +620,119 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as String?);
 
   @override
-  _i7.Future<void> setRomsRoot(String? path) =>
+  _i8.Future<void> setRomsRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setRomsRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setEmulatorsRoot(String? path) =>
+  _i8.Future<void> setEmulatorsRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmulatorsRoot, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
+
+  @override
+  bool platformSupportsArchive(String? platformSlug) =>
+      (super.noSuchMethod(
+            Invocation.method(#platformSupportsArchive, [platformSlug]),
+            returnValue: false,
+          )
+          as bool);
 
   @override
-  _i7.Future<String> getRomsDirectory() =>
+  _i8.Future<String> getRomsDirectory() =>
       (super.noSuchMethod(
             Invocation.method(#getRomsDirectory, []),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomsDirectory, []),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<Set<String>> getAllDownloadedFileNames() =>
+  _i8.Future<Set<String>> getAllDownloadedFileNames() =>
       (super.noSuchMethod(
             Invocation.method(#getAllDownloadedFileNames, []),
-            returnValue: _i7.Future<Set<String>>.value(<String>{}),
+            returnValue: _i8.Future<Set<String>>.value(<String>{}),
           )
-          as _i7.Future<Set<String>>);
+          as _i8.Future<Set<String>>);
 
   @override
-  _i7.Future<Map<String, Set<String>>> getAllDownloadedFileNamesByPlatform() =>
+  _i8.Future<Map<String, Set<String>>> getAllDownloadedFileNamesByPlatform() =>
       (super.noSuchMethod(
             Invocation.method(#getAllDownloadedFileNamesByPlatform, []),
-            returnValue: _i7.Future<Map<String, Set<String>>>.value(
+            returnValue: _i8.Future<Map<String, Set<String>>>.value(
               <String, Set<String>>{},
             ),
           )
-          as _i7.Future<Map<String, Set<String>>>);
+          as _i8.Future<Map<String, Set<String>>>);
 
   @override
-  _i7.Future<String> getRomDirectory(_i2.Game? game) =>
+  _i8.Future<String> getRomDirectory(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getRomDirectory, [game]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomDirectory, [game]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getRomFilePath(_i2.Game? game) =>
+  _i8.Future<String> getRomFilePath(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getRomFilePath, [game]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getRomFilePath, [game]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String?> findExistingRomPath(_i2.Game? game) =>
+  _i8.Future<String?> findExistingRomPath(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#findExistingRomPath, [game]),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<String?> resolveSevenZipPath() =>
+  _i8.Future<String?> resolveSevenZipPath() =>
       (super.noSuchMethod(
             Invocation.method(#resolveSevenZipPath, []),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<String> getEmulatorDirectory(String? emulatorId) =>
+  _i8.Future<String> getEmulatorDirectory(String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#getEmulatorDirectory, [emulatorId]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getEmulatorDirectory, [emulatorId]),
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorAppSupportDirectory(
+  _i8.Future<String> getEmulatorAppSupportDirectory(
     String? emulatorName, {
     String? platformSlug,
   }) =>
@@ -689,8 +742,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorName],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorAppSupportDirectory,
@@ -700,10 +753,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorBiosDirectory(
+  _i8.Future<String> getEmulatorBiosDirectory(
     String? emulatorId, {
     String? platformSlug,
   }) =>
@@ -713,8 +766,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorBiosDirectory,
@@ -724,10 +777,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String> getEmulatorSystemDirectory(
+  _i8.Future<String> getEmulatorSystemDirectory(
     String? emulatorId, {
     String? platformSlug,
   }) =>
@@ -737,8 +790,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorSystemDirectory,
@@ -748,19 +801,19 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<void> deleteEmulator(String? emulatorId) =>
+  _i8.Future<void> deleteEmulator(String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteEmulator, [emulatorId]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<String> getEmulatorExecutable(
+  _i8.Future<String> getEmulatorExecutable(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -769,8 +822,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<String>.value(
-              _i6.dummyValue<String>(
+            returnValue: _i8.Future<String>.value(
+              _i7.dummyValue<String>(
                 this,
                 Invocation.method(#getEmulatorExecutable, [
                   emulatorId,
@@ -779,10 +832,10 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               ),
             ),
           )
-          as _i7.Future<String>);
+          as _i8.Future<String>);
 
   @override
-  _i7.Future<String?> findEmulatorExecutable(
+  _i8.Future<String?> findEmulatorExecutable(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -791,12 +844,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<String?>.value(),
+            returnValue: _i8.Future<String?>.value(),
           )
-          as _i7.Future<String?>);
+          as _i8.Future<String?>);
 
   @override
-  _i7.Future<bool> isEmulatorInstalled(
+  _i8.Future<bool> isEmulatorInstalled(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -805,17 +858,17 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
-  _i7.Future<bool> isRomDownloaded(_i2.Game? game) =>
+  _i8.Future<bool> isRomDownloaded(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#isRomDownloaded, [game]),
-            returnValue: _i7.Future<bool>.value(false),
+            returnValue: _i8.Future<bool>.value(false),
           )
-          as _i7.Future<bool>);
+          as _i8.Future<bool>);
 
   @override
   bool isEmuLaunchScript(String? path) =>
@@ -826,8 +879,8 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
           as bool);
 
   @override
-  _i7.Future<void> launchGame(
-    _i2.Game? game,
+  _i8.Future<void> launchGame(
+    _i3.Game? game,
     String? romPath,
     String? emulatorId,
     String? exePath, {
@@ -839,14 +892,14 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [game, romPath, emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<_i9.Process?> launchGameWithHandle(
-    _i2.Game? game,
+  _i8.Future<_i10.Process?> launchGameWithHandle(
+    _i3.Game? game,
     String? romPath,
     String? emulatorId,
     String? exePath, {
@@ -858,12 +911,12 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [game, romPath, emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<_i9.Process?>.value(),
+            returnValue: _i8.Future<_i10.Process?>.value(),
           )
-          as _i7.Future<_i9.Process?>);
+          as _i8.Future<_i10.Process?>);
 
   @override
-  _i7.Future<void> launchStandalone(
+  _i8.Future<void> launchStandalone(
     String? emulatorId,
     String? exePath, {
     List<String>? args = const [],
@@ -874,37 +927,37 @@ class MockDirectoryService extends _i1.Mock implements _i3.DirectoryService {
               [emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> deleteRom(_i2.Game? game) =>
+  _i8.Future<void> deleteRom(_i3.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRom, [game]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 }
 
 /// A class which mocks [RomMappingService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockRomMappingService extends _i1.Mock implements _i11.RomMappingService {
+class MockRomMappingService extends _i1.Mock implements _i12.RomMappingService {
   MockRomMappingService() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  _i7.Future<void> init() =>
+  _i8.Future<void> init() =>
       (super.noSuchMethod(
             Invocation.method(#init, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
   Map<String, String> getMappings() =>
@@ -915,13 +968,13 @@ class MockRomMappingService extends _i1.Mock implements _i11.RomMappingService {
           as Map<String, String>);
 
   @override
-  _i7.Future<void> updateMapping(String? path, String? romId) =>
+  _i8.Future<void> updateMapping(String? path, String? romId) =>
       (super.noSuchMethod(
             Invocation.method(#updateMapping, [path, romId]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
   Map<String, int> getMTimes() =>
@@ -932,22 +985,22 @@ class MockRomMappingService extends _i1.Mock implements _i11.RomMappingService {
           as Map<String, int>);
 
   @override
-  _i7.Future<void> updateMTime(String? path, int? timestamp) =>
+  _i8.Future<void> updateMTime(String? path, int? timestamp) =>
       (super.noSuchMethod(
             Invocation.method(#updateMTime, [path, timestamp]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> setLastSyncTime(int? timestamp) =>
+  _i8.Future<void> setLastSyncTime(int? timestamp) =>
       (super.noSuchMethod(
             Invocation.method(#setLastSyncTime, [timestamp]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
   String? getRomIdForPath(String? path) =>
@@ -955,20 +1008,20 @@ class MockRomMappingService extends _i1.Mock implements _i11.RomMappingService {
           as String?);
 
   @override
-  _i7.Future<void> removeMapping(String? path) =>
+  _i8.Future<void> removeMapping(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#removeMapping, [path]),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 
   @override
-  _i7.Future<void> clear() =>
+  _i8.Future<void> clear() =>
       (super.noSuchMethod(
             Invocation.method(#clear, []),
-            returnValue: _i7.Future<void>.value(),
-            returnValueForMissingStub: _i7.Future<void>.value(),
+            returnValue: _i8.Future<void>.value(),
+            returnValueForMissingStub: _i8.Future<void>.value(),
           )
-          as _i7.Future<void>);
+          as _i8.Future<void>);
 }
diff --git a/test/widgets/settings_screen_test.mocks.dart b/test/widgets/settings_screen_test.mocks.dart
index 7d137c3..b056927 100644
--- a/test/widgets/settings_screen_test.mocks.dart
+++ b/test/widgets/settings_screen_test.mocks.dart
@@ -3,20 +3,21 @@
 // Do not manually edit this file.
 
 // ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i6;
-import 'dart:io' as _i7;
-import 'dart:typed_data' as _i10;
+import 'dart:async' as _i7;
+import 'dart:io' as _i8;
+import 'dart:typed_data' as _i11;
 
-import 'package:freegosy/core/emulator/emulator_strategy.dart' as _i12;
+import 'package:flutter/foundation.dart' as _i4;
+import 'package:freegosy/core/emulator/emulator_strategy.dart' as _i13;
 import 'package:freegosy/core/emulator/linux_strategies/linux_environment_strategy.dart'
     as _i3;
-import 'package:freegosy/core/emulator/strategy_registry.dart' as _i11;
-import 'package:freegosy/core/romm/romm_models.dart' as _i4;
-import 'package:freegosy/core/romm/romm_service.dart' as _i8;
+import 'package:freegosy/core/emulator/strategy_registry.dart' as _i12;
+import 'package:freegosy/core/romm/romm_models.dart' as _i5;
+import 'package:freegosy/core/romm/romm_service.dart' as _i9;
 import 'package:freegosy/core/storage/directory_service.dart' as _i2;
 import 'package:mockito/mockito.dart' as _i1;
-import 'package:mockito/src/dummies.dart' as _i5;
-import 'package:shared_preferences/shared_preferences.dart' as _i9;
+import 'package:mockito/src/dummies.dart' as _i6;
+import 'package:shared_preferences/shared_preferences.dart' as _i10;
 
 // ignore_for_file: type=lint
 // ignore_for_file: avoid_redundant_argument_values
@@ -44,8 +45,14 @@ class _FakeLinuxEnvironmentStrategy_1 extends _i1.SmartFake
     : super(parent, parentInvocation);
 }
 
-class _FakeRomMConfig_2 extends _i1.SmartFake implements _i4.RomMConfig {
-  _FakeRomMConfig_2(Object parent, Invocation parentInvocation)
+class _FakeValueNotifier_2<T> extends _i1.SmartFake
+    implements _i4.ValueNotifier<T> {
+  _FakeValueNotifier_2(Object parent, Invocation parentInvocation)
+    : super(parent, parentInvocation);
+}
+
+class _FakeRomMConfig_3 extends _i1.SmartFake implements _i5.RomMConfig {
+  _FakeRomMConfig_3(Object parent, Invocation parentInvocation)
     : super(parent, parentInvocation);
 }
 
@@ -61,7 +68,7 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
   String get romsRootPath =>
       (super.noSuchMethod(
             Invocation.getter(#romsRootPath),
-            returnValue: _i5.dummyValue<String>(
+            returnValue: _i6.dummyValue<String>(
               this,
               Invocation.getter(#romsRootPath),
             ),
@@ -72,7 +79,7 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
   String get emulatorsRootPath =>
       (super.noSuchMethod(
             Invocation.getter(#emulatorsRootPath),
-            returnValue: _i5.dummyValue<String>(
+            returnValue: _i6.dummyValue<String>(
               this,
               Invocation.getter(#emulatorsRootPath),
             ),
@@ -83,7 +90,7 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
   String get linuxSyncPreset =>
       (super.noSuchMethod(
             Invocation.getter(#linuxSyncPreset),
-            returnValue: _i5.dummyValue<String>(
+            returnValue: _i6.dummyValue<String>(
               this,
               Invocation.getter(#linuxSyncPreset),
             ),
@@ -145,71 +152,71 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
   );
 
   @override
-  _i6.Future<String?> detectEmuDeckRoot() =>
+  _i7.Future<String?> detectEmuDeckRoot() =>
       (super.noSuchMethod(
             Invocation.method(#detectEmuDeckRoot, []),
-            returnValue: _i6.Future<String?>.value(),
+            returnValue: _i7.Future<String?>.value(),
           )
-          as _i6.Future<String?>);
+          as _i7.Future<String?>);
 
   @override
-  _i6.Future<_i2.StorageStatus> initialize() =>
+  _i7.Future<_i2.StorageStatus> initialize() =>
       (super.noSuchMethod(
             Invocation.method(#initialize, []),
-            returnValue: _i6.Future<_i2.StorageStatus>.value(
+            returnValue: _i7.Future<_i2.StorageStatus>.value(
               _FakeStorageStatus_0(this, Invocation.method(#initialize, [])),
             ),
           )
-          as _i6.Future<_i2.StorageStatus>);
+          as _i7.Future<_i2.StorageStatus>);
 
   @override
-  _i6.Future<String> getDefaultBase() =>
+  _i7.Future<String> getDefaultBase() =>
       (super.noSuchMethod(
             Invocation.method(#getDefaultBase, []),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(#getDefaultBase, []),
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<void> resetRomsRoot() =>
+  _i7.Future<void> resetRomsRoot() =>
       (super.noSuchMethod(
             Invocation.method(#resetRomsRoot, []),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<void> resetEmulatorsRoot() =>
+  _i7.Future<void> resetEmulatorsRoot() =>
       (super.noSuchMethod(
             Invocation.method(#resetEmulatorsRoot, []),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<void> setLinuxSyncPreset(String? preset) =>
+  _i7.Future<void> setLinuxSyncPreset(String? preset) =>
       (super.noSuchMethod(
             Invocation.method(#setLinuxSyncPreset, [preset]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<void> setEmudeckRoot(String? path) =>
+  _i7.Future<void> setEmudeckRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmudeckRoot, [path]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
   void loadEmulatorPathOverrides() => super.noSuchMethod(
@@ -218,13 +225,30 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
   );
 
   @override
-  _i6.Future<void> setEmulatorPathOverride(String? emulatorId, String? path) =>
+  _i7.Future<void> setEmulatorPathOverride(String? emulatorId, String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmulatorPathOverride, [emulatorId, path]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
+
+  @override
+  _i7.Future<String?> getEmulatorUrlOverride(String? emulatorId) =>
+      (super.noSuchMethod(
+            Invocation.method(#getEmulatorUrlOverride, [emulatorId]),
+            returnValue: _i7.Future<String?>.value(),
+          )
+          as _i7.Future<String?>);
+
+  @override
+  _i7.Future<void> setEmulatorUrlOverride(String? emulatorId, String? url) =>
+      (super.noSuchMethod(
+            Invocation.method(#setEmulatorUrlOverride, [emulatorId, url]),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
+          )
+          as _i7.Future<void>);
 
   @override
   String? getEmulatorPathOverride(String? emulatorId) =>
@@ -234,111 +258,119 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
           as String?);
 
   @override
-  _i6.Future<void> setRomsRoot(String? path) =>
+  _i7.Future<void> setRomsRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setRomsRoot, [path]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<void> setEmulatorsRoot(String? path) =>
+  _i7.Future<void> setEmulatorsRoot(String? path) =>
       (super.noSuchMethod(
             Invocation.method(#setEmulatorsRoot, [path]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
+          )
+          as _i7.Future<void>);
+
+  @override
+  bool platformSupportsArchive(String? platformSlug) =>
+      (super.noSuchMethod(
+            Invocation.method(#platformSupportsArchive, [platformSlug]),
+            returnValue: false,
           )
-          as _i6.Future<void>);
+          as bool);
 
   @override
-  _i6.Future<String> getRomsDirectory() =>
+  _i7.Future<String> getRomsDirectory() =>
       (super.noSuchMethod(
             Invocation.method(#getRomsDirectory, []),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(#getRomsDirectory, []),
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<Set<String>> getAllDownloadedFileNames() =>
+  _i7.Future<Set<String>> getAllDownloadedFileNames() =>
       (super.noSuchMethod(
             Invocation.method(#getAllDownloadedFileNames, []),
-            returnValue: _i6.Future<Set<String>>.value(<String>{}),
+            returnValue: _i7.Future<Set<String>>.value(<String>{}),
           )
-          as _i6.Future<Set<String>>);
+          as _i7.Future<Set<String>>);
 
   @override
-  _i6.Future<Map<String, Set<String>>> getAllDownloadedFileNamesByPlatform() =>
+  _i7.Future<Map<String, Set<String>>> getAllDownloadedFileNamesByPlatform() =>
       (super.noSuchMethod(
             Invocation.method(#getAllDownloadedFileNamesByPlatform, []),
-            returnValue: _i6.Future<Map<String, Set<String>>>.value(
+            returnValue: _i7.Future<Map<String, Set<String>>>.value(
               <String, Set<String>>{},
             ),
           )
-          as _i6.Future<Map<String, Set<String>>>);
+          as _i7.Future<Map<String, Set<String>>>);
 
   @override
-  _i6.Future<String> getRomDirectory(_i4.Game? game) =>
+  _i7.Future<String> getRomDirectory(_i5.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getRomDirectory, [game]),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(#getRomDirectory, [game]),
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<String> getRomFilePath(_i4.Game? game) =>
+  _i7.Future<String> getRomFilePath(_i5.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getRomFilePath, [game]),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(#getRomFilePath, [game]),
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<String?> findExistingRomPath(_i4.Game? game) =>
+  _i7.Future<String?> findExistingRomPath(_i5.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#findExistingRomPath, [game]),
-            returnValue: _i6.Future<String?>.value(),
+            returnValue: _i7.Future<String?>.value(),
           )
-          as _i6.Future<String?>);
+          as _i7.Future<String?>);
 
   @override
-  _i6.Future<String?> resolveSevenZipPath() =>
+  _i7.Future<String?> resolveSevenZipPath() =>
       (super.noSuchMethod(
             Invocation.method(#resolveSevenZipPath, []),
-            returnValue: _i6.Future<String?>.value(),
+            returnValue: _i7.Future<String?>.value(),
           )
-          as _i6.Future<String?>);
+          as _i7.Future<String?>);
 
   @override
-  _i6.Future<String> getEmulatorDirectory(String? emulatorId) =>
+  _i7.Future<String> getEmulatorDirectory(String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#getEmulatorDirectory, [emulatorId]),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(#getEmulatorDirectory, [emulatorId]),
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<String> getEmulatorAppSupportDirectory(
+  _i7.Future<String> getEmulatorAppSupportDirectory(
     String? emulatorName, {
     String? platformSlug,
   }) =>
@@ -348,8 +380,8 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               [emulatorName],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorAppSupportDirectory,
@@ -359,10 +391,10 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<String> getEmulatorBiosDirectory(
+  _i7.Future<String> getEmulatorBiosDirectory(
     String? emulatorId, {
     String? platformSlug,
   }) =>
@@ -372,8 +404,8 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               [emulatorId],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorBiosDirectory,
@@ -383,10 +415,10 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<String> getEmulatorSystemDirectory(
+  _i7.Future<String> getEmulatorSystemDirectory(
     String? emulatorId, {
     String? platformSlug,
   }) =>
@@ -396,8 +428,8 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               [emulatorId],
               {#platformSlug: platformSlug},
             ),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(
                   #getEmulatorSystemDirectory,
@@ -407,19 +439,19 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<void> deleteEmulator(String? emulatorId) =>
+  _i7.Future<void> deleteEmulator(String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteEmulator, [emulatorId]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<String> getEmulatorExecutable(
+  _i7.Future<String> getEmulatorExecutable(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -428,8 +460,8 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i6.Future<String>.value(
-              _i5.dummyValue<String>(
+            returnValue: _i7.Future<String>.value(
+              _i6.dummyValue<String>(
                 this,
                 Invocation.method(#getEmulatorExecutable, [
                   emulatorId,
@@ -438,10 +470,10 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               ),
             ),
           )
-          as _i6.Future<String>);
+          as _i7.Future<String>);
 
   @override
-  _i6.Future<String?> findEmulatorExecutable(
+  _i7.Future<String?> findEmulatorExecutable(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -450,12 +482,12 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i6.Future<String?>.value(),
+            returnValue: _i7.Future<String?>.value(),
           )
-          as _i6.Future<String?>);
+          as _i7.Future<String?>);
 
   @override
-  _i6.Future<bool> isEmulatorInstalled(
+  _i7.Future<bool> isEmulatorInstalled(
     String? emulatorId,
     String? executableName,
   ) =>
@@ -464,17 +496,17 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               emulatorId,
               executableName,
             ]),
-            returnValue: _i6.Future<bool>.value(false),
+            returnValue: _i7.Future<bool>.value(false),
           )
-          as _i6.Future<bool>);
+          as _i7.Future<bool>);
 
   @override
-  _i6.Future<bool> isRomDownloaded(_i4.Game? game) =>
+  _i7.Future<bool> isRomDownloaded(_i5.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#isRomDownloaded, [game]),
-            returnValue: _i6.Future<bool>.value(false),
+            returnValue: _i7.Future<bool>.value(false),
           )
-          as _i6.Future<bool>);
+          as _i7.Future<bool>);
 
   @override
   bool isEmuLaunchScript(String? path) =>
@@ -485,8 +517,8 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
           as bool);
 
   @override
-  _i6.Future<void> launchGame(
-    _i4.Game? game,
+  _i7.Future<void> launchGame(
+    _i5.Game? game,
     String? romPath,
     String? emulatorId,
     String? exePath, {
@@ -498,14 +530,14 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               [game, romPath, emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<_i7.Process?> launchGameWithHandle(
-    _i4.Game? game,
+  _i7.Future<_i8.Process?> launchGameWithHandle(
+    _i5.Game? game,
     String? romPath,
     String? emulatorId,
     String? exePath, {
@@ -517,12 +549,12 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               [game, romPath, emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i6.Future<_i7.Process?>.value(),
+            returnValue: _i7.Future<_i8.Process?>.value(),
           )
-          as _i6.Future<_i7.Process?>);
+          as _i7.Future<_i8.Process?>);
 
   @override
-  _i6.Future<void> launchStandalone(
+  _i7.Future<void> launchStandalone(
     String? emulatorId,
     String? exePath, {
     List<String>? args = const [],
@@ -533,42 +565,53 @@ class MockDirectoryService extends _i1.Mock implements _i2.DirectoryService {
               [emulatorId, exePath],
               {#args: args},
             ),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<void> deleteRom(_i4.Game? game) =>
+  _i7.Future<void> deleteRom(_i5.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRom, [game]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 }
 
 /// A class which mocks [RommService].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockRommService extends _i1.Mock implements _i8.RommService {
+class MockRommService extends _i1.Mock implements _i9.RommService {
   MockRommService() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  _i4.RomMConfig get config =>
+  _i4.ValueNotifier<bool> get isOffline =>
+      (super.noSuchMethod(
+            Invocation.getter(#isOffline),
+            returnValue: _FakeValueNotifier_2<bool>(
+              this,
+              Invocation.getter(#isOffline),
+            ),
+          )
+          as _i4.ValueNotifier<bool>);
+
+  @override
+  _i5.RomMConfig get config =>
       (super.noSuchMethod(
             Invocation.getter(#config),
-            returnValue: _FakeRomMConfig_2(this, Invocation.getter(#config)),
+            returnValue: _FakeRomMConfig_3(this, Invocation.getter(#config)),
           )
-          as _i4.RomMConfig);
+          as _i5.RomMConfig);
 
   @override
   String get authHeader =>
       (super.noSuchMethod(
             Invocation.getter(#authHeader),
-            returnValue: _i5.dummyValue<String>(
+            returnValue: _i6.dummyValue<String>(
               this,
               Invocation.getter(#authHeader),
             ),
@@ -576,93 +619,107 @@ class MockRommService extends _i1.Mock implements _i8.RommService {
           as String);
 
   @override
-  void updateConfig(_i4.RomMConfig? newConfig) => super.noSuchMethod(
+  void updateConfig(_i5.RomMConfig? newConfig) => super.noSuchMethod(
     Invocation.method(#updateConfig, [newConfig]),
     returnValueForMissingStub: null,
   );
 
   @override
-  _i6.Future<void> refreshToken(_i9.SharedPreferences? prefs) =>
+  void startHeartbeat() => super.noSuchMethod(
+    Invocation.method(#startHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  void stopHeartbeat() => super.noSuchMethod(
+    Invocation.method(#stopHeartbeat, []),
+    returnValueForMissingStub: null,
+  );
+
+  @override
+  _i7.Future<void> refreshToken(_i10.SharedPreferences? prefs) =>
       (super.noSuchMethod(
             Invocation.method(#refreshToken, [prefs]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<_i4.Game?> getGame(String? id) =>
+  _i7.Future<_i5.Game?> getGame(String? id) =>
       (super.noSuchMethod(
             Invocation.method(#getGame, [id]),
-            returnValue: _i6.Future<_i4.Game?>.value(),
+            returnValue: _i7.Future<_i5.Game?>.value(),
           )
-          as _i6.Future<_i4.Game?>);
+          as _i7.Future<_i5.Game?>);
 
   @override
-  _i6.Future<List<_i4.Platform>> getPlatforms() =>
+  _i7.Future<List<_i5.Platform>> getPlatforms() =>
       (super.noSuchMethod(
             Invocation.method(#getPlatforms, []),
-            returnValue: _i6.Future<List<_i4.Platform>>.value(<_i4.Platform>[]),
+            returnValue: _i7.Future<List<_i5.Platform>>.value(<_i5.Platform>[]),
           )
-          as _i6.Future<List<_i4.Platform>>);
+          as _i7.Future<List<_i5.Platform>>);
 
   @override
-  _i6.Future<List<Map<String, dynamic>>> getCollections() =>
+  _i7.Future<List<Map<String, dynamic>>> getCollections() =>
       (super.noSuchMethod(
             Invocation.method(#getCollections, []),
-            returnValue: _i6.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i7.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i6.Future<List<Map<String, dynamic>>>);
+          as _i7.Future<List<Map<String, dynamic>>>);
 
   @override
-  String? resolveCoverUrl(_i4.Game? game) =>
+  String? resolveCoverUrl(_i5.Game? game) =>
       (super.noSuchMethod(Invocation.method(#resolveCoverUrl, [game]))
           as String?);
 
   @override
-  _i6.Future<List<_i4.Game>> getGames(String? platformId) =>
+  _i7.Future<List<_i5.Game>> getGames(String? platformId) =>
       (super.noSuchMethod(
             Invocation.method(#getGames, [platformId]),
-            returnValue: _i6.Future<List<_i4.Game>>.value(<_i4.Game>[]),
+            returnValue: _i7.Future<List<_i5.Game>>.value(<_i5.Game>[]),
           )
-          as _i6.Future<List<_i4.Game>>);
+          as _i7.Future<List<_i5.Game>>);
 
   @override
-  _i6.Future<List<_i4.Game>> getAllGames({String? platformId}) =>
+  _i7.Future<List<_i5.Game>> getAllGames({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getAllGames, [], {#platformId: platformId}),
-            returnValue: _i6.Future<List<_i4.Game>>.value(<_i4.Game>[]),
+            returnValue: _i7.Future<List<_i5.Game>>.value(<_i5.Game>[]),
           )
-          as _i6.Future<List<_i4.Game>>);
+          as _i7.Future<List<_i5.Game>>);
 
   @override
-  _i6.Future<List<_i4.Game>> getRecentlyPlayed({int? limit = 15}) =>
+  _i7.Future<List<_i5.Game>> getRecentlyPlayed({int? limit = 15}) =>
       (super.noSuchMethod(
             Invocation.method(#getRecentlyPlayed, [], {#limit: limit}),
-            returnValue: _i6.Future<List<_i4.Game>>.value(<_i4.Game>[]),
+            returnValue: _i7.Future<List<_i5.Game>>.value(<_i5.Game>[]),
           )
-          as _i6.Future<List<_i4.Game>>);
+          as _i7.Future<List<_i5.Game>>);
 
   @override
-  _i6.Future<List<_i4.Game>> searchRoms({
+  _i7.Future<List<_i5.Game>> searchRoms({
     String? sha1,
     String? md5,
     String? search,
+    String? platformId,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#searchRoms, [], {
               #sha1: sha1,
               #md5: md5,
               #search: search,
+              #platformId: platformId,
             }),
-            returnValue: _i6.Future<List<_i4.Game>>.value(<_i4.Game>[]),
+            returnValue: _i7.Future<List<_i5.Game>>.value(<_i5.Game>[]),
           )
-          as _i6.Future<List<_i4.Game>>);
+          as _i7.Future<List<_i5.Game>>);
 
   @override
-  _i6.Future<({List<_i4.Game> games, int total})> getGamesPage({
+  _i7.Future<({List<_i5.Game> games, int total})> getGamesPage({
     int? offset = 0,
     int? limit = 50,
     String? platformId,
@@ -691,34 +748,34 @@ class MockRommService extends _i1.Mock implements _i8.RommService {
               #withCharIndex: withCharIndex,
               #withFilterValues: withFilterValues,
             }),
-            returnValue: _i6.Future<({List<_i4.Game> games, int total})>.value((
-              games: <_i4.Game>[],
+            returnValue: _i7.Future<({List<_i5.Game> games, int total})>.value((
+              games: <_i5.Game>[],
               total: 0,
             )),
           )
-          as _i6.Future<({List<_i4.Game> games, int total})>);
+          as _i7.Future<({List<_i5.Game> games, int total})>);
 
   @override
-  _i6.Future<_i4.Game?> getRandomGame() =>
+  _i7.Future<_i5.Game?> getRandomGame() =>
       (super.noSuchMethod(
             Invocation.method(#getRandomGame, []),
-            returnValue: _i6.Future<_i4.Game?>.value(),
+            returnValue: _i7.Future<_i5.Game?>.value(),
           )
-          as _i6.Future<_i4.Game?>);
+          as _i7.Future<_i5.Game?>);
 
   @override
-  _i6.Future<List<_i4.SaveFile>> getSaves(String? gameId) =>
+  _i7.Future<List<_i5.SaveFile>> getSaves(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSaves, [gameId]),
-            returnValue: _i6.Future<List<_i4.SaveFile>>.value(<_i4.SaveFile>[]),
+            returnValue: _i7.Future<List<_i5.SaveFile>>.value(<_i5.SaveFile>[]),
           )
-          as _i6.Future<List<_i4.SaveFile>>);
+          as _i7.Future<List<_i5.SaveFile>>);
 
   @override
-  String getDownloadUrl(_i4.Game? game) =>
+  String getDownloadUrl(_i5.Game? game) =>
       (super.noSuchMethod(
             Invocation.method(#getDownloadUrl, [game]),
-            returnValue: _i5.dummyValue<String>(
+            returnValue: _i6.dummyValue<String>(
               this,
               Invocation.method(#getDownloadUrl, [game]),
             ),
@@ -726,11 +783,11 @@ class MockRommService extends _i1.Mock implements _i8.RommService {
           as String);
 
   @override
-  _i6.Future<bool> uploadSave(
+  _i7.Future<bool> uploadSave(
     String? gameId,
-    _i7.File? saveFile, {
+    _i8.File? saveFile, {
     String? slot,
-    _i7.File? screenshotFile,
+    _i8.File? screenshotFile,
     String? overrideFilename,
   }) =>
       (super.noSuchMethod(
@@ -743,73 +800,73 @@ class MockRommService extends _i1.Mock implements _i8.RommService {
                 #overrideFilename: overrideFilename,
               },
             ),
-            returnValue: _i6.Future<bool>.value(false),
+            returnValue: _i7.Future<bool>.value(false),
           )
-          as _i6.Future<bool>);
+          as _i7.Future<bool>);
 
   @override
-  _i6.Future<bool> deleteSaves(List<int>? saveIds) =>
+  _i7.Future<bool> deleteSaves(List<int>? saveIds) =>
       (super.noSuchMethod(
             Invocation.method(#deleteSaves, [saveIds]),
-            returnValue: _i6.Future<bool>.value(false),
+            returnValue: _i7.Future<bool>.value(false),
           )
-          as _i6.Future<bool>);
+          as _i7.Future<bool>);
 
   @override
-  _i6.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
+  _i7.Future<void> pruneOldSaves(String? gameId, {int? keepCount = 5}) =>
       (super.noSuchMethod(
             Invocation.method(
               #pruneOldSaves,
               [gameId],
               {#keepCount: keepCount},
             ),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
+  _i7.Future<List<Map<String, dynamic>>> getSavesList(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getSavesList, [gameId]),
-            returnValue: _i6.Future<List<Map<String, dynamic>>>.value(
+            returnValue: _i7.Future<List<Map<String, dynamic>>>.value(
               <Map<String, dynamic>>[],
             ),
           )
-          as _i6.Future<List<Map<String, dynamic>>>);
+          as _i7.Future<List<Map<String, dynamic>>>);
 
   @override
-  _i6.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
+  _i7.Future<Map<String, dynamic>?> getLatestSave(String? gameId) =>
       (super.noSuchMethod(
             Invocation.method(#getLatestSave, [gameId]),
-            returnValue: _i6.Future<Map<String, dynamic>?>.value(),
+            returnValue: _i7.Future<Map<String, dynamic>?>.value(),
           )
-          as _i6.Future<Map<String, dynamic>?>);
+          as _i7.Future<Map<String, dynamic>?>);
 
   @override
-  _i6.Future<_i10.Uint8List?> downloadSave(
+  _i7.Future<_i11.Uint8List?> downloadSave(
     String? saveUrl, {
-    _i9.SharedPreferences? prefs,
+    _i10.SharedPreferences? prefs,
   }) =>
       (super.noSuchMethod(
             Invocation.method(#downloadSave, [saveUrl], {#prefs: prefs}),
-            returnValue: _i6.Future<_i10.Uint8List?>.value(),
+            returnValue: _i7.Future<_i11.Uint8List?>.value(),
           )
-          as _i6.Future<_i10.Uint8List?>);
+          as _i7.Future<_i11.Uint8List?>);
 
   @override
-  _i6.Future<List<_i4.Firmware>> getFirmware({String? platformId}) =>
+  _i7.Future<List<_i5.Firmware>> getFirmware({String? platformId}) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmware, [], {#platformId: platformId}),
-            returnValue: _i6.Future<List<_i4.Firmware>>.value(<_i4.Firmware>[]),
+            returnValue: _i7.Future<List<_i5.Firmware>>.value(<_i5.Firmware>[]),
           )
-          as _i6.Future<List<_i4.Firmware>>);
+          as _i7.Future<List<_i5.Firmware>>);
 
   @override
-  String getFirmwareDownloadUrl(_i4.Firmware? firmware) =>
+  String getFirmwareDownloadUrl(_i5.Firmware? firmware) =>
       (super.noSuchMethod(
             Invocation.method(#getFirmwareDownloadUrl, [firmware]),
-            returnValue: _i5.dummyValue<String>(
+            returnValue: _i6.dummyValue<String>(
               this,
               Invocation.method(#getFirmwareDownloadUrl, [firmware]),
             ),
@@ -817,8 +874,8 @@ class MockRommService extends _i1.Mock implements _i8.RommService {
           as String);
 
   @override
-  _i6.Future<_i10.Uint8List?> downloadFirmware(
-    _i4.Firmware? firmware, {
+  _i7.Future<_i11.Uint8List?> downloadFirmware(
+    _i5.Firmware? firmware, {
     void Function(int, int)? onProgress,
   }) =>
       (super.noSuchMethod(
@@ -827,14 +884,14 @@ class MockRommService extends _i1.Mock implements _i8.RommService {
               [firmware],
               {#onProgress: onProgress},
             ),
-            returnValue: _i6.Future<_i10.Uint8List?>.value(),
+            returnValue: _i7.Future<_i11.Uint8List?>.value(),
           )
-          as _i6.Future<_i10.Uint8List?>);
+          as _i7.Future<_i11.Uint8List?>);
 
   @override
-  _i6.Future<bool> updateRomProps(
+  _i7.Future<bool> updateRomProps(
     String? romId,
-    _i9.SharedPreferences? prefs, {
+    _i10.SharedPreferences? prefs, {
     bool? backlogged,
     bool? nowPlaying,
     int? rating,
@@ -853,54 +910,54 @@ class MockRommService extends _i1.Mock implements _i8.RommService {
                 #completion: completion,
               },
             ),
-            returnValue: _i6.Future<bool>.value(false),
+            returnValue: _i7.Future<bool>.value(false),
           )
-          as _i6.Future<bool>);
+          as _i7.Future<bool>);
 
   @override
-  _i6.Future<List<_i4.RomNote>> getRomNotes(String? romId) =>
+  _i7.Future<List<_i5.RomNote>> getRomNotes(String? romId) =>
       (super.noSuchMethod(
             Invocation.method(#getRomNotes, [romId]),
-            returnValue: _i6.Future<List<_i4.RomNote>>.value(<_i4.RomNote>[]),
+            returnValue: _i7.Future<List<_i5.RomNote>>.value(<_i5.RomNote>[]),
           )
-          as _i6.Future<List<_i4.RomNote>>);
+          as _i7.Future<List<_i5.RomNote>>);
 
   @override
-  _i6.Future<bool> createRomNote(
+  _i7.Future<bool> createRomNote(
     String? romId,
     String? title,
     String? content,
   ) =>
       (super.noSuchMethod(
             Invocation.method(#createRomNote, [romId, title, content]),
-            returnValue: _i6.Future<bool>.value(false),
+            returnValue: _i7.Future<bool>.value(false),
           )
-          as _i6.Future<bool>);
+          as _i7.Future<bool>);
 
   @override
-  _i6.Future<bool> deleteRomNote(String? romId, int? noteId) =>
+  _i7.Future<bool> deleteRomNote(String? romId, int? noteId) =>
       (super.noSuchMethod(
             Invocation.method(#deleteRomNote, [romId, noteId]),
-            returnValue: _i6.Future<bool>.value(false),
+            returnValue: _i7.Future<bool>.value(false),
           )
-          as _i6.Future<bool>);
+          as _i7.Future<bool>);
 }
 
 /// A class which mocks [StrategyRegistry].
 ///
 /// See the documentation for Mockito's code generation for more information.
-class MockStrategyRegistry extends _i1.Mock implements _i11.StrategyRegistry {
+class MockStrategyRegistry extends _i1.Mock implements _i12.StrategyRegistry {
   MockStrategyRegistry() {
     _i1.throwOnMissingStub(this);
   }
 
   @override
-  Map<String, List<_i12.EmulatorStrategy>> detectConflicts() =>
+  Map<String, List<_i13.EmulatorStrategy>> detectConflicts() =>
       (super.noSuchMethod(
             Invocation.method(#detectConflicts, []),
-            returnValue: <String, List<_i12.EmulatorStrategy>>{},
+            returnValue: <String, List<_i13.EmulatorStrategy>>{},
           )
-          as Map<String, List<_i12.EmulatorStrategy>>);
+          as Map<String, List<_i13.EmulatorStrategy>>);
 
   @override
   String? getPreferredEmulatorId(String? slug) =>
@@ -908,34 +965,34 @@ class MockStrategyRegistry extends _i1.Mock implements _i11.StrategyRegistry {
           as String?);
 
   @override
-  _i6.Future<void> setPreference(String? canonicalSlug, String? emulatorId) =>
+  _i7.Future<void> setPreference(String? canonicalSlug, String? emulatorId) =>
       (super.noSuchMethod(
             Invocation.method(#setPreference, [canonicalSlug, emulatorId]),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i6.Future<void> clearPreferences() =>
+  _i7.Future<void> clearPreferences() =>
       (super.noSuchMethod(
             Invocation.method(#clearPreferences, []),
-            returnValue: _i6.Future<void>.value(),
-            returnValueForMissingStub: _i6.Future<void>.value(),
+            returnValue: _i7.Future<void>.value(),
+            returnValueForMissingStub: _i7.Future<void>.value(),
           )
-          as _i6.Future<void>);
+          as _i7.Future<void>);
 
   @override
-  _i12.EmulatorStrategy? getStrategyForSlug(String? platformSlug) =>
+  _i13.EmulatorStrategy? getStrategyForSlug(String? platformSlug) =>
       (super.noSuchMethod(
             Invocation.method(#getStrategyForSlug, [platformSlug]),
           )
-          as _i12.EmulatorStrategy?);
+          as _i13.EmulatorStrategy?);
 
   @override
-  _i12.EmulatorStrategy? getStrategyById(String? id) =>
+  _i13.EmulatorStrategy? getStrategyById(String? id) =>
       (super.noSuchMethod(Invocation.method(#getStrategyById, [id]))
-          as _i12.EmulatorStrategy?);
+          as _i13.EmulatorStrategy?);
 
   @override
   void setNdsCore(String? core) => super.noSuchMethod(

Clone this wiki locally