feat: show instruction overlay on first gain points in activity pointing user to click activity stats button (#4099)
This commit is contained in:
parent
c8e67a5c89
commit
e10f2bebeb
8 changed files with 388 additions and 158 deletions
|
|
@ -5251,5 +5251,6 @@
|
|||
"courseTitle": "Course title",
|
||||
"courseDesc": "Course description",
|
||||
"courseSavedSuccessfully": "Course saved successfully",
|
||||
"addCoursePlan": "Add a course plan"
|
||||
"addCoursePlan": "Add a course plan",
|
||||
"activityStatsButtonInstruction": "Click here to view your activity stats and to close the activity when finished"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,18 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pages/chat/chat.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/activity_summary/activity_summary_analytics_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/overlay.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/pressable_button.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
|
||||
class ActivityStatsButton extends StatefulWidget {
|
||||
final ChatController controller;
|
||||
|
|
@ -36,9 +41,69 @@ class _ActivityStatsButtonState extends State<ActivityStatsButton> {
|
|||
|
||||
_analyticsSubscription = widget
|
||||
.controller.pangeaController.getAnalytics.analyticsStream.stream
|
||||
.listen((_) {
|
||||
_updateAnalytics();
|
||||
});
|
||||
.listen((_) => _updateAnalytics());
|
||||
}
|
||||
|
||||
Client get client => widget.controller.room.client;
|
||||
|
||||
void _showInstructionPopup() {
|
||||
if (InstructionsEnum.activityStatsMenu.isToggledOff || xpCount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final renderObject = context.findRenderObject() as RenderBox;
|
||||
final offset = renderObject.localToGlobal(Offset.zero);
|
||||
|
||||
final cellRect = Rect.fromLTWH(
|
||||
offset.dx,
|
||||
offset.dy,
|
||||
renderObject.size.width,
|
||||
renderObject.size.height,
|
||||
);
|
||||
|
||||
OverlayUtil.showTutorialOverlay(
|
||||
context,
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
width: 200,
|
||||
alignment: Alignment.center,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.info_outlined,
|
||||
size: 16.0,
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
),
|
||||
const WidgetSpan(child: SizedBox(width: 4.0)),
|
||||
TextSpan(
|
||||
text: L10n.of(context).activityStatsButtonInstruction,
|
||||
),
|
||||
],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
cellRect,
|
||||
borderRadius: 12.0,
|
||||
padding: 8.0,
|
||||
onClick: () => widget.controller.setShowDropdown(true),
|
||||
onDismiss: () {
|
||||
InstructionsEnum.activityStatsMenu.setToggledOff(true);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -48,60 +113,61 @@ class _ActivityStatsButtonState extends State<ActivityStatsButton> {
|
|||
}
|
||||
|
||||
int get xpCount => analytics.totalXPForUser(
|
||||
Matrix.of(context).client.userID ?? '',
|
||||
client.userID!,
|
||||
);
|
||||
|
||||
int get vocabCount => analytics.uniqueConstructCountForUser(
|
||||
widget.controller.room.client.userID!,
|
||||
client.userID!,
|
||||
ConstructTypeEnum.vocab,
|
||||
);
|
||||
|
||||
int get grammarCount => analytics.uniqueConstructCountForUser(
|
||||
widget.controller.room.client.userID!,
|
||||
client.userID!,
|
||||
ConstructTypeEnum.morph,
|
||||
);
|
||||
|
||||
Future<void> _updateAnalytics() async {
|
||||
final prevXP = xpCount;
|
||||
final analytics = await widget.controller.room.getActivityAnalytics();
|
||||
if (mounted) {
|
||||
setState(() => this.analytics = analytics);
|
||||
if (prevXP == 0 && xpCount > 0) _showInstructionPopup();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 300,
|
||||
height: 55,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
onTap: () => widget.controller.setShowDropdown(
|
||||
!widget.controller.showActivityDropdown,
|
||||
final theme = Theme.of(context);
|
||||
return PressableButton(
|
||||
onPressed: () => widget.controller.setShowDropdown(
|
||||
!widget.controller.showActivityDropdown,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: xpCount > 0
|
||||
? AppConfig.gold.withAlpha(180)
|
||||
: theme.colorScheme.surface,
|
||||
depressed: xpCount <= 0 || widget.controller.showActivityDropdown,
|
||||
child: AnimatedContainer(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
width: 300,
|
||||
height: 55,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: xpCount > 0
|
||||
? AppConfig.gold.withAlpha(180)
|
||||
: theme.colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: AppConfig.goldLight.withAlpha(100),
|
||||
shape: RoundedRectangleBorder(
|
||||
side: const BorderSide(
|
||||
width: 0.20,
|
||||
color: AppConfig.gold,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_StatsBadge(icon: Icons.radar, value: "$xpCount XP"),
|
||||
_StatsBadge(icon: Symbols.dictionary, value: "$vocabCount"),
|
||||
_StatsBadge(
|
||||
icon: Symbols.toys_and_games,
|
||||
value: "$grammarCount",
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_StatsBadge(icon: Icons.radar, value: "$xpCount XP"),
|
||||
_StatsBadge(icon: Symbols.dictionary, value: "$vocabCount"),
|
||||
_StatsBadge(
|
||||
icon: Symbols.toys_and_games,
|
||||
value: "$grammarCount",
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class PangeaAnyState {
|
|||
BuildContext context, {
|
||||
String? overlayKey,
|
||||
bool canPop = true,
|
||||
bool rootOverlay = false,
|
||||
}) {
|
||||
if (overlayKey != null &&
|
||||
entries.any((element) => element.key == overlayKey)) {
|
||||
|
|
@ -62,7 +63,10 @@ class PangeaAnyState {
|
|||
activeOverlays.add(overlayKey);
|
||||
}
|
||||
|
||||
Overlay.of(context).insert(entry);
|
||||
Overlay.of(
|
||||
context,
|
||||
rootOverlay: rootOverlay,
|
||||
).insert(entry);
|
||||
}
|
||||
|
||||
void closeOverlay([String? overlayKey]) {
|
||||
|
|
|
|||
40
lib/pangea/common/utils/cutout_painter.dart
Normal file
40
lib/pangea/common/utils/cutout_painter.dart
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class CutoutBackgroundPainter extends CustomPainter {
|
||||
final Rect holeRect;
|
||||
final Color backgroundColor;
|
||||
final double borderRadius;
|
||||
final double padding;
|
||||
|
||||
CutoutBackgroundPainter({
|
||||
required this.holeRect,
|
||||
required this.backgroundColor,
|
||||
required this.borderRadius,
|
||||
this.padding = 6.0,
|
||||
});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()..color = backgroundColor;
|
||||
|
||||
final path = Path()
|
||||
..addRect(Rect.fromLTWH(0, 0, size.width, size.height))
|
||||
..addRRect(
|
||||
RRect.fromRectAndRadius(
|
||||
Rect.fromLTWH(
|
||||
holeRect.left - padding,
|
||||
holeRect.top - padding,
|
||||
holeRect.width + 2 * padding,
|
||||
holeRect.height + 2 * padding,
|
||||
),
|
||||
Radius.circular(borderRadius),
|
||||
),
|
||||
)
|
||||
..fillType = PathFillType.evenOdd;
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) => true;
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
import 'dart:developer';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/any_state_holder.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/anchored_overlay_widget.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/overlay_container.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/transparent_backdrop.dart';
|
||||
import '../../../config/themes.dart';
|
||||
import '../../../widgets/matrix.dart';
|
||||
import 'error_handler.dart';
|
||||
|
|
@ -22,8 +22,8 @@ class OverlayUtil {
|
|||
required BuildContext context,
|
||||
required Widget child,
|
||||
String? transformTargetId,
|
||||
backDropToDismiss = true,
|
||||
blurBackground = false,
|
||||
bool backDropToDismiss = true,
|
||||
bool blurBackground = false,
|
||||
Color? borderColor,
|
||||
Color? backgroundColor,
|
||||
bool closePrevOverlay = true,
|
||||
|
|
@ -118,7 +118,7 @@ class OverlayUtil {
|
|||
required String transformTargetId,
|
||||
required double maxHeight,
|
||||
required double maxWidth,
|
||||
backDropToDismiss = true,
|
||||
bool backDropToDismiss = true,
|
||||
Color? borderColor,
|
||||
bool closePrevOverlay = true,
|
||||
String? overlayKey,
|
||||
|
|
@ -214,107 +214,32 @@ class OverlayUtil {
|
|||
}
|
||||
}
|
||||
|
||||
static bool get isOverlayOpen => MatrixState.pAnyState.entries.isNotEmpty;
|
||||
}
|
||||
|
||||
class TransparentBackdrop extends StatefulWidget {
|
||||
final Color? backgroundColor;
|
||||
final VoidCallback? onDismiss;
|
||||
final bool blurBackground;
|
||||
|
||||
const TransparentBackdrop({
|
||||
super.key,
|
||||
this.onDismiss,
|
||||
this.backgroundColor,
|
||||
this.blurBackground = false,
|
||||
});
|
||||
|
||||
@override
|
||||
TransparentBackdropState createState() => TransparentBackdropState();
|
||||
}
|
||||
|
||||
class TransparentBackdropState extends State<TransparentBackdrop>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _opacityTween;
|
||||
late Animation<double> _blurTween;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration:
|
||||
const Duration(milliseconds: AppConfig.overlayAnimationDuration),
|
||||
vsync: this,
|
||||
);
|
||||
_opacityTween = Tween<double>(begin: 0.0, end: 0.8).animate(
|
||||
CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
),
|
||||
);
|
||||
_blurTween = Tween<double>(begin: 0.0, end: 3.0).animate(
|
||||
CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
),
|
||||
);
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
if (mounted) _controller.forward();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _opacityTween,
|
||||
builder: (context, _) {
|
||||
return Material(
|
||||
borderOnForeground: false,
|
||||
color: widget.backgroundColor
|
||||
?.withAlpha((_opacityTween.value * 255).round()) ??
|
||||
Colors.transparent,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
hoverColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
focusColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
onTap: () {
|
||||
if (widget.onDismiss != null) {
|
||||
widget.onDismiss!();
|
||||
}
|
||||
MatrixState.pAnyState.closeOverlay();
|
||||
},
|
||||
child: AnimatedBuilder(
|
||||
animation: _blurTween,
|
||||
builder: (context, _) {
|
||||
return BackdropFilter(
|
||||
filter: widget.blurBackground
|
||||
? ImageFilter.blur(
|
||||
sigmaX: _blurTween.value,
|
||||
sigmaY: _blurTween.value,
|
||||
)
|
||||
: ImageFilter.blur(sigmaX: 0, sigmaY: 0),
|
||||
child: Container(
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
color: Colors.transparent,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
// ),
|
||||
static void showTutorialOverlay(
|
||||
BuildContext context,
|
||||
Widget overlayContent,
|
||||
Rect anchorRect, {
|
||||
double? borderRadius,
|
||||
double? padding,
|
||||
final VoidCallback? onClick,
|
||||
final VoidCallback? onDismiss,
|
||||
}) {
|
||||
MatrixState.pAnyState.closeAllOverlays();
|
||||
final entry = OverlayEntry(
|
||||
builder: (context) {
|
||||
return AnchoredOverlayWidget(
|
||||
anchorRect: anchorRect,
|
||||
borderRadius: borderRadius,
|
||||
padding: padding,
|
||||
onClick: onClick,
|
||||
onDismiss: onDismiss,
|
||||
child: overlayContent,
|
||||
);
|
||||
},
|
||||
);
|
||||
MatrixState.pAnyState.openOverlay(
|
||||
entry,
|
||||
context,
|
||||
rootOverlay: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
97
lib/pangea/common/widgets/anchored_overlay_widget.dart
Normal file
97
lib/pangea/common/widgets/anchored_overlay_widget.dart
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/cutout_painter.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class AnchoredOverlayWidget extends StatefulWidget {
|
||||
final Widget child;
|
||||
final Rect anchorRect;
|
||||
final double? borderRadius;
|
||||
final double? padding;
|
||||
final VoidCallback? onClick;
|
||||
final VoidCallback? onDismiss;
|
||||
|
||||
const AnchoredOverlayWidget({
|
||||
required this.child,
|
||||
required this.anchorRect,
|
||||
this.borderRadius,
|
||||
this.padding,
|
||||
this.onClick,
|
||||
this.onDismiss,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AnchoredOverlayWidget> createState() => _AnchoredOverlayWidgetState();
|
||||
}
|
||||
|
||||
class _AnchoredOverlayWidgetState extends State<AnchoredOverlayWidget> {
|
||||
bool _visible = false;
|
||||
|
||||
static const double overlayWidth = 200.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) => setState(() {
|
||||
_visible = true;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final leftPosition = (widget.anchorRect.left +
|
||||
(widget.anchorRect.width / 2) -
|
||||
(overlayWidth / 2))
|
||||
.clamp(8.0, MediaQuery.sizeOf(context).width - overlayWidth - 8.0);
|
||||
|
||||
return AnimatedOpacity(
|
||||
opacity: _visible ? 1.0 : 0.0,
|
||||
duration: FluffyThemes.animationDuration,
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTapDown: (details) {
|
||||
final tapPos = details.globalPosition;
|
||||
if (widget.anchorRect.contains(tapPos)) {
|
||||
widget.onClick?.call();
|
||||
}
|
||||
|
||||
widget.onDismiss?.call();
|
||||
MatrixState.pAnyState.closeOverlay();
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: CustomPaint(
|
||||
painter: CutoutBackgroundPainter(
|
||||
holeRect: widget.anchorRect,
|
||||
backgroundColor: Colors.black54,
|
||||
borderRadius: widget.borderRadius ?? 0.0,
|
||||
padding: widget.padding ?? 6.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: leftPosition,
|
||||
top: widget.anchorRect.bottom + (widget.padding ?? 6.0),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
elevation: 4,
|
||||
child: SizedBox(
|
||||
width: overlayWidth,
|
||||
child: widget.child,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
108
lib/pangea/common/widgets/transparent_backdrop.dart
Normal file
108
lib/pangea/common/widgets/transparent_backdrop.dart
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import '../../../config/themes.dart';
|
||||
import '../../../widgets/matrix.dart';
|
||||
|
||||
class TransparentBackdrop extends StatefulWidget {
|
||||
final Color? backgroundColor;
|
||||
final VoidCallback? onDismiss;
|
||||
final bool blurBackground;
|
||||
|
||||
const TransparentBackdrop({
|
||||
super.key,
|
||||
this.onDismiss,
|
||||
this.backgroundColor,
|
||||
this.blurBackground = false,
|
||||
});
|
||||
|
||||
@override
|
||||
TransparentBackdropState createState() => TransparentBackdropState();
|
||||
}
|
||||
|
||||
class TransparentBackdropState extends State<TransparentBackdrop>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _opacityTween;
|
||||
late Animation<double> _blurTween;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration:
|
||||
const Duration(milliseconds: AppConfig.overlayAnimationDuration),
|
||||
vsync: this,
|
||||
);
|
||||
_opacityTween = Tween<double>(begin: 0.0, end: 0.8).animate(
|
||||
CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
),
|
||||
);
|
||||
_blurTween = Tween<double>(begin: 0.0, end: 3.0).animate(
|
||||
CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
),
|
||||
);
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
if (mounted) _controller.forward();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _opacityTween,
|
||||
builder: (context, _) {
|
||||
return Material(
|
||||
borderOnForeground: false,
|
||||
color: widget.backgroundColor
|
||||
?.withAlpha((_opacityTween.value * 255).round()) ??
|
||||
Colors.transparent,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
hoverColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
focusColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
onTap: () {
|
||||
if (widget.onDismiss != null) {
|
||||
widget.onDismiss!();
|
||||
}
|
||||
MatrixState.pAnyState.closeOverlay();
|
||||
},
|
||||
child: AnimatedBuilder(
|
||||
animation: _blurTween,
|
||||
builder: (context, _) {
|
||||
return BackdropFilter(
|
||||
filter: widget.blurBackground
|
||||
? ImageFilter.blur(
|
||||
sigmaX: _blurTween.value,
|
||||
sigmaY: _blurTween.value,
|
||||
)
|
||||
: ImageFilter.blur(sigmaX: 0, sigmaY: 0),
|
||||
child: Container(
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
color: Colors.transparent,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ enum InstructionsEnum {
|
|||
morphAnalyticsList,
|
||||
readingAssistanceOverview,
|
||||
emptyChatWarning,
|
||||
activityStatsMenu,
|
||||
}
|
||||
|
||||
extension InstructionsEnumExtension on InstructionsEnum {
|
||||
|
|
@ -60,6 +61,7 @@ extension InstructionsEnumExtension on InstructionsEnum {
|
|||
case InstructionsEnum.analyticsVocabList:
|
||||
case InstructionsEnum.morphAnalyticsList:
|
||||
case InstructionsEnum.readingAssistanceOverview:
|
||||
case InstructionsEnum.activityStatsMenu:
|
||||
ErrorHandler.logError(
|
||||
e: Exception("No title for this instruction"),
|
||||
m: 'InstructionsEnumExtension.title',
|
||||
|
|
@ -74,21 +76,6 @@ extension InstructionsEnumExtension on InstructionsEnum {
|
|||
}
|
||||
}
|
||||
|
||||
// IconData? get icon {
|
||||
// switch (this) {
|
||||
// case InstructionsEnum.itInstructions:
|
||||
// return Icons.translate;
|
||||
// case InstructionsEnum.clickMessage:
|
||||
// return Icons.touch_app;
|
||||
// case InstructionsEnum.blurMeansTranslate:
|
||||
// return Icons.blur_on;
|
||||
// case InstructionsEnum.tooltipInstructions:
|
||||
// return Icons.help;
|
||||
// case InstructionsEnum.missingVoice:
|
||||
// return Icons.mic_off;
|
||||
// }
|
||||
// }
|
||||
|
||||
String body(L10n l10n) {
|
||||
switch (this) {
|
||||
case InstructionsEnum.itInstructions:
|
||||
|
|
@ -135,6 +122,8 @@ extension InstructionsEnumExtension on InstructionsEnum {
|
|||
return l10n.readingAssistanceOverviewBody;
|
||||
case InstructionsEnum.emptyChatWarning:
|
||||
return l10n.emptyChatWarningDesc;
|
||||
case InstructionsEnum.activityStatsMenu:
|
||||
return l10n.activityStatsButtonInstruction;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue