Fetch and store shared collections

This commit is contained in:
Vishnu Mohandas 2020-10-14 01:42:37 +05:30
parent fcc172f733
commit 0af41fd97b
3 changed files with 202 additions and 8 deletions

View file

@ -3,13 +3,15 @@ import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:photos/models/collection.dart';
import 'package:photos/models/shared_collection.dart';
import 'package:sqflite/sqflite.dart';
class CollectionsDB {
static final _databaseName = "ente.collections.db";
static final _databaseVersion = 1;
static final table = 'collections';
static final collectionsTable = 'collections';
static final sharedCollectionsTable = 'shared_collections';
static final columnID = 'collection_id';
static final columnOwnerID = 'owner_id';
@ -43,7 +45,7 @@ class CollectionsDB {
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
CREATE TABLE $collectionsTable (
$columnID INTEGER PRIMARY KEY NOT NULL,
$columnOwnerID INTEGER NOT NULL,
$columnEncryptedKey TEXT NOT NULL,
@ -55,21 +57,43 @@ class CollectionsDB {
$columnCreationTime TEXT NOT NULL
)
''');
await db.execute('''
CREATE TABLE $sharedCollectionsTable (
$columnID INTEGER PRIMARY KEY NOT NULL,
$columnOwnerID INTEGER NOT NULL,
$columnEncryptedKey TEXT NOT NULL,
$columnName TEXT NOT NULL,
$columnType TEXT NOT NULL,
$columnCreationTime TEXT NOT NULL
)
''');
}
Future<List<dynamic>> insert(List<Collection> collections) async {
final db = await instance.database;
var batch = db.batch();
for (final collection in collections) {
batch.insert(table, _getRowForCollection(collection),
batch.insert(collectionsTable, _getRowForCollection(collection),
conflictAlgorithm: ConflictAlgorithm.replace);
}
return await batch.commit();
}
Future<List<Collection>> getAll() async {
Future<List<dynamic>> insertSharedCollections(
List<SharedCollection> collections) async {
final db = await instance.database;
final rows = await db.query(table);
var batch = db.batch();
for (final collection in collections) {
batch.insert(collectionsTable, _getRowForSharedCollection(collection),
conflictAlgorithm: ConflictAlgorithm.replace);
}
return await batch.commit();
}
Future<List<Collection>> getAllCollections() async {
final db = await instance.database;
final rows = await db.query(collectionsTable);
final collections = List<Collection>();
for (final row in rows) {
collections.add(_convertToCollection(row));
@ -77,10 +101,34 @@ class CollectionsDB {
return collections;
}
Future<List<SharedCollection>> getAllSharedCollections() async {
final db = await instance.database;
final rows = await db.query(collectionsTable);
final collections = List<SharedCollection>();
for (final row in rows) {
collections.add(_convertToSharedCollection(row));
}
return collections;
}
Future<int> getLastCollectionCreationTime() async {
final db = await instance.database;
final rows = await db.query(
table,
collectionsTable,
orderBy: '$columnCreationTime DESC',
limit: 1,
);
if (rows.isNotEmpty) {
return int.parse(rows[0][columnCreationTime]);
} else {
return null;
}
}
Future<int> getLastSharedCollectionCreationTime() async {
final db = await instance.database;
final rows = await db.query(
sharedCollectionsTable,
orderBy: '$columnCreationTime DESC',
limit: 1,
);
@ -118,4 +166,26 @@ class CollectionsDB {
int.parse(row[columnCreationTime]),
);
}
Map<String, dynamic> _getRowForSharedCollection(SharedCollection collection) {
var row = new Map<String, dynamic>();
row[columnID] = collection.id;
row[columnOwnerID] = collection.ownerID;
row[columnEncryptedKey] = collection.encryptedKey;
row[columnName] = collection.name;
row[columnType] = Collection.typeToString(collection.type);
row[columnCreationTime] = collection.creationTime;
return row;
}
SharedCollection _convertToSharedCollection(Map<String, dynamic> row) {
return SharedCollection(
row[columnID],
row[columnOwnerID],
row[columnEncryptedKey],
row[columnName],
Collection.typeFromString(row[columnType]),
int.parse(row[columnCreationTime]),
);
}
}

View file

@ -0,0 +1,96 @@
import 'dart:convert';
import 'package:photos/models/collection.dart';
class SharedCollection {
final int id;
final int ownerID;
final String encryptedKey;
final String name;
final CollectionType type;
final int creationTime;
SharedCollection(
this.id,
this.ownerID,
this.encryptedKey,
this.name,
this.type,
this.creationTime,
);
SharedCollection copyWith({
int id,
int ownerID,
String encryptedKey,
String name,
CollectionType type,
int creationTime,
}) {
return SharedCollection(
id ?? this.id,
ownerID ?? this.ownerID,
encryptedKey ?? this.encryptedKey,
name ?? this.name,
type ?? this.type,
creationTime ?? this.creationTime,
);
}
Map<String, dynamic> toMap() {
return {
'id': id,
'ownerID': ownerID,
'encryptedKey': encryptedKey,
'name': name,
'type': Collection.typeToString(type),
'creationTime': creationTime,
};
}
factory SharedCollection.fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return SharedCollection(
map['id'],
map['ownerID'],
map['encryptedKey'],
map['name'],
Collection.typeFromString(map['type']),
map['creationTime'],
);
}
String toJson() => json.encode(toMap());
factory SharedCollection.fromJson(String source) =>
SharedCollection.fromMap(json.decode(source));
@override
String toString() {
return 'SharedCollection(id: $id, ownerID: $ownerID, encryptedKey: $encryptedKey, name: $name, type: $type, creationTime: $creationTime)';
}
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is SharedCollection &&
o.id == id &&
o.ownerID == ownerID &&
o.encryptedKey == encryptedKey &&
o.name == name &&
o.type == type &&
o.creationTime == creationTime;
}
@override
int get hashCode {
return id.hashCode ^
ownerID.hashCode ^
encryptedKey.hashCode ^
name.hashCode ^
type.hashCode ^
creationTime.hashCode;
}
}

View file

@ -1,5 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:dio/dio.dart';
@ -8,6 +7,7 @@ import 'package:logging/logging.dart';
import 'package:photos/core/configuration.dart';
import 'package:photos/db/collections_db.dart';
import 'package:photos/models/collection.dart';
import 'package:photos/models/shared_collection.dart';
import 'package:photos/utils/crypto_util.dart';
class CollectionsService {
@ -33,10 +33,16 @@ class CollectionsService {
var collections =
await getOwnedCollections(lastCollectionCreationTime ?? 0);
await _db.insert(collections);
collections = await _db.getAll();
collections = await _db.getAllCollections();
for (final collection in collections) {
_cacheCollectionAttributes(collection);
}
final lastSharedCollectionCreationTime =
await _db.getLastCollectionCreationTime();
var sharedCollections =
await getSharedCollections(lastSharedCollectionCreationTime ?? 0);
await _db.insertSharedCollections(sharedCollections);
}
Collection getCollectionForPath(String path) {
@ -119,6 +125,28 @@ class CollectionsService {
});
}
Future<List<SharedCollection>> getSharedCollections(int sinceTime) {
return Dio()
.get(
Configuration.instance.getHttpEndpoint() + "/collections/shared",
queryParameters: {
"sinceTime": sinceTime,
},
options:
Options(headers: {"X-Auth-Token": Configuration.instance.getToken()}),
)
.then((response) {
final collections = List<SharedCollection>();
if (response != null) {
final c = response.data["collections"];
for (final collection in c) {
collections.add(SharedCollection.fromMap(collection));
}
}
return collections;
});
}
Future<Collection> getOrCreateForPath(String path) async {
if (_localCollections.containsKey(path)) {
return _localCollections[path];