extraRecentMedia parameter added. MediaFile.file() added. Documantation changed

This commit is contained in:
Furkan 2022-12-31 16:43:05 +03:00
parent e07af8a394
commit 1bf66592fe
19 changed files with 268 additions and 124 deletions

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"permission_handler_apple","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_apple-9.0.7\\\\","native_build":true,"dependencies":[]},{"name":"photo_gallery","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\photo_gallery-1.1.1\\\\","native_build":true,"dependencies":[]},{"name":"video_player_avfoundation","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_avfoundation-2.3.8\\\\","native_build":true,"dependencies":[]},{"name":"video_thumbnail","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_thumbnail-0.5.3\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"permission_handler_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_android-10.2.0\\\\","native_build":true,"dependencies":[]},{"name":"photo_gallery","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\photo_gallery-1.1.1\\\\","native_build":true,"dependencies":[]},{"name":"video_player_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_android-2.3.10\\\\","native_build":true,"dependencies":[]},{"name":"video_thumbnail","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_thumbnail-0.5.3\\\\","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[{"name":"permission_handler_windows","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_windows-0.1.2\\\\","native_build":true,"dependencies":[]}],"web":[{"name":"video_player_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_web-2.0.13\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"photo_gallery","dependencies":[]},{"name":"video_player","dependencies":["video_player_android","video_player_avfoundation","video_player_web"]},{"name":"video_player_android","dependencies":[]},{"name":"video_player_avfoundation","dependencies":[]},{"name":"video_player_web","dependencies":[]},{"name":"video_thumbnail","dependencies":[]}],"date_created":"2022-12-30 05:18:44.302087","version":"3.3.9"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"permission_handler_apple","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_apple-9.0.7\\\\","native_build":true,"dependencies":[]},{"name":"photo_gallery","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\photo_gallery-1.1.1\\\\","native_build":true,"dependencies":[]},{"name":"video_player_avfoundation","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_avfoundation-2.3.8\\\\","native_build":true,"dependencies":[]},{"name":"video_thumbnail","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_thumbnail-0.5.3\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"permission_handler_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_android-10.2.0\\\\","native_build":true,"dependencies":[]},{"name":"photo_gallery","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\photo_gallery-1.1.1\\\\","native_build":true,"dependencies":[]},{"name":"video_player_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_android-2.3.10\\\\","native_build":true,"dependencies":[]},{"name":"video_thumbnail","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_thumbnail-0.5.3\\\\","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[{"name":"permission_handler_windows","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler_windows-0.1.2\\\\","native_build":true,"dependencies":[]}],"web":[{"name":"video_player_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\video_player_web-2.0.13\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"photo_gallery","dependencies":[]},{"name":"video_player","dependencies":["video_player_android","video_player_avfoundation","video_player_web"]},{"name":"video_player_android","dependencies":[]},{"name":"video_player_avfoundation","dependencies":[]},{"name":"video_player_web","dependencies":[]},{"name":"video_thumbnail","dependencies":[]}],"date_created":"2022-12-31 16:40:26.960029","version":"3.3.10"}

View File

@ -83,12 +83,12 @@ Quick and simple usage example:
### Pick Single File ### Pick Single File
```dart ```dart
MediaFile? media = await GalleryPicker.pickMedias(context: context,singleMedia: true); MediaFile? singleMedia = await GalleryPicker.pickMedia(context: context,singleMedia: true);
``` ```
### Pick Multiple Files ### Pick Multiple Files
```dart ```dart
List<MediaFile>? medias = await GalleryPicker.pickMedias(context: context); List<MediaFile>? media = await GalleryPicker.pickMedia(context: context);
``` ```
### Get All Media Files in Gallery ### Get All Media Files in Gallery
@ -121,7 +121,8 @@ There is an example at `example/lib/examples/bottom_sheet_example.dart` to see h
title: Text(widget.title), title: Text(widget.title),
), ),
body: BottomSheetLayout( body: BottomSheetLayout(
onSelect: (medias) {}, config: Config()
onSelect: (media) {},
child: Column( child: Column(
children: [ children: [
``` ```
@ -130,13 +131,13 @@ There is an example at `example/lib/examples/bottom_sheet_example.dart` to see h
Within the Gallery Picker you can design a page that will be redirected after selecting any image(s). Within the Gallery Picker you can design a page that will be redirected after selecting any image(s).
Note: There are two builder called multipleMediasBuilder and heroBuilder. If you designed both of them, multipleMediasBuilder will be shown after picking multiple media files, heroBuilder will be shown after picking a single media. Use given hero tag to view your Hero image. You can see a simple example below. Note: There are two builder called multipleMediaBuilder and heroBuilder. If you designed both of them, multipleMediaBuilder will be shown after picking multiple media files, heroBuilder will be shown after picking a single media. Use given hero tag to view your Hero image. You can see a simple example below.
There is an example at `example/lib/examples/pick_medias_with_builder.dart` to see how it could be done. There is an example at `example/lib/examples/pick_medias_with_builder.dart` to see how it could be done.
```dart ```dart
GalleryPicker.pickMediasWithBuilder( GalleryPicker.pickMediaWithBuilder(
multipleMediasBuilder: ((medias, context) { multipleMediaBuilder: ((media, context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('Flippers Page'), title: const Text('Flippers Page'),
@ -146,9 +147,9 @@ There is an example at `example/lib/examples/pick_medias_with_builder.dart` to s
mainAxisSpacing: 5, mainAxisSpacing: 5,
crossAxisSpacing: 5, crossAxisSpacing: 5,
children: [ children: [
for (var media in medias) for (var mediaFile in media)
ThumbnailMedia( ThumbnailMedia(
media: media, media: mediaFile,
) )
], ],
), ),
@ -159,7 +160,7 @@ There is an example at `example/lib/examples/pick_medias_with_builder.dart` to s
MaterialPageRoute( MaterialPageRoute(
builder: (context) => MyHomePage( builder: (context) => MyHomePage(
title: "Selected Medias", title: "Selected Medias",
medias: medias, medias: media,
)), )),
); );
GalleryPicker.dispose(); GalleryPicker.dispose();
@ -220,7 +221,7 @@ A Config class is provided to user to customize your gallery picker. You can cus
#### Customizable appereance features #### Customizable appereance features
```dart ```dart
List<MediaFile>? medias = await GalleryPicker.pickMedias( List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context, context: context,
config: Config( config: Config(
backgroundColor: Colors.white, backgroundColor: Colors.white,
@ -273,7 +274,7 @@ List<MediaFile>? medias = await GalleryPicker.pickMedias(
#### Appearance Mode #### Appearance Mode
```dart ```dart
List<MediaFile>? medias = await GalleryPicker.pickMedias( List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context, context: context,
config: Config( config: Config(
mode: Mode.dark mode: Mode.dark
@ -284,9 +285,19 @@ List<MediaFile>? medias = await GalleryPicker.pickMedias(
#### Give an initial selected media files #### Give an initial selected media files
```dart ```dart
List<MediaFile>? medias = await GalleryPicker.pickMedias( List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context, context: context,
initSelectedMedias: this.selectedMedias, initSelectedMedia: initSelectedMedia,
)
```
#### Give extra media files that will be included in recent
You can give extra pictures to appear on the recent page. You should define these files with MediaFile.file()
```dart
MediaFile file = MediaFile.file(id: "id", file: File("path"), type: MediaType.image);
List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context,
extraRecentMedia: [file],
) )
``` ```
#### Select your priority page #### Select your priority page
@ -294,7 +305,7 @@ List<MediaFile>? medias = await GalleryPicker.pickMedias(
There are two pages called "Recent" and "Gallery". You could change the initial page. There are two pages called "Recent" and "Gallery". You could change the initial page.
```dart ```dart
List<MediaFile>? medias = await GalleryPicker.pickMedias( List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context, context: context,
startWithRecent: true, startWithRecent: true,
) )

View File

@ -123,21 +123,21 @@ class _GalleryPickerExampleState extends State<GalleryPickerExample> {
), ),
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: pickMedias, onPressed: pickMedia,
tooltip: 'Increment', tooltip: 'Increment',
child: const Icon(Icons.add), child: const Icon(Icons.add),
), ),
); );
} }
Future<void> pickMedias() async { Future<void> pickMedia() async {
List<MediaFile>? medias = await GalleryPicker.pickMedias( List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context, context: context,
config: Config(mode: Mode.dark), config: Config(mode: Mode.dark),
); );
if (medias != null) { if (media != null) {
setState(() { setState(() {
selectedMedias += medias; selectedMedias += media;
}); });
} }
} }

View File

@ -27,7 +27,7 @@ class _PickMediasWithBuilderState extends State<PickMediasWithBuilder> {
children: <Widget>[ children: <Widget>[
const Spacer(), const Spacer(),
TextButton( TextButton(
onPressed: pickMediasWithBuilder, onPressed: pickMediaWithBuilder,
child: Container( child: Container(
width: 300, width: 300,
height: 60, height: 60,
@ -49,9 +49,9 @@ class _PickMediasWithBuilderState extends State<PickMediasWithBuilder> {
); );
} }
pickMediasWithBuilder() { pickMediaWithBuilder() {
GalleryPicker.pickMediasWithBuilder( GalleryPicker.pickMediaWithBuilder(
multipleMediasBuilder: ((medias, context) { multipleMediaBuilder: ((medias, context) {
return MultipleMediasView(medias); return MultipleMediasView(medias);
}), }),
heroBuilder: (tag, media, context) { heroBuilder: (tag, media, context) {

View File

@ -79,7 +79,7 @@ class _WhatsappPickPhotoState extends State<WhatsappPickPhoto> {
this.selectedMedias = selectedMedias; this.selectedMedias = selectedMedias;
setState(() {}); setState(() {});
}, },
initSelectedMedias: selectedMedias, initSelectedMedia: selectedMedias,
config: Config(mode: Mode.dark), config: Config(mode: Mode.dark),
child: Stack( child: Stack(
children: [ children: [

View File

@ -163,28 +163,30 @@ class _MyHomePageState extends State<MyHomePage> {
), ),
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: pickMedias, onPressed: pickMedia,
tooltip: 'Increment', tooltip: 'Increment',
child: const Icon(Icons.add), child: const Icon(Icons.add),
), ),
); );
} }
Future<void> pickMedias() async { Future<void> pickMedia() async {
List<MediaFile>? medias = await GalleryPicker.pickMedias( List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context, context: context,
initSelectedMedias: selectedMedias, config: Config(lastWeek: "Bu hafta"),
initSelectedMedia: selectedMedias,
extraRecentMedia: selectedMedias,
startWithRecent: true); startWithRecent: true);
if (medias != null) { if (media != null) {
setState(() { setState(() {
selectedMedias += medias; selectedMedias += media;
}); });
} }
} }
pickMediasWithBuilder() { pickMediaWithBuilder() {
GalleryPicker.pickMediasWithBuilder( GalleryPicker.pickMediaWithBuilder(
multipleMediasBuilder: ((medias, context) { multipleMediaBuilder: ((medias, context) {
return MultipleMediasView(medias); return MultipleMediasView(medias);
}), }),
heroBuilder: (tag, media, context) { heroBuilder: (tag, media, context) {

View File

@ -136,7 +136,7 @@ packages:
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
gallery_picker: gallery_picker:
dependency: "direct overridden" dependency: "direct dev"
description: description:
path: ".." path: ".."
relative: true relative: true

View File

@ -49,6 +49,7 @@ dev_dependencies:
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0
camera: ^0.10.1 camera: ^0.10.1
gallery_picker: ^0.0.6
dependency_overrides: dependency_overrides:
gallery_picker: gallery_picker:

View File

@ -19,12 +19,16 @@ class PhoneGalleryController extends GetxController {
{required this.onSelect, {required this.onSelect,
required this.heroBuilder, required this.heroBuilder,
required this.isRecent, required this.isRecent,
List<MediaFile>? initSelectedMedias, required List<MediaFile>? initSelectedMedias,
required List<MediaFile>? extraRecentMedia,
required this.multipleMediasBuilder}) { required this.multipleMediasBuilder}) {
this.config = config ?? Config(); this.config = config ?? Config();
if (initSelectedMedias != null) { if (initSelectedMedias != null) {
_selectedFiles = initSelectedMedias.map((e) => e).toList(); _selectedFiles = initSelectedMedias.map((e) => e).toList();
} }
if (extraRecentMedia != null) {
_extraRecentMedia = extraRecentMedia.map((e) => e).toList();
}
} }
bool isRecent; bool isRecent;
Function(List<MediaFile> selectedMedias) onSelect; Function(List<MediaFile> selectedMedias) onSelect;
@ -36,20 +40,32 @@ class PhoneGalleryController extends GetxController {
List<GalleryAlbum> _galleryAlbums = []; List<GalleryAlbum> _galleryAlbums = [];
List<GalleryAlbum> get galleryAlbums => _galleryAlbums; List<GalleryAlbum> get galleryAlbums => _galleryAlbums;
List<MediaFile> _selectedFiles = []; List<MediaFile> _selectedFiles = [];
List<MediaFile>? _extraRecentMedia;
List<MediaFile> get selectedFiles => _selectedFiles; List<MediaFile> get selectedFiles => _selectedFiles;
bool _isInitialized = false; bool _isInitialized = false;
bool get isInitialized => _isInitialized; bool get isInitialized => _isInitialized;
List<MediaFile>? get extraRecentMedia => _extraRecentMedia;
bool _pickerMode = false; bool _pickerMode = false;
bool get pickerMode => _pickerMode; bool get pickerMode => _pickerMode;
void updateSelectedFiles(List<MediaFile> medias) { void updateSelectedFiles(List<MediaFile> media) {
_selectedFiles = medias; _selectedFiles = media.map((e) => e).toList();
if (selectedFiles.isNotEmpty) { if (selectedFiles.isNotEmpty) {
_pickerMode = true; _pickerMode = true;
} }
update(); update();
} }
void updateExtraRecentMedia(List<MediaFile> media) {
_extraRecentMedia = media.map((e) => e).toList();
GalleryAlbum? recentTmp = recent;
if (recentTmp != null) {
_extraRecentMedia!.removeWhere(
(element) => recentTmp.files.any((file) => element.id == file.id));
}
update();
}
void changeAlbum(GalleryAlbum? album) { void changeAlbum(GalleryAlbum? album) {
selectedAlbum = album; selectedAlbum = album;
_selectedFiles.clear(); _selectedFiles.clear();
@ -106,7 +122,15 @@ class PhoneGalleryController extends GetxController {
GalleryMedia? media = await PhoneGalleryController.collectGallery; GalleryMedia? media = await PhoneGalleryController.collectGallery;
if (media != null) { if (media != null) {
_galleryAlbums = media.albums; _galleryAlbums = media.albums;
if (_extraRecentMedia != null) {
GalleryAlbum? recentTmp = recent;
if (recentTmp != null) {
_extraRecentMedia!.removeWhere((element) =>
recentTmp.files.any((file) => element.id == file.id));
}
}
} }
_isInitialized = true; _isInitialized = true;
update(); update();
} }
@ -121,13 +145,13 @@ class PhoneGalleryController extends GetxController {
await PhotoGallery.listAlbums(mediumType: MediumType.video); await PhotoGallery.listAlbums(mediumType: MediumType.video);
for (var photoAlbum in photoAlbums) { for (var photoAlbum in photoAlbums) {
GalleryAlbum entireGalleryAlbum = GalleryAlbum(album: photoAlbum); GalleryAlbum entireGalleryAlbum = GalleryAlbum.album(photoAlbum);
await entireGalleryAlbum.initialize(); await entireGalleryAlbum.initialize();
entireGalleryAlbum.setType = AlbumType.image; entireGalleryAlbum.setType = AlbumType.image;
if (videoAlbums.any((element) => element.name == photoAlbum.name)) { if (videoAlbums.any((element) => element.name == photoAlbum.name)) {
Album videoAlbum = videoAlbums Album videoAlbum = videoAlbums
.singleWhere((element) => element.name == photoAlbum.name); .singleWhere((element) => element.name == photoAlbum.name);
GalleryAlbum videoGalleryAlbum = GalleryAlbum(album: videoAlbum); GalleryAlbum videoGalleryAlbum = GalleryAlbum.album(videoAlbum);
await videoGalleryAlbum.initialize(); await videoGalleryAlbum.initialize();
DateTime? lastPhotoDate = entireGalleryAlbum.lastDate; DateTime? lastPhotoDate = entireGalleryAlbum.lastDate;
DateTime? lastVideoDate = videoGalleryAlbum.lastDate; DateTime? lastVideoDate = videoGalleryAlbum.lastDate;
@ -165,7 +189,7 @@ class PhoneGalleryController extends GetxController {
tempGalleryAlbums.add(entireGalleryAlbum); tempGalleryAlbums.add(entireGalleryAlbum);
} }
for (var videoAlbum in videoAlbums) { for (var videoAlbum in videoAlbums) {
GalleryAlbum galleryVideoAlbum = GalleryAlbum(album: videoAlbum); GalleryAlbum galleryVideoAlbum = GalleryAlbum.album(videoAlbum);
await galleryVideoAlbum.initialize(); await galleryVideoAlbum.initialize();
galleryVideoAlbum.setType = AlbumType.video; galleryVideoAlbum.setType = AlbumType.video;
tempGalleryAlbums.add(galleryVideoAlbum); tempGalleryAlbums.add(galleryVideoAlbum);
@ -178,10 +202,31 @@ class PhoneGalleryController extends GetxController {
} }
GalleryAlbum? get recent { GalleryAlbum? get recent {
return _isInitialized return _galleryAlbums.isNotEmpty
? _galleryAlbums.singleWhere((element) => element.album.name == "All") ? _galleryAlbums.singleWhere((element) => element.album.name == "All")
: null; : null;
} }
//GalleryAlbum? get recent {
// if (_isInitialized) {
// GalleryAlbum? recent;
// for (var album in _galleryAlbums) {
// if (recent == null || (album.count > recent.count)) {
// recent = album;
// }
// }
// if (recent != null) {
// return GalleryAlbum(
// album: recent.album,
// type: recent.type,
// thumbnail: recent.thumbnail,
// dateCategories: recent.dateCategories);
// } else {
// return null;
// }
// } else {
// return null;
// }
//}
List<Medium> sortAlbumMediaDates(List<Medium> mediumList) { List<Medium> sortAlbumMediaDates(List<Medium> mediumList) {
mediumList.sort((a, b) { mediumList.sort((a, b) {

View File

@ -11,7 +11,7 @@ export 'user_widgets/album_categories_view.dart';
export 'user_widgets/album_medias.dart'; export 'user_widgets/album_medias.dart';
export 'user_widgets/date_category_view.dart'; export 'user_widgets/date_category_view.dart';
export 'user_widgets/thumbnail_album.dart'; export 'user_widgets/thumbnail_album.dart';
export 'user_widgets/files_stream_builder.dart'; export 'user_widgets/gallery_picker_builder.dart';
export 'user_widgets/photo_provider.dart'; export 'user_widgets/photo_provider.dart';
export 'user_widgets/video_provider.dart'; export 'user_widgets/video_provider.dart';
export 'user_widgets/media_provider.dart'; export 'user_widgets/media_provider.dart';
@ -48,45 +48,53 @@ class GalleryPicker {
} }
} }
static Future<List<MediaFile>?> pickMedias( static Future<List<MediaFile>?> pickMedia(
{Config? config, {Config? config,
bool startWithRecent = false, bool startWithRecent = false,
List<MediaFile>? initSelectedMedias, bool singleMedia = false,
List<MediaFile>? initSelectedMedia,
List<MediaFile>? extraRecentMedia,
required BuildContext context}) async { required BuildContext context}) async {
List<MediaFile>? medias; List<MediaFile>? media;
await Navigator.push( await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => GalleryPickerView( builder: (context) => GalleryPickerView(
onSelect: (mediasTmp) { onSelect: (mediaTmp) {
medias = mediasTmp; media = mediaTmp;
}, },
config: config, config: config,
initSelectedMedias: initSelectedMedias, singleMedia: singleMedia,
initSelectedMedia: initSelectedMedia,
extraRecentMedia: extraRecentMedia,
startWithRecent: startWithRecent, startWithRecent: startWithRecent,
)), )),
); );
return medias; return media;
} }
static Future<void> pickMediasWithBuilder( static Future<void> pickMediaWithBuilder(
{Config? config, {Config? config,
required Widget Function(List<MediaFile> medias, BuildContext context)? required Widget Function(List<MediaFile> media, BuildContext context)?
multipleMediasBuilder, multipleMediaBuilder,
Widget Function(String tag, MediaFile media, BuildContext context)? Widget Function(String tag, MediaFile media, BuildContext context)?
heroBuilder, heroBuilder,
List<MediaFile>? initSelectedMedias, bool singleMedia = false,
List<MediaFile>? initSelectedMedia,
List<MediaFile>? extraRecentMedia,
bool startWithRecent = false, bool startWithRecent = false,
required BuildContext context}) async { required BuildContext context}) async {
await Navigator.push( await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => GalleryPickerView( builder: (context) => GalleryPickerView(
onSelect: (medias) {}, onSelect: (media) {},
multipleMediasBuilder: multipleMediasBuilder, multipleMediaBuilder: multipleMediaBuilder,
heroBuilder: heroBuilder, heroBuilder: heroBuilder,
singleMedia: singleMedia,
config: config, config: config,
initSelectedMedias: initSelectedMedias, initSelectedMedia: initSelectedMedia,
extraRecentMedia: extraRecentMedia,
startWithRecent: startWithRecent, startWithRecent: startWithRecent,
)), )),
); );

View File

@ -13,7 +13,13 @@ class Config {
appbarTextStyle, appbarTextStyle,
selectedMenuStyle, selectedMenuStyle,
unselectedMenuStyle; unselectedMenuStyle;
String recents, gallery, lastMonth, lastWeek, tapPhotoSelect, selected; String recents,
recent,
gallery,
lastMonth,
lastWeek,
tapPhotoSelect,
selected;
List<String> months; List<String> months;
Mode mode; Mode mode;
@ -28,6 +34,7 @@ class Config {
TextStyle? textStyle, TextStyle? textStyle,
TextStyle? appbarTextStyle, TextStyle? appbarTextStyle,
this.recents = "RECENTS", this.recents = "RECENTS",
this.recent = "Recent",
this.gallery = "GALLERY", this.gallery = "GALLERY",
this.lastMonth = "Last Month", this.lastMonth = "Last Month",
this.lastWeek = "Last Week", this.lastWeek = "Last Week",

View File

@ -1,26 +1,36 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:photo_gallery/photo_gallery.dart'; import 'package:photo_gallery/photo_gallery.dart';
import '../controller/gallery_controller.dart';
import '/models/media_file.dart'; import '/models/media_file.dart';
import '/models/medium.dart'; import '/models/medium.dart';
import 'config.dart';
class GalleryAlbum { class GalleryAlbum {
Album album; late Album album;
late List<int>? thumbnail; late List<int>? thumbnail;
List<DateCategory> dateCategories = []; List<DateCategory> dateCategories = [];
late AlbumType type;
int get count => int get count =>
dateCategories.expand((element) => element.files).toList().length; dateCategories.expand((element) => element.files).toList().length;
String? get name => album.name; String? get name => album.name;
GalleryAlbum.album(this.album);
GalleryAlbum(
{required this.album,
required this.type,
this.thumbnail,
this.dateCategories = const []});
List<MediaFile> get medias { List<MediaFile> get medias {
return dateCategories return dateCategories
.expand<MediaFile>((element) => element.files) .expand<MediaFile>((element) => element.files)
.toList(); .toList();
} }
late AlbumType type;
set setType(AlbumType type) { set setType(AlbumType type) {
this.type = type; this.type = type;
} }
@ -36,10 +46,6 @@ class GalleryAlbum {
} }
} }
GalleryAlbum({
required this.album,
});
Future<void> initialize() async { Future<void> initialize() async {
List<DateCategory> dateCategory = []; List<DateCategory> dateCategory = [];
for (var medium in sortAlbumMediaDates((await album.listMedia()).items)) { for (var medium in sortAlbumMediaDates((await album.listMedia()).items)) {
@ -76,14 +82,15 @@ class GalleryAlbum {
dateCategories.expand((element) => element.files).toList(); dateCategories.expand((element) => element.files).toList();
String getDateCategory(Medium mediaFile) { String getDateCategory(Medium mediaFile) {
Config config = Get.find<PhoneGalleryController>().config;
if (daysBetween(mediaFile.lastDate!) <= 3) { if (daysBetween(mediaFile.lastDate!) <= 3) {
return "Recent"; return config.recent;
} else if (daysBetween(mediaFile.lastDate!) > 3 && } else if (daysBetween(mediaFile.lastDate!) > 3 &&
daysBetween(mediaFile.lastDate!) <= 7) { daysBetween(mediaFile.lastDate!) <= 7) {
return "Last week"; return config.lastWeek;
} else if (daysBetween(mediaFile.lastDate!) > 7 && } else if (daysBetween(mediaFile.lastDate!) > 7 &&
daysBetween(mediaFile.lastDate!) <= 31) { daysBetween(mediaFile.lastDate!) <= 31) {
return "Last month"; return config.lastMonth;
} else if (daysBetween(mediaFile.lastDate!) > 31 && } else if (daysBetween(mediaFile.lastDate!) > 31 &&
daysBetween(mediaFile.lastDate!) <= 365) { daysBetween(mediaFile.lastDate!) <= 365) {
return DateFormat.MMMM().format(mediaFile.lastDate!).toString(); return DateFormat.MMMM().format(mediaFile.lastDate!).toString();
@ -140,31 +147,19 @@ class GalleryAlbum {
} }
} }
List<String> dates = [
"Recent",
"Last week",
"Last month",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
class DateCategory { class DateCategory {
String name; String name;
List<MediaFile> files; List<MediaFile> files;
DateCategory({required this.files, required this.name}); DateCategory({required this.files, required this.name});
int getIndexOfCategory() { int getIndexOfCategory() {
int index = dates.indexOf(name); Config config = Get.find<PhoneGalleryController>().config;
int index = [
config.recent,
config.lastWeek,
config.lastMonth,
config.months
].indexOf(name);
if (index == -1) { if (index == -1) {
return 3000 - int.parse(name); return 3000 - int.parse(name);
} else { } else {

View File

@ -5,12 +5,12 @@ import 'gallery_album.dart';
class GalleryMedia { class GalleryMedia {
List<GalleryAlbum> albums; List<GalleryAlbum> albums;
GalleryAlbum? get recent { GalleryAlbum? get recent {
return albums.singleWhere((element) => element.album.name == "All"); return albums.singleWhere((element) => element.name == "All");
} }
GalleryAlbum? getAlbum(String name) { GalleryAlbum? getAlbum(String name) {
try { try {
return albums.singleWhere((element) => element.album.name == name); return albums.singleWhere((element) => element.name == name);
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print(e); print(e);

View File

@ -3,10 +3,13 @@ import 'dart:io';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:photo_gallery/photo_gallery.dart'; import 'package:photo_gallery/photo_gallery.dart';
import 'package:video_thumbnail/video_thumbnail.dart';
import '../controller/gallery_controller.dart'; import '../controller/gallery_controller.dart';
enum MediaType { image, video }
class MediaFile { class MediaFile {
Medium medium; late Medium medium;
MediumType? type; MediumType? type;
Uint8List? thumbnail; Uint8List? thumbnail;
Uint8List? data; Uint8List? data;
@ -17,18 +20,39 @@ class MediaFile {
type = medium.mediumType; type = medium.mediumType;
id = medium.id; id = medium.id;
} }
Future<void> getThumbnail() async { MediaFile.file(
{required this.id, required this.file, required MediaType type}) {
this.type = type == MediaType.image ? MediumType.image : MediumType.video;
medium = Medium(id: id);
}
Future<Uint8List?> getThumbnail() async {
try { try {
thumbnail = if (file != null) {
Uint8List.fromList(await medium.getThumbnail(highQuality: true)); thumbnail = await VideoThumbnail.thumbnailData(
video: file!.path,
imageFormat: ImageFormat.JPEG,
maxWidth:
128, // specify the width of the thumbnail, let the height auto-scaled to keep the source aspect ratio
quality: 25,
);
} else {
thumbnail =
Uint8List.fromList(await medium.getThumbnail(highQuality: true));
}
} catch (e) { } catch (e) {
thumbnailFailed = true; thumbnailFailed = true;
} }
return thumbnail;
} }
Future<File> getFile() async { Future<File> getFile() async {
file = await medium.getFile(); if (file == null) {
return file!; file = await medium.getFile();
return file!;
} else {
return file!;
}
} }
Future<Uint8List> getData() async { Future<Uint8List> getData() async {

View File

@ -3,9 +3,10 @@ import 'package:get/get.dart';
import '../controller/picker_listener.dart'; import '../controller/picker_listener.dart';
import '../models/media_file.dart'; import '../models/media_file.dart';
class FilesStreamBuilder extends StatelessWidget { class GalleryPickerBuilder extends StatelessWidget {
final Widget Function(List<MediaFile>? medias, BuildContext context) builder; final Widget Function(List<MediaFile>? selectedFiles, BuildContext context)
FilesStreamBuilder({super.key, required this.builder}) { builder;
GalleryPickerBuilder({super.key, required this.builder}) {
Get.put(PickerListener()); Get.put(PickerListener());
} }

View File

@ -50,7 +50,7 @@ class AlbumAppBar extends StatelessWidget with PreferredSizeWidget {
Widget getTitle() { Widget getTitle() {
if (!controller.pickerMode && controller.selectedFiles.isEmpty) { if (!controller.pickerMode && controller.selectedFiles.isEmpty) {
return Text( return Text(
album.album.name!, album.name!,
style: controller.config.appbarTextStyle, style: controller.config.appbarTextStyle,
); );
} else if (controller.pickerMode && controller.selectedFiles.isEmpty) { } else if (controller.pickerMode && controller.selectedFiles.isEmpty) {

View File

@ -19,7 +19,7 @@ class AlbumMediasView extends StatelessWidget {
children: [ children: [
ListView( ListView(
children: [ children: [
for (var category in galleryAlbum.dateCategories) for (var category in checkCategories(galleryAlbum.dateCategories))
DateCategoryWiew( DateCategoryWiew(
category: category, category: category,
controller: controller, controller: controller,
@ -36,4 +36,31 @@ class AlbumMediasView extends StatelessWidget {
], ],
); );
} }
List<DateCategory> checkCategories(List<DateCategory> categories) {
if (controller.isRecent &&
controller.extraRecentMedia != null &&
controller.extraRecentMedia!.isNotEmpty) {
List<DateCategory> categoriesTmp = categories.map((e) => e).toList();
int index = categoriesTmp
.indexWhere((element) => element.name == controller.config.recent);
if (index != -1) {
DateCategory category = DateCategory(files: [
...controller.extraRecentMedia!,
...categoriesTmp[index].files
], name: categoriesTmp[index].name);
categoriesTmp[index] = category;
return categoriesTmp;
} else {
return [
DateCategory(
files: controller.extraRecentMedia!,
name: controller.config.recent),
...categoriesTmp
];
}
} else {
return categories;
}
}
} }

View File

@ -8,12 +8,14 @@ import '../controller/bottom_sheet_controller.dart';
class BottomSheetLayout extends StatefulWidget { class BottomSheetLayout extends StatefulWidget {
final Widget child; final Widget child;
final Config? config; final Config? config;
final List<MediaFile>? initSelectedMedias; final List<MediaFile>? initSelectedMedia;
final Function(List<MediaFile> selectedMedias) onSelect; final List<MediaFile>? extraRecentMedia;
final bool singleMedia;
final Function(List<MediaFile> selectedMedia) onSelect;
final Widget Function(String tag, MediaFile media, BuildContext context)? final Widget Function(String tag, MediaFile media, BuildContext context)?
heroBuilder; heroBuilder;
final Widget Function(List<MediaFile> medias, BuildContext context)? final Widget Function(List<MediaFile> media, BuildContext context)?
multipleMediasBuilder; multipleMediaBuilder;
final bool startWithRecent; final bool startWithRecent;
BottomSheetLayout( BottomSheetLayout(
{super.key, {super.key,
@ -21,13 +23,20 @@ class BottomSheetLayout extends StatefulWidget {
required this.onSelect, required this.onSelect,
this.config, this.config,
this.heroBuilder, this.heroBuilder,
this.initSelectedMedias, this.initSelectedMedia,
this.multipleMediasBuilder, this.extraRecentMedia,
this.singleMedia = false,
this.multipleMediaBuilder,
this.startWithRecent = true}) { this.startWithRecent = true}) {
if (initSelectedMedias != null && if (GetInstance().isRegistered<PhoneGalleryController>()) {
GetInstance().isRegistered<PhoneGalleryController>()) { if (initSelectedMedia != null) {
Get.find<PhoneGalleryController>() Get.find<PhoneGalleryController>()
.updateSelectedFiles(initSelectedMedias!); .updateSelectedFiles(initSelectedMedia!);
}
if (extraRecentMedia != null) {
Get.find<PhoneGalleryController>()
.updateExtraRecentMedia(extraRecentMedia!);
}
} }
} }
@ -97,8 +106,10 @@ class _BottomSheetLayoutState extends State<BottomSheetLayout> {
config: widget.config, config: widget.config,
sheetController: bottomSheetBarController, sheetController: bottomSheetBarController,
heroBuilder: widget.heroBuilder, heroBuilder: widget.heroBuilder,
multipleMediasBuilder: widget.multipleMediasBuilder, multipleMediaBuilder: widget.multipleMediaBuilder,
initSelectedMedias: widget.initSelectedMedias, singleMedia: widget.singleMedia,
initSelectedMedia: widget.initSelectedMedia,
extraRecentMedia: widget.extraRecentMedia,
startWithRecent: widget.startWithRecent, startWithRecent: widget.startWithRecent,
) )
: Container( : Container(
@ -115,8 +126,10 @@ class _BottomSheetLayoutState extends State<BottomSheetLayout> {
config: widget.config, config: widget.config,
sheetController: bottomSheetBarController, sheetController: bottomSheetBarController,
heroBuilder: widget.heroBuilder, heroBuilder: widget.heroBuilder,
multipleMediasBuilder: widget.multipleMediasBuilder, singleMedia: widget.singleMedia,
initSelectedMedias: widget.initSelectedMedias, multipleMediaBuilder: widget.multipleMediaBuilder,
initSelectedMedia: widget.initSelectedMedia,
extraRecentMedia: widget.extraRecentMedia,
startWithRecent: widget.startWithRecent, startWithRecent: widget.startWithRecent,
), ),
viewPicker: controller.isClosing ? false : viewCollapsedPicker, viewPicker: controller.isClosing ? false : viewCollapsedPicker,

View File

@ -4,6 +4,7 @@ import 'package:get/get.dart';
import '../../controller/bottom_sheet_controller.dart'; import '../../controller/bottom_sheet_controller.dart';
import '../../controller/gallery_controller.dart'; import '../../controller/gallery_controller.dart';
import '../../models/config.dart'; import '../../models/config.dart';
import '../../models/gallery_album.dart';
import '../../models/media_file.dart'; import '../../models/media_file.dart';
import '../album_categories_view/album_categories_view.dart'; import '../album_categories_view/album_categories_view.dart';
import '../album_view/album_page.dart'; import '../album_view/album_page.dart';
@ -13,24 +14,26 @@ import 'reload_gallery.dart';
class GalleryPickerView extends StatefulWidget { class GalleryPickerView extends StatefulWidget {
final Config? config; final Config? config;
final Function(List<MediaFile> selectedMedias) onSelect; final Function(List<MediaFile> selectedMedia) onSelect;
final Widget Function(String tag, MediaFile media, BuildContext context)? final Widget Function(String tag, MediaFile media, BuildContext context)?
heroBuilder; heroBuilder;
final Widget Function(List<MediaFile> medias, BuildContext context)? final Widget Function(List<MediaFile> media, BuildContext context)?
multipleMediasBuilder; multipleMediaBuilder;
final bool startWithRecent; final bool startWithRecent;
final BottomSheetBarController? sheetController; final BottomSheetBarController? sheetController;
final List<MediaFile>? initSelectedMedias; final List<MediaFile>? initSelectedMedia;
final List<MediaFile>? extraRecentMedia;
final bool singleMedia; final bool singleMedia;
const GalleryPickerView( const GalleryPickerView(
{super.key, {super.key,
this.config, this.config,
required this.onSelect, required this.onSelect,
this.initSelectedMedias, this.initSelectedMedia,
this.extraRecentMedia,
this.singleMedia = false, this.singleMedia = false,
this.sheetController, this.sheetController,
this.heroBuilder, this.heroBuilder,
this.multipleMediasBuilder, this.multipleMediaBuilder,
this.startWithRecent = false}); this.startWithRecent = false});
@override @override
@ -54,8 +57,9 @@ class _GalleryPickerState extends State<GalleryPickerView> {
galleryController = Get.put(PhoneGalleryController(widget.config, galleryController = Get.put(PhoneGalleryController(widget.config,
onSelect: widget.onSelect, onSelect: widget.onSelect,
heroBuilder: widget.heroBuilder, heroBuilder: widget.heroBuilder,
multipleMediasBuilder: widget.multipleMediasBuilder, multipleMediasBuilder: widget.multipleMediaBuilder,
initSelectedMedias: widget.initSelectedMedias, initSelectedMedias: widget.initSelectedMedia,
extraRecentMedia: widget.extraRecentMedia,
isRecent: widget.startWithRecent)); isRecent: widget.startWithRecent));
config = galleryController.config; config = galleryController.config;
} }
@ -83,10 +87,15 @@ class _GalleryPickerState extends State<GalleryPickerView> {
super.dispose(); super.dispose();
} }
GalleryAlbum? selectedAlbum;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width; double width = MediaQuery.of(context).size.width;
return GetBuilder<PhoneGalleryController>(builder: (controller) { return GetBuilder<PhoneGalleryController>(builder: (controller) {
if (controller.selectedAlbum == null && selectedAlbum != null) {
_scrollController = PageController(initialPage: 1);
}
selectedAlbum = controller.selectedAlbum;
return GetInstance().isRegistered<PhoneGalleryController>() return GetInstance().isRegistered<PhoneGalleryController>()
? controller.selectedAlbum == null ? controller.selectedAlbum == null
? Scaffold( ? Scaffold(
@ -208,8 +217,9 @@ class _GalleryPickerState extends State<GalleryPickerView> {
galleryController = Get.put(PhoneGalleryController(config, galleryController = Get.put(PhoneGalleryController(config,
onSelect: widget.onSelect, onSelect: widget.onSelect,
heroBuilder: widget.heroBuilder, heroBuilder: widget.heroBuilder,
initSelectedMedias: widget.initSelectedMedias, initSelectedMedias: widget.initSelectedMedia,
multipleMediasBuilder: widget.multipleMediasBuilder, extraRecentMedia: widget.extraRecentMedia,
multipleMediasBuilder: widget.multipleMediaBuilder,
isRecent: widget.startWithRecent)); isRecent: widget.startWithRecent));
await controller.initializeAlbums(); await controller.initializeAlbums();
if (bottomSheetController != null) { if (bottomSheetController != null) {