made getters non nullable and removed all null assertion operators
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m10s
Pull Request Pipeline / lint (pull_request) Failing after 2m11s

This commit is contained in:
2026-01-02 19:01:44 +01:00
parent 7f923f6dff
commit 3c22b084d6
18 changed files with 87 additions and 86 deletions

View File

@@ -2,3 +2,4 @@ arb-dir: lib/l10n/arb
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-dir: lib/l10n/generated
nullable-getter: false

View File

@@ -37,12 +37,12 @@ enum Ruleset { singleWinner, singleLoser, mostPoints, leastPoints }
String translateRulesetToString(Ruleset ruleset, BuildContext context) {
switch (ruleset) {
case Ruleset.singleWinner:
return AppLocalizations.of(context)!.single_winner;
return AppLocalizations.of(context).single_winner;
case Ruleset.singleLoser:
return AppLocalizations.of(context)!.single_loser;
return AppLocalizations.of(context).single_loser;
case Ruleset.mostPoints:
return AppLocalizations.of(context)!.most_points;
return AppLocalizations.of(context).most_points;
case Ruleset.leastPoints:
return AppLocalizations.of(context)!.least_points;
return AppLocalizations.of(context).least_points;
}
}

View File

@@ -67,8 +67,8 @@ abstract class AppLocalizations {
final String localeName;
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations)!;
}
static const LocalizationsDelegate<AppLocalizations> delegate =

View File

@@ -90,28 +90,28 @@ class _CustomNavigationBarState extends State<CustomNavigationBar>
index: 0,
isSelected: currentIndex == 0,
icon: Icons.home_rounded,
label: AppLocalizations.of(context)!.home,
label: AppLocalizations.of(context).home,
onTabTapped: onTabTapped,
),
NavbarItem(
index: 1,
isSelected: currentIndex == 1,
icon: Icons.gamepad_rounded,
label: AppLocalizations.of(context)!.matches,
label: AppLocalizations.of(context).matches,
onTabTapped: onTabTapped,
),
NavbarItem(
index: 2,
isSelected: currentIndex == 2,
icon: Icons.group_rounded,
label: AppLocalizations.of(context)!.groups,
label: AppLocalizations.of(context).groups,
onTabTapped: onTabTapped,
),
NavbarItem(
index: 3,
isSelected: currentIndex == 3,
icon: Icons.bar_chart_rounded,
label: AppLocalizations.of(context)!.statistics,
label: AppLocalizations.of(context).statistics,
onTabTapped: onTabTapped,
),
],
@@ -132,13 +132,13 @@ class _CustomNavigationBarState extends State<CustomNavigationBar>
String _currentTabTitle() {
switch (currentIndex) {
case 0:
return AppLocalizations.of(context)!.home;
return AppLocalizations.of(context).home;
case 1:
return AppLocalizations.of(context)!.matches;
return AppLocalizations.of(context).matches;
case 2:
return AppLocalizations.of(context)!.groups;
return AppLocalizations.of(context).groups;
case 3:
return AppLocalizations.of(context)!.statistics;
return AppLocalizations.of(context).statistics;
default:
return '';
}

View File

@@ -45,7 +45,7 @@ class _CreateGroupViewState extends State<CreateGroupView> {
backgroundColor: CustomTheme.backgroundColor,
scrolledUnderElevation: 0,
title: Text(
AppLocalizations.of(context)!.create_new_group,
AppLocalizations.of(context).create_new_group,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
centerTitle: true,
@@ -58,7 +58,7 @@ class _CreateGroupViewState extends State<CreateGroupView> {
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
child: TextInputField(
controller: _groupNameController,
hintText: AppLocalizations.of(context)!.group_name,
hintText: AppLocalizations.of(context).group_name,
onChanged: (value) {
setState(() {});
},
@@ -74,7 +74,7 @@ class _CreateGroupViewState extends State<CreateGroupView> {
),
),
CustomWidthButton(
text: AppLocalizations.of(context)!.create_group,
text: AppLocalizations.of(context).create_group,
sizeRelativeToWidth: 0.95,
buttonType: ButtonType.primary,
onPressed:

View File

@@ -53,8 +53,8 @@ class _GroupsViewState extends State<GroupsView> {
replacement: Center(
child: TopCenteredMessage(
icon: Icons.info,
title: AppLocalizations.of(context)!.info,
message: AppLocalizations.of(context)!.no_groups_created_yet,
title: AppLocalizations.of(context).info,
message: AppLocalizations.of(context).no_groups_created_yet,
),
),
child: ListView.builder(
@@ -74,7 +74,7 @@ class _GroupsViewState extends State<GroupsView> {
Positioned(
bottom: MediaQuery.paddingOf(context).bottom,
child: CustomWidthButton(
text: AppLocalizations.of(context)!.create_group,
text: AppLocalizations.of(context).create_group,
sizeRelativeToWidth: 0.90,
onPressed: () async {
await Navigator.push(

View File

@@ -87,7 +87,7 @@ class _HomeViewState extends State<HomeView> {
QuickInfoTile(
width: constraints.maxWidth * 0.45,
height: constraints.maxHeight * 0.15,
title: AppLocalizations.of(context)!.matches,
title: AppLocalizations.of(context).matches,
icon: Icons.groups_rounded,
value: matchCount,
),
@@ -95,7 +95,7 @@ class _HomeViewState extends State<HomeView> {
QuickInfoTile(
width: constraints.maxWidth * 0.45,
height: constraints.maxHeight * 0.15,
title: AppLocalizations.of(context)!.groups,
title: AppLocalizations.of(context).groups,
icon: Icons.groups_rounded,
value: groupCount,
),
@@ -105,7 +105,7 @@ class _HomeViewState extends State<HomeView> {
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: InfoTile(
width: constraints.maxWidth * 0.95,
title: AppLocalizations.of(context)!.recent_matches,
title: AppLocalizations.of(context).recent_matches,
icon: Icons.timer,
content: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
@@ -125,7 +125,7 @@ class _HomeViewState extends State<HomeView> {
children: [
MatchSummaryTile(
matchTitle: recentMatches[0].name,
game: AppLocalizations.of(context)!.winner_label,
game: AppLocalizations.of(context).winner_label,
ruleset: AppLocalizations.of(
context,
)!.ruleset_label,
@@ -175,7 +175,7 @@ class _HomeViewState extends State<HomeView> {
),
InfoTile(
width: constraints.maxWidth * 0.95,
title: AppLocalizations.of(context)!.quick_create,
title: AppLocalizations.of(context).quick_create,
icon: Icons.add_box_rounded,
content: Column(
children: [
@@ -232,7 +232,7 @@ class _HomeViewState extends State<HomeView> {
String _getPlayerText(Match game) {
if (game.group == null) {
final playerCount = game.players?.length ?? 0;
return AppLocalizations.of(context)!.players_count(playerCount);
return AppLocalizations.of(context).players_count(playerCount);
}
if (game.players == null || game.players!.isEmpty) {
return game.group!.name;

View File

@@ -43,7 +43,7 @@ class _ChooseGameViewState extends State<ChooseGameView> {
},
),
title: Text(
AppLocalizations.of(context)!.choose_game,
AppLocalizations.of(context).choose_game,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
centerTitle: true,
@@ -54,7 +54,7 @@ class _ChooseGameViewState extends State<ChooseGameView> {
padding: const EdgeInsets.symmetric(horizontal: 10),
child: CustomSearchBar(
controller: searchBarController,
hintText: AppLocalizations.of(context)!.game_name,
hintText: AppLocalizations.of(context).game_name,
),
),
const SizedBox(height: 5),

View File

@@ -52,7 +52,7 @@ class _ChooseGroupViewState extends State<ChooseGroupView> {
},
),
title: Text(
AppLocalizations.of(context)!.choose_group,
AppLocalizations.of(context).choose_group,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
centerTitle: true,
@@ -63,7 +63,7 @@ class _ChooseGroupViewState extends State<ChooseGroupView> {
padding: const EdgeInsets.symmetric(horizontal: 10),
child: CustomSearchBar(
controller: controller,
hintText: AppLocalizations.of(context)!.search_for_groups,
hintText: AppLocalizations.of(context).search_for_groups,
onChanged: (value) {
setState(() {
filterGroups(value);
@@ -78,12 +78,12 @@ class _ChooseGroupViewState extends State<ChooseGroupView> {
visible: widget.groups.isNotEmpty,
replacement: TopCenteredMessage(
icon: Icons.info,
title: AppLocalizations.of(context)!.info,
message: AppLocalizations.of(context)!.no_groups_created_yet,
title: AppLocalizations.of(context).info,
message: AppLocalizations.of(context).no_groups_created_yet,
),
child: TopCenteredMessage(
icon: Icons.info,
title: AppLocalizations.of(context)!.info,
title: AppLocalizations.of(context).info,
message: AppLocalizations.of(
context,
)!.there_is_no_group_matching_your_search,

View File

@@ -48,7 +48,7 @@ class _ChooseRulesetViewState extends State<ChooseRulesetView> {
},
),
title: Text(
AppLocalizations.of(context)!.choose_ruleset,
AppLocalizations.of(context).choose_ruleset,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
centerTitle: true,

View File

@@ -91,19 +91,19 @@ class _CreateMatchViewState extends State<CreateMatchView> {
return [
(
Ruleset.singleWinner,
AppLocalizations.of(context)!.ruleset_single_winner_desc,
AppLocalizations.of(context).ruleset_single_winner_desc,
),
(
Ruleset.singleLoser,
AppLocalizations.of(context)!.ruleset_single_loser_desc,
AppLocalizations.of(context).ruleset_single_loser_desc,
),
(
Ruleset.mostPoints,
AppLocalizations.of(context)!.ruleset_most_points_desc,
AppLocalizations.of(context).ruleset_most_points_desc,
),
(
Ruleset.leastPoints,
AppLocalizations.of(context)!.ruleset_least_points_desc,
AppLocalizations.of(context).ruleset_least_points_desc,
),
];
}
@@ -122,7 +122,7 @@ class _CreateMatchViewState extends State<CreateMatchView> {
backgroundColor: CustomTheme.backgroundColor,
scrolledUnderElevation: 0,
title: Text(
AppLocalizations.of(context)!.create_new_match,
AppLocalizations.of(context).create_new_match,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
centerTitle: true,
@@ -139,9 +139,9 @@ class _CreateMatchViewState extends State<CreateMatchView> {
),
),
ChooseTile(
title: AppLocalizations.of(context)!.game,
title: AppLocalizations.of(context).game,
trailingText: selectedGameIndex == -1
? AppLocalizations.of(context)!.none
? AppLocalizations.of(context).none
: games[selectedGameIndex].$1,
onPressed: () async {
selectedGameIndex = await Navigator.of(context).push(
@@ -167,9 +167,9 @@ class _CreateMatchViewState extends State<CreateMatchView> {
},
),
ChooseTile(
title: AppLocalizations.of(context)!.ruleset,
title: AppLocalizations.of(context).ruleset,
trailingText: selectedRuleset == null
? AppLocalizations.of(context)!.none
? AppLocalizations.of(context).none
: translateRulesetToString(selectedRuleset!, context),
onPressed: () async {
final rulesets = _getRulesets(context);
@@ -190,9 +190,9 @@ class _CreateMatchViewState extends State<CreateMatchView> {
},
),
ChooseTile(
title: AppLocalizations.of(context)!.group,
title: AppLocalizations.of(context).group,
trailingText: selectedGroup == null
? AppLocalizations.of(context)!.none_group
? AppLocalizations.of(context).none_group
: selectedGroup!.name,
onPressed: () async {
selectedGroup = await Navigator.of(context).push(
@@ -229,7 +229,7 @@ class _CreateMatchViewState extends State<CreateMatchView> {
),
),
CustomWidthButton(
text: AppLocalizations.of(context)!.create_match,
text: AppLocalizations.of(context).create_match,
sizeRelativeToWidth: 0.95,
buttonType: ButtonType.primary,
onPressed: _enableCreateGameButton()

View File

@@ -81,7 +81,7 @@ class _MatchResultViewState extends State<MatchResultView> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.select_winner,
AppLocalizations.of(context).select_winner,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,

View File

@@ -62,8 +62,8 @@ class _MatchViewState extends State<MatchView> {
replacement: Center(
child: TopCenteredMessage(
icon: Icons.report,
title: AppLocalizations.of(context)!.info,
message: AppLocalizations.of(context)!.no_matches_created_yet,
title: AppLocalizations.of(context).info,
message: AppLocalizations.of(context).no_matches_created_yet,
),
),
child: ListView.builder(
@@ -97,7 +97,7 @@ class _MatchViewState extends State<MatchView> {
Positioned(
bottom: MediaQuery.paddingOf(context).bottom,
child: CustomWidthButton(
text: AppLocalizations.of(context)!.create_match,
text: AppLocalizations.of(context).create_match,
sizeRelativeToWidth: 0.90,
onPressed: () async {
Navigator.push(

View File

@@ -29,7 +29,7 @@ class _SettingsViewState extends State<SettingsView> {
padding: const EdgeInsets.fromLTRB(24, 0, 24, 10),
child: Text(
textAlign: TextAlign.start,
AppLocalizations.of(context)!.menu,
AppLocalizations.of(context).menu,
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
@@ -43,7 +43,7 @@ class _SettingsViewState extends State<SettingsView> {
),
child: Text(
textAlign: TextAlign.start,
AppLocalizations.of(context)!.settings,
AppLocalizations.of(context).settings,
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
@@ -51,7 +51,7 @@ class _SettingsViewState extends State<SettingsView> {
),
),
SettingsListTile(
title: AppLocalizations.of(context)!.export_data,
title: AppLocalizations.of(context).export_data,
icon: Icons.upload_outlined,
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
onPressed: () async {
@@ -66,7 +66,7 @@ class _SettingsViewState extends State<SettingsView> {
},
),
SettingsListTile(
title: AppLocalizations.of(context)!.import_data,
title: AppLocalizations.of(context).import_data,
icon: Icons.download_outlined,
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
onPressed: () async {
@@ -78,7 +78,7 @@ class _SettingsViewState extends State<SettingsView> {
},
),
SettingsListTile(
title: AppLocalizations.of(context)!.delete_all_data,
title: AppLocalizations.of(context).delete_all_data,
icon: Icons.download_outlined,
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
onPressed: () {
@@ -86,19 +86,19 @@ class _SettingsViewState extends State<SettingsView> {
context: context,
builder: (context) => AlertDialog(
title: Text(
AppLocalizations.of(context)!.delete_all_data,
AppLocalizations.of(context).delete_all_data,
),
content: Text(
AppLocalizations.of(context)!.this_cannot_be_undone,
AppLocalizations.of(context).this_cannot_be_undone,
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false),
child: Text(AppLocalizations.of(context)!.cancel),
child: Text(AppLocalizations.of(context).cancel),
),
TextButton(
onPressed: () => Navigator.of(context).pop(true),
child: Text(AppLocalizations.of(context)!.delete),
child: Text(AppLocalizations.of(context).delete),
),
],
),
@@ -134,32 +134,32 @@ class _SettingsViewState extends State<SettingsView> {
case ImportResult.success:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.data_successfully_imported,
message: AppLocalizations.of(context).data_successfully_imported,
);
case ImportResult.invalidSchema:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.invalid_schema,
message: AppLocalizations.of(context).invalid_schema,
);
case ImportResult.fileReadError:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.error_reading_file,
message: AppLocalizations.of(context).error_reading_file,
);
case ImportResult.canceled:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.import_canceled,
message: AppLocalizations.of(context).import_canceled,
);
case ImportResult.formatException:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.format_exception,
message: AppLocalizations.of(context).format_exception,
);
case ImportResult.unknownException:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.unknown_exception,
message: AppLocalizations.of(context).unknown_exception,
);
}
}
@@ -176,17 +176,17 @@ class _SettingsViewState extends State<SettingsView> {
case ExportResult.success:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.data_successfully_exported,
message: AppLocalizations.of(context).data_successfully_exported,
);
case ExportResult.canceled:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.export_canceled,
message: AppLocalizations.of(context).export_canceled,
);
case ExportResult.unknownException:
showSnackbar(
context: context,
message: AppLocalizations.of(context)!.unknown_exception,
message: AppLocalizations.of(context).unknown_exception,
);
}
}
@@ -212,7 +212,7 @@ class _SettingsViewState extends State<SettingsView> {
duration: duration,
action: action != null
? SnackBarAction(
label: AppLocalizations.of(context)!.undo,
label: AppLocalizations.of(context).undo,
onPressed: action,
)
: null,

View File

@@ -69,7 +69,7 @@ class _StatisticsViewState extends State<StatisticsView> {
children: [
StatisticsTile(
icon: Icons.sports_score,
title: AppLocalizations.of(context)!.wins,
title: AppLocalizations.of(context).wins,
width: constraints.maxWidth * 0.95,
values: winCounts,
itemCount: 3,
@@ -78,7 +78,7 @@ class _StatisticsViewState extends State<StatisticsView> {
SizedBox(height: constraints.maxHeight * 0.02),
StatisticsTile(
icon: Icons.percent,
title: AppLocalizations.of(context)!.winrate,
title: AppLocalizations.of(context).winrate,
width: constraints.maxWidth * 0.95,
values: winRates,
itemCount: 5,
@@ -99,7 +99,7 @@ class _StatisticsViewState extends State<StatisticsView> {
),
child: TopCenteredMessage(
icon: Icons.info,
title: AppLocalizations.of(context)!.info,
title: AppLocalizations.of(context).info,
message: AppLocalizations.of(
context,
)!.no_statistics_available,
@@ -154,7 +154,7 @@ class _StatisticsViewState extends State<StatisticsView> {
(p) => p.id == playerId,
orElse: () => Player(
id: playerId,
name: AppLocalizations.of(context)!.not_available,
name: AppLocalizations.of(context).not_available,
),
);
winCounts[i] = (player.name, winCounts[i].$2);
@@ -219,7 +219,7 @@ class _StatisticsViewState extends State<StatisticsView> {
(p) => p.id == playerId,
orElse: () => Player(
id: playerId,
name: AppLocalizations.of(context)!.not_available,
name: AppLocalizations.of(context).not_available,
),
);
matchCounts[i] = (player.name, matchCounts[i].$2);

View File

@@ -97,7 +97,7 @@ class _PlayerSelectionState extends State<PlayerSelection> {
CustomSearchBar(
controller: _searchBarController,
constraints: const BoxConstraints(maxHeight: 45, minHeight: 45),
hintText: AppLocalizations.of(context)!.search_for_players,
hintText: AppLocalizations.of(context).search_for_players,
trailingButtonShown: true,
trailingButtonicon: Icons.add_circle,
trailingButtonEnabled: _searchBarController.text.trim().isNotEmpty,
@@ -141,7 +141,7 @@ class _PlayerSelectionState extends State<PlayerSelection> {
child: selectedPlayers.isEmpty
? Center(
child: Text(
AppLocalizations.of(context)!.no_players_selected,
AppLocalizations.of(context).no_players_selected,
),
)
: SingleChildScrollView(
@@ -185,7 +185,7 @@ class _PlayerSelectionState extends State<PlayerSelection> {
),
const SizedBox(height: 10),
Text(
AppLocalizations.of(context)!.all_players,
AppLocalizations.of(context).all_players,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
@@ -199,11 +199,11 @@ class _PlayerSelectionState extends State<PlayerSelection> {
visible: suggestedPlayers.isNotEmpty,
replacement: TopCenteredMessage(
icon: Icons.info,
title: AppLocalizations.of(context)!.info,
title: AppLocalizations.of(context).info,
message: allPlayers.isEmpty
? AppLocalizations.of(context)!.no_players_created_yet
? AppLocalizations.of(context).no_players_created_yet
: (selectedPlayers.length == allPlayers.length)
? AppLocalizations.of(context)!.all_players_selected
? AppLocalizations.of(context).all_players_selected
: AppLocalizations.of(
context,
)!.no_players_found_with_that_name,
@@ -276,7 +276,7 @@ class _PlayerSelectionState extends State<PlayerSelection> {
backgroundColor: CustomTheme.boxColor,
content: Center(
child: Text(
AppLocalizations.of(context)!.could_not_add_player(playerName),
AppLocalizations.of(context).could_not_add_player(playerName),
style: const TextStyle(color: Colors.white),
),
),

View File

@@ -98,7 +98,7 @@ class _MatchTileState extends State<MatchTile> {
const SizedBox(width: 8),
Expanded(
child: Text(
AppLocalizations.of(context)!.winner(winner.name),
AppLocalizations.of(context).winner(winner.name),
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
@@ -115,7 +115,7 @@ class _MatchTileState extends State<MatchTile> {
if (allPlayers.isNotEmpty) ...[
Text(
AppLocalizations.of(context)!.players,
AppLocalizations.of(context).players,
style: const TextStyle(
fontSize: 13,
color: Colors.grey,
@@ -150,7 +150,7 @@ class _MatchTileState extends State<MatchTile> {
context,
)!.yesterday_at(DateFormat('HH:mm').format(dateTime));
} else if (difference.inDays < 7) {
return AppLocalizations.of(context)!.days_ago(difference.inDays);
return AppLocalizations.of(context).days_ago(difference.inDays);
} else {
return DateFormat('MMM d, yyyy').format(dateTime);
}

View File

@@ -36,7 +36,7 @@ class StatisticsTile extends StatelessWidget {
visible: values.isNotEmpty,
replacement: Center(
heightFactor: 4,
child: Text(AppLocalizations.of(context)!.no_data_available),
child: Text(AppLocalizations.of(context).no_data_available),
),
child: Column(
children: List.generate(min(values.length, itemCount), (index) {