Files
stream-chat-flutter/packages/stream_chat_flutter/lib/src/channel/channel_info.dart
T

200 lines
5.4 KiB
Dart

import 'package:collection/collection.dart' show IterableExtension;
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@template streamChannelInfo}
/// Displays information about the current [Channel].
/// {@endtemplate}
class StreamChannelInfo extends StatelessWidget {
/// {@macro streamChannelInfo}
const StreamChannelInfo({
super.key,
required this.channel,
this.textStyle,
this.showTypingIndicator = true,
this.parentId,
});
/// The channel to display information about
final Channel channel;
/// The style of the text displayed
final TextStyle? textStyle;
/// Whether to show the typing indicator
///
/// Defaults to `true`
final bool showTypingIndicator;
/// The ID of the parent message (in the case of a thread)
final String? parentId;
@override
Widget build(BuildContext context) {
final client = StreamChat.of(context).client;
return BetterStreamBuilder<List<Member>>(
stream: channel.state!.membersStream,
initialData: channel.state!.members,
builder: (context, data) => StreamConnectionStatusBuilder(
statusBuilder: (context, status) {
switch (status) {
case ConnectionStatus.connected:
return _ConnectedTitleState(
channel: channel,
showTypingIndicator: showTypingIndicator,
textStyle: textStyle,
members: data,
parentId: parentId,
);
case ConnectionStatus.connecting:
return _ConnectingTitleState(textStyle: textStyle);
case ConnectionStatus.disconnected:
return _DisconnectedTitleState(
client: client,
textStyle: textStyle,
);
default:
return const Offstage();
}
},
),
);
}
}
class _ConnectedTitleState extends StatelessWidget {
const _ConnectedTitleState({
required this.channel,
required this.showTypingIndicator,
this.members,
this.textStyle,
this.parentId,
});
final Channel channel;
final List<Member>? members;
final TextStyle? textStyle;
final bool showTypingIndicator;
final String? parentId;
@override
Widget build(BuildContext context) {
Widget? alternativeWidget;
final memberCount = channel.memberCount;
if (memberCount != null && memberCount > 2) {
var text = context.translations.membersCountText(memberCount);
final onlineCount =
members?.where((m) => m.user?.online == true).length ?? 0;
if (onlineCount > 0) {
text += ', ${context.translations.watchersCountText(onlineCount)}';
}
alternativeWidget = Text(
text,
style: StreamChannelHeaderTheme.of(context).subtitleStyle,
);
} else {
final userId = StreamChat.of(context).currentUser?.id;
final otherMember = members?.firstWhereOrNull(
(element) => element.userId != userId,
);
if (otherMember != null) {
if (otherMember.user?.online == true) {
alternativeWidget = Text(
context.translations.userOnlineText,
style: textStyle,
);
} else {
alternativeWidget = Text(
'${context.translations.userLastOnlineText} '
'${Jiffy(otherMember.user?.lastActive).fromNow()}',
style: textStyle,
);
}
}
}
if (!showTypingIndicator) {
return alternativeWidget ?? const Offstage();
}
return StreamTypingIndicator(
parentId: parentId,
alternativeWidget: alternativeWidget,
style: textStyle,
);
}
}
class _ConnectingTitleState extends StatelessWidget {
const _ConnectingTitleState({
this.textStyle,
});
final TextStyle? textStyle;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 16,
width: 16,
child: Center(
child: CircularProgressIndicator.adaptive(),
),
),
const SizedBox(width: 10),
Text(
context.translations.searchingForNetworkText,
style: textStyle,
),
],
);
}
}
class _DisconnectedTitleState extends StatelessWidget {
const _DisconnectedTitleState({
required this.client,
this.textStyle,
});
final StreamChatClient client;
final TextStyle? textStyle;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
context.translations.offlineLabel,
style: textStyle,
),
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: const VisualDensity(
horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity,
),
),
onPressed: () => client
..closeConnection()
..openConnection(),
child: Text(
context.translations.tryAgainLabel,
style: textStyle?.copyWith(
color: StreamChatTheme.of(context).colorTheme.accentPrimary,
),
),
),
],
);
}
}