mirror of
https://github.com/lichess-org/mobile.git
synced 2026-05-26 13:50:52 +00:00
Enable stricter type checking
This commit is contained in:
@@ -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
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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(
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user