chore: show role goal in text abut button on activity launch page and in tooltip above input bar (#3910)

pull/2245/head
ggurdin 2 months ago committed by GitHub
parent 29543ef4a3
commit ad2e0e26db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -146,7 +146,7 @@ class Message extends StatelessWidget {
toggleInstructions: controller.toggleShowInstructions, toggleInstructions: controller.toggleShowInstructions,
getParticipantOpacity: (role) => getParticipantOpacity: (role) =>
role == null || role.isFinished ? 0.5 : 1.0, role == null || role.isFinished ? 0.5 : 1.0,
isParticipantSelected: (id) => controller.room.ownRole?.id == id, isParticipantSelected: (id) => controller.room.ownRoleState?.id == id,
); );
} }

@ -6,6 +6,7 @@ class ActivityRoleModel {
final String? role; final String? role;
DateTime? finishedAt; DateTime? finishedAt;
DateTime? archivedAt; DateTime? archivedAt;
bool dismissedGoalTooltip;
ActivityRoleModel({ ActivityRoleModel({
required this.id, required this.id,
@ -13,6 +14,7 @@ class ActivityRoleModel {
this.role, this.role,
this.finishedAt, this.finishedAt,
this.archivedAt, this.archivedAt,
this.dismissedGoalTooltip = false,
}); });
bool get isFinished => finishedAt != null; bool get isFinished => finishedAt != null;
@ -45,6 +47,7 @@ class ActivityRoleModel {
archivedAt: json['archived_at'] != null archivedAt: json['archived_at'] != null
? DateTime.parse(json['archived_at']) ? DateTime.parse(json['archived_at'])
: null, : null,
dismissedGoalTooltip: json['dismissed_goal_tooltip'] as bool? ?? false,
); );
} }
@ -55,6 +58,7 @@ class ActivityRoleModel {
'role': role, 'role': role,
'finished_at': finishedAt?.toIso8601String(), 'finished_at': finishedAt?.toIso8601String(),
'archived_at': archivedAt?.toIso8601String(), 'archived_at': archivedAt?.toIso8601String(),
'dismissed_goal_tooltip': dismissedGoalTooltip,
}; };
} }
@ -67,7 +71,8 @@ class ActivityRoleModel {
other.role == role && other.role == role &&
other.finishedAt == finishedAt && other.finishedAt == finishedAt &&
other.archivedAt == archivedAt && other.archivedAt == archivedAt &&
other.id == id; other.id == id &&
other.dismissedGoalTooltip == dismissedGoalTooltip;
} }
@override @override
@ -76,5 +81,6 @@ class ActivityRoleModel {
role.hashCode ^ role.hashCode ^
(finishedAt?.hashCode ?? 0) ^ (finishedAt?.hashCode ?? 0) ^
(archivedAt?.hashCode ?? 0) ^ (archivedAt?.hashCode ?? 0) ^
id.hashCode; id.hashCode ^
dismissedGoalTooltip.hashCode;
} }

