chore: some small updates to activity session UI (#3630)

This commit is contained in:
ggurdin 2025-08-05 12:02:20 -04:00 committed by GitHub
parent aabb97bc15
commit dea50a51fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 93 additions and 54 deletions

View file

@ -5132,7 +5132,7 @@
}
}
},
"endActivityTitle": "Wrapped up my part",
"endActivityTitle": "I'm Done",
"endActivityDesc": "Did you complete the objectives?\nThis is your confirmation that you're stepping back from texting. But dont worry, the fun continues in the chat! Feel free to hang out and enjoy the show until everyone clicks 'Done'.",
"archiveToAnalytics": "Archive to Analytics"
"archiveToAnalytics": "Add to my Completed Activities"
}

View file

@ -125,13 +125,15 @@ class ChatView extends StatelessWidget {
if (!controller.room.isArchived) {
// #Pangea
return [
IconButton(
icon: const Icon(Icons.search_outlined),
tooltip: L10n.of(context).search,
onPressed: () {
context.go('/rooms/${controller.room.id}/search');
},
),
if (controller.room.activityPlan == null ||
!controller.room.showActivityChatUI)
IconButton(
icon: const Icon(Icons.search_outlined),
tooltip: L10n.of(context).search,
onPressed: () {
context.go('/rooms/${controller.room.id}/search');
},
),
IconButton(
icon: const Icon(Icons.settings_outlined),
tooltip: L10n.of(context).chatDetails,

View file

@ -198,15 +198,13 @@ class ActivityFinishedStatusMessageState
runSpacing: 12.0,
children: widget.room.activityRoles
.map(
(role) => Opacity(
opacity: _highlightedRole == role ? 1.0 : 0.5,
child: ActivityParticipantIndicator(
onTap: _highlightedRole == role
? null
: () => _highlightRole(role),
role: role,
displayname: role.userId.localpart,
),
(role) => ActivityParticipantIndicator(
onTap: _highlightedRole == role
? null
: () => _highlightRole(role),
role: role,
displayname: role.userId.localpart,
selected: _highlightedRole == role,
),
)
.toList(),

View file

@ -66,7 +66,7 @@ class ActivityPinnedMessageState extends State<ActivityPinnedMessage> {
Widget build(BuildContext context) {
// if the room has no activity, or if it doesn't have the permission
// levels for sending the required events, don't show the pinned message
if (!room.showActivityChatUI) {
if (!room.isActiveInActivity) {
return const SizedBox.shrink();
}
@ -88,8 +88,7 @@ class ActivityPinnedMessageState extends State<ActivityPinnedMessage> {
: theme.colorScheme.surface,
),
child: ChatAppBarListTile(
title: room.activityPlan?.markdown ??
L10n.of(context).loadingPleaseWait,
title: "🎯 ${room.activityPlan!.learningObjective}",
leading: const SizedBox(width: 18.0),
trailing: Padding(
padding: const EdgeInsets.only(right: 12.0),
@ -102,13 +101,18 @@ class ActivityPinnedMessageState extends State<ActivityPinnedMessage> {
horizontal: 12.0,
vertical: 4.0,
),
backgroundColor: theme.colorScheme.onSurface,
backgroundColor: AppConfig.yellowDark,
foregroundColor: theme.colorScheme.surface,
disabledBackgroundColor:
AppConfig.yellowDark.withAlpha(100),
disabledForegroundColor:
theme.colorScheme.surface.withAlpha(100),
),
child: Text(
L10n.of(context).done,
L10n.of(context).endActivityTitle,
style: const TextStyle(
fontSize: 12.0,
fontSize: 16.0,
fontWeight: FontWeight.w900,
),
),
),

View file

@ -92,8 +92,7 @@ class ActivityPlanModel {
/// use target emoji for learning objective
/// use step emoji for instructions
String get markdown {
String markdown =
''' **$title** \n🎯 $learningObjective \n🪜 $instructions \n\n📖 ''';
String markdown = '''🎯 $learningObjective \n🪜 $instructions \n\n📖''';
// cycle through vocab with index
for (var i = 0; i < vocab.length; i++) {
// if the lemma appears more than once in the vocab list, show the pos

View file

@ -32,7 +32,7 @@ extension ActivityRoomExtension on Room {
}
}
Future<void> setActivityRole({
Future<void> startActivity({
String? role,
}) async {
await client.setRoomStateWithKey(
@ -46,6 +46,21 @@ extension ActivityRoomExtension on Room {
);
}
Future<void> continueActivity() async {
final role = activityRole(client.userID!);
if (role == null || !role.isFinished || role.isArchived) return;
role.finishedAt = null;
final syncFuture = client.waitForRoomInSync(id);
await client.setRoomStateWithKey(
id,
PangeaEventTypes.activityRole,
client.userID!,
role.toJson(),
);
await syncFuture;
}
Future<void> finishActivity() async {
final role = activityRole(client.userID!);
if (role == null) return;
@ -214,6 +229,9 @@ extension ActivityRoomExtension on Room {
return role == null || role.isFinished;
}
bool get hasCompletedActivity =>
activityRole(client.userID!)?.isFinished ?? false;
bool get activityIsFinished {
return activityRoles.isNotEmpty && activityRoles.every((r) => r.isFinished);
}

View file

@ -38,28 +38,30 @@ class ActivityUnfinishedStatusMessageState
return Column(
children: [
if (unassignedRoles > 0)
Wrap(
spacing: 12.0,
runSpacing: 12.0,
children: List.generate(unassignedRoles, (index) {
return ActivityParticipantIndicator(
selected: _selectedRole == index,
onTap: () => _selectRole(index),
);
}),
if (!widget.room.hasCompletedActivity) ...[
if (unassignedRoles > 0)
Wrap(
spacing: 12.0,
runSpacing: 12.0,
children: List.generate(unassignedRoles, (index) {
return ActivityParticipantIndicator(
selected: _selectedRole == index,
onTap: () => _selectRole(index),
);
}),
),
const SizedBox(height: 16.0),
Text(
unassignedRoles > 0
? L10n.of(context).unjoinedActivityMessage
: L10n.of(context).fullActivityMessage,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: isColumnMode ? 16.0 : 12.0,
),
),
const SizedBox(height: 16.0),
Text(
unassignedRoles > 0
? L10n.of(context).unjoinedActivityMessage
: L10n.of(context).fullActivityMessage,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: isColumnMode ? 16.0 : 12.0,
),
),
const SizedBox(height: 16.0),
const SizedBox(height: 16.0),
],
if (unassignedRoles > 0)
ElevatedButton(
style: ElevatedButton.styleFrom(
@ -70,19 +72,28 @@ class ActivityUnfinishedStatusMessageState
foregroundColor: theme.colorScheme.onPrimaryContainer,
backgroundColor: theme.colorScheme.primaryContainer,
),
onPressed: _selectedRole != null
onPressed: widget.room.hasCompletedActivity
? () {
showFutureLoadingDialog(
context: context,
future: () => widget.room.setActivityRole(),
future: widget.room.continueActivity,
);
}
: null,
: _selectedRole != null
? () {
showFutureLoadingDialog(
context: context,
future: widget.room.startActivity,
);
}
: null,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
L10n.of(context).confirmRole,
widget.room.hasCompletedActivity
? L10n.of(context).continueText
: L10n.of(context).confirmRole,
style: TextStyle(
fontSize: isColumnMode ? 16.0 : 12.0,
),

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/events/state_message.dart';
import 'package:fluffychat/pangea/activity_planner/activity_participant_indicator.dart';
import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart';
@ -17,15 +18,21 @@ class ActivityStateEvent extends StatelessWidget {
final activity = ActivityPlanModel.fromJson(event.content);
final roles = event.room.activityRoles;
return Padding(
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
vertical: 16.0,
),
constraints: const BoxConstraints(
maxWidth: FluffyThemes.maxTimelineWidth,
),
child: Column(
spacing: 12.0,
children: [
Text(activity.markdown),
Text(
activity.markdown,
style: const TextStyle(fontSize: 14.0),
),
if (roles.isNotEmpty)
Wrap(
spacing: 12.0,