Expose API to add a photo to the favorites-collection
This commit is contained in:
parent
f6e6e8bf49
commit
65a431f366
3 changed files with 150 additions and 10 deletions
66
lib/models/collection_file_item.dart
Normal file
66
lib/models/collection_file_item.dart
Normal file
|
@ -0,0 +1,66 @@
|
|||
import 'dart:convert';
|
||||
|
||||
class CollectionFileItem {
|
||||
final int id;
|
||||
final String encryptedKey;
|
||||
final String keyDecryptionNonce;
|
||||
|
||||
CollectionFileItem(
|
||||
this.id,
|
||||
this.encryptedKey,
|
||||
this.keyDecryptionNonce,
|
||||
);
|
||||
|
||||
CollectionFileItem copyWith({
|
||||
int id,
|
||||
String encryptedKey,
|
||||
String keyDecryptionNonce,
|
||||
}) {
|
||||
return CollectionFileItem(
|
||||
id ?? this.id,
|
||||
encryptedKey ?? this.encryptedKey,
|
||||
keyDecryptionNonce ?? this.keyDecryptionNonce,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'encryptedKey': encryptedKey,
|
||||
'keyDecryptionNonce': keyDecryptionNonce,
|
||||
};
|
||||
}
|
||||
|
||||
factory CollectionFileItem.fromMap(Map<String, dynamic> map) {
|
||||
if (map == null) return null;
|
||||
|
||||
return CollectionFileItem(
|
||||
map['id'],
|
||||
map['encryptedKey'],
|
||||
map['keyDecryptionNonce'],
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory CollectionFileItem.fromJson(String source) =>
|
||||
CollectionFileItem.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'CollectionFileItem(id: $id, encryptedKey: $encryptedKey, keyDecryptionNonce: $keyDecryptionNonce)';
|
||||
|
||||
@override
|
||||
bool operator ==(Object o) {
|
||||
if (identical(this, o)) return true;
|
||||
|
||||
return o is CollectionFileItem &&
|
||||
o.id == id &&
|
||||
o.encryptedKey == encryptedKey &&
|
||||
o.keyDecryptionNonce == keyDecryptionNonce;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
id.hashCode ^ encryptedKey.hashCode ^ keyDecryptionNonce.hashCode;
|
||||
}
|
|
@ -7,8 +7,11 @@ 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/collection_file_item.dart';
|
||||
import 'package:photos/models/file.dart';
|
||||
import 'package:photos/models/shared_collection.dart';
|
||||
import 'package:photos/utils/crypto_util.dart';
|
||||
import 'package:photos/utils/file_util.dart';
|
||||
|
||||
class CollectionsService {
|
||||
final _logger = Logger("CollectionsService");
|
||||
|
@ -36,7 +39,7 @@ class CollectionsService {
|
|||
await _db.insert(collections);
|
||||
collections = await _db.getAllCollections();
|
||||
for (final collection in collections) {
|
||||
_cacheCollectionAttributes(collection);
|
||||
_cacheOwnedCollectionAttributes(collection);
|
||||
}
|
||||
|
||||
final lastSharedCollectionCreationTime =
|
||||
|
@ -162,7 +165,7 @@ class CollectionsService {
|
|||
final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
|
||||
final encryptedPath =
|
||||
CryptoUtil.encryptSync(utf8.encode(path), _config.getKey());
|
||||
final collection = await createCollection(Collection(
|
||||
final collection = await createAndCacheCollection(Collection(
|
||||
null,
|
||||
null,
|
||||
Sodium.bin2base64(encryptedKeyData.encryptedData),
|
||||
|
@ -173,11 +176,33 @@ class CollectionsService {
|
|||
Sodium.bin2base64(encryptedPath.nonce),
|
||||
null,
|
||||
));
|
||||
_cacheCollectionAttributes(collection);
|
||||
return collection;
|
||||
}
|
||||
|
||||
Future<Collection> createCollection(Collection collection) async {
|
||||
Future<void> addToCollection(int collectionID, List<File> files) {
|
||||
final items = List<CollectionFileItem>();
|
||||
for (final file in files) {
|
||||
final key = decryptFileKey(file);
|
||||
final encryptedKeyData =
|
||||
CryptoUtil.encryptSync(key, getCollectionKey(collectionID));
|
||||
items.add(CollectionFileItem(
|
||||
file.uploadedFileID,
|
||||
Sodium.bin2base64(encryptedKeyData.encryptedData),
|
||||
Sodium.bin2base64(encryptedKeyData.nonce),
|
||||
));
|
||||
}
|
||||
return Dio().post(
|
||||
Configuration.instance.getHttpEndpoint() + "/collections/add-files",
|
||||
data: {
|
||||
"id": collectionID,
|
||||
"files": items,
|
||||
},
|
||||
options:
|
||||
Options(headers: {"X-Auth-Token": Configuration.instance.getToken()}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<Collection> createAndCacheCollection(Collection collection) async {
|
||||
return Dio()
|
||||
.post(
|
||||
Configuration.instance.getHttpEndpoint() + "/collections/",
|
||||
|
@ -186,12 +211,14 @@ class CollectionsService {
|
|||
Options(headers: {"X-Auth-Token": Configuration.instance.getToken()}),
|
||||
)
|
||||
.then((response) {
|
||||
return Collection.fromMap(response.data["collection"]);
|
||||
final collection = Collection.fromMap(response.data["collection"]);
|
||||
_cacheOwnedCollectionAttributes(collection);
|
||||
return collection;
|
||||
});
|
||||
}
|
||||
|
||||
void _cacheCollectionAttributes(Collection collection) {
|
||||
if (collection.ownerID == _config.getUserID()) {
|
||||
void _cacheOwnedCollectionAttributes(Collection collection) {
|
||||
if (collection.encryptedPath != null) {
|
||||
var path = utf8.decode(CryptoUtil.decryptSync(
|
||||
Sodium.base642bin(collection.encryptedPath),
|
||||
_config.getKey(),
|
||||
|
|
|
@ -1,13 +1,28 @@
|
|||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/local_photos_updated_event.dart';
|
||||
import 'package:photos/models/collection.dart';
|
||||
import 'package:photos/models/file.dart';
|
||||
import 'package:photos/services/collections_service.dart';
|
||||
import 'package:photos/utils/crypto_util.dart';
|
||||
import 'package:photos/utils/file_uploader.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class FavoritesService {
|
||||
static final _favoritePhotoIdsKey = "favorite_photo_ids";
|
||||
FavoritesService._privateConstructor();
|
||||
static FavoritesService instance =
|
||||
FavoritesService._privateConstructor();
|
||||
static final _favoritesCollectionIDKey = "favorites_collection_id";
|
||||
|
||||
Configuration _config;
|
||||
CollectionsService _collectionsService;
|
||||
FileUploader _fileUploader;
|
||||
|
||||
FavoritesService._privateConstructor() {
|
||||
_config = Configuration.instance;
|
||||
_collectionsService = CollectionsService.instance;
|
||||
_fileUploader = FileUploader.instance;
|
||||
}
|
||||
static FavoritesService instance = FavoritesService._privateConstructor();
|
||||
|
||||
SharedPreferences _preferences;
|
||||
|
||||
|
@ -44,4 +59,36 @@ class FavoritesService {
|
|||
return value.toSet();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addToFavorites(File file) async {
|
||||
final collectionID = await getOrCreateFavoriteCollectionID();
|
||||
var fileID = file.uploadedFileID;
|
||||
if (fileID == null) {
|
||||
file.collectionID = collectionID;
|
||||
fileID = (await _fileUploader.encryptAndUploadFile(file)).uploadedFileID;
|
||||
}
|
||||
return _collectionsService.addToCollection(collectionID, [file]);
|
||||
}
|
||||
|
||||
Future<int> getOrCreateFavoriteCollectionID() async {
|
||||
if (_preferences.containsKey(_favoritesCollectionIDKey)) {
|
||||
return _preferences.getInt(_favoritesCollectionIDKey);
|
||||
}
|
||||
final key = CryptoUtil.generateKey();
|
||||
final encryptedKeyData = CryptoUtil.encryptSync(key, _config.getKey());
|
||||
final collection =
|
||||
await _collectionsService.createAndCacheCollection(Collection(
|
||||
null,
|
||||
null,
|
||||
Sodium.bin2base64(encryptedKeyData.encryptedData),
|
||||
Sodium.bin2base64(encryptedKeyData.nonce),
|
||||
"Favorites",
|
||||
CollectionType.favorites,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
));
|
||||
await _preferences.setInt(_favoritesCollectionIDKey, collection.id);
|
||||
return collection.id;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue