Merge pull request #1002 from GetStream/refactor/deprecate-v3

refactor(ui, core): deprecate v3
This commit is contained in:
Salvatore Giordano
2022-03-17 10:46:25 +01:00
committed by GitHub
138 changed files with 3979 additions and 1510 deletions
@@ -15,6 +15,7 @@ on:
jobs:
analyze:
timeout-minutes: 15
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- name: "Git Checkout"
@@ -45,6 +46,7 @@ jobs:
format:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
timeout-minutes: 15
steps:
- name: "Git Checkout"
@@ -73,6 +75,7 @@ jobs:
test:
runs-on: macos-latest
if: github.event.pull_request.draft == false
timeout-minutes: 20
steps:
- name: "Git Checkout"
@@ -123,3 +126,12 @@ jobs:
with:
path: packages/stream_chat_flutter/coverage/lcov.info
min_coverage: 67
draft-build:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == true
timeout-minutes: 1
steps:
- name: Run a one-line script
run: echo Draft PR, you are good.
+6
View File
@@ -1,3 +1,9 @@
## 3.5.1
🐞 Fixed
- `channel.unreadCount` was being set as using global unread count on a very specific case.
- The reconnection logic for the WebSocket connection is now more robust.
## 3.5.0
✅ Added
@@ -1926,7 +1926,6 @@ class ChannelClientState {
readList.add(Read(
user: event.user!,
lastRead: event.createdAt,
unreadMessages: event.totalUnreadCount ?? 0,
));
_channelState = _channelState.copyWith(read: readList);
}
+11 -3
View File
@@ -190,8 +190,12 @@ class WebSocket with TimerHelper {
_connectionStatus = ConnectionStatus.connecting;
connectionCompleter = Completer<Event>();
final uri = await _buildUri();
_initWebSocketChannel(uri);
try {
final uri = await _buildUri();
_initWebSocketChannel(uri);
} catch (e, stk) {
_onConnectionError(e, stk);
}
return connectionCompleter!.future;
}
@@ -216,7 +220,11 @@ class WebSocket with TimerHelper {
Duration(milliseconds: delay),
() async {
final uri = await _buildUri(refreshToken: refreshToken);
_initWebSocketChannel(uri);
try {
_initWebSocketChannel(uri);
} catch (e, stk) {
_onConnectionError(e, stk);
}
},
);
}
+1 -1
View File
@@ -3,4 +3,4 @@ import 'package:stream_chat/src/client/client.dart';
/// Current package version
/// Used in [StreamChatClient] to build the `x-stream-client` header
// ignore: constant_identifier_names
const PACKAGE_VERSION = '3.5.0';
const PACKAGE_VERSION = '3.5.1';
+2 -2
View File
@@ -1,7 +1,7 @@
name: stream_chat
homepage: https://getstream.io/
description: The official Dart client for Stream Chat, a service for building chat applications.
version: 3.5.0
version: 3.5.1
repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -30,5 +30,5 @@ dev_dependencies:
dart_code_metrics: ^4.4.0
freezed: ^1.0.0
json_serializable: ^6.0.1
mocktail: ^0.2.0
mocktail: ^0.3.0
test: ^1.17.12
+3 -2
View File
@@ -1,4 +1,4 @@
## Upcoming
## 3.5.1
🛑️ Breaking Changes
@@ -7,7 +7,8 @@
🐞 Fixed
- Mentions overlay now doesn't overflow when not enough height available
- Mentions overlay now doesn't overflow when there is not enough height available
- Updated `stream_chat_flutter_core` dependency to [`3.5.1`](https://pub.dev/packages/stream_chat_flutter_core/changelog).
## 3.5.0
@@ -87,7 +87,7 @@ class MyApp extends StatelessWidget {
/// A list of messages sent in the current channel.
///
/// This is implemented using [MessageListView], a widget that provides query
/// This is implemented using [StreamMessageListView], a widget that provides query
/// functionalities fetching the messages from the api and showing them in a
/// listView.
class ChannelPage extends StatelessWidget {
@@ -98,13 +98,13 @@ class ChannelPage extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
appBar: const ChannelHeader(),
appBar: const StreamChannelHeader(),
body: Column(
children: const <Widget>[
Expanded(
child: MessageListView(),
child: StreamMessageListView(),
),
MessageInput(attachmentLimit: 3),
StreamMessageInput(attachmentLimit: 3),
],
),
);
@@ -125,15 +125,15 @@ class ChannelPage extends StatelessWidget {
Widget build(BuildContext context) => Navigator(
onGenerateRoute: (settings) => MaterialPageRoute(
builder: (context) => Scaffold(
appBar: const ChannelHeader(
appBar: const StreamChannelHeader(
showBackButton: false,
),
body: Column(
children: const <Widget>[
Expanded(
child: MessageListView(),
child: StreamMessageListView(),
),
MessageInput(),
StreamMessageInput(),
],
),
),
@@ -27,7 +27,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// - We make [StreamChat] the root Widget of our application
///
/// - We create a single [ChannelPage] widget under [StreamChat] with three
/// widgets: [ChannelHeader], [MessageListView] and [MessageInput]
/// widgets: [StreamChannelHeader], [StreamMessageListView] and [StreamMessageInput]
///
/// If you now run the simulator you will see a single channel UI.
void main() async {
@@ -91,13 +91,13 @@ class ChannelPage extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
appBar: const ChannelHeader(),
appBar: const StreamChannelHeader(),
body: Column(
children: const <Widget>[
Expanded(
child: MessageListView(),
child: StreamMessageListView(),
),
MessageInput(),
StreamMessageInput(),
],
),
);
@@ -25,7 +25,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// The [ChannelListPage] widget retrieves the list of channels based on a
/// custom query and ordering. In this case we are showing the list of
/// channels in which the current user is a member and we order them based
/// on the time they had a new message. [ChannelListView] handles pagination
/// on the time they had a new message. [StreamChannelListView] handles pagination
/// and updates automatically when new channels are created or when a new
/// message is added to a channel.
void main() async {
@@ -118,13 +118,13 @@ class ChannelPage extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
appBar: const ChannelHeader(),
appBar: const StreamChannelHeader(),
body: Column(
children: const <Widget>[
Expanded(
child: MessageListView(),
child: StreamMessageListView(),
),
MessageInput(),
StreamMessageInput(),
],
),
);
@@ -15,8 +15,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// We start by changing how channel previews are shown in the channel list
/// and include the number of unread messages for each.
///
/// We're passing a custom widget to [ChannelListView.channelPreviewBuilder];
/// this will override the default [ChannelPreview] and allows you to create
/// We're passing a custom widget to [StreamChannelListView.channelPreviewBuilder];
/// this will override the default [StreamChannelPreview] and allows you to create
/// one yourself.
///
/// There are a couple interesting things we do in this widget:
@@ -134,7 +134,7 @@ class _ChannelListPageState extends State<ChannelListPage> {
channel: channel,
),
title: StreamChannelName(
textStyle: ChannelPreviewTheme.of(context).titleStyle!.copyWith(
textStyle: StreamChannelPreviewTheme.of(context).titleStyle!.copyWith(
color: StreamChatTheme.of(context)
.colorTheme
.textHighEmphasis
@@ -162,13 +162,13 @@ class ChannelPage extends StatelessWidget {
// ignore: prefer_expression_function_bodies
Widget build(BuildContext context) {
return Scaffold(
appBar: const ChannelHeader(),
appBar: const StreamChannelHeader(),
body: Column(
children: const <Widget>[
Expanded(
child: MessageListView(),
child: StreamMessageListView(),
),
MessageInput(),
StreamMessageInput(),
],
),
);
@@ -8,8 +8,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// to create sub-conversations inside the same channel.
///
/// Using threaded conversations is very simple and mostly a matter of
/// plugging the [MessageListView] to another widget that renders the widget.
/// To make this simple, such a widget only needs to build [MessageListView]
/// plugging the [StreamMessageListView] to another widget that renders the widget.
/// To make this simple, such a widget only needs to build [StreamMessageListView]
/// with the parent attribute set to the threads root message.
///
/// Now we can open threads and create new ones as well. If you long-press a
@@ -98,17 +98,17 @@ class ChannelPage extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
appBar: const ChannelHeader(),
appBar: const StreamChannelHeader(),
body: Column(
children: <Widget>[
Expanded(
child: MessageListView(
child: StreamMessageListView(
threadBuilder: (_, parentMessage) => ThreadPage(
parent: parentMessage,
),
),
),
const MessageInput(),
const StreamMessageInput(),
],
),
);
@@ -126,17 +126,17 @@ class ThreadPage extends StatelessWidget {
// ignore: prefer_expression_function_bodies
Widget build(BuildContext context) {
return Scaffold(
appBar: ThreadHeader(
appBar: StreamThreadHeader(
parent: parent!,
),
body: Column(
children: <Widget>[
Expanded(
child: MessageListView(
child: StreamMessageListView(
parentMessage: parent,
),
),
MessageInput(
StreamMessageInput(
messageInputController: MessageInputController(
message: Message(parentId: parent!.id),
),
@@ -8,7 +8,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// the SDK supports easily.
///
/// Replacing the built-in message component with your own is done by passing
/// it as a builder function to the [MessageListView] widget.
/// it as a builder function to the [StreamMessageListView] widget.
///
/// The message builder function will get the usual [BuildContext] argument
/// as well as the [Message] object and its position inside the list.
@@ -106,15 +106,15 @@ class ChannelPage extends StatelessWidget {
// ignore: prefer_expression_function_bodies
Widget build(BuildContext context) {
return Scaffold(
appBar: const ChannelHeader(),
appBar: const StreamChannelHeader(),
body: Column(
children: <Widget>[
Expanded(
child: MessageListView(
child: StreamMessageListView(
messageBuilder: _messageBuilder,
),
),
const MessageInput(),
const StreamMessageInput(),
],
),
);
@@ -124,7 +124,7 @@ class ChannelPage extends StatelessWidget {
BuildContext context,
MessageDetails details,
List<Message> messages,
MessageWidget _,
StreamMessageWidget _,
) {
final message = details.message;
final isCurrentUser =
@@ -58,24 +58,24 @@ class MyApp extends StatelessWidget {
final defaultTheme = StreamChatThemeData.fromTheme(themeData);
final colorTheme = defaultTheme.colorTheme;
final customTheme = defaultTheme.merge(StreamChatThemeData(
channelPreviewTheme: ChannelPreviewThemeData(
avatarTheme: AvatarThemeData(
channelPreviewTheme: StreamChannelPreviewThemeData(
avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(8),
),
),
messageListViewTheme: const MessageListViewThemeData(
messageListViewTheme: const StreamMessageListViewThemeData(
backgroundColor: Colors.grey,
backgroundImage: DecorationImage(
image: AssetImage('assets/background_doodle.png'),
fit: BoxFit.cover,
),
),
otherMessageTheme: MessageThemeData(
otherMessageTheme: StreamMessageThemeData(
messageBackgroundColor: colorTheme.textHighEmphasis,
messageTextStyle: TextStyle(
color: colorTheme.barsBg,
),
avatarTheme: AvatarThemeData(
avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(8),
),
),
@@ -137,17 +137,17 @@ class ChannelPage extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
appBar: const ChannelHeader(),
appBar: const StreamChannelHeader(),
body: Column(
children: <Widget>[
Expanded(
child: MessageListView(
child: StreamMessageListView(
threadBuilder: (_, parentMessage) => ThreadPage(
parent: parentMessage,
),
),
),
const MessageInput(),
const StreamMessageInput(),
],
),
);
@@ -165,17 +165,17 @@ class ThreadPage extends StatelessWidget {
// ignore: prefer_expression_function_bodies
Widget build(BuildContext context) {
return Scaffold(
appBar: ThreadHeader(
appBar: StreamThreadHeader(
parent: parent!,
),
body: Column(
children: <Widget>[
Expanded(
child: MessageListView(
child: StreamMessageListView(
parentMessage: parent,
),
),
MessageInput(
StreamMessageInput(
messageInputController: MessageInputController(
message: Message(parentId: parent!.id),
),
@@ -1,17 +1,23 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro attachment_title}
@Deprecated("Use 'StreamAttachmentTitle' instead")
typedef AttachmentTitle = StreamAttachmentTitle;
/// {@template attachment_title}
/// Title for attachments
class AttachmentTitle extends StatelessWidget {
/// {@endtemplate}
class StreamAttachmentTitle extends StatelessWidget {
/// Supply attachment and theme for constructing title
const AttachmentTitle({
const StreamAttachmentTitle({
Key? key,
required this.attachment,
required this.messageTheme,
}) : super(key: key);
/// Theme to apply to text
final MessageThemeData messageTheme;
final StreamMessageThemeData messageTheme;
/// Attachment data to display
final Attachment attachment;
@@ -9,10 +9,16 @@ typedef InProgressBuilder = Widget Function(BuildContext, int, int);
/// Widget to build on failure
typedef FailedBuilder = Widget Function(BuildContext, String);
/// {@macro attachment_upload_state_builder}
@Deprecated("Use 'StreamAttachmentsUploadStateBuilder' instead")
typedef AttachmentUploadStateBuilder = StreamAttachmentUploadStateBuilder;
/// {@template attachment_upload_state_builder}
/// Widget to display attachment upload state
class AttachmentUploadStateBuilder extends StatelessWidget {
/// Constructor for creating an [AttachmentUploadStateBuilder] widget
const AttachmentUploadStateBuilder({
/// {@endtemplate}
class StreamAttachmentUploadStateBuilder extends StatelessWidget {
/// Constructor for creating an [StreamAttachmentUploadStateBuilder] widget
const StreamAttachmentUploadStateBuilder({
Key? key,
required this.message,
required this.attachment,
@@ -137,7 +143,7 @@ class _PreparingState extends StatelessWidget {
),
Align(
alignment: Alignment.topRight,
child: UploadProgressIndicator(
child: StreamUploadProgressIndicator(
uploaded: 0,
total: double.maxFinite.toInt(),
),
@@ -177,7 +183,7 @@ class _InProgressState extends StatelessWidget {
),
Align(
alignment: Alignment.topRight,
child: UploadProgressIndicator(
child: StreamUploadProgressIndicator(
uploaded: sent,
total: total,
),
@@ -28,10 +28,16 @@ extension AttachmentSourceX on AttachmentSource {
}
}
/// {@macro attachment_widget}
@Deprecated("Use 'StreamAttachmentWidget' instead")
typedef AttachmentWidget = StreamAttachmentWidget;
/// {@template attachment_widget}
/// Abstract class for deriving attachment types
abstract class AttachmentWidget extends StatelessWidget {
/// {@endtemplate}
abstract class StreamAttachmentWidget extends StatelessWidget {
/// Constructor for creating attachment widget
const AttachmentWidget({
const StreamAttachmentWidget({
Key? key,
required this.message,
required this.attachment,
@@ -10,10 +10,16 @@ import 'package:stream_chat_flutter/src/utils.dart';
import 'package:stream_chat_flutter/src/video_thumbnail_image.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
/// {@macro file_attachment}
@Deprecated("Use 'StreamFileAttachment' instead")
typedef FileAttachment = StreamFileAttachment;
/// {@template file_attachment}
/// Widget for displaying file attachments
class FileAttachment extends AttachmentWidget {
/// {@endtemplate}
class StreamFileAttachment extends StreamAttachmentWidget {
/// Constructor for creating a widget when attachment is of type 'file'
const FileAttachment({
const StreamFileAttachment({
Key? key,
required Message message,
required Attachment attachment,
@@ -157,7 +163,7 @@ class FileAttachment extends AttachmentWidget {
type: MaterialType.transparency,
shape: _getDefaultShape(context),
child: source.when(
local: () => VideoThumbnailImage(
local: () => StreamVideoThumbnailImage(
fit: BoxFit.cover,
video: attachment.file!.path!,
placeholderBuilder: (_) => const Center(
@@ -168,7 +174,7 @@ class FileAttachment extends AttachmentWidget {
),
),
),
network: () => VideoThumbnailImage(
network: () => StreamVideoThumbnailImage(
fit: BoxFit.cover,
video: attachment.assetUrl!,
placeholderBuilder: (_) => const Center(
@@ -278,7 +284,7 @@ class FileAttachment extends AttachmentWidget {
);
return attachment.uploadState.when(
preparing: () => Text(fileSize(size), style: textStyle),
inProgress: (sent, total) => UploadProgressIndicator(
inProgress: (sent, total) => StreamUploadProgressIndicator(
uploaded: sent,
total: total,
showBackground: false,
@@ -5,10 +5,16 @@ import 'package:stream_chat_flutter/src/attachment/attachment_widget.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro giphy_attachment}
@Deprecated("Use 'StreamGiphyAttachment' instead")
typedef GiphyAttachment = StreamGiphyAttachment;
/// {@template giphy_attachment}
/// Widget for showing a GIF attachment
class GiphyAttachment extends AttachmentWidget {
/// Constructor for creating a [GiphyAttachment] widget
const GiphyAttachment({
/// {@endtemplate}
class StreamGiphyAttachment extends StreamAttachmentWidget {
/// Constructor for creating a [StreamGiphyAttachment] widget
const StreamGiphyAttachment({
Key? key,
required Message message,
required Attachment attachment,
@@ -228,7 +234,7 @@ class GiphyAttachment extends AttachmentWidget {
alignment: Alignment.centerRight,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: VisibleFootnote(),
child: StreamVisibleFootnote(),
),
),
],
@@ -243,7 +249,7 @@ class GiphyAttachment extends AttachmentWidget {
final channel = StreamChannel.of(context).channel;
return StreamChannel(
channel: channel,
child: FullScreenMedia(
child: StreamFullScreenMedia(
mediaAttachments: message.attachments,
startIndex: message.attachments.indexOf(attachment),
userName: message.user?.name,
@@ -5,10 +5,16 @@ import 'package:stream_chat_flutter/src/attachment/attachment_title.dart';
import 'package:stream_chat_flutter/src/attachment/attachment_widget.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro image_attachment}
@Deprecated("use 'StreamImageAttachment' instead")
typedef ImageAttachment = StreamImageAttachment;
/// {@template image_attachment}
/// Widget for showing an image attachment
class ImageAttachment extends AttachmentWidget {
/// Constructor for creating a [ImageAttachment] widget
const ImageAttachment({
/// {@endtemplate}
class StreamImageAttachment extends StreamAttachmentWidget {
/// Constructor for creating a [StreamImageAttachment] widget
const StreamImageAttachment({
Key? key,
required Message message,
required Attachment attachment,
@@ -25,8 +31,8 @@ class ImageAttachment extends AttachmentWidget {
size: size,
);
/// [MessageThemeData] for showing image title
final MessageThemeData messageTheme;
/// [StreamMessageThemeData] for showing image title
final StreamMessageThemeData messageTheme;
/// Flag for showing title
final bool showTitle;
@@ -137,7 +143,7 @@ class ImageAttachment extends AttachmentWidget {
StreamChannel.of(context).channel;
return StreamChannel(
channel: channel,
child: FullScreenMedia(
child: StreamFullScreenMedia(
mediaAttachments: message.attachments,
startIndex:
message.attachments.indexOf(attachment),
@@ -155,7 +161,7 @@ class ImageAttachment extends AttachmentWidget {
),
Padding(
padding: const EdgeInsets.all(8),
child: AttachmentUploadStateBuilder(
child: StreamAttachmentUploadStateBuilder(
message: message,
attachment: attachment,
),
@@ -166,7 +172,7 @@ class ImageAttachment extends AttachmentWidget {
if (showTitle && attachment.title != null)
Material(
color: messageTheme.messageBackgroundColor,
child: AttachmentTitle(
child: StreamAttachmentTitle(
messageTheme: messageTheme,
attachment: attachment,
),
@@ -2,10 +2,16 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro url_attachment}
@Deprecated("Use 'StreamUrlAttachment' instead")
typedef UrlAttachment = StreamUrlAttachment;
/// {@template url_attachment}
/// Widget to display URL attachment
class UrlAttachment extends StatelessWidget {
/// Constructor for creating a [UrlAttachment]
const UrlAttachment({
/// {@endtemplate}
class StreamUrlAttachment extends StatelessWidget {
/// Constructor for creating a [StreamUrlAttachment]
const StreamUrlAttachment({
Key? key,
required this.urlAttachment,
required this.hostDisplayName,
@@ -25,8 +31,8 @@ class UrlAttachment extends StatelessWidget {
/// Padding for text
final EdgeInsets textPadding;
/// [MessageThemeData] for showing image title
final MessageThemeData messageTheme;
/// [StreamMessageThemeData] for showing image title
final StreamMessageThemeData messageTheme;
@override
Widget build(BuildContext context) {
@@ -4,10 +4,16 @@ import 'package:stream_chat_flutter/src/attachment/attachment_widget.dart';
import 'package:stream_chat_flutter/src/video_thumbnail_image.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro video_attachment}
@Deprecated("Use 'StreamVideoAttachment' instead")
typedef VideoAttachment = StreamVideoAttachment;
/// {@template video_attachment}
/// Widget for showing a video attachment
class VideoAttachment extends AttachmentWidget {
/// Constructor for creating a [VideoAttachment] widget
const VideoAttachment({
/// {@endtemplate}
class StreamVideoAttachment extends StreamAttachmentWidget {
/// Constructor for creating a [StreamVideoAttachment] widget
const StreamVideoAttachment({
Key? key,
required Message message,
required Attachment attachment,
@@ -23,8 +29,8 @@ class VideoAttachment extends AttachmentWidget {
size: size,
);
/// [MessageThemeData] for showing title
final MessageThemeData messageTheme;
/// [StreamMessageThemeData] for showing title
final StreamMessageThemeData messageTheme;
/// Callback when show message is tapped
final ShowMessageCallback? onShowMessage;
@@ -43,7 +49,7 @@ class VideoAttachment extends AttachmentWidget {
}
return _buildVideoAttachment(
context,
VideoThumbnailImage(
StreamVideoThumbnailImage(
video: attachment.file!.path!,
height: size?.height,
width: size?.width,
@@ -58,7 +64,7 @@ class VideoAttachment extends AttachmentWidget {
}
return _buildVideoAttachment(
context,
VideoThumbnailImage(
StreamVideoThumbnailImage(
video: attachment.assetUrl!,
height: size?.height,
width: size?.width,
@@ -84,7 +90,7 @@ class VideoAttachment extends AttachmentWidget {
MaterialPageRoute(
builder: (_) => StreamChannel(
channel: channel,
child: FullScreenMedia(
child: StreamFullScreenMedia(
mediaAttachments: message.attachments,
startIndex:
message.attachments.indexOf(attachment),
@@ -111,7 +117,7 @@ class VideoAttachment extends AttachmentWidget {
),
Padding(
padding: const EdgeInsets.all(8),
child: AttachmentUploadStateBuilder(
child: StreamAttachmentUploadStateBuilder(
message: message,
attachment: attachment,
),
@@ -123,7 +129,7 @@ class VideoAttachment extends AttachmentWidget {
if (attachment.title != null)
Material(
color: messageTheme.messageBackgroundColor,
child: AttachmentTitle(
child: StreamAttachmentTitle(
messageTheme: messageTheme,
attachment: attachment,
),
@@ -58,7 +58,7 @@ class AttachmentActionsModal extends StatelessWidget {
/// List of custom actions
final List<AttachmentAction> customActions;
/// Creates a copy of [MessageWidget] with specified attributes overridden.
/// Creates a copy of [StreamMessageWidget] with specified attributes overridden.
AttachmentActionsModal copyWith({
Key? key,
int? currentIndex,
@@ -50,7 +50,7 @@ class StreamBackButton extends StatelessWidget {
Positioned(
top: 7,
right: 7,
child: UnreadIndicator(
child: StreamUnreadIndicator(
cid: cid,
),
),
@@ -152,7 +152,7 @@ class ChannelAvatar extends StatelessWidget {
return BetterStreamBuilder<User>(
stream: streamChat.client.state.currentUserStream.map((it) => it!),
initialData: currentUser,
builder: (context, user) => UserAvatar(
builder: (context, user) => StreamUserAvatar(
borderRadius: borderRadius ?? previewTheme?.borderRadius,
user: user,
constraints: constraints ?? previewTheme?.constraints,
@@ -175,7 +175,7 @@ class ChannelAvatar extends StatelessWidget {
),
),
initialData: member,
builder: (context, member) => UserAvatar(
builder: (context, member) => StreamUserAvatar(
borderRadius: borderRadius ?? previewTheme?.borderRadius,
user: member.user!,
constraints: constraints ?? previewTheme?.constraints,
@@ -188,7 +188,7 @@ class ChannelAvatar extends StatelessWidget {
}
// Group conversation
return GroupAvatar(
return StreamGroupAvatar(
members: otherMembers,
borderRadius: borderRadius ?? previewTheme?.borderRadius,
constraints: constraints ?? previewTheme?.constraints,
@@ -4,10 +4,7 @@ import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// Bottom Sheet with options
@Deprecated(
"'ChannelBottomSheet' is deprecated and shouldn't be used. "
"Please use 'StreamChannelBottomSheet' instead.",
)
@Deprecated("Use 'StreamChannelInfoBottomSheet' instead")
class ChannelBottomSheet extends StatefulWidget {
/// Constructor for creating bottom sheet
const ChannelBottomSheet({Key? key, this.onViewInfoTap}) : super(key: key);
@@ -24,7 +21,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
bool _showActions = true;
late StreamChannelState _streamChannelState;
late ChannelPreviewThemeData _channelPreviewThemeData;
late StreamChannelPreviewThemeData _channelPreviewThemeData;
late StreamChatThemeData _streamChatThemeData;
late StreamChatState _streamChatState;
@@ -58,7 +55,8 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: ChannelName(
child: StreamChannelName(
channel: channel,
textStyle: _streamChatThemeData.textTheme.headlineBold,
),
),
@@ -67,7 +65,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
height: 5,
),
Center(
child: ChannelInfo(
child: StreamChannelInfo(
showTypingIndicator: false,
channel: _streamChannelState.channel,
textStyle: _channelPreviewThemeData.subtitleStyle,
@@ -79,7 +77,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
if (channel.isDistinct && channel.memberCount == 2)
Column(
children: [
UserAvatar(
StreamUserAvatar(
user: members
.firstWhere(
(e) => e.user?.id != userAsMember.user?.id,
@@ -122,7 +120,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Column(
children: [
UserAvatar(
StreamUserAvatar(
user: members[index].user!,
constraints: const BoxConstraints.tightFor(
height: 64,
@@ -150,7 +148,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
const SizedBox(
height: 24,
),
OptionListTile(
StreamOptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.user(
@@ -163,7 +161,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
if (!channel.isDistinct &&
channel.ownCapabilities
.contains(PermissionType.leaveChannel))
OptionListTile(
StreamOptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.userRemove(
@@ -184,7 +182,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
if (isOwner &&
channel.ownCapabilities
.contains(PermissionType.deleteChannel))
OptionListTile(
StreamOptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.delete(
@@ -203,7 +201,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
});
},
),
OptionListTile(
StreamOptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.closeSmall(
@@ -224,7 +222,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
void didChangeDependencies() {
_streamChannelState = StreamChannel.of(context);
_streamChatThemeData = StreamChatTheme.of(context);
_channelPreviewThemeData = ChannelPreviewTheme.of(context);
_channelPreviewThemeData = StreamChannelPreviewTheme.of(context);
_streamChatState = StreamChat.of(context);
super.didChangeDependencies();
}
@@ -4,6 +4,11 @@ import 'package:stream_chat_flutter/src/channel_info.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
///{@macro template_name}
@Deprecated("Use 'StreamChannelHeader' instead")
typedef ChannelHeader = StreamChannelHeader;
/// {@template channel_header}
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/channel_header.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/channel_header_paint.png)
///
@@ -49,9 +54,11 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// The widget components render the ui based on the first ancestor of type
/// [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property.
/// Modify it to change the widget appearance.
class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
/// {@endtemplate}
class StreamChannelHeader extends StatelessWidget
implements PreferredSizeWidget {
/// Creates a channel header
const ChannelHeader({
const StreamChannelHeader({
Key? key,
this.showBackButton = true,
this.onBackPressed,
@@ -96,16 +103,16 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
final Widget? leading;
/// AppBar actions
/// By default it shows the [ChannelAvatar]
/// By default it shows the [StreamChannelAvatar]
final List<Widget>? actions;
/// The background color for this [ChannelHeader].
/// The background color for this [StreamChannelHeader].
final Color? backgroundColor;
@override
Widget build(BuildContext context) {
final channel = StreamChannel.of(context).channel;
final channelHeaderTheme = ChannelHeaderTheme.of(context);
final channelHeaderTheme = StreamChannelHeaderTheme.of(context);
final leadingWidget = leading ??
(showBackButton
@@ -115,7 +122,7 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
)
: const SizedBox());
return ConnectionStatusBuilder(
return StreamConnectionStatusBuilder(
statusBuilder: (context, status) {
var statusString = '';
var showStatus = true;
@@ -135,7 +142,7 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
final theme = Theme.of(context);
return InfoTile(
return StreamInfoTile(
showMessage: showConnectionStateTile && showStatus,
message: statusString,
child: AppBar(
@@ -152,7 +159,8 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
Padding(
padding: const EdgeInsets.only(right: 10),
child: Center(
child: ChannelAvatar(
child: StreamChannelAvatar(
channel: channel,
borderRadius:
channelHeaderTheme.avatarTheme?.borderRadius,
constraints:
@@ -172,12 +180,13 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
title ??
ChannelName(
StreamChannelName(
channel: channel,
textStyle: channelHeaderTheme.titleStyle,
),
const SizedBox(height: 2),
subtitle ??
ChannelInfo(
StreamChannelInfo(
showTypingIndicator: showTypingIndicator,
channel: channel,
textStyle: channelHeaderTheme.subtitleStyle,
@@ -3,10 +3,16 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro channel_info}
@Deprecated("Use 'StreamChannelInfo' instead")
typedef ChannelInfo = StreamChannelInfo;
/// {@template channel_info}
/// Widget which shows channel info
class ChannelInfo extends StatelessWidget {
/// Constructor which creates a [ChannelInfo] widget
const ChannelInfo({
/// {@endtemplate}
class StreamChannelInfo extends StatelessWidget {
/// Constructor which creates a [StreamChannelInfo] widget
const StreamChannelInfo({
Key? key,
required this.channel,
this.textStyle,
@@ -32,7 +38,7 @@ class ChannelInfo extends StatelessWidget {
return BetterStreamBuilder<List<Member>>(
stream: channel.state!.membersStream,
initialData: channel.state!.members,
builder: (context, data) => ConnectionStatusBuilder(
builder: (context, data) => StreamConnectionStatusBuilder(
statusBuilder: (context, status) {
switch (status) {
case ConnectionStatus.connected:
@@ -66,7 +72,7 @@ class ChannelInfo extends StatelessWidget {
}
alternativeWidget = Text(
text,
style: ChannelHeaderTheme.of(context).subtitleStyle,
style: StreamChannelHeaderTheme.of(context).subtitleStyle,
);
} else {
final userId = StreamChat.of(context).currentUser?.id;
@@ -95,7 +101,7 @@ class ChannelInfo extends StatelessWidget {
}
return Align(
child: TypingIndicator(
child: StreamTypingIndicator(
parentId: parentId,
style: textStyle,
alternativeWidget: alternativeWidget,
@@ -11,7 +11,11 @@ typedef TitleBuilder = Widget Function(
StreamChatClient client,
);
///
/// {@macro channel_list_header}
@Deprecated("Use 'StreamChannelListHeader' instead")
typedef ChannelListHeader = StreamChannelListHeader;
/// {@template channel_list_header}
/// It shows the current [StreamChatClient] status.
///
/// ```dart
@@ -43,11 +47,13 @@ typedef TitleBuilder = Widget Function(
/// if you don't have it in the widget tree.
///
/// The widget components render the ui based on the first ancestor of type
/// [StreamChatTheme] and on its [ChannelListHeaderThemeData] property.
/// [StreamChatTheme] and on its [StreamChannelListHeaderThemeData] property.
/// Modify it to change the widget appearance.
class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget {
/// {@endtemplate}
class StreamChannelListHeader extends StatelessWidget
implements PreferredSizeWidget {
/// Instantiates a ChannelListHeader
const ChannelListHeader({
const StreamChannelListHeader({
Key? key,
this.client,
this.titleBuilder,
@@ -91,14 +97,14 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget {
/// By default it shows the new chat button
final List<Widget>? actions;
/// The background color for this [ChannelListHeader].
/// The background color for this [StreamChannelListHeader].
final Color? backgroundColor;
@override
Widget build(BuildContext context) {
final _client = client ?? StreamChat.of(context).client;
final user = _client.state.currentUser;
return ConnectionStatusBuilder(
return StreamConnectionStatusBuilder(
statusBuilder: (context, status) {
var statusString = '';
var showStatus = true;
@@ -117,9 +123,10 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget {
}
final chatThemeData = StreamChatTheme.of(context);
final channelListHeaderThemeData = ChannelListHeaderTheme.of(context);
final channelListHeaderThemeData =
StreamChannelListHeaderTheme.of(context);
final theme = Theme.of(context);
return InfoTile(
return StreamInfoTile(
showMessage: showConnectionStateTile && showStatus,
message: statusString,
child: AppBar(
@@ -135,7 +142,7 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget {
leading: leading ??
Center(
child: user != null
? UserAvatar(
? StreamUserAvatar(
user: user,
showOnlineStatus: false,
onTap: onUserAvatarTap ??
@@ -156,7 +163,7 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget {
[
StreamNeumorphicButton(
child: IconButton(
icon: ConnectionStatusBuilder(
icon: StreamConnectionStatusBuilder(
statusBuilder: (context, status) {
Color? color;
switch (status) {
@@ -234,10 +241,11 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget {
const SizedBox(width: 10),
Text(
context.translations.searchingForNetworkText,
style: ChannelListHeaderTheme.of(context).titleStyle?.copyWith(
fontSize: 16,
fontWeight: FontWeight.bold,
),
style:
StreamChannelListHeaderTheme.of(context).titleStyle?.copyWith(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
);
@@ -247,7 +255,7 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget {
StreamChatClient client,
) {
final chatThemeData = StreamChatTheme.of(context);
final channelListHeaderTheme = ChannelListHeaderTheme.of(context);
final channelListHeaderTheme = StreamChannelListHeaderTheme.of(context);
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:shimmer/shimmer.dart';
import 'package:stream_chat_flutter/src/channel_bottom_sheet.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
@@ -11,7 +10,7 @@ typedef ChannelTapCallback = void Function(Channel, Widget?);
/// Callback called when tapping on a channel
typedef ChannelInfoCallback = void Function(Channel);
/// Builder used to create a custom [ChannelPreview] from a [Channel]
/// Builder used to create a custom [StreamChannelPreview] from a [Channel]
typedef ChannelPreviewBuilder = Widget Function(BuildContext, Channel);
/// Callback for when 'View Info' is tapped
@@ -52,10 +51,7 @@ typedef ViewInfoCallback = void Function(Channel);
/// The widget components render the ui based on the first ancestor of
/// type [StreamChatTheme].
/// Modify it to change the widget appearance.
@Deprecated(
"'ChannelListView' is deprecated and shouldn't be used. "
"Please use 'StreamChannelListView' instead.",
)
@Deprecated("Use 'StreamChannelListView' instead")
class ChannelListView extends StatefulWidget {
/// Instantiate a new ChannelListView
ChannelListView({
@@ -248,7 +244,8 @@ class _ChannelListViewState extends State<ChannelListView> {
child: child,
);
final backgroundColor = ChannelListViewTheme.of(context).backgroundColor;
final backgroundColor =
StreamChannelListViewTheme.of(context).backgroundColor;
if (backgroundColor != null) {
return ColoredBox(
@@ -550,7 +547,8 @@ class _ChannelListViewState extends State<ChannelListView> {
context: context,
builder: (context) => StreamChannel(
channel: channel,
child: ChannelBottomSheet(
child: StreamChannelInfoBottomSheet(
channel: channel,
onViewInfoTap: () {
widget.onViewInfoTap?.call(channel);
},
@@ -639,7 +637,7 @@ class _ChannelListViewState extends State<ChannelListView> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ChannelAvatar(
StreamChannelAvatar(
channel: channel,
borderRadius: BorderRadius.circular(32),
selected: selected,
@@ -654,8 +652,9 @@ class _ChannelListViewState extends State<ChannelListView> {
padding: const EdgeInsets.symmetric(horizontal: 8),
child: StreamChannel(
channel: channel,
child: const ChannelName(
textStyle: TextStyle(
child: StreamChannelName(
channel: channel,
textStyle: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
),
@@ -6,10 +6,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
///
/// The widget uses a [StreamBuilder] to render the channel information
/// image as soon as it updates.
@Deprecated(
"'ChannelName' is deprecated and shouldn't be used. "
"Please use 'StreamChannelName' instead.",
)
@Deprecated("Use 'StreamChannelName' instead")
class ChannelName extends StatelessWidget {
/// Instantiate a new ChannelName
const ChannelName({
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@template channel_preview}
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/channel_preview.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/channel_preview_paint.png)
///
@@ -13,11 +14,13 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// image as soon as it updates.
///
/// Usually you don't use this widget as it's the default channel preview
/// used by [ChannelListView].
/// used by [StreamChannelListView].
///
/// The widget renders the ui based on the first ancestor of type
/// [StreamChatTheme].
/// Modify it to change the widget appearance.
/// {@endtemplate}
@Deprecated("Use 'StreamChannelListTile' instead")
class ChannelPreview extends StatelessWidget {
/// Constructor for creating [ChannelPreview]
const ChannelPreview({
@@ -52,7 +55,7 @@ class ChannelPreview extends StatelessWidget {
final Widget? subtitle;
/// Widget rendering the leading element, by default
/// it shows the [ChannelAvatar]
/// it shows the [StreamChannelAvatar]
final Widget? leading;
/// Widget rendering the trailing element,
@@ -60,7 +63,7 @@ class ChannelPreview extends StatelessWidget {
final Widget? trailing;
/// Widget rendering the sending indicator,
/// by default it uses the [SendingIndicator] widget
/// by default it uses the [StreamSendingIndicator] widget
final Widget? sendingIndicator;
@override
@@ -80,13 +83,18 @@ class ChannelPreview extends StatelessWidget {
),
onTap: () => onTap?.call(channel),
onLongPress: () => onLongPress?.call(channel),
leading: leading ?? ChannelAvatar(onTap: onImageTap),
leading: leading ??
StreamChannelAvatar(
channel: channel,
onTap: onImageTap,
),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: title ??
ChannelName(
StreamChannelName(
channel: channel,
textStyle: channelPreviewTheme.titleStyle,
),
),
@@ -100,7 +108,7 @@ class ChannelPreview extends StatelessWidget {
e.user!.id == channel.client.state.currentUser?.id)) {
return const SizedBox();
}
return UnreadIndicator(
return StreamUnreadIndicator(
cid: channel.cid,
);
},
@@ -136,7 +144,7 @@ class ChannelPreview extends StatelessWidget {
)));
final isMessageRead = readList.length >=
(channel.memberCount ?? 0) - 1;
return SendingIndicator(
return StreamSendingIndicator(
message: lastMessage!,
size: channelPreviewTheme.indicatorIconSize,
isMessageRead: isMessageRead,
@@ -204,7 +212,7 @@ class ChannelPreview extends StatelessWidget {
],
);
}
return TypingIndicator(
return StreamTypingIndicator(
channel: channel,
alternativeWidget: _buildLastMessage(context),
style: channelPreviewTheme.subtitleStyle,
@@ -2,10 +2,17 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro commands_overlay}
@Deprecated("Use 'StreamCommandsOverlay' instead")
typedef CommandsOverlay = StreamCommandsOverlay;
/// {@template commands_overlay}
/// Overlay for displaying commands that can be used
class CommandsOverlay extends StatelessWidget {
/// Constructor for creating a [CommandsOverlay]
const CommandsOverlay({
/// to interact with the channel.
/// {@endtemplate}
class StreamCommandsOverlay extends StatelessWidget {
/// Constructor for creating a [StreamCommandsOverlay]
const StreamCommandsOverlay({
required this.text,
required this.onCommandResult,
required this.size,
@@ -1,14 +1,20 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro connection_status_builder}
@Deprecated("Use 'StreamConnectionStatusBuilder' instead")
typedef ConnectionStatusBuilder = StreamConnectionStatusBuilder;
/// {@template connection_status_builder}
/// Widget that builds itself based on the latest snapshot of interaction with
/// a [Stream] of type [ConnectionStatus].
///
/// The widget will use the closest [StreamChatClient.wsConnectionStatusStream]
/// in case no stream is provided.
class ConnectionStatusBuilder extends StatelessWidget {
/// {@endtemplate}
class StreamConnectionStatusBuilder extends StatelessWidget {
/// Creates a new ConnectionStatusBuilder
const ConnectionStatusBuilder({
const StreamConnectionStatusBuilder({
Key? key,
required this.statusBuilder,
this.connectionStatusStream,
@@ -3,10 +3,16 @@ import 'package:jiffy/jiffy.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro date_divider}
@Deprecated("Use 'StreamDateDivider' instead")
typedef DateDivider = StreamDateDivider;
/// {@template date_divider}
/// It shows a date divider depending on the date difference
class DateDivider extends StatelessWidget {
/// Constructor for creating a [DateDivider]
const DateDivider({
/// {@endtemplate}
class StreamDateDivider extends StatelessWidget {
/// Constructor for creating a [StreamDateDivider]
const StreamDateDivider({
Key? key,
required this.dateTime,
this.uppercase = false,
@@ -3,10 +3,16 @@ import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
import 'package:stream_chat_flutter/src/theme/themes.dart';
/// Widget to display deleted message
class DeletedMessage extends StatelessWidget {
/// Constructor to create [DeletedMessage]
const DeletedMessage({
/// {@macro deleted_message}
@Deprecated("Use 'StreamDeletedMessage' instead")
typedef DeletedMessage = StreamDeletedMessage;
/// {@template deleted_message}
/// Widget to display deleted message.
/// {@endtemplate}
class StreamDeletedMessage extends StatelessWidget {
/// Constructor to create [StreamDeletedMessage]
const StreamDeletedMessage({
Key? key,
required this.messageTheme,
this.borderRadiusGeometry,
@@ -16,7 +22,7 @@ class DeletedMessage extends StatelessWidget {
}) : super(key: key);
/// The theme of the message
final MessageThemeData messageTheme;
final StreamMessageThemeData messageTheme;
/// The border radius of the message text
final BorderRadiusGeometry? borderRadiusGeometry;
@@ -4,10 +4,16 @@ import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:substring_highlight/substring_highlight.dart';
/// {@macro emoji_overlay}
@Deprecated("Use 'StreamEmojiOverlay' instead")
typedef EmojiOverlay = StreamEmojiOverlay;
/// {@template emoji_overlay}
/// Overlay for displaying emoji that can be used
class EmojiOverlay extends StatelessWidget {
/// Constructor for creating a [EmojiOverlay]
const EmojiOverlay({
/// {@endtemplate}
class StreamEmojiOverlay extends StatelessWidget {
/// Constructor for creating a [StreamEmojiOverlay]
const StreamEmojiOverlay({
required this.query,
required this.onEmojiResult,
required this.size,
@@ -225,3 +225,50 @@ extension UserListX on List<User> {
return entries.map((e) => e.key).toList(growable: false);
}
}
/// Extensions on Message
extension MessageX on Message {
/// It replaces the user mentions with the actual user names.
Message replaceMentions({bool linkify = true}) {
var messageTextToRender = text;
for (final user in mentionedUsers.toSet()) {
final userId = user.id;
final userName = user.name;
if (linkify) {
messageTextToRender = messageTextToRender?.replaceAll(
'@$userId',
'[@$userName](@${userName.replaceAll(' ', '')})',
);
} else {
messageTextToRender = messageTextToRender?.replaceAll(
'@$userId',
'@$userName',
);
}
}
return copyWith(text: messageTextToRender);
}
/// It returns the message with the translated text if available locally
Message translate(String language) =>
copyWith(text: i18n?['${language}_text'] ?? text);
/// It returns the message replacing the mentioned user names with
/// the respective user ids
Message replaceMentionsWithId() {
if (mentionedUsers.isEmpty) return this;
var messageTextToSend = text;
if (messageTextToSend == null) return this;
for (final user in mentionedUsers.toSet()) {
final userName = user.name;
messageTextToSend = messageTextToSend!.replaceAll(
'@$userName',
'@${user.id}',
);
}
return copyWith(text: messageTextToSend);
}
}
@@ -21,10 +21,16 @@ enum ReturnActionType {
/// Callback when show message is tapped
typedef ShowMessageCallback = void Function(Message message, Channel channel);
/// {@macro full_screen_media}
@Deprecated("Use 'StreamFullScreenMedia' instead")
typedef FullScreenMedia = StreamFullScreenMedia;
/// {@template full_screen_media}
/// A full screen image widget
class FullScreenMedia extends StatefulWidget {
/// {@endtemplate}
class StreamFullScreenMedia extends StatefulWidget {
/// Instantiate a new FullScreenImage
const FullScreenMedia({
const StreamFullScreenMedia({
Key? key,
required this.mediaAttachments,
required this.message,
@@ -60,10 +66,10 @@ class FullScreenMedia extends StatefulWidget {
final bool autoplayVideos;
@override
_FullScreenMediaState createState() => _FullScreenMediaState();
_StreamFullScreenMediaState createState() => _StreamFullScreenMediaState();
}
class _FullScreenMediaState extends State<FullScreenMedia>
class _StreamFullScreenMediaState extends State<StreamFullScreenMedia>
with SingleTickerProviderStateMixin {
late final AnimationController _animationController;
late final PageController _pageController;
@@ -172,7 +178,7 @@ class _FullScreenMediaState extends State<FullScreenMedia>
),
backgroundDecoration: BoxDecoration(
color: ColorTween(
begin: ChannelHeaderTheme.of(context).color,
begin: StreamChannelHeaderTheme.of(context).color,
end: Colors.black,
).lerp(_curvedAnimation.value),
),
@@ -221,7 +227,7 @@ class _FullScreenMediaState extends State<FullScreenMedia>
builder: (context, value, child) => Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GalleryHeader(
StreamGalleryHeader(
userName: widget.userName,
sentAt: context.translations.sentAtText(
date: widget.message.createdAt,
@@ -242,7 +248,7 @@ class _FullScreenMediaState extends State<FullScreenMedia>
widget.attachmentActionsModalBuilder,
),
if (!widget.message.isEphemeral)
GalleryFooter(
StreamGalleryFooter(
currentPage: value,
totalPages: widget.mediaAttachments.length,
mediaAttachments: widget.mediaAttachments,
@@ -9,10 +9,17 @@ import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/src/video_thumbnail_image.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro gallery_footer}
@Deprecated("Use 'StreamGalleryFooter' instead")
typedef GalleryFooter = StreamGalleryFooter;
/// {@template gallery_footer}
/// Footer widget for media display
class GalleryFooter extends StatefulWidget implements PreferredSizeWidget {
/// {@endtemplate}
class StreamGalleryFooter extends StatefulWidget
implements PreferredSizeWidget {
/// Creates a channel header
const GalleryFooter({
const StreamGalleryFooter({
Key? key,
required this.message,
this.onBackPressed,
@@ -51,22 +58,22 @@ class GalleryFooter extends StatefulWidget implements PreferredSizeWidget {
/// Callback when media is selected
final ValueChanged<int>? mediaSelectedCallBack;
/// The background color of this [GalleryFooter].
/// The background color of this [StreamGalleryFooter].
final Color? backgroundColor;
@override
_GalleryFooterState createState() => _GalleryFooterState();
_StreamGalleryFooterState createState() => _StreamGalleryFooterState();
@override
final Size preferredSize;
}
class _GalleryFooterState extends State<GalleryFooter> {
class _StreamGalleryFooterState extends State<StreamGalleryFooter> {
@override
Widget build(BuildContext context) {
const showShareButton = !kIsWeb;
final mediaQueryData = MediaQuery.of(context);
final galleryFooterThemeData = GalleryFooterTheme.of(context);
final galleryFooterThemeData = StreamGalleryFooterTheme.of(context);
return SizedBox.fromSize(
size: Size(
mediaQueryData.size.width,
@@ -149,7 +156,7 @@ class _GalleryFooterState extends State<GalleryFooter> {
void _showPhotosModal(context) {
final chatThemeData = StreamChatTheme.of(context);
final galleryFooterThemeData = GalleryFooterTheme.of(context);
final galleryFooterThemeData = StreamGalleryFooterTheme.of(context);
showModalBottomSheet(
context: context,
barrierColor: galleryFooterThemeData.bottomSheetBarrierColor,
@@ -222,7 +229,7 @@ class _GalleryFooterState extends State<GalleryFooter> {
onTap: () => widget.mediaSelectedCallBack!(index),
child: FittedBox(
fit: BoxFit.cover,
child: VideoThumbnailImage(
child: StreamVideoThumbnailImage(
video: (attachment.file?.path ??
attachment.assetUrl)!,
),
@@ -264,7 +271,7 @@ class _GalleryFooterState extends State<GalleryFooter> {
),
],
),
child: UserAvatar(
child: StreamUserAvatar(
user: widget.message.user!,
constraints:
BoxConstraints.tight(const Size(24, 24)),
@@ -15,10 +15,17 @@ typedef AttachmentActionsBuilder = Widget Function(
AttachmentActionsModal defaultActionsModal,
);
/// {@macro gallery_header}
@Deprecated("Use 'StreamGalleryHeader' instead")
typedef GalleryHeader = StreamGalleryHeader;
/// {@template gallery_header}
/// Header/AppBar widget for media display screen
class GalleryHeader extends StatelessWidget implements PreferredSizeWidget {
/// {@endtemplate}
class StreamGalleryHeader extends StatelessWidget
implements PreferredSizeWidget {
/// Creates a channel header
const GalleryHeader({
const StreamGalleryHeader({
Key? key,
required this.message,
this.currentIndex = 0,
@@ -62,7 +69,7 @@ class GalleryHeader extends StatelessWidget implements PreferredSizeWidget {
/// Stores the current index of media shown
final int currentIndex;
/// The background color of this [GalleryHeader].
/// The background color of this [StreamGalleryHeader].
final Color? backgroundColor;
/// Widget builder for attachment actions modal
@@ -72,7 +79,7 @@ class GalleryHeader extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
final galleryHeaderThemeData = GalleryHeaderTheme.of(context);
final galleryHeaderThemeData = StreamGalleryHeaderTheme.of(context);
final theme = Theme.of(context);
return AppBar(
toolbarTextStyle: theme.textTheme.bodyText2,
@@ -3,10 +3,16 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart';
/// {@macro gradient_avatar}
@Deprecated("Use 'StreamGradientAvatar' instead")
typedef GradientAvatar = StreamGradientAvatar;
/// {@template gradient_avatar}
/// Fallback user avatar with a polygon gradient overlayed with text
class GradientAvatar extends StatefulWidget {
/// Constructor for [GradientAvatar]
const GradientAvatar({
/// {@endtemplate}
class StreamGradientAvatar extends StatefulWidget {
/// Constructor for [StreamGradientAvatar]
const StreamGradientAvatar({
Key? key,
required this.name,
required this.userId,
@@ -19,10 +25,10 @@ class GradientAvatar extends StatefulWidget {
final String userId;
@override
_GradientAvatarState createState() => _GradientAvatarState();
_StreamGradientAvatarState createState() => _StreamGradientAvatarState();
}
class _GradientAvatarState extends State<GradientAvatar> {
class _StreamGradientAvatarState extends State<StreamGradientAvatar> {
@override
Widget build(BuildContext context) => Center(
child: RepaintBoundary(
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro group_avatar}
@Deprecated("Use 'StreamGroupAvatar' instead")
typedef GroupAvatar = StreamGroupAvatar;
/// {@template group_avatar}
/// Widget for constructing a group of images
class GroupAvatar extends StatelessWidget {
/// Constructor for creating a [GroupAvatar]
const GroupAvatar({
/// {@endtemplate}
class StreamGroupAvatar extends StatelessWidget {
/// Constructor for creating a [StreamGroupAvatar]
const StreamGroupAvatar({
Key? key,
this.channel,
required this.members,
@@ -84,7 +90,7 @@ class GroupAvatar extends StatelessWidget {
),
),
initialData: member,
builder: (context, member) => UserAvatar(
builder: (context, member) => StreamUserAvatar(
showOnlineStatus: false,
user: member.user!,
borderRadius: BorderRadius.zero,
@@ -122,7 +128,8 @@ class GroupAvatar extends StatelessWidget {
),
),
initialData: member,
builder: (context, member) => UserAvatar(
builder: (context, member) =>
StreamUserAvatar(
showOnlineStatus: false,
user: member.user!,
borderRadius: BorderRadius.zero,
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro image_group}
@Deprecated("Use 'StreamImageGroup' instead")
typedef ImageGroup = StreamImageGroup;
/// {@template image_group}
/// Widget for constructing a group of images in message
class ImageGroup extends StatelessWidget {
/// Constructor for creating [ImageGroup] widget
const ImageGroup({
/// {@endtemplate}
class StreamImageGroup extends StatelessWidget {
/// Constructor for creating [StreamImageGroup] widget
const StreamImageGroup({
Key? key,
required this.images,
required this.message,
@@ -27,8 +33,8 @@ class ImageGroup extends StatelessWidget {
/// Message which images are attached to
final Message message;
/// [MessageThemeData] to apply to message
final MessageThemeData messageTheme;
/// [StreamMessageThemeData] to apply to message
final StreamMessageThemeData messageTheme;
/// Size of iamges
final Size size;
@@ -129,7 +135,7 @@ class ImageGroup extends StatelessWidget {
MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: FullScreenMedia(
child: StreamFullScreenMedia(
mediaAttachments: images,
startIndex: index,
userName: message.user?.name,
@@ -142,7 +148,7 @@ class ImageGroup extends StatelessWidget {
if (res != null) onReturnAction?.call(res);
}
Widget _buildImage(BuildContext context, int index) => ImageAttachment(
Widget _buildImage(BuildContext context, int index) => StreamImageAttachment(
attachment: images[index],
size: size,
message: message,
@@ -2,10 +2,16 @@ import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro info_tile}
@Deprecated("Use 'StreamInfoTile' instead")
typedef InfoTile = StreamInfoTile;
/// {@template info_tile}
/// Tile to display a message, used in stream chat to display connection status
class InfoTile extends StatelessWidget {
/// Constructor for creating an [InfoTile] widget
const InfoTile({
/// {@endtemplate}
class StreamInfoTile extends StatelessWidget {
/// Constructor for creating an [StreamInfoTile] widget
const StreamInfoTile({
Key? key,
required this.message,
required this.child,
@@ -59,7 +59,7 @@ abstract class Translations {
/// The error shown when loading messages fails
String get loadingMessagesError;
/// The text for showing the result count in [MessageSearchListView]
/// The text for showing the result count in [StreamMessageSearchListView]
String resultCountText(int count);
/// The text for showing the message is deleted
@@ -74,20 +74,20 @@ abstract class Translations {
/// The text for showing there are no chats
String get emptyChatMessagesText;
/// The text for showing the thread separator in case [MessageListView]
/// The text for showing the thread separator in case [StreamMessageListView]
/// contains a parent message
String threadSeparatorText(int replyCount);
/// The label for "connected" in [ConnectionStatusBuilder]
/// The label for "connected" in [StreamConnectionStatusBuilder]
String get connectedLabel;
/// The label for "disconnected" in [ConnectionStatusBuilder]
/// The label for "disconnected" in [StreamConnectionStatusBuilder]
String get disconnectedLabel;
/// The label for "reconnecting" in [ConnectionStatusBuilder]
/// The label for "reconnecting" in [StreamConnectionStatusBuilder]
String get reconnectingLabel;
/// The label for also send as direct message "checkbox"" in [MessageInput]
/// The label for also send as direct message "checkbox"" in [StreamMessageInput]
String get alsoSendAsDirectMessageLabel;
/// The label for search Gif
@@ -97,24 +97,24 @@ abstract class Translations {
String get sendMessagePermissionError;
/// The label for add a comment or send in case of
/// attachments inside [MessageInput]
/// attachments inside [StreamMessageInput]
String get addACommentOrSendLabel;
/// The label for write a message in [MessageInput]
/// The label for write a message in [StreamMessageInput]
String get writeAMessageLabel;
/// The label for slow mode enabled in [MessageInput]
/// The label for slow mode enabled in [StreamMessageInput]
String get slowModeOnLabel;
/// The label for instant commands in [MessageInput]
/// The label for instant commands in [StreamMessageInput]
String get instantCommandsLabel;
/// The error shown in case the fi"le is too large even after compression
/// while uploading via [MessageInput]
/// while uploading via [StreamMessageInput]
String fileTooLargeAfterCompressionError(double limitInMB);
/// The error shown in case the file is too large
/// while uploading via [MessageInput]
/// while uploading via [StreamMessageInput]
String fileTooLargeError(double limitInMB);
/// The text for showing the query while searching for emojis
@@ -7,21 +7,16 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
extension on Duration {
String format() {
final s = '$this'.split('.')[0].padLeft(8, '0');
if (s.startsWith('00:')) {
return s.replaceFirst('00:', '');
}
return s;
}
}
/// {@macro media_list_view}
@Deprecated("Use 'StreamMediaListView' instead")
typedef MediaListView = StreamMediaListView;
/// {@template media_list_view}
/// Constructs a list of media
class MediaListView extends StatefulWidget {
/// Constructor for creating a [MediaListView] widget
const MediaListView({
/// {@endtemplate}
class StreamMediaListView extends StatefulWidget {
/// Constructor for creating a [StreamMediaListView] widget
const StreamMediaListView({
Key? key,
this.selectedIds = const [],
this.onSelect,
@@ -34,10 +29,10 @@ class MediaListView extends StatefulWidget {
final void Function(AssetEntity media)? onSelect;
@override
_MediaListViewState createState() => _MediaListViewState();
_StreamMediaListViewState createState() => _StreamMediaListViewState();
}
class _MediaListViewState extends State<MediaListView> {
class _StreamMediaListViewState extends State<StreamMediaListView> {
final _media = <AssetEntity>[];
final ScrollController _scrollController = ScrollController();
int _currentPage = 0;
@@ -158,7 +153,10 @@ class _MediaListViewState extends State<MediaListView> {
))
.firstOrNull;
final media = await assetList?.getAssetListPaged(_currentPage, 50);
final media = await assetList?.getAssetListPaged(
page: _currentPage,
size: 50,
);
if (media?.isNotEmpty == true) {
setState(() {
@@ -197,7 +195,7 @@ class MediaThumbnailProvider extends ImageProvider<MediaThumbnailProvider> {
DecoderCallback decode,
) async {
assert(key == this, 'Checks MediaThumbnailProvider');
final bytes = await media.thumbData;
final bytes = await media.thumbnailData;
return decode(bytes!);
}
@@ -219,3 +217,14 @@ class MediaThumbnailProvider extends ImageProvider<MediaThumbnailProvider> {
@override
String toString() => '$runtimeType("${media.id}")';
}
extension on Duration {
String format() {
final s = '$this'.split('.')[0].padLeft(8, '0');
if (s.startsWith('00:')) {
return s.replaceFirst('00:', '');
}
return s;
}
}
@@ -1,101 +0,0 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// This widget is used for showing user tiles for mentions
/// Use [title], [subtitle], [leading], [trailing] for
/// substituting widgets in respective positions
@Deprecated('Use `UserMentionTile` instead. Will be removed in future release')
class MentionTile extends StatelessWidget {
/// Constructor for creating a [MentionTile] widget
const MentionTile(
this.member, {
Key? key,
this.title,
this.subtitle,
this.leading,
this.trailing,
}) : super(key: key);
/// Member to display in the tile
final Member member;
/// Widget to display as title
final Widget? title;
/// Widget to display below [title]
final Widget? subtitle;
/// Widget at the start of the tile
final Widget? leading;
/// Widget at the end of tile
final Widget? trailing;
@override
Widget build(BuildContext context) {
final chatThemeData = StreamChatTheme.of(context);
return SizedBox(
height: 56,
child: Row(
children: [
const SizedBox(
width: 16,
),
leading ??
UserAvatar(
constraints: BoxConstraints.tight(
const Size(
40,
40,
),
),
user: member.user!,
),
const SizedBox(
width: 8,
),
Expanded(
child: Align(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
title ??
Text(
member.user!.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: chatThemeData.textTheme.bodyBold,
),
const SizedBox(
height: 2,
),
subtitle ??
Text(
'@${member.userId}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: chatThemeData.textTheme.footnoteBold.copyWith(
color: chatThemeData.colorTheme.textLowEmphasis,
),
),
],
),
),
),
trailing ??
Padding(
padding: const EdgeInsets.only(
right: 18,
left: 8,
),
child: StreamSvgIcon.mentions(
color: chatThemeData.colorTheme.accentPrimary,
),
),
],
),
);
}
}
@@ -1,10 +1,16 @@
import 'package:flutter/widgets.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro message_action}
@Deprecated("Use 'StreamMessageActions' instead")
typedef MessageAction = StreamMessageAction;
/// {@template message_action}
/// Class describing a message action
class MessageAction {
/// returns a new instance of a [MessageAction]
MessageAction({
/// {@endtemplate}
class StreamMessageAction {
/// returns a new instance of a [StreamMessageAction]
StreamMessageAction({
this.leading,
this.title,
this.onTap,
@@ -3,10 +3,16 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro message_actions_modal}
@Deprecated("Use 'StreamMessageActionsModal' instead")
typedef MessageActionsModal = StreamMessageActionsModal;
/// {@template message_actions_modal}
/// Constructs a modal with actions for a message
class MessageActionsModal extends StatefulWidget {
/// Constructor for creating a [MessageActionsModal] widget
const MessageActionsModal({
/// {@endtemplate}
class StreamMessageActionsModal extends StatefulWidget {
/// Constructor for creating a [StreamMessageActionsModal] widget
const StreamMessageActionsModal({
Key? key,
required this.message,
required this.messageWidget,
@@ -43,8 +49,8 @@ class MessageActionsModal extends StatefulWidget {
/// Message in focus for actions
final Message message;
/// [MessageThemeData] for message
final MessageThemeData messageTheme;
/// [StreamMessageThemeData] for message
final StreamMessageThemeData messageTheme;
/// Flag for showing reactions
final bool? showReactions;
@@ -80,13 +86,14 @@ class MessageActionsModal extends StatefulWidget {
final bool reverse;
/// List of custom actions
final List<MessageAction> customActions;
final List<StreamMessageAction> customActions;
@override
_MessageActionsModalState createState() => _MessageActionsModalState();
_StreamMessageActionsModalState createState() =>
_StreamMessageActionsModalState();
}
class _MessageActionsModalState extends State<MessageActionsModal> {
class _StreamMessageActionsModalState extends State<StreamMessageActionsModal> {
bool _showActions = true;
late List<String> _userPermissions;
late bool _isMyMessage;
@@ -159,7 +166,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
: -(1.2 - divFactor)),
0,
),
child: ReactionPicker(
child: StreamReactionPicker(
message: widget.message,
),
),
@@ -268,7 +275,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
InkWell _buildCustomAction(
BuildContext context,
MessageAction messageAction,
StreamMessageAction messageAction,
) =>
InkWell(
onTap: () {
@@ -589,7 +596,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
elevation: 2,
clipBehavior: Clip.hardEdge,
isScrollControlled: true,
backgroundColor: MessageInputTheme.of(context).inputBackgroundColor,
backgroundColor: StreamMessageInputTheme.of(context).inputBackgroundColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
@@ -631,7 +638,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
if (widget.editMessageInputBuilder != null)
widget.editMessageInputBuilder!(context, widget.message)
else
MessageInput(
StreamMessageInput(
messageInputController: MessageInputController(
message: widget.message,
),
File diff suppressed because it is too large Load Diff
@@ -2,9 +2,9 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// Button for showing visual component of slow mode.
class CountdownButton extends StatelessWidget {
/// Constructor for creating [CountdownButton].
const CountdownButton({
class StreamCountdownButton extends StatelessWidget {
/// Constructor for creating [StreamCountdownButton].
const StreamCountdownButton({
Key? key,
required this.count,
}) : super(key: key);
@@ -18,17 +18,13 @@ import 'package:stream_chat_flutter/src/message_input/tld.dart';
import 'package:stream_chat_flutter/src/multi_overlay.dart';
import 'package:stream_chat_flutter/src/quoted_message_widget.dart';
import 'package:stream_chat_flutter/src/user_mentions_overlay.dart';
import 'package:stream_chat_flutter/src/video_service.dart';
import 'package:stream_chat_flutter/src/video_thumbnail_image.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:video_compress/video_compress.dart';
export 'package:video_compress/video_compress.dart' show VideoQuality;
/// A function that returns true if the message is valid and can be sent.
typedef MessageValidator = bool Function(Message message);
/// A callback that can be passed to [MessageInput.onError].
/// A callback that can be passed to [StreamMessageInput.onError].
///
/// This callback should not throw.
///
@@ -38,7 +34,7 @@ typedef ErrorListener = void Function(
StackTrace? stackTrace,
);
/// A callback that can be passed to [MessageInput.onAttachmentLimitExceed].
/// A callback that can be passed to [StreamMessageInput.onAttachmentLimitExceed].
///
/// This callback should not throw.
///
@@ -63,7 +59,7 @@ typedef MentionTileBuilder = Widget Function(
/// Builder function for building a user mention tile.
///
/// Use [UserMentionTile] for the default implementation.
/// Use [StreamUserMentionTile] for the default implementation.
typedef UserMentionTileBuilder = Widget Function(
BuildContext context,
User user,
@@ -92,7 +88,7 @@ typedef AttachmentsPickerBuilder = Widget Function(
StreamAttachmentPicker defaultPicker,
);
/// Location for actions on the [MessageInput].
/// Location for actions on the [StreamMessageInput].
enum ActionsLocation {
/// Align to left
left,
@@ -173,14 +169,14 @@ const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
/// }
/// ```
///
/// You usually put this widget in the same page of a [MessageListView]
/// You usually put this widget in the same page of a [StreamMessageListView]
/// as the bottom widget.
///
/// The widget renders the ui based on the first ancestor of
/// type [StreamChatTheme]. Modify it to change the widget appearance.
class MessageInput extends StatefulWidget {
class StreamMessageInput extends StatefulWidget {
/// Instantiate a new MessageInput
const MessageInput({
const StreamMessageInput({
Key? key,
this.onMessageSent,
this.preMessageSending,
@@ -202,8 +198,6 @@ class MessageInput extends StatefulWidget {
this.mentionsTileBuilder,
this.userMentionsTileBuilder,
this.maxAttachmentSize = _kDefaultMaxAttachmentSize,
this.compressedVideoQuality = VideoQuality.DefaultQuality,
this.compressedVideoFrameRate = 30,
this.onError,
this.attachmentLimit = 10,
this.onAttachmentLimitExceed,
@@ -224,12 +218,6 @@ class MessageInput extends StatefulWidget {
/// List of options for showing overlays.
final List<OverlayOptions> customOverlays;
/// Video quality to use when compressing the videos.
final VideoQuality compressedVideoQuality;
/// Frame rate to use when compressing the videos.
final int compressedVideoFrameRate;
/// Max attachment size in bytes:
/// - Defaults to 20 MB
/// - Do not set it if you're using our default CDN
@@ -325,7 +313,7 @@ class MessageInput extends StatefulWidget {
/// Builder for creating send button
final MessageRelatedBuilder? sendButtonBuilder;
/// Defines if the [MessageInput] loses focuses after a message is sent.
/// Defines if the [StreamMessageInput] loses focuses after a message is sent.
/// The default behaviour keeps focus until a command is enabled.
final bool? shouldKeepFocusAfterMessage;
@@ -335,25 +323,25 @@ class MessageInput extends StatefulWidget {
/// Restoration ID to save and restore the state of the MessageInput.
final String? restorationId;
/// Wrap [MessageInput] with a [SafeArea widget]
/// Wrap [StreamMessageInput] with a [SafeArea widget]
final bool? enableSafeArea;
/// Elevation of the [MessageInput]
/// Elevation of the [StreamMessageInput]
final double? elevation;
/// Shadow for the [MessageInput] widget
/// Shadow for the [StreamMessageInput] widget
final BoxShadow? shadow;
static bool _defaultValidator(Message message) =>
message.text?.isNotEmpty == true || message.attachments.isNotEmpty;
@override
MessageInputState createState() => MessageInputState();
StreamMessageInputState createState() => StreamMessageInputState();
}
/// State of [MessageInput]
class MessageInputState extends State<MessageInput>
with RestorationMixin<MessageInput> {
/// State of [StreamMessageInput]
class StreamMessageInputState extends State<StreamMessageInput>
with RestorationMixin<StreamMessageInput> {
final _imagePicker = ImagePicker();
late FocusNode _focusNode = widget.focusNode ?? FocusNode();
late final _isInternalFocusNode = widget.focusNode == null;
@@ -367,7 +355,7 @@ class MessageInputState extends State<MessageInput>
bool _openFilePickerSection = false;
late StreamChatThemeData _streamChatTheme;
late MessageInputThemeData _messageInputTheme;
late StreamMessageInputThemeData _messageInputTheme;
bool get _hasQuotedMessage =>
_effectiveController.value.quotedMessage != null;
@@ -410,7 +398,7 @@ class MessageInputState extends State<MessageInput>
}
@override
void didUpdateWidget(covariant MessageInput oldWidget) {
void didUpdateWidget(covariant StreamMessageInput oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.messageInputController == null &&
oldWidget.messageInputController != null) {
@@ -596,7 +584,7 @@ class MessageInputState extends State<MessageInput>
child: child,
);
}
return MultiOverlay(
return StreamMultiOverlay(
childAnchor: Alignment.topCenter,
overlayAnchor: Alignment.bottomCenter,
overlayOptions: [
@@ -1109,7 +1097,7 @@ class MessageInputState extends State<MessageInput>
if (renderObject == null) {
return const Offstage();
}
return CommandsOverlay(
return StreamCommandsOverlay(
channel: StreamChannel.of(context).channel,
size: Size(renderObject.size.width - 16, 400),
text: text,
@@ -1126,8 +1114,6 @@ class MessageInputState extends State<MessageInput>
attachmentLimit: widget.attachmentLimit,
onAttachmentLimitExceeded: widget.onAttachmentLimitExceed,
maxAttachmentSize: widget.maxAttachmentSize,
compressedVideoQuality: widget.compressedVideoQuality,
compressedVideoFrameRate: widget.compressedVideoFrameRate,
onError: _showErrorAlert,
);
@@ -1170,7 +1156,7 @@ class MessageInputState extends State<MessageInput>
}
return LayoutBuilder(
builder: (context, snapshot) => UserMentionsOverlay(
builder: (context, snapshot) => StreamUserMentionsOverlay(
query: query,
mentionAllAppUsers: widget.mentionAllAppUsers,
client: StreamChat.of(context).client,
@@ -1185,10 +1171,10 @@ class MessageInputState extends State<MessageInput>
splits[splits.length - 1] = user.name;
final rejoin = splits.join('@');
_effectiveController.text = rejoin +
_effectiveController.text.substring(
_effectiveController.selectionStart,
);
_effectiveController.text =
'$rejoin${_effectiveController.text.substring(
_effectiveController.selectionStart,
)}';
_onChangedDebounced.cancel();
setState(() => _showMentionsOverlay = false);
@@ -1210,7 +1196,7 @@ class MessageInputState extends State<MessageInput>
// ignore: cast_nullable_to_non_nullable
final renderObject = context.findRenderObject() as RenderBox;
return EmojiOverlay(
return StreamEmojiOverlay(
size: Size(renderObject.size.width - 16, 200),
query: query,
onEmojiResult: (emoji) {
@@ -1241,7 +1227,7 @@ class MessageInputState extends State<MessageInput>
if (!_hasQuotedMessage) return const Offstage();
final containsUrl = _effectiveController.value.quotedMessage!.attachments
.any((element) => element.titleLink != null);
return QuotedMessageWidget(
return StreamQuotedMessageWidget(
reverse: true,
showBorder: !containsUrl,
message: _effectiveController.value.quotedMessage!,
@@ -1275,7 +1261,7 @@ class MessageInputState extends State<MessageInput>
.map<Widget>(
(e) => ClipRRect(
borderRadius: BorderRadius.circular(10),
child: FileAttachment(
child: StreamFileAttachment(
message: Message(), // dummy message
attachment: e,
size: Size(
@@ -1397,7 +1383,7 @@ class MessageInputState extends State<MessageInput>
case 'video':
return Stack(
children: [
VideoThumbnailImage(
StreamVideoThumbnailImage(
height: 104,
width: 104,
video: (attachment.file?.path ?? attachment.assetUrl)!,
@@ -1639,33 +1625,11 @@ class MessageInputState extends State<MessageInput>
);
if (file.size! > widget.maxAttachmentSize) {
if (attachmentType == 'video' && file.path != null) {
final mediaInfo = await (VideoService.compressVideo(
file.path!,
frameRate: widget.compressedVideoFrameRate,
quality: widget.compressedVideoQuality,
) as FutureOr<MediaInfo>);
if (mediaInfo.filesize! > widget.maxAttachmentSize) {
_showErrorAlert(
context.translations.fileTooLargeAfterCompressionError(
widget.maxAttachmentSize / (1024 * 1024),
),
);
return;
}
file = AttachmentFile(
name: file.name,
size: mediaInfo.filesize,
bytes: await mediaInfo.file!.readAsBytes(),
path: mediaInfo.path,
);
} else {
_showErrorAlert(context.translations.fileTooLargeError(
return _showErrorAlert(
context.translations.fileTooLargeError(
widget.maxAttachmentSize / (1024 * 1024),
));
return;
}
),
);
}
_addAttachments([
@@ -1715,6 +1679,8 @@ class MessageInputState extends State<MessageInput>
await streamChannel.reloadChannel();
}
message = message.replaceMentionsWithId();
try {
Future sendingFuture;
if (_isEditing) {
@@ -1831,7 +1797,7 @@ class MessageInputState extends State<MessageInput>
@override
void didChangeDependencies() {
_streamChatTheme = StreamChatTheme.of(context);
_messageInputTheme = MessageInputTheme.of(context);
_messageInputTheme = StreamMessageInputTheme.of(context);
super.didChangeDependencies();
}
@@ -5,9 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/src/media_list_view.dart';
import 'package:stream_chat_flutter/src/video_service.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:video_compress/video_compress.dart';
/// Callback for when a file has to be picked.
typedef FilePickerCallback = void Function(
@@ -34,8 +32,6 @@ class StreamAttachmentPicker extends StatefulWidget {
this.attachmentLimit = 10,
this.onAttachmentLimitExceeded,
this.maxAttachmentSize = 20971520,
this.compressedVideoQuality = VideoQuality.DefaultQuality,
this.compressedVideoFrameRate = 30,
this.onError,
this.allowedAttachmentTypes = const [
DefaultAttachmentTypes.image,
@@ -66,12 +62,6 @@ class StreamAttachmentPicker extends StatefulWidget {
/// Callback for when file is picked.
final FilePickerCallback onFilePicked;
/// Video quality to use when compressing the videos.
final VideoQuality compressedVideoQuality;
/// Frame rate to use when compressing the videos.
final int compressedVideoFrameRate;
/// Max attachment size in bytes:
/// - Defaults to 20 MB
/// - Do not set it if you're using our default CDN
@@ -94,8 +84,6 @@ class StreamAttachmentPicker extends StatefulWidget {
int? attachmentLimit,
AttachmentLimitExceedListener? onAttachmentLimitExceeded,
int? maxAttachmentSize,
VideoQuality? compressedVideoQuality,
int? compressedVideoFrameRate,
ValueChanged<bool>? onChangeInputState,
ValueChanged<String>? onError,
List<DefaultAttachmentTypes>? allowedAttachmentTypes,
@@ -112,10 +100,6 @@ class StreamAttachmentPicker extends StatefulWidget {
onAttachmentLimitExceeded:
onAttachmentLimitExceeded ?? this.onAttachmentLimitExceeded,
maxAttachmentSize: maxAttachmentSize ?? this.maxAttachmentSize,
compressedVideoQuality:
compressedVideoQuality ?? this.compressedVideoQuality,
compressedVideoFrameRate:
compressedVideoFrameRate ?? this.compressedVideoFrameRate,
onError: onError ?? this.onError,
allowedAttachmentTypes:
allowedAttachmentTypes ?? this.allowedAttachmentTypes,
@@ -375,33 +359,11 @@ class _StreamAttachmentPickerState extends State<StreamAttachmentPicker> {
);
if (file.size! > widget.maxAttachmentSize) {
if (medium.type == AssetType.video && file.path != null) {
final mediaInfo = await (VideoService.compressVideo(
file.path!,
frameRate: widget.compressedVideoFrameRate,
quality: widget.compressedVideoQuality,
) as FutureOr<MediaInfo>);
if (mediaInfo.filesize! > widget.maxAttachmentSize) {
widget.onError?.call(
context.translations.fileTooLargeAfterCompressionError(
widget.maxAttachmentSize / (1024 * 1024),
),
);
return;
}
file = AttachmentFile(
name: file.name,
size: mediaInfo.filesize,
bytes: await mediaInfo.file?.readAsBytes(),
path: mediaInfo.path,
);
} else {
widget.onError?.call(context.translations.fileTooLargeError(
return widget.onError?.call(
context.translations.fileTooLargeError(
widget.maxAttachmentSize / (1024 * 1024),
));
return;
}
),
);
}
setState(() {
@@ -507,7 +469,7 @@ class _PickerWidgetState extends State<_PickerWidget> {
),
);
}
return MediaListView(
return StreamMediaListView(
selectedIds: widget.selectedMedias,
onSelect: widget.onMediaSelected,
);
@@ -44,7 +44,7 @@ class StreamMessageSendButton extends StatelessWidget {
late Widget sendButton;
if (timeOut > 0) {
sendButton = CountdownButton(count: timeOut);
sendButton = StreamCountdownButton(count: timeOut);
} else if (isIdle) {
sendButton = idleSendButton ?? _buildIdleSendButton(context);
} else {
@@ -63,7 +63,7 @@ class StreamMessageSendButton extends StatelessWidget {
}
Widget _buildIdleSendButton(BuildContext context) {
final _messageInputTheme = MessageInputTheme.of(context);
final _messageInputTheme = StreamMessageInputTheme.of(context);
return Padding(
padding: const EdgeInsets.all(8),
@@ -75,7 +75,7 @@ class StreamMessageSendButton extends StatelessWidget {
}
Widget _buildSendButton(BuildContext context) {
final _messageInputTheme = MessageInputTheme.of(context);
final _messageInputTheme = StreamMessageInputTheme.of(context);
return Padding(
padding: const EdgeInsets.all(8),
@@ -11,22 +11,22 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:visibility_detector/visibility_detector.dart';
/// Widget builder for message
/// [defaultMessageWidget] is the default [MessageWidget] configuration
/// [defaultMessageWidget] is the default [StreamMessageWidget] configuration
/// Use [defaultMessageWidget.copyWith] to easily customize it
typedef MessageBuilder = Widget Function(
BuildContext,
MessageDetails,
List<Message>,
MessageWidget defaultMessageWidget,
StreamMessageWidget defaultMessageWidget,
);
/// Widget builder for parent message
/// [defaultMessageWidget] is the default [MessageWidget] configuration
/// [defaultMessageWidget] is the default [StreamMessageWidget] configuration
/// Use [defaultMessageWidget.copyWith] to easily customize it
typedef ParentMessageBuilder = Widget Function(
BuildContext,
Message?,
MessageWidget defaultMessageWidget,
StreamMessageWidget defaultMessageWidget,
);
/// Widget builder for system message
@@ -123,6 +123,11 @@ class MessageDetails {
final int index;
}
/// {@macro message_list_view}
@Deprecated("Use 'StreamMessageListView' instead")
typedef MessageListView = StreamMessageListView;
/// {@template message_list_view}
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/message_listview.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/message_listview_paint.png)
///
@@ -165,9 +170,10 @@ class MessageDetails {
/// The widget components render the ui based on the first
/// ancestor of type [StreamChatTheme].
/// Modify it to change the widget appearance.
class MessageListView extends StatefulWidget {
/// {@endtemplate}
class StreamMessageListView extends StatefulWidget {
/// Instantiate a new MessageListView
const MessageListView({
const StreamMessageListView({
Key? key,
this.showScrollToBottom = true,
this.messageBuilder,
@@ -330,10 +336,10 @@ class MessageListView extends StatefulWidget {
final SpacingWidgetBuilder? spacingWidgetBuilder;
@override
_MessageListViewState createState() => _MessageListViewState();
_StreamMessageListViewState createState() => _StreamMessageListViewState();
}
class _MessageListViewState extends State<MessageListView> {
class _StreamMessageListViewState extends State<StreamMessageListView> {
ItemScrollController? _scrollController;
void Function(Message)? _onThreadTap;
final ValueNotifier<bool> _showScrollToBottom = ValueNotifier(false);
@@ -461,7 +467,7 @@ class _MessageListViewState extends State<MessageListView> {
final child = Stack(
alignment: Alignment.center,
children: [
ConnectionStatusBuilder(
StreamConnectionStatusBuilder(
statusBuilder: (context, status) {
var statusString = '';
var showStatus = true;
@@ -478,7 +484,7 @@ class _MessageListViewState extends State<MessageListView> {
break;
}
return InfoTile(
return StreamInfoTile(
showMessage: widget.showConnectionStateTile && showStatus,
tileAnchor: Alignment.topCenter,
childAnchor: Alignment.topCenter,
@@ -592,7 +598,7 @@ class _MessageListViewState extends State<MessageListView> {
)
: Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: DateDivider(
child: StreamDateDivider(
dateTime: nextMessage.createdAt.toLocal(),
),
);
@@ -730,8 +736,10 @@ class _MessageListViewState extends State<MessageListView> {
],
);
final backgroundColor = MessageListViewTheme.of(context).backgroundColor;
final backgroundImage = MessageListViewTheme.of(context).backgroundImage;
final backgroundColor =
StreamMessageListViewTheme.of(context).backgroundColor;
final backgroundImage =
StreamMessageListViewTheme.of(context).backgroundImage;
if (backgroundColor != null || backgroundImage != null) {
return Container(
@@ -761,7 +769,7 @@ class _MessageListViewState extends State<MessageListView> {
child: Text(
context.translations.threadSeparatorText(replyCount),
textAlign: TextAlign.center,
style: ChannelHeaderTheme.of(context).subtitleStyle,
style: StreamChannelHeaderTheme.of(context).subtitleStyle,
),
),
);
@@ -815,7 +823,7 @@ class _MessageListViewState extends State<MessageListView> {
final message = messages[index - 2];
return widget.dateDividerBuilder != null
? widget.dateDividerBuilder!(message.createdAt.toLocal())
: DateDivider(dateTime: message.createdAt.toLocal());
: StreamDateDivider(dateTime: message.createdAt.toLocal());
},
),
);
@@ -976,7 +984,7 @@ class _MessageListViewState extends State<MessageListView> {
final currentUserMember =
members.firstWhereOrNull((e) => e.user!.id == currentUser!.id);
final defaultMessageWidget = MessageWidget(
final defaultMessageWidget = StreamMessageWidget(
showReplyMessage: false,
showResendMessage: false,
showThreadReplyMessage: false,
@@ -1040,7 +1048,7 @@ class _MessageListViewState extends State<MessageListView> {
if ((message.type == 'system' || message.type == 'error') &&
message.text?.isNotEmpty == true) {
return widget.systemMessageBuilder?.call(context, message) ??
SystemMessage(
StreamSystemMessage(
message: message,
onMessageTap: (message) {
if (widget.onSystemMessageTap != null) {
@@ -1110,7 +1118,7 @@ class _MessageListViewState extends State<MessageListView> {
final currentUserMember =
members.firstWhereOrNull((e) => e.user!.id == currentUser!.id);
Widget messageWidget = MessageWidget(
Widget messageWidget = StreamMessageWidget(
message: message,
reverse: isMyMessage,
showReactions: !message.isDeleted,
@@ -1226,7 +1234,7 @@ class _MessageListViewState extends State<MessageListView> {
index,
),
messages,
messageWidget as MessageWidget,
messageWidget as StreamMessageWidget,
);
}
@@ -5,10 +5,16 @@ import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/src/reaction_bubble.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro message_reactions_modal}
@Deprecated("Use 'StreamMessageReactionsModal' instead")
typedef MessageReactionsModal = StreamMessageReactionsModal;
/// {@template message_reactions_modal}
/// Modal widget for displaying message reactions
class MessageReactionsModal extends StatelessWidget {
/// Constructor for creating a [MessageReactionsModal] reactions
const MessageReactionsModal({
/// {@endtemplate}
class StreamMessageReactionsModal extends StatelessWidget {
/// Constructor for creating a [StreamMessageReactionsModal] reactions
const StreamMessageReactionsModal({
Key? key,
required this.message,
required this.messageWidget,
@@ -24,8 +30,8 @@ class MessageReactionsModal extends StatelessWidget {
/// Message to display reactions of
final Message message;
/// [MessageThemeData] to apply to [message]
final MessageThemeData messageTheme;
/// [StreamMessageThemeData] to apply to [message]
final StreamMessageThemeData messageTheme;
/// Flag to reverse message
final bool reverse;
@@ -88,7 +94,7 @@ class MessageReactionsModal extends StatelessWidget {
: -(1.2 - divFactor)),
0,
),
child: ReactionPicker(
child: StreamReactionPicker(
message: message,
),
),
@@ -200,7 +206,7 @@ class MessageReactionsModal extends StatelessWidget {
Stack(
clipBehavior: Clip.none,
children: [
UserAvatar(
StreamUserAvatar(
onTap: onUserAvatarTap,
user: reaction.user!,
constraints: const BoxConstraints.tightFor(
@@ -220,7 +226,7 @@ class MessageReactionsModal extends StatelessWidget {
child: Align(
alignment:
reverse ? Alignment.centerRight : Alignment.centerLeft,
child: ReactionBubble(
child: StreamReactionBubble(
reactions: [reaction],
flipTail: !reverse,
borderColor:
@@ -2,17 +2,23 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro message_search_item}
@Deprecated("Use 'StreamMessageSearchItem' instead")
typedef MessageSearchItem = StreamMessageSearchItem;
/// {@template message_search_item}
/// It shows the current [Message] preview.
///
/// Usually you don't use this widget as it's the default item used by
/// [MessageSearchListView].
/// [StreamMessageSearchListView].
///
/// The widget renders the ui based on the first ancestor of type
/// [StreamChatTheme].
/// Modify it to change the widget appearance.
class MessageSearchItem extends StatelessWidget {
/// {@endtemplate}
class StreamMessageSearchItem extends StatelessWidget {
/// Instantiate a new MessageSearchItem
const MessageSearchItem({
const StreamMessageSearchItem({
Key? key,
required this.getMessageResponse,
this.onTap,
@@ -25,7 +31,7 @@ class MessageSearchItem extends StatelessWidget {
/// Function called when tapping this widget
final VoidCallback? onTap;
/// If true the [MessageSearchItem] will show the current online Status
/// If true the [StreamMessageSearchItem] will show the current online Status
final bool showOnlineStatus;
@override
@@ -34,10 +40,10 @@ class MessageSearchItem extends StatelessWidget {
final channel = getMessageResponse.channel;
final channelName = channel?.extraData['name'];
final user = message.user!;
final channelPreviewTheme = ChannelPreviewTheme.of(context);
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
return ListTile(
onTap: onTap,
leading: UserAvatar(
leading: StreamUserAvatar(
user: user,
showOnlineStatus: showOnlineStatus,
constraints: const BoxConstraints.tightFor(
@@ -120,7 +126,7 @@ class MessageSearchItem extends StatelessWidget {
text = parts.join(' ');
}
final channelPreviewTheme = ChannelPreviewTheme.of(context);
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
return Text.rich(
_getDisplayText(
text!,
@@ -11,13 +11,17 @@ typedef MessageSearchItemBuilder = Widget Function(
GetMessageResponse,
);
/// Builder used when [MessageSearchListView] is empty
/// Builder used when [StreamMessageSearchListView] is empty
typedef EmptyMessageSearchBuilder = Widget Function(
BuildContext context,
String searchQuery,
);
///
/// {@macro message_search_list_view}
@Deprecated("Use 'StreamMessageSearchListView' instead")
typedef MessageSearchListView = StreamMessageSearchListView;
/// {@template message_search_list_view}
/// It shows the list of searched messages.
///
/// ```dart
@@ -47,9 +51,10 @@ typedef EmptyMessageSearchBuilder = Widget Function(
/// The widget components render the ui based on the first ancestor of type
/// [StreamChatTheme].
/// Modify it to change the widget appearance.
class MessageSearchListView extends StatefulWidget {
/// {@endtemplate}
class StreamMessageSearchListView extends StatefulWidget {
/// Instantiate a new MessageSearchListView
const MessageSearchListView({
const StreamMessageSearchListView({
Key? key,
required this.filters,
this.messageQuery,
@@ -96,7 +101,7 @@ class MessageSearchListView extends StatefulWidget {
/// Builder used to create a custom item preview
final MessageSearchItemBuilder? itemBuilder;
/// Function called when tapping on a [MessageSearchItem]
/// Function called when tapping on a [StreamMessageSearchItem]
final MessageSearchItemTapCallback? onItemTap;
/// Builder used to create a custom item separator
@@ -130,10 +135,12 @@ class MessageSearchListView extends StatefulWidget {
final MessageSearchListController? messageSearchListController;
@override
_MessageSearchListViewState createState() => _MessageSearchListViewState();
_StreamMessageSearchListViewState createState() =>
_StreamMessageSearchListViewState();
}
class _MessageSearchListViewState extends State<MessageSearchListView> {
class _StreamMessageSearchListViewState
extends State<StreamMessageSearchListView> {
late final _defaultController = MessageSearchListController();
MessageSearchListController get _messageSearchListController =>
@@ -168,7 +175,7 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
if (error is Error) {
print(error.stackTrace);
}
return InfoTile(
return StreamInfoTile(
showMessage: widget.showErrorTile,
tileAnchor: Alignment.topCenter,
childAnchor: Alignment.topCenter,
@@ -195,7 +202,7 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
);
final backgroundColor =
MessageSearchListViewTheme.of(context).backgroundColor;
StreamMessageSearchListViewTheme.of(context).backgroundColor;
if (backgroundColor != null) {
return ColoredBox(
@@ -219,7 +226,7 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
if (widget.itemBuilder != null) {
return widget.itemBuilder!(context, getMessageResponse);
}
return MessageSearchItem(
return StreamMessageSearchItem(
getMessageResponse: getMessageResponse,
onTap: () => widget.onItemTap!(getMessageResponse),
);
@@ -1,12 +1,19 @@
import 'package:collection/collection.dart' show IterableExtension;
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro message_text}
@Deprecated("Use 'StreamMessageText' instead")
typedef MessageText = StreamMessageText;
/// {@template message_text}
/// Text widget to display in message
class MessageText extends StatelessWidget {
/// Constructor for creating a [MessageText] widget
const MessageText({
/// {@endtemplate}
class StreamMessageText extends StatelessWidget {
/// Constructor for creating a [StreamMessageText] widget
const StreamMessageText({
Key? key,
required this.message,
required this.messageTheme,
@@ -23,8 +30,8 @@ class MessageText extends StatelessWidget {
/// Callback for when link is tapped
final void Function(String)? onLinkTap;
/// [MessageThemeData] whose text theme is to be applied
final MessageThemeData messageTheme;
/// [StreamMessageThemeData] whose text theme is to be applied
final StreamMessageThemeData messageTheme;
@override
Widget build(BuildContext context) {
@@ -34,13 +41,14 @@ class MessageText extends StatelessWidget {
stream: streamChat.currentUserStream.map((it) => it!.language ?? 'en'),
initialData: streamChat.currentUser!.language ?? 'en',
builder: (context, language) {
final translatedText =
message.i18n?['${language}_text'] ?? message.text;
final messageText =
_replaceMentions(translatedText ?? '').replaceAll('\n', '\n\n');
final messageText = message
.translate(language)
.replaceMentions()
.text
?.replaceAll('\n', '\n\n');
final themeData = Theme.of(context);
return MarkdownBody(
data: messageText,
data: messageText ?? '',
onTapLink: (
String link,
String? href,
@@ -80,17 +88,4 @@ class MessageText extends StatelessWidget {
},
);
}
String _replaceMentions(String text) {
var messageTextToRender = text;
for (final user in message.mentionedUsers.toSet()) {
final userId = user.id;
final userName = user.name;
messageTextToRender = messageTextToRender.replaceAll(
'@$userId',
'[@$userName](@${userName.replaceAll(' ', '')})',
);
}
return messageTextToRender;
}
}
@@ -32,20 +32,26 @@ enum DisplayWidget {
show,
}
/// {@macro message_widget}
@Deprecated("Use 'StreamMessageWidget' instead")
typedef MessageWidget = StreamMessageWidget;
/// {@template message_widget}
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/message_widget.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/message_widget_paint.png)
///
/// It shows a message with reactions, replies and user avatar.
///
/// Usually you don't use this widget as it's the default message widget used by
/// [MessageListView].
/// [StreamMessageListView].
///
/// The widget components render the ui based on the first ancestor of type
/// [StreamChatTheme].
/// Modify it to change the widget appearance.
class MessageWidget extends StatefulWidget {
///
MessageWidget({
/// {@endtemplate}
class StreamMessageWidget extends StatefulWidget {
/// Creates a new instance of the message widget.
StreamMessageWidget({
Key? key,
required this.message,
required this.messageTheme,
@@ -121,7 +127,7 @@ class MessageWidget extends StatefulWidget {
context,
Material(
color: messageTheme.messageBackgroundColor,
child: ImageGroup(
child: StreamImageGroup(
size: Size(
mediaQueryData.size.width * 0.8,
mediaQueryData.size.height * 0.3,
@@ -142,7 +148,7 @@ class MessageWidget extends StatefulWidget {
return wrapAttachmentWidget(
context,
ImageAttachment(
StreamImageAttachment(
attachment: attachments[0],
message: message,
messageTheme: messageTheme,
@@ -172,7 +178,7 @@ class MessageWidget extends StatefulWidget {
Column(
children: attachments.map((attachment) {
final mediaQueryData = MediaQuery.of(context);
return VideoAttachment(
return StreamVideoAttachment(
attachment: attachment,
messageTheme: messageTheme,
size: Size(
@@ -204,7 +210,7 @@ class MessageWidget extends StatefulWidget {
Column(
children: attachments.map((attachment) {
final mediaQueryData = MediaQuery.of(context);
return GiphyAttachment(
return StreamGiphyAttachment(
attachment: attachment,
message: message,
size: Size(
@@ -240,7 +246,7 @@ class MessageWidget extends StatefulWidget {
final mediaQueryData = MediaQuery.of(context);
return wrapAttachmentWidget(
context,
FileAttachment(
StreamFileAttachment(
message: message,
attachment: attachment,
size: Size(
@@ -300,7 +306,7 @@ class MessageWidget extends StatefulWidget {
final Message message;
/// The message theme
final MessageThemeData messageTheme;
final StreamMessageThemeData messageTheme;
/// If true the widget will be mirrored
final bool reverse;
@@ -356,7 +362,7 @@ class MessageWidget extends StatefulWidget {
/// The function called when tapping on a link
final void Function(String)? onLinkTap;
/// Used in [MessageReactionsModal] and [MessageActionsModal]
/// Used in [StreamMessageReactionsModal] and [StreamMessageActionsModal]
final bool showReactionPickerIndicator;
/// List of users who read
@@ -417,13 +423,13 @@ class MessageWidget extends StatefulWidget {
final void Function(Message)? onMessageTap;
/// List of custom actions shown on message long tap
final List<MessageAction> customActions;
final List<StreamMessageAction> customActions;
/// Customize onTap on attachment
final void Function(Message message, Attachment attachment)? onAttachmentTap;
/// Creates a copy of [MessageWidget] with specified attributes overridden.
MessageWidget copyWith({
/// Creates a copy of [StreamMessageWidget] with specified attributes overridden.
StreamMessageWidget copyWith({
Key? key,
void Function(User)? onMentionTap,
void Function(Message)? onThreadTap,
@@ -435,7 +441,7 @@ class MessageWidget extends StatefulWidget {
Widget Function(BuildContext, Message)? deletedBottomRowBuilder,
void Function(BuildContext, Message)? onMessageActions,
Message? message,
MessageThemeData? messageTheme,
StreamMessageThemeData? messageTheme,
bool? reverse,
ShapeBorder? shape,
ShapeBorder? attachmentShape,
@@ -473,11 +479,11 @@ class MessageWidget extends StatefulWidget {
bool? translateUserAvatar,
OnQuotedMessageTap? onQuotedMessageTap,
void Function(Message)? onMessageTap,
List<MessageAction>? customActions,
List<StreamMessageAction>? customActions,
void Function(Message message, Attachment attachment)? onAttachmentTap,
Widget Function(BuildContext, User)? userAvatarBuilder,
}) =>
MessageWidget(
StreamMessageWidget(
key: key ?? this.key,
onMentionTap: onMentionTap ?? this.onMentionTap,
onThreadTap: onThreadTap ?? this.onThreadTap,
@@ -539,11 +545,11 @@ class MessageWidget extends StatefulWidget {
);
@override
_MessageWidgetState createState() => _MessageWidgetState();
_StreamMessageWidgetState createState() => _StreamMessageWidgetState();
}
class _MessageWidgetState extends State<MessageWidget>
with AutomaticKeepAliveClientMixin<MessageWidget> {
class _StreamMessageWidgetState extends State<StreamMessageWidget>
with AutomaticKeepAliveClientMixin<StreamMessageWidget> {
bool get showThreadReplyIndicator => widget.showThreadReplyIndicator;
bool get showSendingIndicator => widget.showSendingIndicator;
@@ -717,7 +723,7 @@ class _MessageWidgetState extends State<MessageWidget>
? 0
: 4.0,
),
child: DeletedMessage(
child: StreamDeletedMessage(
borderRadiusGeometry: widget
.borderRadiusGeometry,
borderSide:
@@ -854,7 +860,7 @@ class _MessageWidgetState extends State<MessageWidget>
? () => widget.onQuotedMessageTap!(widget.message.quotedMessageId)
: null;
final chatThemeData = _streamChatTheme;
return QuotedMessageWidget(
return StreamQuotedMessageWidget(
onTap: onTap,
message: widget.message.quotedMessage!,
messageTheme: isMyMessage
@@ -1008,7 +1014,7 @@ class _MessageWidgetState extends State<MessageWidget>
getWebsiteName(hostName.toLowerCase()) ??
hostName.capitalize();
return UrlAttachment(
return StreamUrlAttachment(
urlAttachment: urlAttachment,
hostDisplayName: hostDisplayName,
textPadding: widget.textPadding,
@@ -1041,7 +1047,7 @@ class _MessageWidgetState extends State<MessageWidget>
child: _shouldShowReactions
? GestureDetector(
onTap: () => _showMessageReactionsModalBottomSheet(context),
child: ReactionBubble(
child: StreamReactionBubble(
key: ValueKey('${widget.message.id}.reactions'),
reverse: widget.reverse,
flipTail: widget.reverse,
@@ -1072,7 +1078,7 @@ class _MessageWidgetState extends State<MessageWidget>
barrierColor: _streamChatTheme.colorTheme.overlay,
builder: (context) => StreamChannel(
channel: channel,
child: MessageActionsModal(
child: StreamMessageActionsModal(
messageWidget: widget.copyWith(
key: const Key('MessageWidget'),
message: widget.message.copyWith(
@@ -1129,7 +1135,7 @@ class _MessageWidgetState extends State<MessageWidget>
barrierColor: _streamChatTheme.colorTheme.overlay,
builder: (context) => StreamChannel(
channel: channel,
child: MessageReactionsModal(
child: StreamMessageReactionsModal(
messageWidget: widget.copyWith(
key: const Key('MessageWidget'),
message: widget.message.copyWith(
@@ -1246,7 +1252,7 @@ class _MessageWidgetState extends State<MessageWidget>
final channel = StreamChannel.of(context).channel;
if (!channel.ownCapabilities.contains(PermissionType.readEvents)) {
return SendingIndicator(
return StreamSendingIndicator(
message: message,
size: style!.fontSize,
);
@@ -1261,7 +1267,7 @@ class _MessageWidgetState extends State<MessageWidget>
(it.lastRead.isAfter(message.createdAt) ||
it.lastRead.isAtSameMomentAs(message.createdAt)));
final isMessageRead = readList.length >= (channel.memberCount ?? 0) - 1;
Widget child = SendingIndicator(
Widget child = StreamSendingIndicator(
message: message,
isMessageRead: isMessageRead,
size: style!.fontSize,
@@ -1295,7 +1301,7 @@ class _MessageWidgetState extends State<MessageWidget>
: 0,
),
child: widget.userAvatarBuilder?.call(context, widget.message.user!) ??
UserAvatar(
StreamUserAvatar(
user: widget.message.user!,
onTap: widget.onUserAvatarTap,
constraints: widget.messageTheme.avatarTheme!.constraints,
@@ -1313,7 +1319,7 @@ class _MessageWidgetState extends State<MessageWidget>
padding: isOnlyEmoji ? EdgeInsets.zero : widget.textPadding,
child: widget.textBuilder != null
? widget.textBuilder!(context, widget.message)
: MessageText(
: StreamMessageText(
onLinkTap: widget.onLinkTap,
message: widget.message,
onMentionTap: widget.onMentionTap,
@@ -1430,7 +1436,7 @@ class _ThreadParticipants extends StatelessWidget {
color: _streamChatTheme.colorTheme.barsBg,
),
padding: const EdgeInsets.all(1),
child: UserAvatar(
child: StreamUserAvatar(
user: user,
constraints: BoxConstraints.loose(const Size.fromRadius(7)),
showOnlineStatus: false,
@@ -2,15 +2,21 @@ import 'package:collection/collection.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_portal/flutter_portal.dart';
/// {@macro multi_overlay}
@Deprecated("Use 'StreamMultiOverlay' instead")
typedef MultiOverlay = StreamMultiOverlay;
/// {@template multi_overlay}
/// Widget that renders a single overlay widget from a list of [overlayOptions]
/// It shows the first one that is visible
class MultiOverlay extends StatelessWidget {
/// {@endtemplate}
class StreamMultiOverlay extends StatelessWidget {
/// Constructs a new MultiOverlay widget
/// [overlayOptions] - the list of overlay options
/// [overlayAnchor] - the anchor relative to the overlay
/// [childAnchor] - the anchor relative to the child
/// [child] - the child widget
const MultiOverlay({
const StreamMultiOverlay({
Key? key,
required this.overlayOptions,
required this.child,
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro option_list_tile}
@Deprecated("Use 'StreamOptionListTile' instead")
typedef OptionListTile = StreamOptionListTile;
/// {@template option_list_tile}
/// List tile for [ChannelBottomSheet]
class OptionListTile extends StatelessWidget {
/// Constructor for creating [OptionListTile]
const OptionListTile({
/// {@endtemplate}
class StreamOptionListTile extends StatelessWidget {
/// Constructor for creating [StreamOptionListTile]
const StreamOptionListTile({
Key? key,
required this.title,
this.leading,
@@ -10,54 +10,14 @@ typedef QuotedMessageAttachmentThumbnailBuilder = Widget Function(
Attachment,
);
class _VideoAttachmentThumbnail extends StatefulWidget {
const _VideoAttachmentThumbnail({
Key? key,
required this.attachment,
this.size = const Size(32, 32),
}) : super(key: key);
/// Widget for the quoted message.
@Deprecated("Use 'StreamQuotedMessageWidget' instead")
typedef QuotedMessageWidget = StreamQuotedMessageWidget;
final Size size;
final Attachment attachment;
@override
_VideoAttachmentThumbnailState createState() =>
_VideoAttachmentThumbnailState();
}
class _VideoAttachmentThumbnailState extends State<_VideoAttachmentThumbnail> {
late VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.network(widget.attachment.assetUrl!)
..initialize().then((_) {
// ignore: no-empty-block
setState(() {}); //when your thumbnail will show.
});
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) => SizedBox(
height: widget.size.height,
width: widget.size.width,
child: _controller.value.isInitialized
? VideoPlayer(_controller)
: const CircularProgressIndicator(),
);
}
///
class QuotedMessageWidget extends StatelessWidget {
///
const QuotedMessageWidget({
/// Widget for the quoted message.
class StreamQuotedMessageWidget extends StatelessWidget {
/// Creates a new instance of the widget.
const StreamQuotedMessageWidget({
Key? key,
required this.message,
required this.messageTheme,
@@ -73,7 +33,7 @@ class QuotedMessageWidget extends StatelessWidget {
final Message message;
/// The message theme
final MessageThemeData messageTheme;
final StreamMessageThemeData messageTheme;
/// If true the widget will be mirrored
final bool reverse;
@@ -134,7 +94,7 @@ class QuotedMessageWidget extends StatelessWidget {
if (_hasAttachments) _parseAttachments(context),
if (msg.text!.isNotEmpty)
Flexible(
child: MessageText(
child: StreamMessageText(
message: msg,
messageTheme: isOnlyEmoji && _containsText
? messageTheme.copyWith(
@@ -231,7 +191,7 @@ class QuotedMessageWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(8),
);
Widget _buildUserAvatar() => UserAvatar(
Widget _buildUserAvatar() => StreamUserAvatar(
user: message.user!,
constraints: const BoxConstraints.tightFor(
height: 24,
@@ -242,7 +202,7 @@ class QuotedMessageWidget extends StatelessWidget {
Map<String, QuotedMessageAttachmentThumbnailBuilder>
get _defaultAttachmentBuilder => {
'image': (_, attachment) => ImageAttachment(
'image': (_, attachment) => StreamImageAttachment(
attachment: attachment,
message: message,
messageTheme: messageTheme,
@@ -288,3 +248,47 @@ class QuotedMessageWidget extends StatelessWidget {
return messageTheme.messageBackgroundColor;
}
}
class _VideoAttachmentThumbnail extends StatefulWidget {
const _VideoAttachmentThumbnail({
Key? key,
required this.attachment,
this.size = const Size(32, 32),
}) : super(key: key);
final Size size;
final Attachment attachment;
@override
_VideoAttachmentThumbnailState createState() =>
_VideoAttachmentThumbnailState();
}
class _VideoAttachmentThumbnailState extends State<_VideoAttachmentThumbnail> {
late VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.network(widget.attachment.assetUrl!)
..initialize().then((_) {
// ignore: no-empty-block
setState(() {}); //when your thumbnail will show.
});
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) => SizedBox(
height: widget.size.height,
width: widget.size.width,
child: _controller.value.isInitialized
? VideoPlayer(_controller)
: const CircularProgressIndicator(),
);
}
@@ -4,10 +4,16 @@ import 'package:collection/collection.dart' show IterableExtension;
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro reaction_bubble}
@Deprecated("Use 'StreamReactionBubble' instead")
typedef ReactionBubble = StreamReactionBubble;
/// {@template reaction_bubble}
/// Creates reaction bubble widget for displaying over messages
class ReactionBubble extends StatelessWidget {
/// Constructor for creating a [ReactionBubble]
const ReactionBubble({
/// {@endtemplate}
class StreamReactionBubble extends StatelessWidget {
/// Constructor for creating a [StreamReactionBubble]
const StreamReactionBubble({
Key? key,
required this.reactions,
required this.borderColor,
@@ -111,7 +117,7 @@ class ReactionBubble extends StatelessWidget {
}
Widget _buildReaction(
List<ReactionIcon> reactionIcons,
List<StreamReactionIcon> reactionIcons,
Reaction reaction,
BuildContext context,
) {
@@ -1,9 +1,13 @@
import 'package:flutter/material.dart';
/// Reaction icon data
class ReactionIcon {
/// Constructor for creating [ReactionIcon]
ReactionIcon({
@Deprecated("Use 'StreamReactionIcon' instead")
typedef ReactionIcon = StreamReactionIcon;
/// Reaction icon data
class StreamReactionIcon {
/// Constructor for creating [StreamReactionIcon]
StreamReactionIcon({
required this.type,
required this.builder,
});
@@ -3,16 +3,22 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro reaction_picker}
@Deprecated("Use 'StreamReactionPicker' instead")
typedef ReactionPicker = StreamReactionPicker;
/// {@template reaction_picker}
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/reaction_picker.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/reaction_picker_paint.png)
///
/// It shows a reaction picker
///
/// Usually you don't use this widget as it's one of the default widgets used
/// by [MessageWidget.onMessageActions].
class ReactionPicker extends StatefulWidget {
/// Constructor for creating a [ReactionPicker] widget
const ReactionPicker({
/// by [StreamMessageWidget.onMessageActions].
/// {@endtemplate}
class StreamReactionPicker extends StatefulWidget {
/// Constructor for creating a [StreamReactionPicker] widget
const StreamReactionPicker({
Key? key,
required this.message,
}) : super(key: key);
@@ -21,10 +27,10 @@ class ReactionPicker extends StatefulWidget {
final Message message;
@override
_ReactionPickerState createState() => _ReactionPickerState();
_StreamReactionPickerState createState() => _StreamReactionPickerState();
}
class _ReactionPickerState extends State<ReactionPicker>
class _StreamReactionPickerState extends State<StreamReactionPicker>
with TickerProviderStateMixin {
List<EzAnimation> animations = [];
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro sending_indicator}
@Deprecated("Use 'StreamSendingIndicator' instead")
typedef SendingIndicator = StreamSendingIndicator;
/// {@template sending_indicator}
/// Used to show the sending status of the message
class SendingIndicator extends StatelessWidget {
/// Constructor for creating a [SendingIndicator] widget
const SendingIndicator({
/// {@endtemplate}
class StreamSendingIndicator extends StatelessWidget {
/// Constructor for creating a [StreamSendingIndicator] widget
const StreamSendingIndicator({
Key? key,
required this.message,
this.isMessageRead = false,
@@ -38,29 +38,29 @@ class StreamChatThemeData {
/// Create a theme from scratch
factory StreamChatThemeData({
Brightness? brightness,
TextTheme? textTheme,
ColorTheme? colorTheme,
ChannelListHeaderThemeData? channelListHeaderTheme,
ChannelPreviewThemeData? channelPreviewTheme,
ChannelHeaderThemeData? channelHeaderTheme,
MessageThemeData? otherMessageTheme,
MessageThemeData? ownMessageTheme,
MessageInputThemeData? messageInputTheme,
StreamTextTheme? textTheme,
StreamColorTheme? colorTheme,
StreamChannelListHeaderThemeData? channelListHeaderTheme,
StreamChannelPreviewThemeData? channelPreviewTheme,
StreamChannelHeaderThemeData? channelHeaderTheme,
StreamMessageThemeData? otherMessageTheme,
StreamMessageThemeData? ownMessageTheme,
StreamMessageInputThemeData? messageInputTheme,
Widget Function(BuildContext, User)? defaultUserImage,
Widget Function(BuildContext, User)? placeholderUserImage,
IconThemeData? primaryIconTheme,
List<ReactionIcon>? reactionIcons,
GalleryHeaderThemeData? imageHeaderTheme,
GalleryFooterThemeData? imageFooterTheme,
MessageListViewThemeData? messageListViewTheme,
ChannelListViewThemeData? channelListViewTheme,
UserListViewThemeData? userListViewTheme,
MessageSearchListViewThemeData? messageSearchListViewTheme,
List<StreamReactionIcon>? reactionIcons,
StreamGalleryHeaderThemeData? imageHeaderTheme,
StreamGalleryFooterThemeData? imageFooterTheme,
StreamMessageListViewThemeData? messageListViewTheme,
StreamChannelListViewThemeData? channelListViewTheme,
StreamUserListViewThemeData? userListViewTheme,
StreamMessageSearchListViewThemeData? messageSearchListViewTheme,
}) {
brightness ??= colorTheme?.brightness ?? Brightness.light;
final isDark = brightness == Brightness.dark;
textTheme ??= isDark ? TextTheme.dark() : TextTheme.light();
colorTheme ??= isDark ? ColorTheme.dark() : ColorTheme.light();
textTheme ??= isDark ? StreamTextTheme.dark() : StreamTextTheme.light();
colorTheme ??= isDark ? StreamColorTheme.dark() : StreamColorTheme.light();
final defaultData = StreamChatThemeData.fromColorAndTextTheme(
colorTheme,
@@ -133,14 +133,14 @@ class StreamChatThemeData {
/// Create theme from color and text theme
factory StreamChatThemeData.fromColorAndTextTheme(
ColorTheme colorTheme,
TextTheme textTheme,
StreamColorTheme colorTheme,
StreamTextTheme textTheme,
) {
final accentColor = colorTheme.accentPrimary;
final iconTheme =
IconThemeData(color: colorTheme.textHighEmphasis.withOpacity(0.5));
final channelHeaderTheme = ChannelHeaderThemeData(
avatarTheme: AvatarThemeData(
final channelHeaderTheme = StreamChannelHeaderThemeData(
avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor(
height: 40,
@@ -153,9 +153,9 @@ class StreamChatThemeData {
color: const Color(0xff7A7A7A),
),
);
final channelPreviewTheme = ChannelPreviewThemeData(
final channelPreviewTheme = StreamChannelPreviewThemeData(
unreadCounterColor: colorTheme.accentError,
avatarTheme: AvatarThemeData(
avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor(
height: 40,
@@ -176,14 +176,14 @@ class StreamChatThemeData {
colorTheme: colorTheme,
primaryIconTheme: iconTheme,
defaultUserImage: (context, user) => Center(
child: GradientAvatar(
child: StreamGradientAvatar(
name: user.name,
userId: user.id,
),
),
channelPreviewTheme: channelPreviewTheme,
channelListHeaderTheme: ChannelListHeaderThemeData(
avatarTheme: AvatarThemeData(
channelListHeaderTheme: StreamChannelListHeaderThemeData(
avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor(
height: 40,
@@ -194,7 +194,7 @@ class StreamChatThemeData {
titleStyle: textTheme.headlineBold,
),
channelHeaderTheme: channelHeaderTheme,
ownMessageTheme: MessageThemeData(
ownMessageTheme: StreamMessageThemeData(
messageAuthorStyle:
textTheme.footnote.copyWith(color: colorTheme.textLowEmphasis),
messageTextStyle: textTheme.body,
@@ -206,7 +206,7 @@ class StreamChatThemeData {
reactionsBorderColor: colorTheme.borders,
reactionsMaskColor: colorTheme.appBg,
messageBorderColor: colorTheme.disabled,
avatarTheme: AvatarThemeData(
avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor(
height: 32,
@@ -218,7 +218,7 @@ class StreamChatThemeData {
),
linkBackgroundColor: colorTheme.linkBg,
),
otherMessageTheme: MessageThemeData(
otherMessageTheme: StreamMessageThemeData(
reactionsBackgroundColor: colorTheme.disabled,
reactionsBorderColor: colorTheme.barsBg,
reactionsMaskColor: colorTheme.appBg,
@@ -233,7 +233,7 @@ class StreamChatThemeData {
),
messageBackgroundColor: colorTheme.barsBg,
messageBorderColor: colorTheme.borders,
avatarTheme: AvatarThemeData(
avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor(
height: 32,
@@ -242,7 +242,7 @@ class StreamChatThemeData {
),
linkBackgroundColor: colorTheme.linkBg,
),
messageInputTheme: MessageInputThemeData(
messageInputTheme: StreamMessageInputThemeData(
borderRadius: BorderRadius.circular(20),
sendAnimationDuration: const Duration(milliseconds: 300),
actionButtonColor: colorTheme.accentPrimary,
@@ -267,7 +267,7 @@ class StreamChatThemeData {
),
),
reactionIcons: [
ReactionIcon(
StreamReactionIcon(
type: 'love',
builder: (context, highlighted, size) {
final theme = StreamChatTheme.of(context);
@@ -279,7 +279,7 @@ class StreamChatThemeData {
);
},
),
ReactionIcon(
StreamReactionIcon(
type: 'like',
builder: (context, highlighted, size) {
final theme = StreamChatTheme.of(context);
@@ -291,7 +291,7 @@ class StreamChatThemeData {
);
},
),
ReactionIcon(
StreamReactionIcon(
type: 'sad',
builder: (context, highlighted, size) {
final theme = StreamChatTheme.of(context);
@@ -303,7 +303,7 @@ class StreamChatThemeData {
);
},
),
ReactionIcon(
StreamReactionIcon(
type: 'haha',
builder: (context, highlighted, size) {
final theme = StreamChatTheme.of(context);
@@ -315,7 +315,7 @@ class StreamChatThemeData {
);
},
),
ReactionIcon(
StreamReactionIcon(
type: 'wow',
builder: (context, highlighted, size) {
final theme = StreamChatTheme.of(context);
@@ -328,7 +328,7 @@ class StreamChatThemeData {
},
),
],
galleryHeaderTheme: GalleryHeaderThemeData(
galleryHeaderTheme: StreamGalleryHeaderThemeData(
closeButtonColor: colorTheme.textHighEmphasis,
backgroundColor: channelHeaderTheme.color,
iconMenuPointColor: colorTheme.textHighEmphasis,
@@ -336,7 +336,7 @@ class StreamChatThemeData {
subtitleTextStyle: channelPreviewTheme.subtitleStyle,
bottomSheetBarrierColor: colorTheme.overlay,
),
galleryFooterTheme: GalleryFooterThemeData(
galleryFooterTheme: StreamGalleryFooterThemeData(
backgroundColor: colorTheme.barsBg,
shareIconColor: colorTheme.textHighEmphasis,
titleTextStyle: textTheme.headlineBold,
@@ -346,52 +346,52 @@ class StreamChatThemeData {
bottomSheetPhotosTextStyle: textTheme.headlineBold,
bottomSheetCloseIconColor: colorTheme.textHighEmphasis,
),
messageListViewTheme: MessageListViewThemeData(
messageListViewTheme: StreamMessageListViewThemeData(
backgroundColor: colorTheme.barsBg,
),
channelListViewTheme: ChannelListViewThemeData(
channelListViewTheme: StreamChannelListViewThemeData(
backgroundColor: colorTheme.appBg,
),
userListViewTheme: UserListViewThemeData(
userListViewTheme: StreamUserListViewThemeData(
backgroundColor: colorTheme.appBg,
),
messageSearchListViewTheme: MessageSearchListViewThemeData(
messageSearchListViewTheme: StreamMessageSearchListViewThemeData(
backgroundColor: colorTheme.appBg,
),
);
}
/// The text themes used in the widgets
final TextTheme textTheme;
final StreamTextTheme textTheme;
/// The color themes used in the widgets
final ColorTheme colorTheme;
final StreamColorTheme colorTheme;
/// Theme of the [ChannelPreview]
final ChannelPreviewThemeData channelPreviewTheme;
/// Theme of the [StreamChannelPreview]
final StreamChannelPreviewThemeData channelPreviewTheme;
/// Theme of the [ChannelListHeader]
final ChannelListHeaderThemeData channelListHeaderTheme;
/// Theme of the [StreamChannelListHeader]
final StreamChannelListHeaderThemeData channelListHeaderTheme;
/// Theme of the chat widgets dedicated to a channel header
final ChannelHeaderThemeData channelHeaderTheme;
final StreamChannelHeaderThemeData channelHeaderTheme;
/// The default style for [GalleryHeader]s below the overall
/// The default style for [StreamGalleryHeader]s below the overall
/// [StreamChatTheme].
final GalleryHeaderThemeData galleryHeaderTheme;
final StreamGalleryHeaderThemeData galleryHeaderTheme;
/// The default style for [GalleryFooter]s below the overall
/// The default style for [StreamGalleryFooter]s below the overall
/// [StreamChatTheme].
final GalleryFooterThemeData galleryFooterTheme;
final StreamGalleryFooterThemeData galleryFooterTheme;
/// Theme of the current user messages
final MessageThemeData ownMessageTheme;
final StreamMessageThemeData ownMessageTheme;
/// Theme of other users messages
final MessageThemeData otherMessageTheme;
final StreamMessageThemeData otherMessageTheme;
/// Theme dedicated to the [MessageInput] widget
final MessageInputThemeData messageInputTheme;
/// Theme dedicated to the [StreamMessageInput] widget
final StreamMessageInputThemeData messageInputTheme;
/// The widget that will be built when the user image is unavailable
final Widget Function(BuildContext, User) defaultUserImage;
@@ -403,41 +403,41 @@ class StreamChatThemeData {
final IconThemeData primaryIconTheme;
/// Assets used for rendering reactions
final List<ReactionIcon> reactionIcons;
final List<StreamReactionIcon> reactionIcons;
/// Theme configuration for the [MessageListView] widget.
final MessageListViewThemeData messageListViewTheme;
/// Theme configuration for the [StreamMessageListView] widget.
final StreamMessageListViewThemeData messageListViewTheme;
/// Theme configuration for the [ChannelListView] widget.
final ChannelListViewThemeData channelListViewTheme;
/// Theme configuration for the [StreamChannelListView] widget.
final StreamChannelListViewThemeData channelListViewTheme;
/// Theme configuration for the [UserListView] widget.
final UserListViewThemeData userListViewTheme;
/// Theme configuration for the [StreamUserListView] widget.
final StreamUserListViewThemeData userListViewTheme;
/// Theme configuration for the [MessageSearchListView] widget.
final MessageSearchListViewThemeData messageSearchListViewTheme;
/// Theme configuration for the [StreamMessageSearchListView] widget.
final StreamMessageSearchListViewThemeData messageSearchListViewTheme;
/// Creates a copy of [StreamChatThemeData] with specified attributes
/// overridden.
StreamChatThemeData copyWith({
TextTheme? textTheme,
ColorTheme? colorTheme,
ChannelPreviewThemeData? channelPreviewTheme,
ChannelHeaderThemeData? channelHeaderTheme,
MessageThemeData? ownMessageTheme,
MessageThemeData? otherMessageTheme,
MessageInputThemeData? messageInputTheme,
StreamTextTheme? textTheme,
StreamColorTheme? colorTheme,
StreamChannelPreviewThemeData? channelPreviewTheme,
StreamChannelHeaderThemeData? channelHeaderTheme,
StreamMessageThemeData? ownMessageTheme,
StreamMessageThemeData? otherMessageTheme,
StreamMessageInputThemeData? messageInputTheme,
Widget Function(BuildContext, User)? defaultUserImage,
Widget Function(BuildContext, User)? placeholderUserImage,
IconThemeData? primaryIconTheme,
ChannelListHeaderThemeData? channelListHeaderTheme,
List<ReactionIcon>? reactionIcons,
GalleryHeaderThemeData? galleryHeaderTheme,
GalleryFooterThemeData? galleryFooterTheme,
MessageListViewThemeData? messageListViewTheme,
ChannelListViewThemeData? channelListViewTheme,
UserListViewThemeData? userListViewTheme,
MessageSearchListViewThemeData? messageSearchListViewTheme,
StreamChannelListHeaderThemeData? channelListHeaderTheme,
List<StreamReactionIcon>? reactionIcons,
StreamGalleryHeaderThemeData? galleryHeaderTheme,
StreamGalleryFooterThemeData? galleryFooterTheme,
StreamMessageListViewThemeData? messageListViewTheme,
StreamChannelListViewThemeData? channelListViewTheme,
StreamUserListViewThemeData? userListViewTheme,
StreamMessageSearchListViewThemeData? messageSearchListViewTheme,
}) =>
StreamChatThemeData.raw(
channelListHeaderTheme:
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// It shows a date divider depending on the date difference
class SystemMessage extends StatelessWidget {
/// Constructor for creating a [SystemMessage]
const SystemMessage({
/// {@macro system_message}
@Deprecated("Use 'StreamSystemMessage' instead")
typedef SystemMessage = StreamSystemMessage;
/// {@template system_message}
/// It shows a widget for the message with a system message type.
/// {@endtemplate}
class StreamSystemMessage extends StatelessWidget {
/// Constructor for creating a [StreamSystemMessage]
const StreamSystemMessage({
Key? key,
required this.message,
this.onMessageTap,
@@ -1,11 +1,17 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
/// {@macro avatar_theme_data}
@Deprecated("Use 'StreamAvatarThemeData' instead")
typedef AvatarThemeData = StreamAvatarThemeData;
/// {@template avatar_theme_data}
/// A style that overrides the default appearance of various avatar widgets.
/// {@endtemplate}
// ignore: prefer-match-file-name
class AvatarThemeData with Diagnosticable {
/// Creates an [AvatarThemeData].
const AvatarThemeData({
class StreamAvatarThemeData with Diagnosticable {
/// Creates an [StreamAvatarThemeData].
const StreamAvatarThemeData({
BoxConstraints? constraints,
BorderRadius? borderRadius,
}) : _constraints = constraints,
@@ -25,12 +31,12 @@ class AvatarThemeData with Diagnosticable {
/// Get border radius
BorderRadius get borderRadius => _borderRadius ?? BorderRadius.circular(20);
/// Copy this [AvatarThemeData] to another.
AvatarThemeData copyWith({
/// Copy this [StreamAvatarThemeData] to another.
StreamAvatarThemeData copyWith({
BoxConstraints? constraints,
BorderRadius? borderRadius,
}) =>
AvatarThemeData(
StreamAvatarThemeData(
constraints: constraints ?? _constraints,
borderRadius: borderRadius ?? _borderRadius,
);
@@ -38,12 +44,12 @@ class AvatarThemeData with Diagnosticable {
/// Linearly interpolate between two [UserAvatar] themes.
///
/// All the properties must be non-null.
AvatarThemeData lerp(
AvatarThemeData a,
AvatarThemeData b,
StreamAvatarThemeData lerp(
StreamAvatarThemeData a,
StreamAvatarThemeData b,
double t,
) =>
AvatarThemeData(
StreamAvatarThemeData(
borderRadius: BorderRadius.lerp(a.borderRadius, b.borderRadius, t),
constraints: BoxConstraints.lerp(a.constraints, b.constraints, t),
);
@@ -51,7 +57,7 @@ class AvatarThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AvatarThemeData &&
other is StreamAvatarThemeData &&
runtimeType == other.runtimeType &&
_constraints == other._constraints &&
_borderRadius == other._borderRadius;
@@ -59,8 +65,8 @@ class AvatarThemeData with Diagnosticable {
@override
int get hashCode => _constraints.hashCode ^ _borderRadius.hashCode;
/// Merges one [AvatarThemeData] with the another
AvatarThemeData merge(AvatarThemeData? other) {
/// Merges one [StreamAvatarThemeData] with the another
StreamAvatarThemeData merge(StreamAvatarThemeData? other) {
if (other == null) return this;
return copyWith(
constraints: other._constraints,
@@ -4,27 +4,33 @@ import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
import 'package:stream_chat_flutter/src/theme/avatar_theme.dart';
import 'package:stream_chat_flutter/src/theme/themes.dart';
/// {@macro channel_header_theme}
@Deprecated("Use 'StreamChannelHeaderTheme' instead")
typedef ChannelHeaderTheme = StreamChannelHeaderTheme;
/// {@template channel_header_theme}
/// Overrides the default style of [ChannelHeader] descendants.
///
/// See also:
///
/// * [ChannelHeaderThemeData], which is used to configure this theme.
class ChannelHeaderTheme extends InheritedTheme {
/// Creates a [ChannelHeaderTheme].
/// * [StreamChannelHeaderThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamChannelHeaderTheme extends InheritedTheme {
/// Creates a [StreamChannelHeaderTheme].
///
/// The [data] parameter must not be null.
const ChannelHeaderTheme({
const StreamChannelHeaderTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final ChannelHeaderThemeData data;
final StreamChannelHeaderThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [ChannelHeaderTheme] widget, then
/// If there is no enclosing [StreamChannelHeaderTheme] widget, then
/// [StreamChatThemeData.channelTheme.channelHeaderTheme] is used.
///
/// Typical usage is as follows:
@@ -32,34 +38,40 @@ class ChannelHeaderTheme extends InheritedTheme {
/// ```dart
/// final theme = ChannelHeaderTheme.of(context);
/// ```
static ChannelHeaderThemeData of(BuildContext context) {
static StreamChannelHeaderThemeData of(BuildContext context) {
final channelHeaderTheme =
context.dependOnInheritedWidgetOfExactType<ChannelHeaderTheme>();
context.dependOnInheritedWidgetOfExactType<StreamChannelHeaderTheme>();
return channelHeaderTheme?.data ??
StreamChatTheme.of(context).channelHeaderTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
ChannelHeaderTheme(data: data, child: child);
StreamChannelHeaderTheme(data: data, child: child);
@override
bool updateShouldNotify(ChannelHeaderTheme oldWidget) =>
bool updateShouldNotify(StreamChannelHeaderTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro channel_header_theme_data}
@Deprecated("Use 'StreamChannelHeaderThemeData' instead")
typedef ChannelHeaderThemeData = StreamChannelHeaderThemeData;
/// {@template channel_header_theme_data}
/// A style that overrides the default appearance of [ChannelHeader]s when used
/// with [ChannelHeaderTheme] or with the overall [StreamChatTheme]'s
/// with [StreamChannelHeaderTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.channelHeaderTheme].
///
/// See also:
///
/// * [ChannelHeaderTheme], the theme which is configured with this class.
/// * [StreamChannelHeaderTheme], the theme which is configured with this class.
/// * [StreamChatThemeData.channelHeaderTheme], which can be used to override
/// the default style for [ChannelHeader]s below the overall [StreamChatTheme].
class ChannelHeaderThemeData with Diagnosticable {
/// Creates a [ChannelHeaderThemeData]
const ChannelHeaderThemeData({
/// {@endtemplate}
class StreamChannelHeaderThemeData with Diagnosticable {
/// Creates a [StreamChannelHeaderThemeData]
const StreamChannelHeaderThemeData({
this.titleStyle,
this.subtitleStyle,
this.avatarTheme,
@@ -73,43 +85,43 @@ class ChannelHeaderThemeData with Diagnosticable {
final TextStyle? subtitleStyle;
/// Theme for avatar
final AvatarThemeData? avatarTheme;
final StreamAvatarThemeData? avatarTheme;
/// Color for [ChannelHeaderThemeData]
/// Color for [StreamChannelHeaderThemeData]
final Color? color;
/// Copy with theme
ChannelHeaderThemeData copyWith({
StreamChannelHeaderThemeData copyWith({
TextStyle? titleStyle,
TextStyle? subtitleStyle,
AvatarThemeData? avatarTheme,
StreamAvatarThemeData? avatarTheme,
Color? color,
}) =>
ChannelHeaderThemeData(
StreamChannelHeaderThemeData(
titleStyle: titleStyle ?? this.titleStyle,
subtitleStyle: subtitleStyle ?? this.subtitleStyle,
avatarTheme: avatarTheme ?? this.avatarTheme,
color: color ?? this.color,
);
/// Linearly interpolate between two [ChannelHeaderThemeData].
/// Linearly interpolate between two [StreamChannelHeaderThemeData].
///
/// All the properties must be non-null.
ChannelHeaderThemeData lerp(
ChannelHeaderThemeData a,
ChannelHeaderThemeData b,
StreamChannelHeaderThemeData lerp(
StreamChannelHeaderThemeData a,
StreamChannelHeaderThemeData b,
double t,
) =>
ChannelHeaderThemeData(
StreamChannelHeaderThemeData(
titleStyle: TextStyle.lerp(a.titleStyle, b.titleStyle, t),
subtitleStyle: TextStyle.lerp(a.subtitleStyle, b.subtitleStyle, t),
avatarTheme:
const AvatarThemeData().lerp(a.avatarTheme!, b.avatarTheme!, t),
avatarTheme: const StreamAvatarThemeData()
.lerp(a.avatarTheme!, b.avatarTheme!, t),
color: Color.lerp(a.color, b.color, t),
);
/// Merge with other [ChannelHeaderThemeData]
ChannelHeaderThemeData merge(ChannelHeaderThemeData? other) {
/// Merge with other [StreamChannelHeaderThemeData]
StreamChannelHeaderThemeData merge(StreamChannelHeaderThemeData? other) {
if (other == null) return this;
return copyWith(
titleStyle: titleStyle?.merge(other.titleStyle) ?? other.titleStyle,
@@ -123,7 +135,7 @@ class ChannelHeaderThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ChannelHeaderThemeData &&
other is StreamChannelHeaderThemeData &&
runtimeType == other.runtimeType &&
titleStyle == other.titleStyle &&
subtitleStyle == other.subtitleStyle &&
@@ -3,27 +3,33 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
import 'package:stream_chat_flutter/src/theme/avatar_theme.dart';
/// {@macro channel_list_header_theme}
@Deprecated("Use 'StreamChannelListHeaderTheme' instead")
typedef ChannelListHeaderTheme = StreamChannelListHeaderTheme;
/// {@template channel_list_header_theme}
/// Overrides the default style of [ChannelListHeader] descendants.
///
/// See also:
///
/// * [ChannelListHeaderThemeData], which is used to configure this theme.
class ChannelListHeaderTheme extends InheritedTheme {
/// Creates a [ChannelListHeaderTheme].
/// * [StreamChannelListHeaderThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamChannelListHeaderTheme extends InheritedTheme {
/// Creates a [StreamChannelListHeaderTheme].
///
/// The [data] parameter must not be null.
const ChannelListHeaderTheme({
const StreamChannelListHeaderTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final ChannelListHeaderThemeData data;
final StreamChannelListHeaderThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [ChannelListHeaderTheme] widget, then
/// If there is no enclosing [StreamChannelListHeaderTheme] widget, then
/// [StreamChatThemeData.channelListHeaderTheme] is used.
///
/// Typical usage is as follows:
@@ -31,26 +37,32 @@ class ChannelListHeaderTheme extends InheritedTheme {
/// ```dart
/// final theme = ChannelListHeaderTheme.of(context);
/// ```
static ChannelListHeaderThemeData of(BuildContext context) {
final channelListHeaderTheme =
context.dependOnInheritedWidgetOfExactType<ChannelListHeaderTheme>();
static StreamChannelListHeaderThemeData of(BuildContext context) {
final channelListHeaderTheme = context
.dependOnInheritedWidgetOfExactType<StreamChannelListHeaderTheme>();
return channelListHeaderTheme?.data ??
StreamChatTheme.of(context).channelListHeaderTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
ChannelListHeaderTheme(data: data, child: child);
StreamChannelListHeaderTheme(data: data, child: child);
@override
bool updateShouldNotify(ChannelListHeaderTheme oldWidget) =>
bool updateShouldNotify(StreamChannelListHeaderTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro channel_list_header_theme_data}
@Deprecated("Use ''StreamChannelListHeaderThemeData' instead")
typedef ChannelListHeaderThemeData = StreamChannelListHeaderThemeData;
/// {@template channel_list_header_theme_data}
/// Theme dedicated to the [ChannelListHeader]
class ChannelListHeaderThemeData with Diagnosticable {
/// Returns a new [ChannelListHeaderThemeData]
const ChannelListHeaderThemeData({
/// {@endtemplate}
class StreamChannelListHeaderThemeData with Diagnosticable {
/// Returns a new [StreamChannelListHeaderThemeData]
const StreamChannelListHeaderThemeData({
this.titleStyle,
this.avatarTheme,
this.color,
@@ -60,39 +72,41 @@ class ChannelListHeaderThemeData with Diagnosticable {
final TextStyle? titleStyle;
/// Theme dedicated to the userAvatar
final AvatarThemeData? avatarTheme;
final StreamAvatarThemeData? avatarTheme;
/// Background color of the appbar
final Color? color;
/// Returns a new [ChannelListHeaderThemeData] replacing some of its
/// Returns a new [StreamChannelListHeaderThemeData] replacing some of its
/// properties
ChannelListHeaderThemeData copyWith({
StreamChannelListHeaderThemeData copyWith({
TextStyle? titleStyle,
AvatarThemeData? avatarTheme,
StreamAvatarThemeData? avatarTheme,
Color? color,
}) =>
ChannelListHeaderThemeData(
StreamChannelListHeaderThemeData(
titleStyle: titleStyle ?? this.titleStyle,
avatarTheme: avatarTheme ?? this.avatarTheme,
color: color ?? this.color,
);
/// Linearly interpolate from one [ChannelListHeaderThemeData] to another.
ChannelListHeaderThemeData lerp(
ChannelListHeaderThemeData a,
ChannelListHeaderThemeData b,
/// Linearly interpolate from one [StreamChannelListHeaderThemeData] to another.
StreamChannelListHeaderThemeData lerp(
StreamChannelListHeaderThemeData a,
StreamChannelListHeaderThemeData b,
double t,
) =>
ChannelListHeaderThemeData(
avatarTheme:
const AvatarThemeData().lerp(a.avatarTheme!, b.avatarTheme!, t),
StreamChannelListHeaderThemeData(
avatarTheme: const StreamAvatarThemeData()
.lerp(a.avatarTheme!, b.avatarTheme!, t),
color: Color.lerp(a.color, b.color, t),
titleStyle: TextStyle.lerp(a.titleStyle, b.titleStyle, t),
);
/// Merges [this] [ChannelListHeaderThemeData] with the [other]
ChannelListHeaderThemeData merge(ChannelListHeaderThemeData? other) {
/// Merges [this] [StreamChannelListHeaderThemeData] with the [other]
StreamChannelListHeaderThemeData merge(
StreamChannelListHeaderThemeData? other,
) {
if (other == null) return this;
return copyWith(
titleStyle: titleStyle?.merge(other.titleStyle) ?? other.titleStyle,
@@ -104,7 +118,7 @@ class ChannelListHeaderThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ChannelListHeaderThemeData &&
other is StreamChannelListHeaderThemeData &&
runtimeType == other.runtimeType &&
titleStyle == other.titleStyle &&
avatarTheme == other.avatarTheme &&
@@ -2,27 +2,33 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro channel_list_view_theme}
@Deprecated("Use 'StreamChannelListViewTheme' instead")
typedef ChannelListViewTheme = StreamChannelListViewTheme;
/// {@template channel_list_view_theme}
/// Overrides the default style of [ChannelListView] descendants.
///
/// See also:
///
/// * [ChannelListViewThemeData], which is used to configure this theme.
class ChannelListViewTheme extends InheritedTheme {
/// Creates a [ChannelListViewTheme].
/// * [StreamChannelListViewThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamChannelListViewTheme extends InheritedTheme {
/// Creates a [StreamChannelListViewTheme].
///
/// The [data] parameter must not be null.
const ChannelListViewTheme({
const StreamChannelListViewTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final ChannelListViewThemeData data;
final StreamChannelListViewThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [ChannelListViewTheme] widget, then
/// If there is no enclosing [StreamChannelListViewTheme] widget, then
/// [StreamChatThemeData.channelListViewTheme] is used.
///
/// Typical usage is as follows:
@@ -30,63 +36,69 @@ class ChannelListViewTheme extends InheritedTheme {
/// ```dart
/// ChannelListViewTheme theme = ChannelListViewTheme.of(context);
/// ```
static ChannelListViewThemeData of(BuildContext context) {
final channelListViewTheme =
context.dependOnInheritedWidgetOfExactType<ChannelListViewTheme>();
static StreamChannelListViewThemeData of(BuildContext context) {
final channelListViewTheme = context
.dependOnInheritedWidgetOfExactType<StreamChannelListViewTheme>();
return channelListViewTheme?.data ??
StreamChatTheme.of(context).channelListViewTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
ChannelListViewTheme(data: data, child: child);
StreamChannelListViewTheme(data: data, child: child);
@override
bool updateShouldNotify(ChannelListViewTheme oldWidget) =>
bool updateShouldNotify(StreamChannelListViewTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro channel_list_view_theme_data}
@Deprecated("Use 'StreamChannelListViewThemeData' instead")
typedef ChannelListViewThemeData = StreamChannelListViewThemeData;
/// {@template channel_list_view_theme_data}
/// A style that overrides the default appearance of [ChannelListView]s when
/// used with [ChannelListViewTheme] or with the overall [StreamChatTheme]'s
/// used with [StreamChannelListViewTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.channelListViewTheme].
///
/// See also:
///
/// * [ChannelListViewTheme], the theme which is configured with this class.
/// * [StreamChannelListViewTheme], the theme which is configured with this class.
/// * [StreamChatThemeData.channelListViewTheme], which can be used to override
/// the default style for [ChannelListView]s below the overall
/// [StreamChatTheme].
class ChannelListViewThemeData with Diagnosticable {
/// Creates a [ChannelListViewThemeData].
const ChannelListViewThemeData({
/// {@endtemplate}
class StreamChannelListViewThemeData with Diagnosticable {
/// Creates a [StreamChannelListViewThemeData].
const StreamChannelListViewThemeData({
this.backgroundColor,
});
/// The color of the [ChannelListView] background.
final Color? backgroundColor;
/// Copies this [ChannelListViewThemeData] to another.
ChannelListViewThemeData copyWith({
/// Copies this [StreamChannelListViewThemeData] to another.
StreamChannelListViewThemeData copyWith({
Color? backgroundColor,
}) =>
ChannelListViewThemeData(
StreamChannelListViewThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
);
/// Linearly interpolate between two [ChannelListViewThemeData] themes.
/// Linearly interpolate between two [StreamChannelListViewThemeData] themes.
///
/// All the properties must be non-null.
ChannelListViewThemeData lerp(
ChannelListViewThemeData a,
ChannelListViewThemeData b,
StreamChannelListViewThemeData lerp(
StreamChannelListViewThemeData a,
StreamChannelListViewThemeData b,
double t,
) =>
ChannelListViewThemeData(
StreamChannelListViewThemeData(
backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t),
);
/// Merges one [ChannelListViewThemeData] with another.
ChannelListViewThemeData merge(ChannelListViewThemeData? other) {
/// Merges one [StreamChannelListViewThemeData] with another.
StreamChannelListViewThemeData merge(StreamChannelListViewThemeData? other) {
if (other == null) return this;
return copyWith(
backgroundColor: other.backgroundColor,
@@ -96,7 +108,7 @@ class ChannelListViewThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ChannelListViewThemeData &&
other is StreamChannelListViewThemeData &&
runtimeType == other.runtimeType &&
backgroundColor == other.backgroundColor;
@@ -3,27 +3,33 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
import 'package:stream_chat_flutter/src/theme/avatar_theme.dart';
/// {@macro channel_preview_theme}
@Deprecated("Use 'StreamChannelPreviewTheme' instead")
typedef ChannelPreviewTheme = StreamChannelPreviewTheme;
/// {@template channel_preview_theme}
/// Overrides the default style of [ChannelPreview] descendants.
///
/// See also:
///
/// * [ChannelPreviewThemeData], which is used to configure this theme.
class ChannelPreviewTheme extends InheritedTheme {
/// Creates a [ChannelPreviewTheme].
/// * [StreamChannelPreviewThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamChannelPreviewTheme extends InheritedTheme {
/// Creates a [StreamChannelPreviewTheme].
///
/// The [data] parameter must not be null.
const ChannelPreviewTheme({
const StreamChannelPreviewTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final ChannelPreviewThemeData data;
final StreamChannelPreviewThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [ChannelPreviewTheme] widget, then
/// If there is no enclosing [StreamChannelPreviewTheme] widget, then
/// [StreamChatThemeData.channelPreviewTheme] is used.
///
/// Typical usage is as follows:
@@ -31,34 +37,40 @@ class ChannelPreviewTheme extends InheritedTheme {
/// ```dart
/// final theme = ChannelPreviewTheme.of(context);
/// ```
static ChannelPreviewThemeData of(BuildContext context) {
static StreamChannelPreviewThemeData of(BuildContext context) {
final channelPreviewTheme =
context.dependOnInheritedWidgetOfExactType<ChannelPreviewTheme>();
context.dependOnInheritedWidgetOfExactType<StreamChannelPreviewTheme>();
return channelPreviewTheme?.data ??
StreamChatTheme.of(context).channelPreviewTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
ChannelPreviewTheme(data: data, child: child);
StreamChannelPreviewTheme(data: data, child: child);
@override
bool updateShouldNotify(ChannelPreviewTheme oldWidget) =>
bool updateShouldNotify(StreamChannelPreviewTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro channel_preview_theme_data}
@Deprecated("Use 'StreamChannelPreviewThemeData' instead")
typedef ChannelPreviewThemeData = StreamChannelPreviewThemeData;
/// {@template channel_preview_theme_data}
/// A style that overrides the default appearance of [ChannelPreview]s when used
/// with [ChannelPreviewTheme] or with the overall [StreamChatTheme]'s
/// with [StreamChannelPreviewTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.channelPreviewTheme].
///
/// See also:
///
/// * [ChannelPreviewTheme], the theme which is configured with this class.
/// * [StreamChannelPreviewTheme], the theme which is configured with this class.
/// * [StreamChatThemeData.channelPreviewTheme], which can be used to override
/// the default style for [ChannelHeader]s below the overall [StreamChatTheme].
class ChannelPreviewThemeData with Diagnosticable {
/// Creates a [ChannelPreviewThemeData].
const ChannelPreviewThemeData({
/// {@endtemplate}
class StreamChannelPreviewThemeData with Diagnosticable {
/// Creates a [StreamChannelPreviewThemeData].
const StreamChannelPreviewThemeData({
this.titleStyle,
this.subtitleStyle,
this.lastMessageAtStyle,
@@ -77,7 +89,7 @@ class ChannelPreviewThemeData with Diagnosticable {
final TextStyle? lastMessageAtStyle;
/// Avatar theme
final AvatarThemeData? avatarTheme;
final StreamAvatarThemeData? avatarTheme;
/// Unread counter color
final Color? unreadCounterColor;
@@ -86,15 +98,15 @@ class ChannelPreviewThemeData with Diagnosticable {
final double? indicatorIconSize;
/// Copy with theme
ChannelPreviewThemeData copyWith({
StreamChannelPreviewThemeData copyWith({
TextStyle? titleStyle,
TextStyle? subtitleStyle,
TextStyle? lastMessageAtStyle,
AvatarThemeData? avatarTheme,
StreamAvatarThemeData? avatarTheme,
Color? unreadCounterColor,
double? indicatorIconSize,
}) =>
ChannelPreviewThemeData(
StreamChannelPreviewThemeData(
titleStyle: titleStyle ?? this.titleStyle,
subtitleStyle: subtitleStyle ?? this.subtitleStyle,
lastMessageAtStyle: lastMessageAtStyle ?? this.lastMessageAtStyle,
@@ -103,15 +115,15 @@ class ChannelPreviewThemeData with Diagnosticable {
indicatorIconSize: indicatorIconSize ?? this.indicatorIconSize,
);
/// Linearly interpolate one [ChannelPreviewThemeData] to another.
ChannelPreviewThemeData lerp(
ChannelPreviewThemeData a,
ChannelPreviewThemeData b,
/// Linearly interpolate one [StreamChannelPreviewThemeData] to another.
StreamChannelPreviewThemeData lerp(
StreamChannelPreviewThemeData a,
StreamChannelPreviewThemeData b,
double t,
) =>
ChannelPreviewThemeData(
avatarTheme:
const AvatarThemeData().lerp(a.avatarTheme!, b.avatarTheme!, t),
StreamChannelPreviewThemeData(
avatarTheme: const StreamAvatarThemeData()
.lerp(a.avatarTheme!, b.avatarTheme!, t),
indicatorIconSize: a.indicatorIconSize,
lastMessageAtStyle:
TextStyle.lerp(a.lastMessageAtStyle, b.lastMessageAtStyle, t),
@@ -122,7 +134,7 @@ class ChannelPreviewThemeData with Diagnosticable {
);
/// Merge with theme
ChannelPreviewThemeData merge(ChannelPreviewThemeData? other) {
StreamChannelPreviewThemeData merge(StreamChannelPreviewThemeData? other) {
if (other == null) return this;
return copyWith(
titleStyle: titleStyle?.merge(other.titleStyle) ?? other.titleStyle,
@@ -138,7 +150,7 @@ class ChannelPreviewThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ChannelPreviewThemeData &&
other is StreamChannelPreviewThemeData &&
runtimeType == other.runtimeType &&
titleStyle == other.titleStyle &&
subtitleStyle == other.subtitleStyle &&
@@ -1,9 +1,15 @@
import 'package:flutter/material.dart';
/// {@macro color_theme}
@Deprecated("Use 'StreamColorTheme' instead")
typedef ColorTheme = StreamColorTheme;
/// {@template color_theme}
/// Theme that holds colors
class ColorTheme {
/// {@endtemplate}
class StreamColorTheme {
/// Initialise with light theme
ColorTheme.light({
StreamColorTheme.light({
this.textHighEmphasis = const Color(0xff000000),
this.textLowEmphasis = const Color(0xff7a7a7a),
this.disabled = const Color(0xffdbdbdb),
@@ -55,7 +61,7 @@ class ColorTheme {
}) : brightness = Brightness.light;
/// Initialise with dark theme
ColorTheme.dark({
StreamColorTheme.dark({
this.textHighEmphasis = const Color(0xffffffff),
this.textLowEmphasis = const Color(0xff7a7a7a),
this.disabled = const Color(0xff2d2f2f),
@@ -169,7 +175,7 @@ class ColorTheme {
final Brightness brightness;
/// Copy with theme
ColorTheme copyWith({
StreamColorTheme copyWith({
Brightness brightness = Brightness.light,
Color? textHighEmphasis,
Color? textLowEmphasis,
@@ -192,7 +198,7 @@ class ColorTheme {
Gradient? bgGradient,
}) =>
brightness == Brightness.light
? ColorTheme.light(
? StreamColorTheme.light(
textHighEmphasis: textHighEmphasis ?? this.textHighEmphasis,
textLowEmphasis: textLowEmphasis ?? this.textLowEmphasis,
disabled: disabled ?? this.disabled,
@@ -213,7 +219,7 @@ class ColorTheme {
overlayDark: overlayDark ?? this.overlayDark,
bgGradient: bgGradient ?? this.bgGradient,
)
: ColorTheme.dark(
: StreamColorTheme.dark(
textHighEmphasis: textHighEmphasis ?? this.textHighEmphasis,
textLowEmphasis: textLowEmphasis ?? this.textLowEmphasis,
disabled: disabled ?? this.disabled,
@@ -236,7 +242,7 @@ class ColorTheme {
);
/// Merge color theme
ColorTheme merge(ColorTheme? other) {
StreamColorTheme merge(StreamColorTheme? other) {
if (other == null) return this;
return copyWith(
textHighEmphasis: other.textHighEmphasis,
@@ -2,27 +2,33 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro gallery_footer_theme}
@Deprecated("Use 'StreamGalleryFooterTheme' instead")
typedef GalleryFooterTheme = StreamGalleryFooterTheme;
/// {@template gallery_footer_theme}
/// Overrides the default style of [GalleryFooter] descendants.
///
/// See also:
///
/// * [GalleryFooterThemeData], which is used to configure this theme.
class GalleryFooterTheme extends InheritedTheme {
/// Creates an [GalleryFooterTheme].
/// * [StreamGalleryFooterThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamGalleryFooterTheme extends InheritedTheme {
/// Creates an [StreamGalleryFooterTheme].
///
/// The [data] parameter must not be null.
const GalleryFooterTheme({
const StreamGalleryFooterTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final GalleryFooterThemeData data;
final StreamGalleryFooterThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [GalleryFooterTheme] widget, then
/// If there is no enclosing [StreamGalleryFooterTheme] widget, then
/// [StreamChatThemeData.galleryFooterTheme] is used.
///
/// Typical usage is as follows:
@@ -30,34 +36,40 @@ class GalleryFooterTheme extends InheritedTheme {
/// ```dart
/// ImageFooterTheme theme = ImageFooterTheme.of(context);
/// ```
static GalleryFooterThemeData of(BuildContext context) {
static StreamGalleryFooterThemeData of(BuildContext context) {
final imageFooterTheme =
context.dependOnInheritedWidgetOfExactType<GalleryFooterTheme>();
context.dependOnInheritedWidgetOfExactType<StreamGalleryFooterTheme>();
return imageFooterTheme?.data ??
StreamChatTheme.of(context).galleryFooterTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
GalleryFooterTheme(data: data, child: child);
StreamGalleryFooterTheme(data: data, child: child);
@override
bool updateShouldNotify(GalleryFooterTheme oldWidget) =>
bool updateShouldNotify(StreamGalleryFooterTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro gallery_footer_theme_data}
@Deprecated("Use 'StreamGalleryFooterThemeData' instead")
typedef GalleryFooterThemeData = StreamGalleryFooterThemeData;
/// {@template gallery_footer_theme_data}
/// A style that overrides the default appearance of [GalleryFooter]s when used
/// with [GalleryFooterTheme] or with the overall [StreamChatTheme]'s
/// with [StreamGalleryFooterTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.galleryFooterTheme].
///
/// See also:
///
/// * [GalleryFooterTheme], the theme which is configured with this class.
/// * [StreamGalleryFooterTheme], the theme which is configured with this class.
/// * [StreamChatThemeData.galleryFooterTheme], which can be used to override
/// the default style for [GalleryFooter]s below the overall [StreamChatTheme].
class GalleryFooterThemeData with Diagnosticable {
/// Creates an [GalleryFooterThemeData].
const GalleryFooterThemeData({
/// {@endtemplate}
class StreamGalleryFooterThemeData with Diagnosticable {
/// Creates an [StreamGalleryFooterThemeData].
const StreamGalleryFooterThemeData({
this.backgroundColor,
this.shareIconColor,
this.titleTextStyle,
@@ -108,8 +120,8 @@ class GalleryFooterThemeData with Diagnosticable {
/// Defaults to [ColorTheme.textHighEmphasis].
final Color? bottomSheetCloseIconColor;
/// Copies this [GalleryFooterThemeData] to another.
GalleryFooterThemeData copyWith({
/// Copies this [StreamGalleryFooterThemeData] to another.
StreamGalleryFooterThemeData copyWith({
Color? backgroundColor,
Color? shareIconColor,
TextStyle? titleTextStyle,
@@ -119,7 +131,7 @@ class GalleryFooterThemeData with Diagnosticable {
TextStyle? bottomSheetPhotosTextStyle,
Color? bottomSheetCloseIconColor,
}) =>
GalleryFooterThemeData(
StreamGalleryFooterThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
shareIconColor: shareIconColor ?? this.shareIconColor,
titleTextStyle: titleTextStyle ?? this.titleTextStyle,
@@ -137,12 +149,12 @@ class GalleryFooterThemeData with Diagnosticable {
/// Linearly interpolate between two [GalleryFooter] themes.
///
/// All the properties must be non-null.
GalleryFooterThemeData lerp(
GalleryFooterThemeData a,
GalleryFooterThemeData b,
StreamGalleryFooterThemeData lerp(
StreamGalleryFooterThemeData a,
StreamGalleryFooterThemeData b,
double t,
) =>
GalleryFooterThemeData(
StreamGalleryFooterThemeData(
backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t),
shareIconColor: Color.lerp(a.shareIconColor, b.shareIconColor, t),
titleTextStyle: TextStyle.lerp(a.titleTextStyle, b.titleTextStyle, t),
@@ -167,8 +179,8 @@ class GalleryFooterThemeData with Diagnosticable {
),
);
/// Merges one [GalleryFooterThemeData] with another.
GalleryFooterThemeData merge(GalleryFooterThemeData? other) {
/// Merges one [StreamGalleryFooterThemeData] with another.
StreamGalleryFooterThemeData merge(StreamGalleryFooterThemeData? other) {
if (other == null) return this;
return copyWith(
backgroundColor: other.backgroundColor,
@@ -185,7 +197,7 @@ class GalleryFooterThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is GalleryFooterThemeData &&
other is StreamGalleryFooterThemeData &&
runtimeType == other.runtimeType &&
backgroundColor == other.backgroundColor &&
shareIconColor == other.shareIconColor &&
@@ -2,27 +2,33 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro gallery_header_them}
@Deprecated("Use 'StreamGalleryHeaderTheme' instead")
typedef GalleryHeaderTheme = StreamGalleryHeaderTheme;
/// {@template gallery_header_theme}
/// Overrides the default style of [GalleryHeader] descendants.
///
/// See also:
///
/// * [GalleryHeaderThemeData], which is used to configure this theme.
class GalleryHeaderTheme extends InheritedTheme {
/// Creates a [GalleryHeaderTheme].
/// * [StreamGalleryHeaderThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamGalleryHeaderTheme extends InheritedTheme {
/// Creates a [StreamGalleryHeaderTheme].
///
/// The [data] parameter must not be null.
const GalleryHeaderTheme({
const StreamGalleryHeaderTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final GalleryHeaderThemeData data;
final StreamGalleryHeaderThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [GalleryHeaderTheme] widget, then
/// If there is no enclosing [StreamGalleryHeaderTheme] widget, then
/// [StreamChatThemeData.galleryHeaderTheme] is used.
///
/// Typical usage is as follows:
@@ -30,34 +36,40 @@ class GalleryHeaderTheme extends InheritedTheme {
/// ```dart
/// ImageHeaderTheme theme = ImageHeaderTheme.of(context);
/// ```
static GalleryHeaderThemeData of(BuildContext context) {
static StreamGalleryHeaderThemeData of(BuildContext context) {
final galleryHeaderTheme =
context.dependOnInheritedWidgetOfExactType<GalleryHeaderTheme>();
context.dependOnInheritedWidgetOfExactType<StreamGalleryHeaderTheme>();
return galleryHeaderTheme?.data ??
StreamChatTheme.of(context).galleryHeaderTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
GalleryHeaderTheme(data: data, child: child);
StreamGalleryHeaderTheme(data: data, child: child);
@override
bool updateShouldNotify(GalleryHeaderTheme oldWidget) =>
bool updateShouldNotify(StreamGalleryHeaderTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro gallery_header_theme_data}
@Deprecated("Use 'StreamGalleryHeaderThemeData' instead")
typedef GalleryHeaderThemeData = StreamGalleryHeaderThemeData;
/// {@template gallery_header_theme_data}
/// A style that overrides the default appearance of [GalleryHeader]s when used
/// with [GalleryHeaderTheme] or with the overall [StreamChatTheme]'s
/// with [StreamGalleryHeaderTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.galleryHeaderTheme].
///
/// See also:
///
/// * [GalleryHeaderTheme], the theme which is configured with this class.
/// * [StreamGalleryHeaderTheme], the theme which is configured with this class.
/// * [StreamChatThemeData.galleryHeaderTheme], which can be used to override
/// the default style for [GalleryHeader]s below the overall [StreamChatTheme].
class GalleryHeaderThemeData with Diagnosticable {
/// Creates an [GalleryHeaderThemeData].
const GalleryHeaderThemeData({
/// {@endtemplate}
class StreamGalleryHeaderThemeData with Diagnosticable {
/// Creates an [StreamGalleryHeaderThemeData].
const StreamGalleryHeaderThemeData({
this.closeButtonColor,
this.backgroundColor,
this.iconMenuPointColor,
@@ -92,8 +104,8 @@ class GalleryHeaderThemeData with Diagnosticable {
///
final Color? bottomSheetBarrierColor;
/// Copies this [GalleryHeaderThemeData] to another.
GalleryHeaderThemeData copyWith({
/// Copies this [StreamGalleryHeaderThemeData] to another.
StreamGalleryHeaderThemeData copyWith({
Color? closeButtonColor,
Color? backgroundColor,
Color? iconMenuPointColor,
@@ -101,7 +113,7 @@ class GalleryHeaderThemeData with Diagnosticable {
TextStyle? subtitleTextStyle,
Color? bottomSheetBarrierColor,
}) =>
GalleryHeaderThemeData(
StreamGalleryHeaderThemeData(
closeButtonColor: closeButtonColor ?? this.closeButtonColor,
backgroundColor: backgroundColor ?? this.backgroundColor,
iconMenuPointColor: iconMenuPointColor ?? this.iconMenuPointColor,
@@ -114,12 +126,12 @@ class GalleryHeaderThemeData with Diagnosticable {
/// Linearly interpolate between two [GalleryHeader] themes.
///
/// All the properties must be non-null.
GalleryHeaderThemeData lerp(
GalleryHeaderThemeData a,
GalleryHeaderThemeData b,
StreamGalleryHeaderThemeData lerp(
StreamGalleryHeaderThemeData a,
StreamGalleryHeaderThemeData b,
double t,
) =>
GalleryHeaderThemeData(
StreamGalleryHeaderThemeData(
closeButtonColor: Color.lerp(a.closeButtonColor, b.closeButtonColor, t),
backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t),
iconMenuPointColor:
@@ -131,8 +143,8 @@ class GalleryHeaderThemeData with Diagnosticable {
Color.lerp(a.bottomSheetBarrierColor, b.bottomSheetBarrierColor, t),
);
/// Merges one [GalleryHeaderThemeData] with the another
GalleryHeaderThemeData merge(GalleryHeaderThemeData? other) {
/// Merges one [StreamGalleryHeaderThemeData] with the another
StreamGalleryHeaderThemeData merge(StreamGalleryHeaderThemeData? other) {
if (other == null) return this;
return copyWith(
closeButtonColor: other.closeButtonColor,
@@ -147,7 +159,7 @@ class GalleryHeaderThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is GalleryHeaderThemeData &&
other is StreamGalleryHeaderThemeData &&
runtimeType == other.runtimeType &&
closeButtonColor == other.closeButtonColor &&
backgroundColor == other.backgroundColor &&
@@ -5,27 +5,33 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro message_input_theme}
@Deprecated("Use 'StreamMessageInputTheme' instead")
typedef MessageInputTheme = StreamMessageInputTheme;
/// {@template message_input_theme}
/// Overrides the default style of [MessageInput] descendants.
///
/// See also:
///
/// * [MessageInputThemeData], which is used to configure this theme.
class MessageInputTheme extends InheritedTheme {
/// Creates a [MessageInputTheme].
/// * [StreamMessageInputThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamMessageInputTheme extends InheritedTheme {
/// Creates a [StreamMessageInputTheme].
///
/// The [data] parameter must not be null.
const MessageInputTheme({
const StreamMessageInputTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final MessageInputThemeData data;
final StreamMessageInputThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [MessageInputTheme] widget, then
/// If there is no enclosing [StreamMessageInputTheme] widget, then
/// [StreamChatThemeData.messageInputTheme] is used.
///
/// Typical usage is as follows:
@@ -33,28 +39,34 @@ class MessageInputTheme extends InheritedTheme {
/// ```dart
/// final theme = MessageInputTheme.of(context);
/// ```
static MessageInputThemeData of(BuildContext context) {
static StreamMessageInputThemeData of(BuildContext context) {
final messageInputTheme =
context.dependOnInheritedWidgetOfExactType<MessageInputTheme>();
context.dependOnInheritedWidgetOfExactType<StreamMessageInputTheme>();
return messageInputTheme?.data ??
StreamChatTheme.of(context).messageInputTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
MessageInputTheme(data: data, child: child);
StreamMessageInputTheme(data: data, child: child);
@override
bool updateShouldNotify(MessageInputTheme oldWidget) =>
bool updateShouldNotify(StreamMessageInputTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro message_input_theme_data}
@Deprecated("Use 'StreamMessageInputThemeData' instead")
typedef MessageInputThemeData = StreamMessageInputThemeData;
/// {@template message_input_theme_data}
/// A style that overrides the default appearance of [MessageInput] widgets
/// when used with [MessageInputTheme] or with the overall [StreamChatTheme]'s
/// when used with [StreamMessageInputTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.messageInputTheme].
class MessageInputThemeData with Diagnosticable {
/// Creates a [MessageInputThemeData].
const MessageInputThemeData({
/// {@endtemplate}
class StreamMessageInputThemeData with Diagnosticable {
/// Creates a [StreamMessageInputThemeData].
const StreamMessageInputThemeData({
this.sendAnimationDuration,
this.actionButtonColor,
this.sendButtonColor,
@@ -121,8 +133,8 @@ class MessageInputThemeData with Diagnosticable {
/// Shadow for the [MessageInput] widget
final BoxShadow? shadow;
/// Returns a new [MessageInputThemeData] replacing some of its properties
MessageInputThemeData copyWith({
/// Returns a new [StreamMessageInputThemeData] replacing some of its properties
StreamMessageInputThemeData copyWith({
Duration? sendAnimationDuration,
Color? inputBackgroundColor,
Color? actionButtonColor,
@@ -140,7 +152,7 @@ class MessageInputThemeData with Diagnosticable {
double? elevation,
BoxShadow? shadow,
}) =>
MessageInputThemeData(
StreamMessageInputThemeData(
sendAnimationDuration:
sendAnimationDuration ?? this.sendAnimationDuration,
inputBackgroundColor: inputBackgroundColor ?? this.inputBackgroundColor,
@@ -161,13 +173,13 @@ class MessageInputThemeData with Diagnosticable {
shadow: shadow ?? this.shadow,
);
/// Linearly interpolate from one [MessageInputThemeData] to another.
MessageInputThemeData lerp(
MessageInputThemeData a,
MessageInputThemeData b,
/// Linearly interpolate from one [StreamMessageInputThemeData] to another.
StreamMessageInputThemeData lerp(
StreamMessageInputThemeData a,
StreamMessageInputThemeData b,
double t,
) =>
MessageInputThemeData(
StreamMessageInputThemeData(
actionButtonColor:
Color.lerp(a.actionButtonColor, b.actionButtonColor, t),
actionButtonIdleColor:
@@ -194,8 +206,8 @@ class MessageInputThemeData with Diagnosticable {
shadow: BoxShadow.lerp(a.shadow, b.shadow, t),
);
/// Merges [this] [MessageInputThemeData] with the [other]
MessageInputThemeData merge(MessageInputThemeData? other) {
/// Merges [this] [StreamMessageInputThemeData] with the [other]
StreamMessageInputThemeData merge(StreamMessageInputThemeData? other) {
if (other == null) return this;
return copyWith(
sendAnimationDuration: other.sendAnimationDuration,
@@ -222,7 +234,7 @@ class MessageInputThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is MessageInputThemeData &&
other is StreamMessageInputThemeData &&
runtimeType == other.runtimeType &&
sendAnimationDuration == other.sendAnimationDuration &&
sendButtonColor == other.sendButtonColor &&
@@ -2,27 +2,33 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro message_list_view_theme}
@Deprecated("Use 'StreamMessageListViewTheme' instead")
typedef MessageListViewTheme = StreamMessageListViewTheme;
/// {@template message_list_view_theme}
/// Overrides the default style of [MessageListView] descendants.
///
/// See also:
///
/// * [MessageListViewThemeData], which is used to configure this theme.
class MessageListViewTheme extends InheritedTheme {
/// Creates a [MessageListViewTheme].
/// * [StreamMessageListViewThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamMessageListViewTheme extends InheritedTheme {
/// Creates a [StreamMessageListViewTheme].
///
/// The [data] parameter must not be null.
const MessageListViewTheme({
const StreamMessageListViewTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final MessageListViewThemeData data;
final StreamMessageListViewThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [MessageListViewTheme] widget, then
/// If there is no enclosing [StreamMessageListViewTheme] widget, then
/// [StreamChatThemeData.messageListViewTheme] is used.
///
/// Typical usage is as follows:
@@ -30,35 +36,41 @@ class MessageListViewTheme extends InheritedTheme {
/// ```dart
/// MessageListViewTheme theme = MessageListViewTheme.of(context);
/// ```
static MessageListViewThemeData of(BuildContext context) {
final messageListViewTheme =
context.dependOnInheritedWidgetOfExactType<MessageListViewTheme>();
static StreamMessageListViewThemeData of(BuildContext context) {
final messageListViewTheme = context
.dependOnInheritedWidgetOfExactType<StreamMessageListViewTheme>();
return messageListViewTheme?.data ??
StreamChatTheme.of(context).messageListViewTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
MessageListViewTheme(data: data, child: child);
StreamMessageListViewTheme(data: data, child: child);
@override
bool updateShouldNotify(MessageListViewTheme oldWidget) =>
bool updateShouldNotify(StreamMessageListViewTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro message_list_view_theme_data}
@Deprecated("Use 'StreamMessageListViewThemeData' instead")
typedef MessageListViewThemeData = StreamMessageListViewThemeData;
/// {@template message_list_view_theme_data}
/// A style that overrides the default appearance of [MessageListView]s when
/// used with [MessageListViewTheme] or with the overall [StreamChatTheme]'s
/// used with [StreamMessageListViewTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.messageListViewTheme].
///
/// See also:
///
/// * [MessageListViewTheme], the theme which is configured with this class.
/// * [StreamMessageListViewTheme], the theme which is configured with this class.
/// * [StreamChatThemeData.messageListViewTheme], which can be used to override
/// the default style for [MessageListView]s below the overall
/// [StreamChatTheme].
class MessageListViewThemeData with Diagnosticable {
/// Creates a [MessageListViewThemeData].
const MessageListViewThemeData({
/// {@endtemplate}
class StreamMessageListViewThemeData with Diagnosticable {
/// Creates a [StreamMessageListViewThemeData].
const StreamMessageListViewThemeData({
this.backgroundColor,
this.backgroundImage,
});
@@ -69,12 +81,12 @@ class MessageListViewThemeData with Diagnosticable {
/// The image of the [MessageListView] background.
final DecorationImage? backgroundImage;
/// Copies this [MessageListViewThemeData] to another.
MessageListViewThemeData copyWith({
/// Copies this [StreamMessageListViewThemeData] to another.
StreamMessageListViewThemeData copyWith({
Color? backgroundColor,
DecorationImage? backgroundImage,
}) =>
MessageListViewThemeData(
StreamMessageListViewThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
backgroundImage: backgroundImage ?? this.backgroundImage,
);
@@ -82,18 +94,18 @@ class MessageListViewThemeData with Diagnosticable {
/// Linearly interpolate between two [MessageListView] themes.
///
/// All the properties must be non-null.
MessageListViewThemeData lerp(
MessageListViewThemeData a,
MessageListViewThemeData b,
StreamMessageListViewThemeData lerp(
StreamMessageListViewThemeData a,
StreamMessageListViewThemeData b,
double t,
) =>
MessageListViewThemeData(
StreamMessageListViewThemeData(
backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t),
backgroundImage: t < 0.5 ? a.backgroundImage : b.backgroundImage,
);
/// Merges one [MessageListViewThemeData] with another.
MessageListViewThemeData merge(MessageListViewThemeData? other) {
/// Merges one [StreamMessageListViewThemeData] with another.
StreamMessageListViewThemeData merge(StreamMessageListViewThemeData? other) {
if (other == null) return this;
return copyWith(
backgroundColor: other.backgroundColor,
@@ -104,7 +116,7 @@ class MessageListViewThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is MessageListViewThemeData &&
other is StreamMessageListViewThemeData &&
runtimeType == other.runtimeType &&
backgroundColor == other.backgroundColor &&
backgroundImage == other.backgroundImage;
@@ -2,23 +2,29 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro message_search_list_view_theme}
@Deprecated("Use 'StreamMessageSearchListViewTheme' instead")
typedef MessageSearchListViewTheme = StreamMessageSearchListViewTheme;
/// {@template message_search_list_view_theme}
/// Overrides the default style of [MessageSearchListView] descendants.
///
/// See also:
///
/// * [UserListViewThemeData], which is used to configure this theme.
class MessageSearchListViewTheme extends InheritedTheme {
/// {@endtemplate}
class StreamMessageSearchListViewTheme extends InheritedTheme {
/// Creates a [UserListViewTheme].
///
/// The [data] parameter must not be null.
const MessageSearchListViewTheme({
const StreamMessageSearchListViewTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final MessageSearchListViewThemeData data;
final StreamMessageSearchListViewThemeData data;
/// The closest instance of this class that encloses the given context.
///
@@ -30,64 +36,72 @@ class MessageSearchListViewTheme extends InheritedTheme {
/// ```dart
/// MessageSearchListViewTheme theme = MessageSearchListViewTheme.of(context);
/// ```
static MessageSearchListViewThemeData of(BuildContext context) {
static StreamMessageSearchListViewThemeData of(BuildContext context) {
final messageSearchListViewTheme = context
.dependOnInheritedWidgetOfExactType<MessageSearchListViewTheme>();
.dependOnInheritedWidgetOfExactType<StreamMessageSearchListViewTheme>();
return messageSearchListViewTheme?.data ??
StreamChatTheme.of(context).messageSearchListViewTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
MessageSearchListViewTheme(data: data, child: child);
StreamMessageSearchListViewTheme(data: data, child: child);
@override
bool updateShouldNotify(MessageSearchListViewTheme oldWidget) =>
bool updateShouldNotify(StreamMessageSearchListViewTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro message_search_list_view_theme_data}
@Deprecated("Use 'StreamMessageSearchListViewThemeData' instead")
typedef MessageSearchListViewThemeData = StreamMessageSearchListViewThemeData;
/// {@macro message_search_list_view_theme_data}
/// A style that overrides the default appearance of [MessageSearchListView]s
/// when used with [MessageSearchListView] or with the overall
/// [StreamChatTheme]'s [StreamChatThemeData.messageSearchListViewTheme].
///
/// See also:
///
/// * [MessageSearchListViewTheme], the theme which is configured with this
/// * [StreamMessageSearchListViewTheme], the theme which is configured with this
/// class.
/// * [StreamChatThemeData.messageSearchListViewTheme], which can be used to
/// override the default style for [UserListView]s below the overall
/// [StreamChatTheme].
class MessageSearchListViewThemeData with Diagnosticable {
/// Creates a [MessageSearchListViewThemeData].
const MessageSearchListViewThemeData({
/// {@endtemplate}
class StreamMessageSearchListViewThemeData with Diagnosticable {
/// Creates a [StreamMessageSearchListViewThemeData].
const StreamMessageSearchListViewThemeData({
this.backgroundColor,
});
/// The color of the [MessageSearchListView] background.
final Color? backgroundColor;
/// Copies this [MessageSearchListViewThemeData] to another.
MessageSearchListViewThemeData copyWith({
/// Copies this [StreamMessageSearchListViewThemeData] to another.
StreamMessageSearchListViewThemeData copyWith({
Color? backgroundColor,
}) =>
MessageSearchListViewThemeData(
StreamMessageSearchListViewThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
);
/// Linearly interpolate between two [UserListViewThemeData] themes.
///
/// All the properties must be non-null.
MessageSearchListViewThemeData lerp(
MessageSearchListViewThemeData a,
MessageSearchListViewThemeData b,
StreamMessageSearchListViewThemeData lerp(
StreamMessageSearchListViewThemeData a,
StreamMessageSearchListViewThemeData b,
double t,
) =>
MessageSearchListViewThemeData(
StreamMessageSearchListViewThemeData(
backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t),
);
/// Merges one [MessageSearchListViewThemeData] with another.
MessageSearchListViewThemeData merge(MessageSearchListViewThemeData? other) {
/// Merges one [StreamMessageSearchListViewThemeData] with another.
StreamMessageSearchListViewThemeData merge(
StreamMessageSearchListViewThemeData? other,
) {
if (other == null) return this;
return copyWith(
backgroundColor: other.backgroundColor,
@@ -97,7 +111,7 @@ class MessageSearchListViewThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is MessageSearchListViewThemeData &&
other is StreamMessageSearchListViewThemeData &&
runtimeType == other.runtimeType &&
backgroundColor == other.backgroundColor;
@@ -2,11 +2,17 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/theme/avatar_theme.dart';
/// {@macro message_theme_data}
@Deprecated("Use 'StreamMessageThemeData' instead")
typedef MessageThemeData = StreamMessageThemeData;
/// {@template message_theme_data}
/// Class for getting message theme
/// {@endtemplate}
// ignore: prefer-match-file-name
class MessageThemeData with Diagnosticable {
/// Creates a [MessageThemeData].
const MessageThemeData({
class StreamMessageThemeData with Diagnosticable {
/// Creates a [StreamMessageThemeData].
const StreamMessageThemeData({
this.repliesStyle,
this.messageTextStyle,
this.messageAuthorStyle,
@@ -52,13 +58,13 @@ class MessageThemeData with Diagnosticable {
final Color? reactionsMaskColor;
/// Theme of the avatar
final AvatarThemeData? avatarTheme;
final StreamAvatarThemeData? avatarTheme;
/// Background color for messages with url attachments.
final Color? linkBackgroundColor;
/// Copy with a theme
MessageThemeData copyWith({
StreamMessageThemeData copyWith({
TextStyle? messageTextStyle,
TextStyle? messageAuthorStyle,
TextStyle? messageLinksStyle,
@@ -66,13 +72,13 @@ class MessageThemeData with Diagnosticable {
TextStyle? repliesStyle,
Color? messageBackgroundColor,
Color? messageBorderColor,
AvatarThemeData? avatarTheme,
StreamAvatarThemeData? avatarTheme,
Color? reactionsBackgroundColor,
Color? reactionsBorderColor,
Color? reactionsMaskColor,
Color? linkBackgroundColor,
}) =>
MessageThemeData(
StreamMessageThemeData(
messageTextStyle: messageTextStyle ?? this.messageTextStyle,
messageAuthorStyle: messageAuthorStyle ?? this.messageAuthorStyle,
messageLinksStyle: messageLinksStyle ?? this.messageLinksStyle,
@@ -89,11 +95,15 @@ class MessageThemeData with Diagnosticable {
linkBackgroundColor: linkBackgroundColor ?? this.linkBackgroundColor,
);
/// Linearly interpolate from one [MessageThemeData] to another.
MessageThemeData lerp(MessageThemeData a, MessageThemeData b, double t) =>
MessageThemeData(
avatarTheme:
const AvatarThemeData().lerp(a.avatarTheme!, b.avatarTheme!, t),
/// Linearly interpolate from one [StreamMessageThemeData] to another.
StreamMessageThemeData lerp(
StreamMessageThemeData a,
StreamMessageThemeData b,
double t,
) =>
StreamMessageThemeData(
avatarTheme: const StreamAvatarThemeData()
.lerp(a.avatarTheme!, b.avatarTheme!, t),
createdAtStyle: TextStyle.lerp(a.createdAtStyle, b.createdAtStyle, t),
messageAuthorStyle:
TextStyle.lerp(a.messageAuthorStyle, b.messageAuthorStyle, t),
@@ -120,7 +130,7 @@ class MessageThemeData with Diagnosticable {
);
/// Merge with a theme
MessageThemeData merge(MessageThemeData? other) {
StreamMessageThemeData merge(StreamMessageThemeData? other) {
if (other == null) return this;
return copyWith(
messageTextStyle: messageTextStyle?.merge(other.messageTextStyle) ??
@@ -146,7 +156,7 @@ class MessageThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is MessageThemeData &&
other is StreamMessageThemeData &&
runtimeType == other.runtimeType &&
messageTextStyle == other.messageTextStyle &&
messageAuthorStyle == other.messageAuthorStyle &&
@@ -1,9 +1,15 @@
import 'package:flutter/material.dart';
/// {@macro text_theme}
@Deprecated("Use 'StreamTextTheme' instead")
typedef TextTheme = StreamTextTheme;
/// {@template text_theme}
/// Class for holding text theme
class TextTheme {
/// {@endtemplate}
class StreamTextTheme {
/// Initialise light text theme
TextTheme.light({
StreamTextTheme.light({
this.title = const TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
@@ -46,7 +52,7 @@ class TextTheme {
});
/// Initialise with dark theme
TextTheme.dark({
StreamTextTheme.dark({
this.title = const TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
@@ -113,7 +119,7 @@ class TextTheme {
final TextStyle captionBold;
/// Copy with theme
TextTheme copyWith({
StreamTextTheme copyWith({
Brightness brightness = Brightness.light,
TextStyle? body,
TextStyle? title,
@@ -125,7 +131,7 @@ class TextTheme {
TextStyle? captionBold,
}) =>
brightness == Brightness.light
? TextTheme.light(
? StreamTextTheme.light(
body: body ?? this.body,
title: title ?? this.title,
headlineBold: headlineBold ?? this.headlineBold,
@@ -135,7 +141,7 @@ class TextTheme {
footnote: footnote ?? this.footnote,
captionBold: captionBold ?? this.captionBold,
)
: TextTheme.dark(
: StreamTextTheme.dark(
body: body ?? this.body,
title: title ?? this.title,
headlineBold: headlineBold ?? this.headlineBold,
@@ -147,7 +153,7 @@ class TextTheme {
);
/// Merge text theme
TextTheme merge(TextTheme? other) {
StreamTextTheme merge(StreamTextTheme? other) {
if (other == null) return this;
return copyWith(
body: body.merge(other.body),
@@ -2,27 +2,33 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// {@macro user_list_view_theme}
@Deprecated("Use 'StreamUserListViewTheme' instead")
typedef UserListViewTheme = StreamUserListViewTheme;
/// {@template user_list_view_theme}
/// Overrides the default style of [UserListView] descendants.
///
/// See also:
///
/// * [UserListViewThemeData], which is used to configure this theme.
class UserListViewTheme extends InheritedTheme {
/// Creates a [UserListViewTheme].
/// * [StreamUserListViewThemeData], which is used to configure this theme.
/// {@endtemplate}
class StreamUserListViewTheme extends InheritedTheme {
/// Creates a [StreamUserListViewTheme].
///
/// The [data] parameter must not be null.
const UserListViewTheme({
const StreamUserListViewTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final UserListViewThemeData data;
final StreamUserListViewThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [UserListViewTheme] widget, then
/// If there is no enclosing [StreamUserListViewTheme] widget, then
/// [StreamChatThemeData.userListViewTheme] is used.
///
/// Typical usage is as follows:
@@ -30,35 +36,41 @@ class UserListViewTheme extends InheritedTheme {
/// ```dart
/// UserListViewTheme theme = UserListViewTheme.of(context);
/// ```
static UserListViewThemeData of(BuildContext context) {
static StreamUserListViewThemeData of(BuildContext context) {
final userListViewTheme =
context.dependOnInheritedWidgetOfExactType<UserListViewTheme>();
context.dependOnInheritedWidgetOfExactType<StreamUserListViewTheme>();
return userListViewTheme?.data ??
StreamChatTheme.of(context).userListViewTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
UserListViewTheme(data: data, child: child);
StreamUserListViewTheme(data: data, child: child);
@override
bool updateShouldNotify(UserListViewTheme oldWidget) =>
bool updateShouldNotify(StreamUserListViewTheme oldWidget) =>
data != oldWidget.data;
}
/// {@macro user_list_view_theme_data}
@Deprecated("Use 'StreamUserListViewThemeData' instead")
typedef UserListViewThemeData = StreamUserListViewThemeData;
/// {@template user_list_view_theme_data}
/// A style that overrides the default appearance of [UserListView]s when
/// used with [UserListViewTheme] or with the overall [StreamChatTheme]'s
/// used with [StreamUserListViewTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.userListViewTheme].
///
/// See also:
///
/// * [UserListViewTheme], the theme which is configured with this class.
/// * [StreamUserListViewTheme], the theme which is configured with this class.
/// * [StreamChatThemeData.userListViewTheme], which can be used to override
/// the default style for [UserListView]s below the overall
/// [StreamChatTheme].
class UserListViewThemeData with Diagnosticable {
/// Creates a [UserListViewThemeData].
const UserListViewThemeData({
/// {@endtemplate}
class StreamUserListViewThemeData with Diagnosticable {
/// Creates a [StreamUserListViewThemeData].
const StreamUserListViewThemeData({
this.backgroundColor,
});
@@ -66,27 +78,27 @@ class UserListViewThemeData with Diagnosticable {
final Color? backgroundColor;
/// Copies this [ChannelListViewThemeData] to another.
UserListViewThemeData copyWith({
StreamUserListViewThemeData copyWith({
Color? backgroundColor,
}) =>
UserListViewThemeData(
StreamUserListViewThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
);
/// Linearly interpolate between two [UserListViewThemeData] themes.
/// Linearly interpolate between two [StreamUserListViewThemeData] themes.
///
/// All the properties must be non-null.
UserListViewThemeData lerp(
UserListViewThemeData a,
UserListViewThemeData b,
StreamUserListViewThemeData lerp(
StreamUserListViewThemeData a,
StreamUserListViewThemeData b,
double t,
) =>
UserListViewThemeData(
StreamUserListViewThemeData(
backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t),
);
/// Merges one [UserListViewThemeData] with another.
UserListViewThemeData merge(UserListViewThemeData? other) {
/// Merges one [StreamUserListViewThemeData] with another.
StreamUserListViewThemeData merge(StreamUserListViewThemeData? other) {
if (other == null) return this;
return copyWith(
backgroundColor: other.backgroundColor,
@@ -96,7 +108,7 @@ class UserListViewThemeData with Diagnosticable {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is UserListViewThemeData &&
other is StreamUserListViewThemeData &&
runtimeType == other.runtimeType &&
backgroundColor == other.backgroundColor;
@@ -3,6 +3,11 @@ import 'package:flutter/services.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro thread_header}
@Deprecated("Use 'StreamThreadHeader' instead")
typedef ThreadHeader = StreamThreadHeader;
/// {@template thread_header}
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/thread_header.png)
/// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/packages/stream_chat_flutter/screenshots/thread_header_paint.png)
///
@@ -56,9 +61,11 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// The widget components render the ui based on the first ancestor of type
/// [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property.
/// Modify it to change the widget appearance.
class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
/// {@endtemplate}
class StreamThreadHeader extends StatelessWidget
implements PreferredSizeWidget {
/// Instantiate a new ThreadHeader
const ThreadHeader({
const StreamThreadHeader({
Key? key,
required this.parent,
this.showBackButton = true,
@@ -102,12 +109,12 @@ class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
/// if a user is typing in this thread
final bool showTypingIndicator;
/// The background color of this [ThreadHeader].
/// The background color of this [StreamThreadHeader].
final Color? backgroundColor;
@override
Widget build(BuildContext context) {
final channelHeaderTheme = ChannelHeaderTheme.of(context);
final channelHeaderTheme = StreamChannelHeaderTheme.of(context);
final defaultSubtitle = subtitle ??
Row(
@@ -162,7 +169,7 @@ class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
const SizedBox(height: 2),
if (showTypingIndicator)
Align(
child: TypingIndicator(
child: StreamTypingIndicator(
channel: StreamChannel.of(context).channel,
style: channelHeaderTheme.subtitleStyle,
parentId: parent.id,
@@ -3,10 +3,16 @@ import 'package:lottie/lottie.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
/// {@macro typing_indicator}
@Deprecated("Use 'StreamTypingIndicator' instead")
typedef TypingIndicator = StreamTypingIndicator;
/// {@template typing_indicator}
/// Widget to show the current list of typing users
class TypingIndicator extends StatelessWidget {
/// {@endtemplate}
class StreamTypingIndicator extends StatelessWidget {
/// Instantiate a new TypingIndicator
const TypingIndicator({
const StreamTypingIndicator({
Key? key,
this.channel,
this.alternativeWidget,
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro unread_indicator}
@Deprecated("Use 'StreamUnreadIndicator' instead")
typedef UnreadIndicator = StreamUnreadIndicator;
/// {@template unread_indicator}
/// Widget for showing an unread indicator
class UnreadIndicator extends StatelessWidget {
/// Constructor for creating an [UnreadIndicator]
const UnreadIndicator({
/// {@endtemplate}
class StreamUnreadIndicator extends StatelessWidget {
/// Constructor for creating an [StreamUnreadIndicator]
const StreamUnreadIndicator({
Key? key,
this.cid,
}) : super(key: key);
@@ -1,10 +1,16 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro upload_progress_indicator}
@Deprecated("Use 'StreamUploadProgressIndicator' instead")
typedef UploadProgressIndicator = StreamUploadProgressIndicator;
/// {@template upload_progress_indicator}
/// Widget for showing upload progress
class UploadProgressIndicator extends StatelessWidget {
/// Constructor for creating an [UploadProgressIndicator]
const UploadProgressIndicator({
/// {@endtemplate}
class StreamUploadProgressIndicator extends StatelessWidget {
/// Constructor for creating an [StreamUploadProgressIndicator]
const StreamUploadProgressIndicator({
Key? key,
required this.uploaded,
required this.total,
@@ -2,10 +2,16 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro user_avatar}
@Deprecated("Use 'StreamUserAvatar' instead")
typedef UserAvatar = StreamUserAvatar;
/// {@template user_avatar}
/// Widget that displays a user avatar
class UserAvatar extends StatelessWidget {
/// Constructor to create a [UserAvatar]
const UserAvatar({
/// {@endtemplate}
class StreamUserAvatar extends StatelessWidget {
/// Constructor to create a [StreamUserAvatar]
const StreamUserAvatar({
Key? key,
required this.user,
this.constraints,
@@ -2,21 +2,26 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
///
/// {@macro user_item}
@Deprecated("Use 'StreamUserItem' instead")
typedef UserItem = StreamUserItem;
/// {@template user_item}
/// It shows the current [User] preview.
///
/// The widget uses a [StreamBuilder] to render the user information
/// image as soon as it updates.
///
/// Usually you don't use this widget as it's the default user preview used
/// by [UserListView].
/// by [StreamUserListView].
///
/// The widget renders the ui based on the first ancestor of type
/// [StreamChatTheme].
/// Modify it to change the widget appearance.
class UserItem extends StatelessWidget {
/// {@endtemplate}
class StreamUserItem extends StatelessWidget {
/// Instantiate a new UserItem
const UserItem({
const StreamUserItem({
Key? key,
required this.user,
this.onTap,
@@ -38,10 +43,10 @@ class UserItem extends StatelessWidget {
/// The function called when the image is tapped
final void Function(User)? onImageTap;
/// If true the [UserItem] will show a trailing checkmark
/// If true the [StreamUserItem] will show a trailing checkmark
final bool selected;
/// If true the [UserItem] will show the last seen
/// If true the [StreamUserItem] will show the last seen
final bool showLastOnline;
@override
@@ -58,7 +63,7 @@ class UserItem extends StatelessWidget {
onLongPress!(user);
}
},
leading: UserAvatar(
leading: StreamUserAvatar(
user: user,
onTap: (user) {
if (onImageTap != null) {
@@ -8,7 +8,11 @@ typedef UserTapCallback = void Function(User, Widget?);
/// Builder used to create a custom [ListUserItem] from a [User]
typedef UserItemBuilder = Widget Function(BuildContext, User, bool);
///
/// {@macro user_list_view}
@Deprecated("Use 'StreamUserListView' instead")
typedef UserListView = StreamUserListView;
/// {@template user_list_view}
/// It shows the list of current users.
///
/// ```dart
@@ -42,9 +46,10 @@ typedef UserItemBuilder = Widget Function(BuildContext, User, bool);
/// The widget components render the ui based on the first ancestor of
/// type [StreamChatTheme].
/// Modify it to change the widget appearance.
class UserListView extends StatefulWidget {
/// {@endtemplate}
class StreamUserListView extends StatefulWidget {
/// Instantiate a new UserListView
UserListView({
StreamUserListView({
Key? key,
this.filter = const Filter.empty(),
this.sort,
@@ -160,10 +165,10 @@ class UserListView extends StatefulWidget {
final UserListController? userListController;
@override
_UserListViewState createState() => _UserListViewState();
_StreamUserListViewState createState() => _StreamUserListViewState();
}
class _UserListViewState extends State<UserListView>
class _StreamUserListViewState extends State<StreamUserListView>
with WidgetsBindingObserver {
bool get _isListView => widget.crossAxisCount == 1;
@@ -203,7 +208,7 @@ class _UserListViewState extends State<UserListView>
userListController: _userListController,
);
final backgroundColor = UserListViewTheme.of(context).backgroundColor;
final backgroundColor = StreamUserListViewTheme.of(context).backgroundColor;
Widget child;
@@ -332,7 +337,7 @@ class _UserListViewState extends State<UserListView>
key: ValueKey<String>('USER-${user.id}'),
child: widget.userItemBuilder != null
? widget.userItemBuilder!(context, user, selected)
: UserItem(
: StreamUserItem(
user: user,
onTap: (user) => widget.onUserTap!(user, widget.userWidget),
onLongPress: widget.onUserLongPress,
@@ -362,7 +367,7 @@ class _UserListViewState extends State<UserListView>
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
UserAvatar(
StreamUserAvatar(
user: user,
borderRadius: BorderRadius.circular(32),
selected: selected,
@@ -1,12 +1,18 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro user_mention_tile}
@Deprecated("Use 'StreamUserMentionTile' instead")
typedef UserMentionTile = StreamUserMentionTile;
/// {@template user_mention_tile}
/// This widget is used for showing user tiles for mentions
/// Use [title], [subtitle], [leading], [trailing] for
/// substituting widgets in respective positions
class UserMentionTile extends StatelessWidget {
/// Constructor for creating a [UserMentionTile] widget
const UserMentionTile(
/// {@endtemplate}
class StreamUserMentionTile extends StatelessWidget {
/// Constructor for creating a [StreamUserMentionTile] widget
const StreamUserMentionTile(
this.user, {
Key? key,
this.title,
@@ -41,7 +47,7 @@ class UserMentionTile extends StatelessWidget {
width: 16,
),
leading ??
UserAvatar(
StreamUserAvatar(
user: user,
constraints: BoxConstraints.tight(const Size(40, 40)),
),
@@ -6,16 +6,22 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
/// Builder function for building a mention tile.
///
/// Use [UserMentionTile] for the default implementation.
/// Use [StreamUserMentionTile] for the default implementation.
typedef MentionTileBuilder = Widget Function(
BuildContext context,
User user,
);
/// {@macro user_mention_tile}
@Deprecated("Use 'StreamUserMentionsOverlay' instead")
typedef UserMentionsOverlay = StreamUserMentionsOverlay;
/// {@template user_mentions_overlay}
/// Overlay for displaying users that can be mentioned.
class UserMentionsOverlay extends StatefulWidget {
/// Constructor for creating a [UserMentionsOverlay].
UserMentionsOverlay({
/// {@endtemplate}
class StreamUserMentionsOverlay extends StatefulWidget {
/// Constructor for creating a [StreamUserMentionsOverlay].
StreamUserMentionsOverlay({
Key? key,
required this.query,
required this.channel,
@@ -62,10 +68,11 @@ class UserMentionsOverlay extends StatefulWidget {
final void Function(User user)? onMentionUserTap;
@override
_UserMentionsOverlayState createState() => _UserMentionsOverlayState();
_StreamUserMentionsOverlayState createState() =>
_StreamUserMentionsOverlayState();
}
class _UserMentionsOverlayState extends State<UserMentionsOverlay> {
class _StreamUserMentionsOverlayState extends State<StreamUserMentionsOverlay> {
late Future<List<User>> userMentionsFuture;
@override
@@ -75,7 +82,7 @@ class _UserMentionsOverlayState extends State<UserMentionsOverlay> {
}
@override
void didUpdateWidget(covariant UserMentionsOverlay oldWidget) {
void didUpdateWidget(covariant StreamUserMentionsOverlay oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.channel != oldWidget.channel ||
widget.query != oldWidget.query ||
@@ -116,7 +123,7 @@ class _UserMentionsOverlayState extends State<UserMentionsOverlay> {
child: InkWell(
onTap: () => widget.onMentionUserTap?.call(user),
child: widget.mentionsTileBuilder?.call(context, user) ??
UserMentionTile(user),
StreamUserMentionTile(user),
),
);
},
@@ -9,6 +9,7 @@ import 'package:stream_chat_flutter/src/typing_indicator.dart';
import 'package:stream_chat_flutter/src/unread_indicator.dart';
import 'package:stream_chat_flutter/src/v4/stream_channel_avatar.dart';
import 'package:stream_chat_flutter/src/v4/stream_channel_name.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
/// A widget that displays a channel preview.
@@ -131,7 +132,7 @@ class StreamChannelListTile extends StatelessWidget {
final channelState = channel.state!;
final currentUser = channel.client.state.currentUser!;
final channelPreviewTheme = ChannelPreviewTheme.of(context);
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
final leading = this.leading ??
StreamChannelAvatar(
@@ -182,7 +183,7 @@ class StreamChannelListTile extends StatelessWidget {
return const Offstage();
}
return unreadIndicatorBuilder?.call(context) ??
UnreadIndicator(cid: channel.cid);
StreamUnreadIndicator(cid: channel.cid);
},
),
],
@@ -213,7 +214,7 @@ class StreamChannelListTile extends StatelessWidget {
padding: const EdgeInsets.only(right: 4),
child:
sendingIndicatorBuilder?.call(context, lastMessage) ??
SendingIndicator(
StreamSendingIndicator(
message: lastMessage,
size: channelPreviewTheme.indicatorIconSize,
isMessageRead: channelState
@@ -318,7 +319,7 @@ class ChannelListTileSubtitle extends StatelessWidget {
],
);
}
return TypingIndicator(
return StreamTypingIndicator(
channel: channel,
style: textStyle,
alternativeWidget: ChannelLastMessageText(
@@ -359,10 +360,18 @@ class ChannelLastMessageText extends StatelessWidget {
if (lastMessage == null) return const Offstage();
final lastMessageText = lastMessage.text;
final lastMessageText = lastMessage
.translate(channel.client.state.currentUser?.language ?? 'en')
.replaceMentions(linkify: false)
.text;
final lastMessageAttachments = lastMessage.attachments;
final lastMessageMentionedUsers = lastMessage.mentionedUsers;
final mentionedUsersRegex = RegExp(
lastMessageMentionedUsers.map((it) => '@${it.name}').join('|'),
caseSensitive: false,
);
final messageTextParts = [
...lastMessageAttachments.map((it) {
if (it.type == 'image') {
@@ -376,7 +385,11 @@ class ChannelLastMessageText extends StatelessWidget {
? (it.title ?? 'File')
: '${it.title ?? 'File'} , ';
}),
if (lastMessageText != null) lastMessageText,
if (lastMessageText != null)
if (lastMessageMentionedUsers.isNotEmpty)
...mentionedUsersRegex.allMatchesWithSep(lastMessageText)
else
lastMessageText,
];
final fontStyle = (lastMessage.isSystem || lastMessage.isDeleted)
@@ -395,7 +408,7 @@ class ChannelLastMessageText extends StatelessWidget {
if (lastMessageMentionedUsers.isNotEmpty &&
lastMessageMentionedUsers.any((it) => '@${it.name}' == part))
TextSpan(
text: '$part ',
text: part,
style: mentionsTextStyle,
)
else if (lastMessageAttachments.isNotEmpty &&
@@ -403,12 +416,14 @@ class ChannelLastMessageText extends StatelessWidget {
.where((it) => it.title != null)
.any((it) => it.title == part))
TextSpan(
text: '$part ',
style: regularTextStyle,
text: part,
style: regularTextStyle?.copyWith(
fontStyle: FontStyle.italic,
),
)
else
TextSpan(
text: part == messageTextParts.last ? part : '$part ',
text: part,
style: regularTextStyle,
),
];
@@ -422,3 +437,18 @@ class ChannelLastMessageText extends StatelessWidget {
},
);
}
extension _RegExpX on RegExp {
List<String> allMatchesWithSep(String input, [int start = 0]) {
final result = <String>[];
for (final match in allMatches(input, start)) {
result.add(input.substring(start, match.start));
// ignore: cascade_invocations
result.add(match[0]!);
// ignore: parameter_assignments
start = match.end;
}
result.add(input.substring(start));
return result;
}
}
@@ -148,7 +148,7 @@ class StreamChannelAvatar extends StatelessWidget {
return BetterStreamBuilder<User>(
stream: client.currentUserStream.map((it) => it!),
initialData: currentUser,
builder: (context, user) => UserAvatar(
builder: (context, user) => StreamUserAvatar(
borderRadius: borderRadius ?? previewTheme?.borderRadius,
user: user,
constraints: constraints ?? previewTheme?.constraints,
@@ -171,7 +171,7 @@ class StreamChannelAvatar extends StatelessWidget {
),
),
initialData: member,
builder: (context, member) => UserAvatar(
builder: (context, member) => StreamUserAvatar(
borderRadius: borderRadius ?? previewTheme?.borderRadius,
user: member.user!,
constraints: constraints ?? previewTheme?.constraints,
@@ -184,7 +184,7 @@ class StreamChannelAvatar extends StatelessWidget {
}
// Group conversation
return GroupAvatar(
return StreamGroupAvatar(
channel: channel,
members: otherMembers,
borderRadius: borderRadius ?? previewTheme?.borderRadius,
@@ -52,7 +52,7 @@ class StreamChannelInfoBottomSheet extends StatelessWidget {
Widget build(BuildContext context) {
final themeData = StreamChatTheme.of(context);
final colorTheme = themeData.colorTheme;
final channelPreviewTheme = ChannelPreviewTheme.of(context);
final channelPreviewTheme = StreamChannelPreviewTheme.of(context);
final currentUser = channel.client.state.currentUser;
final isOneToOneChannel = channel.isDistinct && channel.memberCount == 2;
@@ -84,7 +84,7 @@ class StreamChannelInfoBottomSheet extends StatelessWidget {
const SizedBox(height: 5),
Center(
// TODO: Refactor ChannelInfo
child: ChannelInfo(
child: StreamChannelInfo(
showTypingIndicator: false,
channel: channel,
textStyle: channelPreviewTheme.subtitleStyle,
@@ -105,7 +105,7 @@ class StreamChannelInfoBottomSheet extends StatelessWidget {
final user = member.user!;
return Column(
children: [
UserAvatar(
StreamUserAvatar(
user: user,
constraints: const BoxConstraints(
maxHeight: 64,
@@ -132,7 +132,7 @@ class StreamChannelInfoBottomSheet extends StatelessWidget {
),
),
const SizedBox(height: 24),
OptionListTile(
StreamOptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.user(
@@ -143,7 +143,7 @@ class StreamChannelInfoBottomSheet extends StatelessWidget {
onTap: onViewInfoTap,
),
if (!isOneToOneChannel)
OptionListTile(
StreamOptionListTile(
title: context.translations.leaveGroupLabel,
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
@@ -154,7 +154,7 @@ class StreamChannelInfoBottomSheet extends StatelessWidget {
onTap: onLeaveChannelTap,
),
if (isOwner)
OptionListTile(
StreamOptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.delete(
@@ -165,7 +165,7 @@ class StreamChannelInfoBottomSheet extends StatelessWidget {
titleColor: colorTheme.accentError,
onTap: onDeleteConversationTap,
),
OptionListTile(
StreamOptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.closeSmall(
@@ -1,8 +1,6 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:synchronized/synchronized.dart';
import 'package:video_compress/video_compress.dart';
import 'package:video_thumbnail/video_thumbnail.dart';
///
@@ -12,32 +10,6 @@ class _IVideoService {
/// Singleton instance of [_IVideoService]
static final _IVideoService instance = _IVideoService._();
final _lock = Lock();
/// compress video from [path]
/// compress video from [path] return [Future<MediaInfo>]
///
/// you can choose its [quality] and [frameRate]
///
/// ## example
/// ```dart
/// final info = await _flutterVideoCompress.compressVideo(
/// file.path,
/// );
/// debugPrint(info.toJson());
/// ```
Future<MediaInfo?> compressVideo(
String path, {
int frameRate = 30,
VideoQuality quality = VideoQuality.DefaultQuality,
}) async =>
_lock.synchronized(
() => VideoCompress.compressVideo(
path,
frameRate: frameRate,
quality: quality,
),
);
/// Generates a thumbnail image data in memory as UInt8List,
/// it can be easily used by Image.memory(...).
@@ -66,5 +38,10 @@ class _IVideoService {
}
/// Get instance of [_IVideoService]
@Deprecated("Use 'StreamVideoService' instead")
// ignore: non_constant_identifier_names
_IVideoService get VideoService => _IVideoService.instance;
/// Get instance of [_IVideoService]
// ignore: non_constant_identifier_names
_IVideoService get StreamVideoService => _IVideoService.instance;
@@ -6,10 +6,16 @@ import 'package:stream_chat_flutter/src/video_service.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:video_thumbnail/video_thumbnail.dart';
/// {@macro video_thumbnail_image}
@Deprecated("Use 'StreamVideoThumbnailImage' instead")
typedef VideoThumbnailImage = StreamVideoThumbnailImage;
/// {@template video_thumbnail_image}
/// Widget for creating video thumbnail image
class VideoThumbnailImage extends StatefulWidget {
/// Constructor for creating [VideoThumbnailImage]
const VideoThumbnailImage({
/// {@endtemplate}
class StreamVideoThumbnailImage extends StatefulWidget {
/// Constructor for creating [StreamVideoThumbnailImage]
const StreamVideoThumbnailImage({
Key? key,
required this.video,
this.width,
@@ -42,16 +48,17 @@ class VideoThumbnailImage extends StatefulWidget {
final WidgetBuilder? placeholderBuilder;
@override
_VideoThumbnailImageState createState() => _VideoThumbnailImageState();
_StreamVideoThumbnailImageState createState() =>
_StreamVideoThumbnailImageState();
}
class _VideoThumbnailImageState extends State<VideoThumbnailImage> {
class _StreamVideoThumbnailImageState extends State<StreamVideoThumbnailImage> {
late Future<Uint8List?> thumbnailFuture;
late StreamChatThemeData _streamChatTheme;
@override
void initState() {
thumbnailFuture = VideoService.generateVideoThumbnail(
thumbnailFuture = StreamVideoService.generateVideoThumbnail(
video: widget.video,
imageFormat: widget.format,
);
@@ -65,9 +72,9 @@ class _VideoThumbnailImageState extends State<VideoThumbnailImage> {
}
@override
void didUpdateWidget(covariant VideoThumbnailImage oldWidget) {
void didUpdateWidget(covariant StreamVideoThumbnailImage oldWidget) {
if (oldWidget.video != widget.video || oldWidget.format != widget.format) {
thumbnailFuture = VideoService.generateVideoThumbnail(
thumbnailFuture = StreamVideoService.generateVideoThumbnail(
video: widget.video,
imageFormat: widget.format,
);
@@ -2,10 +2,16 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// {@macro visible_footnote}
@Deprecated("Use 'StreamVisibleFootnote' instead")
typedef VisibleFootnote = StreamVisibleFootnote;
/// {@template visible_footnote}
/// Widget for displaying a footnote
class VisibleFootnote extends StatelessWidget {
/// Constructor for creating a [VisibleFootnote]
const VisibleFootnote({Key? key}) : super(key: key);
/// {@endtemplate}
class StreamVisibleFootnote extends StatelessWidget {
/// Constructor for creating a [StreamVisibleFootnote]
const StreamVisibleFootnote({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

Some files were not shown because too many files have changed in this diff Show More