Fetch and store shared collections
This commit is contained in:
parent
fcc172f733
commit
0af41fd97b
3 changed files with 202 additions and 8 deletions
|
@ -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]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
96
lib/models/shared_collection.dart
Normal file
96
lib/models/shared_collection.dart
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
|
|
Loading…
Add table
Reference in a new issue