Skip to content

Commit

Permalink
feat: Question page in a Dialog-like container (+ some fixes) (#4109)
Browse files Browse the repository at this point in the history
* Move the question page into a Dialog

* Improve the accessibility of this screen
  • Loading branch information
g123k authored Jun 10, 2023
1 parent c434341 commit 386e6b6
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ class _ProductTitleCardName extends StatelessWidget {
getProductName(product, appLocalizations),
style: Theme.of(context).textTheme.headlineMedium,
textAlign: TextAlign.start,
maxLines: 3,
overflow: TextOverflow.ellipsis,
).selectable(isSelectable: selectable);
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/smooth_app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@
"description": "Button description shown on a product, clicking the button opens a card with unanswered product questions, users can answer these to contribute to Open food facts and gain rewards."
},
"question_sign_in_text": "Sign in to your Open Food Facts account to get credit for your contributions",
"question_yes_button_accessibility_value": "Answer with yes",
"question_no_button_accessibility_value": "Answer with no",
"question_skip_button_accessibility_value": "Skip this question",
"tap_to_edit_search": "Tap to edit search",
"@Personal preferences": {},
"myPreferences": "My preferences",
Expand Down Expand Up @@ -1894,7 +1897,7 @@
"app_rating_dialog_title": "Great! Let others know what you think of this app!",
"app_rating_dialog_positive_action": "Rate the app",
"app_rating_dialog_negative_action": "Later",
"app_rating_dialog_title_enjoying_app": "Are You enjoying this app?",
"app_rating_dialog_title_enjoying_app": "Are you enjoying this app?",
"app_rating_dialog_title_enjoying_positive_actions": "Yeah!",
"not_really": "Not really",
"app_rating_dialog_title_not_enjoying_app": "We are so sorry to hear that! Could you tell us what happened?",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,47 +25,46 @@ class QuestionAnswersOptions extends StatelessWidget {
Widget build(BuildContext context) {
final double yesNoHeight = MediaQuery.of(context).size.width / (3 * 1.25);

return Expanded(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: SizedBox(
height: yesNoHeight,
child: _buildAnswerButton(
context,
insightAnnotation: InsightAnnotation.NO,
backgroundColor: _noBackground,
contentColor: _yesNoTextColor,
),
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: SizedBox(
height: yesNoHeight,
child: _buildAnswerButton(
context,
insightAnnotation: InsightAnnotation.NO,
backgroundColor: _noBackground,
contentColor: _yesNoTextColor,
),
),
Expanded(
child: SizedBox(
height: yesNoHeight,
child: _buildAnswerButton(
context,
insightAnnotation: InsightAnnotation.YES,
backgroundColor: _yesBackground,
contentColor: _yesNoTextColor,
),
),
Expanded(
child: SizedBox(
height: yesNoHeight,
child: _buildAnswerButton(
context,
insightAnnotation: InsightAnnotation.YES,
backgroundColor: _yesBackground,
contentColor: _yesNoTextColor,
),
),
],
),
SizedBox(
width: double.infinity,
child: _buildAnswerButton(
context,
insightAnnotation: InsightAnnotation.MAYBE,
backgroundColor: _maybeBackground,
contentColor: _maybeTextColor,
),
],
),
SizedBox(
width: double.infinity,
child: _buildAnswerButton(
context,
insightAnnotation: InsightAnnotation.MAYBE,
backgroundColor: _maybeBackground,
contentColor: _maybeTextColor,
),
],
),
),
],
);
}

