Vishnu Mohandas преди 5 години
родител
ревизия
6a73208b00
променени са 6 файла, в които са добавени 106 реда и са изтрити 31 реда
  1. 2 2
      lib/db/db_helper.dart
  2. 1 1
      lib/main.dart
  3. 41 5
      lib/photo_loader.dart
  4. 6 6
      lib/photo_sync_manager.dart
  5. 56 13
      lib/ui/gallery.dart
  6. 0 4
      lib/ui/image_widget.dart

+ 2 - 2
lib/db/db_helper.dart

@@ -82,14 +82,14 @@ class DatabaseHelper {
   Future<List<Photo>> getAllPhotos() async {
     Database db = await instance.database;
     var results = await db.query(table,
-        where: '$columnIsDeleted = 0', orderBy: columnCreateTimestamp);
+        where: '$columnIsDeleted = 0', orderBy: '$columnCreateTimestamp DESC');
     return _convertToPhotos(results);
   }
 
   Future<List<Photo>> getAllDeletedPhotos() async {
     Database db = await instance.database;
     var results = await db.query(table,
-        where: '$columnIsDeleted = 1', orderBy: columnCreateTimestamp);
+        where: '$columnIsDeleted = 1', orderBy: '$columnCreateTimestamp DESC');
     return _convertToPhotos(results);
   }
 

+ 1 - 1
lib/main.dart

@@ -40,7 +40,7 @@ class MyApp extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     final title = 'Orma';
-    return FutureBuilder<List<Photo>>(
+    return FutureBuilder<bool>(
         future: photoLoader.loadPhotos(),
         builder: (context, snapshot) {
           Widget body;

+ 41 - 5
lib/photo_loader.dart

@@ -6,21 +6,47 @@ import 'package:myapp/models/photo.dart';
 class PhotoLoader extends ChangeNotifier {
   final logger = Logger();
   final _photos = List<Photo>();
-  
+  final _collatedPhotos = List<List<Photo>>();
+
   PhotoLoader._privateConstructor();
   static final PhotoLoader instance = PhotoLoader._privateConstructor();
 
-  List<Photo> getPhotos() {
+  List<Photo> get photos {
     return _photos;
   }
 
-  Future<List<Photo>> loadPhotos() async {
+  List<List<Photo>> get collatedPhotos {
+    return _collatedPhotos;
+  }
+
+  Future<bool> loadPhotos() async {
     DatabaseHelper db = DatabaseHelper.instance;
     var photos = await db.getAllPhotos();
+
     _photos.clear();
     _photos.addAll(photos);
+
+    final dailyPhotos = List<Photo>();
+    final collatedPhotos = List<List<Photo>>();
+    for (int index = 0; index < photos.length; index++) {
+      if (index > 0 &&
+          !_arePhotosFromSameDay(photos[index], photos[index - 1])) {
+        var collatedDailyPhotos = List<Photo>();
+        collatedDailyPhotos.addAll(dailyPhotos);
+        collatedPhotos.add(collatedDailyPhotos);
+        dailyPhotos.clear();
+      }
+      dailyPhotos.add(photos[index]);
+    }
+    if (dailyPhotos.isNotEmpty) {
+      collatedPhotos.add(dailyPhotos);
+    }
+    _collatedPhotos.clear();
+    _collatedPhotos.addAll(collatedPhotos);
+
     logger.i("Imported photo size: " + _photos.length.toString());
-    return _photos;
+
+    return true;
   }
 
   void reloadPhotos() async {
@@ -28,4 +54,14 @@ class PhotoLoader extends ChangeNotifier {
     logger.i("Reloading...");
     notifyListeners();
   }
-}
+
+  bool _arePhotosFromSameDay(Photo firstPhoto, Photo secondPhoto) {
+    var firstDate =
+        DateTime.fromMicrosecondsSinceEpoch(firstPhoto.createTimestamp);
+    var secondDate =
+        DateTime.fromMicrosecondsSinceEpoch(secondPhoto.createTimestamp);
+    return firstDate.year == secondDate.year &&
+        firstDate.month == secondDate.month &&
+        firstDate.day == secondDate.day;
+  }
+}

+ 6 - 6
lib/photo_sync_manager.dart

@@ -83,6 +83,9 @@ class PhotoSyncManager {
         await DatabaseHelper.instance.getPhotosToBeUploaded();
     for (Photo photo in photosToBeUploaded) {
       var uploadedPhoto = await _uploadFile(photo);
+      if (uploadedPhoto == null) {
+        return;
+      }
       await DatabaseHelper.instance.updatePhoto(uploadedPhoto);
       prefs.setInt(_lastSyncTimestampKey, uploadedPhoto.syncTimestamp);
     }
@@ -127,18 +130,15 @@ class PhotoSyncManager {
           filename: basename(localPhoto.localPath)),
       "user": Constants.USER,
     });
-    var response = await _dio
+    return _dio
         .post(Constants.ENDPOINT + "/upload", data: formData)
-        .catchError(_onError);
-    if (response != null) {
+        .then((response) {
       _logger.i(response.toString());
       var photo = Photo.fromJson(response.data);
       photo.localPath = localPhoto.localPath;
       photo.localId = localPhoto.localId;
       return photo;
-    } else {
-      return null;
-    }
+    }).catchError(_onError);
   }
 
   Future<void> _deletePhotos() async {

+ 56 - 13
lib/ui/gallery.dart

@@ -4,6 +4,7 @@ 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';
@@ -37,6 +38,16 @@ class _GalleryState extends State<Gallery> {
     12: "December",
   };
 
+  Map<int, String> _days = {
+    1: "Monday",
+    2: "Tuesday",
+    3: "Wednesday",
+    4: "Thursday",
+    5: "Friday",
+    6: "Saturday",
+    7: "Sunday",
+  };
+
   PhotoLoader get photoLoader => Provider.of<PhotoLoader>(context);
   final ScrollController _scrollController = ScrollController();
 
@@ -50,13 +61,13 @@ class _GalleryState extends State<Gallery> {
             int itemIndex = _scrollController.hasClients
                 ? (_scrollController.offset /
                         _scrollController.position.maxScrollExtent *
-                        photoLoader.getPhotos().length)
+                        photoLoader.collatedPhotos.length)
                     .floor()
                 : 0;
-            itemIndex = min(itemIndex, photoLoader.getPhotos().length);
-            Photo photo = photoLoader.getPhotos()[itemIndex];
+            itemIndex = min(itemIndex, photoLoader.collatedPhotos.length);
+            var photos = photoLoader.collatedPhotos[itemIndex];
             var date =
-                DateTime.fromMicrosecondsSinceEpoch(photo.createTimestamp);
+                DateTime.fromMicrosecondsSinceEpoch(photos[0].createTimestamp);
             return Text(
               _months[date.month],
               style: TextStyle(color: Colors.black),
@@ -64,20 +75,52 @@ class _GalleryState extends State<Gallery> {
           },
           labelConstraints: BoxConstraints.tightFor(width: 80.0, height: 30.0),
           controller: _scrollController,
-          child: GridView.builder(
-              itemBuilder: _buildItem,
-              itemCount: photoLoader.getPhotos().length,
-              controller: _scrollController,
-              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
-                crossAxisCount: 4,
-              )),
+          child: ListView.builder(
+            itemCount: photoLoader.collatedPhotos.length,
+            itemBuilder: _buildListItem,
+            controller: _scrollController,
+          ),
         );
       },
     );
   }
 
