diff --git a/example/assets/icon_arrow_right.svg b/example/assets/icon_arrow_right.svg
new file mode 100644
index 00000000..7cfa0c56
--- /dev/null
+++ b/example/assets/icon_arrow_right.svg
@@ -0,0 +1,5 @@
+
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index 595611e8..af3a3d40 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -274,7 +274,7 @@ SPEC CHECKSUMS:
SwiftyGif: e466e86c660d343357ab944a819a101c4127cb40
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
- wakelock: 0d4a70faf8950410735e3f61fb15d517c8a6efc4
+ wakelock: bfc7955c418d0db797614075aabbc58a39ab5107
PODFILE CHECKSUM: eb001256612a59f8f9e4d083ad8b9671e69dd184
diff --git a/example/lib/advanced_options_page.dart b/example/lib/advanced_options_page.dart
index 8a4c79c0..56c9dbf0 100644
--- a/example/lib/advanced_options_page.dart
+++ b/example/lib/advanced_options_page.dart
@@ -17,10 +17,13 @@ class _AdvancedOptionsPageState extends State {
final _formKey = GlobalKey();
final TextEditingController _apiKeyController = TextEditingController();
+ String _apiKeyError;
final TextEditingController _userIdController = TextEditingController();
+ String _userIdError;
final TextEditingController _userTokenController = TextEditingController();
+ String _userTokenError;
final TextEditingController _usernameController = TextEditingController();
@@ -65,17 +68,34 @@ class _AdvancedOptionsPageState extends State {
children: [
TextFormField(
controller: _apiKeyController,
+ onChanged: (_) {
+ if (_apiKeyError != null) {
+ setState(() {
+ _apiKeyError = null;
+ });
+ }
+ },
validator: (value) {
if (value.isEmpty) {
- return 'Please enter the Chat API Key';
+ setState(() {
+ _apiKeyError = 'Please enter the Chat API Key';
+ });
+ return _apiKeyError;
}
return null;
},
+ style: TextStyle(
+ fontSize: 14,
+ color: Colors.black,
+ ),
decoration: InputDecoration(
+ errorStyle: TextStyle(fontSize: 0),
labelStyle: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
- color: Colors.black.withOpacity(.5),
+ color: _apiKeyError != null
+ ? Color(0xffff3742)
+ : Colors.black.withOpacity(.5),
),
border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(8),
@@ -83,7 +103,8 @@ class _AdvancedOptionsPageState extends State {
),
fillColor: Color(0xffF5F5F5),
filled: true,
- labelText: 'Chat API Key',
+ labelText:
+ 'Chat API Key ${_apiKeyError != null ? ':$_apiKeyError' : ''}',
),
textInputAction: TextInputAction.next,
),
@@ -91,18 +112,35 @@ class _AdvancedOptionsPageState extends State {
padding: const EdgeInsets.only(top: 8.0),
child: TextFormField(
controller: _userIdController,
+ onChanged: (_) {
+ if (_userIdError != null) {
+ setState(() {
+ _userIdError = null;
+ });
+ }
+ },
validator: (value) {
if (value.isEmpty) {
- return 'Please enter the User ID';
+ setState(() {
+ _userIdError = 'Please enter the User ID';
+ });
+ return _userIdError;
}
return null;
},
+ style: TextStyle(
+ fontSize: 14,
+ color: Colors.black,
+ ),
textInputAction: TextInputAction.next,
decoration: InputDecoration(
+ errorStyle: TextStyle(fontSize: 0),
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
- color: Colors.black.withOpacity(.5),
+ color: _userIdError != null
+ ? Color(0xffff3742)
+ : Colors.black.withOpacity(.5),
),
border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(8),
@@ -110,26 +148,44 @@ class _AdvancedOptionsPageState extends State {
),
fillColor: Color(0xffF5F5F5),
filled: true,
- labelText: 'User ID',
+ labelText:
+ 'User ID ${_userIdError != null ? ':$_userIdError' : ''}',
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextFormField(
+ onChanged: (_) {
+ if (_userTokenError != null) {
+ setState(() {
+ _userTokenError = null;
+ });
+ }
+ },
controller: _userTokenController,
validator: (value) {
if (value.isEmpty) {
- return 'Please enter the user token';
+ setState(() {
+ _userTokenError = 'Please enter the user token';
+ });
+ return _userTokenError;
}
return null;
},
+ style: TextStyle(
+ fontSize: 14,
+ color: Colors.black,
+ ),
textInputAction: TextInputAction.next,
decoration: InputDecoration(
+ errorStyle: TextStyle(fontSize: 0),
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
- color: Colors.black.withOpacity(.5),
+ color: _userTokenError != null
+ ? Color(0xffff3742)
+ : Colors.black.withOpacity(.5),
),
border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(8),
@@ -137,7 +193,8 @@ class _AdvancedOptionsPageState extends State {
),
fillColor: Color(0xffF5F5F5),
filled: true,
- labelText: 'User Token',
+ labelText:
+ 'User Token ${_userTokenError != null ? ':$_userTokenError' : ''}',
),
),
),
@@ -183,13 +240,13 @@ class _AdvancedOptionsPageState extends State {
if (loading) {
return;
}
- loading = true;
if (_formKey.currentState.validate()) {
final apiKey = _apiKeyController.text;
final userId = _userIdController.text;
final userToken = _userTokenController.text;
final username = _usernameController.text;
+ loading = true;
showDialog(
barrierDismissible: false,
context: context,
@@ -208,7 +265,6 @@ class _AdvancedOptionsPageState extends State {
),
);
- print('CREATE CLIENT');
final client = Client(
apiKey,
logLevel: Level.INFO,
@@ -232,11 +288,9 @@ class _AdvancedOptionsPageState extends State {
errorText = e['message'] ?? errorText;
}
Navigator.pop(context);
- Scaffold.of(context).showSnackBar(
- SnackBar(
- content: Text(errorText),
- ),
- );
+ setState(() {
+ _apiKeyError = errorText;
+ });
loading = false;
await client.disconnect();
return;
diff --git a/example/lib/choose_user_page.dart b/example/lib/choose_user_page.dart
index b5296f8a..fd7d2b6c 100644
--- a/example/lib/choose_user_page.dart
+++ b/example/lib/choose_user_page.dart
@@ -135,20 +135,18 @@ class ChooseUserPage extends StatelessWidget {
token,
);
- await Future.wait([
- secureStorage.write(
- key: kStreamApiKey,
- value: kDefaultStreamApiKey,
- ),
- secureStorage.write(
- key: kStreamUserId,
- value: user.id,
- ),
- secureStorage.write(
- key: kStreamToken,
- value: token,
- ),
- ]);
+ secureStorage.write(
+ key: kStreamApiKey,
+ value: kDefaultStreamApiKey,
+ );
+ secureStorage.write(
+ key: kStreamUserId,
+ value: user.id,
+ );
+ secureStorage.write(
+ key: kStreamToken,
+ value: token,
+ );
if (!kIsWeb) {
initNotifications(client);
@@ -178,9 +176,10 @@ class ChooseUserPage extends StatelessWidget {
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text('Stream test account'),
- trailing: Icon(
- StreamIcons.arrow_right,
- color: StreamChatTheme.of(context).accentColor,
+ trailing: SvgPicture.asset(
+ 'assets/icon_arrow_right.svg',
+ height: 24,
+ width: 24,
),
);
}),
@@ -206,9 +205,11 @@ class ChooseUserPage extends StatelessWidget {
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text('Custom settings'),
- trailing: Icon(
- StreamIcons.arrow_right,
- color: StreamChatTheme.of(context).accentColor,
+ trailing: SvgPicture.asset(
+ 'assets/icon_arrow_right.svg',
+ height: 24,
+ width: 24,
+ clipBehavior: Clip.none,
),
),
][i];
diff --git a/example/lib/stream_version.dart b/example/lib/stream_version.dart
index ee340f89..113e36c0 100644
--- a/example/lib/stream_version.dart
+++ b/example/lib/stream_version.dart
@@ -24,7 +24,6 @@ class StreamVersion extends StatelessWidget {
final streamChatDep =
yaml['packages']['stream_chat_flutter']['version'];
- print('streamChatDep: ${streamChatDep}');
return Text(
'Stream SDK v ${streamChatDep}',
style: TextStyle(
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index ce1ab622..e1442635 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -1,6 +1,6 @@
name: example
description: A new Flutter project.
-version: 1.0.54+56
+version: 1.0.58+60
environment:
sdk: ">=2.2.2 <3.0.0"
diff --git a/lib/src/group_image.dart b/lib/src/group_image.dart
index 2385007d..96e25f74 100644
--- a/lib/src/group_image.dart
+++ b/lib/src/group_image.dart
@@ -46,9 +46,16 @@ class GroupImage extends StatelessWidget {
.take(2)
.map((url) => Flexible(
fit: FlexFit.tight,
- child: CachedNetworkImage(
- imageUrl: url,
+ child: FittedBox(
fit: BoxFit.cover,
+ clipBehavior: Clip.antiAlias,
+ child: Transform.scale(
+ scale: 1.2,
+ child: CachedNetworkImage(
+ imageUrl: url,
+ fit: BoxFit.cover,
+ ),
+ ),
),
))
.toList(),
@@ -64,9 +71,16 @@ class GroupImage extends StatelessWidget {
.skip(2)
.map((url) => Flexible(
fit: FlexFit.tight,
- child: CachedNetworkImage(
- imageUrl: url,
+ child: FittedBox(
fit: BoxFit.cover,
+ clipBehavior: Clip.antiAlias,
+ child: Transform.scale(
+ scale: 1.2,
+ child: CachedNetworkImage(
+ imageUrl: url,
+ fit: BoxFit.cover,
+ ),
+ ),
),
))
.toList(),
diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart
index f9871d69..fd6286a2 100644
--- a/lib/src/message_widget.dart
+++ b/lib/src/message_widget.dart
@@ -493,7 +493,10 @@ class _MessageWidgetState extends State {
message: widget.message,
editMessageInputBuilder: widget.editMessageInputBuilder,
onThreadTap: widget.onThreadTap,
- showEditMessage: widget.showEditMessage,
+ showEditMessage: widget.showEditMessage &&
+ widget.message.attachments
+ ?.any((element) => element.type == 'giphy') !=
+ true,
showReactions: widget.showReactions,
showReply:
widget.showReplyIndicator && widget.onThreadTap != null,
diff --git a/lib/src/stream_chat_theme.dart b/lib/src/stream_chat_theme.dart
index 3b3725ed..967cbbbf 100644
--- a/lib/src/stream_chat_theme.dart
+++ b/lib/src/stream_chat_theme.dart
@@ -229,6 +229,7 @@ class StreamChatThemeData {
backgroundColor: isDark ? Colors.black : Colors.white,
defaultUserImage: (context, user) => Center(
child: CachedNetworkImage(
+ filterQuality: FilterQuality.high,
imageUrl: getRandomPicUrl(user),
fit: BoxFit.cover,
),
diff --git a/lib/src/user_avatar.dart b/lib/src/user_avatar.dart
index d1dd2e41..66edba39 100644
--- a/lib/src/user_avatar.dart
+++ b/lib/src/user_avatar.dart
@@ -38,23 +38,26 @@ class UserAvatar extends StatelessWidget {
: null,
child: Stack(
children: [
- Container(
- constraints: constraints ??
- streamChatTheme.ownMessageTheme.avatarTheme.constraints,
- clipBehavior: Clip.antiAlias,
- decoration: BoxDecoration(
- borderRadius: borderRadius ??
- streamChatTheme.ownMessageTheme.avatarTheme.borderRadius,
- color: streamChatTheme.accentColor,
+ ClipRRect(
+ borderRadius: borderRadius ??
+ streamChatTheme.ownMessageTheme.avatarTheme.borderRadius,
+ child: Container(
+ constraints: constraints ??
+ streamChatTheme.ownMessageTheme.avatarTheme.constraints,
+ decoration: BoxDecoration(
+ color: streamChatTheme.accentColor,
+ ),
+ child: hasImage
+ ? CachedNetworkImage(
+ filterQuality: FilterQuality.high,
+ imageUrl: user.extraData['image'],
+ errorWidget: (_, __, ___) {
+ return streamChatTheme.defaultUserImage(context, user);
+ },
+ fit: BoxFit.cover,
+ )
+ : streamChatTheme.defaultUserImage(context, user),
),
- child: hasImage
- ? CachedNetworkImage(
- imageUrl: user.extraData['image'],
- errorWidget: (_, __, ___) {
- return streamChatTheme.defaultUserImage(context, user);
- },
- )
- : streamChatTheme.defaultUserImage(context, user),
),
if (showOnlineStatus && user.online == true)
Positioned(