-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add ui for sudoku hint button and hint panel
- Loading branch information
1 parent
45ae62d
commit 49968d9
Showing
12 changed files
with
454 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_bloc/flutter_bloc.dart'; | ||
import 'package:sudoku/layout/layout.dart'; | ||
import 'package:sudoku/puzzle/puzzle.dart'; | ||
import 'package:sudoku/sudoku/sudoku.dart'; | ||
import 'package:sudoku/typography/typography.dart'; | ||
import 'package:sudoku/widgets/widgets.dart'; | ||
|
||
/// {@template ask_hint_button} | ||
/// Displays a button to ask gemini for hint. | ||
/// | ||
/// Disables if the remaining hint count decreases to 0 or | ||
/// a hint request is already in progress. | ||
/// | ||
/// {@endtemplate} | ||
// TODO(thecodexhub): Shows a loading indication when loading in progress. | ||
class AskHintButton extends StatelessWidget { | ||
/// {@macro ask_hint_button} | ||
const AskHintButton({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final remainingHints = context.select( | ||
(PuzzleBloc bloc) => bloc.state.puzzle.remainingHints, | ||
); | ||
|
||
final hintInProgress = context.select( | ||
(PuzzleBloc bloc) => bloc.state.hintStatus.isFetchInProgress, | ||
); | ||
|
||
final buttonBeActive = remainingHints > 0 && !hintInProgress; | ||
|
||
return ResponsiveLayoutBuilder( | ||
small: (_, child) => child!, | ||
medium: (_, child) => child!, | ||
large: (_, child) => child!, | ||
child: (layoutSize) { | ||
final maxWidth = switch (layoutSize) { | ||
ResponsiveLayoutSize.small => SudokuBoardSize.small, | ||
ResponsiveLayoutSize.medium => SudokuBoardSize.medium, | ||
ResponsiveLayoutSize.large => SudokuInputSize.large * 3, | ||
}; | ||
|
||
return Column( | ||
children: [ | ||
SizedBox( | ||
width: maxWidth, | ||
child: SudokuElevatedButton( | ||
height: 45, | ||
buttonText: 'Ask Gemini for a hint', | ||
onPressed: buttonBeActive | ||
? () => context.read<PuzzleBloc>().add( | ||
const SudokuHintRequested(), | ||
) | ||
: null, | ||
), | ||
), | ||
const SizedBox(height: 8), | ||
Text( | ||
'Number of hints remaining: $remainingHints', | ||
style: SudokuTextStyle.caption, | ||
), | ||
], | ||
); | ||
}, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_bloc/flutter_bloc.dart'; | ||
import 'package:sudoku/colors/colors.dart'; | ||
import 'package:sudoku/layout/layout.dart'; | ||
import 'package:sudoku/puzzle/puzzle.dart'; | ||
import 'package:sudoku/sudoku/sudoku.dart'; | ||
import 'package:sudoku/typography/typography.dart'; | ||
import 'package:sudoku/widgets/widgets.dart'; | ||
|
||
/// {@template hint_panel} | ||
/// Widget to display hint. Shows an error message if there was an | ||
/// error in fetching or validating the hint. | ||
/// {@endtemplate} | ||
class HintPanel extends StatelessWidget { | ||
/// {@macro hint_panel} | ||
const HintPanel({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final panelBeOpen = context.select( | ||
(PuzzleBloc bloc) => bloc.state.hintStatus.successOrFailed, | ||
); | ||
|
||
final hintAvailable = context.select( | ||
(PuzzleBloc bloc) => bloc.state.hint != null, | ||
); | ||
|
||
if (!panelBeOpen) { | ||
return const SizedBox(); | ||
} | ||
|
||
return ResponsiveLayoutBuilder( | ||
small: (_, child) => child!, | ||
medium: (_, child) => child!, | ||
large: (_, child) => child!, | ||
child: (layoutSize) { | ||
final maxWidth = switch (layoutSize) { | ||
ResponsiveLayoutSize.small => SudokuBoardSize.small, | ||
ResponsiveLayoutSize.medium => SudokuBoardSize.medium, | ||
ResponsiveLayoutSize.large => 880.0, | ||
}; | ||
|
||
return SizedBox( | ||
width: maxWidth, | ||
child: hintAvailable ? const DisplayHint() : const DisplayError(), | ||
); | ||
}, | ||
); | ||
} | ||
} | ||
|
||
/// {@template display_hint} | ||
/// Widget to display the hint, when fetch was successful. | ||
/// {@endtemplate} | ||
@visibleForTesting | ||
class DisplayHint extends StatelessWidget { | ||
/// {@macro display_hint} | ||
const DisplayHint({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final hint = context.read<PuzzleBloc>().state.hint!; | ||
|
||
final defaulTextStyle = SudokuTextStyle.caption; | ||
final titleTextStyle = SudokuTextStyle.bodyText2.copyWith( | ||
fontWeight: SudokuFontWeight.semiBold, | ||
); | ||
|
||
return DecoratedBox( | ||
decoration: BoxDecoration( | ||
borderRadius: BorderRadius.circular(8), | ||
color: SudokuColors.lightPurple.withOpacity(0.27), | ||
), | ||
child: Padding( | ||
padding: const EdgeInsets.all(12), | ||
child: Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
Text('Observation:', style: titleTextStyle), | ||
const SizedBox(height: 4), | ||
Text(hint.observation, style: defaulTextStyle), | ||
const SizedBox(height: 8), | ||
Text('Explanation:', style: titleTextStyle), | ||
const SizedBox(height: 4), | ||
Text(hint.explanation, style: defaulTextStyle), | ||
const SizedBox(height: 8), | ||
Text('Solution:', style: titleTextStyle), | ||
const SizedBox(height: 4), | ||
Text(hint.solution, style: defaulTextStyle), | ||
const SizedBox(height: 8), | ||
SudokuTextButton( | ||
buttonText: 'Approve & Close', | ||
onPressed: () => context.read<PuzzleBloc>().add( | ||
const HintInteractioCompleted(), | ||
), | ||
), | ||
], | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
/// {@template display_hint} | ||
/// Widget to display the hint, when fetch was successful. | ||
/// {@endtemplate} | ||
@visibleForTesting | ||
class DisplayError extends StatelessWidget { | ||
/// {@macro display_hint} | ||
const DisplayError({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = Theme.of(context); | ||
|
||
return DecoratedBox( | ||
decoration: BoxDecoration( | ||
borderRadius: BorderRadius.circular(8), | ||
color: theme.colorScheme.errorContainer.withOpacity(0.45), | ||
), | ||
child: Padding( | ||
padding: const EdgeInsets.all(12), | ||
child: Column( | ||
children: [ | ||
Text( | ||
'There has been an error while fetching or validating ' | ||
'the hint. Please try again!', | ||
textAlign: TextAlign.center, | ||
style: SudokuTextStyle.caption.copyWith( | ||
color: theme.colorScheme.error, | ||
), | ||
), | ||
], | ||
), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
export 'ask_hint_button.dart'; | ||
export 'congrats_dialog.dart'; | ||
export 'game_over_dialog.dart'; | ||
export 'hint_panel.dart'; | ||
export 'mistakes_count_view.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.