lint changes media
This commit is contained in:
@@ -8,24 +8,24 @@ import 'package:jiffy/jiffy.dart';
|
|||||||
import 'package:photo_view/photo_view.dart';
|
import 'package:photo_view/photo_view.dart';
|
||||||
import 'package:stream_chat_flutter/src/image_footer.dart';
|
import 'package:stream_chat_flutter/src/image_footer.dart';
|
||||||
import 'package:stream_chat_flutter/src/image_header.dart';
|
import 'package:stream_chat_flutter/src/image_header.dart';
|
||||||
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
import 'package:video_player/video_player.dart';
|
import 'package:video_player/video_player.dart';
|
||||||
|
|
||||||
import '../stream_chat_flutter.dart';
|
/// Return action for coming back from pages
|
||||||
|
enum ReturnActionType {
|
||||||
|
|
||||||
enum ReturnActionType { none, reply }
|
/// No return action
|
||||||
|
none,
|
||||||
|
|
||||||
|
/// Go to reply message action
|
||||||
|
reply,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Callback when show message is tapped
|
||||||
typedef ShowMessageCallback = void Function(Message message, Channel channel);
|
typedef ShowMessageCallback = void Function(Message message, Channel channel);
|
||||||
|
|
||||||
/// A full screen image widget
|
/// A full screen image widget
|
||||||
class FullScreenMedia extends StatefulWidget {
|
class FullScreenMedia extends StatefulWidget {
|
||||||
/// The url of the image
|
|
||||||
final List<Attachment> mediaAttachments;
|
|
||||||
final Message message;
|
|
||||||
|
|
||||||
final int startIndex;
|
|
||||||
final String userName;
|
|
||||||
final ShowMessageCallback? onShowMessage;
|
|
||||||
|
|
||||||
/// Instantiate a new FullScreenImage
|
/// Instantiate a new FullScreenImage
|
||||||
const FullScreenMedia({
|
const FullScreenMedia({
|
||||||
Key? key,
|
Key? key,
|
||||||
@@ -37,6 +37,21 @@ class FullScreenMedia extends StatefulWidget {
|
|||||||
}) : userName = userName ?? '',
|
}) : userName = userName ?? '',
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
|
/// The url of the image
|
||||||
|
final List<Attachment> mediaAttachments;
|
||||||
|
|
||||||
|
/// Message where attachments are attached
|
||||||
|
final Message message;
|
||||||
|
|
||||||
|
/// First index of media shown
|
||||||
|
final int startIndex;
|
||||||
|
|
||||||
|
/// Username of sender
|
||||||
|
final String userName;
|
||||||
|
|
||||||
|
/// Callback for when show message is tapped
|
||||||
|
final ShowMessageCallback? onShowMessage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_FullScreenMediaState createState() => _FullScreenMediaState();
|
_FullScreenMediaState createState() => _FullScreenMediaState();
|
||||||
}
|
}
|
||||||
@@ -57,7 +72,7 @@ class _FullScreenMediaState extends State<FullScreenMedia>
|
|||||||
super.initState();
|
super.initState();
|
||||||
_controller = AnimationController(
|
_controller = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
duration: Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
);
|
);
|
||||||
_pageController = PageController(initialPage: widget.startIndex);
|
_pageController = PageController(initialPage: widget.startIndex);
|
||||||
_currentPage = widget.startIndex;
|
_currentPage = widget.startIndex;
|
||||||
@@ -77,139 +92,136 @@ class _FullScreenMediaState extends State<FullScreenMedia>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => Scaffold(
|
||||||
return Scaffold(
|
resizeToAvoidBottomInset: false,
|
||||||
resizeToAvoidBottomInset: false,
|
body: Stack(
|
||||||
body: Stack(
|
children: [
|
||||||
children: [
|
AnimatedBuilder(
|
||||||
AnimatedBuilder(
|
animation: _controller,
|
||||||
animation: _controller,
|
builder: (context, snapshot) => PageView.builder(
|
||||||
builder: (context, snapshot) {
|
controller: _pageController,
|
||||||
return PageView.builder(
|
onPageChanged: (val) {
|
||||||
controller: _pageController,
|
setState(() {
|
||||||
onPageChanged: (val) {
|
_currentPage = val;
|
||||||
setState(() {
|
});
|
||||||
_currentPage = val;
|
},
|
||||||
});
|
itemBuilder: (context, index) {
|
||||||
},
|
final attachment = widget.mediaAttachments[index];
|
||||||
itemBuilder: (context, index) {
|
if (attachment.type == 'image' ||
|
||||||
final attachment = widget.mediaAttachments[index];
|
attachment.type == 'giphy') {
|
||||||
if (attachment.type == 'image' ||
|
final imageUrl = attachment.imageUrl ??
|
||||||
attachment.type == 'giphy') {
|
attachment.assetUrl ??
|
||||||
final imageUrl = attachment.imageUrl ??
|
attachment.thumbUrl;
|
||||||
attachment.assetUrl ??
|
return PhotoView(
|
||||||
attachment.thumbUrl;
|
imageProvider: (imageUrl == null &&
|
||||||
return PhotoView(
|
attachment.localUri != null &&
|
||||||
imageProvider: (imageUrl == null &&
|
attachment.file?.bytes != null)
|
||||||
attachment.localUri != null &&
|
? Image.memory(attachment.file!.bytes!).image
|
||||||
attachment.file?.bytes != null)
|
: CachedNetworkImageProvider(imageUrl!),
|
||||||
? Image.memory(attachment.file!.bytes!).image
|
maxScale: PhotoViewComputedScale.covered,
|
||||||
: CachedNetworkImageProvider(imageUrl!),
|
minScale: PhotoViewComputedScale.contained,
|
||||||
maxScale: PhotoViewComputedScale.covered,
|
heroAttributes: PhotoViewHeroAttributes(
|
||||||
minScale: PhotoViewComputedScale.contained,
|
tag: widget.mediaAttachments,
|
||||||
heroAttributes: PhotoViewHeroAttributes(
|
),
|
||||||
tag: widget.mediaAttachments,
|
backgroundDecoration: BoxDecoration(
|
||||||
),
|
color: ColorTween(
|
||||||
backgroundDecoration: BoxDecoration(
|
begin: StreamChatTheme.of(context)
|
||||||
color: ColorTween(
|
.channelTheme
|
||||||
begin: StreamChatTheme.of(context)
|
.channelHeaderTheme
|
||||||
.channelTheme
|
.color,
|
||||||
.channelHeaderTheme
|
end: Colors.black,
|
||||||
.color,
|
).lerp(_controller.value),
|
||||||
end: Colors.black,
|
),
|
||||||
).lerp(_controller.value),
|
onTapUp: (a, b, c) {
|
||||||
),
|
setState(() {
|
||||||
onTapUp: (a, b, c) {
|
_optionsShown = !_optionsShown;
|
||||||
setState(() {
|
});
|
||||||
_optionsShown = !_optionsShown;
|
if (_controller.isCompleted) {
|
||||||
});
|
_controller.reverse();
|
||||||
if (_controller.isCompleted) {
|
} else {
|
||||||
_controller.reverse();
|
_controller.forward();
|
||||||
} else {
|
}
|
||||||
_controller.forward();
|
},
|
||||||
|
);
|
||||||
|
} else if (attachment.type == 'video') {
|
||||||
|
final controller = videoPackages[attachment.id]!;
|
||||||
|
if (!controller.initialized) {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
return InkWell(
|
||||||
);
|
onTap: () {
|
||||||
} else if (attachment.type == 'video') {
|
setState(() {
|
||||||
final controller = videoPackages[attachment.id]!;
|
_optionsShown = !_optionsShown;
|
||||||
if (!controller.initialized) {
|
});
|
||||||
return Center(
|
if (_controller.isCompleted) {
|
||||||
child: CircularProgressIndicator(),
|
_controller.reverse();
|
||||||
);
|
} else {
|
||||||
}
|
_controller.forward();
|
||||||
return InkWell(
|
}
|
||||||
onTap: () {
|
},
|
||||||
setState(() {
|
child: Padding(
|
||||||
_optionsShown = !_optionsShown;
|
padding: const EdgeInsets.symmetric(
|
||||||
});
|
vertical: 50,
|
||||||
if (_controller.isCompleted) {
|
),
|
||||||
_controller.reverse();
|
child: Chewie(
|
||||||
} else {
|
controller: controller.chewieController!,
|
||||||
_controller.forward();
|
),
|
||||||
}
|
),
|
||||||
},
|
);
|
||||||
child: Padding(
|
}
|
||||||
padding: const EdgeInsets.symmetric(
|
return Container();
|
||||||
vertical: 50,
|
},
|
||||||
),
|
itemCount: widget.mediaAttachments.length,
|
||||||
child: Chewie(
|
)),
|
||||||
controller: controller.chewieController!,
|
AnimatedOpacity(
|
||||||
),
|
opacity: _optionsShown ? 1.0 : 0.0,
|
||||||
),
|
duration: const Duration(milliseconds: 300),
|
||||||
);
|
child: Column(
|
||||||
}
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
return Container();
|
children: [
|
||||||
},
|
ImageHeader(
|
||||||
itemCount: widget.mediaAttachments.length,
|
userName: widget.userName,
|
||||||
);
|
sentAt:
|
||||||
}),
|
// ignore: lines_longer_than_80_chars
|
||||||
AnimatedOpacity(
|
'Sent ${getDay(widget.message.createdAt.toLocal())} at ${Jiffy(widget.message.createdAt.toLocal()).format('HH:mm')}',
|
||||||
opacity: _optionsShown ? 1.0 : 0.0,
|
onBackPressed: () {
|
||||||
duration: Duration(milliseconds: 300),
|
Navigator.of(context).pop();
|
||||||
child: Column(
|
},
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
ImageHeader(
|
|
||||||
userName: widget.userName,
|
|
||||||
sentAt:
|
|
||||||
'Sent ${getDay(widget.message.createdAt.toLocal())} at ${Jiffy(widget.message.createdAt.toLocal()).format('HH:mm')}',
|
|
||||||
onBackPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
message: widget.message,
|
|
||||||
currentIndex: _currentPage,
|
|
||||||
onShowMessage: () {
|
|
||||||
widget.onShowMessage?.call(
|
|
||||||
widget.message,
|
|
||||||
StreamChannel.of(context).channel,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (widget.message.type != 'ephemeral')
|
|
||||||
ImageFooter(
|
|
||||||
currentPage: _currentPage,
|
|
||||||
totalPages: widget.mediaAttachments.length,
|
|
||||||
mediaAttachments: widget.mediaAttachments,
|
|
||||||
message: widget.message,
|
message: widget.message,
|
||||||
mediaSelectedCallBack: (val) {
|
currentIndex: _currentPage,
|
||||||
setState(() {
|
onShowMessage: () {
|
||||||
_currentPage = val;
|
widget.onShowMessage?.call(
|
||||||
_pageController.animateToPage(
|
widget.message,
|
||||||
val,
|
StreamChannel.of(context).channel,
|
||||||
duration: Duration(milliseconds: 300),
|
);
|
||||||
curve: Curves.easeInOut,
|
|
||||||
);
|
|
||||||
Navigator.pop(context);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
if (widget.message.type != 'ephemeral')
|
||||||
|
ImageFooter(
|
||||||
|
currentPage: _currentPage,
|
||||||
|
totalPages: widget.mediaAttachments.length,
|
||||||
|
mediaAttachments: widget.mediaAttachments,
|
||||||
|
message: widget.message,
|
||||||
|
mediaSelectedCallBack: (val) {
|
||||||
|
setState(() {
|
||||||
|
_currentPage = val;
|
||||||
|
_pageController.animateToPage(
|
||||||
|
val,
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
);
|
||||||
|
Navigator.pop(context);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String getDay(DateTime dateTime) {
|
String getDay(DateTime dateTime) {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
@@ -236,47 +248,52 @@ class _FullScreenMediaState extends State<FullScreenMedia>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Class for packaging up things required for videos
|
||||||
class VideoPackage {
|
class VideoPackage {
|
||||||
final bool _showControls;
|
/// Constructor for creating [VideoPackage]
|
||||||
final bool _autoInitialize;
|
|
||||||
final VideoPlayerController _videoPlayerController;
|
|
||||||
ChewieController? _chewieController;
|
|
||||||
|
|
||||||
VideoPlayerController get videoPlayer => _videoPlayerController;
|
|
||||||
|
|
||||||
ChewieController? get chewieController => _chewieController;
|
|
||||||
|
|
||||||
bool get initialized => _videoPlayerController.value.isInitialized;
|
|
||||||
|
|
||||||
VideoPackage(
|
VideoPackage(
|
||||||
Attachment attachment, {
|
Attachment attachment, {
|
||||||
bool showControls = false,
|
bool showControls = false,
|
||||||
bool autoInitialize = true,
|
bool autoInitialize = true,
|
||||||
}) : _showControls = showControls,
|
}) : _showControls = showControls,
|
||||||
_autoInitialize = autoInitialize,
|
_autoInitialize = autoInitialize,
|
||||||
_videoPlayerController = attachment.localUri != null
|
_videoPlayerController = attachment.localUri != null
|
||||||
? VideoPlayerController.file(File.fromUri(attachment.localUri!))
|
? VideoPlayerController.file(File.fromUri(attachment.localUri!))
|
||||||
: VideoPlayerController.network(attachment.assetUrl!);
|
: VideoPlayerController.network(attachment.assetUrl!);
|
||||||
|
|
||||||
Future<void> initialize() {
|
final bool _showControls;
|
||||||
return _videoPlayerController.initialize().then((_) {
|
final bool _autoInitialize;
|
||||||
_chewieController = ChewieController(
|
final VideoPlayerController _videoPlayerController;
|
||||||
videoPlayerController: _videoPlayerController,
|
ChewieController? _chewieController;
|
||||||
autoInitialize: _autoInitialize,
|
|
||||||
showControls: _showControls,
|
|
||||||
aspectRatio: _videoPlayerController.value.aspectRatio,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void addListener(VoidCallback listener) {
|
/// Get video player for video
|
||||||
return _videoPlayerController.addListener(listener);
|
VideoPlayerController get videoPlayer => _videoPlayerController;
|
||||||
}
|
|
||||||
|
|
||||||
void removeListener(VoidCallback listener) {
|
/// Get [ChewieController] for video
|
||||||
return _videoPlayerController.removeListener(listener);
|
ChewieController? get chewieController => _chewieController;
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Check if controller is initialised
|
||||||
|
bool get initialized => _videoPlayerController.value.isInitialized;
|
||||||
|
|
||||||
|
/// Initialize all things required for [VideoPackage]
|
||||||
|
Future<void> initialize() => _videoPlayerController.initialize().then((_) {
|
||||||
|
_chewieController = ChewieController(
|
||||||
|
videoPlayerController: _videoPlayerController,
|
||||||
|
autoInitialize: _autoInitialize,
|
||||||
|
showControls: _showControls,
|
||||||
|
aspectRatio: _videoPlayerController.value.aspectRatio,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Add a listener to video player controller
|
||||||
|
void addListener(VoidCallback listener) =>
|
||||||
|
_videoPlayerController.addListener(listener);
|
||||||
|
|
||||||
|
/// Remove a listener to video player controller
|
||||||
|
void removeListener(VoidCallback listener) =>
|
||||||
|
_videoPlayerController.removeListener(listener);
|
||||||
|
|
||||||
|
/// Dispose controllers
|
||||||
Future<void> dispose() {
|
Future<void> dispose() {
|
||||||
_chewieController?.dispose();
|
_chewieController?.dispose();
|
||||||
return _videoPlayerController.dispose();
|
return _videoPlayerController.dispose();
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
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/stream_chat_flutter.dart';
|
||||||
|
|
||||||
import '../stream_chat_flutter.dart';
|
/// Widget for constructing a group of images
|
||||||
|
|
||||||
class GroupImage extends StatelessWidget {
|
class GroupImage extends StatelessWidget {
|
||||||
|
/// Constructor for creating a [GroupImage]
|
||||||
const GroupImage({
|
const GroupImage({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.images,
|
required this.images,
|
||||||
@@ -15,17 +16,30 @@ class GroupImage extends StatelessWidget {
|
|||||||
this.selectionThickness = 4,
|
this.selectionThickness = 4,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// List of images to display
|
||||||
final List<String> images;
|
final List<String> images;
|
||||||
|
|
||||||
|
/// Constraints on the widget
|
||||||
final BoxConstraints? constraints;
|
final BoxConstraints? constraints;
|
||||||
|
|
||||||
|
/// Callback when widget is tapped
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
|
/// Highlights if selected
|
||||||
final bool selected;
|
final bool selected;
|
||||||
|
|
||||||
|
/// [BorderRadius] to pass to the widget
|
||||||
final BorderRadius? borderRadius;
|
final BorderRadius? borderRadius;
|
||||||
|
|
||||||
|
/// Color of selection if selected
|
||||||
final Color? selectionColor;
|
final Color? selectionColor;
|
||||||
|
|
||||||
|
/// Thickness with which color of selection is shown
|
||||||
final double selectionThickness;
|
final double selectionThickness;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var avatar;
|
Widget? avatar;
|
||||||
final streamChatTheme = StreamChatTheme.of(context);
|
final streamChatTheme = StreamChatTheme.of(context);
|
||||||
|
|
||||||
avatar = GestureDetector(
|
avatar = GestureDetector(
|
||||||
|
|||||||
Reference in New Issue
Block a user