Merge pull request #2947 from pangeachat/2842-show-participants-in-chat-list
2842 show participants in chat list
This commit is contained in:
commit
4fccaa92f2
6 changed files with 260 additions and 22 deletions
|
|
@ -20,6 +20,7 @@ import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
|||
import 'package:fluffychat/pangea/public_spaces/public_room_bottom_sheet.dart';
|
||||
import 'package:fluffychat/pangea/spaces/constants/space_constants.dart';
|
||||
import 'package:fluffychat/pangea/spaces/widgets/knocking_users_indicator.dart';
|
||||
import 'package:fluffychat/pangea/spaces/widgets/leaderboard_participant_list.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:fluffychat/utils/stream_extension.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||
|
|
@ -802,6 +803,14 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
// },
|
||||
// ),
|
||||
KnockingUsersIndicator(room: room),
|
||||
SliverList.builder(
|
||||
itemCount: 1,
|
||||
itemBuilder: (context, i) {
|
||||
return LeaderboardParticipantList(
|
||||
space: room,
|
||||
);
|
||||
},
|
||||
),
|
||||
// Pangea#
|
||||
SliverList.builder(
|
||||
itemCount: joinedRooms.length,
|
||||
|
|
|
|||
|
|
@ -98,11 +98,21 @@ class PresenceAvatar extends StatelessWidget {
|
|||
final CachedPresence presence;
|
||||
final double height;
|
||||
final void Function(Profile) onTap;
|
||||
// #Pangea
|
||||
final LinearGradient? gradient;
|
||||
final Widget? floatingIndicator;
|
||||
final bool showPresence;
|
||||
// Pangea#
|
||||
|
||||
const PresenceAvatar({
|
||||
required this.presence,
|
||||
required this.height,
|
||||
required this.onTap,
|
||||
// #Pangea
|
||||
this.gradient,
|
||||
this.showPresence = true,
|
||||
this.floatingIndicator,
|
||||
// Pangea#
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
|
@ -146,7 +156,11 @@ class PresenceAvatar extends StatelessWidget {
|
|||
Container(
|
||||
padding: const EdgeInsets.all(3),
|
||||
decoration: BoxDecoration(
|
||||
gradient: presence.gradient,
|
||||
// #Pangea
|
||||
// gradient: presence.gradient,
|
||||
gradient: gradient ??
|
||||
(showPresence ? presence.gradient : null),
|
||||
// Pangea#
|
||||
borderRadius:
|
||||
BorderRadius.circular(avatarSize),
|
||||
),
|
||||
|
|
@ -159,7 +173,11 @@ class PresenceAvatar extends StatelessWidget {
|
|||
size: avatarSize - 6,
|
||||
),
|
||||
),
|
||||
if (presence.userid == client.userID)
|
||||
// #Pangea
|
||||
// if (presence.userid == client.userID)
|
||||
if (floatingIndicator == null &&
|
||||
presence.userid == client.userID)
|
||||
// Pangea#
|
||||
Positioned(
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
|
|
@ -182,6 +200,9 @@ class PresenceAvatar extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
// #Pangea
|
||||
if (floatingIndicator != null) floatingIndicator!,
|
||||
// Pangea#
|
||||
if (statusMsg != null) ...[
|
||||
Positioned(
|
||||
left: 0,
|
||||
|
|
|
|||
|
|
@ -207,6 +207,36 @@ class SettingsController extends State<Settings> {
|
|||
// Pangea#
|
||||
}
|
||||
|
||||
// #Pangea
|
||||
void setStatus() async {
|
||||
final client = Matrix.of(context).client;
|
||||
final currentPresence = await client.fetchCurrentPresence(client.userID!);
|
||||
final input = await showTextInputDialog(
|
||||
useRootNavigator: false,
|
||||
context: context,
|
||||
title: L10n.of(context).setStatus,
|
||||
message: L10n.of(context).leaveEmptyToClearStatus,
|
||||
okLabel: L10n.of(context).ok,
|
||||
cancelLabel: L10n.of(context).cancel,
|
||||
hintText: L10n.of(context).statusExampleMessage,
|
||||
maxLines: 6,
|
||||
minLines: 1,
|
||||
maxLength: 255,
|
||||
initialText: currentPresence.statusMsg,
|
||||
);
|
||||
if (input == null) return;
|
||||
if (!mounted) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => client.setPresence(
|
||||
client.userID!,
|
||||
PresenceType.online,
|
||||
statusMsg: input,
|
||||
),
|
||||
);
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final client = Matrix.of(context).client;
|
||||
|
|
|
|||
|
|
@ -165,6 +165,25 @@ class SettingsView extends StatelessWidget {
|
|||
// style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
// #Pangea
|
||||
TextButton.icon(
|
||||
onPressed: controller.setStatus,
|
||||
icon: const Icon(
|
||||
Icons.add,
|
||||
size: 14,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor:
|
||||
theme.colorScheme.secondary,
|
||||
iconColor: theme.colorScheme.secondary,
|
||||
),
|
||||
label: Text(
|
||||
L10n.of(context).setStatus,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
// Pangea#
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import 'package:flutter_linkify/flutter_linkify.dart';
|
|||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pages/chat_details/chat_details.dart';
|
||||
import 'package:fluffychat/pages/chat_details/participant_list_item.dart';
|
||||
|
|
@ -23,6 +22,7 @@ import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
|||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/spaces/utils/load_participants_util.dart';
|
||||
import 'package:fluffychat/pangea/spaces/widgets/download_space_analytics_dialog.dart';
|
||||
import 'package:fluffychat/pangea/spaces/widgets/leaderboard_participant_list.dart';
|
||||
import 'package:fluffychat/utils/fluffy_share.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||
import 'package:fluffychat/utils/url_launcher.dart';
|
||||
|
|
@ -721,22 +721,15 @@ class RoomParticipantsSection extends StatelessWidget {
|
|||
runAlignment: WrapAlignment.center,
|
||||
children: [
|
||||
...filteredParticipants.mapIndexed((index, user) {
|
||||
Color? color = index == 0
|
||||
? AppConfig.gold
|
||||
: index == 1
|
||||
? Colors.grey[400]!
|
||||
: index == 2
|
||||
? Colors.brown[400]!
|
||||
: null;
|
||||
|
||||
final publicProfile = participantsLoader.getPublicProfile(
|
||||
user.id,
|
||||
);
|
||||
|
||||
LinearGradient? gradient = index.leaderboardGradient;
|
||||
if (user.id == BotName.byEnvironment ||
|
||||
publicProfile == null ||
|
||||
publicProfile.level == null) {
|
||||
color = null;
|
||||
gradient = null;
|
||||
}
|
||||
|
||||
return Padding(
|
||||
|
|
@ -748,21 +741,13 @@ class RoomParticipantsSection extends StatelessWidget {
|
|||
Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
if (color != null)
|
||||
if (gradient != null)
|
||||
CircleAvatar(
|
||||
radius: _width / 2,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
begin: const Alignment(0.5, -0.5),
|
||||
end: const Alignment(-0.5, 0.5),
|
||||
colors: <Color>[
|
||||
color,
|
||||
Colors.white,
|
||||
color,
|
||||
],
|
||||
),
|
||||
gradient: gradient,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
174
lib/pangea/spaces/widgets/leaderboard_participant_list.dart
Normal file
174
lib/pangea/spaces/widgets/leaderboard_participant_list.dart
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pages/chat_list/status_msg_list.dart';
|
||||
import 'package:fluffychat/pangea/bot/utils/bot_name.dart';
|
||||
import 'package:fluffychat/pangea/spaces/utils/load_participants_util.dart';
|
||||
import 'package:fluffychat/utils/stream_extension.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/user_dialog.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:fluffychat/widgets/presence_builder.dart';
|
||||
|
||||
class LeaderboardParticipantList extends StatefulWidget {
|
||||
final Room space;
|
||||
|
||||
const LeaderboardParticipantList({
|
||||
required this.space,
|
||||
super.key,
|
||||
});
|
||||
|
||||
static const double height = 116;
|
||||
|
||||
@override
|
||||
State<LeaderboardParticipantList> createState() =>
|
||||
LeaderboardParticipantListState();
|
||||
}
|
||||
|
||||
class LeaderboardParticipantListState
|
||||
extends State<LeaderboardParticipantList> {
|
||||
final _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final client = Matrix.of(context).client;
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return StreamBuilder(
|
||||
stream: client.onSync.stream.rateLimit(const Duration(seconds: 3)),
|
||||
builder: (context, snapshot) {
|
||||
return LoadParticipantsUtil(
|
||||
space: widget.space,
|
||||
builder: (participantsLoader) {
|
||||
final participants = participantsLoader.filteredParticipants("");
|
||||
|
||||
return AnimatedSize(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
curve: Curves.easeInOut,
|
||||
child: SizedBox(
|
||||
height: 130.0,
|
||||
child: Scrollbar(
|
||||
controller: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
8.0,
|
||||
8.0,
|
||||
8.0,
|
||||
16.0,
|
||||
),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: participants.length,
|
||||
itemBuilder: (context, i) {
|
||||
final user = participants[i];
|
||||
final publicProfile = participantsLoader.getPublicProfile(
|
||||
user.id,
|
||||
);
|
||||
|
||||
LinearGradient? gradient = i.leaderboardGradient;
|
||||
|
||||
if (user.id == BotName.byEnvironment ||
|
||||
publicProfile == null ||
|
||||
publicProfile.level == null) {
|
||||
gradient = null;
|
||||
}
|
||||
|
||||
return PresenceBuilder(
|
||||
userId: user.id,
|
||||
builder: (context, presence) {
|
||||
Color? dotColor;
|
||||
if (presence != null) {
|
||||
dotColor = presence.presence.isOnline
|
||||
? Colors.green
|
||||
: presence.presence.isUnavailable
|
||||
? Colors.orange
|
||||
: Colors.grey;
|
||||
}
|
||||
|
||||
return PresenceAvatar(
|
||||
presence: presence ??
|
||||
CachedPresence(
|
||||
PresenceType.unavailable,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
user.id,
|
||||
),
|
||||
height: StatusMessageList.height,
|
||||
onTap: (profile) => UserDialog.show(
|
||||
context: context,
|
||||
profile: profile,
|
||||
),
|
||||
gradient: gradient,
|
||||
showPresence: false,
|
||||
floatingIndicator: Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
width: 16,
|
||||
height: 16,
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
width: 10,
|
||||
height: 10,
|
||||
decoration: BoxDecoration(
|
||||
color: dotColor,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: theme.colorScheme.surface,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension LeaderboardGradient on int {
|
||||
LinearGradient? get leaderboardGradient {
|
||||
final Color? color = this == 0
|
||||
? AppConfig.gold
|
||||
: this == 1
|
||||
? Colors.grey[400]!
|
||||
: this == 2
|
||||
? Colors.brown[400]!
|
||||
: null;
|
||||
|
||||
if (color == null) return null;
|
||||
|
||||
return LinearGradient(
|
||||
colors: [
|
||||
color,
|
||||
Colors.white,
|
||||
color,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue