Show a sync status indicator on top
This commit is contained in:
parent
42496a13ba
commit
c6678cd735
4 changed files with 63 additions and 75 deletions
|
@ -1,10 +1,12 @@
|
|||
class PhotoUploadEvent {
|
||||
import 'package:photos/events/event.dart';
|
||||
|
||||
class SyncStatusUpdate extends Event {
|
||||
final int completed;
|
||||
final int total;
|
||||
final bool hasError;
|
||||
final bool wasStopped;
|
||||
|
||||
PhotoUploadEvent({
|
||||
SyncStatusUpdate({
|
||||
this.completed,
|
||||
this.total,
|
||||
this.hasError = false,
|
||||
|
|
|
@ -64,6 +64,7 @@ class SyncService {
|
|||
_logger.severe(e, s);
|
||||
} finally {
|
||||
_isSyncInProgress = false;
|
||||
Bus.instance.fire(SyncStatusUpdate(hasError: true));
|
||||
}
|
||||
});
|
||||
return _existingSync;
|
||||
|
@ -82,6 +83,10 @@ class SyncService {
|
|||
return _prefs.containsKey(_dbUpdationTimeKey);
|
||||
}
|
||||
|
||||
bool isSyncInProgress() {
|
||||
return _isSyncInProgress;
|
||||
}
|
||||
|
||||
Future<void> _doSync() async {
|
||||
final result = await PhotoManager.requestPermission();
|
||||
if (!result) {
|
||||
|
@ -169,19 +174,19 @@ class SyncService {
|
|||
final foldersToBackUp = Configuration.instance.getPathsToBackUp();
|
||||
List<File> filesToBeUploaded =
|
||||
await _db.getFilesToBeUploadedWithinFolders(foldersToBackUp);
|
||||
if (kDebugMode) {
|
||||
filesToBeUploaded = filesToBeUploaded
|
||||
.where((element) => element.fileType != FileType.video)
|
||||
.toList();
|
||||
}
|
||||
final futures = List<Future>();
|
||||
for (int i = 0; i < filesToBeUploaded.length; i++) {
|
||||
if (_syncStopRequested) {
|
||||
_syncStopRequested = false;
|
||||
Bus.instance.fire(PhotoUploadEvent(wasStopped: true));
|
||||
Bus.instance.fire(SyncStatusUpdate(wasStopped: true));
|
||||
return;
|
||||
}
|
||||
File file = filesToBeUploaded[i];
|
||||
if (kDebugMode) {
|
||||
if (file.fileType == FileType.video) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final collectionID = (await CollectionsService.instance
|
||||
.getOrCreateForPath(file.deviceFolder))
|
||||
|
@ -189,19 +194,20 @@ class SyncService {
|
|||
final future = _uploader.upload(file, collectionID).then((value) {
|
||||
Bus.instance
|
||||
.fire(CollectionUpdatedEvent(collectionID: file.collectionID));
|
||||
Bus.instance.fire(PhotoUploadEvent(
|
||||
Bus.instance.fire(SyncStatusUpdate(
|
||||
completed: i + 1, total: filesToBeUploaded.length));
|
||||
});
|
||||
futures.add(future);
|
||||
} catch (e, s) {
|
||||
Bus.instance.fire(PhotoUploadEvent(hasError: true));
|
||||
Bus.instance.fire(SyncStatusUpdate(hasError: true));
|
||||
_logger.severe(e, s);
|
||||
}
|
||||
}
|
||||
try {
|
||||
await Future.wait(futures);
|
||||
} catch (e, s) {
|
||||
Bus.instance.fire(PhotoUploadEvent(hasError: true));
|
||||
_isSyncInProgress = false;
|
||||
Bus.instance.fire(SyncStatusUpdate(hasError: true));
|
||||
_logger.severe("Error in syncing files", e, s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import 'package:photos/services/user_service.dart';
|
|||
import 'package:photos/ui/shared_collections_gallery.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:photos/ui/sign_in_header_widget.dart';
|
||||
import 'package:photos/ui/sync_indicator.dart';
|
||||
import 'package:uni_links/uni_links.dart';
|
||||
|
||||
class HomeWidget extends StatefulWidget {
|
||||
|
@ -43,6 +44,7 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|||
final _selectedFiles = SelectedFiles();
|
||||
final _memoriesWidget = MemoriesWidget();
|
||||
final _signInHeader = SignInHeader();
|
||||
final _syncIndicator = SyncIndicator();
|
||||
final PageController _pageController = PageController();
|
||||
|
||||
GlobalKey<ConvexAppBarState> _appBarKey = GlobalKey<ConvexAppBarState>();
|
||||
|
@ -153,6 +155,7 @@ class _HomeWidgetState extends State<HomeWidget> {
|
|||
selectedFiles: _selectedFiles,
|
||||
headerWidget: Column(
|
||||
children: [
|
||||
_syncIndicator,
|
||||
_signInHeader,
|
||||
_memoriesWidget,
|
||||
],
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/photo_upload_event.dart';
|
||||
import 'package:photos/services/sync_service.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
class SyncIndicator extends StatefulWidget {
|
||||
final RefreshController refreshController;
|
||||
|
||||
const SyncIndicator(this.refreshController, {Key key}) : super(key: key);
|
||||
const SyncIndicator({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SyncIndicatorState createState() => _SyncIndicatorState();
|
||||
}
|
||||
|
||||
class _SyncIndicatorState extends State<SyncIndicator> {
|
||||
PhotoUploadEvent _event;
|
||||
StreamSubscription<PhotoUploadEvent> _subscription;
|
||||
String _completeText = "Sync completed.";
|
||||
SyncStatusUpdate _event;
|
||||
int _latestCompletedCount = 0;
|
||||
StreamSubscription<SyncStatusUpdate> _subscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_subscription = Bus.instance.on<PhotoUploadEvent>().listen((event) {
|
||||
_subscription = Bus.instance.on<SyncStatusUpdate>().listen((event) {
|
||||
setState(() {
|
||||
_event = event;
|
||||
if (!_event.hasError && _event.completed > _latestCompletedCount) {
|
||||
_latestCompletedCount = _event.completed;
|
||||
}
|
||||
});
|
||||
});
|
||||
super.initState();
|
||||
|
@ -39,63 +39,40 @@ class _SyncIndicatorState extends State<SyncIndicator> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ClassicHeader(
|
||||
idleText: "Pull down to sync.",
|
||||
refreshingText: _getRefreshingText(),
|
||||
releaseText: "Release to sync.",
|
||||
completeText: _completeText,
|
||||
failedText: "Sync unsuccessful.",
|
||||
completeDuration: const Duration(milliseconds: 1000),
|
||||
refreshStyle: RefreshStyle.UnFollow,
|
||||
refreshingIcon: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text("Pause?"),
|
||||
content: Text(
|
||||
"Are you sure that you want to pause backing up your memories?"),
|
||||
actions: [
|
||||
FlatButton(
|
||||
child: Text("NO"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
FlatButton(
|
||||
child: Text("YES"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
SyncService.instance.stopSync();
|
||||
_completeText = "Sync stopped.";
|
||||
setState(() {});
|
||||
widget.refreshController.refreshCompleted();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return alert;
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Stack(
|
||||
if (Configuration.instance.hasConfiguredAccount()) {
|
||||
if (SyncService.instance.isSyncInProgress()) {
|
||||
return Container(
|
||||
height: 48,
|
||||
width: double.infinity,
|
||||
margin: EdgeInsets.all(8),
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.pause_circle_outline,
|
||||
size: 24,
|
||||
color: Colors.pink,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 4, 0, 0),
|
||||
child: Text(_getRefreshingText()),
|
||||
),
|
||||
],
|
||||
),
|
||||
CircularProgressIndicator(strokeWidth: 2),
|
||||
Padding(padding: EdgeInsets.all(4)),
|
||||
Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
return Container();
|
||||
}
|
||||
|
||||
String _getRefreshingText() {
|
||||
|
@ -103,13 +80,13 @@ class _SyncIndicatorState extends State<SyncIndicator> {
|
|||
return "Syncing...";
|
||||
} else {
|
||||
var s;
|
||||
// TODO: Display errors softly
|
||||
if (_event.hasError) {
|
||||
widget.refreshController.refreshFailed();
|
||||
s = "Upload failed.";
|
||||
} else if (_event.wasStopped) {
|
||||
s = "Sync stopped.";
|
||||
} else {
|
||||
s = _event.completed.toString() +
|
||||
s = _latestCompletedCount.toString() +
|
||||
"/" +
|
||||
_event.total.toString() +
|
||||
" memories preserved";
|
||||
|
|
Loading…
Add table
Reference in a new issue