diff --git a/lib/db/db_helper.dart b/lib/db/db_helper.dart index d0eae2136..beebf1202 100644 --- a/lib/db/db_helper.dart +++ b/lib/db/db_helper.dart @@ -18,6 +18,7 @@ class DatabaseHelper { static final columnPath = 'path'; static final columnHash = 'hash'; static final columnIsDeleted = 'is_deleted'; + static final columnCreateTimestamp = 'create_timestamp'; static final columnSyncTimestamp = 'sync_timestamp'; // make this a singleton class @@ -52,6 +53,7 @@ class DatabaseHelper { $columnPath TEXT, $columnHash TEXT NOT NULL, $columnIsDeleted INTEGER DEFAULT 0, + $columnCreateTimestamp TEXT NOT NULL, $columnSyncTimestamp TEXT ) '''); @@ -79,13 +81,15 @@ class DatabaseHelper { Future> getAllPhotos() async { Database db = await instance.database; - var results = await db.query(table, where: '$columnIsDeleted = 0'); + var results = await db.query(table, + where: '$columnIsDeleted = 0', orderBy: columnCreateTimestamp); return _convertToPhotos(results); } Future> getAllDeletedPhotos() async { Database db = await instance.database; - var results = await db.query(table, where: '$columnIsDeleted = 1'); + var results = await db.query(table, + where: '$columnIsDeleted = 1', orderBy: columnCreateTimestamp); return _convertToPhotos(results); } @@ -153,6 +157,7 @@ class DatabaseHelper { row[columnThumbnailPath] = photo.thumbnailPath; row[columnPath] = photo.path; row[columnHash] = photo.hash; + row[columnCreateTimestamp] = photo.createTimestamp; row[columnSyncTimestamp] = photo.syncTimestamp; return row; } @@ -165,6 +170,7 @@ class DatabaseHelper { photo.thumbnailPath = row[columnThumbnailPath]; photo.path = row[columnPath]; photo.hash = row[columnHash]; + photo.createTimestamp = int.parse(row[columnCreateTimestamp]); photo.syncTimestamp = row[columnSyncTimestamp] == null ? -1 : int.parse(row[columnSyncTimestamp]); diff --git a/lib/models/photo.dart b/lib/models/photo.dart index 917220094..2956e7fb4 100644 --- a/lib/models/photo.dart +++ b/lib/models/photo.dart @@ -10,6 +10,7 @@ class Photo { String localPath; String thumbnailPath; String hash; + int createTimestamp; int syncTimestamp; Photo(); @@ -19,6 +20,7 @@ class Photo { path = json["path"], hash = json["hash"], thumbnailPath = json["thumbnailPath"], + createTimestamp = json["createTimestamp"], syncTimestamp = json["syncTimestamp"]; static Future fromAsset(AssetEntity asset) async { @@ -29,6 +31,7 @@ class Photo { photo.localPath = file.path; photo.hash = getHash(file); photo.thumbnailPath = file.path; + photo.createTimestamp = asset.createDateTime.microsecondsSinceEpoch; return photo; } diff --git a/lib/photo_sync_manager.dart b/lib/photo_sync_manager.dart index 9999ed6a5..c13a430b9 100644 --- a/lib/photo_sync_manager.dart +++ b/lib/photo_sync_manager.dart @@ -23,8 +23,8 @@ class PhotoSyncManager { PhotoSyncManager(this._assets) { _logger.i("PhotoSyncManager init"); _assets.sort((first, second) => second - .modifiedDateTime.millisecondsSinceEpoch - .compareTo(first.modifiedDateTime.millisecondsSinceEpoch)); + .modifiedDateTime.microsecondsSinceEpoch + .compareTo(first.modifiedDateTime.microsecondsSinceEpoch)); } Future init() async { @@ -46,18 +46,18 @@ class PhotoSyncManager { var bufferLimit = 10; final maxBufferLimit = 1000; for (AssetEntity asset in _assets) { - if (asset.createDateTime.millisecondsSinceEpoch > lastDBUpdateTimestamp) { + if (asset.createDateTime.microsecondsSinceEpoch > lastDBUpdateTimestamp) { photos.add(await Photo.fromAsset(asset)); if (photos.length > bufferLimit) { await _insertPhotosToDB( - photos, prefs, asset.createDateTime.millisecondsSinceEpoch); + photos, prefs, asset.createDateTime.microsecondsSinceEpoch); photos.clear(); bufferLimit = min(maxBufferLimit, bufferLimit * 2); } } } return await _insertPhotosToDB( - photos, prefs, DateTime.now().millisecondsSinceEpoch); + photos, prefs, DateTime.now().microsecondsSinceEpoch); } _syncPhotos() async { @@ -93,16 +93,14 @@ class PhotoSyncManager { _logger.i("External path: " + externalPath); var path = externalPath + "/photos/"; for (Photo photo in diff) { - if (await DatabaseHelper.instance.containsPhotoHash(photo.hash)) { - var localPath = path + basename(photo.path); - await _dio - .download(Constants.ENDPOINT + "/" + photo.path, localPath) - .catchError(_onError); - photo.localPath = localPath; - photo.thumbnailPath = localPath; - await DatabaseHelper.instance.insertPhoto(photo); - PhotoLoader.instance.reloadPhotos(); - } + var localPath = path + basename(photo.path); + await _dio + .download(Constants.ENDPOINT + "/" + photo.path, localPath) + .catchError(_onError); + photo.localPath = localPath; + photo.thumbnailPath = localPath; + await DatabaseHelper.instance.insertPhoto(photo); + PhotoLoader.instance.reloadPhotos(); await prefs.setInt(_lastSyncTimestampKey, photo.syncTimestamp); } } diff --git a/lib/ui/gallery.dart b/lib/ui/gallery.dart index 99d957778..987fdbbec 100644 --- a/lib/ui/gallery.dart +++ b/lib/ui/gallery.dart @@ -1,17 +1,15 @@ import 'dart:io'; +import 'dart:math'; import 'package:draggable_scrollbar/draggable_scrollbar.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:logger/logger.dart'; import 'package:myapp/db/db_helper.dart'; import 'package:myapp/models/photo.dart'; import 'package:myapp/photo_loader.dart'; -import 'package:myapp/photo_sync_manager.dart'; import 'package:myapp/ui/image_widget.dart'; import 'package:provider/provider.dart'; import 'package:share_extend/share_extend.dart'; -import 'package:toast/toast.dart'; import 'change_notifier_builder.dart'; import 'detail_page.dart'; @@ -24,6 +22,21 @@ class Gallery extends StatefulWidget { } class _GalleryState extends State { + Map _months = { + 1: "January", + 2: "February", + 3: "March", + 4: "April", + 5: "May", + 6: "June", + 7: "July", + 8: "August", + 9: "September", + 10: "October", + 11: "November", + 12: "December", + }; + PhotoLoader get photoLoader => Provider.of(context); final ScrollController _scrollController = ScrollController(); @@ -33,7 +46,22 @@ class _GalleryState extends State { value: photoLoader, builder: (_, __) { return DraggableScrollbar.semicircle( - labelTextBuilder: (double offset) => Text("Hello!"), + labelTextBuilder: (double offset) { + int itemIndex = _scrollController.hasClients + ? (_scrollController.offset / + _scrollController.position.maxScrollExtent * + photoLoader.getPhotos().length) + .floor() + : 0; + itemIndex = min(itemIndex, photoLoader.getPhotos().length); + Photo photo = photoLoader.getPhotos()[itemIndex]; + var date = + DateTime.fromMicrosecondsSinceEpoch(photo.createTimestamp); + return Text( + _months[date.month], + style: TextStyle(color: Colors.black), + ); + }, labelConstraints: BoxConstraints.tightFor(width: 80.0, height: 30.0), controller: _scrollController, child: GridView.builder( diff --git a/pubspec.lock b/pubspec.lock index 0c15a8f8a..d37e2b299 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -99,7 +99,7 @@ packages: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.3" + version: "3.1.4" image: dependency: "direct main" description: @@ -113,7 +113,7 @@ packages: name: io url: "https://pub.dartlang.org" source: hosted - version: "0.3.3" + version: "0.3.4" json_annotation: dependency: transitive description: @@ -225,7 +225,7 @@ packages: name: share_extend url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.1.3" shared_preferences: dependency: "direct main" description: