lint changes
This commit is contained in:
@@ -2,16 +2,11 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_portal/flutter_portal.dart';
|
import 'package:flutter_portal/flutter_portal.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
|
||||||
|
|
||||||
|
/// Tile to display a message, used in stream chat to display connection status
|
||||||
class InfoTile extends StatelessWidget {
|
class InfoTile extends StatelessWidget {
|
||||||
final String message;
|
/// Constructor for creating an [InfoTile] widget
|
||||||
final Widget child;
|
|
||||||
final bool showMessage;
|
|
||||||
final Alignment? tileAnchor;
|
|
||||||
final Alignment? childAnchor;
|
|
||||||
final TextStyle? textStyle;
|
|
||||||
final Color? backgroundColor;
|
|
||||||
|
|
||||||
const InfoTile({
|
const InfoTile({
|
||||||
|
Key? key,
|
||||||
required this.message,
|
required this.message,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.showMessage,
|
required this.showMessage,
|
||||||
@@ -19,31 +14,50 @@ class InfoTile extends StatelessWidget {
|
|||||||
this.childAnchor,
|
this.childAnchor,
|
||||||
this.textStyle,
|
this.textStyle,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
});
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// String to display
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
/// Widget to display over
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
/// Flag to show message
|
||||||
|
final bool showMessage;
|
||||||
|
|
||||||
|
/// Anchor for tile - [portalAnchor] for [PortalEntry]
|
||||||
|
final Alignment? tileAnchor;
|
||||||
|
|
||||||
|
/// Alignment for child - [childAnchor] for [PortalEntry]
|
||||||
|
final Alignment? childAnchor;
|
||||||
|
|
||||||
|
/// [TextStyle] for message
|
||||||
|
final TextStyle? textStyle;
|
||||||
|
|
||||||
|
/// Background color for tile
|
||||||
|
final Color? backgroundColor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => PortalEntry(
|
||||||
return PortalEntry(
|
visible: showMessage,
|
||||||
visible: showMessage,
|
portalAnchor: tileAnchor ?? Alignment.topCenter,
|
||||||
portalAnchor: tileAnchor ?? Alignment.topCenter,
|
childAnchor: childAnchor ?? Alignment.bottomCenter,
|
||||||
childAnchor: childAnchor ?? Alignment.bottomCenter,
|
portal: Container(
|
||||||
portal: Container(
|
height: 25,
|
||||||
height: 25,
|
color: backgroundColor ??
|
||||||
color: backgroundColor ??
|
StreamChatTheme.of(context).colorTheme.grey.withOpacity(0.9),
|
||||||
StreamChatTheme.of(context).colorTheme.grey.withOpacity(0.9),
|
child: Center(
|
||||||
child: Center(
|
child: Text(
|
||||||
child: Text(
|
message,
|
||||||
message,
|
style: textStyle ??
|
||||||
style: textStyle ??
|
StreamChatTheme.of(context).textTheme.body.copyWith(
|
||||||
StreamChatTheme.of(context).textTheme.body.copyWith(
|
color: Colors.white,
|
||||||
color: Colors.white,
|
),
|
||||||
),
|
maxLines: 1,
|
||||||
maxLines: 1,
|
overflow: TextOverflow.ellipsis,
|
||||||
overflow: TextOverflow.ellipsis,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
child: child,
|
||||||
child: child,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:photo_manager/photo_manager.dart';
|
import 'package:photo_manager/photo_manager.dart';
|
||||||
import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
|
import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
|
||||||
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
import '../stream_chat_flutter.dart';
|
|
||||||
|
|
||||||
extension on Duration {
|
extension on Duration {
|
||||||
String format() {
|
String format() {
|
||||||
@@ -19,16 +18,21 @@ extension on Duration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a list of media
|
||||||
class MediaListView extends StatefulWidget {
|
class MediaListView extends StatefulWidget {
|
||||||
final List<String> selectedIds;
|
/// Constructor for creating a [MediaListView] widget
|
||||||
final void Function(AssetEntity media)? onSelect;
|
|
||||||
|
|
||||||
const MediaListView({
|
const MediaListView({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.selectedIds = const [],
|
this.selectedIds = const [],
|
||||||
this.onSelect,
|
this.onSelect,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// Stores the media selected
|
||||||
|
final List<String> selectedIds;
|
||||||
|
|
||||||
|
/// Callback for on media selected
|
||||||
|
final void Function(AssetEntity media)? onSelect;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MediaListViewState createState() => _MediaListViewState();
|
_MediaListViewState createState() => _MediaListViewState();
|
||||||
}
|
}
|
||||||
@@ -39,103 +43,103 @@ class _MediaListViewState extends State<MediaListView> {
|
|||||||
int _currentPage = 0;
|
int _currentPage = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => LazyLoadScrollView(
|
||||||
return LazyLoadScrollView(
|
onEndOfPage: () async => _getMedia(),
|
||||||
onEndOfPage: () async => _getMedia(),
|
child: GridView.builder(
|
||||||
child: GridView.builder(
|
itemCount: _media.length,
|
||||||
itemCount: _media.length,
|
controller: _scrollController,
|
||||||
controller: _scrollController,
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
crossAxisCount: 3,
|
||||||
crossAxisCount: 3,
|
),
|
||||||
),
|
itemBuilder: (
|
||||||
itemBuilder: (
|
context,
|
||||||
context,
|
position,
|
||||||
position,
|
) {
|
||||||
) {
|
final media = _media.elementAt(position);
|
||||||
final media = _media.elementAt(position);
|
return Padding(
|
||||||
return Padding(
|
padding: const EdgeInsets.symmetric(horizontal: 1, vertical: 1),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 1, vertical: 1),
|
child: InkWell(
|
||||||
child: InkWell(
|
onTap: () {
|
||||||
onTap: () {
|
if (widget.onSelect != null) {
|
||||||
if (widget.onSelect != null) {
|
widget.onSelect!(media);
|
||||||
widget.onSelect!(media);
|
}
|
||||||
}
|
},
|
||||||
},
|
child: Stack(
|
||||||
child: Stack(
|
children: [
|
||||||
children: [
|
AspectRatio(
|
||||||
AspectRatio(
|
aspectRatio: 1,
|
||||||
aspectRatio: 1,
|
child: FadeInImage(
|
||||||
child: FadeInImage(
|
fadeInDuration: const Duration(milliseconds: 300),
|
||||||
fadeInDuration: Duration(milliseconds: 300),
|
placeholder: const AssetImage(
|
||||||
placeholder: AssetImage(
|
'images/placeholder.png',
|
||||||
'images/placeholder.png',
|
package: 'stream_chat_flutter',
|
||||||
package: 'stream_chat_flutter',
|
),
|
||||||
|
image: MediaThumbnailProvider(
|
||||||
|
media: media,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
image: MediaThumbnailProvider(
|
|
||||||
media: media,
|
|
||||||
),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
),
|
||||||
),
|
Positioned.fill(
|
||||||
Positioned.fill(
|
child: IgnorePointer(
|
||||||
child: IgnorePointer(
|
child: AnimatedOpacity(
|
||||||
child: AnimatedOpacity(
|
duration: const Duration(milliseconds: 300),
|
||||||
duration: Duration(milliseconds: 300),
|
opacity:
|
||||||
opacity: widget.selectedIds.any((id) => id == media.id)
|
widget.selectedIds.any((id) => id == media.id)
|
||||||
? 1.0
|
? 1.0
|
||||||
: 0.0,
|
: 0.0,
|
||||||
child: Container(
|
child: Container(
|
||||||
color: StreamChatTheme.of(context)
|
color: StreamChatTheme.of(context)
|
||||||
.colorTheme
|
.colorTheme
|
||||||
.black
|
.black
|
||||||
.withOpacity(0.5),
|
.withOpacity(0.5),
|
||||||
alignment: Alignment.topRight,
|
alignment: Alignment.topRight,
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 8,
|
top: 8,
|
||||||
right: 8,
|
right: 8,
|
||||||
),
|
),
|
||||||
child: CircleAvatar(
|
child: CircleAvatar(
|
||||||
radius: 12,
|
radius: 12,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
StreamChatTheme.of(context).colorTheme.white,
|
StreamChatTheme.of(context).colorTheme.white,
|
||||||
child: StreamSvgIcon.check(
|
child: StreamSvgIcon.check(
|
||||||
size: 24,
|
size: 24,
|
||||||
color:
|
color: StreamChatTheme.of(context)
|
||||||
StreamChatTheme.of(context).colorTheme.black,
|
.colorTheme
|
||||||
|
.black,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
if (media.type == AssetType.video) ...[
|
||||||
if (media.type == AssetType.video) ...[
|
Positioned(
|
||||||
Positioned(
|
left: 8,
|
||||||
left: 8,
|
bottom: 10,
|
||||||
bottom: 10,
|
child: SvgPicture.asset(
|
||||||
child: SvgPicture.asset(
|
'svgs/video_call_icon.svg',
|
||||||
'svgs/video_call_icon.svg',
|
package: 'stream_chat_flutter',
|
||||||
package: 'stream_chat_flutter',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
right: 4,
|
|
||||||
bottom: 10,
|
|
||||||
child: Text(
|
|
||||||
media.videoDuration.format(),
|
|
||||||
style: TextStyle(
|
|
||||||
color: StreamChatTheme.of(context).colorTheme.white,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Positioned(
|
||||||
]
|
right: 4,
|
||||||
],
|
bottom: 10,
|
||||||
|
child: Text(
|
||||||
|
media.videoDuration.format(),
|
||||||
|
style: TextStyle(
|
||||||
|
color: StreamChatTheme.of(context).colorTheme.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -165,36 +169,38 @@ class _MediaListViewState extends State<MediaListView> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ImageProvider implementation
|
||||||
class MediaThumbnailProvider extends ImageProvider<MediaThumbnailProvider> {
|
class MediaThumbnailProvider extends ImageProvider<MediaThumbnailProvider> {
|
||||||
|
/// Constructor for creating a [MediaThumbnailProvider]
|
||||||
const MediaThumbnailProvider({
|
const MediaThumbnailProvider({
|
||||||
required this.media,
|
required this.media,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Media to load
|
||||||
final AssetEntity media;
|
final AssetEntity media;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ImageStreamCompleter load(key, decode) {
|
ImageStreamCompleter load(
|
||||||
return MultiFrameImageStreamCompleter(
|
MediaThumbnailProvider key, DecoderCallback decode) =>
|
||||||
codec: _loadAsync(key, decode),
|
MultiFrameImageStreamCompleter(
|
||||||
scale: 1,
|
codec: _loadAsync(key, decode),
|
||||||
informationCollector: () sync* {
|
scale: 1,
|
||||||
yield ErrorDescription('Id: ${media.id}');
|
informationCollector: () sync* {
|
||||||
},
|
yield ErrorDescription('Id: ${media.id}');
|
||||||
);
|
},
|
||||||
}
|
);
|
||||||
|
|
||||||
Future<ui.Codec> _loadAsync(
|
Future<ui.Codec> _loadAsync(
|
||||||
MediaThumbnailProvider key, DecoderCallback decode) async {
|
MediaThumbnailProvider key, DecoderCallback decode) async {
|
||||||
assert(key == this);
|
assert(key == this, 'Checks MediaThumbnailProvider');
|
||||||
final bytes = await media.thumbData;
|
final bytes = await media.thumbData;
|
||||||
|
|
||||||
return await decode(bytes!);
|
return decode(bytes!);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MediaThumbnailProvider> obtainKey(ImageConfiguration configuration) {
|
Future<MediaThumbnailProvider> obtainKey(ImageConfiguration configuration) =>
|
||||||
return SynchronousFuture<MediaThumbnailProvider>(this);
|
SynchronousFuture<MediaThumbnailProvider>(this);
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(dynamic other) {
|
bool operator ==(dynamic other) {
|
||||||
|
|||||||
@@ -3,8 +3,19 @@ import 'package:flutter/material.dart';
|
|||||||
import '../stream_chat_flutter.dart';
|
import '../stream_chat_flutter.dart';
|
||||||
|
|
||||||
/// This widget is used for showing user tiles for mentions
|
/// This widget is used for showing user tiles for mentions
|
||||||
/// Use [title], [subtitle], [leading], [trailing] for substituting widgets in respective positions
|
/// Use [title], [subtitle], [leading], [trailing] for
|
||||||
|
/// substituting widgets in respective positions
|
||||||
class MentionTile extends StatelessWidget {
|
class MentionTile extends StatelessWidget {
|
||||||
|
/// Constructor for creating a [MentionTile] widget
|
||||||
|
const MentionTile(
|
||||||
|
this.member, {
|
||||||
|
Key? key,
|
||||||
|
this.title,
|
||||||
|
this.subtitle,
|
||||||
|
this.leading,
|
||||||
|
this.trailing,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Member to display in the tile
|
/// Member to display in the tile
|
||||||
final Member member;
|
final Member member;
|
||||||
|
|
||||||
@@ -20,82 +31,72 @@ class MentionTile extends StatelessWidget {
|
|||||||
/// Widget at the end of tile
|
/// Widget at the end of tile
|
||||||
final Widget? trailing;
|
final Widget? trailing;
|
||||||
|
|
||||||
const MentionTile(
|
|
||||||
this.member, {
|
|
||||||
this.title,
|
|
||||||
this.subtitle,
|
|
||||||
this.leading,
|
|
||||||
this.trailing,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => SizedBox(
|
||||||
return Container(
|
height: 56,
|
||||||
height: 56,
|
child: Row(
|
||||||
child: Row(
|
children: [
|
||||||
children: [
|
const SizedBox(
|
||||||
SizedBox(
|
width: 16,
|
||||||
width: 16,
|
),
|
||||||
),
|
leading ??
|
||||||
leading ??
|
UserAvatar(
|
||||||
UserAvatar(
|
constraints: BoxConstraints.tight(
|
||||||
constraints: BoxConstraints.tight(
|
const Size(
|
||||||
Size(
|
40,
|
||||||
40,
|
40,
|
||||||
40,
|
),
|
||||||
),
|
),
|
||||||
|
user: member.user!,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
title ??
|
||||||
|
Text(
|
||||||
|
member.user!.name,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: StreamChatTheme.of(context).textTheme.bodyBold,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 2,
|
||||||
|
),
|
||||||
|
subtitle ??
|
||||||
|
Text(
|
||||||
|
'@${member.userId}',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: StreamChatTheme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.footnoteBold
|
||||||
|
.copyWith(
|
||||||
|
color:
|
||||||
|
StreamChatTheme.of(context).colorTheme.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
user: member.user!,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 8,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
title ??
|
|
||||||
Text(
|
|
||||||
member.user!.name,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: StreamChatTheme.of(context).textTheme.bodyBold,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 2,
|
|
||||||
),
|
|
||||||
subtitle ??
|
|
||||||
Text(
|
|
||||||
'@${member.userId}',
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: StreamChatTheme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.footnoteBold
|
|
||||||
.copyWith(
|
|
||||||
color:
|
|
||||||
StreamChatTheme.of(context).colorTheme.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
trailing ??
|
||||||
trailing ??
|
Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.only(
|
||||||
padding: const EdgeInsets.only(
|
right: 18,
|
||||||
right: 18,
|
left: 8,
|
||||||
left: 8,
|
),
|
||||||
|
child: StreamSvgIcon.mentions(
|
||||||
|
color: StreamChatTheme.of(context).colorTheme.accentBlue,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: StreamSvgIcon.mentions(
|
],
|
||||||
color: StreamChatTheme.of(context).colorTheme.accentBlue,
|
),
|
||||||
),
|
);
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
|||||||
|
|
||||||
/// Class describing a message action
|
/// Class describing a message action
|
||||||
class MessageAction {
|
class MessageAction {
|
||||||
|
/// returns a new instance of a [MessageAction]
|
||||||
|
MessageAction({
|
||||||
|
this.leading,
|
||||||
|
this.title,
|
||||||
|
this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
/// leading widget
|
/// leading widget
|
||||||
final Widget? leading;
|
final Widget? leading;
|
||||||
|
|
||||||
@@ -11,11 +18,4 @@ class MessageAction {
|
|||||||
|
|
||||||
/// callback called on tap
|
/// callback called on tap
|
||||||
final OnMessageTap? onTap;
|
final OnMessageTap? onTap;
|
||||||
|
|
||||||
/// returns a new instance of a [MessageAction]
|
|
||||||
MessageAction({
|
|
||||||
this.leading,
|
|
||||||
this.title,
|
|
||||||
this.onTap,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user