diff --git a/packages/game_center/lib/app/app_pages.dart b/packages/game_center/lib/app/app_pages.dart index ea2991b..a590c1c 100644 --- a/packages/game_center/lib/app/app_pages.dart +++ b/packages/game_center/lib/app/app_pages.dart @@ -17,34 +17,34 @@ final pages = [ leading: Icon(LauncherPage.icon(selected)), title: Text(LauncherPage.label(context)), ), - pageBuilder: (_) => LauncherPage() + pageBuilder: (_) => const LauncherPage() ), ( titleBuilder: (context, selected) => YaruMasterTile( leading: Icon(SteamPage.icon(selected)), title: Text(SteamPage.label(context)), ), - pageBuilder: (_) => SteamPage(), + pageBuilder: (_) => const SteamPage(), ), ( titleBuilder: (context, selected) => YaruMasterTile( leading: Icon(SystemPage.icon(selected)), title: Text(SystemPage.label(context)), ), - pageBuilder: (_) => SystemPage() + pageBuilder: (_) => const SystemPage() ), ( titleBuilder: (context, selected) => YaruMasterTile( leading: Icon(SettingsPage.icon(selected)), title: Text(SettingsPage.label(context)), ), - pageBuilder: (_) => SettingsPage() + pageBuilder: (_) => const SettingsPage() ), ( titleBuilder: (context, selected) => YaruMasterTile( leading: Icon(AboutPage.icon(selected)), title: Text(AboutPage.label(context)), ), - pageBuilder: (_) => AboutPage() + pageBuilder: (_) => const AboutPage() ), ]; diff --git a/packages/game_center/lib/layout.dart b/packages/game_center/lib/layout.dart index 717a68e..e2d075f 100644 --- a/packages/game_center/lib/layout.dart +++ b/packages/game_center/lib/layout.dart @@ -44,7 +44,7 @@ extension TextStyleToMono on TextStyle { } class AppScrollView extends StatelessWidget { - AppScrollView({required this.children}); + const AppScrollView({required this.children, super.key}); final List children; diff --git a/packages/game_center/lib/steam/proton_model.dart b/packages/game_center/lib/steam/proton_model.dart index 595f55b..88609d3 100644 --- a/packages/game_center/lib/steam/proton_model.dart +++ b/packages/game_center/lib/steam/proton_model.dart @@ -12,6 +12,7 @@ class ProtonModel extends _$ProtonModel { late String installLocation; late List protonVersions; + @override Future> build({String? install}) async { // default install location if (install == null) { @@ -27,12 +28,12 @@ class ProtonModel extends _$ProtonModel { // directory isn't created by Steam by default, so ensure it exists final protonDir = Directory(protonDirectory(installLocation)); - protonDir.create(recursive: true); + await protonDir.create(recursive: true); await updateProtonVersions(); final fileSystem = FileWatcher(protonDirectory(installLocation)); - fileSystem.events.listen((event) async => await updateProtonVersions()); + fileSystem.events.listen((event) async => updateProtonVersions()); return protonVersions; } diff --git a/packages/game_center/lib/steam/steam_model.dart b/packages/game_center/lib/steam/steam_model.dart index da6a399..8aba998 100644 --- a/packages/game_center/lib/steam/steam_model.dart +++ b/packages/game_center/lib/steam/steam_model.dart @@ -2,10 +2,10 @@ import 'dart:io'; import 'package:game_center/steam/steam_data.dart'; import 'package:game_center/util.dart'; +import 'package:path/path.dart' as path; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:vdf/vdf.dart'; import 'package:watcher/watcher.dart'; -import 'package:path/path.dart' as path; part 'steam_model.g.dart'; @@ -24,8 +24,9 @@ class SteamUser { factory SteamUser.fromConfig(Map config) { final id = config['UserLocalConfigStore']['friends'].keys.first; return SteamUser( - id: id, - name: config['UserLocalConfigStore']['friends'][id]['NameHistory']['0'], + id: id as String, + name: config['UserLocalConfigStore']['friends'][id]['NameHistory']['0'] + as String, ); } @@ -68,7 +69,7 @@ class SteamModel extends _$SteamModel { // user configs final users = await listUserDirs(); - userConfigs = new Map(); + userConfigs = {}; for (final steamID in users) { final file = File(steamUserConfig(installLocation, steamID)); userConfigs[steamID] = vdfDecode(await file.readAsString()); @@ -92,9 +93,9 @@ class SteamModel extends _$SteamModel { } Future> listUserDirs() async { - var userdata = - await Directory('$installLocation/$steamDataDir/userdata').list(); - var directories = + final userdata = + Directory('$installLocation/$steamDataDir/userdata').list(); + final directories = userdata.where((x) => x is Directory).map((x) => x as Directory); return directories.map((dir) => path.basename(dir.path)).toList(); } @@ -102,30 +103,36 @@ class SteamModel extends _$SteamModel { Future updateGlobalConfig() async { final file = File(steamGlobalConfig(installLocation)); globalConfig = vdfDecode(await file.readAsString()); - state = AsyncData(( - globalConfig: globalConfig, - userConfigs: userConfigs, - activeUser: activeUser, - )); + state = AsyncData( + ( + globalConfig: globalConfig, + userConfigs: userConfigs, + activeUser: activeUser, + ), + ); } Future updateUserConfig(String steamID) async { final file = File(steamUserConfig(installLocation, steamID)); userConfigs[steamID] = vdfDecode(await file.readAsString()); - state = AsyncData(( - globalConfig: globalConfig, - userConfigs: userConfigs, - activeUser: activeUser, - )); + state = AsyncData( + ( + globalConfig: globalConfig, + userConfigs: userConfigs, + activeUser: activeUser, + ), + ); } Future setActiveUser(String newActiveUserID) async { activeUser = SteamUser.fromConfig(userConfigs[newActiveUserID]!); - state = AsyncData(( - globalConfig: globalConfig, - userConfigs: userConfigs, - activeUser: activeUser, - )); + state = AsyncData( + ( + globalConfig: globalConfig, + userConfigs: userConfigs, + activeUser: activeUser, + ), + ); } /// Enable/disable Steam Play (Proton) for all titles globally. This is @@ -135,7 +142,7 @@ class SteamModel extends _$SteamModel { required bool enable, String? protonVersion, }) async { - Map config = Map.from(globalConfig); + var config = Map.from(globalConfig); if (enable) { config = Map.castFrom( safePut( @@ -146,7 +153,7 @@ class SteamModel extends _$SteamModel { 'Valve', 'Steam', 'CompatToolMapping', - '0' + '0', ], { 'name': protonVersion ?? 'proton_experimental', @@ -164,7 +171,7 @@ class SteamModel extends _$SteamModel { 'Software', 'Valve', 'Steam', - 'CompatToolMapping' + 'CompatToolMapping', ], {}, ), @@ -173,21 +180,22 @@ class SteamModel extends _$SteamModel { final file = File(steamGlobalConfig(installLocation)); await file.writeAsString(vdf.encode(config)); + await updateGlobalConfig(); } /// Check if Steam Play is enabled in the global config. bool steamPlayEnabled() { - Map config = Map.from(globalConfig); + final config = Map.from(globalConfig); final key = config['InstallConfigStore']?['Software']?['Valve']?['Steam'] ?['CompatToolMapping']; - Map compat = Map.castFrom(key ?? new Map()); - return compat.containsKey('0') && compat['0'].isNotEmpty; + final compat = Map.castFrom(key != null ? key as Map : {}); + return compat.containsKey('0') && (compat['0'] as Map).isNotEmpty; } /// Get a map of installed Steam apps for the given user. Map listApps({required String steamID}) { - Map config = Map.from(userConfigs[steamID]!); - var apps = config['UserLocalConfigStore']['Software']['Valve']['Steam'] + final config = Map.from(userConfigs[steamID]!); + final apps = config['UserLocalConfigStore']['Software']['Valve']['Steam'] ['apps'] as Map; return apps.cast(); } @@ -199,7 +207,7 @@ class SteamModel extends _$SteamModel { final apps = listApps(steamID: steamID); for (final app in apps.keys) { final launchOptions = getGameLaunchOptions(steamID: steamID, appID: app); - List options = + final options = launchOptions.isEmpty ? [] : launchOptions.split(RegExp(r'\s+')); if (!options.contains(option)) { return false; @@ -213,9 +221,9 @@ class SteamModel extends _$SteamModel { required String steamID, required String appID, }) { - Map config = Map.from(userConfigs[steamID]!); - String? launchOptions = config['UserLocalConfigStore']['Software']['Valve'] - ['Steam']['apps'][appID]['LaunchOptions']; + final config = Map.from(userConfigs[steamID]!); + final launchOptions = config['UserLocalConfigStore']['Software']['Valve'] + ['Steam']['apps'][appID]['LaunchOptions'] as String?; return launchOptions ?? ''; } @@ -225,7 +233,7 @@ class SteamModel extends _$SteamModel { required String appID, required String options, }) async { - Map config = Map.from(userConfigs[steamID]!); + final config = Map.from(userConfigs[steamID]!); config['UserLocalConfigStore']['Software']['Valve']['Steam']['apps'][appID] ['LaunchOptions'] = options; final file = File(steamUserConfig(installLocation, steamID)); @@ -237,14 +245,14 @@ class SteamModel extends _$SteamModel { required String steamID, required String option, }) async { - Map config = Map.from(userConfigs[steamID]!); - final apps = await listApps(steamID: steamID); + final config = Map.from(userConfigs[steamID]!); + final apps = listApps(steamID: steamID); for (final app in apps.keys) { - final launchOptions = await getGameLaunchOptions( + final launchOptions = getGameLaunchOptions( steamID: steamID, appID: app, ); - List options = + final options = launchOptions.isEmpty ? [] : launchOptions.split(RegExp(r'\s+')); if (!options.contains(option)) { options.insert(0, option); @@ -266,14 +274,14 @@ class SteamModel extends _$SteamModel { required String steamID, required String option, }) async { - Map config = Map.from(userConfigs[steamID]!); - final apps = await listApps(steamID: steamID); + final config = Map.from(userConfigs[steamID]!); + final apps = listApps(steamID: steamID); for (final app in apps.keys) { - final launchOptions = await getGameLaunchOptions( + final launchOptions = getGameLaunchOptions( steamID: steamID, appID: app, ); - List options = + final options = launchOptions.isEmpty ? [] : launchOptions.split(RegExp(r'\s+')); options.remove(option); config['UserLocalConfigStore']['Software']['Valve']['Steam']['apps'][app] @@ -292,11 +300,11 @@ class SteamModel extends _$SteamModel { required String appID, required String option, }) async { - String launchOptions = await getGameLaunchOptions( + final launchOptions = getGameLaunchOptions( steamID: steamID, appID: appID, ); - List options = + final options = launchOptions.isEmpty ? [] : launchOptions.split(RegExp(r'\s+')); if (!options.contains(option)) { options.insert(0, option); @@ -318,11 +326,11 @@ class SteamModel extends _$SteamModel { required String appID, required String option, }) async { - String launchOptions = await getGameLaunchOptions( + final launchOptions = getGameLaunchOptions( steamID: steamID, appID: appID, ); - List options = + final options = launchOptions.isEmpty ? [] : launchOptions.split(RegExp(r'\s+')); options.remove(option); await setGameLaunchOptions( diff --git a/packages/game_center/lib/steam/steam_page.dart b/packages/game_center/lib/steam/steam_page.dart index 9470153..3ff72b9 100644 --- a/packages/game_center/lib/steam/steam_page.dart +++ b/packages/game_center/lib/steam/steam_page.dart @@ -34,7 +34,7 @@ class SteamPage extends ConsumerWidget { child: Text(data.activeUser.name), itemBuilder: (context) => data.userConfigs.values.map( (id) { - var user = SteamUser.fromConfig(id); + final user = SteamUser.fromConfig(id); return PopupMenuItem( child: Text(user.name), onTap: () => notifier.setActiveUser(user.id), @@ -75,7 +75,7 @@ class SteamPage extends ConsumerWidget { child: Text(l10n.loadingLabel), ), error: (error, stackTrace) => Center( - child: Text('${error.toString()}\n${stackTrace.toString()}'), + child: Text('$error\n$stackTrace'), ), ); } @@ -100,7 +100,9 @@ class _SteamSimpleSettings extends ConsumerWidget { YaruSwitchListTile( title: Text(l10n.steamEnableMangoHUD), value: steam.allGamesHaveOption( - steamID: steam.activeUser.id, option: 'mangohud'), + steamID: steam.activeUser.id, + option: 'mangohud', + ), onChanged: (value) async { value ? await steam.addAllGameLaunchOption( @@ -116,7 +118,9 @@ class _SteamSimpleSettings extends ConsumerWidget { YaruSwitchListTile( title: Text(l10n.steamEnableGameMode), value: steam.allGamesHaveOption( - steamID: steam.activeUser.id, option: 'gamemoderun'), + steamID: steam.activeUser.id, + option: 'gamemoderun', + ), onChanged: (value) async { value ? await steam.addAllGameLaunchOption( @@ -167,7 +171,7 @@ class _SteamGlobalConfigText extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context); final steam = ref.watch(steamModelProvider()); - final controller = new TextEditingController(); + final controller = TextEditingController(); steam.whenData((data) async { controller.text = vdf.encode(data.globalConfig).replaceAll('\t', ' '); @@ -201,7 +205,7 @@ class _SteamUserConfigs extends ConsumerWidget { children: [ for (final userID in data.userConfigs.keys) ...[ _SteamUserConfigText(userID: userID), - SizedBox(height: kPagePadding), + const SizedBox(height: kPagePadding), ], ], ), @@ -216,7 +220,7 @@ class _SteamUserConfigs extends ConsumerWidget { } class _SteamUserConfigText extends ConsumerWidget { - _SteamUserConfigText({required this.userID}); + const _SteamUserConfigText({required this.userID}); final String userID; @@ -224,7 +228,7 @@ class _SteamUserConfigText extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context); final steam = ref.watch(steamModelProvider()); - final controller = new TextEditingController(); + final controller = TextEditingController(); steam.whenData((data) async { controller.text = diff --git a/packages/game_center/lib/util.dart b/packages/game_center/lib/util.dart index 42d2a03..18b5e45 100644 --- a/packages/game_center/lib/util.dart +++ b/packages/game_center/lib/util.dart @@ -1,10 +1,15 @@ -Map safePut(Map map, List keys, dynamic value) { +/// Safely insert a deeply nested key into a map. +Map safePut( + Map map, + List keys, + dynamic value, +) { final newMap = Map.from(map); var current = newMap; for (var i = 0; i < keys.length - 1; i++) { - var key = keys[i]; - current = current.putIfAbsent(key, () => Map()); + final key = keys[i]; + current = current.putIfAbsent(key, Map.new) as Map; } current[keys.last] = value; diff --git a/packages/game_center/lib/widgets/expandable_page_section.dart b/packages/game_center/lib/widgets/expandable_page_section.dart index 8d908cb..849e373 100644 --- a/packages/game_center/lib/widgets/expandable_page_section.dart +++ b/packages/game_center/lib/widgets/expandable_page_section.dart @@ -2,10 +2,11 @@ import 'package:flutter/material.dart'; import 'package:yaru/yaru.dart'; class ExpandablePageSection extends StatelessWidget { - ExpandablePageSection({ + const ExpandablePageSection({ required this.title, required this.children, this.expanded = false, + super.key, }); final String title; diff --git a/packages/game_center/test/steam/proton_model_test.dart b/packages/game_center/test/steam/proton_model_test.dart index 7bba3fb..d146e8e 100644 --- a/packages/game_center/test/steam/proton_model_test.dart +++ b/packages/game_center/test/steam/proton_model_test.dart @@ -9,7 +9,7 @@ void main() { test('build', () async { final container = createContainer(); final provider = protonModelProvider(); - container.read(provider.future); + await container.read(provider.future); final model = container.read(provider.notifier); final directory = Directory(model.installLocation); diff --git a/packages/game_center/test/steam/steam_model_test.dart b/packages/game_center/test/steam/steam_model_test.dart index a7e6df8..72b194b 100644 --- a/packages/game_center/test/steam/steam_model_test.dart +++ b/packages/game_center/test/steam/steam_model_test.dart @@ -26,14 +26,14 @@ void main() { final model = container.read(steamModelProvider().notifier); await container.read(steamModelProvider().future); - model.enableSteamPlay(enable: false); + await model.enableSteamPlay(enable: false); expect( model.globalConfig['InstallConfigStore']['Software']['Valve']['Steam'] ['CompatToolMapping'], isEmpty, ); - model.enableSteamPlay(enable: true); + await model.enableSteamPlay(enable: true); expect( model.globalConfig['InstallConfigStore']['Software']['Valve']['Steam'] ['CompatToolMapping'], @@ -53,7 +53,7 @@ void main() { final users = await model.listUserDirs(); for (final user in users) { - final apps = await model.listApps(steamID: user); + final apps = model.listApps(steamID: user); expect(apps, isNotEmpty); } }); @@ -65,8 +65,8 @@ void main() { final users = await model.listUserDirs(); for (final user in users) { - final apps = await model.listApps(steamID: user); - model.setGameLaunchOptions( + final apps = model.listApps(steamID: user); + await model.setGameLaunchOptions( steamID: user, appID: apps.keys.toList()[0], options: '%command%', @@ -86,7 +86,7 @@ void main() { final users = await model.listUserDirs(); for (final user in users) { - final apps = await model.listApps(steamID: user); + final apps = model.listApps(steamID: user); await model.setGameLaunchOptions( steamID: user, @@ -94,7 +94,7 @@ void main() { options: '', ); expect( - await model.getGameLaunchOptions( + model.getGameLaunchOptions( steamID: user, appID: apps.keys.first, ), @@ -107,7 +107,7 @@ void main() { options: 'foo', ); expect( - await model.getGameLaunchOptions( + model.getGameLaunchOptions( steamID: user, appID: apps.keys.first, ), @@ -123,7 +123,7 @@ void main() { final users = await model.listUserDirs(); for (final user in users) { - final apps = await model.listApps(steamID: user); + final apps = model.listApps(steamID: user); await model.setGameLaunchOptions( steamID: user, @@ -136,7 +136,7 @@ void main() { option: 'foo', ); expect( - await model.getGameLaunchOptions( + model.getGameLaunchOptions( steamID: user, appID: apps.keys.first, ), @@ -149,7 +149,7 @@ void main() { option: 'foo', ); expect( - await model.getGameLaunchOptions( + model.getGameLaunchOptions( steamID: user, appID: apps.keys.first, ), diff --git a/packages/game_center/test/steam/test_utils.dart b/packages/game_center/test/steam/test_utils.dart index 6a96490..062b227 100644 --- a/packages/game_center/test/steam/test_utils.dart +++ b/packages/game_center/test/steam/test_utils.dart @@ -1,5 +1,5 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:riverpod/riverpod.dart'; /// A testing utility which creates a [ProviderContainer] and automatically /// disposes it at the end of the test. diff --git a/packages/game_center/test/util/util_test.dart b/packages/game_center/test/util/util_test.dart index eee5598..726f6f0 100644 --- a/packages/game_center/test/util/util_test.dart +++ b/packages/game_center/test/util/util_test.dart @@ -3,12 +3,12 @@ import 'package:game_center/util.dart'; void main() { test('Safe put on empty map', () { - var emptyMap = Map(); + var emptyMap = {}; var inserted = safePut(emptyMap, ['foo'], 'test'); expect(inserted.containsKey('foo'), isTrue); expect(inserted['foo'], equals('test')); - emptyMap = Map(); + emptyMap = {}; inserted = safePut(emptyMap, ['foo', 'bar'], 'test'); expect(inserted.containsKey('foo'), isTrue); expect(inserted['foo'].containsKey('bar'), isTrue); @@ -16,13 +16,13 @@ void main() { }); test('Safe put on non-empty map', () { - var map = { + final map = { 'foo': { 'bar': 'test', }, 'bar': 'test', }; - var inserted = safePut(map, ['foo', 'test'], 'bar'); + final inserted = safePut(map, ['foo', 'test'], 'bar'); expect(inserted.containsKey('foo'), isTrue); expect(inserted['foo'].containsKey('bar'), isTrue); expect(inserted['foo'].containsKey('test'), isTrue);