chore: normalize activity role list into separate widget and use it in activity state event and activity role selection widgets (#3747)
This commit is contained in:
parent
bd303a5796
commit
3fcf3845d8
4 changed files with 135 additions and 88 deletions
115
lib/pangea/activity_sessions/activity_participant_list.dart
Normal file
115
lib/pangea/activity_sessions/activity_participant_list.dart
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_participant_indicator.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_role_model.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
|
||||
class ActivityParticipantList extends StatelessWidget {
|
||||
final Room room;
|
||||
final Function(String)? onTap;
|
||||
|
||||
final bool Function(String)? canSelect;
|
||||
final bool Function(String)? isSelected;
|
||||
final double Function(ActivityRoleModel?)? getOpacity;
|
||||
|
||||
const ActivityParticipantList({
|
||||
super.key,
|
||||
required this.room,
|
||||
this.onTap,
|
||||
this.canSelect,
|
||||
this.isSelected,
|
||||
this.getOpacity,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final availableRoles = room.activityPlan!.roles;
|
||||
final assignedRoles = room.assignedRoles ?? {};
|
||||
|
||||
final remainingMembers = room.getParticipants().where(
|
||||
(p) => !assignedRoles.values.any((r) => r.userId == p.id),
|
||||
);
|
||||
|
||||
return Column(
|
||||
spacing: 12.0,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 12.0,
|
||||
runSpacing: 12.0,
|
||||
children: availableRoles.values.map((availableRole) {
|
||||
final assignedRole = assignedRoles[availableRole.id];
|
||||
final user = room.getParticipants().firstWhereOrNull(
|
||||
(u) => u.id == assignedRole?.userId,
|
||||
);
|
||||
|
||||
final selectable =
|
||||
canSelect != null ? canSelect!(availableRole.id) : true;
|
||||
|
||||
return ActivityParticipantIndicator(
|
||||
availableRole: availableRole,
|
||||
assignedRole: assignedRole,
|
||||
opacity: getOpacity != null ? getOpacity!(assignedRole) : 1.0,
|
||||
avatarUrl: availableRole.avatarUrl ?? user?.avatarUrl?.toString(),
|
||||
onTap: onTap != null && selectable
|
||||
? () => onTap!(availableRole.id)
|
||||
: null,
|
||||
selected:
|
||||
isSelected != null ? isSelected!(availableRole.id) : false,
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 12.0,
|
||||
runSpacing: 12.0,
|
||||
children: remainingMembers.map((member) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(18.0),
|
||||
),
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Opacity(
|
||||
opacity: 0.5,
|
||||
child: Row(
|
||||
spacing: 4.0,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Avatar(
|
||||
size: 18.0,
|
||||
mxContent: member.avatarUrl,
|
||||
name: member.calcDisplayname(),
|
||||
userId: member.id,
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 80.0,
|
||||
),
|
||||
child: Text(
|
||||
member.calcDisplayname(),
|
||||
style: TextStyle(
|
||||
fontSize: 12.0,
|
||||
color: theme.colorScheme.onPrimaryContainer,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,12 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.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_plan_model.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_participant_indicator.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_participant_list.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
|
||||
class ActivityStateEvent extends StatelessWidget {
|
||||
final Event event;
|
||||
|
|
@ -22,15 +20,6 @@ class ActivityStateEvent extends StatelessWidget {
|
|||
|
||||
try {
|
||||
final activity = ActivityPlanModel.fromJson(event.content);
|
||||
final availableRoles = event.room.activityPlan!.roles;
|
||||
final assignedRoles = event.room.assignedRoles ?? {};
|
||||
|
||||
final remainingMembers = event.room.getParticipants().where(
|
||||
(p) => !assignedRoles.values.any((r) => r.userId == p.id),
|
||||
);
|
||||
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 24.0,
|
||||
|
|
@ -48,69 +37,10 @@ class ActivityStateEvent extends StatelessWidget {
|
|||
),
|
||||
if (event.room.ownRole != null ||
|
||||
event.room.remainingRoles == 0) ...[
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 12.0,
|
||||
runSpacing: 12.0,
|
||||
children: availableRoles.values.map((availableRole) {
|
||||
final assignedRole = assignedRoles[availableRole.id];
|
||||
final user = event.room.getParticipants().firstWhereOrNull(
|
||||
(u) => u.id == assignedRole?.userId,
|
||||
);
|
||||
|
||||
return ActivityParticipantIndicator(
|
||||
availableRole: availableRole,
|
||||
assignedRole: assignedRole,
|
||||
opacity: assignedRole == null || assignedRole.isFinished
|
||||
? 0.5
|
||||
: 1.0,
|
||||
avatarUrl:
|
||||
availableRole.avatarUrl ?? user?.avatarUrl?.toString(),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 12.0,
|
||||
runSpacing: 12.0,
|
||||
children: remainingMembers.map((member) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(18.0),
|
||||
),
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Opacity(
|
||||
opacity: 0.5,
|
||||
child: Row(
|
||||
spacing: 4.0,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Avatar(
|
||||
size: 18.0,
|
||||
mxContent: member.avatarUrl,
|
||||
name: member.calcDisplayname(),
|
||||
userId: member.id,
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 80.0,
|
||||
),
|
||||
child: Text(
|
||||
member.calcDisplayname(),
|
||||
style: TextStyle(
|
||||
fontSize: 12.0,
|
||||
color: theme.colorScheme.onPrimaryContainer,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
ActivityParticipantList(
|
||||
room: event.room,
|
||||
getOpacity: (role) =>
|
||||
role == null || role.isFinished ? 0.5 : 1.0,
|
||||
),
|
||||
],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import 'package:matrix/matrix.dart';
|
|||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_participant_indicator.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_participant_list.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||
|
||||
|
|
@ -47,18 +47,11 @@ class ActivityUnfinishedStatusMessageState
|
|||
children: [
|
||||
if (!completed) ...[
|
||||
if (unassignedIds.isNotEmpty)
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 12.0,
|
||||
runSpacing: 12.0,
|
||||
children: unassignedIds.map((id) {
|
||||
return ActivityParticipantIndicator(
|
||||
availableRole: availableRoles[id]!,
|
||||
selected: _selectedRoleId == id,
|
||||
onTap: () => _selectRole(id),
|
||||
avatarUrl: availableRoles[id]?.avatarUrl,
|
||||
);
|
||||
}).toList(),
|
||||
ActivityParticipantList(
|
||||
room: widget.room,
|
||||
onTap: _selectRole,
|
||||
isSelected: (id) => _selectedRoleId == id,
|
||||
canSelect: (id) => unassignedIds.contains(id),
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -173,22 +173,27 @@ class SpaceAnalyticsView extends StatelessWidget {
|
|||
controller.downloads.length,
|
||||
),
|
||||
icon: Icons.group_outlined,
|
||||
mini: mini,
|
||||
),
|
||||
_TableHeaderCell(
|
||||
text: L10n.of(context).level,
|
||||
icon: Icons.star,
|
||||
mini: mini,
|
||||
),
|
||||
_TableHeaderCell(
|
||||
text: L10n.of(context).vocab,
|
||||
icon: Symbols.dictionary,
|
||||
mini: mini,
|
||||
),
|
||||
_TableHeaderCell(
|
||||
text: L10n.of(context).grammar,
|
||||
icon: Symbols.toys_and_games,
|
||||
mini: mini,
|
||||
),
|
||||
_TableHeaderCell(
|
||||
text: L10n.of(context).activities,
|
||||
icon: Icons.radar,
|
||||
mini: mini,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -263,18 +268,21 @@ class SpaceAnalyticsView extends StatelessWidget {
|
|||
text: download.summary?.level?.toString(),
|
||||
downloadStatus: download.downloadStatus,
|
||||
requestStatus: download.requestStatus,
|
||||
mini: mini,
|
||||
),
|
||||
_TableContentCell(
|
||||
text: download.summary?.numLemmas
|
||||
.toString(),
|
||||
downloadStatus: download.downloadStatus,
|
||||
requestStatus: download.requestStatus,
|
||||
mini: mini,
|
||||
),
|
||||
_TableContentCell(
|
||||
text: download.summary?.numMorphConstructs
|
||||
.toString(),
|
||||
downloadStatus: download.downloadStatus,
|
||||
requestStatus: download.requestStatus,
|
||||
mini: mini,
|
||||
),
|
||||
_TableContentCell(
|
||||
text: download
|
||||
|
|
@ -282,6 +290,7 @@ class SpaceAnalyticsView extends StatelessWidget {
|
|||
.toString(),
|
||||
downloadStatus: download.downloadStatus,
|
||||
requestStatus: download.requestStatus,
|
||||
mini: mini,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue