Reduce coupling between gallery and the app bar
This commit is contained in:
parent
9829eb4792
commit
c07a103450
6 changed files with 78 additions and 109 deletions
|
@ -15,13 +15,13 @@ class FileRepository {
|
|||
return _files;
|
||||
}
|
||||
|
||||
Future<bool> loadFiles() async {
|
||||
Future<List<File>> loadFiles() async {
|
||||
var files = await FileDB.instance.getAllLocalFiles();
|
||||
|
||||
_files.clear();
|
||||
_files.addAll(files);
|
||||
|
||||
return true;
|
||||
return _files;
|
||||
}
|
||||
|
||||
Future<void> reloadFiles() async {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/local_photos_updated_event.dart';
|
||||
|
@ -21,33 +19,22 @@ class DeviceFolderPage extends StatefulWidget {
|
|||
|
||||
class _DeviceFolderPageState extends State<DeviceFolderPage> {
|
||||
final logger = Logger("DeviceFolderPageState");
|
||||
Set<File> _selectedFiles = Set<File>();
|
||||
|
||||
@override
|
||||
Widget build(Object context) {
|
||||
var gallery = Gallery(
|
||||
syncLoader: () => _getFilteredFiles(FileRepository.instance.files),
|
||||
reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
||||
tagPrefix: "device_folder",
|
||||
);
|
||||
return Scaffold(
|
||||
appBar: GalleryAppBarWidget(
|
||||
gallery,
|
||||
GalleryAppBarType.local_folder,
|
||||
widget.folder.name,
|
||||
widget.folder.thumbnail.deviceFolder,
|
||||
_selectedFiles,
|
||||
onSelectionClear: () {
|
||||
setState(() {
|
||||
_selectedFiles.clear();
|
||||
});
|
||||
},
|
||||
),
|
||||
body: Gallery(
|
||||
syncLoader: () => _getFilteredFiles(FileRepository.instance.files),
|
||||
selectedFiles: _selectedFiles,
|
||||
onFileSelectionChange: (Set<File> selectedFiles) {
|
||||
setState(() {
|
||||
_selectedFiles = selectedFiles;
|
||||
});
|
||||
},
|
||||
reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
||||
tagPrefix: "device_folder",
|
||||
),
|
||||
body: gallery,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,7 @@ class Gallery extends StatefulWidget {
|
|||
// should have done the job.
|
||||
final Stream<Event> reloadEvent;
|
||||
final Future<void> Function() onRefresh;
|
||||
final Set<File> selectedFiles;
|
||||
final Function(Set<File>) onFileSelectionChange;
|
||||
final fileSelectionChangeListeners = new List<Function(Set<File>)>();
|
||||
final String tagPrefix;
|
||||
|
||||
Gallery({
|
||||
|
@ -30,14 +29,19 @@ class Gallery extends StatefulWidget {
|
|||
this.asyncLoader,
|
||||
this.reloadEvent,
|
||||
this.onRefresh,
|
||||
this.selectedFiles,
|
||||
this.onFileSelectionChange,
|
||||
this.tagPrefix,
|
||||
});
|
||||
|
||||
_GalleryState state;
|
||||
|
||||
@override
|
||||
_GalleryState createState() {
|
||||
return _GalleryState();
|
||||
state = _GalleryState();
|
||||
return state;
|
||||
}
|
||||
|
||||
void clearSelection() {
|
||||
state.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +56,7 @@ class _GalleryState extends State<Gallery> {
|
|||
bool _requiresLoad = false;
|
||||
bool _hasLoadedAll = false;
|
||||
double _scrollOffset = 0;
|
||||
Set<File> _selectedFiles = HashSet<File>();
|
||||
Set<File> _selectedFiles = Set<File>();
|
||||
List<File> _files;
|
||||
RefreshController _refreshController = RefreshController();
|
||||
|
||||
|
@ -69,6 +73,12 @@ class _GalleryState extends State<Gallery> {
|
|||
super.initState();
|
||||
}
|
||||
|
||||
void clearSelection() {
|
||||
setState(() {
|
||||
_selectedFiles = Set<File>();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!_requiresLoad) {
|
||||
|
@ -100,7 +110,6 @@ class _GalleryState extends State<Gallery> {
|
|||
if (_files.isEmpty) {
|
||||
return Center(child: Text("Nothing to see here! 👀"));
|
||||
}
|
||||
_selectedFiles = widget.selectedFiles ?? Set<File>();
|
||||
_collateFiles();
|
||||
_scrollController = ScrollController(
|
||||
initialScrollOffset: _scrollOffset,
|
||||
|
@ -227,7 +236,9 @@ class _GalleryState extends State<Gallery> {
|
|||
} else {
|
||||
_selectedFiles.add(file);
|
||||
}
|
||||
widget.onFileSelectionChange(_selectedFiles);
|
||||
for (final listener in widget.fileSelectionChangeListeners) {
|
||||
listener.call(_selectedFiles);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:photos/db/file_db.dart';
|
|||
import 'package:photos/events/remote_sync_event.dart';
|
||||
import 'package:photos/models/file.dart';
|
||||
import 'package:photos/file_repository.dart';
|
||||
import 'package:photos/ui/gallery.dart';
|
||||
import 'package:photos/ui/setup_page.dart';
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
import 'package:photos/ui/share_folder_widget.dart';
|
||||
|
@ -20,14 +21,17 @@ enum GalleryAppBarType {
|
|||
|
||||
class GalleryAppBarWidget extends StatefulWidget
|
||||
implements PreferredSizeWidget {
|
||||
final Gallery gallery;
|
||||
final GalleryAppBarType type;
|
||||
final String title;
|
||||
final String path;
|
||||
final Set<File> selectedFiles;
|
||||
final Function() onSelectionClear;
|
||||
|
||||
GalleryAppBarWidget(this.type, this.title, this.path, this.selectedFiles,
|
||||
{this.onSelectionClear});
|
||||
GalleryAppBarWidget(
|
||||
this.gallery,
|
||||
this.type,
|
||||
this.title,
|
||||
this.path,
|
||||
);
|
||||
|
||||
@override
|
||||
_GalleryAppBarWidgetState createState() => _GalleryAppBarWidgetState();
|
||||
|
@ -39,6 +43,7 @@ class GalleryAppBarWidget extends StatefulWidget
|
|||
class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
||||
bool _hasSyncErrors = false;
|
||||
StreamSubscription<RemoteSyncEvent> _subscription;
|
||||
Set<File> _selectedFiles = Set<File>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -47,12 +52,18 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
_hasSyncErrors = !event.success;
|
||||
});
|
||||
});
|
||||
if (widget.gallery != null)
|
||||
widget.gallery.fileSelectionChangeListeners.add((selectedFiles) {
|
||||
setState(() {
|
||||
_selectedFiles = selectedFiles;
|
||||
});
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.selectedFiles.isEmpty) {
|
||||
if (_selectedFiles.isEmpty) {
|
||||
return AppBar(
|
||||
title: Text(widget.title),
|
||||
actions: _getDefaultActions(context),
|
||||
|
@ -66,7 +77,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
_clearSelectedFiles();
|
||||
},
|
||||
),
|
||||
title: Text(widget.selectedFiles.length.toString()),
|
||||
title: Text(_selectedFiles.length.toString()),
|
||||
actions: _getActions(context),
|
||||
);
|
||||
}
|
||||
|
@ -105,7 +116,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
|
||||
List<Widget> _getActions(BuildContext context) {
|
||||
List<Widget> actions = List<Widget>();
|
||||
if (widget.selectedFiles.isNotEmpty) {
|
||||
if (_selectedFiles.isNotEmpty) {
|
||||
if (widget.type != GalleryAppBarType.remote_folder) {
|
||||
actions.add(IconButton(
|
||||
icon: Icon(Icons.delete),
|
||||
|
@ -125,7 +136,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
}
|
||||
|
||||
void _shareSelected(BuildContext context) {
|
||||
shareMultiple(context, widget.selectedFiles.toList());
|
||||
shareMultiple(context, _selectedFiles.toList());
|
||||
}
|
||||
|
||||
void _showDeleteSheet(BuildContext context) {
|
||||
|
@ -158,9 +169,9 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
|
||||
Future _deleteSelected(BuildContext context, bool deleteEverywhere) async {
|
||||
await PhotoManager.editor
|
||||
.deleteWithIds(widget.selectedFiles.map((p) => p.localId).toList());
|
||||
.deleteWithIds(_selectedFiles.map((p) => p.localId).toList());
|
||||
|
||||
for (File file in widget.selectedFiles) {
|
||||
for (File file in _selectedFiles) {
|
||||
deleteEverywhere
|
||||
? await FileDB.instance.markForDeletion(file)
|
||||
: await FileDB.instance.delete(file);
|
||||
|
@ -171,12 +182,10 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
}
|
||||
|
||||
void _clearSelectedFiles() {
|
||||
widget.gallery.clearSelection();
|
||||
setState(() {
|
||||
widget.selectedFiles.clear();
|
||||
_selectedFiles.clear();
|
||||
});
|
||||
if (widget.onSelectionClear != null) {
|
||||
widget.onSelectionClear();
|
||||
}
|
||||
}
|
||||
|
||||
void _openSyncConfiguration(BuildContext context) {
|
||||
|
|
|
@ -14,7 +14,6 @@ import 'package:photos/ui/device_folders_gallery_widget.dart';
|
|||
import 'package:photos/ui/gallery.dart';
|
||||
import 'package:photos/ui/gallery_app_bar_widget.dart';
|
||||
import 'package:photos/ui/loading_photos_widget.dart';
|
||||
import 'package:photos/ui/loading_widget.dart';
|
||||
import 'package:photos/ui/remote_folder_gallery_widget.dart';
|
||||
import 'package:photos/ui/search_page.dart';
|
||||
import 'package:photos/utils/logging_util.dart';
|
||||
|
@ -59,33 +58,24 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var gallery = _getMainGalleryWidget();
|
||||
return Scaffold(
|
||||
appBar: GalleryAppBarWidget(
|
||||
gallery,
|
||||
GalleryAppBarType.homepage,
|
||||
widget.title,
|
||||
"/",
|
||||
_selectedPhotos,
|
||||
onSelectionClear: _clearSelectedPhotos,
|
||||
),
|
||||
bottomNavigationBar: _buildBottomNavigationBar(),
|
||||
body: FutureBuilder<bool>(
|
||||
future: PhotoSyncManager.instance.hasScannedDisk(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return IndexedStack(
|
||||
children: <Widget>[
|
||||
snapshot.data ? _getMainGalleryWidget() : LoadingPhotosWidget(),
|
||||
_deviceFolderGalleryWidget,
|
||||
_remoteFolderGalleryWidget,
|
||||
],
|
||||
index: _selectedNavBarItem,
|
||||
);
|
||||
} else if (snapshot.hasError) {
|
||||
return Center(child: Text(snapshot.error.toString()));
|
||||
} else {
|
||||
return loadWidget;
|
||||
}
|
||||
},
|
||||
body: IndexedStack(
|
||||
children: <Widget>[
|
||||
PhotoSyncManager.instance.hasScannedDisk()
|
||||
? gallery
|
||||
: LoadingPhotosWidget(),
|
||||
_deviceFolderGalleryWidget,
|
||||
_remoteFolderGalleryWidget,
|
||||
],
|
||||
index: _selectedNavBarItem,
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
|
@ -109,28 +99,15 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|||
}
|
||||
|
||||
Widget _getMainGalleryWidget() {
|
||||
return FutureBuilder<bool>(
|
||||
future: FileRepository.instance.loadFiles(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Gallery(
|
||||
syncLoader: () => _getFilteredPhotos(FileRepository.instance.files),
|
||||
reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
||||
onRefresh: PhotoSyncManager.instance.sync,
|
||||
selectedFiles: _selectedPhotos,
|
||||
onFileSelectionChange: (Set<File> selectedPhotos) {
|
||||
setState(() {
|
||||
_selectedPhotos = selectedPhotos;
|
||||
});
|
||||
},
|
||||
tagPrefix: "home_gallery",
|
||||
);
|
||||
} else if (snapshot.hasError) {
|
||||
return Center(child: Text(snapshot.error.toString()));
|
||||
} else {
|
||||
return loadWidget;
|
||||
}
|
||||
return Gallery(
|
||||
asyncLoader: (_, __) {
|
||||
return FileRepository.instance.loadFiles().then((files) {
|
||||
return _getFilteredPhotos(files);
|
||||
});
|
||||
},
|
||||
reloadEvent: Bus.instance.on<LocalPhotosUpdatedEvent>(),
|
||||
onRefresh: PhotoSyncManager.instance.sync,
|
||||
tagPrefix: "home_gallery",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:photos/db/file_db.dart';
|
||||
import 'package:photos/folder_service.dart';
|
||||
import 'package:photos/models/folder.dart';
|
||||
import 'package:photos/models/file.dart';
|
||||
import 'package:photos/ui/gallery.dart';
|
||||
import 'package:photos/ui/gallery_app_bar_widget.dart';
|
||||
|
||||
|
@ -16,36 +15,22 @@ class RemoteFolderPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _RemoteFolderPageState extends State<RemoteFolderPage> {
|
||||
Set<File> _selectedPhotos = Set<File>();
|
||||
|
||||
@override
|
||||
Widget build(Object context) {
|
||||
var gallery = Gallery(
|
||||
asyncLoader: (offset, limit) =>
|
||||
FileDB.instance.getAllInFolder(widget.folder.id, offset, limit),
|
||||
onRefresh: () => FolderSharingService.instance.syncDiff(widget.folder),
|
||||
tagPrefix: "remote_folder",
|
||||
);
|
||||
return Scaffold(
|
||||
appBar: GalleryAppBarWidget(
|
||||
gallery,
|
||||
GalleryAppBarType.remote_folder,
|
||||
widget.folder.name,
|
||||
widget.folder.deviceFolder,
|
||||
_selectedPhotos,
|
||||
onSelectionClear: () {
|
||||
setState(() {
|
||||
_selectedPhotos.clear();
|
||||
});
|
||||
},
|
||||
),
|
||||
body: Gallery(
|
||||
asyncLoader: (offset, limit) =>
|
||||
FileDB.instance.getAllInFolder(widget.folder.id, offset, limit),
|
||||
onRefresh: () => FolderSharingService.instance.syncDiff(widget.folder),
|
||||
selectedFiles: _selectedPhotos,
|
||||
onFileSelectionChange: (Set<File> selectedPhotos) {
|
||||
setState(
|
||||
() {
|
||||
_selectedPhotos = selectedPhotos;
|
||||
},
|
||||
);
|
||||
},
|
||||
tagPrefix: "remote_folder",
|
||||
),
|
||||
body: gallery,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue