feat: show unlocked constructs snackbar (#2193)

pull/1817/head
ggurdin 8 months ago committed by GitHub
parent b104069d31
commit 269af9f4e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -4827,5 +4827,6 @@
"startChatting": "Start chatting",
"referFriends": "Refer friends",
"referFriendDialogTitle": "Invite a friend to your conversation",
"referFriendDialogDesc": "Do you have a friend who is excited to learn a new language with you? Then copy and send this invitation link to join and start chatting with you today."
"referFriendDialogDesc": "Do you have a friend who is excited to learn a new language with you? Then copy and send this invitation link to join and start chatting with you today.",
"youUnlocked": "You've unlocked"
}

@ -30,6 +30,7 @@ import 'package:fluffychat/pages/chat_details/chat_details.dart';
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
import 'package:fluffychat/pangea/analytics_misc/level_up.dart';
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
import 'package:fluffychat/pangea/chat/utils/unlocked_morphs_snackbar.dart';
import 'package:fluffychat/pangea/chat/widgets/event_too_large_dialog.dart';
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
import 'package:fluffychat/pangea/choreographer/enums/edit_type.dart';
@ -365,7 +366,9 @@ class ChatController extends State<ChatPageWithRoom>
_levelSubscription = pangeaController.getAnalytics.stateStream
.where(
(update) => update is Map<String, dynamic> && update['level_up'] != null,
(update) =>
update is Map<String, dynamic> &&
(update['level_up'] != null || update['unlocked_constructs'] != null),
)
// .listen(
// (update) => Future.delayed(
@ -380,13 +383,20 @@ class ChatController extends State<ChatPageWithRoom>
// remove delay now that GetAnalyticsController._onLevelUp
// is async is should take roughly 500ms to make requests anyway
(update) {
LevelUpUtil.showLevelUpDialog(
update['level_up'],
update['analytics_room_id'],
update["construct_summary_state_event_id"],
update['construct_summary'],
context,
);
if (update['level_up'] != null) {
LevelUpUtil.showLevelUpDialog(
update['level_up'],
update['analytics_room_id'],
update["construct_summary_state_event_id"],
update['construct_summary'],
context,
);
} else if (update['unlocked_constructs'] != null) {
showUnlockedMorphsSnackbar(
update['unlocked_constructs'],
context,
);
}
},
);
// Pangea#

