lint
This commit is contained in:
@@ -3,107 +3,114 @@ import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat_flutter/src/utils.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
/// Widget to display URL attachment
|
||||
class UrlAttachment extends StatelessWidget {
|
||||
final Attachment urlAttachment;
|
||||
final String hostDisplayName;
|
||||
final EdgeInsets textPadding;
|
||||
|
||||
/// Constructor for creating a [UrlAttachment]
|
||||
const UrlAttachment({
|
||||
Key? key,
|
||||
required this.urlAttachment,
|
||||
required this.hostDisplayName,
|
||||
this.textPadding = const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
/// Attachment to be displayed
|
||||
final Attachment urlAttachment;
|
||||
|
||||
/// Host name
|
||||
final String hostDisplayName;
|
||||
|
||||
/// Padding for text
|
||||
final EdgeInsets textPadding;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
launchURL(
|
||||
context,
|
||||
urlAttachment.ogScrapeUrl,
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
if (urlAttachment.imageUrl != null)
|
||||
Container(
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
margin: EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
width: double.infinity,
|
||||
imageUrl: urlAttachment.imageUrl!,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
bottom: -1,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(16),
|
||||
Widget build(BuildContext context) => GestureDetector(
|
||||
onTap: () {
|
||||
launchURL(
|
||||
context,
|
||||
urlAttachment.ogScrapeUrl,
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
if (urlAttachment.imageUrl != null)
|
||||
Container(
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
margin: const EdgeInsets.symmetric(horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
width: double.infinity,
|
||||
imageUrl: urlAttachment.imageUrl!,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
bottom: -1,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(16),
|
||||
),
|
||||
color:
|
||||
StreamChatTheme.of(context).colorTheme.blueAlice,
|
||||
),
|
||||
color: StreamChatTheme.of(context).colorTheme.blueAlice,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 8,
|
||||
left: 8,
|
||||
right: 8,
|
||||
),
|
||||
child: Text(
|
||||
hostDisplayName,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.bodyBold
|
||||
.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.accentBlue,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 8,
|
||||
left: 8,
|
||||
right: 8,
|
||||
),
|
||||
child: Text(
|
||||
hostDisplayName,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.bodyBold
|
||||
.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.accentBlue,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: textPadding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (urlAttachment.title != null)
|
||||
Text(
|
||||
urlAttachment.title!.trim(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.body
|
||||
.copyWith(fontWeight: FontWeight.w700),
|
||||
),
|
||||
if (urlAttachment.text != null)
|
||||
Text(
|
||||
urlAttachment.text!,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.body
|
||||
.copyWith(fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: textPadding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (urlAttachment.title != null)
|
||||
Text(
|
||||
urlAttachment.title!.trim(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.body
|
||||
.copyWith(fontWeight: FontWeight.w700),
|
||||
),
|
||||
if (urlAttachment.text != null)
|
||||
Text(
|
||||
urlAttachment.text!,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.body
|
||||
.copyWith(fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
import '../stream_chat_flutter.dart';
|
||||
|
||||
/// Widget that displays a user avatar
|
||||
class UserAvatar extends StatelessWidget {
|
||||
/// Constructor to create a [UserAvatar]
|
||||
const UserAvatar({
|
||||
Key? key,
|
||||
required this.user,
|
||||
@@ -20,16 +21,37 @@ class UserAvatar extends StatelessWidget {
|
||||
this.selectionThickness = 4,
|
||||
}) : super(key: key);
|
||||
|
||||
/// User whose avatar is to displayed
|
||||
final User user;
|
||||
|
||||
/// Alignment of the online indicator
|
||||
final Alignment onlineIndicatorAlignment;
|
||||
|
||||
/// Size of the avatar
|
||||
final BoxConstraints? constraints;
|
||||
|
||||
/// [BorderRadius] of the image
|
||||
final BorderRadius? borderRadius;
|
||||
|
||||
/// Size of the online indicator
|
||||
final BoxConstraints? onlineIndicatorConstraints;
|
||||
|
||||
/// Callback when avatar is tapped
|
||||
final void Function(User)? onTap;
|
||||
|
||||
/// Callback when avatar is long pressed
|
||||
final void Function(User)? onLongPress;
|
||||
|
||||
/// Flag for showing online status
|
||||
final bool showOnlineStatus;
|
||||
|
||||
/// Flag for if avatar is selected
|
||||
final bool selected;
|
||||
|
||||
/// Color of selection
|
||||
final Color? selectionColor;
|
||||
|
||||
/// Selection thickness around the avatar
|
||||
final double selectionThickness;
|
||||
|
||||
@override
|
||||
@@ -53,10 +75,10 @@ class UserAvatar extends StatelessWidget {
|
||||
child: hasImage
|
||||
? CachedNetworkImage(
|
||||
filterQuality: FilterQuality.high,
|
||||
// ignore: cast_nullable_to_non_nullable
|
||||
imageUrl: user.extraData['image'] as String,
|
||||
errorWidget: (_, __, ___) {
|
||||
return streamChatTheme.defaultUserImage(context, user);
|
||||
},
|
||||
errorWidget: (_, __, ___) =>
|
||||
streamChatTheme.defaultUserImage(context, user),
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: streamChatTheme.defaultUserImage(context, user),
|
||||
@@ -98,12 +120,12 @@ class UserAvatar extends StatelessWidget {
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
constraints: onlineIndicatorConstraints ??
|
||||
BoxConstraints.tightFor(
|
||||
const BoxConstraints.tightFor(
|
||||
width: 8,
|
||||
height: 8,
|
||||
),
|
||||
child: Material(
|
||||
shape: CircleBorder(),
|
||||
shape: const CircleBorder(),
|
||||
color: streamChatTheme.colorTheme.accentGreen,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -5,16 +5,17 @@ import 'package:stream_chat_flutter/src/user_list_view.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';
|
||||
|
||||
///
|
||||
/// It shows the current [User] preview.
|
||||
///
|
||||
/// The widget uses a [StreamBuilder] to render the user information image as soon as it updates.
|
||||
/// The widget uses a [StreamBuilder] to render the user information
|
||||
/// image as soon as it updates.
|
||||
///
|
||||
/// Usually you don't use this widget as it's the default user preview used by [UserListView].
|
||||
/// Usually you don't use this widget as it's the default user preview used
|
||||
/// by [UserListView].
|
||||
///
|
||||
/// The widget renders the ui based on the first ancestor of type [StreamChatTheme].
|
||||
/// The widget renders the ui based on the first ancestor of type
|
||||
/// [StreamChatTheme].
|
||||
/// Modify it to change the widget appearance.
|
||||
class UserItem extends StatelessWidget {
|
||||
/// Instantiate a new UserItem
|
||||
@@ -47,50 +48,47 @@ class UserItem extends StatelessWidget {
|
||||
final bool showLastOnline;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
if (onTap != null) {
|
||||
onTap!(user);
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
if (onLongPress != null) {
|
||||
onLongPress!(user);
|
||||
}
|
||||
},
|
||||
leading: UserAvatar(
|
||||
user: user,
|
||||
onTap: (user) {
|
||||
if (onImageTap != null) {
|
||||
onImageTap!(user);
|
||||
Widget build(BuildContext context) => ListTile(
|
||||
onTap: () {
|
||||
if (onTap != null) {
|
||||
onTap!(user);
|
||||
}
|
||||
},
|
||||
constraints: BoxConstraints.tightFor(
|
||||
height: 40,
|
||||
width: 40,
|
||||
onLongPress: () {
|
||||
if (onLongPress != null) {
|
||||
onLongPress!(user);
|
||||
}
|
||||
},
|
||||
leading: UserAvatar(
|
||||
user: user,
|
||||
onTap: (user) {
|
||||
if (onImageTap != null) {
|
||||
onImageTap!(user);
|
||||
}
|
||||
},
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
height: 40,
|
||||
width: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
trailing: selected
|
||||
? StreamSvgIcon.checkSend(
|
||||
color: StreamChatTheme.of(context).colorTheme.accentBlue,
|
||||
)
|
||||
: null,
|
||||
title: Text(
|
||||
user.name,
|
||||
style: StreamChatTheme.of(context).textTheme.bodyBold,
|
||||
),
|
||||
subtitle: showLastOnline ? _buildLastActive(context) : null,
|
||||
);
|
||||
}
|
||||
trailing: selected
|
||||
? StreamSvgIcon.checkSend(
|
||||
color: StreamChatTheme.of(context).colorTheme.accentBlue,
|
||||
)
|
||||
: null,
|
||||
title: Text(
|
||||
user.name,
|
||||
style: StreamChatTheme.of(context).textTheme.bodyBold,
|
||||
),
|
||||
subtitle: showLastOnline ? _buildLastActive(context) : null,
|
||||
);
|
||||
|
||||
Widget _buildLastActive(context) {
|
||||
return Text(
|
||||
user.online == true
|
||||
? 'Online'
|
||||
: 'Last online ${Jiffy(user.lastActive).fromNow()}',
|
||||
style: StreamChatTheme.of(context).textTheme.footnote.copyWith(
|
||||
color: StreamChatTheme.of(context).colorTheme.black.withOpacity(.5)),
|
||||
);
|
||||
}
|
||||
Widget _buildLastActive(context) => Text(
|
||||
user.online == true
|
||||
? 'Online'
|
||||
: 'Last online ${Jiffy(user.lastActive).fromNow()}',
|
||||
style: StreamChatTheme.of(context).textTheme.footnote.copyWith(
|
||||
color:
|
||||
StreamChatTheme.of(context).colorTheme.black.withOpacity(.5)),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user