import 'package:clock/clock.dart'; import 'package:collection/collection.dart'; import 'package:drift/drift.dart'; import 'package:drift/native.dart'; import 'package:flutter/foundation.dart'; import 'package:np_common/or_null.dart'; import 'package:np_db/np_db.dart'; import 'package:np_db_sqlite/src/converter.dart'; import 'package:np_db_sqlite/src/database.dart'; import 'package:np_db_sqlite/src/database_extension.dart'; import 'package:np_string/np_string.dart'; class FilesBuilder { FilesBuilder({ int initialFileId = 0, }) : fileId = initialFileId; List build() { return files.map((f) => f.copyWith()).toList(); } void add( String relativePath, { int? contentLength, String? contentType, String? etag, DateTime? lastModified, bool isCollection = false, bool hasPreview = true, bool? isFavorite, String ownerId = "admin", String? ownerDisplayName, DbImageData? imageData, DbLocation? location, }) { files.add(DbFile( fileId: fileId++, contentLength: contentLength, contentType: contentType, etag: etag, lastModified: lastModified ?? DateTime.utc(2020, 1, 2, 3, 4, 5 + files.length), isCollection: isCollection, usedBytes: null, hasPreview: hasPreview, ownerId: ownerId.toCi(), ownerDisplayName: ownerDisplayName ?? ownerId.toString(), relativePath: relativePath, isFavorite: isFavorite, isArchived: null, overrideDateTime: null, bestDateTime: _getBestDateTime( overrideDateTime: null, dateTimeOriginal: imageData?.exifDateTimeOriginal, lastModified: lastModified ?? DateTime.utc(2020, 1, 2, 3, 4, 5 + files.length), ), imageData: imageData, location: location, trashData: null, )); } void addGenericFile( String relativePath, String contentType, { int contentLength = 1024, String? etag, DateTime? lastModified, bool hasPreview = true, bool? isFavorite, String ownerId = "admin", String? ownerDisplayName, }) => add( relativePath, contentLength: contentLength, contentType: contentType, etag: etag, lastModified: lastModified, hasPreview: hasPreview, isFavorite: isFavorite, ownerId: ownerId, ownerDisplayName: ownerDisplayName, ); void addJpeg( String relativePath, { int contentLength = 1024, String? etag, DateTime? lastModified, bool hasPreview = true, bool? isFavorite, String ownerId = "admin", String? ownerDisplayName, OrNull? imageData, DbLocation? location, }) => add( relativePath, contentLength: contentLength, contentType: "image/jpeg", etag: etag, lastModified: lastModified, hasPreview: hasPreview, isFavorite: isFavorite, ownerId: ownerId, ownerDisplayName: ownerDisplayName, imageData: imageData == null ? DbImageData( lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5), fileEtag: etag, width: 640, height: 480, exif: null, exifDateTimeOriginal: null, ) : imageData.obj, location: location, ); void addDir( String relativePath, { int contentLength = 1024, String? etag, DateTime? lastModified, bool? isFavorite, String ownerId = "admin", String? ownerDisplayName, }) => add( relativePath, etag: etag, lastModified: lastModified, isCollection: true, hasPreview: false, isFavorite: isFavorite, ownerId: ownerId, ownerDisplayName: ownerDisplayName, ); void addAlbumJson( String homeDir, String filename, { int contentLength = 1024, String? etag, DateTime? lastModified, String ownerId = "admin", String? ownerDisplayName, }) => add( "$homeDir/.com.nkming.nc_photos/albums/$filename.nc_album.json", contentLength: contentLength, contentType: "application/json", etag: etag, lastModified: lastModified, hasPreview: false, ownerId: ownerId, ownerDisplayName: ownerDisplayName, ); final files = []; int fileId; } DbAccount buildAccount({ String serverAddress = "example.com", String userId = "admin", }) => DbAccount( serverAddress: serverAddress, userId: userId.toCi(), ); SqliteDb buildTestDb() { driftRuntimeOptions.debugPrint = _debugPrintSql; return SqliteDb( executor: NativeDatabase.memory( logStatements: true, ), ); } Future insertFiles( SqliteDb db, DbAccount account, Iterable files) async { final sqlAccount = await db.accountOf(ByAccount.db(account)); for (final f in files) { final sharedQuery = db.selectOnly(db.files).join([ innerJoin(db.accountFiles, db.accountFiles.file.equalsExp(db.files.rowId), useColumns: false), ]) ..addColumns([db.files.rowId]) ..where(db.accountFiles.account.equals(sqlAccount.rowId).not()) ..where(db.files.fileId.equals(f.fileId)); var rowId = (await sharedQuery.map((r) => r.read(db.files.rowId)).get()) .firstOrNull; final insert = FileConverter.toSql(f); if (rowId == null) { final dbFile = await db.into(db.files).insertReturning(insert.file.copyWith( server: Value(sqlAccount.server), )); rowId = dbFile.rowId; } final sqlAccountFile = await db .into(db.accountFiles) .insertReturning(insert.accountFile.copyWith( account: Value(sqlAccount.rowId), file: Value(rowId), )); if (insert.image != null) { await db.into(db.images).insert( insert.image!.copyWith(accountFile: Value(sqlAccountFile.rowId))); } if (insert.imageLocation != null) { await db.into(db.imageLocations).insert(insert.imageLocation! .copyWith(accountFile: Value(sqlAccountFile.rowId))); } if (insert.trash != null) { await db .into(db.trashes) .insert(insert.trash!.copyWith(file: Value(rowId))); } } } bool shouldPrintSql = false; void _debugPrintSql(String log) { if (shouldPrintSql) { debugPrint(log, wrapWidth: 1024); } } DateTime _getBestDateTime({ DateTime? overrideDateTime, DateTime? dateTimeOriginal, DateTime? lastModified, }) => overrideDateTime ?? dateTimeOriginal ?? lastModified ?? clock.now().toUtc();