@ -158,7 +158,7 @@ class MorphFeatureBox extends StatelessWidget {
morphFeature: morphFeature,
morphTag: morphTag,
constructAnalytics: analytics,
onTap: analytics.points > 0
onTap: analytics.points > 10
? () => onConstructZoom(id)
: null,
);
@ -196,16 +196,17 @@ class MorphTagChip extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final unlocked = constructAnalytics.points > 10;
return InkWell(
borderRadius: BorderRadius.circular(32.0),
onTap: onTap,
child: Opacity(
opacity: constructAnalytics.points > 0 ? 1.0 : 0.3,
opacity: unlocked ? 1.0 : 0.3,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(32.0),
gradient: constructAnalytics.points > 0
gradient: unlocked
? LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
@ -215,7 +216,7 @@ class MorphTagChip extends StatelessWidget {
],
)
: null,
color: constructAnalytics.points > 0 ? null : theme.disabledColor,
color: unlocked ? null : theme.disabledColor,
),
padding: const EdgeInsets.symmetric(
vertical: 4.0,
@ -228,8 +229,7 @@ class MorphTagChip extends StatelessWidget {
SizedBox(
width: 28.0,
height: 28.0,
child: constructAnalytics.points > 0 ||
Matrix.of(context).client.isSupportAccount
child: unlocked || Matrix.of(context).client.isSupportAccount
? MorphIcon(
morphFeature: morphFeature,
morphTag: morphTag,

@ -36,6 +36,22 @@ class ConstructListModel {
/// A list of unique grammar lemmas
List<String> grammarLemmasList = [];
List<ConstructIdentifier> get unlockedGrammarLemmas {
final morphs = constructList(type: ConstructTypeEnum.morph);
final List<ConstructIdentifier> unlocked = [];
for (final morph in grammarLemmasList) {
final matches = morphs.where((m) => m.lemma == morph);
final totalPoints = matches.fold<int>(
0,
(total, match) => total + match.points,
);
if (totalPoints > 10) {
unlocked.add(matches.first.id);
}
}
return unlocked;
}
/// Analytics data consumed by widgets. Updated each time new analytics come in.
int prevXP = 0;
int totalXP = 0;

@ -18,6 +18,7 @@ import 'package:fluffychat/pangea/common/constants/local.key.dart';
import 'package:fluffychat/pangea/common/controllers/base_controller.dart';
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/constructs/construct_repo.dart';
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
@ -139,7 +140,12 @@ class GetAnalyticsController extends BaseController {
final offset =
_pangeaController.userController.publicProfile?.xpOffset ?? 0;
final prevUnlockedMorphs = constructListModel.unlockedGrammarLemmas.toSet();
constructListModel.updateConstructs(analyticsUpdate.newConstructs, offset);
final newUnlockedMorphs = constructListModel.unlockedGrammarLemmas
.toSet()
.difference(prevUnlockedMorphs);
if (analyticsUpdate.type == AnalyticsUpdateType.server) {
await _getConstructs(forceUpdate: true);
}
@ -149,6 +155,9 @@ class GetAnalyticsController extends BaseController {
if (oldLevel > constructListModel.level) {
await _onLevelDown(constructListModel.level, oldLevel);
}
if (newUnlockedMorphs.isNotEmpty) {
_onUnlockMorphLemmas(newUnlockedMorphs);
}
_updateAnalyticsStream(origin: analyticsUpdate.origin);
// Update public profile each time that new analytics are added.
// If the level hasn't changed, this will not send an update to the server.
@ -187,6 +196,10 @@ class GetAnalyticsController extends BaseController {
);
}
void _onUnlockMorphLemmas(Set<ConstructIdentifier> unlocked) {
setState({'unlocked_constructs': unlocked});
}
/// A local cache of eventIds and construct uses for messages sent since the last update.
/// It's a map of eventIDs to a list of OneConstructUses. Not just a list of OneConstructUses
/// because, with practice activity constructs, we might need to add to the list for a given

@ -85,7 +85,7 @@ class LearningProgressIndicatorsState
int uniqueLemmas(ProgressIndicatorEnum indicator) {
switch (indicator) {
case ProgressIndicatorEnum.morphsUsed:
return _constructsModel.grammarLemmas;
return _constructsModel.unlockedGrammarLemmas.length;
case ProgressIndicatorEnum.wordsUsed:
return _constructsModel.vocabLemmas;
default:

@ -0,0 +1,77 @@
// ignore_for_file: depend_on_referenced_packages, implementation_imports
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart';
import 'package:fluffychat/pangea/morphs/morph_icon.dart';
void showUnlockedMorphsSnackbar(
Set<ConstructIdentifier> unlockedConstructs,
BuildContext context,
) {
for (final construct in unlockedConstructs) {
final copy = getGrammarCopy(
category: construct.category,
lemma: construct.lemma,
context: context,
);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
behavior: FluffyThemes.isColumnMode(context)
? SnackBarBehavior.floating
: SnackBarBehavior.fixed,
width: FluffyThemes.isColumnMode(context)
? MediaQuery.of(context).size.width
: null,
showCloseIcon: true,
duration: const Duration(seconds: 5),
dismissDirection: DismissDirection.none,
backgroundColor: Theme.of(context).colorScheme.surface,
content: Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 16.0,
alignment: WrapAlignment.center,
children: [
Text(
L10n.of(context).youUnlocked,
style: TextStyle(
fontSize: FluffyThemes.isColumnMode(context) ? 32.0 : 16.0,
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
),
Row(
mainAxisSize: MainAxisSize.min,
spacing: 16.0,
children: [
Flexible(
child: Text(
copy ?? construct.lemma,
style: TextStyle(
fontSize:
FluffyThemes.isColumnMode(context) ? 32.0 : 16.0,
color: AppConfig.gold,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
),
),
MorphIcon(
morphFeature: construct.category,
morphTag: construct.lemma,
),
],
),
],
),
),
),
);
}
}
Loading…
Cancel
Save