added lint changes, started migrating

This commit is contained in:
Deven Joshi
2021-05-04 16:11:28 +05:30
parent 88b8818e45
commit eb57c6eb9f
55 changed files with 884 additions and 885 deletions
@@ -13,52 +13,138 @@ linter:
# these rules are documented on and in the same order as
# the Dart Lint rules page to make maintenance easier
# https://github.com/dart-lang/linter/blob/master/example/all.yaml
# - always_declare_return_types
# - always_specify_types
# - annotate_overrides
# - avoid_as
- always_use_package_imports
- avoid_empty_else
- avoid_init_to_null
- avoid_return_types_on_setters
- avoid_web_libraries_in_flutter
- await_only_futures
- camel_case_types
- avoid_relative_lib_imports
- avoid_slow_async_io
- avoid_types_as_parameter_names
- cancel_subscriptions
- close_sinks
# - comment_references # we do not presume as to what people want to reference in their dartdocs
# - constant_identifier_names # https://github.com/dart-lang/linter/issues/204
- control_flow_in_finally
- empty_constructor_bodies
- empty_statements
- hash_and_equals
- implementation_imports
# - invariant_booleans
# - iterable_contains_unrelated_type
- library_names
# - library_prefixes
# - list_remove_unrelated_type
# - literal_only_boolean_expressions
- non_constant_identifier_names
# - one_member_abstracts
# - only_throw_errors
# - overridden_fields
# - package_api_docs
- package_names
- package_prefixed_library_names
- prefer_is_not_empty
# - prefer_mixin # https://github.com/dart-lang/language/issues/32
# - public_member_api_docs
- slash_for_doc_comments
# - sort_constructors_first
# - sort_unnamed_constructors_first
# - super_goes_last # no longer needed w/ Dart 2
- invariant_booleans
- iterable_contains_unrelated_type
- list_remove_unrelated_type
- literal_only_boolean_expressions
- no_adjacent_strings_in_list
- no_duplicate_case_values
- no_logic_in_create_state
- prefer_void_to_null
- test_types_in_equals
- throw_in_finally
# - type_annotate_public_apis # subset of always_specify_types
- type_init_formals
# - unawaited_futures
- unnecessary_brace_in_string_interps
- unnecessary_getters_setters
- unnecessary_statements
- unrelated_type_equality_checks
- omit_local_variable_types
- use_key_in_widget_constructors
- valid_regexps
- always_declare_return_types
- always_require_non_null_named_parameters
- annotate_overrides
- avoid_bool_literals_in_conditional_expressions
- avoid_catching_errors
- avoid_init_to_null
- avoid_null_checks_in_equality_operators
- avoid_positional_boolean_parameters
- avoid_private_typedef_functions
- avoid_redundant_argument_values
- avoid_return_types_on_setters
- avoid_returning_null_for_void
- avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements
- avoid_unnecessary_containers
- avoid_unused_constructor_parameters
- await_only_futures
- camel_case_extensions
- camel_case_types
- cascade_invocations
- constant_identifier_names
- curly_braces_in_flow_control_structures
- directives_ordering
- empty_catches
- empty_constructor_bodies
- exhaustive_cases
- file_names
- implementation_imports
- join_return_with_assignment
- leading_newlines_in_multiline_strings
- library_names
- library_prefixes
- lines_longer_than_80_chars
- missing_whitespace_between_adjacent_strings
- non_constant_identifier_names
- null_closures
- one_member_abstracts
- only_throw_errors
- package_api_docs
- package_prefixed_library_names
- parameter_assignments
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
- prefer_asserts_with_message
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
- prefer_constructors_over_static_methods
- prefer_contains
- prefer_equal_for_default_values
- prefer_expression_function_bodies
- prefer_final_fields
- prefer_final_in_for_each
- prefer_final_locals
- prefer_function_declarations_over_variables
- prefer_generic_function_type_aliases
- prefer_if_elements_to_conditional_expressions
- prefer_if_null_operators
- prefer_initializing_formals
- prefer_inlined_adds
- prefer_int_literals
- prefer_interpolation_to_compose_strings
- prefer_is_empty
- prefer_is_not_empty
- prefer_is_not_operator
- prefer_null_aware_operators
- prefer_single_quotes
- prefer_spread_collections
- prefer_typing_uninitialized_variables
- provide_deprecation_message
- public_member_api_docs
- recursive_getters
- sized_box_for_whitespace
- slash_for_doc_comments
- sort_child_properties_last
- sort_constructors_first
- sort_unnamed_constructors_first
- type_annotate_public_apis
- type_init_formals
- unnecessary_await_in_return
- unnecessary_brace_in_string_interps
- unnecessary_const
- unnecessary_getters_setters
- unnecessary_lambdas
- unnecessary_new
- unnecessary_null_aware_assignments
- unnecessary_null_in_if_null_operators
- unnecessary_nullable_for_final_variable_declarations
- unnecessary_parenthesis
- unnecessary_raw_strings
- unnecessary_string_escapes
- unnecessary_string_interpolations
- unnecessary_this
- use_is_even_rather_than_modulo
- use_late_for_private_fields_and_variables
- use_rethrow_when_possible
- use_setters_to_change_properties
- use_to_and_as_if_applicable
- package_names
- sort_pub_dependencies
- cast_nullable_to_non_nullable
- unnecessary_null_checks
- tighten_type_of_initializing_formals
- null_check_on_nullable_type_parameter
@@ -1,7 +1,7 @@
export 'attachment_upload_state_builder.dart';
export 'attachment_widget.dart'
show AttachmentError, AttachmentSource, AttachmentSourceX;
export 'file_attachment.dart';
export 'giphy_attachment.dart';
export 'image_attachment.dart';
export 'video_attachment.dart';
export 'attachment_upload_state_builder.dart';
export 'attachment_widget.dart'
show AttachmentError, AttachmentSource, AttachmentSourceX;
@@ -1,57 +1,59 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import '../stream_chat_theme.dart';
import '../utils.dart';
/// Title for attachments
class AttachmentTitle extends StatelessWidget {
/// Supply attachment and theme for constructing title
const AttachmentTitle({
Key? key,
required this.attachment,
required this.messageTheme,
}) : super(key: key);
/// Theme to apply to text
final MessageTheme messageTheme;
/// Attachment data to display
final Attachment attachment;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (attachment.titleLink != null) {
launchURL(context, attachment.titleLink!);
}
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (attachment.title != null)
Text(
attachment.title!,
overflow: TextOverflow.ellipsis,
style: messageTheme.messageText?.copyWith(
color: StreamChatTheme.of(context).colorTheme.accentBlue,
fontWeight: FontWeight.bold,
Widget build(BuildContext context) => GestureDetector(
onTap: () {
if (attachment.titleLink != null) {
launchURL(context, attachment.titleLink);
}
},
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (attachment.title != null)
Text(
attachment.title!,
overflow: TextOverflow.ellipsis,
style: messageTheme.messageText?.copyWith(
color: StreamChatTheme.of(context).colorTheme.accentBlue,
fontWeight: FontWeight.bold,
),
),
),
if (attachment.titleLink != null || attachment.ogScrapeUrl != null)
Text(
Uri.parse(attachment.titleLink ?? attachment.ogScrapeUrl!)
.authority
.split('.')
.reversed
.take(2)
.toList()
.reversed
.join('.'),
style: messageTheme.messageText,
),
],
if (attachment.titleLink != null ||
attachment.ogScrapeUrl != null)
Text(
Uri.parse(attachment.titleLink ?? attachment.ogScrapeUrl!)
.authority
.split('.')
.reversed
.take(2)
.toList()
.reversed
.join('.'),
style: messageTheme.messageText,
),
],
),
),
),
);
}
);
}
@@ -2,9 +2,13 @@ import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/upload_progress_indicator.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
/// Widget to build in progress
typedef InProgressBuilder = Widget Function(BuildContext, int, int);
/// Widget to build on failure
typedef FailedBuilder = Widget Function(BuildContext, String);
/// Widget to display attachment upload state
class AttachmentUploadStateBuilder extends StatelessWidget {
final Message message;
final Attachment attachment;
@@ -87,7 +91,6 @@ class _IconButton extends StatelessWidget {
elevation: 0,
highlightElevation: 0,
focusElevation: 0,
disabledElevation: 0,
hoverElevation: 0,
onPressed: onPressed,
fillColor:
@@ -237,7 +240,7 @@ class _SuccessState extends StatelessWidget {
alignment: Alignment.topRight,
child: CircleAvatar(
backgroundColor: StreamChatTheme.of(context).colorTheme.overlayDark,
maxRadius: 12.0,
maxRadius: 12,
child: StreamSvgIcon.check(
color: StreamChatTheme.of(context).colorTheme.white,
),
@@ -42,7 +42,7 @@ class FileAttachment extends AttachmentWidget {
onTap: onAttachmentTap,
child: Container(
width: size?.width ?? 100,
height: 56.0,
height: 56,
decoration: BoxDecoration(
color: colorTheme.white,
borderRadius: BorderRadius.circular(12),
@@ -54,12 +54,12 @@ class FileAttachment extends AttachmentWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 40.0,
height: 40,
width: 33.33,
margin: EdgeInsets.all(8.0),
margin: EdgeInsets.all(8),
child: _getFileTypeImage(context),
),
SizedBox(width: 8.0),
SizedBox(width: 8),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
@@ -71,12 +71,12 @@ class FileAttachment extends AttachmentWidget {
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 3.0),
SizedBox(height: 3),
_buildSubtitle(context),
],
),
),
SizedBox(width: 8.0),
SizedBox(width: 8),
_buildTrailing(context),
],
),
@@ -87,7 +87,7 @@ class FileAttachment extends AttachmentWidget {
ShapeBorder _getDefaultShape(BuildContext context) {
return RoundedRectangleBorder(
side: BorderSide(width: 0.0, color: Colors.transparent),
side: BorderSide(width: 0, color: Colors.transparent),
borderRadius: BorderRadius.circular(8),
);
}
@@ -159,8 +159,8 @@ class FileAttachment extends AttachmentWidget {
placeholderBuilder: (_) {
return Center(
child: Container(
width: 20.0,
height: 20.0,
width: 20,
height: 20,
child: const CircularProgressIndicator(),
),
);
@@ -171,8 +171,8 @@ class FileAttachment extends AttachmentWidget {
placeholderBuilder: (_) {
return Center(
child: Container(
width: 20.0,
height: 20.0,
width: 20,
height: 20,
child: const CircularProgressIndicator(),
),
);
@@ -197,7 +197,6 @@ class FileAttachment extends AttachmentWidget {
elevation: 0,
highlightElevation: 0,
focusElevation: 0,
disabledElevation: 0,
hoverElevation: 0,
onPressed: onPressed,
fillColor: fillColor,
@@ -214,7 +213,7 @@ class FileAttachment extends AttachmentWidget {
var trailingWidget = trailing;
trailingWidget ??= attachment.uploadState.when(
preparing: () => Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: _buildButton(
icon: StreamSvgIcon.close(color: theme.colorTheme.white),
fillColor: theme.colorTheme.overlayDark,
@@ -222,7 +221,7 @@ class FileAttachment extends AttachmentWidget {
),
),
inProgress: (_, __) => Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: _buildButton(
icon: StreamSvgIcon.close(color: theme.colorTheme.white),
fillColor: theme.colorTheme.overlayDark,
@@ -230,15 +229,15 @@ class FileAttachment extends AttachmentWidget {
),
),
success: () => Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: CircleAvatar(
backgroundColor: theme.colorTheme.accentBlue,
maxRadius: 12.0,
maxRadius: 12,
child: StreamSvgIcon.check(color: theme.colorTheme.white),
),
),
failed: (_) => Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: _buildButton(
icon: StreamSvgIcon.retry(color: theme.colorTheme.white),
fillColor: theme.colorTheme.overlayDark,
@@ -251,7 +250,6 @@ class FileAttachment extends AttachmentWidget {
) ??
IconButton(
icon: StreamSvgIcon.cloudDownload(color: theme.colorTheme.black),
padding: const EdgeInsets.all(8),
visualDensity: VisualDensity.compact,
splashRadius: 16,
onPressed: () {
@@ -262,7 +260,6 @@ class FileAttachment extends AttachmentWidget {
if (message.status == MessageSendingStatus.sent) {
trailingWidget = IconButton(
icon: StreamSvgIcon.cloudDownload(color: theme.colorTheme.black),
padding: const EdgeInsets.all(8),
visualDensity: VisualDensity.compact,
splashRadius: 16,
onPressed: () {
@@ -304,9 +301,9 @@ class FileAttachment extends AttachmentWidget {
progressIndicatorColor: theme.colorTheme.accentBlue,
);
},
success: () => Text('${fileSize(size, 2)}', style: textStyle),
success: () => Text(fileSize(size), style: textStyle),
failed: (_) => Text('UPLOAD ERROR', style: textStyle),
) ??
Text('${fileSize(size)}', style: textStyle);
Text(fileSize(size), style: textStyle);
}
}
@@ -52,10 +52,10 @@ class GiphyAttachment extends AttachmentWidget {
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(16.0),
bottomRight: Radius.circular(0.0),
topLeft: Radius.circular(16.0),
bottomLeft: Radius.circular(16.0),
topRight: Radius.circular(16),
bottomRight: Radius.circular(0),
topLeft: Radius.circular(16),
bottomLeft: Radius.circular(16),
),
),
child: Column(
@@ -63,7 +63,7 @@ class GiphyAttachment extends AttachmentWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: Row(
children: [
StreamSvgIcon.giphyIcon(),
@@ -91,7 +91,7 @@ class GiphyAttachment extends AttachmentWidget {
),
),
Padding(
padding: const EdgeInsets.all(2.0),
padding: const EdgeInsets.all(2),
child: GestureDetector(
onTap: () => onAttachmentTap ?? _onImageTap(context),
child: CachedNetworkImage(
@@ -123,8 +123,6 @@ class GiphyAttachment extends AttachmentWidget {
height: 0.5,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
@@ -156,7 +154,7 @@ class GiphyAttachment extends AttachmentWidget {
.colorTheme
.black
.withOpacity(0.2),
height: 50.0,
height: 50,
),
Expanded(
child: Container(
@@ -189,7 +187,7 @@ class GiphyAttachment extends AttachmentWidget {
.colorTheme
.black
.withOpacity(0.2),
height: 50.0,
height: 50,
),
Expanded(
child: Container(
@@ -217,11 +215,11 @@ class GiphyAttachment extends AttachmentWidget {
],
),
),
SizedBox(height: 4.0),
SizedBox(height: 4),
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
@@ -230,10 +228,10 @@ class GiphyAttachment extends AttachmentWidget {
.colorTheme
.black
.withOpacity(0.5),
size: 16.0,
size: 16,
),
SizedBox(
width: 8.0,
width: 8,
),
Text(
'Only visible to you',
@@ -332,8 +330,8 @@ class GiphyAttachment extends AttachmentWidget {
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 4.0,
horizontal: 8,
vertical: 4,
),
child: Row(
children: [
@@ -34,137 +34,131 @@ class ImageAttachment extends AttachmentWidget {
);
@override
Widget build(BuildContext context) {
return source.when(
local: () {
if (attachment.localUri == null || attachment.file?.bytes == null) {
return AttachmentError(size: size);
}
return _buildImageAttachment(
context,
Image.memory(
attachment.file!.bytes!,
height: size?.height,
width: size?.width,
fit: BoxFit.cover,
errorBuilder: (context, _, __) {
return Image.asset(
Widget build(BuildContext context) => source.when(
local: () {
if (attachment.localUri == null || attachment.file?.bytes == null) {
return AttachmentError(size: size);
}
return _buildImageAttachment(
context,
Image.memory(
attachment.file!.bytes!,
height: size?.height,
width: size?.width,
fit: BoxFit.cover,
errorBuilder: (context, _, __) => Image.asset(
'images/placeholder.png',
package: 'stream_chat_flutter',
);
},
),
);
},
network: () {
var imageUrl =
attachment.thumbUrl ?? attachment.imageUrl ?? attachment.assetUrl;
if (imageUrl == null) {
return AttachmentError(size: size);
}
var imageUri = Uri.parse(imageUrl);
if (imageUri.host == 'stream-io-cdn.com') {
imageUri = imageUri.replace(queryParameters: {
...imageUri.queryParameters,
'h': '500',
'w': '500',
'crop': 'center',
'resize': 'crop',
});
} else if (imageUri.host == 'stream-cloud-uploads.imgix.net') {
imageUri = imageUri.replace(queryParameters: {
...imageUri.queryParameters,
'height': '500',
'width': '500',
'fit': 'crop',
});
}
imageUrl = imageUri.toString();
return _buildImageAttachment(
context,
CachedNetworkImage(
cacheKey: imageUri.path,
height: size?.height,
width: size?.width,
placeholder: (_, __) {
final image = Image.asset(
'images/placeholder.png',
fit: BoxFit.cover,
package: 'stream_chat_flutter',
);
final colorTheme = StreamChatTheme.of(context).colorTheme;
return Shimmer.fromColors(
baseColor: colorTheme.greyGainsboro,
highlightColor: colorTheme.whiteSmoke,
child: image,
);
},
imageUrl: imageUrl,
errorWidget: (context, url, error) {
return AttachmentError(size: size);
},
fit: BoxFit.cover,
),
);
},
);
}
Widget _buildImageAttachment(BuildContext context, Widget imageWidget) {
return ConstrainedBox(
constraints: BoxConstraints.loose(size!),
child: Column(
children: <Widget>[
Expanded(
child: Stack(
children: [
GestureDetector(
onTap: onAttachmentTap ??
() async {
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (_) {
final channel = StreamChannel.of(context).channel;
return StreamChannel(
channel: channel,
child: FullScreenMedia(
mediaAttachments: [attachment],
userName: message.user?.name,
message: message,
onShowMessage: onShowMessage,
),
);
},
),
);
if (result != null) onReturnAction?.call(result);
},
child: imageWidget,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: AttachmentUploadStateBuilder(
message: message,
attachment: attachment,
),
),
],
),
),
if (showTitle && attachment.title != null)
Material(
color: messageTheme.messageBackgroundColor,
child: AttachmentTitle(
messageTheme: messageTheme,
attachment: attachment,
),
),
],
),
);
}
);
},
network: () {
var imageUrl =
attachment.thumbUrl ?? attachment.imageUrl ?? attachment.assetUrl;
if (imageUrl == null) {
return AttachmentError(size: size);
}
var imageUri = Uri.parse(imageUrl);
if (imageUri.host == 'stream-io-cdn.com') {
imageUri = imageUri.replace(queryParameters: {
...imageUri.queryParameters,
'h': '500',
'w': '500',
'crop': 'center',
'resize': 'crop',
});
} else if (imageUri.host == 'stream-cloud-uploads.imgix.net') {
imageUri = imageUri.replace(queryParameters: {
...imageUri.queryParameters,
'height': '500',
'width': '500',
'fit': 'crop',
});
}
imageUrl = imageUri.toString();
return _buildImageAttachment(
context,
CachedNetworkImage(
cacheKey: imageUri.path,
height: size?.height,
width: size?.width,
placeholder: (_, __) {
final image = Image.asset(
'images/placeholder.png',
fit: BoxFit.cover,
package: 'stream_chat_flutter',
);
final colorTheme = StreamChatTheme.of(context).colorTheme;
return Shimmer.fromColors(
baseColor: colorTheme.greyGainsboro,
highlightColor: colorTheme.whiteSmoke,
child: image,
);
},
imageUrl: imageUrl,
errorWidget: (context, url, error) => AttachmentError(size: size),
fit: BoxFit.cover,
),
);
},
);
Widget _buildImageAttachment(BuildContext context, Widget imageWidget) =>
ConstrainedBox(
constraints: BoxConstraints.loose(size!),
child: Column(
children: <Widget>[
Expanded(
child: Stack(
children: [
GestureDetector(
onTap: onAttachmentTap ??
() async {
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (_) {
final channel =
StreamChannel.of(context).channel;
return StreamChannel(
channel: channel,
child: FullScreenMedia(
mediaAttachments: [attachment],
userName: message.user?.name,
message: message,
onShowMessage: onShowMessage,
),
);
},
),
);
if (result != null) onReturnAction?.call(result);
},
child: imageWidget,
),
Padding(
padding: const EdgeInsets.all(8),
child: AttachmentUploadStateBuilder(
message: message,
attachment: attachment,
),
),
],
),
),
if (showTitle && attachment.title != null)
Material(
color: messageTheme.messageBackgroundColor,
child: AttachmentTitle(
messageTheme: messageTheme,
attachment: attachment,
),
),
],
),
);
}
@@ -30,100 +30,97 @@ class VideoAttachment extends AttachmentWidget {
);
@override
Widget build(BuildContext context) {
return source.when(
local: () {
if (attachment.file == null) {
return AttachmentError(size: size);
}
return _buildVideoAttachment(
context,
VideoThumbnailImage(
video: attachment.file!.path!,
height: size?.height,
width: size?.width,
fit: BoxFit.cover,
errorBuilder: (_, __) => AttachmentError(size: size),
),
);
},
network: () {
if (attachment.assetUrl == null) {
return AttachmentError(size: size);
}
return _buildVideoAttachment(
context,
VideoThumbnailImage(
video: attachment.assetUrl!,
height: size?.height,
width: size?.width,
fit: BoxFit.cover,
errorBuilder: (_, __) => AttachmentError(size: size),
),
);
},
);
}
Widget build(BuildContext context) => source.when(
local: () {
if (attachment.file == null) {
return AttachmentError(size: size);
}
return _buildVideoAttachment(
context,
VideoThumbnailImage(
video: attachment.file!.path!,
height: size?.height,
width: size?.width,
fit: BoxFit.cover,
errorBuilder: (_, __) => AttachmentError(size: size),
),
);
},
network: () {
if (attachment.assetUrl == null) {
return AttachmentError(size: size);
}
return _buildVideoAttachment(
context,
VideoThumbnailImage(
video: attachment.assetUrl!,
height: size?.height,
width: size?.width,
fit: BoxFit.cover,
errorBuilder: (_, __) => AttachmentError(size: size),
),
);
},
);
Widget _buildVideoAttachment(BuildContext context, Widget videoWidget) {
return ConstrainedBox(
constraints: BoxConstraints.loose(size ?? Size.infinite),
child: Column(
children: <Widget>[
Expanded(
child: GestureDetector(
onTap: onAttachmentTap ??
() async {
final channel = StreamChannel.of(context).channel;
final res = await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => StreamChannel(
channel: channel,
child: FullScreenMedia(
mediaAttachments: [attachment],
userName: message.user?.name,
message: message,
onShowMessage: onShowMessage,
Widget _buildVideoAttachment(BuildContext context, Widget videoWidget) =>
ConstrainedBox(
constraints: BoxConstraints.loose(size ?? Size.infinite),
child: Column(
children: <Widget>[
Expanded(
child: GestureDetector(
onTap: onAttachmentTap ??
() async {
final channel = StreamChannel.of(context).channel;
final res = await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => StreamChannel(
channel: channel,
child: FullScreenMedia(
mediaAttachments: [attachment],
userName: message.user?.name,
message: message,
onShowMessage: onShowMessage,
),
),
),
),
);
if (res != null) onReturnAction?.call(res);
},
child: Stack(
children: [
videoWidget,
Center(
child: Material(
shape: CircleBorder(),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(Icons.play_arrow),
);
if (res != null) onReturnAction?.call(res);
},
child: Stack(
children: [
videoWidget,
const Center(
child: Material(
shape: CircleBorder(),
child: Padding(
padding: EdgeInsets.all(16),
child: Icon(Icons.play_arrow),
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: AttachmentUploadStateBuilder(
message: message,
attachment: attachment,
Padding(
padding: const EdgeInsets.all(8),
child: AttachmentUploadStateBuilder(
message: message,
attachment: attachment,
),
),
),
],
],
),
),
),
),
if (attachment.title != null)
Material(
color: messageTheme.messageBackgroundColor,
child: AttachmentTitle(
messageTheme: messageTheme,
attachment: attachment,
if (attachment.title != null)
Material(
color: messageTheme.messageBackgroundColor,
child: AttachmentTitle(
messageTheme: messageTheme,
attachment: attachment,
),
),
),
],
),
);
}
],
),
);
}
@@ -42,27 +42,25 @@ class AttachmentActionsModal extends StatelessWidget {
});
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => Navigator.maybePop(context),
child: _buildPage(context),
);
}
Widget build(BuildContext context) => GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => Navigator.maybePop(context),
child: _buildPage(context),
);
Widget _buildPage(context) {
final theme = StreamChatTheme.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
SizedBox(height: kToolbarHeight),
const SizedBox(height: kToolbarHeight),
Padding(
padding: const EdgeInsets.only(right: 8.0),
padding: const EdgeInsets.only(right: 8),
child: Container(
width: MediaQuery.of(context).size.width * 0.5,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
borderRadius: BorderRadius.circular(16),
),
child: Container(
child: Column(
@@ -73,7 +71,7 @@ class AttachmentActionsModal extends StatelessWidget {
context,
'Reply',
StreamSvgIcon.iconCurveLineLeftUp(
size: 24.0,
size: 24,
color: theme.colorTheme.grey,
),
() {
@@ -84,7 +82,7 @@ class AttachmentActionsModal extends StatelessWidget {
context,
'Show in Chat',
StreamSvgIcon.eye(
size: 24.0,
size: 24,
color: theme.colorTheme.black,
),
onShowMessage,
@@ -93,7 +91,7 @@ class AttachmentActionsModal extends StatelessWidget {
context,
'Save ${message.attachments[currentIndex].type == 'video' ? 'Video' : 'Image'}',
StreamSvgIcon.iconSave(
size: 24.0,
size: 24,
color: theme.colorTheme.grey,
),
() {
@@ -144,7 +142,7 @@ class AttachmentActionsModal extends StatelessWidget {
context,
'Delete',
StreamSvgIcon.delete(
size: 24.0,
size: 24,
color: theme.colorTheme.accentRed,
),
() {
@@ -201,7 +199,7 @@ class AttachmentActionsModal extends StatelessWidget {
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: Row(
children: [
icon,
@@ -271,7 +269,7 @@ class AttachmentActionsModal extends StatelessWidget {
children: [
CircularProgressIndicator(
value: progress.toProgressIndicatorValue,
strokeWidth: 8.0,
strokeWidth: 8,
valueColor: AlwaysStoppedAnimation(
theme.colorTheme.accentBlue,
),
@@ -30,7 +30,6 @@ class StreamBackButton extends StatelessWidget {
elevation: 0,
highlightElevation: 0,
focusElevation: 0,
disabledElevation: 0,
hoverElevation: 0,
onPressed: () {
if (onPressed != null) {
@@ -39,7 +38,7 @@ class StreamBackButton extends StatelessWidget {
Navigator.maybePop(context);
}
},
padding: const EdgeInsets.all(14.0),
padding: const EdgeInsets.all(14),
child: StreamSvgIcon.left(
size: 24,
color: StreamChatTheme.of(context).colorTheme.black,
@@ -7,7 +7,7 @@ import 'option_list_tile.dart';
class ChannelBottomSheet extends StatefulWidget {
final VoidCallback? onViewInfoTap;
ChannelBottomSheet({this.onViewInfoTap});
const ChannelBottomSheet({this.onViewInfoTap});
@override
_ChannelBottomSheetState createState() => _ChannelBottomSheetState();
@@ -31,29 +31,29 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0),
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: !_showActions
? SizedBox()
? const SizedBox()
: ListView(
shrinkWrap: true,
children: [
SizedBox(
height: 24.0,
const SizedBox(
height: 24,
),
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: ChannelName(
textStyle:
StreamChatTheme.of(context).textTheme.headlineBold,
),
),
),
SizedBox(
height: 5.0,
const SizedBox(
height: 5,
),
Center(
child: ChannelInfo(
@@ -64,8 +64,8 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
.subtitle,
),
),
SizedBox(
height: 17.0,
const SizedBox(
height: 17,
),
if (channel.isDistinct && channel.memberCount == 2)
Column(
@@ -75,16 +75,16 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
.firstWhere(
(e) => e.user?.id != userAsMember.user?.id)
.user!,
constraints: BoxConstraints(
maxHeight: 64.0,
maxWidth: 64.0,
constraints: const BoxConstraints(
maxHeight: 64,
maxWidth: 64,
),
borderRadius: BorderRadius.circular(32.0),
borderRadius: BorderRadius.circular(32),
onlineIndicatorConstraints:
BoxConstraints.tight(Size(12.0, 12.0)),
BoxConstraints.tight(const Size(12, 12)),
),
SizedBox(
height: 6.0,
const SizedBox(
height: 6,
),
Text(
members
@@ -102,50 +102,48 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
),
if (!(channel.isDistinct && channel.memberCount == 2))
Container(
height: 94.0,
height: 94,
alignment: Alignment.center,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: members.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
children: [
UserAvatar(
user: members[index].user!,
constraints: BoxConstraints.tightFor(
height: 64.0,
width: 64.0,
),
borderRadius: BorderRadius.circular(32.0),
onlineIndicatorConstraints:
BoxConstraints.tight(Size(12.0, 12.0)),
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Column(
children: [
UserAvatar(
user: members[index].user!,
constraints: const BoxConstraints.tightFor(
height: 64,
width: 64,
),
SizedBox(
height: 6.0,
),
Text(
members[index].user?.name ?? '',
style: StreamChatTheme.of(context)
.textTheme
.footnoteBold,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
);
},
borderRadius: BorderRadius.circular(32),
onlineIndicatorConstraints:
BoxConstraints.tight(Size(12, 12)),
),
const SizedBox(
height: 6,
),
Text(
members[index].user?.name ?? '',
style: StreamChatTheme.of(context)
.textTheme
.footnoteBold,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
),
),
SizedBox(
height: 24.0,
const SizedBox(
height: 24,
),
OptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.user(
color: StreamChatTheme.of(context).colorTheme.grey,
),
@@ -156,7 +154,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
if (!channel.isDistinct)
OptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.userRemove(
color: StreamChatTheme.of(context).colorTheme.grey,
),
@@ -175,7 +173,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
if (isOwner)
OptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.delete(
color: StreamChatTheme.of(context).colorTheme.accentRed,
),
@@ -195,7 +193,7 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
),
OptionListTile(
leading: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: StreamSvgIcon.closeSmall(
color: StreamChatTheme.of(context).colorTheme.grey,
),
@@ -144,7 +144,7 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
actions: actions ??
<Widget>[
Padding(
padding: const EdgeInsets.only(right: 10.0),
padding: const EdgeInsets.only(right: 10),
child: Center(
child: ChannelImage(
borderRadius: StreamChatTheme.of(context)
@@ -169,7 +169,6 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget {
height: preferredSize.height,
width: preferredSize.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
title ??
@@ -158,30 +158,29 @@ class ChannelImage extends StatelessWidget {
alignment: Alignment.center,
fit: StackFit.expand,
children: <Widget>[
image != null
? CachedNetworkImage(
imageUrl: image,
errorWidget: (_, __, ___) {
return Center(
child: Text(
snapshot.data?.containsKey('name') ?? false
? snapshot.data!['name'][0]
: '',
style: TextStyle(
color: StreamChatTheme.of(context)
.colorTheme
.white,
fontWeight: FontWeight.bold,
),
),
);
},
fit: BoxFit.cover,
)
: StreamChatTheme.of(context).defaultChannelImage(
context,
channel,
),
if (image != null)
CachedNetworkImage(
imageUrl: image,
errorWidget: (_, __, ___) {
return Center(
child: Text(
snapshot.data?.containsKey('name') ?? false
? snapshot.data!['name'][0]
: '',
style: TextStyle(
color: StreamChatTheme.of(context).colorTheme.white,
fontWeight: FontWeight.bold,
),
),
);
},
fit: BoxFit.cover,
)
else
StreamChatTheme.of(context).defaultChannelImage(
context,
channel,
),
Material(
color: Colors.transparent,
child: InkWell(
@@ -27,28 +27,26 @@ class ChannelInfo extends StatelessWidget {
return StreamBuilder<List<Member>>(
stream: channel.state?.membersStream,
initialData: channel.state?.members,
builder: (context, snapshot) {
return ConnectionStatusBuilder(
statusBuilder: (context, status) {
switch (status) {
case ConnectionStatus.connected:
return _buildConnectedTitleState(context, snapshot.data);
case ConnectionStatus.connecting:
return _buildConnectingTitleState(context);
case ConnectionStatus.disconnected:
return _buildDisconnectedTitleState(context, client);
default:
return Offstage();
}
},
);
},
builder: (context, snapshot) => ConnectionStatusBuilder(
statusBuilder: (context, status) {
switch (status) {
case ConnectionStatus.connected:
return _buildConnectedTitleState(context, snapshot.data);
case ConnectionStatus.connecting:
return _buildConnectingTitleState(context);
case ConnectionStatus.disconnected:
return _buildDisconnectedTitleState(context, client);
default:
return const Offstage();
}
},
),
);
}
Widget _buildConnectedTitleState(
BuildContext context, List<Member>? members) {
var alternativeWidget;
Widget? alternativeWidget;
if (channel.memberCount != null && channel.memberCount! > 2) {
var text = '${channel.memberCount} Members';
@@ -82,7 +80,7 @@ class ChannelInfo extends StatelessWidget {
}
if (!showTypingIndicator) {
return alternativeWidget ?? Offstage();
return alternativeWidget ?? const Offstage();
}
return TypingIndicator(
@@ -92,58 +90,55 @@ class ChannelInfo extends StatelessWidget {
);
}
Widget _buildConnectingTitleState(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 16,
width: 16,
child: Center(
child: CircularProgressIndicator(),
Widget _buildConnectingTitleState(BuildContext context) => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 16,
width: 16,
child: const Center(
child: CircularProgressIndicator(),
),
),
),
SizedBox(width: 10),
Text(
'Searching for Network',
style: textStyle,
),
],
);
}
SizedBox(width: 10),
Text(
'Searching for Network',
style: textStyle,
),
],
);
Widget _buildDisconnectedTitleState(
BuildContext context,
StreamChatClient client,
) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Offline...',
style: textStyle,
),
TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.all(0),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: VisualDensity(
horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity,
) =>
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Offline...',
style: textStyle,
),
TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.all(0),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: const VisualDensity(
horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity,
),
),
onPressed: () async {
await client.disconnect();
await client.connect();
},
child: Text(
'Try Again',
style: textStyle?.copyWith(
color: StreamChatTheme.of(context).colorTheme.accentBlue,
),
),
),
onPressed: () async {
await client.disconnect();
await client.connect();
},
child: Text(
'Try Again',
style: textStyle?.copyWith(
color: StreamChatTheme.of(context).colorTheme.accentBlue,
),
),
),
],
);
}
],
);
}
@@ -168,8 +168,8 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget {
return SvgPicture.asset(
'svgs/icon_pen_write.svg',
package: 'stream_chat_flutter',
width: 24.0,
height: 24.0,
width: 24,
height: 24,
color: color,
);
},
@@ -54,7 +54,7 @@ typedef ViewInfoCallback = void Function(Channel);
/// Modify it to change the widget appearance.
class ChannelListView extends StatefulWidget {
/// Instantiate a new ChannelListView
ChannelListView({
const ChannelListView({
Key? key,
this.filter,
this.options,
@@ -248,7 +248,7 @@ class _ChannelListViewState extends State<ChannelListView> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: StreamSvgIcon.message(
size: 136,
color: StreamChatTheme.of(context)
@@ -257,7 +257,7 @@ class _ChannelListViewState extends State<ChannelListView> {
),
),
Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: Text(
'Lets start chatting!',
style: StreamChatTheme.of(context).textTheme.headline,
@@ -265,7 +265,7 @@ class _ChannelListViewState extends State<ChannelListView> {
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
vertical: 8,
horizontal: 52,
),
child: Text(
@@ -340,7 +340,7 @@ class _ChannelListViewState extends State<ChannelListView> {
highlightColor: StreamChatTheme.of(context).colorTheme.whiteSmoke,
child: Column(
children: [
SizedBox(height: 4.0),
SizedBox(height: 4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
@@ -358,7 +358,7 @@ class _ChannelListViewState extends State<ChannelListView> {
],
),
SizedBox(
height: 16.0,
height: 16,
),
],
),
@@ -441,7 +441,7 @@ class _ChannelListViewState extends State<ChannelListView> {
WidgetSpan(
child: Padding(
padding: const EdgeInsets.only(
right: 2.0,
right: 2,
),
child: Icon(Icons.error_outline),
),
@@ -477,7 +477,6 @@ class _ChannelListViewState extends State<ChannelListView> {
enabled: widget.swipeToAction,
actionPane: SlidableBehindActionPane(),
actionExtentRatio: 0.12,
closeOnScroll: true,
secondaryActions: <Widget>[
IconSlideAction(
color: backgroundColor,
@@ -589,7 +588,6 @@ class _ChannelListViewState extends State<ChannelListView> {
key: ValueKey<String>('CHANNEL-${channel.id}'),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ChannelImage(
channel: channel,
@@ -634,7 +632,7 @@ class _ChannelListViewState extends State<ChannelListView> {
.accentRed
.withOpacity(.2),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
padding: const EdgeInsets.symmetric(vertical: 16),
child: Center(
child: Text('Error loading channels'),
),
@@ -644,7 +642,7 @@ class _ChannelListViewState extends State<ChannelListView> {
return snapshot.data!
? Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16),
child: const CircularProgressIndicator(),
),
)
@@ -653,7 +651,7 @@ class _ChannelListViewState extends State<ChannelListView> {
}
Widget _separatorBuilder(context, i) {
var effect = StreamChatTheme.of(context).colorTheme.borderBottom;
final effect = StreamChatTheme.of(context).colorTheme.borderBottom;
return Container(
height: 1,
@@ -47,7 +47,7 @@ class ChannelPreview extends StatelessWidget {
/// Widget rendering the sending indicator, by default it uses the [SendingIndicator] widget
final Widget? sendingIndicator;
ChannelPreview({
const ChannelPreview({
required this.channel,
Key? key,
this.onTap,
@@ -128,7 +128,7 @@ class ChannelPreview extends StatelessWidget {
if (lastMessage?.user?.id ==
StreamChat.of(context).user?.id) {
return Padding(
padding: const EdgeInsets.only(right: 4.0),
padding: const EdgeInsets.only(right: 4),
child: SendingIndicator(
message: lastMessage!,
size: channelPreviewTheme.indicatorIconSize,
@@ -167,7 +167,7 @@ class ChannelPreview extends StatelessWidget {
String stringDate;
final now = DateTime.now();
var startOfDay = DateTime(now.year, now.month, now.day);
final startOfDay = DateTime(now.year, now.month, now.day);
if (lastMessageAt.millisecondsSinceEpoch >=
startOfDay.millisecondsSinceEpoch) {
@@ -298,7 +298,7 @@ class ChannelPreview extends StatelessWidget {
));
} else {
resList.add(TextSpan(
text: e == textList.last ? '$e' : '$e ',
text: e == textList.last ? e : '$e ',
style: normalTextStyle,
));
}
@@ -53,7 +53,7 @@ class DeletedMessage extends StatelessWidget {
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
vertical: 8,
horizontal: 16,
),
child: Transform(
@@ -150,7 +150,7 @@ class _FullScreenMediaState extends State<FullScreenMedia>
},
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 50.0,
vertical: 50,
),
child: Chewie(
controller: controller.chewieController!,
@@ -113,8 +113,8 @@ class GroupImage extends StatelessWidget {
child: Container(
color: selectionColor ??
StreamChatTheme.of(context).colorTheme.accentBlue,
height: 64.0,
width: 64.0,
height: 64,
width: 64,
child: Padding(
padding: EdgeInsets.all(selectionThickness),
child: avatar,
@@ -82,47 +82,45 @@ class _ImageFooterState extends State<ImageFooter> {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
!showShareButton
? Container(
width: 48,
)
: IconButton(
icon: StreamSvgIcon.iconShare(
size: 24.0,
color: StreamChatTheme.of(context).colorTheme.black,
),
onPressed: () async {
final attachment =
widget.mediaAttachments[widget.currentPage];
final url = attachment.imageUrl ??
attachment.assetUrl ??
attachment.thumbUrl!;
final type = attachment.type == 'image'
? 'jpg'
: url.split('?').first.split('.').last;
final request =
await HttpClient().getUrl(Uri.parse(url));
final response = await request.close();
final bytes =
await consolidateHttpClientResponseBytes(response);
final tmpPath = await getTemporaryDirectory();
final filePath =
'${tmpPath.path}/${attachment.id}.$type';
final file = File(filePath);
await file.writeAsBytes(bytes);
await Share.shareFiles(
[filePath],
mimeTypes: [
'image/$type',
],
);
},
),
if (!showShareButton)
Container(
width: 48,
)
else
IconButton(
icon: StreamSvgIcon.iconShare(
size: 24,
color: StreamChatTheme.of(context).colorTheme.black,
),
onPressed: () async {
final attachment =
widget.mediaAttachments[widget.currentPage];
final url = attachment.imageUrl ??
attachment.assetUrl ??
attachment.thumbUrl!;
final type = attachment.type == 'image'
? 'jpg'
: url.split('?').first.split('.').last;
final request = await HttpClient().getUrl(Uri.parse(url));
final response = await request.close();
final bytes =
await consolidateHttpClientResponseBytes(response);
final tmpPath = await getTemporaryDirectory();
final filePath = '${tmpPath.path}/${attachment.id}.$type';
final file = File(filePath);
await file.writeAsBytes(bytes);
await Share.shareFiles(
[filePath],
mimeTypes: [
'image/$type',
],
);
},
),
InkWell(
onTap: widget.onTitleTap,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
@@ -156,12 +154,12 @@ class _ImageFooterState extends State<ImageFooter> {
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0),
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
builder: (context) {
final crossAxisCount = 3;
const crossAxisCount = 3;
final noOfRowToShowInitially =
widget.mediaAttachments.length > crossAxisCount ? 2 : 1;
final size = MediaQuery.of(context).size;
@@ -181,7 +179,7 @@ class _ImageFooterState extends State<ImageFooter> {
children: [
Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16),
child: Text(
'Photos',
style: StreamChatTheme.of(context)
@@ -209,8 +207,8 @@ class _ImageFooterState extends State<ImageFooter> {
padding: const EdgeInsets.all(1),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
mainAxisSpacing: 2.0,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2,
crossAxisSpacing: 2,
),
itemBuilder: (context, index) {
Widget media;
@@ -230,7 +228,7 @@ class _ImageFooterState extends State<ImageFooter> {
media = InkWell(
onTap: () => widget.mediaSelectedCallBack!(index),
child: AspectRatio(
aspectRatio: 1.0,
aspectRatio: 1,
child: CachedNetworkImage(
imageUrl: attachment.imageUrl ??
attachment.assetUrl ??
@@ -246,7 +244,7 @@ class _ImageFooterState extends State<ImageFooter> {
media,
if (widget.message.user != null)
Padding(
padding: EdgeInsets.all(8.0),
padding: EdgeInsets.all(8),
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
@@ -254,7 +252,7 @@ class _ImageFooterState extends State<ImageFooter> {
color: Colors.white.withOpacity(0.6),
boxShadow: [
BoxShadow(
blurRadius: 8.0,
blurRadius: 8,
color: StreamChatTheme.of(context)
.colorTheme
.black
@@ -287,7 +285,7 @@ class _ImageFooterState extends State<ImageFooter> {
/// Sends the current message
Future sendMessage() async {
var text = _messageController.text.trim();
final text = _messageController.text.trim();
final attachments = widget.message.attachments;
@@ -311,10 +309,10 @@ class _ImageFooterState extends State<ImageFooter> {
class IconClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var leftX = size.width / 5;
var rightX = 4 * size.width / 5;
var topY = size.height / 5;
var bottomY = 4 * size.height / 5;
final leftX = size.width / 5;
final rightX = 4 * size.width / 5;
final topY = size.height / 5;
final bottomY = 4 * size.height / 5;
final path = Path();
path.moveTo(leftX, topY);
@@ -322,7 +320,7 @@ class IconClipper extends CustomClipper<Path> {
path.lineTo(rightX, bottomY);
path.lineTo(rightX, topY);
path.lineTo(leftX, topY);
path.lineTo(0.0, 0.0);
path.lineTo(0, 0);
path.close();
return path;
}
@@ -27,22 +27,19 @@ class ImageGroup extends StatelessWidget {
direction: Axis.vertical,
children: <Widget>[
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Flex(
crossAxisAlignment: CrossAxisAlignment.stretch,
direction: Axis.horizontal,
children: [
Flexible(
flex: 1,
fit: FlexFit.tight,
child: _buildImage(context, 0),
),
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Padding(
padding: const EdgeInsets.only(left: 2.0),
padding: const EdgeInsets.only(left: 2),
child: _buildImage(context, 1),
),
),
@@ -52,24 +49,21 @@ class ImageGroup extends StatelessWidget {
if (images.length >= 3)
Flexible(
fit: FlexFit.tight,
flex: 1,
child: Padding(
padding: const EdgeInsets.only(top: 2.0),
padding: const EdgeInsets.only(top: 2),
child: Flex(
direction: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Flexible(
fit: FlexFit.tight,
flex: 1,
child: _buildImage(context, 2),
),
if (images.length >= 4)
Flexible(
fit: FlexFit.tight,
flex: 1,
child: Padding(
padding: const EdgeInsets.only(left: 2.0),
padding: const EdgeInsets.only(left: 2),
child: Stack(
fit: StackFit.expand,
children: <Widget>[
@@ -53,7 +53,7 @@ class ImageHeader extends StatelessWidget implements PreferredSizeWidget {
? IconButton(
icon: StreamSvgIcon.close(
color: StreamChatTheme.of(context).colorTheme.black,
size: 24.0,
size: 24,
),
onPressed: onBackPressed,
)
@@ -79,7 +79,6 @@ class ImageHeader extends StatelessWidget implements PreferredSizeWidget {
height: preferredSize.height,
width: preferredSize.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
@@ -11,7 +11,7 @@ class InfoTile extends StatelessWidget {
final TextStyle? textStyle;
final Color? backgroundColor;
InfoTile({
const InfoTile({
required this.message,
required this.child,
required this.showMessage,
@@ -28,7 +28,7 @@ class InfoTile extends StatelessWidget {
portalAnchor: tileAnchor ?? Alignment.topCenter,
childAnchor: childAnchor ?? Alignment.bottomCenter,
portal: Container(
height: 25.0,
height: 25,
color: backgroundColor ??
StreamChatTheme.of(context).colorTheme.grey.withOpacity(0.9),
child: Center(
@@ -54,7 +54,7 @@ class _MediaListViewState extends State<MediaListView> {
) {
final media = _media.elementAt(position);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 1.0, vertical: 1.0),
padding: const EdgeInsets.symmetric(horizontal: 1, vertical: 1),
child: InkWell(
onTap: () {
if (widget.onSelect != null) {
@@ -64,7 +64,7 @@ class _MediaListViewState extends State<MediaListView> {
child: Stack(
children: [
AspectRatio(
aspectRatio: 1.0,
aspectRatio: 1,
child: FadeInImage(
fadeInDuration: Duration(milliseconds: 300),
placeholder: AssetImage(
@@ -144,9 +144,7 @@ class _MediaListViewState extends State<MediaListView> {
}
void _getMedia() async {
final assetList = await PhotoManager.getAssetPathList(
hasAll: true,
).then((value) {
final assetList = await PhotoManager.getAssetPathList().then((value) {
if (value.isNotEmpty == true) {
return value.singleWhere((element) => element.isAll);
}
@@ -178,7 +176,7 @@ class MediaThumbnailProvider extends ImageProvider<MediaThumbnailProvider> {
ImageStreamCompleter load(key, decode) {
return MultiFrameImageStreamCompleter(
codec: _loadAsync(key, decode),
scale: 1.0,
scale: 1,
informationCollector: () sync* {
yield ErrorDescription('Id: ${media.id}');
},
@@ -20,7 +20,7 @@ class MentionTile extends StatelessWidget {
/// Widget at the end of tile
final Widget? trailing;
MentionTile(
const MentionTile(
this.member, {
this.title,
this.subtitle,
@@ -31,12 +31,11 @@ class MentionTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
height: 56.0,
height: 56,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
width: 16.0,
width: 16,
),
leading ??
UserAvatar(
@@ -49,7 +48,7 @@ class MentionTile extends StatelessWidget {
user: member.user!,
),
SizedBox(
width: 8.0,
width: 8,
),
Expanded(
child: Align(
@@ -60,13 +59,13 @@ class MentionTile extends StatelessWidget {
children: [
title ??
Text(
'${member.user!.name}',
member.user!.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: StreamChatTheme.of(context).textTheme.bodyBold,
),
SizedBox(
height: 2.0,
height: 2,
),
subtitle ??
Text(
@@ -88,8 +87,8 @@ class MentionTile extends StatelessWidget {
trailing ??
Padding(
padding: const EdgeInsets.only(
right: 18.0,
left: 8.0,
right: 18,
left: 8,
),
child: StreamSvgIcon.mentions(
color: StreamChatTheme.of(context).colorTheme.accentBlue,
@@ -119,7 +119,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
),
if (_showActions)
TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
tween: Tween(begin: 0, end: 1),
duration: Duration(milliseconds: 300),
curve: Curves.easeInOutBack,
builder: (context, val, snapshot) {
@@ -128,7 +128,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
child: Center(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: widget.reverse
? CrossAxisAlignment.end
@@ -146,7 +146,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
: (divFactor > 1.0
? 0.0
: -(1.0 - divFactor)),
0.0),
0),
child: ReactionPicker(
message: widget.message,
),
@@ -166,7 +166,6 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
messageTheme: widget.messageTheme,
showReactions: false,
showUsername: false,
showThreadReplyIndicator: false,
showReplyMessage: false,
showUserAvatar: widget.showUserAvatar,
attachmentPadding: EdgeInsets.all(
@@ -176,7 +175,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
translateUserAvatar: false,
padding: const EdgeInsets.all(0),
textPadding: EdgeInsets.symmetric(
vertical: 8.0,
vertical: 8,
horizontal: widget.message.text!.isOnlyEmoji
? 0
: 16.0,
@@ -185,7 +184,6 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
widget.showReactions &&
(widget.message.status ==
MessageSendingStatus.sent),
showInChannelIndicator: false,
showSendingIndicator: false,
shape: widget.messageShape,
attachmentShape: widget.attachmentShape,
@@ -269,7 +267,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
messageAction.onTap?.call(widget.message);
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
child: Row(
children: [
messageAction.leading ?? Offstage(),
@@ -289,7 +287,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
title: 'Flag Message',
icon: StreamSvgIcon.flag(
color: StreamChatTheme.of(context).colorTheme.accentRed,
size: 24.0,
size: 24,
),
question:
'Do you want to send a copy of this message to a\nmoderator for further investigation?',
@@ -305,7 +303,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
context,
icon: StreamSvgIcon.flag(
color: theme.colorTheme.accentRed,
size: 24.0,
size: 24,
),
details: 'The message has been reported to a moderator.',
title: 'Message flagged',
@@ -317,7 +315,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
context,
icon: StreamSvgIcon.flag(
color: theme.colorTheme.accentRed,
size: 24.0,
size: 24,
),
details: 'The message has been reported to a moderator.',
title: 'Message flagged',
@@ -339,7 +337,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
title: 'Delete message',
icon: StreamSvgIcon.flag(
color: StreamChatTheme.of(context).colorTheme.accentRed,
size: 24.0,
size: 24,
),
question: 'Are you sure you want to permanently delete this\nmessage?',
okText: 'DELETE',
@@ -365,7 +363,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
context,
icon: StreamSvgIcon.error(
color: StreamChatTheme.of(context).colorTheme.accentRed,
size: 24.0,
size: 24,
),
details: 'The operation couldn\'t be completed.',
title: 'Something went wrong',
@@ -382,7 +380,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
}
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
child: Row(
children: [
StreamSvgIcon.reply(
@@ -401,9 +399,9 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
Widget _buildFlagButton(BuildContext context) {
return InkWell(
onTap: () => _showFlagDialog(),
onTap: _showFlagDialog,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
child: Row(
children: [
StreamSvgIcon.iconFlag(
@@ -424,9 +422,9 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
final isDeleteFailed =
widget.message.status == MessageSendingStatus.failed_delete;
return InkWell(
onTap: () => _showDeleteDialog(),
onTap: _showDeleteDialog,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
child: Row(
children: [
StreamSvgIcon.delete(
@@ -453,7 +451,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
Navigator.pop(context);
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
child: Row(
children: [
StreamSvgIcon.copy(
@@ -478,7 +476,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
_showEditBottomSheet(context);
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
child: Row(
children: [
StreamSvgIcon.edit(
@@ -509,7 +507,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
}
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
child: Row(
children: [
StreamSvgIcon.circleUp(
@@ -555,7 +553,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: StreamSvgIcon.edit(
color: StreamChatTheme.of(context)
.colorTheme
@@ -574,16 +572,17 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
],
),
),
widget.editMessageInputBuilder != null
? widget.editMessageInputBuilder!(context, widget.message)
: MessageInput(
editMessage: widget.message,
preMessageSending: (m) {
FocusScope.of(context).unfocus();
Navigator.pop(context);
return m;
},
),
if (widget.editMessageInputBuilder != null)
widget.editMessageInputBuilder!(context, widget.message)
else
MessageInput(
editMessage: widget.message,
preMessageSending: (m) {
FocusScope.of(context).unfocus();
Navigator.pop(context);
return m;
},
),
],
),
);
@@ -600,7 +599,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
}
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 11.0, horizontal: 16.0),
padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16),
child: Row(
children: [
StreamSvgIcon.thread(
@@ -109,7 +109,7 @@ const _kMaxAttachmentSize = 20971520; // 20MB in Bytes
/// Modify it to change the widget appearance.
class MessageInput extends StatefulWidget {
/// Instantiate a new MessageInput
MessageInput({
const MessageInput({
Key? key,
this.onMessageSent,
this.preMessageSending,
@@ -306,7 +306,7 @@ class MessageInputState extends State<MessageInput> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: StreamSvgIcon.reply(
color: StreamChatTheme.of(context)
.colorTheme
@@ -326,15 +326,15 @@ class MessageInputState extends State<MessageInput> {
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
padding: const EdgeInsets.symmetric(vertical: 8),
child: _buildTextField(context),
),
if (widget.parentMessage != null && !widget.hideSendAsDm)
Padding(
padding: const EdgeInsets.only(
right: 12.0,
left: 12.0,
bottom: 12.0,
right: 12,
left: 12,
bottom: 12,
),
child: _buildDmCheckbox(),
),
@@ -356,7 +356,6 @@ class MessageInputState extends State<MessageInput> {
Flex _buildTextField(BuildContext context) {
return Flex(
direction: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
if (!_commandEnabled && widget.actionsLocation == ActionsLocation.left)
_buildExpandActionsButton(),
@@ -371,7 +370,6 @@ class MessageInputState extends State<MessageInput> {
Widget _buildDmCheckbox() {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 16,
@@ -407,7 +405,7 @@ class MessageInputState extends State<MessageInput> {
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
firstChild: StreamSvgIcon.check(
size: 16.0,
size: 16,
color: StreamChatTheme.of(context).colorTheme.white,
),
secondChild: SizedBox(
@@ -420,7 +418,7 @@ class MessageInputState extends State<MessageInput> {
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text(
'Also send as direct message',
style: StreamChatTheme.of(context).textTheme.footnote.copyWith(
@@ -456,7 +454,7 @@ class MessageInputState extends State<MessageInput> {
Widget _buildExpandActionsButton() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: AnimatedCrossFade(
crossFadeState: _actionsShrunk
? CrossFadeState.showFirst
@@ -464,7 +462,6 @@ class MessageInputState extends State<MessageInput> {
firstChild: IconButton(
onPressed: () => setState(() => _actionsShrunk = false),
icon: Transform.rotate(
alignment: Alignment.center,
angle: (widget.actionsLocation == ActionsLocation.right ||
widget.actionsLocation == ActionsLocation.rightInside)
? pi
@@ -484,7 +481,6 @@ class MessageInputState extends State<MessageInput> {
),
secondChild: FittedBox(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
if (!widget.disableAttachments) _buildAttachmentButton(),
@@ -510,10 +506,10 @@ class MessageInputState extends State<MessageInput> {
Expanded _buildTextInput(BuildContext context) {
final theme = StreamChatTheme.of(context);
final margin = (widget.sendButtonLocation == SendButtonLocation.inside
? const EdgeInsets.only(right: 8.0)
? const EdgeInsets.only(right: 8)
: EdgeInsets.zero) +
(widget.actionsLocation != ActionsLocation.left
? const EdgeInsets.only(left: 8.0)
? const EdgeInsets.only(left: 8)
: EdgeInsets.zero);
return Expanded(
child: Center(
@@ -545,7 +541,6 @@ class MessageInputState extends State<MessageInput> {
child: TextField(
key: Key('messageInputText'),
enabled: _inputEnabled,
minLines: null,
maxLines: null,
onSubmitted: (_) => sendMessage(),
keyboardType: widget.keyboardType,
@@ -607,7 +602,7 @@ class MessageInputState extends State<MessageInput> {
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: Container(
constraints: BoxConstraints.tight(Size(64, 24)),
decoration: BoxDecoration(
@@ -620,7 +615,7 @@ class MessageInputState extends State<MessageInput> {
children: [
StreamSvgIcon.lightning(
color: Colors.white,
size: 16.0,
size: 16,
),
Text(
_chosenCommand?.name.toUpperCase() ?? '',
@@ -640,7 +635,6 @@ class MessageInputState extends State<MessageInput> {
: (widget.actionsLocation == ActionsLocation.leftInside
? Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_buildExpandActionsButton(),
],
@@ -650,11 +644,10 @@ class MessageInputState extends State<MessageInput> {
prefixIconConstraints: BoxConstraints.tightFor(height: 40),
suffixIcon: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (_commandEnabled)
Padding(
padding: const EdgeInsets.only(right: 8.0),
padding: const EdgeInsets.only(right: 8),
child: IconButton(
icon: StreamSvgIcon.closeSmall(),
splashRadius: 24,
@@ -776,7 +769,7 @@ class MessageInputState extends State<MessageInput> {
void _checkCommands(String s, BuildContext context) {
if (s.startsWith('/')) {
var matchedCommandsList = StreamChannel.of(context)
final matchedCommandsList = StreamChannel.of(context)
.channel
.config
?.commands
@@ -825,19 +818,18 @@ class MessageInputState extends State<MessageInput> {
left: 0,
right: 0,
child: TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
tween: Tween(begin: 0, end: 1),
duration: Duration(milliseconds: 300),
curve: Curves.easeInOutExpo,
builder: (context, val, wid) {
return Transform.scale(
alignment: Alignment.center,
scale: val,
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: Card(
elevation: 2.0,
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
borderRadius: BorderRadius.circular(8),
),
color: StreamChatTheme.of(context).colorTheme.white,
clipBehavior: Clip.antiAlias,
@@ -845,20 +837,19 @@ class MessageInputState extends State<MessageInput> {
constraints: BoxConstraints.loose(Size.fromHeight(400)),
decoration: BoxDecoration(
color: StreamChatTheme.of(context).colorTheme.white,
borderRadius: BorderRadius.circular(8.0)),
borderRadius: BorderRadius.circular(8)),
child: ListView(
padding: const EdgeInsets.all(0),
shrinkWrap: true,
children: [
if (commands.isNotEmpty)
Padding(
padding:
const EdgeInsets.only(left: 0.0, top: 8.0),
padding: const EdgeInsets.only(top: 8),
child: Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
horizontal: 8,
),
child: StreamSvgIcon.lightning(
color: StreamChatTheme.of(context)
@@ -879,7 +870,7 @@ class MessageInputState extends State<MessageInput> {
),
),
SizedBox(
height: 10.0,
height: 10,
),
...commands
.map(
@@ -888,19 +879,19 @@ class MessageInputState extends State<MessageInput> {
_setCommand(c);
},
child: Container(
height: 40.0,
height: 40,
child: Row(
children: [
SizedBox(
width: 16.0,
width: 16,
),
_buildCommandIcon(c.name),
SizedBox(
width: 8.0,
width: 8,
),
Text.rich(
TextSpan(
text: '${c.name.capitalize()}',
text: c.name.capitalize(),
style: TextStyle(
fontWeight: FontWeight.bold),
children: [
@@ -987,10 +978,8 @@ class MessageInputState extends State<MessageInput> {
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
iconSize: 24,
icon: StreamSvgIcon.pictures(
color: _getIconColor(0),
),
@@ -1010,11 +999,10 @@ class MessageInputState extends State<MessageInput> {
onPressed: !_attachmentContainsFile && _attachments.isNotEmpty
? null
: () {
pickFile(DefaultAttachmentTypes.file, false);
pickFile(DefaultAttachmentTypes.file);
},
),
IconButton(
iconSize: 24,
icon: StreamSvgIcon.camera(
color: _getIconColor(2),
),
@@ -1026,7 +1014,6 @@ class MessageInputState extends State<MessageInput> {
),
IconButton(
padding: const EdgeInsets.all(0),
iconSize: 24,
icon: StreamSvgIcon.record(
color: _getIconColor(3),
),
@@ -1052,22 +1039,22 @@ class MessageInputState extends State<MessageInput> {
decoration: BoxDecoration(
color: StreamChatTheme.of(context).colorTheme.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0),
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: Container(
width: double.infinity,
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: Container(
width: 40.0,
height: 4.0,
width: 40,
height: 4,
decoration: BoxDecoration(
color:
StreamChatTheme.of(context).colorTheme.whiteSmoke,
borderRadius: BorderRadius.circular(4.0),
borderRadius: BorderRadius.circular(4),
),
),
),
@@ -1080,7 +1067,7 @@ class MessageInputState extends State<MessageInput> {
child: Container(
decoration: BoxDecoration(
color: StreamChatTheme.of(context).colorTheme.white,
borderRadius: BorderRadius.circular(8.0),
borderRadius: BorderRadius.circular(8),
),
child: _PickerWidget(
filePickerIndex: _filePickerIndex,
@@ -1159,7 +1146,7 @@ class MessageInputState extends State<MessageInput> {
return CircleAvatar(
radius: 12,
child: StreamSvgIcon.giphyIcon(
size: 24.0,
size: 24,
),
);
case 'ban':
@@ -1167,7 +1154,7 @@ class MessageInputState extends State<MessageInput> {
backgroundColor: StreamChatTheme.of(context).colorTheme.accentBlue,
radius: 12,
child: StreamSvgIcon.iconUserDelete(
size: 16.0,
size: 16,
color: Colors.white,
),
);
@@ -1176,7 +1163,7 @@ class MessageInputState extends State<MessageInput> {
backgroundColor: StreamChatTheme.of(context).colorTheme.accentBlue,
radius: 12,
child: StreamSvgIcon.flag(
size: 14.0,
size: 14,
color: Colors.white,
),
);
@@ -1186,7 +1173,7 @@ class MessageInputState extends State<MessageInput> {
radius: 12,
child: ClipOval(
child: StreamSvgIcon.imgur(
size: 24.0,
size: 24,
),
),
);
@@ -1195,7 +1182,7 @@ class MessageInputState extends State<MessageInput> {
backgroundColor: StreamChatTheme.of(context).colorTheme.accentBlue,
radius: 12,
child: StreamSvgIcon.mute(
size: 16.0,
size: 16,
color: Colors.white,
),
);
@@ -1204,7 +1191,7 @@ class MessageInputState extends State<MessageInput> {
backgroundColor: StreamChatTheme.of(context).colorTheme.accentBlue,
radius: 12,
child: StreamSvgIcon.userAdd(
size: 16.0,
size: 16,
color: Colors.white,
),
);
@@ -1213,7 +1200,7 @@ class MessageInputState extends State<MessageInput> {
backgroundColor: StreamChatTheme.of(context).colorTheme.accentBlue,
radius: 12,
child: StreamSvgIcon.volumeUp(
size: 16.0,
size: 16,
color: Colors.white,
),
);
@@ -1222,7 +1209,7 @@ class MessageInputState extends State<MessageInput> {
backgroundColor: StreamChatTheme.of(context).colorTheme.accentBlue,
radius: 12,
child: StreamSvgIcon.lightning(
size: 16.0,
size: 16,
color: Colors.white,
),
);
@@ -1263,18 +1250,18 @@ class MessageInputState extends State<MessageInput> {
left: 0,
right: 0,
child: TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
tween: Tween(begin: 0, end: 1),
duration: Duration(milliseconds: 300),
curve: Curves.easeInOutExpo,
builder: (context, val, wid) {
return Transform.scale(
scale: val,
child: Card(
margin: EdgeInsets.all(8.0),
elevation: 2.0,
margin: EdgeInsets.all(8),
elevation: 2,
color: StreamChatTheme.of(context).colorTheme.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
borderRadius: BorderRadius.circular(8),
),
clipBehavior: Clip.antiAlias,
child: Container(
@@ -1291,7 +1278,7 @@ class MessageInputState extends State<MessageInput> {
shrinkWrap: true,
children: [
SizedBox(
height: 8.0,
height: 8,
),
...snapshot.data!
.where((it) => it.user != null)
@@ -1333,7 +1320,7 @@ class MessageInputState extends State<MessageInput> {
},
).toList(),
SizedBox(
height: 8.0,
height: 8,
),
],
);
@@ -1361,7 +1348,7 @@ class MessageInputState extends State<MessageInput> {
final emojis = _emojiNames
.where((e) => e.contains(query))
.map((e) => Emoji.byName(e))
.map(Emoji.byName)
.where((e) => e != null);
if (emojis.isEmpty) {
@@ -1377,11 +1364,11 @@ class MessageInputState extends State<MessageInput> {
left: 0,
right: 0,
child: Card(
margin: EdgeInsets.all(8.0),
elevation: 2.0,
margin: EdgeInsets.all(8),
elevation: 2,
color: StreamChatTheme.of(context).colorTheme.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
borderRadius: BorderRadius.circular(8),
),
clipBehavior: Clip.antiAlias,
child: Container(
@@ -1390,7 +1377,7 @@ class MessageInputState extends State<MessageInput> {
boxShadow: [
BoxShadow(
spreadRadius: -8,
blurRadius: 5.0,
blurRadius: 5,
offset: Offset(0, -4),
),
],
@@ -1403,12 +1390,11 @@ class MessageInputState extends State<MessageInput> {
itemBuilder: (context, i) {
if (i == 0) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
padding: const EdgeInsets.only(left: 8, top: 8),
child: Row(
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
padding: const EdgeInsets.symmetric(horizontal: 8),
child: StreamSvgIcon.smile(
color: StreamChatTheme.of(context)
.colorTheme
@@ -1516,7 +1502,7 @@ class MessageInputState extends State<MessageInput> {
Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: LimitedBox(
maxHeight: 136.0,
maxHeight: 136,
child: ListView(
reverse: true,
shrinkWrap: true,
@@ -1524,16 +1510,15 @@ class MessageInputState extends State<MessageInput> {
.map<Widget>(
(e) => ClipRRect(
borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.antiAlias,
child: FileAttachment(
message: Message(), // dummy message
attachment: e,
size: Size(
MediaQuery.of(context).size.width * 0.65,
56.0,
56,
),
trailing: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: _buildRemoveButton(e),
),
),
@@ -1547,18 +1532,17 @@ class MessageInputState extends State<MessageInput> {
Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: LimitedBox(
maxHeight: 104.0,
maxHeight: 104,
child: ListView(
scrollDirection: Axis.horizontal,
children: remainingAttachments
.map<Widget>(
(attachment) => ClipRRect(
borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.antiAlias,
child: Stack(
children: <Widget>[
AspectRatio(
aspectRatio: 1.0,
aspectRatio: 1,
child: Container(
height: 104,
width: 104,
@@ -1593,7 +1577,6 @@ class MessageInputState extends State<MessageInput> {
elevation: 0,
highlightElevation: 0,
focusElevation: 0,
disabledElevation: 0,
hoverElevation: 0,
onPressed: () {
setState(() => _attachments.remove(attachment.id));
@@ -1803,7 +1786,7 @@ class MessageInputState extends State<MessageInput> {
leading: Icon(Icons.image),
title: Text('Upload a photo'),
onTap: () {
pickFile(DefaultAttachmentTypes.image, false);
pickFile(DefaultAttachmentTypes.image);
Navigator.pop(context);
},
),
@@ -1811,7 +1794,7 @@ class MessageInputState extends State<MessageInput> {
leading: Icon(Icons.video_library),
title: Text('Upload a video'),
onTap: () {
pickFile(DefaultAttachmentTypes.video, false);
pickFile(DefaultAttachmentTypes.video);
Navigator.pop(context);
},
),
@@ -1837,7 +1820,7 @@ class MessageInputState extends State<MessageInput> {
leading: Icon(Icons.insert_drive_file),
title: Text('Upload a file'),
onTap: () {
pickFile(DefaultAttachmentTypes.file, false);
pickFile(DefaultAttachmentTypes.file);
Navigator.pop(context);
},
),
@@ -1967,7 +1950,7 @@ class MessageInputState extends State<MessageInput> {
Widget _buildIdleSendButton(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: StreamSvgIcon(
assetName: _getIdleSendIcon(),
color:
@@ -1978,7 +1961,7 @@ class MessageInputState extends State<MessageInput> {
Widget _buildSendButton(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: IconButton(
onPressed: sendMessage,
padding: const EdgeInsets.all(0),
@@ -2112,44 +2095,44 @@ class MessageInputState extends State<MessageInput> {
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0),
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
)),
builder: (context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 26.0,
height: 26,
),
StreamSvgIcon.error(
color: StreamChatTheme.of(context).colorTheme.accentRed,
size: 24.0,
size: 24,
),
SizedBox(
height: 26.0,
height: 26,
),
Text(
'Something went wrong',
style: StreamChatTheme.of(context).textTheme.headlineBold,
),
SizedBox(
height: 7.0,
height: 7,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
description,
textAlign: TextAlign.center,
),
),
SizedBox(
height: 36.0,
height: 36,
),
Container(
color:
StreamChatTheme.of(context).colorTheme.black.withOpacity(.08),
height: 1.0,
height: 1,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
@@ -2345,7 +2328,7 @@ class __PickerWidgetState extends State<_PickerWidget> {
color: StreamChatTheme.of(context).colorTheme.grey),
textAlign: TextAlign.center,
),
SizedBox(height: 6.0),
SizedBox(height: 6),
Center(
child: Text(
'Allow access to your gallery',
@@ -111,7 +111,7 @@ class MessageDetails {
/// Modify it to change the widget appearance.
class MessageListView extends StatefulWidget {
/// Instantiate a new MessageListView
MessageListView({
const MessageListView({
Key? key,
this.showScrollToBottom = true,
this.messageBuilder,
@@ -418,7 +418,6 @@ class _MessageListViewState extends State<MessageListView> {
child: ScrollablePositionedList.separated(
key: ValueKey(initialIndex! + initialAlignment!),
itemPositionsListener: _itemPositionListener,
addAutomaticKeepAlives: true,
initialScrollIndex: initialIndex ?? 0,
initialAlignment: initialAlignment ?? 0,
physics: widget.scrollPhysics,
@@ -437,7 +436,7 @@ class _MessageListViewState extends State<MessageListView> {
StreamChatTheme.of(context).colorTheme.bgGradient,
),
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: Text(
'$replyCount ${replyCount == 1 ? 'Reply' : 'Replies'}',
textAlign: TextAlign.center,
@@ -464,7 +463,7 @@ class _MessageListViewState extends State<MessageListView> {
dateTime: nextMessage.createdAt.toLocal(),
);
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
padding: const EdgeInsets.symmetric(vertical: 12),
child: divider,
);
}
@@ -554,7 +553,7 @@ class _MessageListViewState extends State<MessageListView> {
),
if (widget.showScrollToBottom) _buildScrollToBottom(),
Positioned(
top: 20.0,
top: 20,
child: ValueListenableBuilder<Iterable<ItemPosition>>(
valueListenable: _itemPositionListener.itemPositions,
builder: (context, values, _) {
@@ -660,7 +659,7 @@ class _MessageListViewState extends State<MessageListView> {
top: -10,
child: CircleAvatar(
child: Padding(
padding: const EdgeInsets.all(3.0),
padding: const EdgeInsets.all(3),
child: Text(
'$unreadCount',
style: TextStyle(
@@ -712,7 +711,7 @@ class _MessageListViewState extends State<MessageListView> {
}
return Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: const CircularProgressIndicator(),
),
);
@@ -799,8 +798,6 @@ class _MessageListViewState extends State<MessageListView> {
final isOnlyEmoji = message.text!.isOnlyEmoji;
return MessageWidget(
showThreadReplyIndicator: false,
showInChannelIndicator: false,
showReplyMessage: false,
showResendMessage: false,
showThreadReplyMessage: false,
@@ -810,7 +807,7 @@ class _MessageListViewState extends State<MessageListView> {
message: message,
reverse: isMyMessage,
showUsername: !isMyMessage,
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
showSendingIndicator: false,
onThreadTap: _onThreadTap as void Function(Message)?,
borderRadiusGeometry: BorderRadius.only(
@@ -820,7 +817,7 @@ class _MessageListViewState extends State<MessageListView> {
bottomRight: Radius.circular(16),
),
textPadding: EdgeInsets.symmetric(
vertical: 8.0,
vertical: 8,
horizontal: isOnlyEmoji ? 0 : 16.0,
),
borderSide: isMyMessage || isOnlyEmoji ? BorderSide.none : null,
@@ -940,7 +937,7 @@ class _MessageListViewState extends State<MessageListView> {
message: message,
reverse: isMyMessage,
showReactions: !message.isDeleted,
padding: const EdgeInsets.symmetric(horizontal: 8.0),
padding: const EdgeInsets.symmetric(horizontal: 8),
showInChannelIndicator: showInChannelIndicator,
showThreadReplyIndicator: showThreadReplyIndicator,
showUsername: showUsername,
@@ -997,7 +994,7 @@ class _MessageListViewState extends State<MessageListView> {
bottomRight: Radius.circular(16),
),
textPadding: EdgeInsets.symmetric(
vertical: 8.0,
vertical: 8,
horizontal: isOnlyEmoji ? 0 : 16.0,
),
messageTheme: isMyMessage
@@ -1069,7 +1066,7 @@ class _MessageListViewState extends State<MessageListView> {
);
},
child: Padding(
padding: const EdgeInsets.only(top: 4.0),
padding: const EdgeInsets.only(top: 4),
child: child,
),
);
@@ -59,7 +59,7 @@ class MessageReactionsModal extends StatelessWidget {
: (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize));
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
tween: Tween(begin: 0, end: 1),
duration: Duration(milliseconds: 300),
curve: Curves.easeInOutBack,
builder: (context, val, snapshot) {
@@ -86,7 +86,7 @@ class MessageReactionsModal extends StatelessWidget {
child: Center(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -102,7 +102,7 @@ class MessageReactionsModal extends StatelessWidget {
: (divFactor > 1.0
? 0.0
: -(1.0 - divFactor)),
0.0),
0),
child: ReactionPicker(
message: message,
),
@@ -121,7 +121,6 @@ class MessageReactionsModal extends StatelessWidget {
showReactions: false,
showUsername: false,
showUserAvatar: showUserAvatar,
showThreadReplyIndicator: false,
showTimestamp: false,
translateUserAvatar: false,
showSendingIndicator: false,
@@ -133,9 +132,8 @@ class MessageReactionsModal extends StatelessWidget {
attachmentPadding: EdgeInsets.all(
hasFileAttachment ? 4 : 2,
),
showInChannelIndicator: false,
textPadding: EdgeInsets.symmetric(
vertical: 8.0,
vertical: 8,
horizontal:
message.text!.isOnlyEmoji ? 0 : 16.0,
),
@@ -184,7 +182,6 @@ class MessageReactionsModal extends StatelessWidget {
child: Wrap(
spacing: 16,
runSpacing: 16,
alignment: WrapAlignment.start,
children: message.latestReactions!
.map((e) => _buildReaction(
e,
@@ -214,8 +211,6 @@ class MessageReactionsModal extends StatelessWidget {
)),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Stack(
clipBehavior: Clip.none,
@@ -147,8 +147,8 @@ class MessageSearchItem extends StatelessWidget {
List<Attachment> attachments,
TextStyle? normalTextStyle,
TextStyle? mentionsTextStyle) {
var textList = text.split(' ');
var resList = <TextSpan>[];
final textList = text.split(' ');
final resList = <TextSpan>[];
for (var e in textList) {
if (mentions.isNotEmpty &&
mentions.any((element) => '@${element.name}' == e)) {
@@ -166,7 +166,7 @@ class MessageSearchItem extends StatelessWidget {
));
} else {
resList.add(TextSpan(
text: e == textList.last ? '$e' : '$e ',
text: e == textList.last ? e : '$e ',
style: normalTextStyle,
));
}
@@ -189,10 +189,7 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
},
);
},
childBuilder: widget.childBuilder ??
(list) {
return _buildListView(list);
},
childBuilder: widget.childBuilder ?? _buildListView,
);
}
@@ -228,7 +225,7 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
.accentRed
.withOpacity(.2),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
padding: const EdgeInsets.symmetric(vertical: 16),
child: Center(
child: Text('Error loading messages'),
),
@@ -201,8 +201,8 @@ class MessageWidget extends StatefulWidget {
this.readList,
this.padding,
this.textPadding = const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
horizontal: 16,
vertical: 8,
),
this.attachmentPadding = EdgeInsets.zero,
this.allRead = false,
@@ -211,8 +211,7 @@ class MessageWidget extends StatefulWidget {
this.onAttachmentTap,
}) : attachmentBuilders = {
'image': (context, message, attachments) {
var border = RoundedRectangleBorder(
side: BorderSide.none,
final border = RoundedRectangleBorder(
borderRadius: attachmentBorderRadiusGeometry ?? BorderRadius.zero,
);
@@ -267,8 +266,7 @@ class MessageWidget extends StatefulWidget {
);
},
'video': (context, message, attachments) {
var border = RoundedRectangleBorder(
side: BorderSide.none,
final border = RoundedRectangleBorder(
borderRadius: attachmentBorderRadiusGeometry ?? BorderRadius.zero,
);
@@ -302,7 +300,6 @@ class MessageWidget extends StatefulWidget {
},
'giphy': (context, message, attachments) {
final border = RoundedRectangleBorder(
side: BorderSide.none,
borderRadius: attachmentBorderRadiusGeometry ?? BorderRadius.zero,
);
@@ -329,7 +326,7 @@ class MessageWidget extends StatefulWidget {
);
},
'file': (context, message, attachments) {
var border = RoundedRectangleBorder(
final border = RoundedRectangleBorder(
side: attachmentBorderSide ??
BorderSide(
color: StreamChatTheme.of(context).colorTheme.greyWhisper,
@@ -426,7 +423,7 @@ class _MessageWidgetState extends State<MessageWidget>
super.build(context);
final avatarWidth =
widget.messageTheme.avatarTheme?.constraints.maxWidth ?? 40;
var leftPadding =
final leftPadding =
widget.showUserAvatar != DisplayWidget.gone ? avatarWidth + 8.5 : 0.5;
return Material(
@@ -460,7 +457,6 @@ class _MessageWidgetState extends State<MessageWidget>
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
@@ -481,8 +477,8 @@ class _MessageWidgetState extends State<MessageWidget>
BoxConstraints(maxWidth: 22 * 6.0),
child: _buildReactionIndicator(context),
),
portalAnchor: Alignment(-1.0, -1.0),
childAnchor: Alignment(1, -1.0),
portalAnchor: Alignment(-1, -1),
childAnchor: Alignment(1, -1),
child: Stack(
clipBehavior: Clip.none,
children: [
@@ -526,7 +522,7 @@ class _MessageWidgetState extends State<MessageWidget>
)
: Card(
clipBehavior: Clip.antiAlias,
elevation: 0.0,
elevation: 0,
margin: EdgeInsets.symmetric(
horizontal: (isFailedState
? 15.0
@@ -650,9 +646,9 @@ class _MessageWidgetState extends State<MessageWidget>
children: [
StreamSvgIcon.eye(
color: StreamChatTheme.of(context).colorTheme.grey,
size: 16.0,
size: 16,
),
SizedBox(width: 8.0),
SizedBox(width: 8),
Text(
'Only visible to you',
style: StreamChatTheme.of(context)
@@ -665,7 +661,7 @@ class _MessageWidgetState extends State<MessageWidget>
);
}
var children = <Widget>[];
final children = <Widget>[];
final threadParticipants = widget.message.threadParticipants?.take(2);
final showThreadParticipants = threadParticipants?.isNotEmpty == true;
@@ -757,18 +753,18 @@ class _MessageWidgetState extends State<MessageWidget>
return mappedChild;
},
),
].insertBetween(const SizedBox(width: 8.0)),
].insertBetween(const SizedBox(width: 8)),
);
}
Widget _buildUrlAttachment() {
var urlAttachment = widget.message.attachments
final urlAttachment = widget.message.attachments
.firstWhere((element) => element.ogScrapeUrl != null);
var host = Uri.parse(urlAttachment.ogScrapeUrl!).host;
var splitList = host.split('.');
var hostName = splitList.length == 3 ? splitList[1] : splitList[0];
var hostDisplayName = urlAttachment.authorName?.capitalize() ??
final host = Uri.parse(urlAttachment.ogScrapeUrl!).host;
final splitList = host.split('.');
final hostName = splitList.length == 3 ? splitList[1] : splitList[0];
final hostDisplayName = urlAttachment.authorName?.capitalize() ??
getWebsiteName(hostName.toLowerCase()) ??
hostName.capitalize();
@@ -11,7 +11,7 @@ class OptionListTile extends StatelessWidget {
final Color? separatorColor;
final TextStyle? titleTextStyle;
OptionListTile({
const OptionListTile({
this.title,
this.leading,
this.trailing,
@@ -29,12 +29,12 @@ class OptionListTile extends StatelessWidget {
Container(
color: separatorColor ??
StreamChatTheme.of(context).colorTheme.greyGainsboro,
height: 1.0,
height: 1,
),
Material(
color: tileColor ?? StreamChatTheme.of(context).colorTheme.white,
child: Container(
height: 63.0,
height: 63,
child: InkWell(
onTap: onTap,
child: Row(
@@ -42,7 +42,7 @@ class OptionListTile extends StatelessWidget {
if (leading != null) Center(child: leading),
if (leading == null)
SizedBox(
width: 16.0,
width: 16,
),
Expanded(
flex: 4,
@@ -62,7 +62,7 @@ class OptionListTile extends StatelessWidget {
Expanded(
flex: 2,
child: Padding(
padding: const EdgeInsets.only(right: 16.0),
padding: const EdgeInsets.only(right: 16),
child: Align(
alignment: Alignment.centerRight,
child: trailing ?? Container(),
@@ -87,7 +87,7 @@ class QuotedMessageWidget extends StatelessWidget {
final GestureTapCallback? onTap;
///
QuotedMessageWidget({
const QuotedMessageWidget({
Key? key,
required this.message,
required this.messageTheme,
@@ -237,7 +237,7 @@ class QuotedMessageWidget extends StatelessWidget {
ShapeBorder _getDefaultShape(BuildContext context) {
return RoundedRectangleBorder(
side: BorderSide(width: 0.0, color: Colors.transparent),
side: BorderSide(width: 0, color: Colors.transparent),
borderRadius: BorderRadius.circular(8),
);
}
@@ -40,7 +40,6 @@ class ReactionBubble extends StatelessWidget {
alignment: Alignment.center,
child: Stack(
alignment: Alignment.center,
fit: StackFit.loose,
children: [
Transform.translate(
offset: Offset(reverse ? offset : -offset, 0),
@@ -115,7 +114,7 @@ class ReactionBubble extends StatelessWidget {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 4.0,
horizontal: 4,
),
child: reactionIcon != null
? StreamSvgIcon(
@@ -239,9 +238,9 @@ class ReactionBubblePainter extends CustomPainter {
..strokeWidth = 1
..style = PaintingStyle.stroke;
final dy = -2.2;
final startAngle = 1.1;
final sweepAngle = 1.2;
const dy = -2.2;
const startAngle = 1.1;
const sweepAngle = 1.2;
final path = Path();
path.addArc(
Rect.fromCircle(
@@ -259,9 +258,9 @@ class ReactionBubblePainter extends CustomPainter {
..color = color
..strokeWidth = 1;
final dy = -2.2;
final startAngle = 1;
final sweepAngle = 1.3;
const dy = -2.2;
const startAngle = 1;
const sweepAngle = 1.3;
final path = Path();
path.addArc(
Rect.fromCircle(
@@ -280,9 +279,9 @@ class ReactionBubblePainter extends CustomPainter {
..strokeWidth = 1
..style = PaintingStyle.fill;
final dy = -2.2;
final startAngle = 1.1;
final sweepAngle = 1.2;
const dy = -2.2;
const startAngle = 1.1;
const sweepAngle = 1.2;
final path = Path();
path.addArc(
Rect.fromCircle(
@@ -49,7 +49,7 @@ class _ReactionPickerState extends State<ReactionPicker>
}
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
tween: Tween(begin: 0, end: 1),
curve: Curves.easeInOutBack,
duration: Duration(milliseconds: 500),
builder: (context, val, wid) {
@@ -61,8 +61,8 @@ class _ReactionPickerState extends State<ReactionPicker>
clipBehavior: Clip.hardEdge,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
horizontal: 16,
vertical: 8,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -74,7 +74,7 @@ class _ReactionPickerState extends State<ReactionPicker>
?.indexWhere((reaction) =>
reaction.type == reactionIcon.type) ??
-1;
var index = reactionIcons.indexOf(reactionIcon);
final index = reactionIcons.indexOf(reactionIcon);
return ConstrainedBox(
constraints: BoxConstraints.tightFor(
@@ -83,8 +83,6 @@ class _ReactionPickerState extends State<ReactionPicker>
),
child: RawMaterialButton(
elevation: 0,
padding: const EdgeInsets.all(0),
clipBehavior: Clip.none,
shape: ContinuousRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
@@ -110,7 +108,6 @@ class _ReactionPickerState extends State<ReactionPicker>
animation: animations[index],
builder: (context, val) {
return Transform.scale(
alignment: Alignment.center,
scale: animations[index].value,
child: StreamSvgIcon(
assetName: reactionIcon.assetName,
@@ -43,7 +43,7 @@ class StreamChat extends StatefulWidget {
/// upon the [Event.type]
final EventHandler? onBackgroundEventReceived;
StreamChat({
const StreamChat({
Key? key,
required this.client,
required this.child,
@@ -13,7 +13,7 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
class StreamChatTheme extends InheritedWidget {
final StreamChatThemeData data;
StreamChatTheme({
const StreamChatTheme({
Key? key,
required this.data,
required Widget child,
@@ -237,7 +237,7 @@ class StreamChatThemeData {
lastMessageAt: textTheme.footnote.copyWith(
color: colorTheme.black.withOpacity(.5),
),
indicatorIconSize: 16.0),
indicatorIconSize: 16),
channelListHeaderTheme: ChannelListHeaderTheme(
avatarTheme: AvatarTheme(
borderRadius: BorderRadius.circular(20),
@@ -543,17 +543,13 @@ class ColorTheme {
stops: [0, 1],
),
this.borderTop = const Effect(
sigmaX: 0,
sigmaY: -1,
color: Color(0xff000000),
blur: 0.0,
alpha: 0.08),
sigmaX: 0, sigmaY: -1, color: Color(0xff000000), blur: 0, alpha: 0.08),
this.borderBottom = const Effect(
sigmaX: 0, sigmaY: 1, color: Color(0xff000000), blur: 0.0, alpha: 0.08),
sigmaX: 0, sigmaY: 1, color: Color(0xff000000), blur: 0, alpha: 0.08),
this.shadowIconButton = const Effect(
sigmaX: 0, sigmaY: 2, color: Color(0xff000000), alpha: 0.5, blur: 4.0),
sigmaX: 0, sigmaY: 2, color: Color(0xff000000), alpha: 0.5, blur: 4),
this.modalShadow = const Effect(
sigmaX: 0, sigmaY: 0, color: Color(0xff000000), alpha: 1, blur: 8.0),
sigmaX: 0, sigmaY: 0, color: Color(0xff000000), alpha: 1, blur: 8),
}) : brightness = Brightness.light;
ColorTheme.dark({
@@ -572,28 +568,28 @@ class ColorTheme {
sigmaX: 0,
sigmaY: -1,
color: Color(0xff141924),
blur: 0.0,
blur: 0,
),
this.borderBottom = const Effect(
sigmaX: 0,
sigmaY: 1,
color: Color(0xff141924),
blur: 0.0,
alpha: 1.0,
blur: 0,
alpha: 1,
),
this.shadowIconButton = const Effect(
sigmaX: 0,
sigmaY: 2,
color: Color(0xff000000),
alpha: 0.5,
blur: 4.0,
blur: 4,
),
this.modalShadow = const Effect(
sigmaX: 0,
sigmaY: 0,
color: Color(0xff000000),
alpha: 1,
blur: 8.0,
blur: 8,
),
this.highlight = const Color(0xff302d22),
this.overlay = const Color.fromRGBO(0, 0, 0, 0.4),
@@ -13,7 +13,7 @@ class StreamNeumorphicButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(8.0),
margin: EdgeInsets.all(8),
height: 40,
width: 40,
decoration: BoxDecoration(
@@ -22,15 +22,12 @@ class StreamNeumorphicButton extends StatelessWidget {
boxShadow: [
BoxShadow(
color: Colors.grey.shade700,
offset: Offset(0, 1.0),
offset: Offset(0, 1),
blurRadius: 0.5,
spreadRadius: 0,
),
BoxShadow(
color: Colors.white,
offset: Offset.zero,
blurRadius: 0.5,
spreadRadius: 0,
),
],
),
@@ -25,7 +25,6 @@ class StreamSvgIcon extends StatelessWidget {
width: width,
height: height,
color: color,
alignment: Alignment.center,
);
}
@@ -28,7 +28,7 @@ class Swipeable extends StatefulWidget {
}
class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin {
double _dragExtent = 0.0;
double _dragExtent = 0;
late AnimationController _moveController;
late AnimationController _iconMoveController;
late Animation<Offset> _moveAnimation;
@@ -45,15 +45,15 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin {
AnimationController(duration: _animationDuration, vsync: this);
_iconMoveController =
AnimationController(duration: _animationDuration, vsync: this);
_moveAnimation = Tween<Offset>(begin: Offset.zero, end: Offset(1.0, 0.0))
_moveAnimation = Tween<Offset>(begin: Offset.zero, end: Offset(1, 0))
.animate(_moveController);
_iconTransitionAnimation =
Tween<Offset>(begin: Offset(-0.1, 0.0), end: Offset(0.4, 0.0))
Tween<Offset>(begin: Offset(-0.1, 0), end: Offset(0.4, 0))
.animate(_moveController);
_iconFadeAnimation =
Tween<double>(begin: 0.7, end: 1.0).animate(_iconMoveController);
Tween<double>(begin: 0.7, end: 1).animate(_iconMoveController);
final controllerValue = 0.0;
const controllerValue = 0.0;
_moveController.animateTo(controllerValue);
_iconMoveController.animateTo(controllerValue);
}
@@ -77,19 +77,19 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin {
if (_dragExtent.isNegative) return;
var movePastThresholdPixels = widget.threshold;
final movePastThresholdPixels = widget.threshold;
var newPos = _dragExtent.abs() / context.size!.width;
if (_dragExtent.abs() > movePastThresholdPixels) {
// how many "thresholds" past the threshold we are. 1 = the threshold 2
// = two thresholds.
var n = _dragExtent.abs() / movePastThresholdPixels;
final n = _dragExtent.abs() / movePastThresholdPixels;
// Take the number of thresholds past the threshold, and reduce this
// number
var reducedThreshold = math.pow(n, 0.3);
final reducedThreshold = math.pow(n, 0.3);
var adjustedPixelPos = movePastThresholdPixels * reducedThreshold;
final adjustedPixelPos = movePastThresholdPixels * reducedThreshold;
newPos = adjustedPixelPos / context.size!.width;
if (_dragExtent > 0 && !_pastThreshold) {
@@ -111,8 +111,8 @@ class _SwipeableState extends State<Swipeable> with TickerProviderStateMixin {
}
void _handleDragEnd(DragEndDetails details) {
_moveController.animateTo(0.0, duration: _animationDuration);
_iconMoveController.animateTo(0.0, duration: _animationDuration);
_moveController.animateTo(0, duration: _animationDuration);
_iconMoveController.animateTo(0, duration: _animationDuration);
_dragExtent = 0.0;
if (_pastThreshold && widget.onSwipeEnd != null) {
widget.onSwipeEnd!();
@@ -118,7 +118,6 @@ class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
child: Container(
height: preferredSize.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
title ??
@@ -133,7 +132,6 @@ class ThreadHeader extends StatelessWidget implements PreferredSizeWidget {
subtitle ??
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
@@ -33,8 +33,8 @@ class UnreadIndicator extends StatelessWidget {
.unreadCounterColor,
child: Padding(
padding: const EdgeInsets.only(
left: 5.0,
right: 5.0,
left: 5,
right: 5,
top: 2,
bottom: 1,
),
@@ -10,7 +10,7 @@ class UploadProgressIndicator extends StatelessWidget {
final bool showBackground;
final TextStyle? textStyle;
UploadProgressIndicator({
const UploadProgressIndicator({
Key? key,
required this.uploaded,
required this.total,
@@ -8,12 +8,12 @@ class UrlAttachment extends StatelessWidget {
final String hostDisplayName;
final EdgeInsets textPadding;
UrlAttachment({
const UrlAttachment({
required this.urlAttachment,
required this.hostDisplayName,
this.textPadding = const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
horizontal: 16,
vertical: 8,
),
});
@@ -32,9 +32,9 @@ class UrlAttachment extends StatelessWidget {
if (urlAttachment.imageUrl != null)
Container(
clipBehavior: Clip.antiAliasWithSaveLayer,
margin: EdgeInsets.symmetric(horizontal: 8.0),
margin: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
borderRadius: BorderRadius.circular(8),
),
child: Stack(
children: [
@@ -44,20 +44,20 @@ class UrlAttachment extends StatelessWidget {
fit: BoxFit.cover,
),
Positioned(
left: 0.0,
left: 0,
bottom: -1,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(16.0),
topRight: Radius.circular(16),
),
color: StreamChatTheme.of(context).colorTheme.blueAlice,
),
child: Padding(
padding: const EdgeInsets.only(
top: 8.0,
left: 8.0,
right: 8.0,
top: 8,
left: 8,
right: 8,
),
child: Text(
hostDisplayName,
@@ -42,7 +42,6 @@ class UserAvatar extends StatelessWidget {
Widget avatar = FittedBox(
fit: BoxFit.cover,
child: ClipRRect(
clipBehavior: Clip.antiAlias,
borderRadius: borderRadius ??
streamChatTheme.ownMessageTheme.avatarTheme?.borderRadius,
child: Container(
@@ -97,7 +96,7 @@ class UserAvatar extends StatelessWidget {
type: MaterialType.circle,
color: streamChatTheme.colorTheme.white,
child: Container(
margin: const EdgeInsets.all(2.0),
margin: const EdgeInsets.all(2),
constraints: onlineIndicatorConstraints ??
BoxConstraints.tightFor(
width: 8,
@@ -61,7 +61,6 @@ class UserItem extends StatelessWidget {
},
leading: UserAvatar(
user: user,
showOnlineStatus: true,
onTap: (user) {
if (onImageTap != null) {
onImageTap!(user);
@@ -151,7 +151,7 @@ class _UserListViewState extends State<UserListView>
@override
Widget build(BuildContext context) {
var child = UserListCore(
final child = UserListCore(
errorBuilder: widget.errorBuilder as Widget Function(Object)? ??
(err) {
return _buildError(err as Error);
@@ -225,7 +225,7 @@ class _UserListViewState extends State<UserListView>
WidgetSpan(
child: Padding(
padding: const EdgeInsets.only(
right: 2.0,
right: 2,
),
child: Icon(Icons.error_outline),
),
@@ -237,7 +237,7 @@ class _UserListViewState extends State<UserListView>
),
Padding(
padding: const EdgeInsets.only(
top: 16.0,
top: 16,
),
child: Text(message),
),
@@ -313,7 +313,7 @@ class _UserListViewState extends State<UserListView>
color:
StreamChatTheme.of(context).colorTheme.black.withOpacity(0.05),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
child: Text(
header,
style: TextStyle(
@@ -360,7 +360,6 @@ class _UserListViewState extends State<UserListView>
? widget.userItemBuilder!(context, user, selected)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
UserAvatar(
user: user,
@@ -414,7 +413,7 @@ class _UserListViewState extends State<UserListView>
.accentRed
.withOpacity(.2),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
padding: const EdgeInsets.symmetric(vertical: 16),
child: Center(
child: Text('Error loading users'),
),
@@ -23,7 +23,7 @@ class UserReactionDisplay extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: reactionToEmoji.keys.map((reactionType) {
var firstUserReaction = message.latestReactions!
final firstUserReaction = message.latestReactions!
.firstWhere((element) => element.type == reactionType,
orElse: () {
return null;
+18 -18
View File
@@ -33,8 +33,8 @@ Future<bool?> showConfirmationDialog(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0),
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
)),
builder: (context) {
final effect = StreamChatTheme.of(context).colorTheme.borderTop;
@@ -42,20 +42,20 @@ Future<bool?> showConfirmationDialog(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 26.0),
SizedBox(height: 26),
if (icon != null) icon,
SizedBox(height: 26.0),
SizedBox(height: 26),
Text(
title,
style: StreamChatTheme.of(context).textTheme.headlineBold,
),
SizedBox(height: 7.0),
SizedBox(height: 7),
if (question != null)
Text(
question,
textAlign: TextAlign.center,
),
SizedBox(height: 36.0),
SizedBox(height: 36),
Container(
color: effect.color!.withOpacity(effect.alpha ?? 1),
height: 1,
@@ -126,8 +126,8 @@ Future<bool?> showInfoDialog(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0),
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
)),
builder: (context) {
return SafeArea(
@@ -135,11 +135,11 @@ Future<bool?> showInfoDialog(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 26.0,
height: 26,
),
if (icon != null) icon,
SizedBox(
height: 26.0,
height: 26,
),
Text(
title,
@@ -147,16 +147,16 @@ Future<bool?> showInfoDialog(
StreamChatTheme.of(context).textTheme.headlineBold,
),
SizedBox(
height: 7.0,
height: 7,
),
if (details != null) Text(details),
SizedBox(
height: 36.0,
height: 36,
),
Container(
color: theme?.colorTheme.black.withOpacity(.08) ??
StreamChatTheme.of(context).colorTheme.black.withOpacity(.08),
height: 1.0,
height: 1,
),
Center(
child: TextButton(
@@ -236,7 +236,7 @@ String fileSize(dynamic size, [int round = 2]) {
* the optional parameter [round] specifies the number
* of digits after comma/point (default is 2)
*/
final divider = 1024;
const divider = 1024;
int _size;
try {
_size = int.parse(size.toString());
@@ -274,21 +274,21 @@ String fileSize(dynamic size, [int round = 2]) {
if (_size < divider * divider * divider * divider * divider &&
_size % divider == 0) {
num r = _size / divider / divider / divider / divider;
final num r = _size / divider / divider / divider / divider;
return '${r.toStringAsFixed(0)} TB';
}
if (_size < divider * divider * divider * divider * divider) {
num r = _size / divider / divider / divider / divider;
final num r = _size / divider / divider / divider / divider;
return '${r.toStringAsFixed(round)} TB';
}
if (_size < divider * divider * divider * divider * divider * divider &&
_size % divider == 0) {
num r = _size / divider / divider / divider / divider / divider;
final num r = _size / divider / divider / divider / divider / divider;
return '${r.toStringAsFixed(0)} PB';
} else {
num r = _size / divider / divider / divider / divider / divider;
final num r = _size / divider / divider / divider / divider / divider;
return '${r.toStringAsFixed(round)} PB';
}
}
@@ -239,7 +239,7 @@ void main() {
),
);
await tester.tap(find.text('Show in Chat'));
verify(() => onShowMessage.call()).called(1);
verify(onShowMessage.call).called(1);
},
);
@@ -26,8 +26,8 @@ void main() {
child: Container(
child: FileAttachment(
size: Size(
300.0,
300.0,
300,
300,
),
message: Message(),
attachment: Attachment(
@@ -318,7 +318,6 @@ void main() {
body: ChannelHeader(
showTypingIndicator: false,
showBackButton: false,
showConnectionStateTile: false,
),
),
),
@@ -224,7 +224,6 @@ void main() {
borderColor: Colors.red,
backgroundColor: Colors.blue,
maskColor: Colors.green,
highlightOwnReactions: true,
reverse: true,
flipTail: true,
tailCirclesSpacing: 4,