diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 528f88e65..ef4e74caf 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4498,6 +4498,13 @@ "selectBotChatMode": "Select chat mode", "messageNotInTargetLang": "Message not in target language", "other": "Other", + "levelShort": "LVL {level}", + "@levelShort": { + "type": "text", + "placeholders": { + "level": {} + } + }, "botModeValidation": "Please select a chat mode", "clickBestOption": "Choose the best options to translate your message!", "unlockedLanguageTools": "You’ve unlocked the language tools for this message. Try them out by clicking below!", diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index ef4487e9a..ffd263952 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -35,6 +35,8 @@ abstract class AppConfig { static const Color activeToggleColor = Color(0xFF33D057); static const Color success = Color(0xFF33D057); static const Color warning = Color.fromARGB(255, 210, 124, 12); + static const Color gold = Color.fromARGB(255, 253, 191, 1); + static const Color goldLight = Color.fromARGB(255, 254, 223, 73); static const int overlayAnimationDuration = 250; // static String _privacyUrl = // 'https://gitlab.com/famedly/fluffychat/-/blob/main/PRIVACY.md'; diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index 46f5b944a..b10f1a574 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -275,26 +275,44 @@ class ClientChooserButton extends StatelessWidget { color: Colors.transparent, borderRadius: BorderRadius.circular(99), child: - // #Pangea - Stack( - alignment: Alignment.bottomRight, - children: [ - Padding( - padding: const EdgeInsets.all(4), - child: - // Pangea# - Avatar( - mxContent: snapshot.data?.avatarUrl, - name: snapshot.data?.displayName ?? - matrix.client.userID!.localpart, - size: 50, + // // #Pangea + // Stack( + // alignment: Alignment.bottomRight, + // children: [ + // Padding( + // padding: const EdgeInsets.all(4), + // child: + // // Pangea# + Container( + decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(15), + // color: Theme.of(context).colorScheme.surfaceBright, + borderRadius: BorderRadius.circular(30), + boxShadow: [ + BoxShadow( + color: Theme.of(context).colorScheme.primary, + spreadRadius: 1, + blurRadius: 1, + offset: const Offset( + 0, + 1, + ), // changes position of shadow ), - // #Pangea - ), - const Icon(Icons.settings_outlined, size: 20), - ], + ], + ), + child: Avatar( + mxContent: snapshot.data?.avatarUrl, + name: snapshot.data?.displayName ?? + matrix.client.userID!.localpart, + size: 60, + ), ), - // Pangea# + // // #Pangea + // ), + // const Icon(Icons.settings_outlined, size: 20), + // ], + // ), + // // Pangea# ), ), ], diff --git a/lib/pangea/enum/progress_indicators_enum.dart b/lib/pangea/enum/progress_indicators_enum.dart index 80ccf279a..713f36f71 100644 --- a/lib/pangea/enum/progress_indicators_enum.dart +++ b/lib/pangea/enum/progress_indicators_enum.dart @@ -13,7 +13,7 @@ extension ProgressIndicatorsExtension on ProgressIndicatorEnum { IconData get icon { switch (this) { case ProgressIndicatorEnum.wordsUsed: - return Icons.text_fields_outlined; + return Symbols.dictionary; case ProgressIndicatorEnum.morphsUsed: return Symbols.toys_and_games; case ProgressIndicatorEnum.level: @@ -25,24 +25,7 @@ extension ProgressIndicatorsExtension on ProgressIndicatorEnum { Theme.of(context).brightness == Brightness.dark; Color color(BuildContext context) { - switch (this) { - case ProgressIndicatorEnum.wordsUsed: - return Theme.of(context).brightness == Brightness.dark - ? const Color.fromARGB(255, 169, 183, 237) - : const Color.fromARGB(255, 38, 59, 141); - // case ProgressIndicatorEnum.errorTypes: - // return Theme.of(context).brightness == Brightness.dark - // ? const Color.fromARGB(255, 212, 144, 216) - // : const Color.fromARGB(255, 163, 39, 169); - case ProgressIndicatorEnum.level: - return Theme.of(context).brightness == Brightness.dark - ? const Color.fromARGB(255, 250, 220, 129) - : const Color.fromARGB(255, 255, 208, 67); - case ProgressIndicatorEnum.morphsUsed: - return Theme.of(context).brightness == Brightness.dark - ? const Color.fromARGB(255, 169, 183, 237) - : const Color.fromARGB(255, 38, 59, 141); - } + return Theme.of(context).colorScheme.primary; } String tooltip(BuildContext context) { diff --git a/lib/pangea/widgets/animations/progress_bar/animated_level_dart.dart b/lib/pangea/widgets/animations/progress_bar/animated_level_dart.dart index adbc32e33..f7d7fed4e 100644 --- a/lib/pangea/widgets/animations/progress_bar/animated_level_dart.dart +++ b/lib/pangea/widgets/animations/progress_bar/animated_level_dart.dart @@ -1,3 +1,4 @@ +import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:flutter/material.dart'; @@ -5,14 +6,16 @@ class AnimatedLevelBar extends StatefulWidget { final double height; final double beginWidth; final double endWidth; - final BoxDecoration? decoration; + final Color primaryColor; + final Color highlightColor; const AnimatedLevelBar({ super.key, required this.height, required this.beginWidth, required this.endWidth, - this.decoration, + required this.primaryColor, + required this.highlightColor, }); @override @@ -76,10 +79,40 @@ class AnimatedLevelBarState extends State return AnimatedBuilder( animation: _animation, builder: (context, child) { - return Container( - height: widget.height, - width: _animation.value, - decoration: widget.decoration, + return Stack( + children: [ + Container( + height: widget.height, + width: _animation.value, + decoration: BoxDecoration( + color: widget.primaryColor, + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + spreadRadius: 0, + blurRadius: 5, + offset: const Offset(5, 0), + ), + ], + ), + ), + Positioned( + top: 2, + child: Container( + height: 6, + width: _animation.value >= 8 ? _animation.value - 8 : 0, + decoration: BoxDecoration( + color: widget.highlightColor, + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + ), + ), + ), + ], ); }, ); diff --git a/lib/pangea/widgets/animations/progress_bar/level_bar.dart b/lib/pangea/widgets/animations/progress_bar/level_bar.dart index 78b4d4944..b323d3660 100644 --- a/lib/pangea/widgets/animations/progress_bar/level_bar.dart +++ b/lib/pangea/widgets/animations/progress_bar/level_bar.dart @@ -36,19 +36,8 @@ class LevelBarState extends State { height: widget.progressBarDetails.height, beginWidth: prevWidth, endWidth: width, - decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - color: widget.details.fillColor, - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.2), - blurRadius: 5, - offset: const Offset(5, 0), - ), - ], - ), + primaryColor: AppConfig.gold, + highlightColor: AppConfig.goldLight, ); } } diff --git a/lib/pangea/widgets/animations/progress_bar/progress_bar_background.dart b/lib/pangea/widgets/animations/progress_bar/progress_bar_background.dart index 1ebfe145d..d052e1c5d 100644 --- a/lib/pangea/widgets/animations/progress_bar/progress_bar_background.dart +++ b/lib/pangea/widgets/animations/progress_bar/progress_bar_background.dart @@ -13,13 +13,9 @@ class ProgressBarBackground extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - height: details.height + 4, - width: details.totalWidth + 4, + height: details.height, + width: details.totalWidth, decoration: BoxDecoration( - border: Border.all( - color: details.borderColor.withOpacity(0.5), - width: 2, - ), borderRadius: const BorderRadius.all( Radius.circular(AppConfig.borderRadius), ), diff --git a/lib/pangea/widgets/animations/progress_bar/progress_bar_details.dart b/lib/pangea/widgets/animations/progress_bar/progress_bar_details.dart index 347a98a49..a5196bf65 100644 --- a/lib/pangea/widgets/animations/progress_bar/progress_bar_details.dart +++ b/lib/pangea/widgets/animations/progress_bar/progress_bar_details.dart @@ -20,6 +20,6 @@ class ProgressBarDetails { const ProgressBarDetails({ required this.totalWidth, required this.borderColor, - this.height = 16, + this.height = 14, }); } diff --git a/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart b/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart index 9075aa38b..d737cc4f5 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart @@ -7,11 +7,12 @@ import 'package:fluffychat/pangea/models/analytics/construct_list_model.dart'; import 'package:fluffychat/pangea/pages/settings_learning/settings_learning.dart'; import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart'; import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/learning_progress_bar.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/learning_settings_button.dart'; import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/level_badge.dart'; import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart'; -import 'package:fluffychat/pangea/widgets/flag.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; /// A summary of "My Analytics" shown at the top of the chat list /// It shows a variety of progress indicators such as @@ -76,22 +77,40 @@ class LearningProgressIndicatorsState return const SizedBox(); } + final userL2 = MatrixState.pangeaController.languageController.userL2; + return Row( children: [ const ClientChooserButton(), - const SizedBox(width: 6), + const SizedBox(width: 10), Expanded( child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text( + Matrix.of(context).client.userID ?? L10n.of(context)!.user, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontSize: 12, + ), + ), + const SizedBox(height: 6), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + LearningSettingsButton( + onTap: () => showDialog( + context: context, + builder: (c) => const SettingsLearning(), + ), + l2: userL2!.getDisplayName(context) ?? userL2.langCode, + ), Row( children: ProgressIndicatorEnum.values .where((i) => i != ProgressIndicatorEnum.level) .map( (indicator) => Padding( - padding: const EdgeInsets.only(right: 10), + padding: const EdgeInsets.only(left: 6), child: ProgressIndicatorBadge( points: uniqueLemmas(indicator), loading: _loading, @@ -111,22 +130,11 @@ class LearningProgressIndicatorsState ) .toList(), ), - InkWell( - onTap: () => showDialog( - context: context, - builder: (c) => const SettingsLearning(), - ), - child: LanguageFlag( - language: MatrixState - .pangeaController.languageController.userL2, - size: 24, - ), - ), ], ), const SizedBox(height: 6), SizedBox( - height: 36, + height: 22, child: Stack( alignment: Alignment.center, children: [ diff --git a/lib/pangea/widgets/chat_list/analytics_summary/learning_settings_button.dart b/lib/pangea/widgets/chat_list/analytics_summary/learning_settings_button.dart new file mode 100644 index 000000000..55818a823 --- /dev/null +++ b/lib/pangea/widgets/chat_list/analytics_summary/learning_settings_button.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +/// A badge that represents one learning progress indicator (i.e., construct uses) +class LearningSettingsButton extends StatelessWidget { + final String l2; + final VoidCallback onTap; + + const LearningSettingsButton({ + super.key, + required this.l2, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return Tooltip( + message: L10n.of(context)!.learningSettings, + child: InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15), + ), + onTap: onTap, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: Theme.of(context).colorScheme.surfaceBright, + boxShadow: [ + BoxShadow( + color: Theme.of(context).colorScheme.primary, + spreadRadius: 1, + blurRadius: 1, + offset: const Offset(1, 1), // changes position of shadow + ), + ], + ), + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 14, + Icons.language, + color: Theme.of(context).colorScheme.primary, + weight: 1000, + ), + const SizedBox(width: 5), + Text( + l2, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.primary, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pangea/widgets/chat_list/analytics_summary/level_badge.dart b/lib/pangea/widgets/chat_list/analytics_summary/level_badge.dart index 005da0ad4..6b3c74a99 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/level_badge.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/level_badge.dart @@ -1,4 +1,6 @@ +import 'package:fluffychat/config/app_config.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; class LevelBadge extends StatelessWidget { final int level; @@ -7,39 +9,45 @@ class LevelBadge extends StatelessWidget { super.key, }); - Color levelColor(int level) { - final colors = [ - const Color.fromARGB(255, 33, 97, 140), // Dark blue - const Color.fromARGB(255, 186, 104, 200), // Soft purple - const Color.fromARGB(255, 123, 31, 162), // Deep purple - const Color.fromARGB(255, 0, 150, 136), // Teal - const Color.fromARGB(255, 247, 143, 143), // Light pink - const Color.fromARGB(255, 220, 20, 60), // Crimson red - ]; - return colors[level % colors.length]; - } - @override Widget build(BuildContext context) { return Container( - width: 32, - height: 32, decoration: BoxDecoration( - color: levelColor(level), - borderRadius: BorderRadius.circular(32), + borderRadius: BorderRadius.circular(15), + color: Theme.of(context).colorScheme.surfaceBright, boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.2), - blurRadius: 5, - offset: const Offset(5, 0), + color: Theme.of(context).colorScheme.primary, + spreadRadius: 1, + blurRadius: 1, + offset: const Offset(1, 1), // changes position of shadow ), ], ), - child: Center( - child: Text( - "$level", - style: const TextStyle(color: Colors.white, fontSize: 16), - ), + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + CircleAvatar( + backgroundColor: AppConfig.gold, + radius: 8, + child: Icon( + size: 12, + Icons.star, + color: Theme.of(context).colorScheme.surfaceBright, + weight: 1000, + ), + ), + const SizedBox(width: 4), + Text( + L10n.of(context)!.levelShort(level), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.primary, + ), + ), + ], ), ); } diff --git a/lib/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart b/lib/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart index 537826956..2f25e7b1a 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart @@ -21,31 +21,52 @@ class ProgressIndicatorBadge extends StatelessWidget { return Tooltip( message: indicator.tooltip(context), child: InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15), + ), onTap: onTap, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - indicator.icon, - color: indicator.color(context), - ), - const SizedBox(width: 5), - !loading - ? Text( - points.toString(), - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ) - : const SizedBox( - height: 8, - width: 8, - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: Theme.of(context).colorScheme.surfaceBright, + boxShadow: [ + BoxShadow( + color: Theme.of(context).colorScheme.primary, + spreadRadius: 1, + blurRadius: 1, + offset: const Offset(-1, 1), // changes position of shadow + ), + ], + ), + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 14, + indicator.icon, + color: indicator.color(context), + weight: 1000, + ), + const SizedBox(width: 5), + !loading + ? Text( + points.toString(), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: indicator.color(context), + ), + ) + : const SizedBox( + height: 8, + width: 8, + child: CircularProgressIndicator.adaptive( + strokeWidth: 2, + ), ), - ), - ], + ], + ), ), ), );