Enable stricter type checking

This commit is contained in:
Vincent Velociter
2022-12-07 19:48:32 +01:00
parent 5f96006d55
commit 48295c8da1
21 changed files with 73 additions and 61 deletions
+4
View File
@@ -10,6 +10,10 @@
include: package:flutter_lints/flutter.yaml
analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
+3 -3
View File
@@ -46,7 +46,7 @@ class ProviderLogger extends ProviderObserver {
@override
void didAddProvider(
ProviderBase provider,
ProviderBase<Object?> provider,
Object? value,
ProviderContainer container,
) {
@@ -56,7 +56,7 @@ class ProviderLogger extends ProviderObserver {
@override
void didDisposeProvider(
ProviderBase provider,
ProviderBase<Object?> provider,
ProviderContainer container,
) {
_logger.info('${provider.name ?? provider.runtimeType} disposed.');
@@ -64,7 +64,7 @@ class ProviderLogger extends ProviderObserver {
@override
void providerDidFail(
ProviderBase provider,
ProviderBase<Object?> provider,
Object error,
StackTrace stackTrace,
ProviderContainer container,
@@ -86,9 +86,9 @@ class AuthRepository {
}
TaskEither<IOError, User> getAccountTask() {
return _apiClient
.get(Uri.parse('$kLichessHost/api/account'))
.map((response) => User.fromJson(jsonDecode(response.body)));
return _apiClient.get(Uri.parse('$kLichessHost/api/account')).map(
(response) =>
User.fromJson(jsonDecode(response.body) as Map<String, dynamic>));
}
void dispose() {
+1 -1
View File
@@ -17,7 +17,7 @@ class AuthWidget extends ConsumerWidget {
final authState = ref.watch(authStateChangesProvider);
final authActionsAsync = ref.watch(authWidgetProvider);
final brightness = ref.watch(selectedBrigthnessProvider);
ref.listen<AsyncValue>(
ref.listen<AsyncValue<void>>(
authWidgetProvider,
(_, state) => state.showSnackbarOnError(context),
);
@@ -27,7 +27,7 @@ class GameRepository {
yield* resp.stream
.toStringStream()
.where((event) => event.isNotEmpty && event != '\n')
.map((event) => jsonDecode(event));
.map((event) => jsonDecode(event) as Map<String, dynamic>);
}
/// Stream the state of a game being played with the Board API, as ndjson.
@@ -37,7 +37,7 @@ class GameRepository {
yield* resp.stream
.toStringStream()
.where((event) => event.isNotEmpty && event != '\n')
.map((event) => jsonDecode(event));
.map((event) => jsonDecode(event) as Map<String, dynamic>);
}
TaskEither<IOError, void> playMoveTask(GameId gameId, Move move) {
@@ -51,7 +51,7 @@ class CreateGameService {
switch (event['type']) {
case 'gameStart':
final game = event['game'];
if (game['compat']['board']) {
if (game['compat']['board'] as bool) {
final perf = Perf.values.firstWhere(
(v) => v.name == game['perf'],
orElse: () => Perf.blitz);
@@ -61,18 +61,18 @@ class CreateGameService {
rating: account.perfs[perf]!.rating,
);
final opponent = Player(
id: game['opponent']['id'],
name: game['opponent']['username'],
rating: game['opponent']['rating']);
id: game['opponent']['id'] as String?,
name: game['opponent']['username'] as String,
rating: game['opponent']['rating'] as int?);
return Game(
id: GameId(value: game['gameId'] as String),
initialFen: game['fen'],
initialFen: game['fen'] as String,
speed: Speed.values.firstWhere((v) => v.name == game['speed'],
orElse: () => Speed.blitz),
orientation: Side.values.firstWhere(
(v) => v.name == game['color'],
orElse: () => Side.white),
rated: game['rated'],
rated: game['rated'] as bool,
white: game['color'] == 'white' ? player : opponent,
black: game['color'] == 'white' ? opponent : player,
);
@@ -56,11 +56,11 @@ class _BoardScreenState extends ConsumerState<BoardScreen> {
}
});
});
ref.listen<AsyncValue>(
ref.listen<AsyncValue<void>>(
gameActionProvider,
(_, state) => state.showSnackbarOnError(context),
);
ref.listen<AsyncValue>(playActionProvider, (_, state) {
ref.listen<AsyncValue<Game?>>(playActionProvider, (_, state) {
state.showSnackbarOnError(context);
if (state.valueOrNull is Game) {
@@ -69,7 +69,7 @@ class _BoardScreenState extends ConsumerState<BoardScreen> {
ref.invalidate(isBoardTurnedProvider);
ref.invalidate(gameStateProvider);
Navigator.of(context).pushReplacement(
MaterialPageRoute(
MaterialPageRoute<void>(
builder: (context) =>
BoardScreen(game: state.value!, account: widget.account)),
);
@@ -13,7 +13,7 @@ class GameStateNotifier extends AutoDisposeNotifier<GameState?> {
return null;
}
onGameStateEvent(Map<String, dynamic> json) {
void onGameStateEvent(Map<String, dynamic> json) {
final soundService = ref.read(soundServiceProvider);
final newState = GameState.fromJson(json);
@@ -36,7 +36,7 @@ class GameStateNotifier extends AutoDisposeNotifier<GameState?> {
state = newState;
}
onUserMove(GameId gameId, Move move) async {
void onUserMove(GameId gameId, Move move) async {
final gameRepository = ref.read(gameRepositoryProvider);
final savedState = state;
if (state != null) {
@@ -18,8 +18,8 @@ final gameStreamProvider =
event['type'] == 'gameFull' || event['type'] == 'gameState')
.map((raw) {
if (raw['type'] == 'gameFull') {
gameStateNotifier.onGameStateEvent(raw['state']);
return GameClock.fromJson(raw['state']);
gameStateNotifier.onGameStateEvent(raw['state'] as Map<String, dynamic>);
return GameClock.fromJson(raw['state'] as Map<String, dynamic>);
} else {
gameStateNotifier.onGameStateEvent(raw);
return GameClock.fromJson(raw);
@@ -82,13 +82,13 @@ class PlayForm extends ConsumerWidget {
final authActionsAsync = ref.watch(authWidgetProvider);
final playActionAsync = ref.watch(playActionProvider);
ref.listen<AsyncValue>(playActionProvider, (_, state) {
ref.listen<AsyncValue<Game?>>(playActionProvider, (_, state) {
state.showSnackbarOnError(context);
if (state.valueOrNull is Game && account != null) {
ref.invalidate(playActionProvider);
Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute(
MaterialPageRoute<void>(
builder: (context) =>
BoardScreen(game: state.value!, account: account!)),
);
@@ -214,9 +214,9 @@ class PlayForm extends ConsumerWidget {
}).toList(),
);
},
error: (err, __) {
error: (err, st) {
debugPrint(
'SEVERE [PlayScreen] could not load bot info: ${err.toString()}');
'SEVERE [PlayScreen] could not load bot info: ${err.toString()}\n$st');
return const Text('Could not load bot ratings.');
},
loading: () => const CircularProgressIndicator.adaptive(),
@@ -4,7 +4,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../data/settings_repository.dart';
class ThemeModeNotifier extends StateNotifier<ThemeMode> {
ThemeModeNotifier(this.ref, initialThemeMode) : super(initialThemeMode);
ThemeModeNotifier(this.ref, ThemeMode initialThemeMode)
: super(initialThemeMode);
final Ref ref;
@@ -11,7 +11,7 @@ class ThemeModeScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final themeMode = ref.watch(themeModeProvider);
void onChanged(value) => ref
void onChanged(ThemeMode? value) => ref
.read(themeModeProvider.notifier)
.changeTheme(value ?? ThemeMode.system);
+1 -1
View File
@@ -22,7 +22,7 @@ class TvRepository {
yield* resp.stream
.toStringStream()
.where((event) => event.isNotEmpty && event != '\n')
.map((event) => jsonDecode(event));
.map((event) => jsonDecode(event) as Map<String, dynamic>);
}
void dispose() {
+6 -3
View File
@@ -20,11 +20,14 @@ class FeaturedGame with _$FeaturedGame {
return FeaturedGame(
id: GameId(value: json['id'] as String),
initialFen: json['fen'] as String,
orientation: json['orientation'] == 'white' ? Side.white : Side.black,
orientation:
json['orientation'] as String == 'white' ? Side.white : Side.black,
white: FeaturedPlayer.fromJson(
json['players'].firstWhere((p) => p['color'] == 'white')),
(json['players'] as List<Map<String, dynamic>>)
.firstWhere((p) => p['color'] == 'white')),
black: FeaturedPlayer.fromJson(
json['players'].firstWhere((p) => p['color'] == 'black')),
(json['players'] as List<Map<String, dynamic>>)
.firstWhere((p) => p['color'] == 'black')),
);
}
}
@@ -17,10 +17,10 @@ class FeaturedPlayer with _$FeaturedPlayer {
factory FeaturedPlayer.fromJson(Map<String, dynamic> json) {
return FeaturedPlayer(
side: json['color'] == 'white' ? Side.white : Side.black,
name: json['user']['name'],
title: json['user']['title'],
rating: json['rating'],
seconds: json['seconds'],
name: json['user']['name'] as String,
title: json['user']['title'] as String?,
rating: json['rating'] as int?,
seconds: json['seconds'] as int,
);
}
@@ -16,12 +16,12 @@ class FeaturedPosition with _$FeaturedPosition {
factory FeaturedPosition.fromJson(Map<String, dynamic> json) {
return FeaturedPosition(
fen: json['fen'],
fen: json['fen'] as String,
turn: json['fen'].substring(json['fen'].length - 1) == 'w'
? Side.white
: Side.black,
lastMove: json['lm'] != null ? Move.fromUci(json['lm']) : null,
position: Chess.fromSetup(Setup.parseFen(json['fen'])),
lastMove: json['lm'] != null ? Move.fromUci(json['lm'] as String) : null,
position: Chess.fromSetup(Setup.parseFen(json['fen'] as String)),
);
}
+6 -4
View File
@@ -17,13 +17,15 @@ final tvStreamProvider = StreamProvider.autoDispose<FeaturedPosition>((ref) {
return tvRepository.tvFeed().map((raw) {
switch (raw['t']) {
case 'featured':
featuredGameNotifier.onFeaturedEvent(FeaturedGame.fromJson(raw['d']));
return FeaturedPosition.fromJson(raw['d']);
featuredGameNotifier.onFeaturedEvent(
FeaturedGame.fromJson(raw['d'] as Map<String, dynamic>));
return FeaturedPosition.fromJson(raw['d'] as Map<String, dynamic>);
case 'fen':
featuredGameNotifier.onFenEvent(FenEvent.fromJson(raw['d']));
featuredGameNotifier
.onFenEvent(FenEvent.fromJson(raw['d'] as Map<String, dynamic>));
soundService.playMove();
return FeaturedPosition.fromJson(raw['d']);
return FeaturedPosition.fromJson(raw['d'] as Map<String, dynamic>);
default:
throw Exception('Unsupported event $raw');
@@ -15,16 +15,16 @@ class UserRepository {
final ApiClient apiClient;
TaskEither<IOError, User> getUserTask(String username) {
return apiClient
.get(Uri.parse('$kLichessHost/api/user/$username'))
.map((response) => User.fromJson(jsonDecode(response.body)));
return apiClient.get(Uri.parse('$kLichessHost/api/user/$username')).map(
(response) =>
User.fromJson(jsonDecode(response.body) as Map<String, dynamic>));
}
TaskEither<IOError, List<UserStatus>> getUsersStatusTask(List<String> ids) {
return apiClient
.get(Uri.parse('$kLichessHost/api/users/status?ids=${ids.join(',')}'))
.map((response) => jsonDecode(response.body)
.map<UserStatus>((e) => UserStatus.fromJson(e))
.map((response) => (jsonDecode(response.body) as List<dynamic>)
.map((e) => UserStatus.fromJson(e as Map<String, dynamic>))
.toList());
}
+12 -10
View File
@@ -23,18 +23,20 @@ class User with _$User {
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
username: json['username'],
title: json['title'],
patron: json['patron'],
createdAt: DateTime.fromMillisecondsSinceEpoch(json['createdAt']),
seenAt: DateTime.fromMillisecondsSinceEpoch(json['seenAt']),
profile:
json['profile'] != null ? Profile.fromJson(json['profile']) : null,
id: json['id'] as String,
username: json['username'] as String,
title: json['title'] as String?,
patron: json['patron'] as bool?,
createdAt: DateTime.fromMillisecondsSinceEpoch(json['createdAt'] as int),
seenAt: DateTime.fromMillisecondsSinceEpoch(json['seenAt'] as int),
profile: json['profile'] != null
? Profile.fromJson(json['profile'] as Map<String, dynamic>)
: null,
perfs: Map.unmodifiable({
for (final entry in json['perfs'].entries)
for (final entry in (json['perfs'] as Map<String, dynamic>).entries)
if (entry.key != 'storm')
Perf.values.byName(entry.key): UserPerf.fromJson(entry.value)
Perf.values.byName(entry.key):
UserPerf.fromJson(entry.value as Map<String, dynamic>)
}),
);
}
+1 -1
View File
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
extension AsyncValueUI on AsyncValue {
extension AsyncValueUI on AsyncValue<Object?> {
void showSnackbarOnError(BuildContext context) {
if (!isRefreshing && hasError) {
ScaffoldMessenger.of(context).showSnackBar(
+2 -2
View File
@@ -31,7 +31,7 @@ class FakeAuthRepository implements AuthRepository {
@override
TaskEither<IOError, void> signInTask() {
return TaskEither(() async {
await Future.delayed(const Duration(milliseconds: 5));
await Future<void>.delayed(const Duration(milliseconds: 5));
_authState.value = fakeUser;
return Either.right(null);
});
@@ -40,7 +40,7 @@ class FakeAuthRepository implements AuthRepository {
@override
TaskEither<IOError, void> signOutTask() {
return TaskEither(() async {
await Future.delayed(const Duration(milliseconds: 5));
await Future<void>.delayed(const Duration(milliseconds: 5));
_authState.value = null;
return Either.right(null);
});