Expand All @@ -80,41 +79,51 @@ class QuestionAnswersOptions extends StatelessWidget {
final ThemeData theme = Theme.of(context);

String buttonText;
String hintText;
IconData iconData;
switch (insightAnnotation) {
case InsightAnnotation.YES:
buttonText = appLocalizations.yes;
hintText = appLocalizations.question_yes_button_accessibility_value;
iconData = Icons.check;
break;
case InsightAnnotation.NO:
buttonText = appLocalizations.no;
hintText = appLocalizations.question_no_button_accessibility_value;
iconData = Icons.clear;
break;
case InsightAnnotation.MAYBE:
buttonText = appLocalizations.skip;
hintText = appLocalizations.question_skip_button_accessibility_value;
iconData = Icons.question_mark;
}

return Padding(
padding: padding,
child: TextButton.icon(
onPressed: () => onAnswer(insightAnnotation),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(backgroundColor),
shape: MaterialStateProperty.all(
const RoundedRectangleBorder(
borderRadius: ROUNDED_BORDER_RADIUS,
return Semantics(
value: buttonText,
hint: hintText,
excludeSemantics: true,
button: true,
child: Padding(
padding: padding,
child: TextButton.icon(
onPressed: () => onAnswer(insightAnnotation),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(backgroundColor),
shape: MaterialStateProperty.all(
const RoundedRectangleBorder(
borderRadius: ROUNDED_BORDER_RADIUS,
),
),
),
),
icon: Icon(
iconData,
color: contentColor,
size: 36,
),
label: Text(
buttonText,
style: theme.textTheme.displayMedium!.apply(color: contentColor),
icon: Icon(
iconData,
color: contentColor,
size: 36,
),
label: Text(
buttonText,
style: theme.textTheme.displayMedium!.apply(color: contentColor),
),
),
),
);
Expand Down
58 changes: 34 additions & 24 deletions packages/smooth_app/lib/pages/hunger_games/question_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,33 +47,42 @@ class QuestionCard extends StatelessWidget {
if (product == null) {
return _buildQuestionShimmer();
}
return Card(
elevation: 4,
clipBehavior: Clip.antiAlias,
shape: const RoundedRectangleBorder(
borderRadius: ROUNDED_BORDER_RADIUS,
),
child: Column(
children: <Widget>[
ProductImageCarousel(
product,
height: screenSize.height / 6,
alternateImageUrl: question.imageUrl,
return Semantics(
value: '${question.question} ${question.value}',
readOnly: true,
child: ExcludeSemantics(
child: Card(
elevation: 4,
clipBehavior: Clip.antiAlias,
shape: const RoundedRectangleBorder(
borderRadius: ROUNDED_BORDER_RADIUS,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: SMALL_SPACE),
child: Column(
children: <Widget>[
ProductTitleCard(
product,
true,
dense: true,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ProductImageCarousel(
product,
height: screenSize.height / 6,
alternateImageUrl: question.imageUrl,
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: SMALL_SPACE),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ProductTitleCard(
product,
true,
dense: true,
),
],
),
],
),
),
_buildQuestionText(context, question),
],
),
_buildQuestionText(context, question),
],
),
),
);
},
Expand All @@ -85,6 +94,7 @@ class QuestionCard extends StatelessWidget {
color: robotoffBackground,
padding: const EdgeInsets.all(SMALL_SPACE),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
alignment: Alignment.center,
Expand Down
85 changes: 76 additions & 9 deletions packages/smooth_app/lib/pages/hunger_games/question_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
Expand All @@ -13,10 +15,28 @@ import 'package:smooth_app/pages/hunger_games/question_card.dart';
import 'package:smooth_app/query/product_questions_query.dart';
import 'package:smooth_app/query/questions_query.dart';
import 'package:smooth_app/query/random_questions_query.dart';
import 'package:smooth_app/widgets/smooth_scaffold.dart';

class QuestionPage extends StatefulWidget {
const QuestionPage({
Future<void> openQuestionPage(
BuildContext context, {
Product? product,
List<RobotoffQuestion>? questions,
Function()? updateProductUponAnswers,
}) =>
showDialog<void>(
context: context,
barrierColor: Colors.black.withOpacity(0.7),
builder: (_) => BackdropFilter(
filter: ImageFilter.blur(sigmaX: 1.0, sigmaY: 1.0),
child: _QuestionPage(
product: product,
questions: questions,
updateProductUponAnswers: updateProductUponAnswers,
),
),
);

class _QuestionPage extends StatefulWidget {
const _QuestionPage({
this.product,
this.questions,
this.updateProductUponAnswers,
Expand All @@ -25,13 +45,14 @@ class QuestionPage extends StatefulWidget {
final Product? product;
final List<RobotoffQuestion>? questions;
final Function()? updateProductUponAnswers;

bool get shouldDisplayContinueButton => product == null;

@override
State<QuestionPage> createState() => _QuestionPageState();
State<_QuestionPage> createState() => _QuestionPageState();
}

class _QuestionPageState extends State<QuestionPage>
class _QuestionPageState extends State<_QuestionPage>
with SingleTickerProviderStateMixin, TraceableClientMixin {
final Map<String, InsightAnnotation> _anonymousAnnotationList =
<String, InsightAnnotation>{};
Expand Down Expand Up @@ -91,10 +112,19 @@ class _QuestionPageState extends State<QuestionPage>
}
return true;
},
child: SmoothScaffold(
backgroundColor: Theme.of(context).colorScheme.background,
appBar: AppBar(),
body: _buildAnimationSwitcher(),
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: _buildAnimationSwitcher(),
),
Positioned.directional(
textDirection: Directionality.of(context),
top: 0.0,
start: SMALL_SPACE,
child: const _CloseButton(),
),
],
),
);

Expand Down Expand Up @@ -179,6 +209,7 @@ class _QuestionPageState extends State<QuestionPage>
final RobotoffQuestion question = questions[questionIndex];

return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
QuestionCard(
question,
Expand Down Expand Up @@ -218,3 +249,39 @@ class _QuestionPageState extends State<QuestionPage>
);
}
}

class _CloseButton extends StatelessWidget {
const _CloseButton();

@override
Widget build(BuildContext context) {
final String tooltip = MaterialLocalizations.of(context).closeButtonTooltip;

return Semantics(
value: tooltip,
button: true,
excludeSemantics: true,
child: Material(
type: MaterialType.button,
shape: const CircleBorder(),
color: Theme.of(context).primaryColor,
child: InkWell(
customBorder: const CircleBorder(),
onTap: () => Navigator.maybePop(context),
child: Tooltip(
message: tooltip,
child: Container(
width: kToolbarHeight,
height: kToolbarHeight,
alignment: Alignment.center,
child: const Icon(
Icons.close,
color: Colors.white,
),
),
),
),
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,7 @@ class UserPreferencesContribute extends AbstractUserPreferences {
},
);

Future<void> _hungerGames() async => Navigator.push(
context,
MaterialPageRoute<QuestionPage>(
builder: (_) => const QuestionPage(),
),
);
Future<void> _hungerGames() async => openQuestionPage(context);

Widget _getListTile(
final String title,
Expand Down
Loading

0 comments on commit 386e6b6

Please sign in to comment.