Update interactions
This commit is contained in:
parent
4ce04f98be
commit
81882999c1
8 changed files with 92 additions and 43 deletions
|
@ -1,5 +1,4 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ class DatabaseHelper {
|
|||
static final table = 'photos';
|
||||
|
||||
static final columnLocalPath = 'local_path';
|
||||
static final columnThumbnailPath = 'thumbnail_path';
|
||||
static final columnUrl = 'url';
|
||||
static final columnHash = 'hash';
|
||||
static final columnSyncTimestamp = 'sync_timestamp';
|
||||
|
@ -42,6 +43,7 @@ class DatabaseHelper {
|
|||
await db.execute('''
|
||||
CREATE TABLE $table (
|
||||
$columnLocalPath TEXT NOT NULL,
|
||||
$columnThumbnailPath TEXT NOT NULL,
|
||||
$columnUrl TEXT,
|
||||
$columnHash TEXT NOT NULL,
|
||||
$columnSyncTimestamp TEXT
|
||||
|
@ -53,6 +55,7 @@ class DatabaseHelper {
|
|||
Database db = await instance.database;
|
||||
var row = new Map<String, dynamic>();
|
||||
row[columnLocalPath] = photo.localPath;
|
||||
row[columnThumbnailPath] = photo.thumbnailPath;
|
||||
row[columnUrl] = photo.url;
|
||||
row[columnHash] = photo.hash;
|
||||
row[columnSyncTimestamp] = photo.syncTimestamp;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:image/image.dart';
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
|
||||
class Photo {
|
||||
String url;
|
||||
String localPath;
|
||||
String thumbnailPath;
|
||||
String hash;
|
||||
int syncTimestamp;
|
||||
|
||||
|
@ -18,6 +20,7 @@ class Photo {
|
|||
|
||||
Photo.fromRow(Map<String, dynamic> row)
|
||||
: localPath = row["local_path"],
|
||||
thumbnailPath = row["thumbnail_path"],
|
||||
url = row["url"],
|
||||
hash = row["hash"],
|
||||
syncTimestamp = row["sync_timestamp"] == null
|
||||
|
@ -28,6 +31,7 @@ class Photo {
|
|||
Photo photo = Photo();
|
||||
var file = (await asset.originFile);
|
||||
photo.localPath = file.path;
|
||||
photo.thumbnailPath = getThumbnailPath(file.path);
|
||||
photo.hash = getHash(file);
|
||||
return photo;
|
||||
}
|
||||
|
@ -35,4 +39,12 @@ class Photo {
|
|||
static String getHash(File file) {
|
||||
return sha256.convert(file.readAsBytesSync()).toString();
|
||||
}
|
||||
|
||||
static String getThumbnailPath(String path) {
|
||||
Image image = decodeImage(File(path).readAsBytesSync());
|
||||
Image thumbnail = copyResize(image, width: 150);
|
||||
String thumbnailPath = path + ".thumbnail";
|
||||
File(thumbnailPath)..writeAsBytesSync(encodePng(thumbnail));
|
||||
return thumbnailPath;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,11 +39,17 @@ class PhotoSyncManager {
|
|||
if (lastDBUpdateTimestamp == null) {
|
||||
lastDBUpdateTimestamp = 0;
|
||||
}
|
||||
for (AssetEntity asset in _assets) {
|
||||
if (asset.createDateTime.millisecondsSinceEpoch > lastDBUpdateTimestamp) {
|
||||
await insertPhotoToDB(await Photo.fromAsset(asset));
|
||||
}
|
||||
}
|
||||
// for (AssetEntity asset in _assets) {
|
||||
// if (asset.createDateTime.millisecondsSinceEpoch > lastDBUpdateTimestamp) {
|
||||
// try {
|
||||
// var photo = await Photo.fromAsset(asset);
|
||||
// await DatabaseHelper.instance.insertPhoto(photo);
|
||||
// } catch (e) {
|
||||
// _logger.e(e);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
PhotoLoader.instance.reloadPhotos();
|
||||
return await prefs.setInt(
|
||||
_lastDBUpdateTimestampKey, DateTime.now().millisecondsSinceEpoch);
|
||||
}
|
||||
|
@ -98,7 +104,9 @@ class PhotoSyncManager {
|
|||
.download(_endpoint + photo.url, localPath)
|
||||
.catchError(_onError);
|
||||
photo.localPath = localPath;
|
||||
await insertPhotoToDB(photo);
|
||||
photo.thumbnailPath = Photo.getThumbnailPath(localPath);
|
||||
await DatabaseHelper.instance.insertPhoto(photo);
|
||||
PhotoLoader.instance.reloadPhotos();
|
||||
}
|
||||
await prefs.setInt(_lastSyncTimestampKey, photo.syncTimestamp);
|
||||
}
|
||||
|
@ -131,12 +139,6 @@ class PhotoSyncManager {
|
|||
return photo;
|
||||
}
|
||||
|
||||
Future<void> insertPhotoToDB(Photo photo) async {
|
||||
_logger.i("Inserting to DB");
|
||||
await DatabaseHelper.instance.insertPhoto(photo);
|
||||
PhotoLoader.instance.reloadPhotos();
|
||||
}
|
||||
|
||||
void _onError(error) {
|
||||
_logger.e(error);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import 'package:myapp/photo_loader.dart';
|
||||
import 'package:myapp/ui/image_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
|
||||
import 'change_notifier_builder.dart';
|
||||
import 'detail_page.dart';
|
||||
|
@ -18,44 +20,67 @@ class Gallery extends StatefulWidget {
|
|||
|
||||
class _GalleryState extends State<Gallery> {
|
||||
Logger _logger = Logger();
|
||||
|
||||
|
||||
int _crossAxisCount = 4;
|
||||
|
||||
PhotoLoader get photoLoader => Provider.of<PhotoLoader>(context);
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.i("Build");
|
||||
return ChangeNotifierBuilder(
|
||||
value: photoLoader,
|
||||
builder: (_, __) {
|
||||
return GridView.builder(
|
||||
itemBuilder: _buildItem,
|
||||
itemCount: photoLoader.getPhotos().length,
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildItem(BuildContext context, int index) {
|
||||
var file = File(photoLoader.getPhotos()[index].localPath);
|
||||
_logger.i("Build with _crossAxisCount: " + _crossAxisCount.toString());
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
routeToDetailPage(file, context);
|
||||
onScaleUpdate: (ScaleUpdateDetails details) {
|
||||
_logger.i("Scale update: " + details.horizontalScale.toString());
|
||||
setState(() {
|
||||
if (details.horizontalScale < 1) {
|
||||
_crossAxisCount = 8;
|
||||
} else if (details.horizontalScale < 2) {
|
||||
_crossAxisCount = 5;
|
||||
} else if (details.horizontalScale < 4) {
|
||||
_crossAxisCount = 4;
|
||||
} else if (details.horizontalScale < 8) {
|
||||
_crossAxisCount = 2;
|
||||
} else {
|
||||
_crossAxisCount = 1;
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Hero(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(1.0),
|
||||
child: ImageWidget(path: file.path),
|
||||
),
|
||||
tag: 'photo_' + file.path,
|
||||
child: ChangeNotifierBuilder(
|
||||
value: photoLoader,
|
||||
builder: (_, __) {
|
||||
return GridView.builder(
|
||||
itemBuilder: _buildItem,
|
||||
itemCount: photoLoader.getPhotos().length,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: _crossAxisCount,
|
||||
));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void routeToDetailPage(File file, BuildContext context) async {
|
||||
Widget _buildItem(BuildContext context, int index) {
|
||||
var photo = photoLoader.getPhotos()[index];
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
routeToDetailPage(photo.localPath, context);
|
||||
},
|
||||
onLongPress: () {
|
||||
Toast.show(photo.thumbnailPath, context);
|
||||
},
|
||||
child: Hero(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(1.0),
|
||||
child: ImageWidget(path: photo.thumbnailPath),
|
||||
),
|
||||
tag: 'photo_' + photo.localPath,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void routeToDetailPage(String path, BuildContext context) async {
|
||||
final page = DetailPage(
|
||||
file: file,
|
||||
file: File(path),
|
||||
);
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
|
|
|
@ -31,7 +31,6 @@ class _ImageWidgetState extends State<ImageWidget> {
|
|||
Widget image;
|
||||
|
||||
if (cachedImage != null) {
|
||||
_logger.i("Cache hit for " + path);
|
||||
image = cachedImage;
|
||||
} else {
|
||||
image = FutureBuilder<Image>(
|
||||
|
|
|
@ -94,7 +94,7 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.3"
|
||||
image:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image
|
||||
url: "https://pub.dartlang.org"
|
||||
|
@ -315,6 +315,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.11"
|
||||
toast:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: toast
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.5"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -32,6 +32,8 @@ dependencies:
|
|||
dio: ^3.0.9
|
||||
local_image_provider: ^1.0.0
|
||||
crypto: ^2.1.3
|
||||
toast: ^0.1.5
|
||||
image: ^2.1.4
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in a new issue