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