diff --git a/lib/pangea/activity_sessions/activity_participant_indicator.dart b/lib/pangea/activity_sessions/activity_participant_indicator.dart index 2ba790e3d..4cbc37fe6 100644 --- a/lib/pangea/activity_sessions/activity_participant_indicator.dart +++ b/lib/pangea/activity_sessions/activity_participant_indicator.dart @@ -45,6 +45,7 @@ class ActivityParticipantIndicator extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); + final borderRadius = this.borderRadius ?? BorderRadius.circular(8.0); return MouseRegion( cursor: SystemMouseCursors.basic, child: GestureDetector( @@ -99,20 +100,21 @@ class ActivityParticipantIndicator extends StatelessWidget { opacity: opacity, child: ShimmerBackground( enabled: shimmer, + borderRadius: borderRadius, child: Container( + alignment: Alignment.center, padding: padding ?? const EdgeInsets.symmetric( vertical: 4.0, horizontal: 8.0, ), decoration: BoxDecoration( - borderRadius: borderRadius ?? BorderRadius.circular(8.0), + borderRadius: borderRadius, color: (hovered || selected) && selectable ? theme.colorScheme.surfaceContainerHighest : theme.colorScheme.surface.withAlpha(130), ), height: 125.0, - constraints: const BoxConstraints(maxWidth: 100.0), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/pangea/activity_sessions/activity_participant_list.dart b/lib/pangea/activity_sessions/activity_participant_list.dart index ecc3f7a7f..a29c3f23a 100644 --- a/lib/pangea/activity_sessions/activity_participant_list.dart +++ b/lib/pangea/activity_sessions/activity_participant_list.dart @@ -52,51 +52,79 @@ class ActivityParticipantList extends StatelessWidget { spacing: 12.0, mainAxisSize: MainAxisSize.min, children: [ - Wrap( - alignment: WrapAlignment.center, - spacing: 12.0, - runSpacing: 12.0, - children: availableRoles.map((availableRole) { - final selected = - isSelected != null ? isSelected!(availableRole.id) : false; + LayoutBuilder( + builder: (context, constraints) { + const minItemWidth = 125.0; - final assignedRole = assignedRoles[availableRole.id] ?? - (selected - ? ActivityRoleModel( - id: availableRole.id, - userId: Matrix.of(context).client.userID!, - role: availableRole.name, - ) - : null); + final rows = (availableRoles.length / + (constraints.maxWidth / minItemWidth)) + .ceil(); - final User? user = participants.participants.firstWhereOrNull( - (u) => u.id == assignedRole?.userId, - ) ?? - course?.getParticipants().firstWhereOrNull( - (u) => u.id == assignedRole?.userId, + final entriesPerRow = (availableRoles.length / rows).ceil(); + + return Column( + spacing: 8.0, + children: List.generate(rows, (rowIndex) { + final entries = availableRoles + .skip(rowIndex * entriesPerRow) + .take(entriesPerRow) + .toList(); + + return Row( + spacing: 8.0, + mainAxisAlignment: MainAxisAlignment.center, + children: entries.map((availableRole) { + final selected = isSelected != null + ? isSelected!(availableRole.id) + : false; + + final assignedRole = assignedRoles[availableRole.id] ?? + (selected + ? ActivityRoleModel( + id: availableRole.id, + userId: Matrix.of(context).client.userID!, + role: availableRole.name, + ) + : null); + + final User? user = + participants.participants.firstWhereOrNull( + (u) => u.id == assignedRole?.userId, + ) ?? + course?.getParticipants().firstWhereOrNull( + (u) => u.id == assignedRole?.userId, + ); + + final selectable = canSelect != null + ? canSelect!(availableRole.id) + : true; + + final shimmering = isShimmering != null + ? isShimmering!(availableRole.id) + : false; + + return Expanded( + child: ActivityParticipantIndicator( + name: availableRole.name, + userId: assignedRole?.userId, + opacity: getOpacity != null + ? getOpacity!(assignedRole) + : 1.0, + user: user, + onTap: onTap != null && selectable + ? () => onTap!(availableRole.id) + : null, + selected: selected, + selectable: selectable, + shimmer: shimmering, + room: room, + ), ); - - final selectable = - canSelect != null ? canSelect!(availableRole.id) : true; - - final shimmering = isShimmering != null - ? isShimmering!(availableRole.id) - : false; - - return ActivityParticipantIndicator( - name: availableRole.name, - userId: assignedRole?.userId, - opacity: getOpacity != null ? getOpacity!(assignedRole) : 1.0, - user: user, - onTap: onTap != null && selectable - ? () => onTap!(availableRole.id) - : null, - selected: selected, - selectable: selectable, - shimmer: shimmering, - room: room, + }).toList(), + ); + }), ); - }).toList(), + }, ), Wrap( alignment: WrapAlignment.center, diff --git a/lib/pangea/activity_sessions/activity_user_summaries_widget.dart b/lib/pangea/activity_sessions/activity_user_summaries_widget.dart index 2553f1a5a..fa2a52513 100644 --- a/lib/pangea/activity_sessions/activity_user_summaries_widget.dart +++ b/lib/pangea/activity_sessions/activity_user_summaries_widget.dart @@ -290,14 +290,20 @@ class ButtonControlledCarouselView extends StatelessWidget { (role) => role.userId == p.participantId, ); final userRoleInfo = availableRoles[userRole.id]!; - return ActivityParticipantIndicator( - name: userRoleInfo.name, - userId: p.participantId, - user: user, - borderRadius: BorderRadius.circular(4), - selected: highlightedRole?.id == userRole.id, - onTap: () => _scrollToUser(userRole, index, cardWidth), - room: controller.room, + return SizedBox( + width: 100.0, + height: 125.0, + child: Center( + child: ActivityParticipantIndicator( + name: userRoleInfo.name, + userId: p.participantId, + user: user, + borderRadius: BorderRadius.circular(4), + selected: highlightedRole?.id == userRole.id, + onTap: () => _scrollToUser(userRole, index, cardWidth), + room: controller.room, + ), + ), ); }, ); diff --git a/lib/pangea/common/widgets/shimmer_background.dart b/lib/pangea/common/widgets/shimmer_background.dart index 0fbc5104e..86b7cd49e 100644 --- a/lib/pangea/common/widgets/shimmer_background.dart +++ b/lib/pangea/common/widgets/shimmer_background.dart @@ -9,6 +9,7 @@ class ShimmerBackground extends StatelessWidget { final Color shimmerColor; final Color? baseColor; final bool enabled; + final BorderRadius? borderRadius; const ShimmerBackground({ super.key, @@ -16,10 +17,13 @@ class ShimmerBackground extends StatelessWidget { this.shimmerColor = AppConfig.goldLight, this.baseColor, this.enabled = true, + this.borderRadius, }); @override Widget build(BuildContext context) { + final borderRadius = + this.borderRadius ?? BorderRadius.circular(AppConfig.borderRadius); return Stack( children: [ child, @@ -27,7 +31,7 @@ class ShimmerBackground extends StatelessWidget { Positioned.fill( child: IgnorePointer( child: ClipRRect( - borderRadius: BorderRadius.circular(AppConfig.borderRadius), + borderRadius: borderRadius, child: Shimmer.fromColors( baseColor: baseColor ?? shimmerColor.withValues(alpha: 0.1), highlightColor: shimmerColor.withValues(alpha: 0.6), @@ -35,8 +39,7 @@ class ShimmerBackground extends StatelessWidget { child: Container( decoration: BoxDecoration( color: shimmerColor.withValues(alpha: 0.3), - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), + borderRadius: borderRadius, ), ), ),