mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-03-13 18:58:53 +01:00
Migrate album to save files as file descriptors
This commit is contained in:
parent
07ee28d0cb
commit
1c999f6fab
35 changed files with 1162 additions and 466 deletions
|
@ -9,6 +9,7 @@ import 'package:nc_photos/entity/album.dart';
|
|||
import 'package:nc_photos/entity/album/item.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/entity/share.dart';
|
||||
import 'package:nc_photos/object_extension.dart';
|
||||
import 'package:nc_photos/use_case/list_share.dart';
|
||||
|
@ -28,12 +29,12 @@ class ListAlbumShareOutlierItem with EquatableMixin {
|
|||
String toString() => _$toString();
|
||||
|
||||
@override
|
||||
get props => [
|
||||
List<Object?> get props => [
|
||||
file,
|
||||
shareItems,
|
||||
];
|
||||
|
||||
final File file;
|
||||
final FileDescriptor file;
|
||||
@Format(r"${$?.toReadableString()}")
|
||||
final List<ListAlbumShareOutlierShareItem> shareItems;
|
||||
}
|
||||
|
@ -164,7 +165,6 @@ class ListAlbumShareOutlierBloc extends Bloc<ListAlbumShareOutlierBlocEvent,
|
|||
ListAlbumShareOutlierBlocState> {
|
||||
ListAlbumShareOutlierBloc(this._c)
|
||||
: assert(require(_c)),
|
||||
assert(ListShare.require(_c)),
|
||||
super(ListAlbumShareOutlierBlocInit()) {
|
||||
on<ListAlbumShareOutlierBlocEvent>(_onEvent);
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ class ListAlbumShareOutlierBloc extends Bloc<ListAlbumShareOutlierBlocEvent,
|
|||
});
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe(
|
||||
"[_processAlbumItems] Failed while _processSingleFile: ${logFilename(fi.file.path)}",
|
||||
"[_processAlbumItems] Failed while _processSingleFile: ${logFilename(fi.file.fdPath)}",
|
||||
e,
|
||||
stackTrace);
|
||||
errors.add(e);
|
||||
|
@ -312,7 +312,7 @@ class ListAlbumShareOutlierBloc extends Bloc<ListAlbumShareOutlierBlocEvent,
|
|||
.map((s) => s.userId)
|
||||
.toSet();
|
||||
_log.info(
|
||||
"[_processSingleFileItem] Sharees: ${albumSharees.map((s) => managedAlbumSharees.contains(s) ? "(managed)$s" : s).toReadableString()} for file: ${logFilename(fileItem.file.path)}");
|
||||
"[_processSingleFileItem] Sharees: ${albumSharees.map((s) => managedAlbumSharees.contains(s) ? "(managed)$s" : s).toReadableString()} for file: ${logFilename(fileItem.file.fdPath)}");
|
||||
|
||||
// check all shares (including reshares) against sharees that are managed by
|
||||
// us
|
||||
|
@ -320,10 +320,10 @@ class ListAlbumShareOutlierBloc extends Bloc<ListAlbumShareOutlierBlocEvent,
|
|||
var missings = managedAlbumSharees
|
||||
.difference(allSharees)
|
||||
// Can't share to ourselves or the file owner
|
||||
.where((s) => s != account.userId && s != fileItem.file.ownerId)
|
||||
.where((s) => s != account.userId && s != fileItem.ownerId)
|
||||
.toList();
|
||||
_log.info(
|
||||
"[_processSingleFileItem] Missing shares: ${missings.toReadableString()} for file: ${logFilename(fileItem.file.path)}");
|
||||
"[_processSingleFileItem] Missing shares: ${missings.toReadableString()} for file: ${logFilename(fileItem.file.fdPath)}");
|
||||
for (final m in missings) {
|
||||
final as = albumShares[m]!;
|
||||
shareItems.add(
|
||||
|
@ -338,14 +338,14 @@ class ListAlbumShareOutlierBloc extends Bloc<ListAlbumShareOutlierBlocEvent,
|
|||
.toSet();
|
||||
final extras = ownedSharees.difference(albumSharees);
|
||||
_log.info(
|
||||
"[_processSingleFileItem] Extra shares: ${extras.toReadableString()} for file: ${logFilename(fileItem.file.path)}");
|
||||
"[_processSingleFileItem] Extra shares: ${extras.toReadableString()} for file: ${logFilename(fileItem.file.fdPath)}");
|
||||
for (final e in extras) {
|
||||
try {
|
||||
shareItems.add(ListAlbumShareOutlierExtraShareItem(
|
||||
shares.firstWhere((s) => s.shareWith == e)));
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe(
|
||||
"[_processSingleFileItem] Failed while processing extra share for file: ${logFilename(fileItem.file.path)}",
|
||||
"[_processSingleFileItem] Failed while processing extra share for file: ${logFilename(fileItem.file.fdPath)}",
|
||||
e,
|
||||
stackTrace);
|
||||
errors.add(e);
|
||||
|
|
|
@ -21,7 +21,7 @@ extension _$ListAlbumShareOutlierBlocNpLog on ListAlbumShareOutlierBloc {
|
|||
extension _$ListAlbumShareOutlierItemToString on ListAlbumShareOutlierItem {
|
||||
String _$toString() {
|
||||
// ignore: unnecessary_string_interpolations
|
||||
return "ListAlbumShareOutlierItem {file: ${file.path}, shareItems: ${shareItems.toReadableString()}}";
|
||||
return "ListAlbumShareOutlierItem {file: ${file.fdPath}, shareItems: ${shareItems.toReadableString()}}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,13 @@ class Album with EquatableMixin {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
if (jsonVersion < 10) {
|
||||
result = upgraderFactory?.buildV9()?.doJson(result);
|
||||
if (result == null) {
|
||||
_log.info("[fromJson] Version $jsonVersion not compatible");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (jsonVersion > version) {
|
||||
_log.warning(
|
||||
"[fromJson] Reading album with newer version: $jsonVersion > $version");
|
||||
|
@ -224,7 +231,7 @@ class Album with EquatableMixin {
|
|||
final int savedVersion;
|
||||
|
||||
/// versioning of this class, use to upgrade old persisted album
|
||||
static const version = 9;
|
||||
static const version = 10;
|
||||
|
||||
static final _log = _$AlbumNpLog.log;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'package:logging/logging.dart';
|
|||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/album/item.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
|
@ -78,11 +77,8 @@ class AlbumAutoCoverProvider extends AlbumCoverProvider {
|
|||
return items
|
||||
.whereType<AlbumFileItem>()
|
||||
.map((e) => e.file)
|
||||
.where((element) =>
|
||||
file_util.isSupportedFormat(element) &&
|
||||
(element.hasPreview ?? false) &&
|
||||
element.fileId != null)
|
||||
.sorted(compareFileDateTimeDescending)
|
||||
.where(file_util.isSupportedFormat)
|
||||
.sorted(compareFileDescriptorDateTimeDescending)
|
||||
.firstOrNull;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,11 @@ class AlbumSqliteDbDataSource2 implements AlbumDataSource2 {
|
|||
if (dbAlbum.version < 9) {
|
||||
dbAlbum = AlbumUpgraderV8(logFilePath: file.path).doDb(dbAlbum)!;
|
||||
}
|
||||
if (dbAlbum.version < 10) {
|
||||
dbAlbum =
|
||||
AlbumUpgraderV9(account: account, logFilePath: file.path)
|
||||
.doDb(dbAlbum)!;
|
||||
}
|
||||
return DbAlbumConverter.fromDb(file, dbAlbum);
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe(
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
import 'package:np_common/or_null.dart';
|
||||
import 'package:np_common/type.dart';
|
||||
import 'package:np_string/np_string.dart';
|
||||
import 'package:to_string/to_string.dart';
|
||||
|
@ -57,11 +56,13 @@ abstract class AlbumItem with EquatableMixin {
|
|||
|
||||
JsonObj toContentJson();
|
||||
|
||||
bool compareServerIdentity(AlbumItem other);
|
||||
|
||||
@override
|
||||
String toString() => _$toString();
|
||||
|
||||
@override
|
||||
get props => [
|
||||
List<Object?> get props => [
|
||||
addedBy,
|
||||
addedAt,
|
||||
];
|
||||
|
@ -75,29 +76,19 @@ abstract class AlbumItem with EquatableMixin {
|
|||
@toString
|
||||
class AlbumFileItem extends AlbumItem {
|
||||
AlbumFileItem({
|
||||
required CiString addedBy,
|
||||
required DateTime addedAt,
|
||||
required super.addedBy,
|
||||
required super.addedAt,
|
||||
required this.file,
|
||||
}) : super(addedBy: addedBy, addedAt: addedAt);
|
||||
|
||||
@override
|
||||
// ignore: hash_and_equals
|
||||
bool operator ==(Object? other) => equals(other, isDeep: true);
|
||||
|
||||
bool equals(Object? other, {bool isDeep = false}) {
|
||||
if (other is AlbumFileItem) {
|
||||
return super == other && (file.equals(other.file, isDeep: isDeep));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
required this.ownerId,
|
||||
});
|
||||
|
||||
factory AlbumFileItem.fromJson(
|
||||
JsonObj json, CiString addedBy, DateTime addedAt) {
|
||||
return AlbumFileItem(
|
||||
addedBy: addedBy,
|
||||
addedAt: addedAt,
|
||||
file: File.fromJson(json["file"].cast<String, dynamic>()),
|
||||
file: FileDescriptor.fromJson(json["file"].cast<String, dynamic>()),
|
||||
ownerId: (json["ownerId"] as String).toCi(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -105,37 +96,43 @@ class AlbumFileItem extends AlbumItem {
|
|||
String toString() => _$toString();
|
||||
|
||||
@override
|
||||
toContentJson() {
|
||||
JsonObj toContentJson() {
|
||||
return {
|
||||
"file": file.toJson(),
|
||||
"file": file.toFdJson(),
|
||||
"ownerId": ownerId.raw,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
bool compareServerIdentity(AlbumItem other) =>
|
||||
other is AlbumFileItem &&
|
||||
file.compareServerIdentity(other.file) &&
|
||||
addedBy == other.addedBy &&
|
||||
addedAt == other.addedAt;
|
||||
|
||||
AlbumFileItem copyWith({
|
||||
CiString? addedBy,
|
||||
DateTime? addedAt,
|
||||
File? file,
|
||||
FileDescriptor? file,
|
||||
CiString? ownerId,
|
||||
}) {
|
||||
return AlbumFileItem(
|
||||
addedBy: addedBy ?? this.addedBy,
|
||||
addedAt: addedAt ?? this.addedAt,
|
||||
file: file ?? this.file,
|
||||
ownerId: ownerId ?? this.ownerId,
|
||||
);
|
||||
}
|
||||
|
||||
AlbumFileItem minimize() => AlbumFileItem(
|
||||
addedBy: addedBy,
|
||||
addedAt: addedAt,
|
||||
file: file.copyWith(metadata: const OrNull(null)),
|
||||
);
|
||||
|
||||
@override
|
||||
get props => [
|
||||
List<Object?> get props => [
|
||||
...super.props,
|
||||
// file is handled separately, see [equals]
|
||||
file,
|
||||
ownerId,
|
||||
];
|
||||
|
||||
final File file;
|
||||
final FileDescriptor file;
|
||||
final CiString ownerId;
|
||||
|
||||
static const _type = "file";
|
||||
}
|
||||
|
@ -161,12 +158,19 @@ class AlbumLabelItem extends AlbumItem {
|
|||
String toString() => _$toString();
|
||||
|
||||
@override
|
||||
toContentJson() {
|
||||
JsonObj toContentJson() {
|
||||
return {
|
||||
"text": text,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
bool compareServerIdentity(AlbumItem other) =>
|
||||
other is AlbumLabelItem &&
|
||||
text == other.text &&
|
||||
addedBy == other.addedBy &&
|
||||
addedAt == other.addedAt;
|
||||
|
||||
AlbumLabelItem copyWith({
|
||||
CiString? addedBy,
|
||||
DateTime? addedAt,
|
||||
|
@ -180,7 +184,7 @@ class AlbumLabelItem extends AlbumItem {
|
|||
}
|
||||
|
||||
@override
|
||||
get props => [
|
||||
List<Object?> get props => [
|
||||
...super.props,
|
||||
text,
|
||||
];
|
||||
|
|
|
@ -27,7 +27,7 @@ extension _$AlbumItemToString on AlbumItem {
|
|||
extension _$AlbumFileItemToString on AlbumFileItem {
|
||||
String _$toString() {
|
||||
// ignore: unnecessary_string_interpolations
|
||||
return "AlbumFileItem {addedBy: $addedBy, addedAt: $addedAt, file: ${file.path}}";
|
||||
return "AlbumFileItem {addedBy: $addedBy, addedAt: $addedAt, file: ${file.fdPath}, ownerId: $ownerId}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -350,6 +350,64 @@ class AlbumUpgraderV8 implements AlbumUpgrader {
|
|||
final String? logFilePath;
|
||||
}
|
||||
|
||||
/// Upgrade v9 Album to v10
|
||||
///
|
||||
/// In v10, file items are now stored as FileDescriptor instead of File
|
||||
@npLog
|
||||
class AlbumUpgraderV9 implements AlbumUpgrader {
|
||||
const AlbumUpgraderV9({
|
||||
required this.account,
|
||||
this.logFilePath,
|
||||
});
|
||||
|
||||
@override
|
||||
JsonObj? doJson(JsonObj json) {
|
||||
_log.fine("[doJson] Upgrade v9 Album for file: $logFilePath");
|
||||
final result = JsonObj.from(json);
|
||||
if (result["provider"]["type"] != "static") {
|
||||
return result;
|
||||
}
|
||||
for (final item in (result["provider"]["content"]["items"] as List)) {
|
||||
if (item["type"] != "file") {
|
||||
continue;
|
||||
}
|
||||
final originalFile =
|
||||
(item["content"]["file"] as Map).cast<String, dynamic>();
|
||||
item["content"]["file"] =
|
||||
AlbumUpgraderV8._fileJsonToFileDescriptorJson(originalFile);
|
||||
item["content"]["ownerId"] =
|
||||
originalFile["ownerId"] ?? account.userId.raw;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
DbAlbum? doDb(DbAlbum dbObj) {
|
||||
_log.fine("[doDb] Upgrade v9 Album for file: $logFilePath");
|
||||
if (dbObj.providerType != "static") {
|
||||
return dbObj;
|
||||
}
|
||||
final content = Map.of(dbObj.providerContent);
|
||||
for (final item in content["items"] as List) {
|
||||
if (item["type"] != "file") {
|
||||
continue;
|
||||
}
|
||||
final originalFile =
|
||||
(item["content"]["file"] as Map).cast<String, dynamic>();
|
||||
item["content"]["file"] =
|
||||
AlbumUpgraderV8._fileJsonToFileDescriptorJson(originalFile);
|
||||
item["content"]["ownerId"] =
|
||||
originalFile["ownerId"] ?? account.userId.raw;
|
||||
}
|
||||
return dbObj.copyWith(providerContent: content);
|
||||
}
|
||||
|
||||
final Account account;
|
||||
|
||||
/// File path for logging only
|
||||
final String? logFilePath;
|
||||
}
|
||||
|
||||
abstract class AlbumUpgraderFactory {
|
||||
const AlbumUpgraderFactory();
|
||||
|
||||
|
@ -361,6 +419,7 @@ abstract class AlbumUpgraderFactory {
|
|||
AlbumUpgraderV6? buildV6();
|
||||
AlbumUpgraderV7? buildV7();
|
||||
AlbumUpgraderV8? buildV8();
|
||||
AlbumUpgraderV9? buildV9();
|
||||
}
|
||||
|
||||
class DefaultAlbumUpgraderFactory extends AlbumUpgraderFactory {
|
||||
|
@ -371,32 +430,38 @@ class DefaultAlbumUpgraderFactory extends AlbumUpgraderFactory {
|
|||
});
|
||||
|
||||
@override
|
||||
buildV1() => AlbumUpgraderV1(logFilePath: logFilePath);
|
||||
AlbumUpgraderV1 buildV1() => AlbumUpgraderV1(logFilePath: logFilePath);
|
||||
|
||||
@override
|
||||
buildV2() => AlbumUpgraderV2(logFilePath: logFilePath);
|
||||
AlbumUpgraderV2 buildV2() => AlbumUpgraderV2(logFilePath: logFilePath);
|
||||
|
||||
@override
|
||||
buildV3() => AlbumUpgraderV3(logFilePath: logFilePath);
|
||||
AlbumUpgraderV3 buildV3() => AlbumUpgraderV3(logFilePath: logFilePath);
|
||||
|
||||
@override
|
||||
buildV4() => AlbumUpgraderV4(logFilePath: logFilePath);
|
||||
AlbumUpgraderV4 buildV4() => AlbumUpgraderV4(logFilePath: logFilePath);
|
||||
|
||||
@override
|
||||
buildV5() => AlbumUpgraderV5(
|
||||
AlbumUpgraderV5 buildV5() => AlbumUpgraderV5(
|
||||
account,
|
||||
albumFile: albumFile,
|
||||
logFilePath: logFilePath,
|
||||
);
|
||||
|
||||
@override
|
||||
buildV6() => AlbumUpgraderV6(logFilePath: logFilePath);
|
||||
AlbumUpgraderV6 buildV6() => AlbumUpgraderV6(logFilePath: logFilePath);
|
||||
|
||||
@override
|
||||
buildV7() => AlbumUpgraderV7(logFilePath: logFilePath);
|
||||
AlbumUpgraderV7 buildV7() => AlbumUpgraderV7(logFilePath: logFilePath);
|
||||
|
||||
@override
|
||||
AlbumUpgraderV8? buildV8() => AlbumUpgraderV8(logFilePath: logFilePath);
|
||||
AlbumUpgraderV8 buildV8() => AlbumUpgraderV8(logFilePath: logFilePath);
|
||||
|
||||
@override
|
||||
AlbumUpgraderV9 buildV9() => AlbumUpgraderV9(
|
||||
account: account,
|
||||
logFilePath: logFilePath,
|
||||
);
|
||||
|
||||
final Account account;
|
||||
final File? albumFile;
|
||||
|
|
|
@ -61,3 +61,10 @@ extension _$AlbumUpgraderV8NpLog on AlbumUpgraderV8 {
|
|||
|
||||
static final log = Logger("entity.album.upgrader.AlbumUpgraderV8");
|
||||
}
|
||||
|
||||
extension _$AlbumUpgraderV9NpLog on AlbumUpgraderV9 {
|
||||
// ignore: unused_element
|
||||
Logger get _log => log;
|
||||
|
||||
static final log = Logger("entity.album.upgrader.AlbumUpgraderV9");
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ class CollectionAlbumAdapter implements CollectionAdapter {
|
|||
_provider.album,
|
||||
sharee,
|
||||
onShareFileFailed: (f, e, stackTrace) {
|
||||
_log.severe("[share] Failed to share file: ${logFilename(f.path)}", e,
|
||||
_log.severe("[share] Failed to share file: ${logFilename(f.fdPath)}", e,
|
||||
stackTrace);
|
||||
fileFailed = true;
|
||||
},
|
||||
|
|
|
@ -50,6 +50,7 @@ class CollectionExporter {
|
|||
addedBy: account.userId,
|
||||
addedAt: clock.now().toUtc(),
|
||||
file: f,
|
||||
ownerId: f.ownerId ?? account.userId,
|
||||
);
|
||||
}
|
||||
} else if (e is CollectionLabelItem) {
|
||||
|
|
|
@ -55,7 +55,7 @@ class FileDescriptor with EquatableMixin {
|
|||
JsonObj toFdJson() => toJson(this);
|
||||
|
||||
@override
|
||||
get props => [
|
||||
List<Object?> get props => [
|
||||
fdPath,
|
||||
fdId,
|
||||
fdMime,
|
||||
|
@ -136,3 +136,23 @@ extension FileDescriptorExtension on FileDescriptor {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FileDescriptorServerIdentityComparator {
|
||||
const FileDescriptorServerIdentityComparator(this.file);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other is FileDescriptorServerIdentityComparator) {
|
||||
return file.compareServerIdentity(other.file);
|
||||
} else if (other is FileDescriptor) {
|
||||
return file.compareServerIdentity(other);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => file.fdId.hashCode;
|
||||
|
||||
final FileDescriptor file;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ class AddFileToAlbum {
|
|||
static bool require(DiContainer c) =>
|
||||
DiContainer.has(c, DiType.albumRepo) &&
|
||||
DiContainer.has(c, DiType.shareRepo) &&
|
||||
ListShare.require(c) &&
|
||||
PreProcessAlbum.require(c);
|
||||
|
||||
/// Add list of files to [album]
|
||||
|
@ -47,7 +46,8 @@ class AddFileToAlbum {
|
|||
.map((f) => AlbumFileItem(
|
||||
addedBy: account.userId,
|
||||
addedAt: clock.now(),
|
||||
file: f,
|
||||
file: f.toDescriptor(),
|
||||
ownerId: f.ownerId ?? account.userId,
|
||||
))
|
||||
.where((i) => itemSet.add(OverrideComparator<AlbumItem>(
|
||||
i, _isItemFileEqual, _getItemHashCode)))
|
||||
|
@ -63,18 +63,14 @@ class AddFileToAlbum {
|
|||
);
|
||||
// UpdateAlbumWithActualItems only persists when there are changes to
|
||||
// several properties, so we can't rely on it
|
||||
newAlbum = await UpdateAlbumWithActualItems(null)(
|
||||
account,
|
||||
newAlbum,
|
||||
newItems,
|
||||
);
|
||||
newAlbum =
|
||||
await UpdateAlbumWithActualItems(null)(account, newAlbum, newItems);
|
||||
await UpdateAlbum(_c.albumRepo)(account, newAlbum);
|
||||
|
||||
if (album.shares?.isNotEmpty == true) {
|
||||
final newFiles =
|
||||
addItems.whereType<AlbumFileItem>().map((e) => e.file).toList();
|
||||
if (newFiles.isNotEmpty) {
|
||||
await _shareFiles(account, newAlbum, newFiles);
|
||||
final newFileItems = addItems.whereType<AlbumFileItem>().toList();
|
||||
if (newFileItems.isNotEmpty) {
|
||||
await _shareFiles(account, newAlbum, newFileItems);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +78,7 @@ class AddFileToAlbum {
|
|||
}
|
||||
|
||||
Future<void> _shareFiles(
|
||||
Account account, Album album, List<File> files) async {
|
||||
Account account, Album album, List<AlbumFileItem> fileItems) async {
|
||||
final albumShares = (album.shares!.map((e) => e.userId).toList()
|
||||
..add(album.albumFile!.ownerId ?? account.userId))
|
||||
.where((element) => element != account.userId)
|
||||
|
@ -90,30 +86,30 @@ class AddFileToAlbum {
|
|||
if (albumShares.isEmpty) {
|
||||
return;
|
||||
}
|
||||
for (final f in files) {
|
||||
for (final i in fileItems) {
|
||||
try {
|
||||
final fileShares = (await ListShare(_c)(account, f))
|
||||
final fileShares = (await ListShare(_c)(account, i.file))
|
||||
.where((element) => element.shareType == ShareType.user)
|
||||
.map((e) => e.shareWith!)
|
||||
.toSet();
|
||||
final diffShares = albumShares.difference(fileShares);
|
||||
for (final s in diffShares) {
|
||||
if (s == f.ownerId) {
|
||||
if (s == i.ownerId) {
|
||||
// skip files already owned by the target user
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
await CreateUserShare(_c.shareRepo)(account, f, s.raw);
|
||||
await CreateUserShare(_c.shareRepo)(account, i.file, s.raw);
|
||||
} catch (e, stackTrace) {
|
||||
_log.shout(
|
||||
"[_shareFiles] Failed while CreateUserShare: ${logFilename(f.path)}",
|
||||
"[_shareFiles] Failed while CreateUserShare: ${logFilename(i.file.fdPath)}",
|
||||
e,
|
||||
stackTrace);
|
||||
}
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
_log.shout(
|
||||
"[_shareFiles] Failed while listing shares: ${logFilename(f.path)}",
|
||||
"[_shareFiles] Failed while listing shares: ${logFilename(i.file.fdPath)}",
|
||||
e,
|
||||
stackTrace);
|
||||
}
|
||||
|
@ -133,7 +129,7 @@ bool _isItemFileEqual(AlbumItem a, AlbumItem b) {
|
|||
|
||||
int _getItemHashCode(AlbumItem a) {
|
||||
if (a is AlbumFileItem) {
|
||||
return a.file.fileId?.hashCode ?? a.file.path.hashCode;
|
||||
return a.file.fdId.hashCode;
|
||||
} else {
|
||||
return a.hashCode;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ part 'remove_album.g.dart';
|
|||
class RemoveAlbum {
|
||||
RemoveAlbum(this._c)
|
||||
: assert(require(_c)),
|
||||
assert(ListShare.require(_c)),
|
||||
assert(UnshareFileFromAlbum.require(_c));
|
||||
|
||||
static bool require(DiContainer c) =>
|
||||
|
|
|
@ -30,9 +30,6 @@ class RemoveFromAlbum {
|
|||
|
||||
/// Remove a list of AlbumItems from [album]
|
||||
///
|
||||
/// The items are compared with [identical], so it must come from [album] for
|
||||
/// it to work
|
||||
///
|
||||
/// If [shouldUnshare] is false, files will not be unshared after removing
|
||||
/// from the album
|
||||
Future<Album> call(
|
||||
|
@ -65,7 +62,8 @@ class RemoveFromAlbum {
|
|||
.toList();
|
||||
final provider = album.provider as AlbumStaticProvider;
|
||||
final newItems = provider.items
|
||||
.where((element) => !filtered.containsIdentical(element))
|
||||
.where((e) =>
|
||||
!filtered.containsIf(e, (a, b) => a.compareServerIdentity(b)))
|
||||
.toList();
|
||||
var newAlbum = album.copyWith(
|
||||
provider: AlbumStaticProvider.of(album).copyWith(
|
||||
|
@ -108,7 +106,7 @@ class RemoveFromAlbum {
|
|||
isNeedUpdate = true;
|
||||
break;
|
||||
}
|
||||
if (fileItem.file.bestDateTime == newAlbum.provider.latestItemTime) {
|
||||
if (fileItem.file.fdDateTime == newAlbum.provider.latestItemTime) {
|
||||
isNeedUpdate = true;
|
||||
break;
|
||||
}
|
||||
|
@ -130,7 +128,7 @@ class RemoveFromAlbum {
|
|||
}
|
||||
|
||||
Future<void> _unshareFiles(
|
||||
Account account, Album album, List<File> files) async {
|
||||
Account account, Album album, List<FileDescriptor> files) async {
|
||||
final albumShares = (album.shares!.map((e) => e.userId).toList()
|
||||
..add(album.albumFile!.ownerId ?? account.userId))
|
||||
.where((element) => element != account.userId)
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:nc_photos/debug_util.dart';
|
|||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/album/item.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/entity/share.dart';
|
||||
import 'package:nc_photos/entity/sharee.dart';
|
||||
import 'package:nc_photos/use_case/create_share.dart';
|
||||
|
@ -25,7 +25,7 @@ class ShareAlbumWithUser {
|
|||
Account account,
|
||||
Album album,
|
||||
Sharee sharee, {
|
||||
ErrorWithValueHandler<File>? onShareFileFailed,
|
||||
ErrorWithValueHandler<FileDescriptor>? onShareFileFailed,
|
||||
}) async {
|
||||
assert(album.provider is AlbumStaticProvider);
|
||||
final newShares = (album.shares ?? [])
|
||||
|
@ -56,12 +56,12 @@ class ShareAlbumWithUser {
|
|||
Account account,
|
||||
Album album,
|
||||
CiString shareWith, {
|
||||
ErrorWithValueHandler<File>? onShareFileFailed,
|
||||
ErrorWithValueHandler<FileDescriptor>? onShareFileFailed,
|
||||
}) async {
|
||||
final files = AlbumStaticProvider.of(album)
|
||||
.items
|
||||
.whereType<AlbumFileItem>()
|
||||
.where((item) => item.file.ownerId != shareWith)
|
||||
.where((item) => item.ownerId != shareWith)
|
||||
.map((e) => e.file);
|
||||
try {
|
||||
await CreateUserShare(shareRepo)(
|
||||
|
@ -74,12 +74,12 @@ class ShareAlbumWithUser {
|
|||
onShareFileFailed?.call(album.albumFile!, e, stackTrace);
|
||||
}
|
||||
for (final f in files) {
|
||||
_log.info("[_createFileShares] Sharing '${f.path}' with '$shareWith'");
|
||||
_log.info("[_createFileShares] Sharing '${f.fdPath}' with '$shareWith'");
|
||||
try {
|
||||
await CreateUserShare(shareRepo)(account, f, shareWith.raw);
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe(
|
||||
"[_createFileShares] Failed sharing file '${logFilename(f.path)}' with '$shareWith'",
|
||||
"[_createFileShares] Failed sharing file '${logFilename(f.fdPath)}' with '$shareWith'",
|
||||
e,
|
||||
stackTrace);
|
||||
onShareFileFailed?.call(f, e, stackTrace);
|
||||
|
|
|
@ -21,7 +21,6 @@ part 'unshare_album_with_user.g.dart';
|
|||
class UnshareAlbumWithUser {
|
||||
UnshareAlbumWithUser(this._c)
|
||||
: assert(require(_c)),
|
||||
assert(ListShare.require(_c)),
|
||||
assert(UnshareFileFromAlbum.require(_c));
|
||||
|
||||
static bool require(DiContainer c) =>
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'package:nc_photos/di_container.dart';
|
|||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/album/item.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/entity/share.dart';
|
||||
import 'package:nc_photos/stream_extension.dart';
|
||||
|
@ -22,8 +21,7 @@ part 'unshare_file_from_album.g.dart';
|
|||
class UnshareFileFromAlbum {
|
||||
UnshareFileFromAlbum(this._c)
|
||||
: assert(require(_c)),
|
||||
assert(ListAlbum.require(_c)),
|
||||
assert(ListShare.require(_c));
|
||||
assert(ListAlbum.require(_c));
|
||||
|
||||
static bool require(DiContainer c) => DiContainer.has(c, DiType.shareRepo);
|
||||
|
||||
|
@ -34,7 +32,7 @@ class UnshareFileFromAlbum {
|
|||
Future<void> call(
|
||||
Account account,
|
||||
Album album,
|
||||
List<File> files,
|
||||
List<FileDescriptor> files,
|
||||
List<CiString> unshareWith, {
|
||||
ErrorWithValueHandler<Share>? onUnshareFileFailed,
|
||||
}) async {
|
||||
|
@ -57,7 +55,7 @@ class UnshareFileFromAlbum {
|
|||
exclusiveShares.addAll(
|
||||
shares.where((element) => unshareWith.contains(element.shareWith)));
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe("[call] Failed while ListShare: '${logFilename(f.path)}'",
|
||||
_log.severe("[call] Failed while ListShare: '${logFilename(f.fdPath)}'",
|
||||
e, stackTrace);
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +75,7 @@ class UnshareFileFromAlbum {
|
|||
// remove files shared as part of this other shared album
|
||||
exclusiveShares.removeWhere((s) =>
|
||||
sharesOfInterest.any((i) => i.userId == s.shareWith) &&
|
||||
albumFiles.any((f) => f.fileId == s.itemSource));
|
||||
albumFiles.any((f) => f.fdId == s.itemSource));
|
||||
}
|
||||
_log.fine("[call] Post-filter shares: $exclusiveShares");
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class RemoveFromNcAlbum {
|
|||
var count = fileItems.length;
|
||||
await Remove(_c)(
|
||||
account,
|
||||
fileItems.map((e) => e.file.toFile()).toList(),
|
||||
fileItems.map((e) => e.file).toList(),
|
||||
onError: (i, f, e, stackTrace) {
|
||||
--count;
|
||||
try {
|
||||
|
|
|
@ -55,6 +55,7 @@ class PopulateAlbum {
|
|||
addedBy: account.userId,
|
||||
addedAt: clock.now(),
|
||||
file: f,
|
||||
ownerId: f.ownerId ?? account.userId,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +73,7 @@ class PopulateAlbum {
|
|||
addedBy: account.userId,
|
||||
addedAt: clock.now(),
|
||||
file: f,
|
||||
ownerId: f.ownerId ?? account.userId,
|
||||
)));
|
||||
return products;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,7 @@ import 'package:nc_photos/use_case/resync_album.dart';
|
|||
class PreProcessAlbum {
|
||||
PreProcessAlbum(this._c)
|
||||
: assert(require(_c)),
|
||||
assert(PopulateAlbum.require(_c)),
|
||||
assert(ResyncAlbum.require(_c));
|
||||
assert(PopulateAlbum.require(_c));
|
||||
|
||||
static bool require(DiContainer c) => true;
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import 'package:nc_photos/di_container.dart';
|
|||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/album/item.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/event/event.dart';
|
||||
import 'package:nc_photos/stream_extension.dart';
|
||||
|
@ -61,7 +60,7 @@ class Remove {
|
|||
Account account, List<FileDescriptor> removes) async {
|
||||
final albums = await ListAlbum(_c)(account).whereType<Album>().toList();
|
||||
// figure out which files need to be unshared with whom
|
||||
final unshares = <FileServerIdentityComparator, Set<CiString>>{};
|
||||
final unshares = <FileDescriptorServerIdentityComparator, Set<CiString>>{};
|
||||
// clean up only make sense for static albums
|
||||
for (final a in albums.where((a) => a.provider is AlbumStaticProvider)) {
|
||||
try {
|
||||
|
@ -69,22 +68,21 @@ class Remove {
|
|||
final itemsToRemove = provider.items
|
||||
.whereType<AlbumFileItem>()
|
||||
.where((i) =>
|
||||
(i.file.isOwned(account.userId) ||
|
||||
i.addedBy == account.userId) &&
|
||||
(i.ownerId == account.userId || i.addedBy == account.userId) &&
|
||||
removes.any((r) => r.compareServerIdentity(i.file)))
|
||||
.toList();
|
||||
if (itemsToRemove.isEmpty) {
|
||||
continue;
|
||||
}
|
||||
for (final i in itemsToRemove) {
|
||||
final key = FileServerIdentityComparator(i.file);
|
||||
final key = FileDescriptorServerIdentityComparator(i.file);
|
||||
final value = (a.shares?.map((s) => s.userId).toList() ?? [])
|
||||
..add(a.albumFile!.ownerId!)
|
||||
..remove(account.userId);
|
||||
(unshares[key] ??= <CiString>{}).addAll(value);
|
||||
}
|
||||
_log.fine(
|
||||
"[_cleanUpAlbums] Removing from album '${a.name}': ${itemsToRemove.map((e) => e.file.path).toReadableString()}");
|
||||
"[_cleanUpAlbums] Removing from album '${a.name}': ${itemsToRemove.map((e) => e.file.fdPath).toReadableString()}");
|
||||
// skip unsharing as we'll handle it ourselves
|
||||
await RemoveFromAlbum(_c)(account, a, itemsToRemove,
|
||||
shouldUnshare: false);
|
||||
|
|
|
@ -6,7 +6,7 @@ import 'package:nc_photos/di_container.dart';
|
|||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/album/item.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/use_case/find_file.dart';
|
||||
import 'package:nc_photos/use_case/find_file_descriptor.dart';
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
|
||||
part 'resync_album.g.dart';
|
||||
|
@ -14,9 +14,7 @@ part 'resync_album.g.dart';
|
|||
/// Resync files inside an album with the file db
|
||||
@npLog
|
||||
class ResyncAlbum {
|
||||
ResyncAlbum(this._c) : assert(require(_c));
|
||||
|
||||
static bool require(DiContainer c) => true;
|
||||
const ResyncAlbum(this._c);
|
||||
|
||||
Future<List<AlbumItem>> call(Account account, Album album) async {
|
||||
_log.info("[call] Resync album: ${album.name}");
|
||||
|
@ -26,11 +24,11 @@ class ResyncAlbum {
|
|||
}
|
||||
final items = AlbumStaticProvider.of(album).items;
|
||||
|
||||
final files = await FindFile(_c)(
|
||||
final files = await FindFileDescriptor(_c)(
|
||||
account,
|
||||
items
|
||||
.whereType<AlbumFileItem>()
|
||||
.map((i) => i.file.fileId)
|
||||
.map((i) => i.file.fdId)
|
||||
.whereNotNull()
|
||||
.toList(),
|
||||
onFileNotFound: (_) {},
|
||||
|
@ -40,19 +38,18 @@ class ResyncAlbum {
|
|||
return items.map((i) {
|
||||
if (i is AlbumFileItem) {
|
||||
try {
|
||||
if (i.file.fileId! == nextFile?.fileId) {
|
||||
final newItem = i.copyWith(
|
||||
file: nextFile,
|
||||
);
|
||||
if (i.file.fdId == nextFile?.fdId) {
|
||||
final newItem = i.copyWith(file: nextFile);
|
||||
nextFile = fileIt.moveNext() ? fileIt.current : null;
|
||||
return newItem;
|
||||
} else {
|
||||
_log.warning("[call] File not found: ${logFilename(i.file.path)}");
|
||||
_log.warning(
|
||||
"[call] File not found: ${logFilename(i.file.fdPath)}");
|
||||
return i;
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
_log.shout(
|
||||
"[call] Failed syncing file in album: ${logFilename(i.file.path)}",
|
||||
"[call] Failed syncing file in album: ${logFilename(i.file.fdPath)}",
|
||||
e,
|
||||
stackTrace);
|
||||
return i;
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/album/item.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/exception.dart';
|
||||
|
||||
class UpdateAlbum {
|
||||
UpdateAlbum(this.albumRepo);
|
||||
const UpdateAlbum(this.albumRepo);
|
||||
|
||||
Future<void> call(Account account, Album album) async {
|
||||
if (album.savedVersion > Album.version) {
|
||||
|
@ -13,23 +11,7 @@ class UpdateAlbum {
|
|||
throw AlbumDowngradeException(
|
||||
"Not allowed to downgrade album '${album.name}'");
|
||||
}
|
||||
final provider = album.provider;
|
||||
if (provider is AlbumStaticProvider) {
|
||||
await albumRepo.update(
|
||||
account,
|
||||
album.copyWith(
|
||||
provider: provider.copyWith(
|
||||
items: _minimizeItems(provider.items),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
await albumRepo.update(account, album);
|
||||
}
|
||||
}
|
||||
|
||||
List<AlbumItem> _minimizeItems(List<AlbumItem> items) {
|
||||
return items.map((e) => e is AlbumFileItem ? e.minimize() : e).toList();
|
||||
await albumRepo.update(account, album);
|
||||
}
|
||||
|
||||
final AlbumRepo albumRepo;
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:nc_photos/entity/album.dart';
|
|||
import 'package:nc_photos/entity/album/item.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/album/sort_provider.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:np_common/or_null.dart';
|
||||
|
||||
|
@ -49,7 +48,7 @@ class UpdateAlbumTime {
|
|||
.map((e) => e.file)
|
||||
.where((element) => file_util.isSupportedFormat(element))
|
||||
.first;
|
||||
latestItemTime = latestFile.bestDateTime;
|
||||
latestItemTime = latestFile.fdDateTime;
|
||||
} catch (_) {
|
||||
latestItemTime = null;
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@ class UpdateAutoAlbumCover {
|
|||
final coverFile = sortedItems
|
||||
.whereType<AlbumFileItem>()
|
||||
.map((e) => e.file)
|
||||
.where((element) => file_util.isSupportedFormat(element))
|
||||
.firstWhere((element) => element.hasPreview ?? false);
|
||||
.where(file_util.isSupportedFormat)
|
||||
.first;
|
||||
// cache the result for later use
|
||||
if ((album.coverProvider as AlbumAutoCoverProvider)
|
||||
.coverFile
|
||||
|
|
|
@ -7,7 +7,6 @@ import 'package:nc_photos/app_localizations.dart';
|
|||
import 'package:nc_photos/bloc/list_album_share_outlier.dart';
|
||||
import 'package:nc_photos/di_container.dart';
|
||||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/entity/share.dart';
|
||||
|
@ -190,7 +189,7 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
Widget _buildMissingShareeItem(
|
||||
BuildContext context, _MissingShareeItem item) {
|
||||
final Widget trailing;
|
||||
switch (_getItemStatus(item.file.path, item.shareWith)) {
|
||||
switch (_getItemStatus(item.file.fdPath, item.shareWith)) {
|
||||
case null:
|
||||
trailing = _buildFixButton(
|
||||
onPressed: () {
|
||||
|
@ -223,7 +222,7 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
|
||||
Widget _buildExtraShareItem(BuildContext context, _ExtraShareItem item) {
|
||||
final Widget trailing;
|
||||
switch (_getItemStatus(item.file.path, item.share.shareWith!)) {
|
||||
switch (_getItemStatus(item.file.fdPath, item.share.shareWith!)) {
|
||||
case null:
|
||||
trailing = _buildFixButton(
|
||||
onPressed: () {
|
||||
|
@ -254,7 +253,7 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildFileThumbnail(File file) {
|
||||
Widget _buildFileThumbnail(FileDescriptor file) {
|
||||
if (file_util.isAlbumFile(widget.account, file)) {
|
||||
return const SizedBox.square(
|
||||
dimension: 56,
|
||||
|
@ -270,8 +269,8 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
}
|
||||
}
|
||||
|
||||
String _buildFilename(File file) {
|
||||
if (widget.album.albumFile?.path.equalsIgnoreCase(file.path) == true) {
|
||||
String _buildFilename(FileDescriptor file) {
|
||||
if (widget.album.albumFile?.path.equalsIgnoreCase(file.fdPath) == true) {
|
||||
return widget.album.name;
|
||||
} else {
|
||||
return file.filename;
|
||||
|
@ -326,9 +325,9 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
// select only items that are not fixed/being fixed
|
||||
final items = _items.where((i) {
|
||||
if (i is _MissingShareeItem) {
|
||||
return _getItemStatus(i.file.path, i.shareWith) == null;
|
||||
return _getItemStatus(i.file.fdPath, i.shareWith) == null;
|
||||
} else if (i is _ExtraShareItem) {
|
||||
return _getItemStatus(i.file.path, i.share.shareWith!) == null;
|
||||
return _getItemStatus(i.file.fdPath, i.share.shareWith!) == null;
|
||||
} else {
|
||||
// ?
|
||||
return false;
|
||||
|
@ -337,10 +336,10 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
setState(() {
|
||||
for (final i in items) {
|
||||
if (i is _MissingShareeItem) {
|
||||
_setItemStatus(i.file.path, i.shareWith, _ItemStatus.processing);
|
||||
_setItemStatus(i.file.fdPath, i.shareWith, _ItemStatus.processing);
|
||||
} else if (i is _ExtraShareItem) {
|
||||
_setItemStatus(
|
||||
i.file.path, i.share.shareWith!, _ItemStatus.processing);
|
||||
i.file.fdPath, i.share.shareWith!, _ItemStatus.processing);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -372,14 +371,14 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
Future<void> _fixMissingSharee(_MissingShareeItem item) async {
|
||||
final shareRepo = ShareRepo(ShareRemoteDataSource());
|
||||
setState(() {
|
||||
_setItemStatus(item.file.path, item.shareWith, _ItemStatus.processing);
|
||||
_setItemStatus(item.file.fdPath, item.shareWith, _ItemStatus.processing);
|
||||
});
|
||||
try {
|
||||
await CreateUserShare(shareRepo)(
|
||||
widget.account, item.file, item.shareWith.raw);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_setItemStatus(item.file.path, item.shareWith, _ItemStatus.fixed);
|
||||
_setItemStatus(item.file.fdPath, item.shareWith, _ItemStatus.fixed);
|
||||
});
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
|
@ -391,7 +390,7 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
));
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_removeItemStatus(item.file.path, item.shareWith);
|
||||
_removeItemStatus(item.file.fdPath, item.shareWith);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -401,14 +400,14 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
final shareRepo = ShareRepo(ShareRemoteDataSource());
|
||||
setState(() {
|
||||
_setItemStatus(
|
||||
item.file.path, item.share.shareWith!, _ItemStatus.processing);
|
||||
item.file.fdPath, item.share.shareWith!, _ItemStatus.processing);
|
||||
});
|
||||
try {
|
||||
await RemoveShare(shareRepo)(widget.account, item.share);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_setItemStatus(
|
||||
item.file.path, item.share.shareWith!, _ItemStatus.fixed);
|
||||
item.file.fdPath, item.share.shareWith!, _ItemStatus.fixed);
|
||||
});
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
|
@ -419,7 +418,7 @@ class _AlbumShareOutlierBrowserState extends State<AlbumShareOutlierBrowser> {
|
|||
));
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_removeItemStatus(item.file.path, item.share.shareWith!);
|
||||
_removeItemStatus(item.file.fdPath, item.share.shareWith!);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -466,7 +465,7 @@ abstract class _ListItem {
|
|||
class _ExtraShareItem extends _ListItem {
|
||||
const _ExtraShareItem(this.file, this.share);
|
||||
|
||||
final File file;
|
||||
final FileDescriptor file;
|
||||
final Share share;
|
||||
}
|
||||
|
||||
|
@ -474,7 +473,7 @@ class _MissingShareeItem extends _ListItem {
|
|||
const _MissingShareeItem(
|
||||
this.file, this.shareWith, this.shareWithDisplayName);
|
||||
|
||||
final File file;
|
||||
final FileDescriptor file;
|
||||
final CiString shareWith;
|
||||
final String? shareWithDisplayName;
|
||||
}
|
||||
|
|
|
@ -178,7 +178,8 @@ Future<void> _dbUpdateExisting() async {
|
|||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2021, 2, 3, 4, 5, 6),
|
||||
file: files[1],
|
||||
file: files[1].toDescriptor(),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -258,7 +259,8 @@ Future<void> _dbUpdateShares() async {
|
|||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2021, 2, 3, 4, 5, 6),
|
||||
file: files[1],
|
||||
file: files[1].toDescriptor(),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -320,7 +322,8 @@ Future<void> _dbUpdateDeleteShares() async {
|
|||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2021, 2, 3, 4, 5, 6),
|
||||
file: files[1],
|
||||
file: files[1].toDescriptor(),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:test/test.dart';
|
|||
import '../test_util.dart' as util;
|
||||
|
||||
part 'album_test/album_upgrader_v8.dart';
|
||||
part 'album_test/album_upgrader_v9.dart';
|
||||
|
||||
void main() {
|
||||
group("Album", () {
|
||||
|
@ -93,74 +94,7 @@ void main() {
|
|||
});
|
||||
|
||||
group("AlbumStaticProvider", () {
|
||||
test("AlbumFileItem", () {
|
||||
final json = <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
},
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test2.jpg",
|
||||
},
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
Album.fromJson(
|
||||
json,
|
||||
upgraderFactory: const _NullAlbumUpgraderFactory(),
|
||||
),
|
||||
Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: File(path: "remote.php/dav/files/admin/test1.jpg"),
|
||||
),
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: File(path: "remote.php/dav/files/admin/test2.jpg"),
|
||||
),
|
||||
],
|
||||
),
|
||||
coverProvider: const AlbumAutoCoverProvider(),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
));
|
||||
});
|
||||
|
||||
test("AlbumFileItem", _fromJsonStaticProviderFileItem);
|
||||
test("AlbumLabelItem", () {
|
||||
final json = <String, dynamic>{
|
||||
"version": Album.version,
|
||||
|
@ -455,69 +389,7 @@ void main() {
|
|||
});
|
||||
|
||||
group("AlbumStaticProvider", () {
|
||||
test("AlbumFileItem", () {
|
||||
final album = Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: File(path: "remote.php/dav/files/admin/test1.jpg"),
|
||||
),
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: File(path: "remote.php/dav/files/admin/test2.jpg"),
|
||||
),
|
||||
],
|
||||
),
|
||||
coverProvider: const AlbumAutoCoverProvider(),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
);
|
||||
expect(album.toRemoteJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
},
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test2.jpg",
|
||||
},
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("AlbumFileItem", _toRemoteJsonStaticProviderFileItem);
|
||||
test("AlbumLabelItem", () {
|
||||
final album = Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
|
@ -751,69 +623,7 @@ void main() {
|
|||
});
|
||||
|
||||
group("AlbumStaticProvider", () {
|
||||
test("AlbumFileItem", () {
|
||||
final album = Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: File(path: "remote.php/dav/files/admin/test1.jpg"),
|
||||
),
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: File(path: "remote.php/dav/files/admin/test2.jpg"),
|
||||
),
|
||||
],
|
||||
),
|
||||
coverProvider: const AlbumAutoCoverProvider(),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
);
|
||||
expect(album.toAppDbJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
},
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test2.jpg",
|
||||
},
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("AlbumFileItem", _toDbJsonStaticProviderFileItem);
|
||||
test("AlbumLabelItem", () {
|
||||
final album = Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
|
@ -1829,6 +1639,304 @@ void main() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
group("AlbumUpgraderV9", () {
|
||||
group("doJson", () {
|
||||
test("non static provider", _upgradeV9JsonNonStatic);
|
||||
group("static provider", () {
|
||||
test("normal", _upgradeV9JsonStaticNormal);
|
||||
test("w/o ownerId", _upgradeV9JsonStaticNoOwnerId);
|
||||
test("other ownerId", _upgradeV9JsonStaticOtherOwnerId);
|
||||
});
|
||||
});
|
||||
group("doDb", () {
|
||||
test("non static provider", _upgradeV9DbNonStatic);
|
||||
group("static provider", () {
|
||||
test("normal", _upgradeV9DbStaticNormal);
|
||||
test("w/o ownerId", _upgradeV9DbStaticNoOwnerId);
|
||||
test("other ownerId", _upgradeV9DbStaticOtherOwnerId);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void _fromJsonStaticProviderFileItem() {
|
||||
final json = <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 1,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test2.jpg",
|
||||
"fdId": 2,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-01T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
Album.fromJson(
|
||||
json,
|
||||
upgraderFactory: const _NullAlbumUpgraderFactory(),
|
||||
),
|
||||
Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: FileDescriptor(
|
||||
fdPath: "remote.php/dav/files/admin/test1.jpg",
|
||||
fdId: 1,
|
||||
fdMime: "image/jpeg",
|
||||
fdIsArchived: false,
|
||||
fdIsFavorite: false,
|
||||
fdDateTime: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: FileDescriptor(
|
||||
fdPath: "remote.php/dav/files/admin/test2.jpg",
|
||||
fdId: 2,
|
||||
fdMime: "image/jpeg",
|
||||
fdIsArchived: false,
|
||||
fdIsFavorite: false,
|
||||
fdDateTime: DateTime.utc(2020, 1, 1, 3, 4, 5, 678, 901),
|
||||
),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
),
|
||||
coverProvider: const AlbumAutoCoverProvider(),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _toRemoteJsonStaticProviderFileItem() {
|
||||
final album = Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: FileDescriptor(
|
||||
fdPath: "remote.php/dav/files/admin/test1.jpg",
|
||||
fdId: 1,
|
||||
fdMime: "image/jpeg",
|
||||
fdIsArchived: false,
|
||||
fdIsFavorite: false,
|
||||
fdDateTime: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: FileDescriptor(
|
||||
fdPath: "remote.php/dav/files/admin/test2.jpg",
|
||||
fdId: 2,
|
||||
fdMime: "image/jpeg",
|
||||
fdIsArchived: false,
|
||||
fdIsFavorite: false,
|
||||
fdDateTime: DateTime.utc(2020, 1, 1, 3, 4, 5, 678, 901),
|
||||
),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
),
|
||||
coverProvider: const AlbumAutoCoverProvider(),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
);
|
||||
expect(album.toRemoteJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 1,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test2.jpg",
|
||||
"fdId": 2,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-01T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
void _toDbJsonStaticProviderFileItem() {
|
||||
final album = Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: FileDescriptor(
|
||||
fdPath: "remote.php/dav/files/admin/test1.jpg",
|
||||
fdId: 1,
|
||||
fdMime: "image/jpeg",
|
||||
fdIsArchived: false,
|
||||
fdIsFavorite: false,
|
||||
fdDateTime: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
file: FileDescriptor(
|
||||
fdPath: "remote.php/dav/files/admin/test2.jpg",
|
||||
fdId: 2,
|
||||
fdMime: "image/jpeg",
|
||||
fdIsArchived: false,
|
||||
fdIsFavorite: false,
|
||||
fdDateTime: DateTime.utc(2020, 1, 1, 3, 4, 5, 678, 901),
|
||||
),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
),
|
||||
coverProvider: const AlbumAutoCoverProvider(),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
);
|
||||
expect(album.toAppDbJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 1,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test2.jpg",
|
||||
"fdId": 2,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-01T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
"addedBy": "admin",
|
||||
"addedAt": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1958,19 +2066,21 @@ class _NullAlbumUpgraderFactory extends AlbumUpgraderFactory {
|
|||
const _NullAlbumUpgraderFactory();
|
||||
|
||||
@override
|
||||
buildV1() => null;
|
||||
AlbumUpgraderV1? buildV1() => null;
|
||||
@override
|
||||
buildV2() => null;
|
||||
AlbumUpgraderV2? buildV2() => null;
|
||||
@override
|
||||
buildV3() => null;
|
||||
AlbumUpgraderV3? buildV3() => null;
|
||||
@override
|
||||
buildV4() => null;
|
||||
AlbumUpgraderV4? buildV4() => null;
|
||||
@override
|
||||
buildV5() => null;
|
||||
AlbumUpgraderV5? buildV5() => null;
|
||||
@override
|
||||
buildV6() => null;
|
||||
AlbumUpgraderV6? buildV6() => null;
|
||||
@override
|
||||
buildV7() => null;
|
||||
AlbumUpgraderV7? buildV7() => null;
|
||||
@override
|
||||
AlbumUpgraderV8? buildV8() => null;
|
||||
@override
|
||||
AlbumUpgraderV9? buildV9() => null;
|
||||
}
|
||||
|
|
498
app/test/entity/album_test/album_upgrader_v9.dart
Normal file
498
app/test/entity/album_test/album_upgrader_v9.dart
Normal file
|
@ -0,0 +1,498 @@
|
|||
part of '../album_test.dart';
|
||||
|
||||
void _upgradeV9JsonNonStatic() {
|
||||
final account = util.buildAccount();
|
||||
final json = <String, dynamic>{
|
||||
"version": 9,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "tag",
|
||||
"content": <String, dynamic>{
|
||||
"tags": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.json",
|
||||
},
|
||||
};
|
||||
expect(AlbumUpgraderV9(account: account).doJson(json), json);
|
||||
}
|
||||
|
||||
void _upgradeV9JsonStaticNormal() {
|
||||
final account = util.buildAccount();
|
||||
final json = <String, dynamic>{
|
||||
"version": 9,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fileId": 1,
|
||||
"contentLength": 12345,
|
||||
"contentType": "image/jpeg",
|
||||
"lastModified": "2020-01-02T03:04:05.678901Z",
|
||||
"ownerId": "admin",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.json",
|
||||
},
|
||||
};
|
||||
expect(
|
||||
AlbumUpgraderV9(account: account).doJson(json),
|
||||
<String, dynamic>{
|
||||
"version": 9,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 1,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _upgradeV9JsonStaticNoOwnerId() {
|
||||
final account = util.buildAccount();
|
||||
final json = <String, dynamic>{
|
||||
"version": 9,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fileId": 1,
|
||||
"contentLength": 12345,
|
||||
"contentType": "image/jpeg",
|
||||
"lastModified": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.json",
|
||||
},
|
||||
};
|
||||
expect(
|
||||
AlbumUpgraderV9(account: account).doJson(json),
|
||||
<String, dynamic>{
|
||||
"version": 9,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 1,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _upgradeV9JsonStaticOtherOwnerId() {
|
||||
final account = util.buildAccount();
|
||||
final json = <String, dynamic>{
|
||||
"version": 9,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fileId": 1,
|
||||
"contentLength": 12345,
|
||||
"contentType": "image/jpeg",
|
||||
"lastModified": "2020-01-02T03:04:05.678901Z",
|
||||
"ownerId": "user1",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.json",
|
||||
},
|
||||
};
|
||||
expect(
|
||||
AlbumUpgraderV9(account: account).doJson(json),
|
||||
<String, dynamic>{
|
||||
"version": 9,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"provider": <String, dynamic>{
|
||||
"type": "static",
|
||||
"content": <String, dynamic>{
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 1,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "user1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"sortProvider": <String, dynamic>{
|
||||
"type": "null",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.json",
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _upgradeV9DbNonStatic() {
|
||||
final account = util.buildAccount();
|
||||
final dbObj = DbAlbum(
|
||||
fileId: 1,
|
||||
fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5",
|
||||
version: 9,
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test1",
|
||||
providerType: "tag",
|
||||
providerContent: {"tags": []},
|
||||
coverProviderType: "auto",
|
||||
coverProviderContent: {},
|
||||
sortProviderType: "null",
|
||||
sortProviderContent: {},
|
||||
shares: [],
|
||||
);
|
||||
expect(
|
||||
AlbumUpgraderV9(account: account).doDb(dbObj),
|
||||
DbAlbum(
|
||||
fileId: 1,
|
||||
fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5",
|
||||
version: 9,
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test1",
|
||||
providerType: "tag",
|
||||
providerContent: {"tags": []},
|
||||
coverProviderType: "auto",
|
||||
coverProviderContent: {},
|
||||
sortProviderType: "null",
|
||||
sortProviderContent: {},
|
||||
shares: [],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _upgradeV9DbStaticNormal() {
|
||||
final account = util.buildAccount();
|
||||
final dbObj = DbAlbum(
|
||||
fileId: 1,
|
||||
fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5",
|
||||
version: 9,
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test1",
|
||||
providerType: "static",
|
||||
providerContent: {
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fileId": 2,
|
||||
"contentLength": 12345,
|
||||
"contentType": "image/jpeg",
|
||||
"lastModified": "2020-01-02T03:04:05.678901Z",
|
||||
"ownerId": "admin",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
coverProviderType: "auto",
|
||||
coverProviderContent: {},
|
||||
sortProviderType: "null",
|
||||
sortProviderContent: {},
|
||||
shares: [],
|
||||
);
|
||||
expect(
|
||||
AlbumUpgraderV9(account: account).doDb(dbObj),
|
||||
DbAlbum(
|
||||
fileId: 1,
|
||||
fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5",
|
||||
version: 9,
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test1",
|
||||
providerType: "static",
|
||||
providerContent: {
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 2,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
coverProviderType: "auto",
|
||||
coverProviderContent: {},
|
||||
sortProviderType: "null",
|
||||
sortProviderContent: {},
|
||||
shares: [],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _upgradeV9DbStaticNoOwnerId() {
|
||||
final account = util.buildAccount();
|
||||
final dbObj = DbAlbum(
|
||||
fileId: 1,
|
||||
fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5",
|
||||
version: 9,
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test1",
|
||||
providerType: "static",
|
||||
providerContent: {
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fileId": 2,
|
||||
"contentLength": 12345,
|
||||
"contentType": "image/jpeg",
|
||||
"lastModified": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
coverProviderType: "auto",
|
||||
coverProviderContent: {},
|
||||
sortProviderType: "null",
|
||||
sortProviderContent: {},
|
||||
shares: [],
|
||||
);
|
||||
expect(
|
||||
AlbumUpgraderV9(account: account).doDb(dbObj),
|
||||
DbAlbum(
|
||||
fileId: 1,
|
||||
fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5",
|
||||
version: 9,
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test1",
|
||||
providerType: "static",
|
||||
providerContent: {
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 2,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "admin",
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
coverProviderType: "auto",
|
||||
coverProviderContent: {},
|
||||
sortProviderType: "null",
|
||||
sortProviderContent: {},
|
||||
shares: [],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _upgradeV9DbStaticOtherOwnerId() {
|
||||
final account = util.buildAccount();
|
||||
final dbObj = DbAlbum(
|
||||
fileId: 1,
|
||||
fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5",
|
||||
version: 9,
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test1",
|
||||
providerType: "static",
|
||||
providerContent: {
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fileId": 2,
|
||||
"contentLength": 12345,
|
||||
"contentType": "image/jpeg",
|
||||
"lastModified": "2020-01-02T03:04:05.678901Z",
|
||||
"ownerId": "user1",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
coverProviderType: "auto",
|
||||
coverProviderContent: {},
|
||||
sortProviderType: "null",
|
||||
sortProviderContent: {},
|
||||
shares: [],
|
||||
);
|
||||
expect(
|
||||
AlbumUpgraderV9(account: account).doDb(dbObj),
|
||||
DbAlbum(
|
||||
fileId: 1,
|
||||
fileEtag: "8a3e0799b6f0711c23cc2d93950eceb5",
|
||||
version: 9,
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test1",
|
||||
providerType: "static",
|
||||
providerContent: {
|
||||
"items": [
|
||||
<String, dynamic>{
|
||||
"type": "file",
|
||||
"content": <String, dynamic>{
|
||||
"file": <String, dynamic>{
|
||||
"fdPath": "remote.php/dav/files/admin/test1.jpg",
|
||||
"fdId": 2,
|
||||
"fdMime": "image/jpeg",
|
||||
"fdIsArchived": false,
|
||||
"fdIsFavorite": false,
|
||||
"fdDateTime": "2020-01-02T03:04:05.678901Z",
|
||||
},
|
||||
"ownerId": "user1",
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
coverProviderType: "auto",
|
||||
coverProviderContent: {},
|
||||
sortProviderType: "null",
|
||||
sortProviderContent: {},
|
||||
shares: [],
|
||||
),
|
||||
);
|
||||
}
|
|
@ -57,13 +57,13 @@ class MockAlbumMemoryRepo extends MockAlbumRepo {
|
|||
]) : albums = initialData.map((a) => a.copyWith()).toList();
|
||||
|
||||
@override
|
||||
get(Account account, File albumFile) async {
|
||||
Future<Album> get(Account account, File albumFile) async {
|
||||
return albums.firstWhere((element) =>
|
||||
element.albumFile?.compareServerIdentity(albumFile) == true);
|
||||
}
|
||||
|
||||
@override
|
||||
getAll(Account account, List<File> albumFiles) async* {
|
||||
Stream<dynamic> getAll(Account account, List<File> albumFiles) async* {
|
||||
final results = await waitOr(
|
||||
albumFiles.map((f) => get(account, f)),
|
||||
(error, stackTrace) => ExceptionEvent(error, stackTrace),
|
||||
|
@ -74,7 +74,7 @@ class MockAlbumMemoryRepo extends MockAlbumRepo {
|
|||
}
|
||||
|
||||
@override
|
||||
update(Account account, Album album) async {
|
||||
Future<void> update(Account account, Album album) async {
|
||||
final i = albums.indexWhere((element) =>
|
||||
element.albumFile?.compareServerIdentity(album.albumFile!) == true);
|
||||
albums[i] = album;
|
||||
|
@ -373,7 +373,7 @@ class MockFileMemoryRepo2 extends BasicFileRepo {
|
|||
/// Mock of [ShareRepo] where all methods will throw UnimplementedError
|
||||
class MockShareRepo implements ShareRepo {
|
||||
@override
|
||||
Future<Share> create(Account account, File file, String shareWith) {
|
||||
Future<Share> create(Account account, FileDescriptor file, String shareWith) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
@ -393,7 +393,7 @@ class MockShareRepo implements ShareRepo {
|
|||
@override
|
||||
Future<List<Share>> list(
|
||||
Account account,
|
||||
File file, {
|
||||
FileDescriptor file, {
|
||||
bool? isIncludeReshare,
|
||||
}) {
|
||||
throw UnimplementedError();
|
||||
|
@ -429,13 +429,13 @@ class MockShareMemoryRepo extends MockShareRepo {
|
|||
}
|
||||
|
||||
@override
|
||||
list(
|
||||
Future<List<Share>> list(
|
||||
Account account,
|
||||
File file, {
|
||||
FileDescriptor file, {
|
||||
bool? isIncludeReshare,
|
||||
}) async {
|
||||
return shares.where((s) {
|
||||
if (s.itemSource != file.fileId) {
|
||||
if (s.itemSource != file.fdId) {
|
||||
return false;
|
||||
} else if (isIncludeReshare == true || s.uidOwner == account.userId) {
|
||||
return true;
|
||||
|
@ -446,18 +446,19 @@ class MockShareMemoryRepo extends MockShareRepo {
|
|||
}
|
||||
|
||||
@override
|
||||
create(Account account, File file, String shareWith) async {
|
||||
Future<Share> create(
|
||||
Account account, FileDescriptor file, String shareWith) async {
|
||||
final share = Share(
|
||||
id: (_id++).toString(),
|
||||
shareType: ShareType.user,
|
||||
stime: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
uidOwner: account.userId,
|
||||
displaynameOwner: account.username2,
|
||||
uidFileOwner: file.ownerId!,
|
||||
uidFileOwner: account.userId,
|
||||
path: file.strippedPath,
|
||||
itemType: ShareItemType.file,
|
||||
mimeType: file.contentType ?? "",
|
||||
itemSource: file.fileId!,
|
||||
mimeType: file.fdMime ?? "",
|
||||
itemSource: file.fdId,
|
||||
shareWith: shareWith.toCi(),
|
||||
shareWithDisplayName: shareWith,
|
||||
);
|
||||
|
|
|
@ -201,8 +201,7 @@ class AlbumBuilder {
|
|||
Album build() {
|
||||
final latestFileItem = items
|
||||
.whereType<AlbumFileItem>()
|
||||
.stableSorted(
|
||||
(a, b) => a.file.lastModified!.compareTo(b.file.lastModified!))
|
||||
.stableSorted((a, b) => a.file.fdDateTime.compareTo(b.file.fdDateTime))
|
||||
.reversed
|
||||
.firstOrNull;
|
||||
return Album(
|
||||
|
@ -210,7 +209,7 @@ class AlbumBuilder {
|
|||
name: name,
|
||||
provider: AlbumStaticProvider(
|
||||
items: items,
|
||||
latestItemTime: latestFileItem?.file.lastModified,
|
||||
latestItemTime: latestFileItem?.file.fdDateTime,
|
||||
),
|
||||
coverProvider: cover == null
|
||||
? AlbumAutoCoverProvider(coverFile: latestFileItem?.file)
|
||||
|
@ -233,15 +232,17 @@ class AlbumBuilder {
|
|||
/// If [isCover] is true, the coverProvider of the album will become
|
||||
/// [AlbumManualCoverProvider]
|
||||
void addFileItem(
|
||||
File file, {
|
||||
FileDescriptor file, {
|
||||
String addedBy = "admin",
|
||||
DateTime? addedAt,
|
||||
bool isCover = false,
|
||||
String? ownerId,
|
||||
}) {
|
||||
final fileItem = AlbumFileItem(
|
||||
file: file,
|
||||
addedBy: addedBy.toCi(),
|
||||
addedAt: addedAt ?? file.lastModified!,
|
||||
addedAt: addedAt ?? file.fdDateTime,
|
||||
ownerId: ownerId?.toCi() ?? file.as<File>()?.ownerId ?? addedBy.toCi(),
|
||||
);
|
||||
items.add(fileItem);
|
||||
if (isCover) {
|
||||
|
@ -272,7 +273,7 @@ class AlbumBuilder {
|
|||
final String ownerId;
|
||||
|
||||
final items = <AlbumItem>[];
|
||||
File? cover;
|
||||
FileDescriptor? cover;
|
||||
final shares = <AlbumShare>[];
|
||||
}
|
||||
|
||||
|
|
|
@ -76,14 +76,13 @@ Future<void> _addFile() async {
|
|||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
file: file,
|
||||
).minimize(),
|
||||
file: file.toDescriptor(),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
latestItemTime: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: file,
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(coverFile: file.toDescriptor()),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
albumFile: albumFile,
|
||||
),
|
||||
|
@ -104,13 +103,13 @@ Future<void> _addExistingFile() async {
|
|||
lastModified: DateTime.utc(2019, 1, 2, 3, 4, 5),
|
||||
))
|
||||
.build();
|
||||
final oldFile = files[0].toDescriptor();
|
||||
final album = (util.AlbumBuilder()
|
||||
..addFileItem(
|
||||
files[0],
|
||||
oldFile,
|
||||
addedAt: clock.now().toUtc(),
|
||||
))
|
||||
.build();
|
||||
final oldFile = files[0];
|
||||
final newFile = files[0].copyWith();
|
||||
final albumFile = album.albumFile!;
|
||||
final c = DiContainer(
|
||||
|
@ -142,12 +141,15 @@ Future<void> _addExistingFile() async {
|
|||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
file: files[0],
|
||||
file: files[0].toDescriptor(),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
latestItemTime: DateTime.utc(2019, 1, 2, 3, 4, 5),
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(coverFile: files[0]),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: files[0].toDescriptor(),
|
||||
),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
albumFile: albumFile,
|
||||
),
|
||||
|
@ -156,23 +158,27 @@ Future<void> _addExistingFile() async {
|
|||
// when there's a conflict, it's guaranteed that the original file in the
|
||||
// album is kept and the incoming file dropped
|
||||
expect(
|
||||
identical(
|
||||
AlbumStaticProvider.of(c.albumMemoryRepo.albums[0])
|
||||
.items
|
||||
.whereType<AlbumFileItem>()
|
||||
.first
|
||||
.file,
|
||||
oldFile),
|
||||
true);
|
||||
identical(
|
||||
AlbumStaticProvider.of(c.albumMemoryRepo.albums[0])
|
||||
.items
|
||||
.whereType<AlbumFileItem>()
|
||||
.first
|
||||
.file,
|
||||
oldFile,
|
||||
),
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
identical(
|
||||
AlbumStaticProvider.of(c.albumMemoryRepo.albums[0])
|
||||
.items
|
||||
.whereType<AlbumFileItem>()
|
||||
.first
|
||||
.file,
|
||||
newFile),
|
||||
false);
|
||||
identical(
|
||||
AlbumStaticProvider.of(c.albumMemoryRepo.albums[0])
|
||||
.items
|
||||
.whereType<AlbumFileItem>()
|
||||
.first
|
||||
.file,
|
||||
newFile,
|
||||
),
|
||||
false,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -189,7 +195,8 @@ Future<void> _addExistingSharedFile() async {
|
|||
final user1Files = [
|
||||
files[0].copyWith(path: "remote.php/dav/files/user1/test1.jpg")
|
||||
];
|
||||
final album = (util.AlbumBuilder()..addFileItem(files[0])).build();
|
||||
final album =
|
||||
(util.AlbumBuilder()..addFileItem(files[0].toDescriptor())).build();
|
||||
final albumFile = album.albumFile!;
|
||||
final c = DiContainer(
|
||||
fileRepo: MockFileMemoryRepo(),
|
||||
|
@ -222,12 +229,15 @@ Future<void> _addExistingSharedFile() async {
|
|||
AlbumFileItem(
|
||||
addedBy: "admin".toCi(),
|
||||
addedAt: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
file: files[0],
|
||||
file: files[0].toDescriptor(),
|
||||
ownerId: "admin".toCi(),
|
||||
),
|
||||
],
|
||||
latestItemTime: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(coverFile: files[0]),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: files[0].toDescriptor(),
|
||||
),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
albumFile: albumFile,
|
||||
),
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:nc_photos/entity/album.dart';
|
|||
import 'package:nc_photos/entity/album/cover_provider.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/album/sort_provider.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/use_case/album/remove_from_album.dart';
|
||||
import 'package:np_common/or_null.dart';
|
||||
import 'package:np_db_sqlite/np_db_sqlite_compat.dart' as compat;
|
||||
|
@ -45,7 +46,8 @@ Future<void> _removeLastFile() async {
|
|||
final account = util.buildAccount();
|
||||
final files =
|
||||
(util.FilesBuilder(initialFileId: 1)..addJpeg("admin/test1.jpg")).build();
|
||||
final album = (util.AlbumBuilder()..addFileItem(files[0])).build();
|
||||
final album =
|
||||
(util.AlbumBuilder()..addFileItem(files[0].toDescriptor())).build();
|
||||
final file1 = files[0];
|
||||
final fileItem1 = util.AlbumBuilder.fileItemsOf(album)[0];
|
||||
final albumFile = album.albumFile!;
|
||||
|
@ -94,9 +96,9 @@ Future<void> _remove1OfNFiles() async {
|
|||
..addJpeg("admin/test3.jpg"))
|
||||
.build();
|
||||
final album = (util.AlbumBuilder()
|
||||
..addFileItem(files[0])
|
||||
..addFileItem(files[1])
|
||||
..addFileItem(files[2]))
|
||||
..addFileItem(files[0].toDescriptor())
|
||||
..addFileItem(files[1].toDescriptor())
|
||||
..addFileItem(files[2].toDescriptor()))
|
||||
.build();
|
||||
final fileItems = util.AlbumBuilder.fileItemsOf(album);
|
||||
final albumFile = album.albumFile!;
|
||||
|
@ -126,10 +128,12 @@ Future<void> _remove1OfNFiles() async {
|
|||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [fileItems[1].minimize(), fileItems[2].minimize()],
|
||||
items: [fileItems[1], fileItems[2]],
|
||||
latestItemTime: files[2].lastModified,
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(coverFile: files[2]),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: files[2].toDescriptor(),
|
||||
),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
albumFile: albumFile,
|
||||
),
|
||||
|
@ -151,9 +155,9 @@ Future<void> _removeLatestOfNFiles() async {
|
|||
lastModified: DateTime.utc(2020, 1, 2, 3, 4, 6)))
|
||||
.build();
|
||||
final album = (util.AlbumBuilder()
|
||||
..addFileItem(files[0])
|
||||
..addFileItem(files[1])
|
||||
..addFileItem(files[2]))
|
||||
..addFileItem(files[0].toDescriptor())
|
||||
..addFileItem(files[1].toDescriptor())
|
||||
..addFileItem(files[2].toDescriptor()))
|
||||
.build();
|
||||
final fileItems = util.AlbumBuilder.fileItemsOf(album);
|
||||
final albumFile = album.albumFile!;
|
||||
|
@ -183,10 +187,12 @@ Future<void> _removeLatestOfNFiles() async {
|
|||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [fileItems[1].minimize(), fileItems[2].minimize()],
|
||||
items: [fileItems[1], fileItems[2]],
|
||||
latestItemTime: files[1].lastModified,
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(coverFile: files[1]),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: files[1].toDescriptor(),
|
||||
),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
albumFile: albumFile,
|
||||
),
|
||||
|
@ -205,9 +211,9 @@ Future<void> _removeManualCoverFile() async {
|
|||
..addJpeg("admin/test3.jpg"))
|
||||
.build();
|
||||
final album = (util.AlbumBuilder()
|
||||
..addFileItem(files[0], isCover: true)
|
||||
..addFileItem(files[1])
|
||||
..addFileItem(files[2]))
|
||||
..addFileItem(files[0].toDescriptor(), isCover: true)
|
||||
..addFileItem(files[1].toDescriptor())
|
||||
..addFileItem(files[2].toDescriptor()))
|
||||
.build();
|
||||
final fileItems = util.AlbumBuilder.fileItemsOf(album);
|
||||
final albumFile = album.albumFile!;
|
||||
|
@ -237,10 +243,12 @@ Future<void> _removeManualCoverFile() async {
|
|||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
|
||||
name: "test",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [fileItems[1].minimize(), fileItems[2].minimize()],
|
||||
items: [fileItems[1], fileItems[2]],
|
||||
latestItemTime: files[2].lastModified,
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(coverFile: files[2]),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: files[2].toDescriptor(),
|
||||
),
|
||||
sortProvider: const AlbumNullSortProvider(),
|
||||
albumFile: albumFile,
|
||||
),
|
||||
|
@ -256,7 +264,7 @@ Future<void> _removeFromSharedAlbumOwned() async {
|
|||
final files =
|
||||
(util.FilesBuilder(initialFileId: 1)..addJpeg("admin/test1.jpg")).build();
|
||||
final album = (util.AlbumBuilder()
|
||||
..addFileItem(files[0])
|
||||
..addFileItem(files[0].toDescriptor())
|
||||
..addShare("user1"))
|
||||
.build();
|
||||
final file1 = files[0];
|
||||
|
@ -297,7 +305,7 @@ Future<void> _removeFromSharedAlbumOwnedWithOtherShare() async {
|
|||
..addJpeg("user1/test1.jpg", ownerId: "user1"))
|
||||
.build();
|
||||
final album = (util.AlbumBuilder()
|
||||
..addFileItem(files[0], addedBy: "user1")
|
||||
..addFileItem(files[0].toDescriptor(), addedBy: "user1")
|
||||
..addShare("user1")
|
||||
..addShare("user2"))
|
||||
.build();
|
||||
|
@ -349,7 +357,7 @@ Future<void> _removeFromSharedAlbumOwnedLeaveExtraShare() async {
|
|||
final files =
|
||||
(util.FilesBuilder(initialFileId: 1)..addJpeg("admin/test1.jpg")).build();
|
||||
final album = (util.AlbumBuilder()
|
||||
..addFileItem(files[0])
|
||||
..addFileItem(files[0].toDescriptor())
|
||||
..addShare("user1"))
|
||||
.build();
|
||||
final file1 = files[0];
|
||||
|
@ -392,12 +400,12 @@ Future<void> _removeFromSharedAlbumOwnedFileInOtherAlbum() async {
|
|||
final files =
|
||||
(util.FilesBuilder(initialFileId: 2)..addJpeg("admin/test1.jpg")).build();
|
||||
final album1 = (util.AlbumBuilder()
|
||||
..addFileItem(files[0])
|
||||
..addFileItem(files[0].toDescriptor())
|
||||
..addShare("user1")
|
||||
..addShare("user2"))
|
||||
.build();
|
||||
final album2 = (util.AlbumBuilder.ofId(albumId: 1)
|
||||
..addFileItem(files[0])
|
||||
..addFileItem(files[0].toDescriptor())
|
||||
..addShare("user1"))
|
||||
.build();
|
||||
final album1fileItems = util.AlbumBuilder.fileItemsOf(album1);
|
||||
|
@ -440,7 +448,7 @@ Future<void> _removeFromSharedAlbumNotOwned() async {
|
|||
final files =
|
||||
(util.FilesBuilder(initialFileId: 1)..addJpeg("admin/test1.jpg")).build();
|
||||
final album = (util.AlbumBuilder(ownerId: "user1")
|
||||
..addFileItem(files[0])
|
||||
..addFileItem(files[0].toDescriptor())
|
||||
..addShare("admin")
|
||||
..addShare("user2"))
|
||||
.build();
|
||||
|
@ -489,7 +497,7 @@ Future<void> _removeFromSharedAlbumNotOwnedWithOwnerShare() async {
|
|||
final files =
|
||||
(util.FilesBuilder(initialFileId: 1)..addJpeg("admin/test1.jpg")).build();
|
||||
final album = (util.AlbumBuilder(ownerId: "user1")
|
||||
..addFileItem(files[0])
|
||||
..addFileItem(files[0].toDescriptor())
|
||||
..addShare("admin")
|
||||
..addShare("user2"))
|
||||
.build();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:clock/clock.dart';
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
import 'package:kiwi/kiwi.dart';
|
||||
import 'package:nc_photos/use_case/album/share_album_with_user.dart';
|
||||
|
@ -97,37 +98,30 @@ Future<void> _shareWithFile() async {
|
|||
/// Expect: share (admin -> user1) added to album's shares list;
|
||||
/// new shares (admin -> user1) are created for the album json
|
||||
Future<void> _shareWithFileOwnedByUser() async {
|
||||
final account = util.buildAccount();
|
||||
final files = (util.FilesBuilder(initialFileId: 1)
|
||||
..addJpeg("admin/test1.jpg", ownerId: "user1"))
|
||||
.build();
|
||||
final album = (util.AlbumBuilder()..addFileItem(files[0])).build();
|
||||
final albumFile = album.albumFile!;
|
||||
final albumRepo = MockAlbumMemoryRepo([album]);
|
||||
final shareRepo = MockShareMemoryRepo();
|
||||
await withClock(Clock.fixed(DateTime.utc(2020, 1, 2, 3, 4, 5)), () async {
|
||||
final account = util.buildAccount();
|
||||
final files = (util.FilesBuilder(initialFileId: 1)
|
||||
..addJpeg("admin/test1.jpg", ownerId: "user1"))
|
||||
.build();
|
||||
final album = (util.AlbumBuilder()..addFileItem(files[0])).build();
|
||||
final albumFile = album.albumFile!;
|
||||
final albumRepo = MockAlbumMemoryRepo([album]);
|
||||
final shareRepo = MockShareMemoryRepo();
|
||||
|
||||
await ShareAlbumWithUser(shareRepo, albumRepo)(
|
||||
account,
|
||||
albumRepo.findAlbumByPath(albumFile.path),
|
||||
util.buildSharee(shareWith: "user1".toCi()),
|
||||
);
|
||||
expect(
|
||||
albumRepo
|
||||
.findAlbumByPath(albumFile.path)
|
||||
.shares
|
||||
?.map((s) => s.copyWith(
|
||||
// we need to set a known value to sharedAt
|
||||
sharedAt: OrNull(DateTime.utc(2020, 1, 2, 3, 4, 5)),
|
||||
))
|
||||
.toList(),
|
||||
[util.buildAlbumShare(userId: "user1")],
|
||||
);
|
||||
expect(
|
||||
shareRepo.shares,
|
||||
[
|
||||
util.buildShare(id: "0", file: albumFile, shareWith: "user1"),
|
||||
],
|
||||
);
|
||||
await ShareAlbumWithUser(shareRepo, albumRepo)(
|
||||
account,
|
||||
albumRepo.findAlbumByPath(albumFile.path),
|
||||
util.buildSharee(shareWith: "user1".toCi()),
|
||||
);
|
||||
expect(
|
||||
albumRepo.findAlbumByPath(albumFile.path).shares?.toList(),
|
||||
[util.buildAlbumShare(userId: "user1")],
|
||||
);
|
||||
expect(
|
||||
shareRepo.shares,
|
||||
[util.buildShare(id: "0", file: albumFile, shareWith: "user1")],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Share a shared album (admin -> user1) with a user (user2)
|
||||
|
|
Loading…
Reference in a new issue