add media list view controller to message input

This commit is contained in:
MateusHBR
2022-04-18 14:28:27 -03:00
parent 852f4b1ec5
commit 4e82131cf3
2 changed files with 64 additions and 7 deletions
@@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; 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/media_list_view_controller.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart';
extension on Duration { extension on Duration {
@@ -25,6 +26,7 @@ class MediaListView extends StatefulWidget {
Key? key, Key? key,
this.selectedIds = const [], this.selectedIds = const [],
this.onSelect, this.onSelect,
this.controller,
}) : super(key: key); }) : super(key: key);
/// Stores the media selected /// Stores the media selected
@@ -33,18 +35,28 @@ class MediaListView extends StatefulWidget {
/// Callback for on media selected /// Callback for on media selected
final void Function(AssetEntity media)? onSelect; final void Function(AssetEntity media)? onSelect;
/// Controller that handles MediaListView
final MediaListViewController? controller;
@override @override
_MediaListViewState createState() => _MediaListViewState(); _MediaListViewState createState() => _MediaListViewState();
} }
class _MediaListViewState extends State<MediaListView> { class _MediaListViewState extends State<MediaListView> {
final _media = <AssetEntity>[]; var _media = <AssetEntity>[];
final ScrollController _scrollController = ScrollController(); var _currentPage = 0;
int _currentPage = 0; final _scrollController = ScrollController();
/// Controller necessary to verify limited access to photo gallery in iOS and
/// update the media list when listerners are emitted
late final controller = widget.controller ?? MediaListViewController();
@override @override
Widget build(BuildContext context) => LazyLoadScrollView( Widget build(BuildContext context) => LazyLoadScrollView(
onEndOfPage: () async => _getMedia(), onEndOfPage: () async {
await _getMedia();
_updatePage();
},
child: GridView.builder( child: GridView.builder(
itemCount: _media.length, itemCount: _media.length,
controller: _scrollController, controller: _scrollController,
@@ -141,9 +153,29 @@ class _MediaListViewState extends State<MediaListView> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
controller.addListener(_updateMediaList);
_getMedia(); _getMedia();
} }
@override
void dispose() {
super.dispose();
controller.removeListener(_updateMediaList);
if (widget.controller == null) {
controller.dispose();
}
}
void _updateMediaList() {
if (controller.shouldUpdateMedia) {
_getMedia();
}
}
void _updatePage() {
++_currentPage;
}
Future<void> _getMedia() async { Future<void> _getMedia() async {
final assetList = (await PhotoManager.getAssetPathList( final assetList = (await PhotoManager.getAssetPathList(
filterOption: FilterOptionGroup( filterOption: FilterOptionGroup(
@@ -162,13 +194,11 @@ class _MediaListViewState extends State<MediaListView> {
page: _currentPage, page: _currentPage,
size: 50, size: 50,
); );
if (media?.isNotEmpty == true) { if (media?.isNotEmpty == true) {
setState(() { setState(() {
_media.addAll(media!); _media = media!;
}); });
} }
++_currentPage;
} }
} }
@@ -15,6 +15,7 @@ import 'package:stream_chat_flutter/src/emoji/emoji.dart';
import 'package:stream_chat_flutter/src/emoji_overlay.dart'; import 'package:stream_chat_flutter/src/emoji_overlay.dart';
import 'package:stream_chat_flutter/src/extension.dart'; import 'package:stream_chat_flutter/src/extension.dart';
import 'package:stream_chat_flutter/src/media_list_view.dart'; import 'package:stream_chat_flutter/src/media_list_view.dart';
import 'package:stream_chat_flutter/src/media_list_view_controller.dart';
import 'package:stream_chat_flutter/src/multi_overlay.dart'; import 'package:stream_chat_flutter/src/multi_overlay.dart';
import 'package:stream_chat_flutter/src/quoted_message_widget.dart'; import 'package:stream_chat_flutter/src/quoted_message_widget.dart';
import 'package:stream_chat_flutter/src/user_mentions_overlay.dart'; import 'package:stream_chat_flutter/src/user_mentions_overlay.dart';
@@ -343,6 +344,7 @@ class MessageInputState extends State<MessageInput> {
final List<User> _mentionedUsers = []; final List<User> _mentionedUsers = [];
final _imagePicker = ImagePicker(); final _imagePicker = ImagePicker();
final _mediaListViewController = MediaListViewController();
late final _focusNode = widget.focusNode ?? FocusNode(); late final _focusNode = widget.focusNode ?? FocusNode();
late final _isInternalFocusNode = widget.focusNode == null; late final _isInternalFocusNode = widget.focusNode == null;
bool _inputEnabled = true; bool _inputEnabled = true;
@@ -1056,6 +1058,26 @@ class MessageInputState extends State<MessageInput> {
); );
}, },
), ),
const Spacer(),
FutureBuilder(
future: PhotoManager.requestPermissionExtend(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.data == PermissionState.limited) {
return TextButton(
child: Text(context.translations.viewLibrary),
onPressed: () async {
await PhotoManager.presentLimited();
_mediaListViewController.updateMedia(
newValue: true,
);
},
);
}
return const SizedBox.shrink();
},
),
], ],
), ),
DecoratedBox( DecoratedBox(
@@ -1088,6 +1110,7 @@ class MessageInputState extends State<MessageInput> {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: _PickerWidget( child: _PickerWidget(
mediaListViewController: _mediaListViewController,
filePickerIndex: _filePickerIndex, filePickerIndex: _filePickerIndex,
streamChatTheme: _streamChatTheme, streamChatTheme: _streamChatTheme,
containsFile: _attachmentContainsFile, containsFile: _attachmentContainsFile,
@@ -1966,6 +1989,7 @@ class _PickerWidget extends StatefulWidget {
required this.onAddMoreFilesClick, required this.onAddMoreFilesClick,
required this.onMediaSelected, required this.onMediaSelected,
required this.streamChatTheme, required this.streamChatTheme,
required this.mediaListViewController,
}) : super(key: key); }) : super(key: key);
final int filePickerIndex; final int filePickerIndex;
@@ -1974,6 +1998,7 @@ class _PickerWidget extends StatefulWidget {
final void Function(DefaultAttachmentTypes) onAddMoreFilesClick; final void Function(DefaultAttachmentTypes) onAddMoreFilesClick;
final void Function(AssetEntity) onMediaSelected; final void Function(AssetEntity) onMediaSelected;
final StreamChatThemeData streamChatTheme; final StreamChatThemeData streamChatTheme;
final MediaListViewController mediaListViewController;
@override @override
_PickerWidgetState createState() => _PickerWidgetState(); _PickerWidgetState createState() => _PickerWidgetState();
@@ -2021,7 +2046,9 @@ class _PickerWidgetState extends State<_PickerWidget> {
), ),
); );
} }
return MediaListView( return MediaListView(
controller: widget.mediaListViewController,
selectedIds: widget.selectedMedias, selectedIds: widget.selectedMedias,
onSelect: widget.onMediaSelected, onSelect: widget.onMediaSelected,
); );