-  Widget _buildItem(BuildContext context, int index) {
-    var photo = photoLoader.getPhotos()[index];
+  Widget _buildListItem(BuildContext context, int index) {
+    var photos = photoLoader.collatedPhotos[index];
+    return Column(
+      children: <Widget>[_getDay(photos), _getGallery(photos)],
+    );
+  }
+
+  Widget _getDay(List<Photo> photos) {
+    var date = DateTime.fromMicrosecondsSinceEpoch(photos[0].createTimestamp);
+    return Container(
+      padding: const EdgeInsets.all(4.0),
+      alignment: Alignment.centerLeft,
+      child: Text(_days[date.weekday] +
+          ", " +
+          _months[date.month] +
+          " " +
+          date.day.toString()),
+    );
+  }
+
+  Widget _getGallery(List<Photo> photos) {
+    return GridView.builder(
+      shrinkWrap: true,
+      padding: EdgeInsets.only(bottom: 12),
+      physics: ScrollPhysics(), // to disable GridView's scrolling
+      itemBuilder: (context, index) {
+        return _buildPhoto(context, photos[index]);
+      },
+      itemCount: photos.length,
+      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
+        crossAxisCount: 4,
+      ),
+    );
+  }
+
+  Widget _buildPhoto(BuildContext context, Photo photo) {
     return GestureDetector(
       onTap: () {
         routeToDetailPage(photo, context);

+ 0 - 4
lib/ui/image_widget.dart

@@ -4,9 +4,7 @@ import 'dart:typed_data';
 import 'package:flutter/material.dart';
 import 'package:myapp/core/lru_map.dart';
 import 'package:myapp/models/photo.dart';
-import 'package:myapp/photo_loader.dart';
 import 'package:photo_manager/photo_manager.dart';
-import 'package:provider/provider.dart';
 
 class ImageWidget extends StatefulWidget {
   final Photo photo;
@@ -20,8 +18,6 @@ class ImageWidget extends StatefulWidget {
 }
 
 class _ImageWidgetState extends State<ImageWidget> {
-  PhotoLoader get photoLoader => Provider.of<PhotoLoader>(context);
-
   @override
   Widget build(BuildContext context) {
     final path = widget.photo.localPath;