Skip to content

Commit

Permalink
Merge pull request #122 from lichess-org/loadPuzzleFromSession
Browse files Browse the repository at this point in the history
Load puzzle from session
  • Loading branch information
veloce authored Apr 26, 2023
2 parents ad8e990 + 0272443 commit dd5b6dd
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 41 deletions.
8 changes: 8 additions & 0 deletions lib/src/model/puzzle/puzzle_providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart'
hide Tuple2;

import 'package:lichess_mobile/src/model/common/id.dart';
import 'package:lichess_mobile/src/model/auth/auth_controller.dart';
import 'package:lichess_mobile/src/model/puzzle/puzzle.dart';
import 'package:lichess_mobile/src/model/puzzle/puzzle_theme.dart';
Expand Down Expand Up @@ -32,6 +33,13 @@ Future<PuzzleStreakResponse> streak(StreakRef ref) {
return Result.release(repo.streak());
}

// TODO when history database is available should first try to fetch from there
@Riverpod(keepAlive: true)
Future<Puzzle> puzzle(PuzzleRef ref, PuzzleId id) {
final repo = ref.watch(puzzleRepositoryProvider);
return Result.release(repo.fetch(id));
}

@Riverpod(keepAlive: true)
Future<Puzzle> dailyPuzzle(DailyPuzzleRef ref) {
final repo = ref.watch(puzzleRepositoryProvider);
Expand Down
4 changes: 2 additions & 2 deletions lib/src/ui/puzzle/puzzle_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ class _BottomBar extends ConsumerWidget {
puzzleState.nextContext != null
? () => ref
.read(viewModelProvider.notifier)
.continueWithNextPuzzle(puzzleState.nextContext!)
.loadPuzzle(puzzleState.nextContext!)
: null,
highlighted: true,
label: context.l10n.puzzleContinueTraining,
Expand Down Expand Up @@ -419,7 +419,7 @@ class _DifficultySelector extends ConsumerWidget {
if (context.mounted && nextContext != null) {
ref
.read(viewModelProvider.notifier)
.continueWithNextPuzzle(nextContext);
.loadPuzzle(nextContext);
}
},
);
Expand Down
121 changes: 85 additions & 36 deletions lib/src/ui/puzzle/puzzle_session_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'package:lichess_mobile/src/widgets/table_board_layout.dart';
import 'package:lichess_mobile/src/model/common/id.dart';
import 'package:lichess_mobile/src/model/settings/brightness.dart';
import 'package:lichess_mobile/src/styles/lichess_colors.dart';
import 'package:lichess_mobile/src/model/puzzle/puzzle_providers.dart';
import 'package:lichess_mobile/src/model/puzzle/puzzle_session.dart';
import 'package:lichess_mobile/src/model/puzzle/puzzle_service.dart';

Expand All @@ -27,6 +29,7 @@ class PuzzleSessionWidget extends ConsumerStatefulWidget {

class PuzzleSessionWidgetState extends ConsumerState<PuzzleSessionWidget> {
final lastAttemptKey = GlobalKey();
PuzzleId? loadingPuzzleId;

@override
void initState() {
Expand Down Expand Up @@ -94,13 +97,42 @@ class PuzzleSessionWidgetState extends ConsumerState<PuzzleSessionWidget> {
for (final attempt in session.attempts)
_SessionItem(
isCurrent: attempt.id == puzzleState.puzzle.puzzle.id,
isLoading: loadingPuzzleId == attempt.id,
brightness: brightness,
attempt: attempt,
onTap: puzzleState.puzzle.puzzle.id != attempt.id &&
loadingPuzzleId == null
? (id) async {
final provider = puzzleProvider(id);
setState(() {
loadingPuzzleId = id;
});
try {
final puzzle = await ref.read(provider.future);
final nextContext = PuzzleContext(
userId: widget.initialPuzzleContext.userId,
theme: widget.initialPuzzleContext.theme,
puzzle: puzzle,
);

ref
.read(widget.viewModelProvider.notifier)
.loadPuzzle(nextContext);
} finally {
if (mounted) {
setState(() {
loadingPuzzleId = null;
});
}
}
}
: null,
),
if (puzzleState.mode == PuzzleMode.view ||
currentAttempt == null)
_SessionItem(
isCurrent: currentAttempt == null,
isLoading: false,
brightness: brightness,
key: lastAttemptKey,
),
Expand All @@ -118,13 +150,17 @@ class _SessionItem extends StatelessWidget {
const _SessionItem({
this.attempt,
required this.isCurrent,
required this.isLoading,
required this.brightness,
this.onTap,
super.key,
});

final bool isCurrent;
final bool isLoading;
final PuzzleAttempt? attempt;
final Brightness brightness;
final void Function(PuzzleId id)? onTap;

Color get good => brightness == Brightness.light
? LichessColors.good.shade300
Expand All @@ -142,44 +178,57 @@ class _SessionItem extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Container(
width: 38,
height: 26,
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
decoration: BoxDecoration(
color: isCurrent
? Colors.grey
: attempt != null
? attempt!.win
? good
: error
: next,
borderRadius: const BorderRadius.all(Radius.circular(5)),
),
child: attempt?.ratingDiff != null && attempt!.ratingDiff != 0
? Padding(
padding: const EdgeInsets.all(2.0),
child: FittedBox(
fit: BoxFit.cover,
child: Text(
attempt!.ratingDiffString!,
maxLines: 1,
style: const TextStyle(
color: Colors.white,
height: 1,
return GestureDetector(
onTap: attempt != null ? () => onTap?.call(attempt!.id) : null,
child: Container(
width: 38,
height: 26,
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
decoration: BoxDecoration(
color: isCurrent
? Colors.grey
: attempt != null
? attempt!.win
? good
: error
: next,
borderRadius: const BorderRadius.all(Radius.circular(5)),
),
child: isLoading
? const Padding(
padding: EdgeInsets.all(2.0),
child: FittedBox(
fit: BoxFit.cover,
child: CircularProgressIndicator.adaptive(
backgroundColor: Colors.white,
),
),
),
)
: Icon(
attempt != null
? attempt!.win
? Icons.check
: Icons.close
: null,
color: Colors.white,
size: 18,
),
)
: attempt?.ratingDiff != null && attempt!.ratingDiff != 0
? Padding(
padding: const EdgeInsets.all(2.0),
child: FittedBox(
fit: BoxFit.cover,
child: Text(
attempt!.ratingDiffString!,
maxLines: 1,
style: const TextStyle(
color: Colors.white,
height: 1,
),
),
),
)
: Icon(
attempt != null
? attempt!.win
? Icons.check
: Icons.close
: null,
color: Colors.white,
size: 18,
),
),
);
}
}
2 changes: 1 addition & 1 deletion lib/src/ui/puzzle/puzzle_streak_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ class _RetryFetchPuzzleDialog extends ConsumerWidget {
Navigator.of(context).pop();
}
if (data != null) {
ref.read(viewModelProvider.notifier).continueWithNextPuzzle(data);
ref.read(viewModelProvider.notifier).loadPuzzle(data);
}
},
);
Expand Down
4 changes: 2 additions & 2 deletions lib/src/ui/puzzle/puzzle_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ class PuzzleViewModel extends _$PuzzleViewModel {
return nextPuzzle;
}

void continueWithNextPuzzle(PuzzleContext nextContext) {
void loadPuzzle(PuzzleContext nextContext) {
state = _loadNewContext(nextContext, state.streak);
}

Expand Down Expand Up @@ -338,7 +338,7 @@ class PuzzleViewModel extends _$PuzzleViewModel {
if (nextContext != null) {
await Future<void>.delayed(const Duration(milliseconds: 250));
soundService.play(Sound.confirmation);
continueWithNextPuzzle(nextContext);
loadPuzzle(nextContext);
} else {
// no more puzzle
state = state.copyWith.streak!(
Expand Down

0 comments on commit dd5b6dd

Please sign in to comment.