@ -15,6 +15,10 @@ class ActivityRolesModel {
roles[role.id] = role; roles[role.id] = role;
} }
void dismissTooltip(ActivityRoleModel role) {
roles[role.id]?.dismissedGoalTooltip = true;
}
void finishAll() { void finishAll() {
for (final id in roles.keys) { for (final id in roles.keys) {
if (roles[id]!.isFinished) continue; if (roles[id]!.isFinished) continue;

@ -43,7 +43,7 @@ extension ActivityRoomExtension on Room {
Future<void> continueActivity() async { Future<void> continueActivity() async {
final currentRoles = activityRoles ?? ActivityRolesModel.empty; final currentRoles = activityRoles ?? ActivityRolesModel.empty;
final role = ownRole; final role = ownRoleState;
if (role == null || !role.isFinished) return; if (role == null || !role.isFinished) return;
role.finishedAt = null; // Reset finished state role.finishedAt = null; // Reset finished state
@ -58,7 +58,7 @@ extension ActivityRoomExtension on Room {
Future<void> finishActivity() async { Future<void> finishActivity() async {
final currentRoles = activityRoles ?? ActivityRolesModel.empty; final currentRoles = activityRoles ?? ActivityRolesModel.empty;
final role = ownRole; final role = ownRoleState;
if (role == null || role.isFinished) return; if (role == null || role.isFinished) return;
role.finishedAt = DateTime.now(); role.finishedAt = DateTime.now();
currentRoles.updateRole(role); currentRoles.updateRole(role);
@ -84,7 +84,7 @@ extension ActivityRoomExtension on Room {
Future<void> archiveActivity() async { Future<void> archiveActivity() async {
final currentRoles = activityRoles ?? ActivityRolesModel.empty; final currentRoles = activityRoles ?? ActivityRolesModel.empty;
final role = ownRole; final role = ownRoleState;
if (role == null || !role.isFinished || role.isArchived) return; if (role == null || !role.isFinished || role.isArchived) return;
role.archivedAt = DateTime.now(); role.archivedAt = DateTime.now();
@ -97,6 +97,21 @@ extension ActivityRoomExtension on Room {
); );
} }
Future<void> dismissGoalTooltip() async {
final currentRoles = activityRoles ?? ActivityRolesModel.empty;
final role = ownRoleState;
if (role == null) return;
role.finishedAt = DateTime.now();
currentRoles.dismissTooltip(role);
await client.setRoomStateWithKey(
id,
PangeaEventTypes.activityRole,
"",
currentRoles.toJson(),
);
}
Future<void> setActivitySummary( Future<void> setActivitySummary(
ActivitySummaryModel summary, ActivitySummaryModel summary,
) async { ) async {
@ -270,7 +285,14 @@ extension ActivityRoomExtension on Room {
); );
} }
ActivityRoleModel? get ownRole => activityRoles?.role(client.userID!); ActivityRole? get ownRole {
final role = ownRoleState;
if (role == null || activityPlan == null) return null;
return activityPlan!.roles[role.id];
}
ActivityRoleModel? get ownRoleState => activityRoles?.role(client.userID!);
int get remainingRoles { int get remainingRoles {
final availableRoles = activityPlan?.roles; final availableRoles = activityPlan?.roles;
@ -289,17 +311,17 @@ extension ActivityRoomExtension on Room {
bool get isActiveInActivity { bool get isActiveInActivity {
if (!showActivityChatUI) return false; if (!showActivityChatUI) return false;
final role = ownRole; final role = ownRoleState;
return role != null && !role.isFinished; return role != null && !role.isFinished;
} }
bool get isInactiveInActivity { bool get isInactiveInActivity {
if (!showActivityChatUI) return false; if (!showActivityChatUI) return false;
final role = ownRole; final role = ownRoleState;
return role == null || role.isFinished; return role == null || role.isFinished;
} }
bool get hasCompletedActivity => ownRole?.isFinished ?? false; bool get hasCompletedActivity => ownRoleState?.isFinished ?? false;
bool get activityIsFinished { bool get activityIsFinished {
final roles = activityRoles?.roles.values.where( final roles = activityRoles?.roles.values.where(
@ -321,7 +343,10 @@ extension ActivityRoomExtension on Room {
}); });
} }
bool get isHiddenActivityRoom => ownRole?.isArchived ?? false; bool get isHiddenActivityRoom => ownRoleState?.isArchived ?? false;
bool get hasDismissedGoalTooltip =>
ownRoleState?.dismissedGoalTooltip ?? false;
Room? get courseParent => pangeaSpaceParents.firstWhereOrNull( Room? get courseParent => pangeaSpaceParents.firstWhereOrNull(
(parent) => parent.coursePlan != null, (parent) => parent.coursePlan != null,
@ -333,7 +358,7 @@ extension ActivityRoomExtension on Room {
bool get isActivitySession => isActivityRoomType || activityPlan != null; bool get isActivitySession => isActivityRoomType || activityPlan != null;
bool get showActivityFinished => bool get showActivityFinished =>
showActivityChatUI && ownRole != null && hasCompletedActivity; showActivityChatUI && ownRoleState != null && hasCompletedActivity;
String? get activityId { String? get activityId {
if (!isActivitySession) return null; if (!isActivitySession) return null;

@ -84,7 +84,7 @@ class ActivitySessionStartController extends State<ActivitySessionStartPage> {
false; false;
SessionState get state { SessionState get state {
if (room?.ownRole != null) return SessionState.confirmedRole; if (room?.ownRoleState != null) return SessionState.confirmedRole;
if (_selectedRoleId != null) return SessionState.selectedRole; if (_selectedRoleId != null) return SessionState.selectedRole;
if (room == null) { if (room == null) {
return widget.isNew return widget.isNew
@ -99,7 +99,7 @@ class ActivitySessionStartController extends State<ActivitySessionStartPage> {
case SessionState.confirmedRole: case SessionState.confirmedRole:
return L10n.of(context).waitingToFillRole(room!.remainingRoles); return L10n.of(context).waitingToFillRole(room!.remainingRoles);
case SessionState.selectedRole: case SessionState.selectedRole:
return activity!.description; return activity!.roles[_selectedRoleId!]!.goal;
case SessionState.notStarted: case SessionState.notStarted:
return null; return null;
@ -131,7 +131,7 @@ class ActivitySessionStartController extends State<ActivitySessionStartPage> {
bool isParticipantSelected(String id) { bool isParticipantSelected(String id) {
if (state == SessionState.confirmedRole) { if (state == SessionState.confirmedRole) {
return room?.ownRole?.id == id; return room?.ownRoleState?.id == id;
} }
return _selectedRoleId == id; return _selectedRoleId == id;
} }

@ -6,6 +6,7 @@ import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pages/chat/chat.dart';
import 'package:fluffychat/pages/chat/chat_emoji_picker.dart'; import 'package:fluffychat/pages/chat/chat_emoji_picker.dart';
import 'package:fluffychat/pages/chat/reply_display.dart'; import 'package:fluffychat/pages/chat/reply_display.dart';
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
import 'package:fluffychat/pangea/chat/widgets/pangea_chat_input_row.dart'; import 'package:fluffychat/pangea/chat/widgets/pangea_chat_input_row.dart';
import 'package:fluffychat/pangea/choreographer/widgets/it_bar.dart'; import 'package:fluffychat/pangea/choreographer/widgets/it_bar.dart';
@ -34,6 +35,12 @@ class ChatInputBarState extends State<ChatInputBar> {
}); });
} }
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => _updateHeight());
}
@override @override
void dispose() { void dispose() {
_debounceTimer?.cancel(); _debounceTimer?.cancel();
@ -48,46 +55,92 @@ class ChatInputBarState extends State<ChatInputBar> {
return true; return true;
}, },
child: SizeChangedLayoutNotifier( child: SizeChangedLayoutNotifier(
child: Container( child: Column(
padding: EdgeInsets.only( children: [
bottom: widget.padding, if (widget.controller.room.showActivityChatUI &&
left: widget.padding, widget.controller.room.ownRole?.goal != null)
right: widget.padding, Container(
), decoration: BoxDecoration(
constraints: const BoxConstraints( color: Theme.of(context).colorScheme.surface,
maxWidth: FluffyThemes.maxTimelineWidth, border: Border(
), top: BorderSide(
alignment: Alignment.center, color: Theme.of(context).colorScheme.outline,
child: Material( width: 0.1,
clipBehavior: Clip.hardEdge, ),
type: MaterialType.transparency,
borderRadius: const BorderRadius.all(
Radius.circular(24),
),
child: Column(
children: [
ITBar(choreographer: widget.controller.choreographer),
DecoratedBox(
decoration: BoxDecoration(
color:
Theme.of(context).colorScheme.surfaceContainerHighest,
), ),
child: Column( ),
children: [ child: AnimatedSize(
// #Pangea duration: FluffyThemes.animationDuration,
if (!widget.controller.obscureText) child: widget.controller.room.hasDismissedGoalTooltip
// Pangea# ? const SizedBox()
ReplyDisplay(widget.controller), : Padding(
PangeaChatInputRow( padding: const EdgeInsets.all(12.0),
controller: widget.controller, child: Row(
spacing: 10.0,
children: [
Expanded(
child: Text(
widget.controller.room.ownRole!.goal!,
style: const TextStyle(
fontSize: 12.0,
),
textAlign: TextAlign.center,
),
),
IconButton(
icon: const Icon(Icons.close),
onPressed: () async {
await widget.controller.room
.dismissGoalTooltip();
if (mounted) setState(() {});
},
),
],
),
),
),
),
Container(
padding: EdgeInsets.only(
bottom: widget.padding,
left: widget.padding,
right: widget.padding,
),
constraints: const BoxConstraints(
maxWidth: FluffyThemes.maxTimelineWidth,
),
alignment: Alignment.center,
child: Material(
clipBehavior: Clip.hardEdge,
type: MaterialType.transparency,
borderRadius: const BorderRadius.all(
Radius.circular(24),
),
child: Column(
children: [
ITBar(choreographer: widget.controller.choreographer),
DecoratedBox(
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.surfaceContainerHighest,
), ),
ChatEmojiPicker(widget.controller), child: Column(
], children: [
), if (!widget.controller.obscureText)
ReplyDisplay(widget.controller),
PangeaChatInputRow(
controller: widget.controller,
),
ChatEmojiPicker(widget.controller),
],
),
),
],
), ),
], ),
), ),
), ],
), ),
), ),
); );

Loading…
Cancel
Save