chore: show role goal in text abut button on activity launch page and in tooltip above input bar (#3910)
This commit is contained in:
parent
29543ef4a3
commit
ad2e0e26db
6 changed files with 140 additions and 52 deletions
|
|
@ -146,7 +146,7 @@ class Message extends StatelessWidget {
|
|||
toggleInstructions: controller.toggleShowInstructions,
|
||||
getParticipantOpacity: (role) =>
|
||||
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;
|
||||
DateTime? finishedAt;
|
||||
DateTime? archivedAt;
|
||||
bool dismissedGoalTooltip;
|
||||
|
||||
ActivityRoleModel({
|
||||
required this.id,
|
||||
|
|
@ -13,6 +14,7 @@ class ActivityRoleModel {
|
|||
this.role,
|
||||
this.finishedAt,
|
||||
this.archivedAt,
|
||||
this.dismissedGoalTooltip = false,
|
||||
});
|
||||
|
||||
bool get isFinished => finishedAt != null;
|
||||
|
|
@ -45,6 +47,7 @@ class ActivityRoleModel {
|
|||
archivedAt: json['archived_at'] != null
|
||||
? DateTime.parse(json['archived_at'])
|
||||
: null,
|
||||
dismissedGoalTooltip: json['dismissed_goal_tooltip'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +58,7 @@ class ActivityRoleModel {
|
|||
'role': role,
|
||||
'finished_at': finishedAt?.toIso8601String(),
|
||||
'archived_at': archivedAt?.toIso8601String(),
|
||||
'dismissed_goal_tooltip': dismissedGoalTooltip,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +71,8 @@ class ActivityRoleModel {
|
|||
other.role == role &&
|
||||
other.finishedAt == finishedAt &&
|
||||
other.archivedAt == archivedAt &&
|
||||
other.id == id;
|
||||
other.id == id &&
|
||||
other.dismissedGoalTooltip == dismissedGoalTooltip;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -76,5 +81,6 @@ class ActivityRoleModel {
|
|||
role.hashCode ^
|
||||
(finishedAt?.hashCode ?? 0) ^
|
||||
(archivedAt?.hashCode ?? 0) ^
|
||||
id.hashCode;
|
||||
id.hashCode ^
|
||||
dismissedGoalTooltip.hashCode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ class ActivityRolesModel {
|
|||
roles[role.id] = role;
|
||||
}
|
||||
|
||||
void dismissTooltip(ActivityRoleModel role) {
|
||||
roles[role.id]?.dismissedGoalTooltip = true;
|
||||
}
|
||||
|
||||
void finishAll() {
|
||||
for (final id in roles.keys) {
|
||||
if (roles[id]!.isFinished) continue;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ extension ActivityRoomExtension on Room {
|
|||
|
||||
Future<void> continueActivity() async {
|
||||
final currentRoles = activityRoles ?? ActivityRolesModel.empty;
|
||||
final role = ownRole;
|
||||
final role = ownRoleState;
|
||||
if (role == null || !role.isFinished) return;
|
||||
|
||||
role.finishedAt = null; // Reset finished state
|
||||
|
|
@ -58,7 +58,7 @@ extension ActivityRoomExtension on Room {
|
|||
|
||||
Future<void> finishActivity() async {
|
||||
final currentRoles = activityRoles ?? ActivityRolesModel.empty;
|
||||
final role = ownRole;
|
||||
final role = ownRoleState;
|
||||
if (role == null || role.isFinished) return;
|
||||
role.finishedAt = DateTime.now();
|
||||
currentRoles.updateRole(role);
|
||||
|
|
@ -84,7 +84,7 @@ extension ActivityRoomExtension on Room {
|
|||
|
||||
Future<void> archiveActivity() async {
|
||||
final currentRoles = activityRoles ?? ActivityRolesModel.empty;
|
||||
final role = ownRole;
|
||||
final role = ownRoleState;
|
||||
if (role == null || !role.isFinished || role.isArchived) return;
|
||||
|
||||
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(
|
||||
ActivitySummaryModel summary,
|
||||
) 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 {
|
||||
final availableRoles = activityPlan?.roles;
|
||||
|
|
@ -289,17 +311,17 @@ extension ActivityRoomExtension on Room {
|
|||
|
||||
bool get isActiveInActivity {
|
||||
if (!showActivityChatUI) return false;
|
||||
final role = ownRole;
|
||||
final role = ownRoleState;
|
||||
return role != null && !role.isFinished;
|
||||
}
|
||||
|
||||
bool get isInactiveInActivity {
|
||||
if (!showActivityChatUI) return false;
|
||||
final role = ownRole;
|
||||
final role = ownRoleState;
|
||||
return role == null || role.isFinished;
|
||||
}
|
||||
|
||||
bool get hasCompletedActivity => ownRole?.isFinished ?? false;
|
||||
bool get hasCompletedActivity => ownRoleState?.isFinished ?? false;
|
||||
|
||||
bool get activityIsFinished {
|
||||
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(
|
||||
(parent) => parent.coursePlan != null,
|
||||
|
|
@ -333,7 +358,7 @@ extension ActivityRoomExtension on Room {
|
|||
bool get isActivitySession => isActivityRoomType || activityPlan != null;
|
||||
|
||||
bool get showActivityFinished =>
|
||||
showActivityChatUI && ownRole != null && hasCompletedActivity;
|
||||
showActivityChatUI && ownRoleState != null && hasCompletedActivity;
|
||||
|
||||
String? get activityId {
|
||||
if (!isActivitySession) return null;
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class ActivitySessionStartController extends State<ActivitySessionStartPage> {
|
|||
false;
|
||||
|
||||
SessionState get state {
|
||||
if (room?.ownRole != null) return SessionState.confirmedRole;
|
||||
if (room?.ownRoleState != null) return SessionState.confirmedRole;
|
||||
if (_selectedRoleId != null) return SessionState.selectedRole;
|
||||
if (room == null) {
|
||||
return widget.isNew
|
||||
|
|
@ -99,7 +99,7 @@ class ActivitySessionStartController extends State<ActivitySessionStartPage> {
|
|||
case SessionState.confirmedRole:
|
||||
return L10n.of(context).waitingToFillRole(room!.remainingRoles);
|
||||
case SessionState.selectedRole:
|
||||
return activity!.description;
|
||||
return activity!.roles[_selectedRoleId!]!.goal;
|
||||
case SessionState.notStarted:
|
||||
return null;
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ class ActivitySessionStartController extends State<ActivitySessionStartPage> {
|
|||
|
||||
bool isParticipantSelected(String id) {
|
||||
if (state == SessionState.confirmedRole) {
|
||||
return room?.ownRole?.id == id;
|
||||
return room?.ownRoleState?.id == 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_emoji_picker.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/choreographer/widgets/it_bar.dart';
|
||||
|
||||
|
|
@ -34,6 +35,12 @@ class ChatInputBarState extends State<ChatInputBar> {
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _updateHeight());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounceTimer?.cancel();
|
||||
|
|
@ -48,46 +55,92 @@ class ChatInputBarState extends State<ChatInputBar> {
|
|||
return true;
|
||||
},
|
||||
child: SizeChangedLayoutNotifier(
|
||||
child: 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,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// #Pangea
|
||||
if (!widget.controller.obscureText)
|
||||
// Pangea#
|
||||
ReplyDisplay(widget.controller),
|
||||
PangeaChatInputRow(
|
||||
controller: widget.controller,
|
||||
),
|
||||
ChatEmojiPicker(widget.controller),
|
||||
],
|
||||
child: Column(
|
||||
children: [
|
||||
if (widget.controller.room.showActivityChatUI &&
|
||||
widget.controller.room.ownRole?.goal != null)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
width: 0.1,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
child: AnimatedSize(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
child: widget.controller.room.hasDismissedGoalTooltip
|
||||
? const SizedBox()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
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,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
if (!widget.controller.obscureText)
|
||||
ReplyDisplay(widget.controller),
|
||||
PangeaChatInputRow(
|
||||
controller: widget.controller,
|
||||
),
|
||||
ChatEmojiPicker(widget.controller),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue