mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
rework trashed assets handling
- add new table trashed_local_asset - mirror trashed assets data in trashed_local_asset. - compute checksums for assets trashed out-of-app. - restore assets present in trashed_local_asset and non-trashed in remote_asset. - simplify moving-to-trash logic based on remote_asset events.
This commit is contained in:
parent
3d56a5ca9c
commit
f7e5288173
29 changed files with 2085 additions and 876 deletions
|
|
@ -89,7 +89,8 @@ data class PlatformAsset (
|
||||||
val height: Long? = null,
|
val height: Long? = null,
|
||||||
val durationInSeconds: Long,
|
val durationInSeconds: Long,
|
||||||
val orientation: Long,
|
val orientation: Long,
|
||||||
val isFavorite: Boolean
|
val isFavorite: Boolean,
|
||||||
|
val size: Long? = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
companion object {
|
companion object {
|
||||||
|
|
@ -104,7 +105,8 @@ data class PlatformAsset (
|
||||||
val durationInSeconds = pigeonVar_list[7] as Long
|
val durationInSeconds = pigeonVar_list[7] as Long
|
||||||
val orientation = pigeonVar_list[8] as Long
|
val orientation = pigeonVar_list[8] as Long
|
||||||
val isFavorite = pigeonVar_list[9] as Boolean
|
val isFavorite = pigeonVar_list[9] as Boolean
|
||||||
return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite)
|
val size = pigeonVar_list[10] as Long?
|
||||||
|
return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun toList(): List<Any?> {
|
fun toList(): List<Any?> {
|
||||||
|
|
@ -119,6 +121,7 @@ data class PlatformAsset (
|
||||||
durationInSeconds,
|
durationInSeconds,
|
||||||
orientation,
|
orientation,
|
||||||
isFavorite,
|
isFavorite,
|
||||||
|
size,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
|
|
@ -209,6 +212,40 @@ data class SyncDelta (
|
||||||
|
|
||||||
override fun hashCode(): Int = toList().hashCode()
|
override fun hashCode(): Int = toList().hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
|
data class TrashedAssetParams (
|
||||||
|
val id: String,
|
||||||
|
val type: Long,
|
||||||
|
val albumId: String? = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
companion object {
|
||||||
|
fun fromList(pigeonVar_list: List<Any?>): TrashedAssetParams {
|
||||||
|
val id = pigeonVar_list[0] as String
|
||||||
|
val type = pigeonVar_list[1] as Long
|
||||||
|
val albumId = pigeonVar_list[2] as String?
|
||||||
|
return TrashedAssetParams(id, type, albumId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun toList(): List<Any?> {
|
||||||
|
return listOf(
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
albumId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is TrashedAssetParams) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (this === other) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return MessagesPigeonUtils.deepEquals(toList(), other.toList()) }
|
||||||
|
|
||||||
|
override fun hashCode(): Int = toList().hashCode()
|
||||||
|
}
|
||||||
private open class MessagesPigeonCodec : StandardMessageCodec() {
|
private open class MessagesPigeonCodec : StandardMessageCodec() {
|
||||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
|
|
@ -227,6 +264,11 @@ private open class MessagesPigeonCodec : StandardMessageCodec() {
|
||||||
SyncDelta.fromList(it)
|
SyncDelta.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
132.toByte() -> {
|
||||||
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
|
TrashedAssetParams.fromList(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> super.readValueOfType(type, buffer)
|
else -> super.readValueOfType(type, buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -244,6 +286,10 @@ private open class MessagesPigeonCodec : StandardMessageCodec() {
|
||||||
stream.write(131)
|
stream.write(131)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
|
is TrashedAssetParams -> {
|
||||||
|
stream.write(132)
|
||||||
|
writeValue(stream, value.toList())
|
||||||
|
}
|
||||||
else -> super.writeValue(stream, value)
|
else -> super.writeValue(stream, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -260,6 +306,8 @@ interface NativeSyncApi {
|
||||||
fun getAssetsCountSince(albumId: String, timestamp: Long): Long
|
fun getAssetsCountSince(albumId: String, timestamp: Long): Long
|
||||||
fun getAssetsForAlbum(albumId: String, updatedTimeCond: Long?): List<PlatformAsset>
|
fun getAssetsForAlbum(albumId: String, updatedTimeCond: Long?): List<PlatformAsset>
|
||||||
fun hashPaths(paths: List<String>): List<ByteArray?>
|
fun hashPaths(paths: List<String>): List<ByteArray?>
|
||||||
|
fun getTrashedAssetsForAlbum(albumId: String, updatedTimeCond: Long?): List<PlatformAsset>
|
||||||
|
fun hashTrashedAssets(trashedAssets: List<TrashedAssetParams>): List<ByteArray?>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** The codec used by NativeSyncApi. */
|
/** The codec used by NativeSyncApi. */
|
||||||
|
|
@ -418,6 +466,41 @@ interface NativeSyncApi {
|
||||||
channel.setMessageHandler(null)
|
channel.setMessageHandler(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
run {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getTrashedAssetsForAlbum$separatedMessageChannelSuffix", codec, taskQueue)
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler { message, reply ->
|
||||||
|
val args = message as List<Any?>
|
||||||
|
val albumIdArg = args[0] as String
|
||||||
|
val updatedTimeCondArg = args[1] as Long?
|
||||||
|
val wrapped: List<Any?> = try {
|
||||||
|
listOf(api.getTrashedAssetsForAlbum(albumIdArg, updatedTimeCondArg))
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
MessagesPigeonUtils.wrapError(exception)
|
||||||
|
}
|
||||||
|
reply.reply(wrapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashTrashedAssets$separatedMessageChannelSuffix", codec, taskQueue)
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler { message, reply ->
|
||||||
|
val args = message as List<Any?>
|
||||||
|
val trashedAssetsArg = args[0] as List<TrashedAssetParams>
|
||||||
|
val wrapped: List<Any?> = try {
|
||||||
|
listOf(api.hashTrashedAssets(trashedAssetsArg))
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
MessagesPigeonUtils.wrapError(exception)
|
||||||
|
}
|
||||||
|
reply.reply(wrapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,4 +21,15 @@ class NativeSyncApiImpl26(context: Context) : NativeSyncApiImplBase(context), Na
|
||||||
override fun getMediaChanges(): SyncDelta {
|
override fun getMediaChanges(): SyncDelta {
|
||||||
throw IllegalStateException("Method not supported on this Android version.")
|
throw IllegalStateException("Method not supported on this Android version.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getTrashedAssetsForAlbum(
|
||||||
|
albumId: String,
|
||||||
|
updatedTimeCond: Long?
|
||||||
|
): List<PlatformAsset> {
|
||||||
|
throw IllegalStateException("Method not supported on this Android version.")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashTrashedAssets(trashedAssets: List<TrashedAssetParams>): List<ByteArray?> {
|
||||||
|
throw IllegalStateException("Method not supported on this Android version.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
package app.alextran.immich.sync
|
package app.alextran.immich.sync
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.content.ContentUris
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.annotation.RequiresExtension
|
import androidx.annotation.RequiresExtension
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.io.BufferedInputStream
|
||||||
|
import java.security.DigestInputStream
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.Q)
|
@RequiresApi(Build.VERSION_CODES.Q)
|
||||||
@RequiresExtension(extension = Build.VERSION_CODES.R, version = 1)
|
@RequiresExtension(extension = Build.VERSION_CODES.R, version = 1)
|
||||||
|
|
@ -33,6 +40,56 @@ class NativeSyncApiImpl30(context: Context) : NativeSyncApiImplBase(context), Na
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresExtension(extension = Build.VERSION_CODES.R, version = 1)
|
||||||
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
|
override fun getTrashedAssetsForAlbum(
|
||||||
|
albumId: String,
|
||||||
|
updatedTimeCond: Long?
|
||||||
|
): List<PlatformAsset> {
|
||||||
|
val trashed = mutableListOf<PlatformAsset>()
|
||||||
|
val volumes = MediaStore.getExternalVolumeNames(ctx)
|
||||||
|
|
||||||
|
var selection = "$BUCKET_SELECTION AND $MEDIA_SELECTION"
|
||||||
|
val selectionArgs = mutableListOf(albumId, *MEDIA_SELECTION_ARGS)
|
||||||
|
|
||||||
|
if (updatedTimeCond != null) {
|
||||||
|
selection += " AND (${MediaStore.Files.FileColumns.DATE_MODIFIED} > ? OR ${MediaStore.Files.FileColumns.DATE_ADDED} > ?)"
|
||||||
|
selectionArgs.addAll(listOf(updatedTimeCond.toString(), updatedTimeCond.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (volume in volumes) {
|
||||||
|
val uri = MediaStore.Files.getContentUri(volume)
|
||||||
|
val queryArgs = Bundle().apply {
|
||||||
|
putString(ContentResolver.QUERY_ARG_SQL_SELECTION, selection)
|
||||||
|
putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs.toTypedArray())
|
||||||
|
putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.contentResolver.query(uri, ASSET_PROJECTION, queryArgs, null).use { cursor ->
|
||||||
|
getAssets(cursor).forEach { res ->
|
||||||
|
if (res is AssetResult.ValidAsset) trashed += res.asset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return trashed
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashTrashedAssets(trashedAssets: List<TrashedAssetParams>): List<ByteArray?> {
|
||||||
|
val result = ArrayList<ByteArray?>(trashedAssets.size)
|
||||||
|
for (item in trashedAssets) {
|
||||||
|
val digest = try {
|
||||||
|
val id = item.id.toLong()
|
||||||
|
val mediaType = item.type.toInt()
|
||||||
|
val uri = contentUriForType(id, mediaType)
|
||||||
|
sha1OfUri(ctx, uri)
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
result.add(digest)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
override fun shouldFullSync(): Boolean =
|
override fun shouldFullSync(): Boolean =
|
||||||
MediaStore.getVersion(ctx) != prefs.getString(SHARED_PREF_MEDIA_STORE_VERSION_KEY, null)
|
MediaStore.getVersion(ctx) != prefs.getString(SHARED_PREF_MEDIA_STORE_VERSION_KEY, null)
|
||||||
|
|
||||||
|
|
@ -86,4 +143,31 @@ class NativeSyncApiImpl30(context: Context) : NativeSyncApiImplBase(context), Na
|
||||||
// Unmounted volumes are handled in dart when the album is removed
|
// Unmounted volumes are handled in dart when the album is removed
|
||||||
return SyncDelta(hasChanges, changed, deleted, assetAlbums)
|
return SyncDelta(hasChanges, changed, deleted, assetAlbums)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun contentUriForType(id: Long, mediaType: Int): Uri {
|
||||||
|
val vol = MediaStore.VOLUME_EXTERNAL
|
||||||
|
val base = when (mediaType) {
|
||||||
|
MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE -> MediaStore.Images.Media.getContentUri(vol)
|
||||||
|
MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO -> MediaStore.Video.Media.getContentUri(vol)
|
||||||
|
MediaStore.Files.FileColumns.MEDIA_TYPE_AUDIO -> MediaStore.Audio.Media.getContentUri(vol)
|
||||||
|
else -> MediaStore.Files.getContentUri(vol)
|
||||||
|
}
|
||||||
|
return ContentUris.withAppendedId(base, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sha1OfUri(ctx: Context, uri: Uri): ByteArray? {
|
||||||
|
return try {
|
||||||
|
val md = MessageDigest.getInstance("SHA-1")
|
||||||
|
ctx.contentResolver.openInputStream(uri)?.use { input ->
|
||||||
|
DigestInputStream(BufferedInputStream(input), md).use { dis ->
|
||||||
|
val buf = ByteArray(DEFAULT_BUFFER_SIZE)
|
||||||
|
while (dis.read(buf) != -1) { /* pump */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: return null
|
||||||
|
md.digest()
|
||||||
|
} catch (_: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ open class NativeSyncApiImplBase(context: Context) {
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
||||||
add(MediaStore.MediaColumns.IS_FAVORITE)
|
add(MediaStore.MediaColumns.IS_FAVORITE)
|
||||||
}
|
}
|
||||||
|
add(MediaStore.MediaColumns.SIZE)
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
|
|
||||||
const val HASH_BUFFER_SIZE = 2 * 1024 * 1024
|
const val HASH_BUFFER_SIZE = 2 * 1024 * 1024
|
||||||
|
|
@ -82,6 +83,7 @@ open class NativeSyncApiImplBase(context: Context) {
|
||||||
val orientationColumn =
|
val orientationColumn =
|
||||||
c.getColumnIndexOrThrow(MediaStore.MediaColumns.ORIENTATION)
|
c.getColumnIndexOrThrow(MediaStore.MediaColumns.ORIENTATION)
|
||||||
val favoriteColumn = c.getColumnIndex(MediaStore.MediaColumns.IS_FAVORITE)
|
val favoriteColumn = c.getColumnIndex(MediaStore.MediaColumns.IS_FAVORITE)
|
||||||
|
val sizeColumn = c.getColumnIndex(MediaStore.MediaColumns.SIZE)
|
||||||
|
|
||||||
while (c.moveToNext()) {
|
while (c.moveToNext()) {
|
||||||
val id = c.getLong(idColumn).toString()
|
val id = c.getLong(idColumn).toString()
|
||||||
|
|
@ -111,7 +113,7 @@ open class NativeSyncApiImplBase(context: Context) {
|
||||||
val bucketId = c.getString(bucketIdColumn)
|
val bucketId = c.getString(bucketIdColumn)
|
||||||
val orientation = c.getInt(orientationColumn)
|
val orientation = c.getInt(orientationColumn)
|
||||||
val isFavorite = if (favoriteColumn == -1) false else c.getInt(favoriteColumn) != 0
|
val isFavorite = if (favoriteColumn == -1) false else c.getInt(favoriteColumn) != 0
|
||||||
|
val size = c.getLong(sizeColumn)
|
||||||
val asset = PlatformAsset(
|
val asset = PlatformAsset(
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
|
|
@ -123,6 +125,7 @@ open class NativeSyncApiImplBase(context: Context) {
|
||||||
duration,
|
duration,
|
||||||
orientation.toLong(),
|
orientation.toLong(),
|
||||||
isFavorite,
|
isFavorite,
|
||||||
|
size
|
||||||
)
|
)
|
||||||
yield(AssetResult.ValidAsset(asset, bucketId))
|
yield(AssetResult.ValidAsset(asset, bucketId))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
mobile/drift_schemas/main/drift_schema_v11.json
generated
2
mobile/drift_schemas/main/drift_schema_v11.json
generated
File diff suppressed because one or more lines are too long
|
|
@ -140,6 +140,7 @@ struct PlatformAsset: Hashable {
|
||||||
var durationInSeconds: Int64
|
var durationInSeconds: Int64
|
||||||
var orientation: Int64
|
var orientation: Int64
|
||||||
var isFavorite: Bool
|
var isFavorite: Bool
|
||||||
|
var size: Int64? = nil
|
||||||
|
|
||||||
|
|
||||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
|
|
@ -154,6 +155,7 @@ struct PlatformAsset: Hashable {
|
||||||
let durationInSeconds = pigeonVar_list[7] as! Int64
|
let durationInSeconds = pigeonVar_list[7] as! Int64
|
||||||
let orientation = pigeonVar_list[8] as! Int64
|
let orientation = pigeonVar_list[8] as! Int64
|
||||||
let isFavorite = pigeonVar_list[9] as! Bool
|
let isFavorite = pigeonVar_list[9] as! Bool
|
||||||
|
let size: Int64? = nilOrValue(pigeonVar_list[10])
|
||||||
|
|
||||||
return PlatformAsset(
|
return PlatformAsset(
|
||||||
id: id,
|
id: id,
|
||||||
|
|
@ -165,7 +167,8 @@ struct PlatformAsset: Hashable {
|
||||||
height: height,
|
height: height,
|
||||||
durationInSeconds: durationInSeconds,
|
durationInSeconds: durationInSeconds,
|
||||||
orientation: orientation,
|
orientation: orientation,
|
||||||
isFavorite: isFavorite
|
isFavorite: isFavorite,
|
||||||
|
size: size
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
func toList() -> [Any?] {
|
func toList() -> [Any?] {
|
||||||
|
|
@ -180,6 +183,7 @@ struct PlatformAsset: Hashable {
|
||||||
durationInSeconds,
|
durationInSeconds,
|
||||||
orientation,
|
orientation,
|
||||||
isFavorite,
|
isFavorite,
|
||||||
|
size,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
static func == (lhs: PlatformAsset, rhs: PlatformAsset) -> Bool {
|
static func == (lhs: PlatformAsset, rhs: PlatformAsset) -> Bool {
|
||||||
|
|
@ -267,6 +271,39 @@ struct SyncDelta: Hashable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generated class from Pigeon that represents data sent in messages.
|
||||||
|
struct TrashedAssetParams: Hashable {
|
||||||
|
var id: String
|
||||||
|
var type: Int64
|
||||||
|
var albumId: String? = nil
|
||||||
|
|
||||||
|
|
||||||
|
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||||
|
static func fromList(_ pigeonVar_list: [Any?]) -> TrashedAssetParams? {
|
||||||
|
let id = pigeonVar_list[0] as! String
|
||||||
|
let type = pigeonVar_list[1] as! Int64
|
||||||
|
let albumId: String? = nilOrValue(pigeonVar_list[2])
|
||||||
|
|
||||||
|
return TrashedAssetParams(
|
||||||
|
id: id,
|
||||||
|
type: type,
|
||||||
|
albumId: albumId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
func toList() -> [Any?] {
|
||||||
|
return [
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
albumId,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
static func == (lhs: TrashedAssetParams, rhs: TrashedAssetParams) -> Bool {
|
||||||
|
return deepEqualsMessages(lhs.toList(), rhs.toList()) }
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
deepHashMessages(value: toList(), hasher: &hasher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class MessagesPigeonCodecReader: FlutterStandardReader {
|
private class MessagesPigeonCodecReader: FlutterStandardReader {
|
||||||
override func readValue(ofType type: UInt8) -> Any? {
|
override func readValue(ofType type: UInt8) -> Any? {
|
||||||
switch type {
|
switch type {
|
||||||
|
|
@ -276,6 +313,8 @@ private class MessagesPigeonCodecReader: FlutterStandardReader {
|
||||||
return PlatformAlbum.fromList(self.readValue() as! [Any?])
|
return PlatformAlbum.fromList(self.readValue() as! [Any?])
|
||||||
case 131:
|
case 131:
|
||||||
return SyncDelta.fromList(self.readValue() as! [Any?])
|
return SyncDelta.fromList(self.readValue() as! [Any?])
|
||||||
|
case 132:
|
||||||
|
return TrashedAssetParams.fromList(self.readValue() as! [Any?])
|
||||||
default:
|
default:
|
||||||
return super.readValue(ofType: type)
|
return super.readValue(ofType: type)
|
||||||
}
|
}
|
||||||
|
|
@ -293,6 +332,9 @@ private class MessagesPigeonCodecWriter: FlutterStandardWriter {
|
||||||
} else if let value = value as? SyncDelta {
|
} else if let value = value as? SyncDelta {
|
||||||
super.writeByte(131)
|
super.writeByte(131)
|
||||||
super.writeValue(value.toList())
|
super.writeValue(value.toList())
|
||||||
|
} else if let value = value as? TrashedAssetParams {
|
||||||
|
super.writeByte(132)
|
||||||
|
super.writeValue(value.toList())
|
||||||
} else {
|
} else {
|
||||||
super.writeValue(value)
|
super.writeValue(value)
|
||||||
}
|
}
|
||||||
|
|
@ -324,6 +366,8 @@ protocol NativeSyncApi {
|
||||||
func getAssetsCountSince(albumId: String, timestamp: Int64) throws -> Int64
|
func getAssetsCountSince(albumId: String, timestamp: Int64) throws -> Int64
|
||||||
func getAssetsForAlbum(albumId: String, updatedTimeCond: Int64?) throws -> [PlatformAsset]
|
func getAssetsForAlbum(albumId: String, updatedTimeCond: Int64?) throws -> [PlatformAsset]
|
||||||
func hashPaths(paths: [String]) throws -> [FlutterStandardTypedData?]
|
func hashPaths(paths: [String]) throws -> [FlutterStandardTypedData?]
|
||||||
|
func getTrashedAssetsForAlbum(albumId: String, updatedTimeCond: Int64?) throws -> [PlatformAsset]
|
||||||
|
func hashTrashedAssets(trashedAssets: [TrashedAssetParams]) throws -> [FlutterStandardTypedData?]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||||
|
|
@ -476,5 +520,40 @@ class NativeSyncApiSetup {
|
||||||
} else {
|
} else {
|
||||||
hashPathsChannel.setMessageHandler(nil)
|
hashPathsChannel.setMessageHandler(nil)
|
||||||
}
|
}
|
||||||
|
let getTrashedAssetsForAlbumChannel = taskQueue == nil
|
||||||
|
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getTrashedAssetsForAlbum\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||||
|
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getTrashedAssetsForAlbum\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
|
||||||
|
if let api = api {
|
||||||
|
getTrashedAssetsForAlbumChannel.setMessageHandler { message, reply in
|
||||||
|
let args = message as! [Any?]
|
||||||
|
let albumIdArg = args[0] as! String
|
||||||
|
let updatedTimeCondArg: Int64? = nilOrValue(args[1])
|
||||||
|
do {
|
||||||
|
let result = try api.getTrashedAssetsForAlbum(albumId: albumIdArg, updatedTimeCond: updatedTimeCondArg)
|
||||||
|
reply(wrapResult(result))
|
||||||
|
} catch {
|
||||||
|
reply(wrapError(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
getTrashedAssetsForAlbumChannel.setMessageHandler(nil)
|
||||||
|
}
|
||||||
|
let hashTrashedAssetsChannel = taskQueue == nil
|
||||||
|
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashTrashedAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||||
|
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashTrashedAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
|
||||||
|
if let api = api {
|
||||||
|
hashTrashedAssetsChannel.setMessageHandler { message, reply in
|
||||||
|
let args = message as! [Any?]
|
||||||
|
let trashedAssetsArg = args[0] as! [TrashedAssetParams]
|
||||||
|
do {
|
||||||
|
let result = try api.hashTrashedAssets(trashedAssets: trashedAssetsArg)
|
||||||
|
reply(wrapResult(result))
|
||||||
|
} catch {
|
||||||
|
reply(wrapError(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hashTrashedAssetsChannel.setMessageHandler(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
76
mobile/lib/domain/models/asset/trashed_asset.model.dart
Normal file
76
mobile/lib/domain/models/asset/trashed_asset.model.dart
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
|
||||||
|
class TrashedAsset {
|
||||||
|
final String id;
|
||||||
|
final String name;
|
||||||
|
final String albumId;
|
||||||
|
final String? checksum;
|
||||||
|
final AssetType type;
|
||||||
|
final DateTime createdAt;
|
||||||
|
final DateTime updatedAt;
|
||||||
|
final int? size;
|
||||||
|
|
||||||
|
const TrashedAsset({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.checksum,
|
||||||
|
required this.albumId,
|
||||||
|
required this.type,
|
||||||
|
required this.createdAt,
|
||||||
|
required this.updatedAt,
|
||||||
|
this.size,
|
||||||
|
});
|
||||||
|
|
||||||
|
TrashedAsset copyWith({
|
||||||
|
String? id,
|
||||||
|
String? name,
|
||||||
|
String? albumId,
|
||||||
|
String? checksum,
|
||||||
|
AssetType? type,
|
||||||
|
DateTime? createdAt,
|
||||||
|
DateTime? updatedAt,
|
||||||
|
int? size,
|
||||||
|
}) {
|
||||||
|
return TrashedAsset(
|
||||||
|
id: id ?? this.id,
|
||||||
|
name: name ?? this.name,
|
||||||
|
albumId: albumId ?? this.albumId,
|
||||||
|
checksum: checksum ?? this.checksum,
|
||||||
|
type: type ?? this.type,
|
||||||
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
|
size: size ?? this.size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'TrashedAsset('
|
||||||
|
'id: $id, '
|
||||||
|
'name: $name, '
|
||||||
|
'albumId: $albumId, '
|
||||||
|
'checksum: $checksum, '
|
||||||
|
'type: $type, '
|
||||||
|
'createdAt: $createdAt, '
|
||||||
|
'updatedAt: $updatedAt, '
|
||||||
|
'size: ${size ?? "<NA>"}'
|
||||||
|
')';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is TrashedAsset &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
id == other.id &&
|
||||||
|
name == other.name &&
|
||||||
|
albumId == other.albumId &&
|
||||||
|
checksum == other.checksum &&
|
||||||
|
type == other.type &&
|
||||||
|
createdAt == other.createdAt &&
|
||||||
|
updatedAt == other.updatedAt &&
|
||||||
|
size == other.size;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(id, name, albumId, checksum, type, createdAt, updatedAt, size);
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,8 @@ import 'dart:convert';
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/asset/trashed_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/services/trash_sync.service.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||||
|
|
@ -16,6 +18,7 @@ class HashService {
|
||||||
final DriftLocalAssetRepository _localAssetRepository;
|
final DriftLocalAssetRepository _localAssetRepository;
|
||||||
final StorageRepository _storageRepository;
|
final StorageRepository _storageRepository;
|
||||||
final NativeSyncApi _nativeSyncApi;
|
final NativeSyncApi _nativeSyncApi;
|
||||||
|
final TrashSyncService _trashSyncService;
|
||||||
final bool Function()? _cancelChecker;
|
final bool Function()? _cancelChecker;
|
||||||
final _log = Logger('HashService');
|
final _log = Logger('HashService');
|
||||||
|
|
||||||
|
|
@ -24,6 +27,7 @@ class HashService {
|
||||||
required DriftLocalAssetRepository localAssetRepository,
|
required DriftLocalAssetRepository localAssetRepository,
|
||||||
required StorageRepository storageRepository,
|
required StorageRepository storageRepository,
|
||||||
required NativeSyncApi nativeSyncApi,
|
required NativeSyncApi nativeSyncApi,
|
||||||
|
required TrashSyncService trashSyncService,
|
||||||
bool Function()? cancelChecker,
|
bool Function()? cancelChecker,
|
||||||
this.batchSizeLimit = kBatchHashSizeLimit,
|
this.batchSizeLimit = kBatchHashSizeLimit,
|
||||||
this.batchFileLimit = kBatchHashFileLimit,
|
this.batchFileLimit = kBatchHashFileLimit,
|
||||||
|
|
@ -31,7 +35,8 @@ class HashService {
|
||||||
_localAssetRepository = localAssetRepository,
|
_localAssetRepository = localAssetRepository,
|
||||||
_storageRepository = storageRepository,
|
_storageRepository = storageRepository,
|
||||||
_cancelChecker = cancelChecker,
|
_cancelChecker = cancelChecker,
|
||||||
_nativeSyncApi = nativeSyncApi;
|
_nativeSyncApi = nativeSyncApi,
|
||||||
|
_trashSyncService = trashSyncService;
|
||||||
|
|
||||||
bool get isCancelled => _cancelChecker?.call() ?? false;
|
bool get isCancelled => _cancelChecker?.call() ?? false;
|
||||||
|
|
||||||
|
|
@ -55,6 +60,20 @@ class HashService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_trashSyncService.isAutoSyncMode) {
|
||||||
|
final backupAlbums = await _localAlbumRepository.getBackupAlbums();
|
||||||
|
for (final album in backupAlbums) {
|
||||||
|
if (isCancelled) {
|
||||||
|
_log.warning("Hashing cancelled. Stopped processing albums.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
final trashedToHash = await _trashSyncService.getAssetsToHash(album.id);
|
||||||
|
if (trashedToHash.isNotEmpty) {
|
||||||
|
await _hashTrashedAssets(album, trashedToHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stopwatch.stop();
|
stopwatch.stop();
|
||||||
_log.info("Hashing took - ${stopwatch.elapsedMilliseconds}ms");
|
_log.info("Hashing took - ${stopwatch.elapsedMilliseconds}ms");
|
||||||
}
|
}
|
||||||
|
|
@ -130,6 +149,130 @@ class HashService {
|
||||||
await _localAssetRepository.updateHashes(hashed);
|
await _localAssetRepository.updateHashes(hashed);
|
||||||
await _storageRepository.clearCache();
|
await _storageRepository.clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _hashTrashedAssets(LocalAlbum album, Iterable<TrashedAsset> assetsToHash) async {
|
||||||
|
int bytesProcessed = 0;
|
||||||
|
final toHash = <TrashedAsset>[];
|
||||||
|
|
||||||
|
for (final asset in assetsToHash) {
|
||||||
|
if (isCancelled) {
|
||||||
|
_log.warning("Hashing cancelled. Stopped processing assets.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asset.size == null) {
|
||||||
|
_log.warning(
|
||||||
|
"Cannot get size for asset ${asset.id}, name: ${asset.name}, created on: ${asset.createdAt} from album: ${album.name}",
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesProcessed += asset.size!;
|
||||||
|
toHash.add(asset);
|
||||||
|
|
||||||
|
if (toHash.length >= batchFileLimit || bytesProcessed >= batchSizeLimit) {
|
||||||
|
await _processTrashedBatch(album, toHash);
|
||||||
|
toHash.clear();
|
||||||
|
bytesProcessed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await _processTrashedBatch(album, toHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _processTrashedBatch(LocalAlbum album, List<TrashedAsset> toHash) async {
|
||||||
|
if (toHash.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_log.fine("Hashing ${toHash.length} trashed files");
|
||||||
|
|
||||||
|
final params = toHash.map((e) => TrashedAssetParams(id: e.id, type: e.type.index, albumId: album.id)).toList();
|
||||||
|
final hashes = await _nativeSyncApi.hashTrashedAssets(params);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
hashes.length == toHash.length,
|
||||||
|
"Trashed Assets, Hashes length does not match toHash length: ${hashes.length} != ${toHash.length}",
|
||||||
|
);
|
||||||
|
final hashed = <TrashedAsset>[];
|
||||||
|
|
||||||
|
for (int i = 0; i < hashes.length; i++) {
|
||||||
|
if (isCancelled) {
|
||||||
|
_log.warning("Hashing cancelled. Stopped processing batch.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final hash = hashes[i];
|
||||||
|
final asset = toHash[i];
|
||||||
|
if (hash?.length == 20) {
|
||||||
|
hashed.add(asset.copyWith(checksum: base64.encode(hash!)));
|
||||||
|
} else {
|
||||||
|
_log.warning(
|
||||||
|
"Failed to hash trashed file for ${asset.id}: ${asset.name} created at ${asset.createdAt} from album: ${album.name}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_log.fine("Hashed ${hashed.length}/${toHash.length} trashed assets");
|
||||||
|
await _trashSyncService.updateChecksums(hashed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future<void> _hashTrashedAssets(LocalAlbum album, Iterable<TrashedAsset> assetsToHash) async {
|
||||||
|
// final trashedAssets = assetsToHash
|
||||||
|
// .map((e) => TrashedAssetParams(id: e.id, type: e.type.index, albumId: album.id))
|
||||||
|
// .toList();
|
||||||
|
//
|
||||||
|
// final byId = <String, LocalAsset>{for (final a in assetsToHash) a.id: a};
|
||||||
|
//
|
||||||
|
// final hashed = <LocalAsset>[];
|
||||||
|
// const chunkSize = 10;
|
||||||
|
//
|
||||||
|
// for (int i = 0; i < trashedAssets.length; i += chunkSize) {
|
||||||
|
// if (isCancelled) {
|
||||||
|
// _log.warning("Hashing cancelled. Stopped processing assets.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// final end = (i + chunkSize <= trashedAssets.length) ? i + chunkSize : trashedAssets.length;
|
||||||
|
// final batch = trashedAssets.sublist(i, end);
|
||||||
|
//
|
||||||
|
// List<Uint8List?> hashes;
|
||||||
|
// try {
|
||||||
|
// hashes = await _nativeSyncApi.hashTrashedAssets(batch);
|
||||||
|
// } catch (e, s) {
|
||||||
|
// _log.severe("hashTrashedAssets failed for batch [$i..${end - 1}]: $e", e, s);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (hashes.length != batch.length) {
|
||||||
|
// _log.warning(
|
||||||
|
// "hashTrashedAssets returned ${hashes.length} hashes for ${batch.length} assets (batch [$i..${end - 1}]).",
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// final limit = hashes.length < batch.length ? hashes.length : batch.length;
|
||||||
|
// for (int j = 0; j < limit; j++) {
|
||||||
|
// if (isCancelled) {
|
||||||
|
// _log.warning("Hashing cancelled. Stopped processing assets.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// final asset = batch[j];
|
||||||
|
// final hash = hashes[j];
|
||||||
|
//
|
||||||
|
// if (hash != null && hash.length == 20) {
|
||||||
|
// final localAsset = byId[asset.id];
|
||||||
|
// if (localAsset != null) {
|
||||||
|
// hashed.add(localAsset.copyWith(checksum: base64.encode(hash)));
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// _log.warning("Failed to hash file for ${asset.id} from album: ${album.name}");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// _log.warning("updateHashes for album: ${album.name}, assets: ${hashed.map((e) => '${e.name}-${e.checksum}')}");
|
||||||
|
//
|
||||||
|
// await _trashSyncService.updateHashes(hashed);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AssetToPath {
|
class _AssetToPath {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/services/trash_sync.service.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||||
import 'package:immich_mobile/utils/datetime_helpers.dart';
|
import 'package:immich_mobile/utils/datetime_helpers.dart';
|
||||||
|
|
@ -14,14 +15,17 @@ import 'package:platform/platform.dart';
|
||||||
class LocalSyncService {
|
class LocalSyncService {
|
||||||
final DriftLocalAlbumRepository _localAlbumRepository;
|
final DriftLocalAlbumRepository _localAlbumRepository;
|
||||||
final NativeSyncApi _nativeSyncApi;
|
final NativeSyncApi _nativeSyncApi;
|
||||||
|
final TrashSyncService _trashSyncService;
|
||||||
final Platform _platform;
|
final Platform _platform;
|
||||||
final Logger _log = Logger("DeviceSyncService");
|
final Logger _log = Logger("DeviceSyncService");
|
||||||
|
|
||||||
LocalSyncService({
|
LocalSyncService({
|
||||||
required DriftLocalAlbumRepository localAlbumRepository,
|
required DriftLocalAlbumRepository localAlbumRepository,
|
||||||
|
required TrashSyncService trashSyncService,
|
||||||
required NativeSyncApi nativeSyncApi,
|
required NativeSyncApi nativeSyncApi,
|
||||||
Platform? platform,
|
Platform? platform,
|
||||||
}) : _localAlbumRepository = localAlbumRepository,
|
}) : _localAlbumRepository = localAlbumRepository,
|
||||||
|
_trashSyncService = trashSyncService,
|
||||||
_nativeSyncApi = nativeSyncApi,
|
_nativeSyncApi = nativeSyncApi,
|
||||||
_platform = platform ?? const LocalPlatform();
|
_platform = platform ?? const LocalPlatform();
|
||||||
|
|
||||||
|
|
@ -74,7 +78,10 @@ class LocalSyncService {
|
||||||
await updateAlbum(dbAlbum, album);
|
await updateAlbum(dbAlbum, album);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_trashSyncService.isAutoSyncMode) {
|
||||||
|
// On Android we need to sync trashed assets
|
||||||
|
await _trashSyncService.updateLocalTrashFromDevice();
|
||||||
|
}
|
||||||
await _nativeSyncApi.checkpointSync();
|
await _nativeSyncApi.checkpointSync();
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
_log.severe("Error performing device sync", e, s);
|
_log.severe("Error performing device sync", e, s);
|
||||||
|
|
@ -99,6 +106,9 @@ class LocalSyncService {
|
||||||
onlyFirst: removeAlbum,
|
onlyFirst: removeAlbum,
|
||||||
onlySecond: addAlbum,
|
onlySecond: addAlbum,
|
||||||
);
|
);
|
||||||
|
if (_trashSyncService.isAutoSyncMode) {
|
||||||
|
await _trashSyncService.updateLocalTrashFromDevice();
|
||||||
|
}
|
||||||
|
|
||||||
await _nativeSyncApi.checkpointSync();
|
await _nativeSyncApi.checkpointSync();
|
||||||
stopwatch.stop();
|
stopwatch.stop();
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,11 @@ class SyncStreamService {
|
||||||
return _syncStreamRepository.deletePartnerV1(data.cast());
|
return _syncStreamRepository.deletePartnerV1(data.cast());
|
||||||
case SyncEntityType.assetV1:
|
case SyncEntityType.assetV1:
|
||||||
final remoteSyncAssets = data.cast<SyncAssetV1>();
|
final remoteSyncAssets = data.cast<SyncAssetV1>();
|
||||||
|
if (_trashSyncService.isAutoSyncMode) {
|
||||||
await _trashSyncService.handleRemoteChanges(
|
await _trashSyncService.handleRemoteChanges(
|
||||||
remoteSyncAssets.map<TrashSyncItem>((e) => (remoteId: e.id, checksum: e.checksum, deletedAt: e.deletedAt)),
|
remoteSyncAssets.where((e) => e.deletedAt != null).map((e) => e.checksum),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return _syncStreamRepository.updateAssetsV1(remoteSyncAssets);
|
return _syncStreamRepository.updateAssetsV1(remoteSyncAssets);
|
||||||
case SyncEntityType.assetDeleteV1:
|
case SyncEntityType.assetDeleteV1:
|
||||||
return _syncStreamRepository.deleteAssetsV1(data.cast());
|
return _syncStreamRepository.deleteAssetsV1(data.cast());
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/local_trashed_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/trashed_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart';
|
||||||
|
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||||
import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
|
import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
|
||||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
|
import 'package:immich_mobile/utils/datetime_helpers.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:platform/platform.dart';
|
import 'package:platform/platform.dart';
|
||||||
|
|
||||||
|
|
@ -12,8 +15,10 @@ typedef TrashSyncItem = ({String remoteId, String checksum, DateTime? deletedAt}
|
||||||
|
|
||||||
class TrashSyncService {
|
class TrashSyncService {
|
||||||
final AppSettingsService _appSettingsService;
|
final AppSettingsService _appSettingsService;
|
||||||
final RemoteAssetRepository _remoteAssetRepository;
|
final NativeSyncApi _nativeSyncApi;
|
||||||
final DriftLocalAssetRepository _localAssetRepository;
|
final DriftLocalAssetRepository _localAssetRepository;
|
||||||
|
final DriftLocalAlbumRepository _localAlbumRepository;
|
||||||
|
final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository;
|
||||||
final LocalFilesManagerRepository _localFilesManager;
|
final LocalFilesManagerRepository _localFilesManager;
|
||||||
final StorageRepository _storageRepository;
|
final StorageRepository _storageRepository;
|
||||||
final Platform _platform;
|
final Platform _platform;
|
||||||
|
|
@ -21,85 +26,96 @@ class TrashSyncService {
|
||||||
|
|
||||||
TrashSyncService({
|
TrashSyncService({
|
||||||
required AppSettingsService appSettingsService,
|
required AppSettingsService appSettingsService,
|
||||||
required RemoteAssetRepository remoteAssetRepository,
|
required NativeSyncApi nativeSyncApi,
|
||||||
required DriftLocalAssetRepository localAssetRepository,
|
required DriftLocalAssetRepository localAssetRepository,
|
||||||
|
required DriftLocalAlbumRepository localAlbumRepository,
|
||||||
|
required DriftTrashedLocalAssetRepository trashedLocalAssetRepository,
|
||||||
required LocalFilesManagerRepository localFilesManager,
|
required LocalFilesManagerRepository localFilesManager,
|
||||||
required StorageRepository storageRepository,
|
required StorageRepository storageRepository,
|
||||||
}) : _appSettingsService = appSettingsService,
|
}) : _appSettingsService = appSettingsService,
|
||||||
_remoteAssetRepository = remoteAssetRepository,
|
_nativeSyncApi = nativeSyncApi,
|
||||||
_localAssetRepository = localAssetRepository,
|
_localAssetRepository = localAssetRepository,
|
||||||
|
_localAlbumRepository = localAlbumRepository,
|
||||||
|
_trashedLocalAssetRepository = trashedLocalAssetRepository,
|
||||||
_localFilesManager = localFilesManager,
|
_localFilesManager = localFilesManager,
|
||||||
_storageRepository = storageRepository,
|
_storageRepository = storageRepository,
|
||||||
_platform = const LocalPlatform();
|
_platform = const LocalPlatform();
|
||||||
|
|
||||||
Future<void> handleRemoteChanges(Iterable<TrashSyncItem> syncItems) async {
|
bool get isAutoSyncMode =>
|
||||||
if (!_platform.isAndroid || !_appSettingsService.getSetting<bool>(AppSettingsEnum.manageLocalMediaAndroid)) {
|
_platform.isAndroid && _appSettingsService.getSetting<bool>(AppSettingsEnum.manageLocalMediaAndroid);
|
||||||
return Future.value();
|
|
||||||
|
Future<void> updateChecksums(Iterable<TrashedAsset> assets) async =>
|
||||||
|
_trashedLocalAssetRepository.updateChecksums(assets);
|
||||||
|
|
||||||
|
Future<Iterable<TrashedAsset>> getAssetsToHash(String albumId) async =>
|
||||||
|
_trashedLocalAssetRepository.getToHash(albumId);
|
||||||
|
|
||||||
|
Future<void> updateLocalTrashFromDevice() async {
|
||||||
|
final backupAlbums = await _localAlbumRepository.getBackupAlbums();
|
||||||
|
if (backupAlbums.isEmpty) {
|
||||||
|
_logger.info("No backup albums found");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
final trashedAssetsItems = <TrashSyncItem>[];
|
for (final album in backupAlbums) {
|
||||||
final modifiedAssetsChecksums = <String>{};
|
_logger.info("deviceTrashedAssets prepare, album: ${album.id}/${album.name}");
|
||||||
for (var syncItem in syncItems) {
|
final deviceTrashedAssets = await _nativeSyncApi.getTrashedAssetsForAlbum(album.id);
|
||||||
if (syncItem.deletedAt != null) {
|
await _trashedLocalAssetRepository.applyTrashSnapshot(deviceTrashedAssets.toTrashedAssets(album.id), album.id);
|
||||||
trashedAssetsItems.add(syncItem);
|
|
||||||
} else {
|
|
||||||
modifiedAssetsChecksums.add(syncItem.checksum);
|
|
||||||
}
|
}
|
||||||
}
|
// todo find for more suitable place
|
||||||
await _applyRemoteTrashToLocal(trashedAssetsItems);
|
await applyRemoteRestoreToLocal();
|
||||||
await _applyRemoteRestoreToLocal(modifiedAssetsChecksums);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _applyRemoteTrashToLocal(Iterable<TrashSyncItem> trashedAssets) async {
|
Future<void> handleRemoteChanges(Iterable<String> checksums) async {
|
||||||
if (trashedAssets.isEmpty) {
|
if (checksums.isEmpty) {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
} else {
|
} else {
|
||||||
final trashedAssetsMap = <String, String>{for (final e in trashedAssets) e.checksum: e.remoteId};
|
final localAssetsToTrash = await _localAssetRepository.getBackupSelectedAssetsByAlbum(checksums);
|
||||||
final localAssetsToTrash = await _localAssetRepository.getBackupSelectedAssets(trashedAssetsMap.keys);
|
|
||||||
if (localAssetsToTrash.isNotEmpty) {
|
if (localAssetsToTrash.isNotEmpty) {
|
||||||
final mediaUrls = await Future.wait(
|
final mediaUrls = await Future.wait(
|
||||||
localAssetsToTrash.map(
|
localAssetsToTrash.values
|
||||||
(localAsset) => _storageRepository.getAssetEntityForAsset(localAsset).then((e) => e?.getMediaUrl()),
|
.expand((e) => e)
|
||||||
),
|
.map((localAsset) => _storageRepository.getAssetEntityForAsset(localAsset).then((e) => e?.getMediaUrl())),
|
||||||
);
|
);
|
||||||
_logger.info("Moving to trash ${mediaUrls.join(", ")} assets");
|
_logger.info("Moving to trash ${mediaUrls.join(", ")} assets");
|
||||||
await _localFilesManager.moveToTrash(mediaUrls.nonNulls.toList());
|
final result = await _localFilesManager.moveToTrash(mediaUrls.nonNulls.toList());
|
||||||
final itemsToTrash = <LocalRemoteIds>[];
|
if (result) {
|
||||||
for (final asset in localAssetsToTrash) {
|
await _localAssetRepository.trash(localAssetsToTrash);
|
||||||
final remoteId = trashedAssetsMap[asset.checksum]!;
|
|
||||||
itemsToTrash.add((localId: asset.id, remoteId: remoteId));
|
|
||||||
}
|
}
|
||||||
await _localAssetRepository.trash(itemsToTrash);
|
|
||||||
} else {
|
} else {
|
||||||
_logger.info("No assets found in backup-enabled albums for assets: $trashedAssetsMap");
|
_logger.info("No assets found in backup-enabled albums for assets: $checksums");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _applyRemoteRestoreToLocal(Iterable<String> modifiedAssetsChecksums) async {
|
Future<void> applyRemoteRestoreToLocal() async {
|
||||||
if (modifiedAssetsChecksums.isEmpty) {
|
final remoteAssetsToRestore = await _trashedLocalAssetRepository.getToRestore();
|
||||||
return Future.value();
|
|
||||||
} else {
|
|
||||||
final remoteAssetsToRestore = await _remoteAssetRepository.getByChecksums(
|
|
||||||
modifiedAssetsChecksums,
|
|
||||||
isTrashed: true,
|
|
||||||
);
|
|
||||||
if (remoteAssetsToRestore.isNotEmpty) {
|
if (remoteAssetsToRestore.isNotEmpty) {
|
||||||
final remoteAssetMap = <String, AssetType>{for (final e in remoteAssetsToRestore) e.id: e.type};
|
_logger.info("remoteAssetsToRestore: $remoteAssetsToRestore");
|
||||||
_logger.info("remoteAssetsToRestore: $remoteAssetMap");
|
for (final asset in remoteAssetsToRestore) {
|
||||||
final localTrashedAssets = await _localAssetRepository.getLocalTrashedAssets(remoteAssetMap.keys);
|
_logger.info("Restoring from trash, localId: ${asset.id}, remoteId: ${asset.checksum}");
|
||||||
if (localTrashedAssets.isNotEmpty) {
|
await _localFilesManager.restoreFromTrashById(asset.id, asset.type.index);
|
||||||
for (final LocalTrashedAsset asset in localTrashedAssets) {
|
|
||||||
_logger.info("Restoring from trash, localId: ${asset.localId}, remoteId: ${asset.remoteId}");
|
|
||||||
final type = remoteAssetMap[asset.remoteId]!;
|
|
||||||
await _localFilesManager.restoreFromTrashById(asset.localId, type.index);
|
|
||||||
await _localAssetRepository.deleteLocalTrashedAssets(remoteAssetMap.keys);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_logger.info("No local assets found for restoration");
|
|
||||||
}
|
}
|
||||||
|
// todo It`s necessary? could cause race with deletion in applyTrashSnapshot? 18/09/2025
|
||||||
|
await _trashedLocalAssetRepository.delete(remoteAssetsToRestore.map((e) => e.id));
|
||||||
} else {
|
} else {
|
||||||
_logger.info("No remote assets found for restoration");
|
_logger.info("No remote assets found for restoration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension on Iterable<PlatformAsset> {
|
||||||
|
List<TrashedAsset> toTrashedAssets(String albumId) {
|
||||||
|
return map(
|
||||||
|
(e) => TrashedAsset(
|
||||||
|
id: e.id,
|
||||||
|
name: e.name,
|
||||||
|
checksum: null,
|
||||||
|
type: AssetType.values.elementAtOrNull(e.type) ?? AssetType.other,
|
||||||
|
createdAt: tryFromSecondsSinceEpoch(e.createdAt) ?? DateTime.now(),
|
||||||
|
updatedAt: tryFromSecondsSinceEpoch(e.updatedAt) ?? DateTime.now(),
|
||||||
|
size: e.size,
|
||||||
|
albumId: albumId,
|
||||||
|
),
|
||||||
|
).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import 'package:drift/drift.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/local_trashed_asset.model.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_trashed_asset.entity.drift.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
|
||||||
|
|
||||||
@TableIndex.sql(
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_local_trashed_asset_remote_id ON local_trashed_asset_entity (remote_id)',
|
|
||||||
)
|
|
||||||
class LocalTrashedAssetEntity extends Table with DriftDefaultsMixin {
|
|
||||||
const LocalTrashedAssetEntity();
|
|
||||||
|
|
||||||
TextColumn get id => text()();
|
|
||||||
|
|
||||||
TextColumn get remoteId => text().references(RemoteAssetEntity, #id, onDelete: KeyAction.cascade)();
|
|
||||||
|
|
||||||
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Set<Column> get primaryKey => {id};
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LocalTrashedAssetEntityDataDomainExtension on LocalTrashedAssetEntityData {
|
|
||||||
LocalTrashedAsset toDto() => LocalTrashedAsset(localId: id, remoteId: remoteId, createdAt: createdAt);
|
|
||||||
}
|
|
||||||
|
|
@ -1,614 +0,0 @@
|
||||||
// dart format width=80
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
import 'package:drift/drift.dart' as i0;
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_trashed_asset.entity.drift.dart'
|
|
||||||
as i1;
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_trashed_asset.entity.dart'
|
|
||||||
as i2;
|
|
||||||
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i3;
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'
|
|
||||||
as i4;
|
|
||||||
import 'package:drift/internal/modular.dart' as i5;
|
|
||||||
|
|
||||||
typedef $$LocalTrashedAssetEntityTableCreateCompanionBuilder =
|
|
||||||
i1.LocalTrashedAssetEntityCompanion Function({
|
|
||||||
required String id,
|
|
||||||
required String remoteId,
|
|
||||||
i0.Value<DateTime> createdAt,
|
|
||||||
});
|
|
||||||
typedef $$LocalTrashedAssetEntityTableUpdateCompanionBuilder =
|
|
||||||
i1.LocalTrashedAssetEntityCompanion Function({
|
|
||||||
i0.Value<String> id,
|
|
||||||
i0.Value<String> remoteId,
|
|
||||||
i0.Value<DateTime> createdAt,
|
|
||||||
});
|
|
||||||
|
|
||||||
final class $$LocalTrashedAssetEntityTableReferences
|
|
||||||
extends
|
|
||||||
i0.BaseReferences<
|
|
||||||
i0.GeneratedDatabase,
|
|
||||||
i1.$LocalTrashedAssetEntityTable,
|
|
||||||
i1.LocalTrashedAssetEntityData
|
|
||||||
> {
|
|
||||||
$$LocalTrashedAssetEntityTableReferences(
|
|
||||||
super.$_db,
|
|
||||||
super.$_table,
|
|
||||||
super.$_typedResult,
|
|
||||||
);
|
|
||||||
|
|
||||||
static i4.$RemoteAssetEntityTable _remoteIdTable(i0.GeneratedDatabase db) =>
|
|
||||||
i5.ReadDatabaseContainer(db)
|
|
||||||
.resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity')
|
|
||||||
.createAlias(
|
|
||||||
i0.$_aliasNameGenerator(
|
|
||||||
i5.ReadDatabaseContainer(db)
|
|
||||||
.resultSet<i1.$LocalTrashedAssetEntityTable>(
|
|
||||||
'local_trashed_asset_entity',
|
|
||||||
)
|
|
||||||
.remoteId,
|
|
||||||
i5.ReadDatabaseContainer(
|
|
||||||
db,
|
|
||||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
i4.$$RemoteAssetEntityTableProcessedTableManager get remoteId {
|
|
||||||
final $_column = $_itemColumn<String>('remote_id')!;
|
|
||||||
|
|
||||||
final manager = i4
|
|
||||||
.$$RemoteAssetEntityTableTableManager(
|
|
||||||
$_db,
|
|
||||||
i5.ReadDatabaseContainer(
|
|
||||||
$_db,
|
|
||||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity'),
|
|
||||||
)
|
|
||||||
.filter((f) => f.id.sqlEquals($_column));
|
|
||||||
final item = $_typedResult.readTableOrNull(_remoteIdTable($_db));
|
|
||||||
if (item == null) return manager;
|
|
||||||
return i0.ProcessedTableManager(
|
|
||||||
manager.$state.copyWith(prefetchedData: [item]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class $$LocalTrashedAssetEntityTableFilterComposer
|
|
||||||
extends
|
|
||||||
i0.Composer<i0.GeneratedDatabase, i1.$LocalTrashedAssetEntityTable> {
|
|
||||||
$$LocalTrashedAssetEntityTableFilterComposer({
|
|
||||||
required super.$db,
|
|
||||||
required super.$table,
|
|
||||||
super.joinBuilder,
|
|
||||||
super.$addJoinBuilderToRootComposer,
|
|
||||||
super.$removeJoinBuilderFromRootComposer,
|
|
||||||
});
|
|
||||||
i0.ColumnFilters<String> get id => $composableBuilder(
|
|
||||||
column: $table.id,
|
|
||||||
builder: (column) => i0.ColumnFilters(column),
|
|
||||||
);
|
|
||||||
|
|
||||||
i0.ColumnFilters<DateTime> get createdAt => $composableBuilder(
|
|
||||||
column: $table.createdAt,
|
|
||||||
builder: (column) => i0.ColumnFilters(column),
|
|
||||||
);
|
|
||||||
|
|
||||||
i4.$$RemoteAssetEntityTableFilterComposer get remoteId {
|
|
||||||
final i4.$$RemoteAssetEntityTableFilterComposer composer = $composerBuilder(
|
|
||||||
composer: this,
|
|
||||||
getCurrentColumn: (t) => t.remoteId,
|
|
||||||
referencedTable: i5.ReadDatabaseContainer(
|
|
||||||
$db,
|
|
||||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity'),
|
|
||||||
getReferencedColumn: (t) => t.id,
|
|
||||||
builder:
|
|
||||||
(
|
|
||||||
joinBuilder, {
|
|
||||||
$addJoinBuilderToRootComposer,
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
}) => i4.$$RemoteAssetEntityTableFilterComposer(
|
|
||||||
$db: $db,
|
|
||||||
$table: i5.ReadDatabaseContainer(
|
|
||||||
$db,
|
|
||||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity'),
|
|
||||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
|
||||||
joinBuilder: joinBuilder,
|
|
||||||
$removeJoinBuilderFromRootComposer:
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return composer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class $$LocalTrashedAssetEntityTableOrderingComposer
|
|
||||||
extends
|
|
||||||
i0.Composer<i0.GeneratedDatabase, i1.$LocalTrashedAssetEntityTable> {
|
|
||||||
$$LocalTrashedAssetEntityTableOrderingComposer({
|
|
||||||
required super.$db,
|
|
||||||
required super.$table,
|
|
||||||
super.joinBuilder,
|
|
||||||
super.$addJoinBuilderToRootComposer,
|
|
||||||
super.$removeJoinBuilderFromRootComposer,
|
|
||||||
});
|
|
||||||
i0.ColumnOrderings<String> get id => $composableBuilder(
|
|
||||||
column: $table.id,
|
|
||||||
builder: (column) => i0.ColumnOrderings(column),
|
|
||||||
);
|
|
||||||
|
|
||||||
i0.ColumnOrderings<DateTime> get createdAt => $composableBuilder(
|
|
||||||
column: $table.createdAt,
|
|
||||||
builder: (column) => i0.ColumnOrderings(column),
|
|
||||||
);
|
|
||||||
|
|
||||||
i4.$$RemoteAssetEntityTableOrderingComposer get remoteId {
|
|
||||||
final i4.$$RemoteAssetEntityTableOrderingComposer composer =
|
|
||||||
$composerBuilder(
|
|
||||||
composer: this,
|
|
||||||
getCurrentColumn: (t) => t.remoteId,
|
|
||||||
referencedTable: i5.ReadDatabaseContainer(
|
|
||||||
$db,
|
|
||||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity'),
|
|
||||||
getReferencedColumn: (t) => t.id,
|
|
||||||
builder:
|
|
||||||
(
|
|
||||||
joinBuilder, {
|
|
||||||
$addJoinBuilderToRootComposer,
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
}) => i4.$$RemoteAssetEntityTableOrderingComposer(
|
|
||||||
$db: $db,
|
|
||||||
$table: i5.ReadDatabaseContainer(
|
|
||||||
$db,
|
|
||||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity'),
|
|
||||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
|
||||||
joinBuilder: joinBuilder,
|
|
||||||
$removeJoinBuilderFromRootComposer:
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return composer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class $$LocalTrashedAssetEntityTableAnnotationComposer
|
|
||||||
extends
|
|
||||||
i0.Composer<i0.GeneratedDatabase, i1.$LocalTrashedAssetEntityTable> {
|
|
||||||
$$LocalTrashedAssetEntityTableAnnotationComposer({
|
|
||||||
required super.$db,
|
|
||||||
required super.$table,
|
|
||||||
super.joinBuilder,
|
|
||||||
super.$addJoinBuilderToRootComposer,
|
|
||||||
super.$removeJoinBuilderFromRootComposer,
|
|
||||||
});
|
|
||||||
i0.GeneratedColumn<String> get id =>
|
|
||||||
$composableBuilder(column: $table.id, builder: (column) => column);
|
|
||||||
|
|
||||||
i0.GeneratedColumn<DateTime> get createdAt =>
|
|
||||||
$composableBuilder(column: $table.createdAt, builder: (column) => column);
|
|
||||||
|
|
||||||
i4.$$RemoteAssetEntityTableAnnotationComposer get remoteId {
|
|
||||||
final i4.$$RemoteAssetEntityTableAnnotationComposer composer =
|
|
||||||
$composerBuilder(
|
|
||||||
composer: this,
|
|
||||||
getCurrentColumn: (t) => t.remoteId,
|
|
||||||
referencedTable: i5.ReadDatabaseContainer(
|
|
||||||
$db,
|
|
||||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity'),
|
|
||||||
getReferencedColumn: (t) => t.id,
|
|
||||||
builder:
|
|
||||||
(
|
|
||||||
joinBuilder, {
|
|
||||||
$addJoinBuilderToRootComposer,
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
}) => i4.$$RemoteAssetEntityTableAnnotationComposer(
|
|
||||||
$db: $db,
|
|
||||||
$table: i5.ReadDatabaseContainer(
|
|
||||||
$db,
|
|
||||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity'),
|
|
||||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
|
||||||
joinBuilder: joinBuilder,
|
|
||||||
$removeJoinBuilderFromRootComposer:
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return composer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class $$LocalTrashedAssetEntityTableTableManager
|
|
||||||
extends
|
|
||||||
i0.RootTableManager<
|
|
||||||
i0.GeneratedDatabase,
|
|
||||||
i1.$LocalTrashedAssetEntityTable,
|
|
||||||
i1.LocalTrashedAssetEntityData,
|
|
||||||
i1.$$LocalTrashedAssetEntityTableFilterComposer,
|
|
||||||
i1.$$LocalTrashedAssetEntityTableOrderingComposer,
|
|
||||||
i1.$$LocalTrashedAssetEntityTableAnnotationComposer,
|
|
||||||
$$LocalTrashedAssetEntityTableCreateCompanionBuilder,
|
|
||||||
$$LocalTrashedAssetEntityTableUpdateCompanionBuilder,
|
|
||||||
(
|
|
||||||
i1.LocalTrashedAssetEntityData,
|
|
||||||
i1.$$LocalTrashedAssetEntityTableReferences,
|
|
||||||
),
|
|
||||||
i1.LocalTrashedAssetEntityData,
|
|
||||||
i0.PrefetchHooks Function({bool remoteId})
|
|
||||||
> {
|
|
||||||
$$LocalTrashedAssetEntityTableTableManager(
|
|
||||||
i0.GeneratedDatabase db,
|
|
||||||
i1.$LocalTrashedAssetEntityTable table,
|
|
||||||
) : super(
|
|
||||||
i0.TableManagerState(
|
|
||||||
db: db,
|
|
||||||
table: table,
|
|
||||||
createFilteringComposer: () =>
|
|
||||||
i1.$$LocalTrashedAssetEntityTableFilterComposer(
|
|
||||||
$db: db,
|
|
||||||
$table: table,
|
|
||||||
),
|
|
||||||
createOrderingComposer: () =>
|
|
||||||
i1.$$LocalTrashedAssetEntityTableOrderingComposer(
|
|
||||||
$db: db,
|
|
||||||
$table: table,
|
|
||||||
),
|
|
||||||
createComputedFieldComposer: () =>
|
|
||||||
i1.$$LocalTrashedAssetEntityTableAnnotationComposer(
|
|
||||||
$db: db,
|
|
||||||
$table: table,
|
|
||||||
),
|
|
||||||
updateCompanionCallback:
|
|
||||||
({
|
|
||||||
i0.Value<String> id = const i0.Value.absent(),
|
|
||||||
i0.Value<String> remoteId = const i0.Value.absent(),
|
|
||||||
i0.Value<DateTime> createdAt = const i0.Value.absent(),
|
|
||||||
}) => i1.LocalTrashedAssetEntityCompanion(
|
|
||||||
id: id,
|
|
||||||
remoteId: remoteId,
|
|
||||||
createdAt: createdAt,
|
|
||||||
),
|
|
||||||
createCompanionCallback:
|
|
||||||
({
|
|
||||||
required String id,
|
|
||||||
required String remoteId,
|
|
||||||
i0.Value<DateTime> createdAt = const i0.Value.absent(),
|
|
||||||
}) => i1.LocalTrashedAssetEntityCompanion.insert(
|
|
||||||
id: id,
|
|
||||||
remoteId: remoteId,
|
|
||||||
createdAt: createdAt,
|
|
||||||
),
|
|
||||||
withReferenceMapper: (p0) => p0
|
|
||||||
.map(
|
|
||||||
(e) => (
|
|
||||||
e.readTable(table),
|
|
||||||
i1.$$LocalTrashedAssetEntityTableReferences(db, table, e),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
prefetchHooksCallback: ({remoteId = false}) {
|
|
||||||
return i0.PrefetchHooks(
|
|
||||||
db: db,
|
|
||||||
explicitlyWatchedTables: [],
|
|
||||||
addJoins:
|
|
||||||
<
|
|
||||||
T extends i0.TableManagerState<
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic,
|
|
||||||
dynamic
|
|
||||||
>
|
|
||||||
>(state) {
|
|
||||||
if (remoteId) {
|
|
||||||
state =
|
|
||||||
state.withJoin(
|
|
||||||
currentTable: table,
|
|
||||||
currentColumn: table.remoteId,
|
|
||||||
referencedTable: i1
|
|
||||||
.$$LocalTrashedAssetEntityTableReferences
|
|
||||||
._remoteIdTable(db),
|
|
||||||
referencedColumn: i1
|
|
||||||
.$$LocalTrashedAssetEntityTableReferences
|
|
||||||
._remoteIdTable(db)
|
|
||||||
.id,
|
|
||||||
)
|
|
||||||
as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
},
|
|
||||||
getPrefetchedDataCallback: (items) async {
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef $$LocalTrashedAssetEntityTableProcessedTableManager =
|
|
||||||
i0.ProcessedTableManager<
|
|
||||||
i0.GeneratedDatabase,
|
|
||||||
i1.$LocalTrashedAssetEntityTable,
|
|
||||||
i1.LocalTrashedAssetEntityData,
|
|
||||||
i1.$$LocalTrashedAssetEntityTableFilterComposer,
|
|
||||||
i1.$$LocalTrashedAssetEntityTableOrderingComposer,
|
|
||||||
i1.$$LocalTrashedAssetEntityTableAnnotationComposer,
|
|
||||||
$$LocalTrashedAssetEntityTableCreateCompanionBuilder,
|
|
||||||
$$LocalTrashedAssetEntityTableUpdateCompanionBuilder,
|
|
||||||
(
|
|
||||||
i1.LocalTrashedAssetEntityData,
|
|
||||||
i1.$$LocalTrashedAssetEntityTableReferences,
|
|
||||||
),
|
|
||||||
i1.LocalTrashedAssetEntityData,
|
|
||||||
i0.PrefetchHooks Function({bool remoteId})
|
|
||||||
>;
|
|
||||||
i0.Index get idxLocalTrashedAssetRemoteId => i0.Index(
|
|
||||||
'idx_local_trashed_asset_remote_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_local_trashed_asset_remote_id ON local_trashed_asset_entity (remote_id)',
|
|
||||||
);
|
|
||||||
|
|
||||||
class $LocalTrashedAssetEntityTable extends i2.LocalTrashedAssetEntity
|
|
||||||
with
|
|
||||||
i0.TableInfo<
|
|
||||||
$LocalTrashedAssetEntityTable,
|
|
||||||
i1.LocalTrashedAssetEntityData
|
|
||||||
> {
|
|
||||||
@override
|
|
||||||
final i0.GeneratedDatabase attachedDatabase;
|
|
||||||
final String? _alias;
|
|
||||||
$LocalTrashedAssetEntityTable(this.attachedDatabase, [this._alias]);
|
|
||||||
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
|
|
||||||
@override
|
|
||||||
late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
|
|
||||||
'id',
|
|
||||||
aliasedName,
|
|
||||||
false,
|
|
||||||
type: i0.DriftSqlType.string,
|
|
||||||
requiredDuringInsert: true,
|
|
||||||
);
|
|
||||||
static const i0.VerificationMeta _remoteIdMeta = const i0.VerificationMeta(
|
|
||||||
'remoteId',
|
|
||||||
);
|
|
||||||
@override
|
|
||||||
late final i0.GeneratedColumn<String> remoteId = i0.GeneratedColumn<String>(
|
|
||||||
'remote_id',
|
|
||||||
aliasedName,
|
|
||||||
false,
|
|
||||||
type: i0.DriftSqlType.string,
|
|
||||||
requiredDuringInsert: true,
|
|
||||||
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
|
||||||
'REFERENCES remote_asset_entity (id) ON DELETE CASCADE',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
static const i0.VerificationMeta _createdAtMeta = const i0.VerificationMeta(
|
|
||||||
'createdAt',
|
|
||||||
);
|
|
||||||
@override
|
|
||||||
late final i0.GeneratedColumn<DateTime> createdAt =
|
|
||||||
i0.GeneratedColumn<DateTime>(
|
|
||||||
'created_at',
|
|
||||||
aliasedName,
|
|
||||||
false,
|
|
||||||
type: i0.DriftSqlType.dateTime,
|
|
||||||
requiredDuringInsert: false,
|
|
||||||
defaultValue: i3.currentDateAndTime,
|
|
||||||
);
|
|
||||||
@override
|
|
||||||
List<i0.GeneratedColumn> get $columns => [id, remoteId, createdAt];
|
|
||||||
@override
|
|
||||||
String get aliasedName => _alias ?? actualTableName;
|
|
||||||
@override
|
|
||||||
String get actualTableName => $name;
|
|
||||||
static const String $name = 'local_trashed_asset_entity';
|
|
||||||
@override
|
|
||||||
i0.VerificationContext validateIntegrity(
|
|
||||||
i0.Insertable<i1.LocalTrashedAssetEntityData> instance, {
|
|
||||||
bool isInserting = false,
|
|
||||||
}) {
|
|
||||||
final context = i0.VerificationContext();
|
|
||||||
final data = instance.toColumns(true);
|
|
||||||
if (data.containsKey('id')) {
|
|
||||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
|
||||||
} else if (isInserting) {
|
|
||||||
context.missing(_idMeta);
|
|
||||||
}
|
|
||||||
if (data.containsKey('remote_id')) {
|
|
||||||
context.handle(
|
|
||||||
_remoteIdMeta,
|
|
||||||
remoteId.isAcceptableOrUnknown(data['remote_id']!, _remoteIdMeta),
|
|
||||||
);
|
|
||||||
} else if (isInserting) {
|
|
||||||
context.missing(_remoteIdMeta);
|
|
||||||
}
|
|
||||||
if (data.containsKey('created_at')) {
|
|
||||||
context.handle(
|
|
||||||
_createdAtMeta,
|
|
||||||
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Set<i0.GeneratedColumn> get $primaryKey => {id};
|
|
||||||
@override
|
|
||||||
i1.LocalTrashedAssetEntityData map(
|
|
||||||
Map<String, dynamic> data, {
|
|
||||||
String? tablePrefix,
|
|
||||||
}) {
|
|
||||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
|
||||||
return i1.LocalTrashedAssetEntityData(
|
|
||||||
id: attachedDatabase.typeMapping.read(
|
|
||||||
i0.DriftSqlType.string,
|
|
||||||
data['${effectivePrefix}id'],
|
|
||||||
)!,
|
|
||||||
remoteId: attachedDatabase.typeMapping.read(
|
|
||||||
i0.DriftSqlType.string,
|
|
||||||
data['${effectivePrefix}remote_id'],
|
|
||||||
)!,
|
|
||||||
createdAt: attachedDatabase.typeMapping.read(
|
|
||||||
i0.DriftSqlType.dateTime,
|
|
||||||
data['${effectivePrefix}created_at'],
|
|
||||||
)!,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
$LocalTrashedAssetEntityTable createAlias(String alias) {
|
|
||||||
return $LocalTrashedAssetEntityTable(attachedDatabase, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get withoutRowId => true;
|
|
||||||
@override
|
|
||||||
bool get isStrict => true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class LocalTrashedAssetEntityData extends i0.DataClass
|
|
||||||
implements i0.Insertable<i1.LocalTrashedAssetEntityData> {
|
|
||||||
final String id;
|
|
||||||
final String remoteId;
|
|
||||||
final DateTime createdAt;
|
|
||||||
const LocalTrashedAssetEntityData({
|
|
||||||
required this.id,
|
|
||||||
required this.remoteId,
|
|
||||||
required this.createdAt,
|
|
||||||
});
|
|
||||||
@override
|
|
||||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
|
||||||
final map = <String, i0.Expression>{};
|
|
||||||
map['id'] = i0.Variable<String>(id);
|
|
||||||
map['remote_id'] = i0.Variable<String>(remoteId);
|
|
||||||
map['created_at'] = i0.Variable<DateTime>(createdAt);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
factory LocalTrashedAssetEntityData.fromJson(
|
|
||||||
Map<String, dynamic> json, {
|
|
||||||
i0.ValueSerializer? serializer,
|
|
||||||
}) {
|
|
||||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
|
||||||
return LocalTrashedAssetEntityData(
|
|
||||||
id: serializer.fromJson<String>(json['id']),
|
|
||||||
remoteId: serializer.fromJson<String>(json['remoteId']),
|
|
||||||
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
|
||||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
|
||||||
return <String, dynamic>{
|
|
||||||
'id': serializer.toJson<String>(id),
|
|
||||||
'remoteId': serializer.toJson<String>(remoteId),
|
|
||||||
'createdAt': serializer.toJson<DateTime>(createdAt),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
i1.LocalTrashedAssetEntityData copyWith({
|
|
||||||
String? id,
|
|
||||||
String? remoteId,
|
|
||||||
DateTime? createdAt,
|
|
||||||
}) => i1.LocalTrashedAssetEntityData(
|
|
||||||
id: id ?? this.id,
|
|
||||||
remoteId: remoteId ?? this.remoteId,
|
|
||||||
createdAt: createdAt ?? this.createdAt,
|
|
||||||
);
|
|
||||||
LocalTrashedAssetEntityData copyWithCompanion(
|
|
||||||
i1.LocalTrashedAssetEntityCompanion data,
|
|
||||||
) {
|
|
||||||
return LocalTrashedAssetEntityData(
|
|
||||||
id: data.id.present ? data.id.value : this.id,
|
|
||||||
remoteId: data.remoteId.present ? data.remoteId.value : this.remoteId,
|
|
||||||
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return (StringBuffer('LocalTrashedAssetEntityData(')
|
|
||||||
..write('id: $id, ')
|
|
||||||
..write('remoteId: $remoteId, ')
|
|
||||||
..write('createdAt: $createdAt')
|
|
||||||
..write(')'))
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(id, remoteId, createdAt);
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) =>
|
|
||||||
identical(this, other) ||
|
|
||||||
(other is i1.LocalTrashedAssetEntityData &&
|
|
||||||
other.id == this.id &&
|
|
||||||
other.remoteId == this.remoteId &&
|
|
||||||
other.createdAt == this.createdAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
class LocalTrashedAssetEntityCompanion
|
|
||||||
extends i0.UpdateCompanion<i1.LocalTrashedAssetEntityData> {
|
|
||||||
final i0.Value<String> id;
|
|
||||||
final i0.Value<String> remoteId;
|
|
||||||
final i0.Value<DateTime> createdAt;
|
|
||||||
const LocalTrashedAssetEntityCompanion({
|
|
||||||
this.id = const i0.Value.absent(),
|
|
||||||
this.remoteId = const i0.Value.absent(),
|
|
||||||
this.createdAt = const i0.Value.absent(),
|
|
||||||
});
|
|
||||||
LocalTrashedAssetEntityCompanion.insert({
|
|
||||||
required String id,
|
|
||||||
required String remoteId,
|
|
||||||
this.createdAt = const i0.Value.absent(),
|
|
||||||
}) : id = i0.Value(id),
|
|
||||||
remoteId = i0.Value(remoteId);
|
|
||||||
static i0.Insertable<i1.LocalTrashedAssetEntityData> custom({
|
|
||||||
i0.Expression<String>? id,
|
|
||||||
i0.Expression<String>? remoteId,
|
|
||||||
i0.Expression<DateTime>? createdAt,
|
|
||||||
}) {
|
|
||||||
return i0.RawValuesInsertable({
|
|
||||||
if (id != null) 'id': id,
|
|
||||||
if (remoteId != null) 'remote_id': remoteId,
|
|
||||||
if (createdAt != null) 'created_at': createdAt,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
i1.LocalTrashedAssetEntityCompanion copyWith({
|
|
||||||
i0.Value<String>? id,
|
|
||||||
i0.Value<String>? remoteId,
|
|
||||||
i0.Value<DateTime>? createdAt,
|
|
||||||
}) {
|
|
||||||
return i1.LocalTrashedAssetEntityCompanion(
|
|
||||||
id: id ?? this.id,
|
|
||||||
remoteId: remoteId ?? this.remoteId,
|
|
||||||
createdAt: createdAt ?? this.createdAt,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
|
||||||
final map = <String, i0.Expression>{};
|
|
||||||
if (id.present) {
|
|
||||||
map['id'] = i0.Variable<String>(id.value);
|
|
||||||
}
|
|
||||||
if (remoteId.present) {
|
|
||||||
map['remote_id'] = i0.Variable<String>(remoteId.value);
|
|
||||||
}
|
|
||||||
if (createdAt.present) {
|
|
||||||
map['created_at'] = i0.Variable<DateTime>(createdAt.value);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return (StringBuffer('LocalTrashedAssetEntityCompanion(')
|
|
||||||
..write('id: $id, ')
|
|
||||||
..write('remoteId: $remoteId, ')
|
|
||||||
..write('createdAt: $createdAt')
|
|
||||||
..write(')'))
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/asset/trashed_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.drift.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
|
||||||
|
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)')
|
||||||
|
class TrashedLocalAssetEntity extends Table with DriftDefaultsMixin {
|
||||||
|
const TrashedLocalAssetEntity();
|
||||||
|
|
||||||
|
TextColumn get id => text()();
|
||||||
|
|
||||||
|
TextColumn get albumId => text()();
|
||||||
|
|
||||||
|
TextColumn get checksum => text().nullable()();
|
||||||
|
|
||||||
|
TextColumn get name => text()();
|
||||||
|
|
||||||
|
IntColumn get type => intEnum<AssetType>()();
|
||||||
|
|
||||||
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
|
IntColumn get size => integer().nullable()();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {id};
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TrashedLocalAssetEntityDataDomainExtension on TrashedLocalAssetEntityData {
|
||||||
|
TrashedAsset toDto(String albumId) => TrashedAsset(
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
albumId: albumId,
|
||||||
|
checksum: checksum,
|
||||||
|
type: type,
|
||||||
|
createdAt: createdAt,
|
||||||
|
updatedAt: updatedAt,
|
||||||
|
size: size,
|
||||||
|
);
|
||||||
|
}
|
||||||
794
mobile/lib/infrastructure/entities/trashed_local_asset.entity.drift.dart
generated
Normal file
794
mobile/lib/infrastructure/entities/trashed_local_asset.entity.drift.dart
generated
Normal file
|
|
@ -0,0 +1,794 @@
|
||||||
|
// dart format width=80
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
import 'package:drift/drift.dart' as i0;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.drift.dart'
|
||||||
|
as i1;
|
||||||
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart' as i2;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.dart'
|
||||||
|
as i3;
|
||||||
|
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
|
||||||
|
|
||||||
|
typedef $$TrashedLocalAssetEntityTableCreateCompanionBuilder =
|
||||||
|
i1.TrashedLocalAssetEntityCompanion Function({
|
||||||
|
required String id,
|
||||||
|
required String albumId,
|
||||||
|
i0.Value<String?> checksum,
|
||||||
|
required String name,
|
||||||
|
required i2.AssetType type,
|
||||||
|
i0.Value<DateTime> createdAt,
|
||||||
|
i0.Value<DateTime> updatedAt,
|
||||||
|
i0.Value<int?> size,
|
||||||
|
});
|
||||||
|
typedef $$TrashedLocalAssetEntityTableUpdateCompanionBuilder =
|
||||||
|
i1.TrashedLocalAssetEntityCompanion Function({
|
||||||
|
i0.Value<String> id,
|
||||||
|
i0.Value<String> albumId,
|
||||||
|
i0.Value<String?> checksum,
|
||||||
|
i0.Value<String> name,
|
||||||
|
i0.Value<i2.AssetType> type,
|
||||||
|
i0.Value<DateTime> createdAt,
|
||||||
|
i0.Value<DateTime> updatedAt,
|
||||||
|
i0.Value<int?> size,
|
||||||
|
});
|
||||||
|
|
||||||
|
class $$TrashedLocalAssetEntityTableFilterComposer
|
||||||
|
extends
|
||||||
|
i0.Composer<i0.GeneratedDatabase, i1.$TrashedLocalAssetEntityTable> {
|
||||||
|
$$TrashedLocalAssetEntityTableFilterComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.ColumnFilters<String> get id => $composableBuilder(
|
||||||
|
column: $table.id,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<String> get albumId => $composableBuilder(
|
||||||
|
column: $table.albumId,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<String> get checksum => $composableBuilder(
|
||||||
|
column: $table.checksum,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<String> get name => $composableBuilder(
|
||||||
|
column: $table.name,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnWithTypeConverterFilters<i2.AssetType, i2.AssetType, int> get type =>
|
||||||
|
$composableBuilder(
|
||||||
|
column: $table.type,
|
||||||
|
builder: (column) => i0.ColumnWithTypeConverterFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<DateTime> get createdAt => $composableBuilder(
|
||||||
|
column: $table.createdAt,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder(
|
||||||
|
column: $table.updatedAt,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<int> get size => $composableBuilder(
|
||||||
|
column: $table.size,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $$TrashedLocalAssetEntityTableOrderingComposer
|
||||||
|
extends
|
||||||
|
i0.Composer<i0.GeneratedDatabase, i1.$TrashedLocalAssetEntityTable> {
|
||||||
|
$$TrashedLocalAssetEntityTableOrderingComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.ColumnOrderings<String> get id => $composableBuilder(
|
||||||
|
column: $table.id,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<String> get albumId => $composableBuilder(
|
||||||
|
column: $table.albumId,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<String> get checksum => $composableBuilder(
|
||||||
|
column: $table.checksum,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<String> get name => $composableBuilder(
|
||||||
|
column: $table.name,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<int> get type => $composableBuilder(
|
||||||
|
column: $table.type,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<DateTime> get createdAt => $composableBuilder(
|
||||||
|
column: $table.createdAt,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<DateTime> get updatedAt => $composableBuilder(
|
||||||
|
column: $table.updatedAt,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<int> get size => $composableBuilder(
|
||||||
|
column: $table.size,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $$TrashedLocalAssetEntityTableAnnotationComposer
|
||||||
|
extends
|
||||||
|
i0.Composer<i0.GeneratedDatabase, i1.$TrashedLocalAssetEntityTable> {
|
||||||
|
$$TrashedLocalAssetEntityTableAnnotationComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.GeneratedColumn<String> get id =>
|
||||||
|
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<String> get albumId =>
|
||||||
|
$composableBuilder(column: $table.albumId, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<String> get checksum =>
|
||||||
|
$composableBuilder(column: $table.checksum, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<String> get name =>
|
||||||
|
$composableBuilder(column: $table.name, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumnWithTypeConverter<i2.AssetType, int> get type =>
|
||||||
|
$composableBuilder(column: $table.type, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
$composableBuilder(column: $table.createdAt, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<DateTime> get updatedAt =>
|
||||||
|
$composableBuilder(column: $table.updatedAt, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<int> get size =>
|
||||||
|
$composableBuilder(column: $table.size, builder: (column) => column);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $$TrashedLocalAssetEntityTableTableManager
|
||||||
|
extends
|
||||||
|
i0.RootTableManager<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$TrashedLocalAssetEntityTable,
|
||||||
|
i1.TrashedLocalAssetEntityData,
|
||||||
|
i1.$$TrashedLocalAssetEntityTableFilterComposer,
|
||||||
|
i1.$$TrashedLocalAssetEntityTableOrderingComposer,
|
||||||
|
i1.$$TrashedLocalAssetEntityTableAnnotationComposer,
|
||||||
|
$$TrashedLocalAssetEntityTableCreateCompanionBuilder,
|
||||||
|
$$TrashedLocalAssetEntityTableUpdateCompanionBuilder,
|
||||||
|
(
|
||||||
|
i1.TrashedLocalAssetEntityData,
|
||||||
|
i0.BaseReferences<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$TrashedLocalAssetEntityTable,
|
||||||
|
i1.TrashedLocalAssetEntityData
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
i1.TrashedLocalAssetEntityData,
|
||||||
|
i0.PrefetchHooks Function()
|
||||||
|
> {
|
||||||
|
$$TrashedLocalAssetEntityTableTableManager(
|
||||||
|
i0.GeneratedDatabase db,
|
||||||
|
i1.$TrashedLocalAssetEntityTable table,
|
||||||
|
) : super(
|
||||||
|
i0.TableManagerState(
|
||||||
|
db: db,
|
||||||
|
table: table,
|
||||||
|
createFilteringComposer: () =>
|
||||||
|
i1.$$TrashedLocalAssetEntityTableFilterComposer(
|
||||||
|
$db: db,
|
||||||
|
$table: table,
|
||||||
|
),
|
||||||
|
createOrderingComposer: () =>
|
||||||
|
i1.$$TrashedLocalAssetEntityTableOrderingComposer(
|
||||||
|
$db: db,
|
||||||
|
$table: table,
|
||||||
|
),
|
||||||
|
createComputedFieldComposer: () =>
|
||||||
|
i1.$$TrashedLocalAssetEntityTableAnnotationComposer(
|
||||||
|
$db: db,
|
||||||
|
$table: table,
|
||||||
|
),
|
||||||
|
updateCompanionCallback:
|
||||||
|
({
|
||||||
|
i0.Value<String> id = const i0.Value.absent(),
|
||||||
|
i0.Value<String> albumId = const i0.Value.absent(),
|
||||||
|
i0.Value<String?> checksum = const i0.Value.absent(),
|
||||||
|
i0.Value<String> name = const i0.Value.absent(),
|
||||||
|
i0.Value<i2.AssetType> type = const i0.Value.absent(),
|
||||||
|
i0.Value<DateTime> createdAt = const i0.Value.absent(),
|
||||||
|
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
||||||
|
i0.Value<int?> size = const i0.Value.absent(),
|
||||||
|
}) => i1.TrashedLocalAssetEntityCompanion(
|
||||||
|
id: id,
|
||||||
|
albumId: albumId,
|
||||||
|
checksum: checksum,
|
||||||
|
name: name,
|
||||||
|
type: type,
|
||||||
|
createdAt: createdAt,
|
||||||
|
updatedAt: updatedAt,
|
||||||
|
size: size,
|
||||||
|
),
|
||||||
|
createCompanionCallback:
|
||||||
|
({
|
||||||
|
required String id,
|
||||||
|
required String albumId,
|
||||||
|
i0.Value<String?> checksum = const i0.Value.absent(),
|
||||||
|
required String name,
|
||||||
|
required i2.AssetType type,
|
||||||
|
i0.Value<DateTime> createdAt = const i0.Value.absent(),
|
||||||
|
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
||||||
|
i0.Value<int?> size = const i0.Value.absent(),
|
||||||
|
}) => i1.TrashedLocalAssetEntityCompanion.insert(
|
||||||
|
id: id,
|
||||||
|
albumId: albumId,
|
||||||
|
checksum: checksum,
|
||||||
|
name: name,
|
||||||
|
type: type,
|
||||||
|
createdAt: createdAt,
|
||||||
|
updatedAt: updatedAt,
|
||||||
|
size: size,
|
||||||
|
),
|
||||||
|
withReferenceMapper: (p0) => p0
|
||||||
|
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
|
||||||
|
.toList(),
|
||||||
|
prefetchHooksCallback: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef $$TrashedLocalAssetEntityTableProcessedTableManager =
|
||||||
|
i0.ProcessedTableManager<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$TrashedLocalAssetEntityTable,
|
||||||
|
i1.TrashedLocalAssetEntityData,
|
||||||
|
i1.$$TrashedLocalAssetEntityTableFilterComposer,
|
||||||
|
i1.$$TrashedLocalAssetEntityTableOrderingComposer,
|
||||||
|
i1.$$TrashedLocalAssetEntityTableAnnotationComposer,
|
||||||
|
$$TrashedLocalAssetEntityTableCreateCompanionBuilder,
|
||||||
|
$$TrashedLocalAssetEntityTableUpdateCompanionBuilder,
|
||||||
|
(
|
||||||
|
i1.TrashedLocalAssetEntityData,
|
||||||
|
i0.BaseReferences<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$TrashedLocalAssetEntityTable,
|
||||||
|
i1.TrashedLocalAssetEntityData
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
i1.TrashedLocalAssetEntityData,
|
||||||
|
i0.PrefetchHooks Function()
|
||||||
|
>;
|
||||||
|
i0.Index get idxTrashedLocalAssetChecksum => i0.Index(
|
||||||
|
'idx_trashed_local_asset_checksum',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
||||||
|
);
|
||||||
|
|
||||||
|
class $TrashedLocalAssetEntityTable extends i3.TrashedLocalAssetEntity
|
||||||
|
with
|
||||||
|
i0.TableInfo<
|
||||||
|
$TrashedLocalAssetEntityTable,
|
||||||
|
i1.TrashedLocalAssetEntityData
|
||||||
|
> {
|
||||||
|
@override
|
||||||
|
final i0.GeneratedDatabase attachedDatabase;
|
||||||
|
final String? _alias;
|
||||||
|
$TrashedLocalAssetEntityTable(this.attachedDatabase, [this._alias]);
|
||||||
|
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
|
||||||
|
'id',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _albumIdMeta = const i0.VerificationMeta(
|
||||||
|
'albumId',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> albumId = i0.GeneratedColumn<String>(
|
||||||
|
'album_id',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _checksumMeta = const i0.VerificationMeta(
|
||||||
|
'checksum',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> checksum = i0.GeneratedColumn<String>(
|
||||||
|
'checksum',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _nameMeta = const i0.VerificationMeta(
|
||||||
|
'name',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> name = i0.GeneratedColumn<String>(
|
||||||
|
'name',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumnWithTypeConverter<i2.AssetType, int> type =
|
||||||
|
i0.GeneratedColumn<int>(
|
||||||
|
'type',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.int,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
).withConverter<i2.AssetType>(
|
||||||
|
i1.$TrashedLocalAssetEntityTable.$convertertype,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _createdAtMeta = const i0.VerificationMeta(
|
||||||
|
'createdAt',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<DateTime> createdAt =
|
||||||
|
i0.GeneratedColumn<DateTime>(
|
||||||
|
'created_at',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.dateTime,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: i4.currentDateAndTime,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _updatedAtMeta = const i0.VerificationMeta(
|
||||||
|
'updatedAt',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<DateTime> updatedAt =
|
||||||
|
i0.GeneratedColumn<DateTime>(
|
||||||
|
'updated_at',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.dateTime,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: i4.currentDateAndTime,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _sizeMeta = const i0.VerificationMeta(
|
||||||
|
'size',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<int> size = i0.GeneratedColumn<int>(
|
||||||
|
'size',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i0.DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
List<i0.GeneratedColumn> get $columns => [
|
||||||
|
id,
|
||||||
|
albumId,
|
||||||
|
checksum,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
createdAt,
|
||||||
|
updatedAt,
|
||||||
|
size,
|
||||||
|
];
|
||||||
|
@override
|
||||||
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
|
@override
|
||||||
|
String get actualTableName => $name;
|
||||||
|
static const String $name = 'trashed_local_asset_entity';
|
||||||
|
@override
|
||||||
|
i0.VerificationContext validateIntegrity(
|
||||||
|
i0.Insertable<i1.TrashedLocalAssetEntityData> instance, {
|
||||||
|
bool isInserting = false,
|
||||||
|
}) {
|
||||||
|
final context = i0.VerificationContext();
|
||||||
|
final data = instance.toColumns(true);
|
||||||
|
if (data.containsKey('id')) {
|
||||||
|
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_idMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('album_id')) {
|
||||||
|
context.handle(
|
||||||
|
_albumIdMeta,
|
||||||
|
albumId.isAcceptableOrUnknown(data['album_id']!, _albumIdMeta),
|
||||||
|
);
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_albumIdMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('checksum')) {
|
||||||
|
context.handle(
|
||||||
|
_checksumMeta,
|
||||||
|
checksum.isAcceptableOrUnknown(data['checksum']!, _checksumMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('name')) {
|
||||||
|
context.handle(
|
||||||
|
_nameMeta,
|
||||||
|
name.isAcceptableOrUnknown(data['name']!, _nameMeta),
|
||||||
|
);
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_nameMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('created_at')) {
|
||||||
|
context.handle(
|
||||||
|
_createdAtMeta,
|
||||||
|
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('updated_at')) {
|
||||||
|
context.handle(
|
||||||
|
_updatedAtMeta,
|
||||||
|
updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('size')) {
|
||||||
|
context.handle(
|
||||||
|
_sizeMeta,
|
||||||
|
size.isAcceptableOrUnknown(data['size']!, _sizeMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<i0.GeneratedColumn> get $primaryKey => {id};
|
||||||
|
@override
|
||||||
|
i1.TrashedLocalAssetEntityData map(
|
||||||
|
Map<String, dynamic> data, {
|
||||||
|
String? tablePrefix,
|
||||||
|
}) {
|
||||||
|
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||||
|
return i1.TrashedLocalAssetEntityData(
|
||||||
|
id: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}id'],
|
||||||
|
)!,
|
||||||
|
albumId: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}album_id'],
|
||||||
|
)!,
|
||||||
|
checksum: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}checksum'],
|
||||||
|
),
|
||||||
|
name: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}name'],
|
||||||
|
)!,
|
||||||
|
type: i1.$TrashedLocalAssetEntityTable.$convertertype.fromSql(
|
||||||
|
attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}type'],
|
||||||
|
)!,
|
||||||
|
),
|
||||||
|
createdAt: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.dateTime,
|
||||||
|
data['${effectivePrefix}created_at'],
|
||||||
|
)!,
|
||||||
|
updatedAt: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.dateTime,
|
||||||
|
data['${effectivePrefix}updated_at'],
|
||||||
|
)!,
|
||||||
|
size: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}size'],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
$TrashedLocalAssetEntityTable createAlias(String alias) {
|
||||||
|
return $TrashedLocalAssetEntityTable(attachedDatabase, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
static i0.JsonTypeConverter2<i2.AssetType, int, int> $convertertype =
|
||||||
|
const i0.EnumIndexConverter<i2.AssetType>(i2.AssetType.values);
|
||||||
|
@override
|
||||||
|
bool get withoutRowId => true;
|
||||||
|
@override
|
||||||
|
bool get isStrict => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TrashedLocalAssetEntityData extends i0.DataClass
|
||||||
|
implements i0.Insertable<i1.TrashedLocalAssetEntityData> {
|
||||||
|
final String id;
|
||||||
|
final String albumId;
|
||||||
|
final String? checksum;
|
||||||
|
final String name;
|
||||||
|
final i2.AssetType type;
|
||||||
|
final DateTime createdAt;
|
||||||
|
final DateTime updatedAt;
|
||||||
|
final int? size;
|
||||||
|
const TrashedLocalAssetEntityData({
|
||||||
|
required this.id,
|
||||||
|
required this.albumId,
|
||||||
|
this.checksum,
|
||||||
|
required this.name,
|
||||||
|
required this.type,
|
||||||
|
required this.createdAt,
|
||||||
|
required this.updatedAt,
|
||||||
|
this.size,
|
||||||
|
});
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
map['id'] = i0.Variable<String>(id);
|
||||||
|
map['album_id'] = i0.Variable<String>(albumId);
|
||||||
|
if (!nullToAbsent || checksum != null) {
|
||||||
|
map['checksum'] = i0.Variable<String>(checksum);
|
||||||
|
}
|
||||||
|
map['name'] = i0.Variable<String>(name);
|
||||||
|
{
|
||||||
|
map['type'] = i0.Variable<int>(
|
||||||
|
i1.$TrashedLocalAssetEntityTable.$convertertype.toSql(type),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
map['created_at'] = i0.Variable<DateTime>(createdAt);
|
||||||
|
map['updated_at'] = i0.Variable<DateTime>(updatedAt);
|
||||||
|
if (!nullToAbsent || size != null) {
|
||||||
|
map['size'] = i0.Variable<int>(size);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory TrashedLocalAssetEntityData.fromJson(
|
||||||
|
Map<String, dynamic> json, {
|
||||||
|
i0.ValueSerializer? serializer,
|
||||||
|
}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return TrashedLocalAssetEntityData(
|
||||||
|
id: serializer.fromJson<String>(json['id']),
|
||||||
|
albumId: serializer.fromJson<String>(json['albumId']),
|
||||||
|
checksum: serializer.fromJson<String?>(json['checksum']),
|
||||||
|
name: serializer.fromJson<String>(json['name']),
|
||||||
|
type: i1.$TrashedLocalAssetEntityTable.$convertertype.fromJson(
|
||||||
|
serializer.fromJson<int>(json['type']),
|
||||||
|
),
|
||||||
|
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
||||||
|
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
|
||||||
|
size: serializer.fromJson<int?>(json['size']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return <String, dynamic>{
|
||||||
|
'id': serializer.toJson<String>(id),
|
||||||
|
'albumId': serializer.toJson<String>(albumId),
|
||||||
|
'checksum': serializer.toJson<String?>(checksum),
|
||||||
|
'name': serializer.toJson<String>(name),
|
||||||
|
'type': serializer.toJson<int>(
|
||||||
|
i1.$TrashedLocalAssetEntityTable.$convertertype.toJson(type),
|
||||||
|
),
|
||||||
|
'createdAt': serializer.toJson<DateTime>(createdAt),
|
||||||
|
'updatedAt': serializer.toJson<DateTime>(updatedAt),
|
||||||
|
'size': serializer.toJson<int?>(size),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.TrashedLocalAssetEntityData copyWith({
|
||||||
|
String? id,
|
||||||
|
String? albumId,
|
||||||
|
i0.Value<String?> checksum = const i0.Value.absent(),
|
||||||
|
String? name,
|
||||||
|
i2.AssetType? type,
|
||||||
|
DateTime? createdAt,
|
||||||
|
DateTime? updatedAt,
|
||||||
|
i0.Value<int?> size = const i0.Value.absent(),
|
||||||
|
}) => i1.TrashedLocalAssetEntityData(
|
||||||
|
id: id ?? this.id,
|
||||||
|
albumId: albumId ?? this.albumId,
|
||||||
|
checksum: checksum.present ? checksum.value : this.checksum,
|
||||||
|
name: name ?? this.name,
|
||||||
|
type: type ?? this.type,
|
||||||
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
|
size: size.present ? size.value : this.size,
|
||||||
|
);
|
||||||
|
TrashedLocalAssetEntityData copyWithCompanion(
|
||||||
|
i1.TrashedLocalAssetEntityCompanion data,
|
||||||
|
) {
|
||||||
|
return TrashedLocalAssetEntityData(
|
||||||
|
id: data.id.present ? data.id.value : this.id,
|
||||||
|
albumId: data.albumId.present ? data.albumId.value : this.albumId,
|
||||||
|
checksum: data.checksum.present ? data.checksum.value : this.checksum,
|
||||||
|
name: data.name.present ? data.name.value : this.name,
|
||||||
|
type: data.type.present ? data.type.value : this.type,
|
||||||
|
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
||||||
|
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
|
||||||
|
size: data.size.present ? data.size.value : this.size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('TrashedLocalAssetEntityData(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('albumId: $albumId, ')
|
||||||
|
..write('checksum: $checksum, ')
|
||||||
|
..write('name: $name, ')
|
||||||
|
..write('type: $type, ')
|
||||||
|
..write('createdAt: $createdAt, ')
|
||||||
|
..write('updatedAt: $updatedAt, ')
|
||||||
|
..write('size: $size')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
id,
|
||||||
|
albumId,
|
||||||
|
checksum,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
createdAt,
|
||||||
|
updatedAt,
|
||||||
|
size,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
(other is i1.TrashedLocalAssetEntityData &&
|
||||||
|
other.id == this.id &&
|
||||||
|
other.albumId == this.albumId &&
|
||||||
|
other.checksum == this.checksum &&
|
||||||
|
other.name == this.name &&
|
||||||
|
other.type == this.type &&
|
||||||
|
other.createdAt == this.createdAt &&
|
||||||
|
other.updatedAt == this.updatedAt &&
|
||||||
|
other.size == this.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TrashedLocalAssetEntityCompanion
|
||||||
|
extends i0.UpdateCompanion<i1.TrashedLocalAssetEntityData> {
|
||||||
|
final i0.Value<String> id;
|
||||||
|
final i0.Value<String> albumId;
|
||||||
|
final i0.Value<String?> checksum;
|
||||||
|
final i0.Value<String> name;
|
||||||
|
final i0.Value<i2.AssetType> type;
|
||||||
|
final i0.Value<DateTime> createdAt;
|
||||||
|
final i0.Value<DateTime> updatedAt;
|
||||||
|
final i0.Value<int?> size;
|
||||||
|
const TrashedLocalAssetEntityCompanion({
|
||||||
|
this.id = const i0.Value.absent(),
|
||||||
|
this.albumId = const i0.Value.absent(),
|
||||||
|
this.checksum = const i0.Value.absent(),
|
||||||
|
this.name = const i0.Value.absent(),
|
||||||
|
this.type = const i0.Value.absent(),
|
||||||
|
this.createdAt = const i0.Value.absent(),
|
||||||
|
this.updatedAt = const i0.Value.absent(),
|
||||||
|
this.size = const i0.Value.absent(),
|
||||||
|
});
|
||||||
|
TrashedLocalAssetEntityCompanion.insert({
|
||||||
|
required String id,
|
||||||
|
required String albumId,
|
||||||
|
this.checksum = const i0.Value.absent(),
|
||||||
|
required String name,
|
||||||
|
required i2.AssetType type,
|
||||||
|
this.createdAt = const i0.Value.absent(),
|
||||||
|
this.updatedAt = const i0.Value.absent(),
|
||||||
|
this.size = const i0.Value.absent(),
|
||||||
|
}) : id = i0.Value(id),
|
||||||
|
albumId = i0.Value(albumId),
|
||||||
|
name = i0.Value(name),
|
||||||
|
type = i0.Value(type);
|
||||||
|
static i0.Insertable<i1.TrashedLocalAssetEntityData> custom({
|
||||||
|
i0.Expression<String>? id,
|
||||||
|
i0.Expression<String>? albumId,
|
||||||
|
i0.Expression<String>? checksum,
|
||||||
|
i0.Expression<String>? name,
|
||||||
|
i0.Expression<int>? type,
|
||||||
|
i0.Expression<DateTime>? createdAt,
|
||||||
|
i0.Expression<DateTime>? updatedAt,
|
||||||
|
i0.Expression<int>? size,
|
||||||
|
}) {
|
||||||
|
return i0.RawValuesInsertable({
|
||||||
|
if (id != null) 'id': id,
|
||||||
|
if (albumId != null) 'album_id': albumId,
|
||||||
|
if (checksum != null) 'checksum': checksum,
|
||||||
|
if (name != null) 'name': name,
|
||||||
|
if (type != null) 'type': type,
|
||||||
|
if (createdAt != null) 'created_at': createdAt,
|
||||||
|
if (updatedAt != null) 'updated_at': updatedAt,
|
||||||
|
if (size != null) 'size': size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.TrashedLocalAssetEntityCompanion copyWith({
|
||||||
|
i0.Value<String>? id,
|
||||||
|
i0.Value<String>? albumId,
|
||||||
|
i0.Value<String?>? checksum,
|
||||||
|
i0.Value<String>? name,
|
||||||
|
i0.Value<i2.AssetType>? type,
|
||||||
|
i0.Value<DateTime>? createdAt,
|
||||||
|
i0.Value<DateTime>? updatedAt,
|
||||||
|
i0.Value<int?>? size,
|
||||||
|
}) {
|
||||||
|
return i1.TrashedLocalAssetEntityCompanion(
|
||||||
|
id: id ?? this.id,
|
||||||
|
albumId: albumId ?? this.albumId,
|
||||||
|
checksum: checksum ?? this.checksum,
|
||||||
|
name: name ?? this.name,
|
||||||
|
type: type ?? this.type,
|
||||||
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
|
size: size ?? this.size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
if (id.present) {
|
||||||
|
map['id'] = i0.Variable<String>(id.value);
|
||||||
|
}
|
||||||
|
if (albumId.present) {
|
||||||
|
map['album_id'] = i0.Variable<String>(albumId.value);
|
||||||
|
}
|
||||||
|
if (checksum.present) {
|
||||||
|
map['checksum'] = i0.Variable<String>(checksum.value);
|
||||||
|
}
|
||||||
|
if (name.present) {
|
||||||
|
map['name'] = i0.Variable<String>(name.value);
|
||||||
|
}
|
||||||
|
if (type.present) {
|
||||||
|
map['type'] = i0.Variable<int>(
|
||||||
|
i1.$TrashedLocalAssetEntityTable.$convertertype.toSql(type.value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (createdAt.present) {
|
||||||
|
map['created_at'] = i0.Variable<DateTime>(createdAt.value);
|
||||||
|
}
|
||||||
|
if (updatedAt.present) {
|
||||||
|
map['updated_at'] = i0.Variable<DateTime>(updatedAt.value);
|
||||||
|
}
|
||||||
|
if (size.present) {
|
||||||
|
map['size'] = i0.Variable<int>(size.value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('TrashedLocalAssetEntityCompanion(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('albumId: $albumId, ')
|
||||||
|
..write('checksum: $checksum, ')
|
||||||
|
..write('name: $name, ')
|
||||||
|
..write('type: $type, ')
|
||||||
|
..write('createdAt: $createdAt, ')
|
||||||
|
..write('updatedAt: $updatedAt, ')
|
||||||
|
..write('size: $size')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ import 'package:immich_mobile/infrastructure/entities/exif.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_trashed_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/memory.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/memory.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
|
||||||
|
|
@ -63,7 +63,7 @@ class IsarDatabaseRepository implements IDatabaseRepository {
|
||||||
PersonEntity,
|
PersonEntity,
|
||||||
AssetFaceEntity,
|
AssetFaceEntity,
|
||||||
StoreEntity,
|
StoreEntity,
|
||||||
LocalTrashedAssetEntity,
|
TrashedLocalAssetEntity,
|
||||||
],
|
],
|
||||||
include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'},
|
include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'},
|
||||||
)
|
)
|
||||||
|
|
@ -136,8 +136,8 @@ class Drift extends $Drift implements IDatabaseRepository {
|
||||||
await m.alterTable(TableMigration(v10.userEntity));
|
await m.alterTable(TableMigration(v10.userEntity));
|
||||||
},
|
},
|
||||||
from10To11: (m, v11) async {
|
from10To11: (m, v11) async {
|
||||||
await m.create(v11.localTrashedAssetEntity);
|
await m.create(v11.trashedLocalAssetEntity);
|
||||||
await m.createIndex(v11.idxLocalTrashedAssetRemoteId);
|
await m.createIndex(v11.idxTrashedLocalAssetChecksum);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.da
|
||||||
as i17;
|
as i17;
|
||||||
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart'
|
||||||
as i18;
|
as i18;
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_trashed_asset.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.drift.dart'
|
||||||
as i19;
|
as i19;
|
||||||
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
|
||||||
as i20;
|
as i20;
|
||||||
|
|
@ -79,8 +79,8 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
||||||
late final i17.$AssetFaceEntityTable assetFaceEntity = i17
|
late final i17.$AssetFaceEntityTable assetFaceEntity = i17
|
||||||
.$AssetFaceEntityTable(this);
|
.$AssetFaceEntityTable(this);
|
||||||
late final i18.$StoreEntityTable storeEntity = i18.$StoreEntityTable(this);
|
late final i18.$StoreEntityTable storeEntity = i18.$StoreEntityTable(this);
|
||||||
late final i19.$LocalTrashedAssetEntityTable localTrashedAssetEntity = i19
|
late final i19.$TrashedLocalAssetEntityTable trashedLocalAssetEntity = i19
|
||||||
.$LocalTrashedAssetEntityTable(this);
|
.$TrashedLocalAssetEntityTable(this);
|
||||||
i20.MergedAssetDrift get mergedAssetDrift => i21.ReadDatabaseContainer(
|
i20.MergedAssetDrift get mergedAssetDrift => i21.ReadDatabaseContainer(
|
||||||
this,
|
this,
|
||||||
).accessor<i20.MergedAssetDrift>(i20.MergedAssetDrift.new);
|
).accessor<i20.MergedAssetDrift>(i20.MergedAssetDrift.new);
|
||||||
|
|
@ -112,9 +112,9 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
||||||
personEntity,
|
personEntity,
|
||||||
assetFaceEntity,
|
assetFaceEntity,
|
||||||
storeEntity,
|
storeEntity,
|
||||||
localTrashedAssetEntity,
|
trashedLocalAssetEntity,
|
||||||
i11.idxLatLng,
|
i11.idxLatLng,
|
||||||
i19.idxLocalTrashedAssetRemoteId,
|
i19.idxTrashedLocalAssetChecksum,
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
i0.StreamQueryUpdateRules
|
i0.StreamQueryUpdateRules
|
||||||
|
|
@ -294,18 +294,6 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
||||||
),
|
),
|
||||||
result: [i0.TableUpdate('asset_face_entity', kind: i0.UpdateKind.update)],
|
result: [i0.TableUpdate('asset_face_entity', kind: i0.UpdateKind.update)],
|
||||||
),
|
),
|
||||||
i0.WritePropagation(
|
|
||||||
on: i0.TableUpdateQuery.onTableName(
|
|
||||||
'remote_asset_entity',
|
|
||||||
limitUpdateKind: i0.UpdateKind.delete,
|
|
||||||
),
|
|
||||||
result: [
|
|
||||||
i0.TableUpdate(
|
|
||||||
'local_trashed_asset_entity',
|
|
||||||
kind: i0.UpdateKind.delete,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
@override
|
@override
|
||||||
i0.DriftDatabaseOptions get options =>
|
i0.DriftDatabaseOptions get options =>
|
||||||
|
|
@ -354,9 +342,9 @@ class $DriftManager {
|
||||||
i17.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity);
|
i17.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity);
|
||||||
i18.$$StoreEntityTableTableManager get storeEntity =>
|
i18.$$StoreEntityTableTableManager get storeEntity =>
|
||||||
i18.$$StoreEntityTableTableManager(_db, _db.storeEntity);
|
i18.$$StoreEntityTableTableManager(_db, _db.storeEntity);
|
||||||
i19.$$LocalTrashedAssetEntityTableTableManager get localTrashedAssetEntity =>
|
i19.$$TrashedLocalAssetEntityTableTableManager get trashedLocalAssetEntity =>
|
||||||
i19.$$LocalTrashedAssetEntityTableTableManager(
|
i19.$$TrashedLocalAssetEntityTableTableManager(
|
||||||
_db,
|
_db,
|
||||||
_db.localTrashedAssetEntity,
|
_db.trashedLocalAssetEntity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4298,9 +4298,9 @@ final class Schema11 extends i0.VersionedSchema {
|
||||||
personEntity,
|
personEntity,
|
||||||
assetFaceEntity,
|
assetFaceEntity,
|
||||||
storeEntity,
|
storeEntity,
|
||||||
localTrashedAssetEntity,
|
trashedLocalAssetEntity,
|
||||||
idxLatLng,
|
idxLatLng,
|
||||||
idxLocalTrashedAssetRemoteId,
|
idxTrashedLocalAssetChecksum,
|
||||||
];
|
];
|
||||||
late final Shape20 userEntity = Shape20(
|
late final Shape20 userEntity = Shape20(
|
||||||
source: i0.VersionedTable(
|
source: i0.VersionedTable(
|
||||||
|
|
@ -4645,13 +4645,22 @@ final class Schema11 extends i0.VersionedSchema {
|
||||||
),
|
),
|
||||||
alias: null,
|
alias: null,
|
||||||
);
|
);
|
||||||
late final Shape22 localTrashedAssetEntity = Shape22(
|
late final Shape22 trashedLocalAssetEntity = Shape22(
|
||||||
source: i0.VersionedTable(
|
source: i0.VersionedTable(
|
||||||
entityName: 'local_trashed_asset_entity',
|
entityName: 'trashed_local_asset_entity',
|
||||||
withoutRowId: true,
|
withoutRowId: true,
|
||||||
isStrict: true,
|
isStrict: true,
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
columns: [_column_0, _column_95, _column_9],
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_95,
|
||||||
|
_column_22,
|
||||||
|
_column_1,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_96,
|
||||||
|
],
|
||||||
attachedDatabase: database,
|
attachedDatabase: database,
|
||||||
),
|
),
|
||||||
alias: null,
|
alias: null,
|
||||||
|
|
@ -4660,9 +4669,9 @@ final class Schema11 extends i0.VersionedSchema {
|
||||||
'idx_lat_lng',
|
'idx_lat_lng',
|
||||||
'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)',
|
'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)',
|
||||||
);
|
);
|
||||||
final i1.Index idxLocalTrashedAssetRemoteId = i1.Index(
|
final i1.Index idxTrashedLocalAssetChecksum = i1.Index(
|
||||||
'idx_local_trashed_asset_remote_id',
|
'idx_trashed_local_asset_checksum',
|
||||||
'CREATE INDEX IF NOT EXISTS idx_local_trashed_asset_remote_id ON local_trashed_asset_entity (remote_id)',
|
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4670,21 +4679,35 @@ class Shape22 extends i0.VersionedTable {
|
||||||
Shape22({required super.source, required super.alias}) : super.aliased();
|
Shape22({required super.source, required super.alias}) : super.aliased();
|
||||||
i1.GeneratedColumn<String> get id =>
|
i1.GeneratedColumn<String> get id =>
|
||||||
columnsByName['id']! as i1.GeneratedColumn<String>;
|
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||||
i1.GeneratedColumn<String> get remoteId =>
|
i1.GeneratedColumn<String> get albumId =>
|
||||||
columnsByName['remote_id']! as i1.GeneratedColumn<String>;
|
columnsByName['album_id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get checksum =>
|
||||||
|
columnsByName['checksum']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get name =>
|
||||||
|
columnsByName['name']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<int> get type =>
|
||||||
|
columnsByName['type']! as i1.GeneratedColumn<int>;
|
||||||
i1.GeneratedColumn<DateTime> get createdAt =>
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<DateTime> get updatedAt =>
|
||||||
|
columnsByName['updated_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<int> get size =>
|
||||||
|
columnsByName['size']! as i1.GeneratedColumn<int>;
|
||||||
}
|
}
|
||||||
|
|
||||||
i1.GeneratedColumn<String> _column_95(String aliasedName) =>
|
i1.GeneratedColumn<String> _column_95(String aliasedName) =>
|
||||||
i1.GeneratedColumn<String>(
|
i1.GeneratedColumn<String>(
|
||||||
'remote_id',
|
'album_id',
|
||||||
aliasedName,
|
aliasedName,
|
||||||
false,
|
false,
|
||||||
type: i1.DriftSqlType.string,
|
type: i1.DriftSqlType.string,
|
||||||
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
);
|
||||||
'REFERENCES remote_asset_entity (id) ON DELETE CASCADE',
|
i1.GeneratedColumn<int> _column_96(String aliasedName) =>
|
||||||
),
|
i1.GeneratedColumn<int>(
|
||||||
|
'size',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
);
|
);
|
||||||
i0.MigrationStepWithVersion migrationSteps({
|
i0.MigrationStepWithVersion migrationSteps({
|
||||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,12 @@ import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
||||||
import 'package:immich_mobile/domain/models/local_trashed_asset.model.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_trashed_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_trashed_asset.entity.drift.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
|
|
||||||
typedef LocalRemoteIds = ({String localId, String remoteId});
|
typedef AssetsByAlbums = Map<String, List<LocalAsset>>;
|
||||||
|
|
||||||
class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
|
|
@ -58,7 +56,7 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> delete(Iterable<String> ids) {
|
Future<void> delete(List<String> ids) {
|
||||||
if (ids.isEmpty) {
|
if (ids.isEmpty) {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
}
|
}
|
||||||
|
|
@ -70,27 +68,37 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> trash(Iterable<LocalRemoteIds> ids) async {
|
Future<void> trash(AssetsByAlbums assetsByAlbums) async {
|
||||||
if (ids.isEmpty) return;
|
if (assetsByAlbums.isEmpty) {
|
||||||
|
return;
|
||||||
final Map<String, String> idToRemote = {for (final e in ids) e.localId: e.remoteId};
|
|
||||||
|
|
||||||
final localRows = await (_db.localAssetEntity.select()..where((t) => t.id.isIn(idToRemote.keys))).get();
|
|
||||||
|
|
||||||
await _db.batch((batch) {
|
|
||||||
for (final row in localRows) {
|
|
||||||
final remoteId = idToRemote[row.id];
|
|
||||||
if (remoteId == null) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
batch.insert(
|
|
||||||
_db.localTrashedAssetEntity,
|
final companions = <TrashedLocalAssetEntityCompanion>[];
|
||||||
LocalTrashedAssetEntityCompanion(id: Value(row.id), remoteId: Value(remoteId)),
|
final idToDelete = <String>{};
|
||||||
mode: InsertMode.insertOrReplace,
|
|
||||||
|
assetsByAlbums.forEach((albumId, assets) {
|
||||||
|
for (final asset in assets) {
|
||||||
|
idToDelete.add(asset.id);
|
||||||
|
companions.add(
|
||||||
|
TrashedLocalAssetEntityCompanion(
|
||||||
|
id: Value(asset.id),
|
||||||
|
name: Value(asset.name),
|
||||||
|
albumId: Value(albumId),
|
||||||
|
checksum: asset.checksum == null ? const Value.absent() : Value(asset.checksum),
|
||||||
|
type: Value(asset.type),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (final slice in idToRemote.keys.slices(32000)) {
|
});
|
||||||
batch.deleteWhere(_db.localAssetEntity, (e) => e.id.isIn(slice));
|
|
||||||
|
await _db.transaction(() async {
|
||||||
|
for (final slice in companions.slices(200)) {
|
||||||
|
await _db.batch((batch) {
|
||||||
|
batch.insertAllOnConflictUpdate(_db.trashedLocalAssetEntity, slice);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (final slice in idToDelete.slices(800)) {
|
||||||
|
await (_db.delete(_db.localAssetEntity)..where((e) => e.id.isIn(slice))).go();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -128,41 +136,30 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
return query.map((localAlbum) => localAlbum.toDto()).get();
|
return query.map((localAlbum) => localAlbum.toDto()).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<LocalAsset>> getBackupSelectedAssets(Iterable<String> checksums) {
|
Future<AssetsByAlbums> getBackupSelectedAssetsByAlbum(Iterable<String> checksums) async {
|
||||||
if (checksums.isEmpty) {
|
if (checksums.isEmpty) {
|
||||||
return Future.value([]);
|
return {};
|
||||||
}
|
|
||||||
final backedUpAssetIds = _db.localAlbumAssetEntity.selectOnly()
|
|
||||||
..addColumns([_db.localAlbumAssetEntity.assetId])
|
|
||||||
..join([
|
|
||||||
innerJoin(
|
|
||||||
_db.localAlbumEntity,
|
|
||||||
_db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id),
|
|
||||||
useColumns: false,
|
|
||||||
),
|
|
||||||
])
|
|
||||||
..where(_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected));
|
|
||||||
final query = _db.localAssetEntity.select()
|
|
||||||
..where((la) => la.checksum.isIn(checksums) & la.id.isInQuery(backedUpAssetIds));
|
|
||||||
return query.map((row) => row.toDto()).get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<LocalTrashedAsset>> getLocalTrashedAssets(Iterable<String> remoteIds) {
|
final lAlbumAsset = _db.localAlbumAssetEntity;
|
||||||
if (remoteIds.isEmpty) {
|
final lAlbum = _db.localAlbumEntity;
|
||||||
return Future.value([]);
|
final lAsset = _db.localAssetEntity;
|
||||||
}
|
|
||||||
final query = _db.localTrashedAssetEntity.select()..where((t) => t.remoteId.isIn(remoteIds));
|
|
||||||
return query.map((row) => row.toDto()).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteLocalTrashedAssets(Iterable<String> remoteIds) {
|
final result = <String, List<LocalAsset>>{};
|
||||||
if (remoteIds.isEmpty) {
|
|
||||||
return Future.value();
|
for (final slice in checksums.toSet().slices(800)) {
|
||||||
|
final rows = await (_db.select(lAlbumAsset).join([
|
||||||
|
innerJoin(lAlbum, lAlbumAsset.albumId.equalsExp(lAlbum.id)),
|
||||||
|
innerJoin(lAsset, lAlbumAsset.assetId.equalsExp(lAsset.id)),
|
||||||
|
])..where(lAlbum.backupSelection.equalsValue(BackupSelection.selected) & lAsset.checksum.isIn(slice))).get();
|
||||||
|
|
||||||
|
for (final row in rows) {
|
||||||
|
final albumId = row.readTable(lAlbumAsset).albumId;
|
||||||
|
final assetData = row.readTable(lAsset);
|
||||||
|
final asset = assetData.toDto();
|
||||||
|
(result[albumId] ??= <LocalAsset>[]).add(asset);
|
||||||
}
|
}
|
||||||
return _db.batch((batch) {
|
|
||||||
for (final slice in remoteIds.slices(32000)) {
|
|
||||||
batch.deleteWhere(_db.localTrashedAssetEntity, (e) => e.remoteId.isIn(slice));
|
|
||||||
}
|
}
|
||||||
});
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -241,13 +241,4 @@ class RemoteAssetRepository extends DriftDatabaseRepository {
|
||||||
Future<int> getCount() {
|
Future<int> getCount() {
|
||||||
return _db.managers.remoteAssetEntity.count();
|
return _db.managers.remoteAssetEntity.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<RemoteAsset>> getByChecksums(Iterable<String> checksums, {bool? isTrashed}) {
|
|
||||||
if (checksums.isEmpty) return Future.value([]);
|
|
||||||
final query = _db.remoteAssetEntity.select()..where((rae) => rae.checksum.isIn(checksums));
|
|
||||||
if (isTrashed != null) {
|
|
||||||
query.where((rae) => isTrashed ? rae.deletedAt.isNotNull() : rae.deletedAt.isNull());
|
|
||||||
}
|
|
||||||
return query.map((row) => row.toDto()).get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/asset/trashed_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.drift.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
|
|
||||||
|
class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
|
||||||
|
final Drift _db;
|
||||||
|
|
||||||
|
const DriftTrashedLocalAssetRepository(this._db) : super(_db);
|
||||||
|
|
||||||
|
Future<void> updateChecksums(Iterable<TrashedAsset> assets) {
|
||||||
|
if (assets.isEmpty) {
|
||||||
|
return Future.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _db.batch((batch) async {
|
||||||
|
for (final asset in assets) {
|
||||||
|
batch.update(
|
||||||
|
_db.trashedLocalAssetEntity,
|
||||||
|
TrashedLocalAssetEntityCompanion(checksum: Value(asset.checksum)),
|
||||||
|
where: (e) => e.id.equals(asset.id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Iterable<TrashedAsset>> getToHash(String albumId) {
|
||||||
|
final query = _db.trashedLocalAssetEntity.select()..where((r) => r.albumId.equals(albumId) & r.checksum.isNull());
|
||||||
|
return query.map((row) => row.toDto(albumId)).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<TrashedAsset>> getToRestore() async {
|
||||||
|
final trashed = _db.trashedLocalAssetEntity;
|
||||||
|
final remote = _db.remoteAssetEntity;
|
||||||
|
final album = _db.localAlbumEntity;
|
||||||
|
|
||||||
|
final selectedAlbumIds = (_db.selectOnly(album)
|
||||||
|
..addColumns([album.id])
|
||||||
|
..where(album.backupSelection.equalsValue(BackupSelection.selected)));
|
||||||
|
|
||||||
|
final rows = await (_db.select(trashed).join([
|
||||||
|
innerJoin(remote, remote.checksum.equalsExp(trashed.checksum)),
|
||||||
|
])..where(trashed.albumId.isInQuery(selectedAlbumIds) & remote.deletedAt.isNull())).get();
|
||||||
|
|
||||||
|
return rows.map((result) {
|
||||||
|
final assetData = result.readTable(trashed);
|
||||||
|
return assetData.toDto(assetData.albumId);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies resulted snapshot of trashed assets:
|
||||||
|
/// - upserts incoming rows
|
||||||
|
/// - deletes rows that are not present in the snapshot
|
||||||
|
Future<void> applyTrashSnapshot(Iterable<TrashedAsset> assets, String albumId) async {
|
||||||
|
if (assets.isEmpty) {
|
||||||
|
await _db.delete(_db.trashedLocalAssetEntity).go();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _db.transaction(() async {
|
||||||
|
final table = _db.trashedLocalAssetEntity;
|
||||||
|
|
||||||
|
final companions = assets.map(
|
||||||
|
(a) => TrashedLocalAssetEntityCompanion.insert(
|
||||||
|
id: a.id,
|
||||||
|
albumId: albumId,
|
||||||
|
checksum: a.checksum == null ? const Value.absent() : Value(a.checksum),
|
||||||
|
name: a.name,
|
||||||
|
type: a.type,
|
||||||
|
createdAt: Value(a.createdAt),
|
||||||
|
updatedAt: Value(a.updatedAt),
|
||||||
|
size: a.size == null ? const Value.absent() : Value(a.size),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
for (final slice in companions.slices(400)) {
|
||||||
|
await _db.batch((b) {
|
||||||
|
b.insertAllOnConflictUpdate(table, slice);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final keepIds = assets.map((asset) => asset.id);
|
||||||
|
if (keepIds.length <= 900) {
|
||||||
|
await (_db.delete(table)..where((row) => row.id.isNotIn(keepIds))).go();
|
||||||
|
} else {
|
||||||
|
final existingIds = await (_db.selectOnly(table)..addColumns([table.id])).map((r) => r.read(table.id)!).get();
|
||||||
|
final toDelete = existingIds.where((id) => !keepIds.contains(id));
|
||||||
|
for (final slice in toDelete.slices(400)) {
|
||||||
|
await (_db.delete(table)..where((row) => row.id.isIn(slice))).go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<int> watchCount() {
|
||||||
|
final t = _db.trashedLocalAssetEntity;
|
||||||
|
return (_db.selectOnly(t)..addColumns([t.id.count()])).watchSingle().map((row) => row.read<int>(t.id.count()) ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<int> watchHashedCount() {
|
||||||
|
final t = _db.trashedLocalAssetEntity;
|
||||||
|
return (_db.selectOnly(t)
|
||||||
|
..addColumns([t.id.count()])
|
||||||
|
..where(t.checksum.isNotNull()))
|
||||||
|
.watchSingle()
|
||||||
|
.map((row) => row.read<int>(t.id.count()) ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> delete(Iterable<String> ids) {
|
||||||
|
if (ids.isEmpty) {
|
||||||
|
return Future.value();
|
||||||
|
}
|
||||||
|
return _db.batch((batch) {
|
||||||
|
for (final slice in ids.slices(32000)) {
|
||||||
|
batch.deleteWhere(_db.trashedLocalAssetEntity, (e) => e.id.isIn(slice));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
118
mobile/lib/platform/native_sync_api.g.dart
generated
118
mobile/lib/platform/native_sync_api.g.dart
generated
|
|
@ -41,6 +41,7 @@ class PlatformAsset {
|
||||||
required this.durationInSeconds,
|
required this.durationInSeconds,
|
||||||
required this.orientation,
|
required this.orientation,
|
||||||
required this.isFavorite,
|
required this.isFavorite,
|
||||||
|
this.size,
|
||||||
});
|
});
|
||||||
|
|
||||||
String id;
|
String id;
|
||||||
|
|
@ -63,8 +64,22 @@ class PlatformAsset {
|
||||||
|
|
||||||
bool isFavorite;
|
bool isFavorite;
|
||||||
|
|
||||||
|
int? size;
|
||||||
|
|
||||||
List<Object?> _toList() {
|
List<Object?> _toList() {
|
||||||
return <Object?>[id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite];
|
return <Object?>[
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
createdAt,
|
||||||
|
updatedAt,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
durationInSeconds,
|
||||||
|
orientation,
|
||||||
|
isFavorite,
|
||||||
|
size,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Object encode() {
|
Object encode() {
|
||||||
|
|
@ -84,6 +99,7 @@ class PlatformAsset {
|
||||||
durationInSeconds: result[7]! as int,
|
durationInSeconds: result[7]! as int,
|
||||||
orientation: result[8]! as int,
|
orientation: result[8]! as int,
|
||||||
isFavorite: result[9]! as bool,
|
isFavorite: result[9]! as bool,
|
||||||
|
size: result[10] as int?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,6 +221,45 @@ class SyncDelta {
|
||||||
int get hashCode => Object.hashAll(_toList());
|
int get hashCode => Object.hashAll(_toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TrashedAssetParams {
|
||||||
|
TrashedAssetParams({required this.id, required this.type, this.albumId});
|
||||||
|
|
||||||
|
String id;
|
||||||
|
|
||||||
|
int type;
|
||||||
|
|
||||||
|
String? albumId;
|
||||||
|
|
||||||
|
List<Object?> _toList() {
|
||||||
|
return <Object?>[id, type, albumId];
|
||||||
|
}
|
||||||
|
|
||||||
|
Object encode() {
|
||||||
|
return _toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
static TrashedAssetParams decode(Object result) {
|
||||||
|
result as List<Object?>;
|
||||||
|
return TrashedAssetParams(id: result[0]! as String, type: result[1]! as int, albumId: result[2] as String?);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (other is! TrashedAssetParams || other.runtimeType != runtimeType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (identical(this, other)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return _deepEquals(encode(), other.encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||||
|
int get hashCode => Object.hashAll(_toList());
|
||||||
|
}
|
||||||
|
|
||||||
class _PigeonCodec extends StandardMessageCodec {
|
class _PigeonCodec extends StandardMessageCodec {
|
||||||
const _PigeonCodec();
|
const _PigeonCodec();
|
||||||
@override
|
@override
|
||||||
|
|
@ -221,6 +276,9 @@ class _PigeonCodec extends StandardMessageCodec {
|
||||||
} else if (value is SyncDelta) {
|
} else if (value is SyncDelta) {
|
||||||
buffer.putUint8(131);
|
buffer.putUint8(131);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
|
} else if (value is TrashedAssetParams) {
|
||||||
|
buffer.putUint8(132);
|
||||||
|
writeValue(buffer, value.encode());
|
||||||
} else {
|
} else {
|
||||||
super.writeValue(buffer, value);
|
super.writeValue(buffer, value);
|
||||||
}
|
}
|
||||||
|
|
@ -235,6 +293,8 @@ class _PigeonCodec extends StandardMessageCodec {
|
||||||
return PlatformAlbum.decode(readValue(buffer)!);
|
return PlatformAlbum.decode(readValue(buffer)!);
|
||||||
case 131:
|
case 131:
|
||||||
return SyncDelta.decode(readValue(buffer)!);
|
return SyncDelta.decode(readValue(buffer)!);
|
||||||
|
case 132:
|
||||||
|
return TrashedAssetParams.decode(readValue(buffer)!);
|
||||||
default:
|
default:
|
||||||
return super.readValueOfType(type, buffer);
|
return super.readValueOfType(type, buffer);
|
||||||
}
|
}
|
||||||
|
|
@ -495,4 +555,60 @@ class NativeSyncApi {
|
||||||
return (pigeonVar_replyList[0] as List<Object?>?)!.cast<Uint8List?>();
|
return (pigeonVar_replyList[0] as List<Object?>?)!.cast<Uint8List?>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<PlatformAsset>> getTrashedAssetsForAlbum(String albumId, {int? updatedTimeCond}) async {
|
||||||
|
final String pigeonVar_channelName =
|
||||||
|
'dev.flutter.pigeon.immich_mobile.NativeSyncApi.getTrashedAssetsForAlbum$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
|
pigeonVar_channelName,
|
||||||
|
pigeonChannelCodec,
|
||||||
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[albumId, updatedTimeCond]);
|
||||||
|
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
if (pigeonVar_replyList == null) {
|
||||||
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: pigeonVar_replyList[0]! as String,
|
||||||
|
message: pigeonVar_replyList[1] as String?,
|
||||||
|
details: pigeonVar_replyList[2],
|
||||||
|
);
|
||||||
|
} else if (pigeonVar_replyList[0] == null) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: 'null-error',
|
||||||
|
message: 'Host platform returned null value for non-null return value.',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (pigeonVar_replyList[0] as List<Object?>?)!.cast<PlatformAsset>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Uint8List?>> hashTrashedAssets(List<TrashedAssetParams> trashedAssets) async {
|
||||||
|
final String pigeonVar_channelName =
|
||||||
|
'dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashTrashedAssets$pigeonVar_messageChannelSuffix';
|
||||||
|
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
|
pigeonVar_channelName,
|
||||||
|
pigeonChannelCodec,
|
||||||
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[trashedAssets]);
|
||||||
|
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
if (pigeonVar_replyList == null) {
|
||||||
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: pigeonVar_replyList[0]! as String,
|
||||||
|
message: pigeonVar_replyList[1] as String?,
|
||||||
|
details: pigeonVar_replyList[2],
|
||||||
|
);
|
||||||
|
} else if (pigeonVar_replyList[0] == null) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: 'null-error',
|
||||||
|
message: 'Host platform returned null value for non-null return value.',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (pigeonVar_replyList[0] as List<Object?>?)!.cast<Uint8List?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/services/asset.service.dart';
|
import 'package:immich_mobile/domain/services/asset.service.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||||
|
|
||||||
final localAssetRepository = Provider<DriftLocalAssetRepository>(
|
final localAssetRepository = Provider<DriftLocalAssetRepository>(
|
||||||
|
|
@ -12,6 +13,10 @@ final remoteAssetRepositoryProvider = Provider<RemoteAssetRepository>(
|
||||||
(ref) => RemoteAssetRepository(ref.watch(driftProvider)),
|
(ref) => RemoteAssetRepository(ref.watch(driftProvider)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final trashedLocalAssetRepository = Provider<DriftTrashedLocalAssetRepository>(
|
||||||
|
(ref) => DriftTrashedLocalAssetRepository(ref.watch(driftProvider)),
|
||||||
|
);
|
||||||
|
|
||||||
final assetServiceProvider = Provider(
|
final assetServiceProvider = Provider(
|
||||||
(ref) => AssetService(
|
(ref) => AssetService(
|
||||||
remoteAssetRepository: ref.watch(remoteAssetRepositoryProvider),
|
remoteAssetRepository: ref.watch(remoteAssetRepositoryProvider),
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ final syncStreamRepositoryProvider = Provider((ref) => SyncStreamRepository(ref.
|
||||||
final localSyncServiceProvider = Provider(
|
final localSyncServiceProvider = Provider(
|
||||||
(ref) => LocalSyncService(
|
(ref) => LocalSyncService(
|
||||||
localAlbumRepository: ref.watch(localAlbumRepository),
|
localAlbumRepository: ref.watch(localAlbumRepository),
|
||||||
|
trashSyncService: ref.watch(trashSyncServiceProvider),
|
||||||
nativeSyncApi: ref.watch(nativeSyncApiProvider),
|
nativeSyncApi: ref.watch(nativeSyncApiProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -39,5 +40,6 @@ final hashServiceProvider = Provider(
|
||||||
localAssetRepository: ref.watch(localAssetRepository),
|
localAssetRepository: ref.watch(localAssetRepository),
|
||||||
storageRepository: ref.watch(storageRepositoryProvider),
|
storageRepository: ref.watch(storageRepositoryProvider),
|
||||||
nativeSyncApi: ref.watch(nativeSyncApiProvider),
|
nativeSyncApi: ref.watch(nativeSyncApiProvider),
|
||||||
|
trashSyncService: ref.watch(trashSyncServiceProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,31 @@
|
||||||
|
import 'package:async/async.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/services/trash_sync.service.dart';
|
import 'package:immich_mobile/domain/services/trash_sync.service.dart';
|
||||||
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
|
import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
|
||||||
|
|
||||||
import 'asset.provider.dart';
|
import 'asset.provider.dart';
|
||||||
|
|
||||||
|
typedef TrashedAssetsCount = ({int total, int hashed});
|
||||||
|
|
||||||
final trashSyncServiceProvider = Provider(
|
final trashSyncServiceProvider = Provider(
|
||||||
(ref) => TrashSyncService(
|
(ref) => TrashSyncService(
|
||||||
appSettingsService: ref.watch(appSettingsServiceProvider),
|
appSettingsService: ref.watch(appSettingsServiceProvider),
|
||||||
remoteAssetRepository: ref.watch(remoteAssetRepositoryProvider),
|
nativeSyncApi: ref.watch(nativeSyncApiProvider),
|
||||||
localAssetRepository: ref.watch(localAssetRepository),
|
localAssetRepository: ref.watch(localAssetRepository),
|
||||||
|
localAlbumRepository: ref.watch(localAlbumRepository),
|
||||||
|
trashedLocalAssetRepository: ref.watch(trashedLocalAssetRepository),
|
||||||
localFilesManager: ref.watch(localFilesManagerRepositoryProvider),
|
localFilesManager: ref.watch(localFilesManagerRepositoryProvider),
|
||||||
storageRepository: ref.watch(storageRepositoryProvider),
|
storageRepository: ref.watch(storageRepositoryProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final trashedAssetsCountProvider = StreamProvider<TrashedAssetsCount>((ref) {
|
||||||
|
final repo = ref.watch(trashedLocalAssetRepository);
|
||||||
|
final total$ = repo.watchCount();
|
||||||
|
final hashed$ = repo.watchHashedCount();
|
||||||
|
return StreamZip<int>([total$, hashed$]).map((values) => (total: values[0], hashed: values[1]));
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,12 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/trash_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/sync_status.provider.dart';
|
import 'package:immich_mobile/providers/sync_status.provider.dart';
|
||||||
import 'package:immich_mobile/utils/migration.dart';
|
import 'package:immich_mobile/utils/migration.dart';
|
||||||
import 'package:immich_mobile/widgets/settings/beta_sync_settings/entity_count_tile.dart';
|
import 'package:immich_mobile/widgets/settings/beta_sync_settings/entity_count_tile.dart';
|
||||||
|
|
@ -225,6 +226,7 @@ class _SyncStatsCounts extends ConsumerWidget {
|
||||||
final localAlbumService = ref.watch(localAlbumServiceProvider);
|
final localAlbumService = ref.watch(localAlbumServiceProvider);
|
||||||
final remoteAlbumService = ref.watch(remoteAlbumServiceProvider);
|
final remoteAlbumService = ref.watch(remoteAlbumServiceProvider);
|
||||||
final memoryService = ref.watch(driftMemoryServiceProvider);
|
final memoryService = ref.watch(driftMemoryServiceProvider);
|
||||||
|
final trashSyncService = ref.watch(trashSyncServiceProvider);
|
||||||
|
|
||||||
Future<List<dynamic>> loadCounts() async {
|
Future<List<dynamic>> loadCounts() async {
|
||||||
final assetCounts = assetService.getAssetCounts();
|
final assetCounts = assetService.getAssetCounts();
|
||||||
|
|
@ -347,6 +349,42 @@ class _SyncStatsCounts extends ConsumerWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (trashSyncService.isAutoSyncMode) ...[
|
||||||
|
_SectionHeaderText(text: "trashed".t(context: context)),
|
||||||
|
Consumer(
|
||||||
|
builder: (context, ref, _) {
|
||||||
|
final counts = ref.watch(trashedAssetsCountProvider);
|
||||||
|
return counts.when(
|
||||||
|
data: (c) => Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
|
||||||
|
child: Flex(
|
||||||
|
direction: Axis.horizontal,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
spacing: 8.0,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: EntitiyCountTile(
|
||||||
|
label: "local".t(context: context),
|
||||||
|
count: c.total,
|
||||||
|
icon: Icons.delete_outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: EntitiyCountTile(
|
||||||
|
label: "hashed_assets".t(context: context),
|
||||||
|
count: c.hashed,
|
||||||
|
icon: Icons.tag,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
loading: () => const CircularProgressIndicator(),
|
||||||
|
error: (e, st) => Text('Error: $e'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ class PlatformAsset {
|
||||||
final int durationInSeconds;
|
final int durationInSeconds;
|
||||||
final int orientation;
|
final int orientation;
|
||||||
final bool isFavorite;
|
final bool isFavorite;
|
||||||
|
final int? size;
|
||||||
|
|
||||||
const PlatformAsset({
|
const PlatformAsset({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
|
@ -36,6 +37,7 @@ class PlatformAsset {
|
||||||
this.durationInSeconds = 0,
|
this.durationInSeconds = 0,
|
||||||
this.orientation = 0,
|
this.orientation = 0,
|
||||||
this.isFavorite = false,
|
this.isFavorite = false,
|
||||||
|
this.size,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,6 +73,19 @@ class SyncDelta {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TrashedAssetParams {
|
||||||
|
final String id;
|
||||||
|
// Follows AssetType enum from base_asset.model.dart
|
||||||
|
final int type;
|
||||||
|
final String? albumId;
|
||||||
|
|
||||||
|
const TrashedAssetParams({
|
||||||
|
required this.id,
|
||||||
|
required this.type,
|
||||||
|
this.albumId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@HostApi()
|
@HostApi()
|
||||||
abstract class NativeSyncApi {
|
abstract class NativeSyncApi {
|
||||||
bool shouldFullSync();
|
bool shouldFullSync();
|
||||||
|
|
@ -96,4 +111,11 @@ abstract class NativeSyncApi {
|
||||||
|
|
||||||
@TaskQueue(type: TaskQueueType.serialBackgroundThread)
|
@TaskQueue(type: TaskQueueType.serialBackgroundThread)
|
||||||
List<Uint8List?> hashPaths(List<String> paths);
|
List<Uint8List?> hashPaths(List<String> paths);
|
||||||
|
|
||||||
|
@TaskQueue(type: TaskQueueType.serialBackgroundThread)
|
||||||
|
List<PlatformAsset> getTrashedAssetsForAlbum(String albumId, {int? updatedTimeCond});
|
||||||
|
|
||||||
|
@TaskQueue(type: TaskQueueType.serialBackgroundThread)
|
||||||
|
List<Uint8List?> hashTrashedAssets(List<TrashedAssetParams> trashedAssets);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ void main() {
|
||||||
late MockLocalAssetRepository mockAssetRepo;
|
late MockLocalAssetRepository mockAssetRepo;
|
||||||
late MockStorageRepository mockStorageRepo;
|
late MockStorageRepository mockStorageRepo;
|
||||||
late MockNativeSyncApi mockNativeApi;
|
late MockNativeSyncApi mockNativeApi;
|
||||||
|
late MockTrashSyncService mockTrashSyncService;
|
||||||
final sortBy = {SortLocalAlbumsBy.backupSelection, SortLocalAlbumsBy.isIosSharedAlbum};
|
final sortBy = {SortLocalAlbumsBy.backupSelection, SortLocalAlbumsBy.isIosSharedAlbum};
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
|
|
@ -28,12 +29,14 @@ void main() {
|
||||||
mockAssetRepo = MockLocalAssetRepository();
|
mockAssetRepo = MockLocalAssetRepository();
|
||||||
mockStorageRepo = MockStorageRepository();
|
mockStorageRepo = MockStorageRepository();
|
||||||
mockNativeApi = MockNativeSyncApi();
|
mockNativeApi = MockNativeSyncApi();
|
||||||
|
mockTrashSyncService = MockTrashSyncService();
|
||||||
|
|
||||||
sut = HashService(
|
sut = HashService(
|
||||||
localAlbumRepository: mockAlbumRepo,
|
localAlbumRepository: mockAlbumRepo,
|
||||||
localAssetRepository: mockAssetRepo,
|
localAssetRepository: mockAssetRepo,
|
||||||
storageRepository: mockStorageRepo,
|
storageRepository: mockStorageRepo,
|
||||||
nativeSyncApi: mockNativeApi,
|
nativeSyncApi: mockNativeApi,
|
||||||
|
trashSyncService: mockTrashSyncService,
|
||||||
);
|
);
|
||||||
|
|
||||||
registerFallbackValue(LocalAlbumStub.recent);
|
registerFallbackValue(LocalAlbumStub.recent);
|
||||||
|
|
@ -138,6 +141,7 @@ void main() {
|
||||||
localAssetRepository: mockAssetRepo,
|
localAssetRepository: mockAssetRepo,
|
||||||
storageRepository: mockStorageRepo,
|
storageRepository: mockStorageRepo,
|
||||||
nativeSyncApi: mockNativeApi,
|
nativeSyncApi: mockNativeApi,
|
||||||
|
trashSyncService: mockTrashSyncService,
|
||||||
batchFileLimit: 1,
|
batchFileLimit: 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -173,6 +177,7 @@ void main() {
|
||||||
localAssetRepository: mockAssetRepo,
|
localAssetRepository: mockAssetRepo,
|
||||||
storageRepository: mockStorageRepo,
|
storageRepository: mockStorageRepo,
|
||||||
nativeSyncApi: mockNativeApi,
|
nativeSyncApi: mockNativeApi,
|
||||||
|
trashSyncService: mockTrashSyncService,
|
||||||
batchSizeLimit: 80,
|
batchSizeLimit: 80,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
318
mobile/test/drift/main/generated/schema_v11.dart
generated
318
mobile/test/drift/main/generated/schema_v11.dart
generated
|
|
@ -7074,12 +7074,12 @@ class StoreEntityCompanion extends UpdateCompanion<StoreEntityData> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalTrashedAssetEntity extends Table
|
class TrashedLocalAssetEntity extends Table
|
||||||
with TableInfo<LocalTrashedAssetEntity, LocalTrashedAssetEntityData> {
|
with TableInfo<TrashedLocalAssetEntity, TrashedLocalAssetEntityData> {
|
||||||
@override
|
@override
|
||||||
final GeneratedDatabase attachedDatabase;
|
final GeneratedDatabase attachedDatabase;
|
||||||
final String? _alias;
|
final String? _alias;
|
||||||
LocalTrashedAssetEntity(this.attachedDatabase, [this._alias]);
|
TrashedLocalAssetEntity(this.attachedDatabase, [this._alias]);
|
||||||
late final GeneratedColumn<String> id = GeneratedColumn<String>(
|
late final GeneratedColumn<String> id = GeneratedColumn<String>(
|
||||||
'id',
|
'id',
|
||||||
aliasedName,
|
aliasedName,
|
||||||
|
|
@ -7087,15 +7087,33 @@ class LocalTrashedAssetEntity extends Table
|
||||||
type: DriftSqlType.string,
|
type: DriftSqlType.string,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
);
|
);
|
||||||
late final GeneratedColumn<String> remoteId = GeneratedColumn<String>(
|
late final GeneratedColumn<String> albumId = GeneratedColumn<String>(
|
||||||
'remote_id',
|
'album_id',
|
||||||
aliasedName,
|
aliasedName,
|
||||||
false,
|
false,
|
||||||
type: DriftSqlType.string,
|
type: DriftSqlType.string,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
);
|
||||||
'REFERENCES remote_asset_entity (id) ON DELETE CASCADE',
|
late final GeneratedColumn<String> checksum = GeneratedColumn<String>(
|
||||||
),
|
'checksum',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
);
|
||||||
|
late final GeneratedColumn<String> name = GeneratedColumn<String>(
|
||||||
|
'name',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
);
|
||||||
|
late final GeneratedColumn<int> type = GeneratedColumn<int>(
|
||||||
|
'type',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: DriftSqlType.int,
|
||||||
|
requiredDuringInsert: true,
|
||||||
);
|
);
|
||||||
late final GeneratedColumn<DateTime> createdAt = GeneratedColumn<DateTime>(
|
late final GeneratedColumn<DateTime> createdAt = GeneratedColumn<DateTime>(
|
||||||
'created_at',
|
'created_at',
|
||||||
|
|
@ -7105,40 +7123,84 @@ class LocalTrashedAssetEntity extends Table
|
||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: const CustomExpression('CURRENT_TIMESTAMP'),
|
defaultValue: const CustomExpression('CURRENT_TIMESTAMP'),
|
||||||
);
|
);
|
||||||
|
late final GeneratedColumn<DateTime> updatedAt = GeneratedColumn<DateTime>(
|
||||||
|
'updated_at',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: DriftSqlType.dateTime,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const CustomExpression('CURRENT_TIMESTAMP'),
|
||||||
|
);
|
||||||
|
late final GeneratedColumn<int> size = GeneratedColumn<int>(
|
||||||
|
'size',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
);
|
||||||
@override
|
@override
|
||||||
List<GeneratedColumn> get $columns => [id, remoteId, createdAt];
|
List<GeneratedColumn> get $columns => [
|
||||||
|
id,
|
||||||
|
albumId,
|
||||||
|
checksum,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
createdAt,
|
||||||
|
updatedAt,
|
||||||
|
size,
|
||||||
|
];
|
||||||
@override
|
@override
|
||||||
String get aliasedName => _alias ?? actualTableName;
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
@override
|
@override
|
||||||
String get actualTableName => $name;
|
String get actualTableName => $name;
|
||||||
static const String $name = 'local_trashed_asset_entity';
|
static const String $name = 'trashed_local_asset_entity';
|
||||||
@override
|
@override
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
@override
|
@override
|
||||||
LocalTrashedAssetEntityData map(
|
TrashedLocalAssetEntityData map(
|
||||||
Map<String, dynamic> data, {
|
Map<String, dynamic> data, {
|
||||||
String? tablePrefix,
|
String? tablePrefix,
|
||||||
}) {
|
}) {
|
||||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||||
return LocalTrashedAssetEntityData(
|
return TrashedLocalAssetEntityData(
|
||||||
id: attachedDatabase.typeMapping.read(
|
id: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.string,
|
DriftSqlType.string,
|
||||||
data['${effectivePrefix}id'],
|
data['${effectivePrefix}id'],
|
||||||
)!,
|
)!,
|
||||||
remoteId: attachedDatabase.typeMapping.read(
|
albumId: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.string,
|
DriftSqlType.string,
|
||||||
data['${effectivePrefix}remote_id'],
|
data['${effectivePrefix}album_id'],
|
||||||
|
)!,
|
||||||
|
checksum: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}checksum'],
|
||||||
|
),
|
||||||
|
name: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}name'],
|
||||||
|
)!,
|
||||||
|
type: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}type'],
|
||||||
)!,
|
)!,
|
||||||
createdAt: attachedDatabase.typeMapping.read(
|
createdAt: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.dateTime,
|
DriftSqlType.dateTime,
|
||||||
data['${effectivePrefix}created_at'],
|
data['${effectivePrefix}created_at'],
|
||||||
)!,
|
)!,
|
||||||
|
updatedAt: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.dateTime,
|
||||||
|
data['${effectivePrefix}updated_at'],
|
||||||
|
)!,
|
||||||
|
size: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}size'],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
LocalTrashedAssetEntity createAlias(String alias) {
|
TrashedLocalAssetEntity createAlias(String alias) {
|
||||||
return LocalTrashedAssetEntity(attachedDatabase, alias);
|
return TrashedLocalAssetEntity(attachedDatabase, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -7147,34 +7209,58 @@ class LocalTrashedAssetEntity extends Table
|
||||||
bool get isStrict => true;
|
bool get isStrict => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalTrashedAssetEntityData extends DataClass
|
class TrashedLocalAssetEntityData extends DataClass
|
||||||
implements Insertable<LocalTrashedAssetEntityData> {
|
implements Insertable<TrashedLocalAssetEntityData> {
|
||||||
final String id;
|
final String id;
|
||||||
final String remoteId;
|
final String albumId;
|
||||||
|
final String? checksum;
|
||||||
|
final String name;
|
||||||
|
final int type;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
const LocalTrashedAssetEntityData({
|
final DateTime updatedAt;
|
||||||
|
final int? size;
|
||||||
|
const TrashedLocalAssetEntityData({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.remoteId,
|
required this.albumId,
|
||||||
|
this.checksum,
|
||||||
|
required this.name,
|
||||||
|
required this.type,
|
||||||
required this.createdAt,
|
required this.createdAt,
|
||||||
|
required this.updatedAt,
|
||||||
|
this.size,
|
||||||
});
|
});
|
||||||
@override
|
@override
|
||||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||||
final map = <String, Expression>{};
|
final map = <String, Expression>{};
|
||||||
map['id'] = Variable<String>(id);
|
map['id'] = Variable<String>(id);
|
||||||
map['remote_id'] = Variable<String>(remoteId);
|
map['album_id'] = Variable<String>(albumId);
|
||||||
|
if (!nullToAbsent || checksum != null) {
|
||||||
|
map['checksum'] = Variable<String>(checksum);
|
||||||
|
}
|
||||||
|
map['name'] = Variable<String>(name);
|
||||||
|
map['type'] = Variable<int>(type);
|
||||||
map['created_at'] = Variable<DateTime>(createdAt);
|
map['created_at'] = Variable<DateTime>(createdAt);
|
||||||
|
map['updated_at'] = Variable<DateTime>(updatedAt);
|
||||||
|
if (!nullToAbsent || size != null) {
|
||||||
|
map['size'] = Variable<int>(size);
|
||||||
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
factory LocalTrashedAssetEntityData.fromJson(
|
factory TrashedLocalAssetEntityData.fromJson(
|
||||||
Map<String, dynamic> json, {
|
Map<String, dynamic> json, {
|
||||||
ValueSerializer? serializer,
|
ValueSerializer? serializer,
|
||||||
}) {
|
}) {
|
||||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||||
return LocalTrashedAssetEntityData(
|
return TrashedLocalAssetEntityData(
|
||||||
id: serializer.fromJson<String>(json['id']),
|
id: serializer.fromJson<String>(json['id']),
|
||||||
remoteId: serializer.fromJson<String>(json['remoteId']),
|
albumId: serializer.fromJson<String>(json['albumId']),
|
||||||
|
checksum: serializer.fromJson<String?>(json['checksum']),
|
||||||
|
name: serializer.fromJson<String>(json['name']),
|
||||||
|
type: serializer.fromJson<int>(json['type']),
|
||||||
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
||||||
|
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
|
||||||
|
size: serializer.fromJson<int?>(json['size']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override
|
@override
|
||||||
|
|
@ -7182,88 +7268,164 @@ class LocalTrashedAssetEntityData extends DataClass
|
||||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{
|
||||||
'id': serializer.toJson<String>(id),
|
'id': serializer.toJson<String>(id),
|
||||||
'remoteId': serializer.toJson<String>(remoteId),
|
'albumId': serializer.toJson<String>(albumId),
|
||||||
|
'checksum': serializer.toJson<String?>(checksum),
|
||||||
|
'name': serializer.toJson<String>(name),
|
||||||
|
'type': serializer.toJson<int>(type),
|
||||||
'createdAt': serializer.toJson<DateTime>(createdAt),
|
'createdAt': serializer.toJson<DateTime>(createdAt),
|
||||||
|
'updatedAt': serializer.toJson<DateTime>(updatedAt),
|
||||||
|
'size': serializer.toJson<int?>(size),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalTrashedAssetEntityData copyWith({
|
TrashedLocalAssetEntityData copyWith({
|
||||||
String? id,
|
String? id,
|
||||||
String? remoteId,
|
String? albumId,
|
||||||
|
Value<String?> checksum = const Value.absent(),
|
||||||
|
String? name,
|
||||||
|
int? type,
|
||||||
DateTime? createdAt,
|
DateTime? createdAt,
|
||||||
}) => LocalTrashedAssetEntityData(
|
DateTime? updatedAt,
|
||||||
|
Value<int?> size = const Value.absent(),
|
||||||
|
}) => TrashedLocalAssetEntityData(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
remoteId: remoteId ?? this.remoteId,
|
albumId: albumId ?? this.albumId,
|
||||||
|
checksum: checksum.present ? checksum.value : this.checksum,
|
||||||
|
name: name ?? this.name,
|
||||||
|
type: type ?? this.type,
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
|
size: size.present ? size.value : this.size,
|
||||||
);
|
);
|
||||||
LocalTrashedAssetEntityData copyWithCompanion(
|
TrashedLocalAssetEntityData copyWithCompanion(
|
||||||
LocalTrashedAssetEntityCompanion data,
|
TrashedLocalAssetEntityCompanion data,
|
||||||
) {
|
) {
|
||||||
return LocalTrashedAssetEntityData(
|
return TrashedLocalAssetEntityData(
|
||||||
id: data.id.present ? data.id.value : this.id,
|
id: data.id.present ? data.id.value : this.id,
|
||||||
remoteId: data.remoteId.present ? data.remoteId.value : this.remoteId,
|
albumId: data.albumId.present ? data.albumId.value : this.albumId,
|
||||||
|
checksum: data.checksum.present ? data.checksum.value : this.checksum,
|
||||||
|
name: data.name.present ? data.name.value : this.name,
|
||||||
|
type: data.type.present ? data.type.value : this.type,
|
||||||
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
||||||
|
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
|
||||||
|
size: data.size.present ? data.size.value : this.size,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('LocalTrashedAssetEntityData(')
|
return (StringBuffer('TrashedLocalAssetEntityData(')
|
||||||
..write('id: $id, ')
|
..write('id: $id, ')
|
||||||
..write('remoteId: $remoteId, ')
|
..write('albumId: $albumId, ')
|
||||||
..write('createdAt: $createdAt')
|
..write('checksum: $checksum, ')
|
||||||
|
..write('name: $name, ')
|
||||||
|
..write('type: $type, ')
|
||||||
|
..write('createdAt: $createdAt, ')
|
||||||
|
..write('updatedAt: $updatedAt, ')
|
||||||
|
..write('size: $size')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(id, remoteId, createdAt);
|
int get hashCode => Object.hash(
|
||||||
|
id,
|
||||||
|
albumId,
|
||||||
|
checksum,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
createdAt,
|
||||||
|
updatedAt,
|
||||||
|
size,
|
||||||
|
);
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
(other is LocalTrashedAssetEntityData &&
|
(other is TrashedLocalAssetEntityData &&
|
||||||
other.id == this.id &&
|
other.id == this.id &&
|
||||||
other.remoteId == this.remoteId &&
|
other.albumId == this.albumId &&
|
||||||
other.createdAt == this.createdAt);
|
other.checksum == this.checksum &&
|
||||||
|
other.name == this.name &&
|
||||||
|
other.type == this.type &&
|
||||||
|
other.createdAt == this.createdAt &&
|
||||||
|
other.updatedAt == this.updatedAt &&
|
||||||
|
other.size == this.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalTrashedAssetEntityCompanion
|
class TrashedLocalAssetEntityCompanion
|
||||||
extends UpdateCompanion<LocalTrashedAssetEntityData> {
|
extends UpdateCompanion<TrashedLocalAssetEntityData> {
|
||||||
final Value<String> id;
|
final Value<String> id;
|
||||||
final Value<String> remoteId;
|
final Value<String> albumId;
|
||||||
|
final Value<String?> checksum;
|
||||||
|
final Value<String> name;
|
||||||
|
final Value<int> type;
|
||||||
final Value<DateTime> createdAt;
|
final Value<DateTime> createdAt;
|
||||||
const LocalTrashedAssetEntityCompanion({
|
final Value<DateTime> updatedAt;
|
||||||
|
final Value<int?> size;
|
||||||
|
const TrashedLocalAssetEntityCompanion({
|
||||||
this.id = const Value.absent(),
|
this.id = const Value.absent(),
|
||||||
this.remoteId = const Value.absent(),
|
this.albumId = const Value.absent(),
|
||||||
|
this.checksum = const Value.absent(),
|
||||||
|
this.name = const Value.absent(),
|
||||||
|
this.type = const Value.absent(),
|
||||||
this.createdAt = const Value.absent(),
|
this.createdAt = const Value.absent(),
|
||||||
|
this.updatedAt = const Value.absent(),
|
||||||
|
this.size = const Value.absent(),
|
||||||
});
|
});
|
||||||
LocalTrashedAssetEntityCompanion.insert({
|
TrashedLocalAssetEntityCompanion.insert({
|
||||||
required String id,
|
required String id,
|
||||||
required String remoteId,
|
required String albumId,
|
||||||
|
this.checksum = const Value.absent(),
|
||||||
|
required String name,
|
||||||
|
required int type,
|
||||||
this.createdAt = const Value.absent(),
|
this.createdAt = const Value.absent(),
|
||||||
|
this.updatedAt = const Value.absent(),
|
||||||
|
this.size = const Value.absent(),
|
||||||
}) : id = Value(id),
|
}) : id = Value(id),
|
||||||
remoteId = Value(remoteId);
|
albumId = Value(albumId),
|
||||||
static Insertable<LocalTrashedAssetEntityData> custom({
|
name = Value(name),
|
||||||
|
type = Value(type);
|
||||||
|
static Insertable<TrashedLocalAssetEntityData> custom({
|
||||||
Expression<String>? id,
|
Expression<String>? id,
|
||||||
Expression<String>? remoteId,
|
Expression<String>? albumId,
|
||||||
|
Expression<String>? checksum,
|
||||||
|
Expression<String>? name,
|
||||||
|
Expression<int>? type,
|
||||||
Expression<DateTime>? createdAt,
|
Expression<DateTime>? createdAt,
|
||||||
|
Expression<DateTime>? updatedAt,
|
||||||
|
Expression<int>? size,
|
||||||
}) {
|
}) {
|
||||||
return RawValuesInsertable({
|
return RawValuesInsertable({
|
||||||
if (id != null) 'id': id,
|
if (id != null) 'id': id,
|
||||||
if (remoteId != null) 'remote_id': remoteId,
|
if (albumId != null) 'album_id': albumId,
|
||||||
|
if (checksum != null) 'checksum': checksum,
|
||||||
|
if (name != null) 'name': name,
|
||||||
|
if (type != null) 'type': type,
|
||||||
if (createdAt != null) 'created_at': createdAt,
|
if (createdAt != null) 'created_at': createdAt,
|
||||||
|
if (updatedAt != null) 'updated_at': updatedAt,
|
||||||
|
if (size != null) 'size': size,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalTrashedAssetEntityCompanion copyWith({
|
TrashedLocalAssetEntityCompanion copyWith({
|
||||||
Value<String>? id,
|
Value<String>? id,
|
||||||
Value<String>? remoteId,
|
Value<String>? albumId,
|
||||||
|
Value<String?>? checksum,
|
||||||
|
Value<String>? name,
|
||||||
|
Value<int>? type,
|
||||||
Value<DateTime>? createdAt,
|
Value<DateTime>? createdAt,
|
||||||
|
Value<DateTime>? updatedAt,
|
||||||
|
Value<int?>? size,
|
||||||
}) {
|
}) {
|
||||||
return LocalTrashedAssetEntityCompanion(
|
return TrashedLocalAssetEntityCompanion(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
remoteId: remoteId ?? this.remoteId,
|
albumId: albumId ?? this.albumId,
|
||||||
|
checksum: checksum ?? this.checksum,
|
||||||
|
name: name ?? this.name,
|
||||||
|
type: type ?? this.type,
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
|
size: size ?? this.size,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7273,21 +7435,41 @@ class LocalTrashedAssetEntityCompanion
|
||||||
if (id.present) {
|
if (id.present) {
|
||||||
map['id'] = Variable<String>(id.value);
|
map['id'] = Variable<String>(id.value);
|
||||||
}
|
}
|
||||||
if (remoteId.present) {
|
if (albumId.present) {
|
||||||
map['remote_id'] = Variable<String>(remoteId.value);
|
map['album_id'] = Variable<String>(albumId.value);
|
||||||
|
}
|
||||||
|
if (checksum.present) {
|
||||||
|
map['checksum'] = Variable<String>(checksum.value);
|
||||||
|
}
|
||||||
|
if (name.present) {
|
||||||
|
map['name'] = Variable<String>(name.value);
|
||||||
|
}
|
||||||
|
if (type.present) {
|
||||||
|
map['type'] = Variable<int>(type.value);
|
||||||
}
|
}
|
||||||
if (createdAt.present) {
|
if (createdAt.present) {
|
||||||
map['created_at'] = Variable<DateTime>(createdAt.value);
|
map['created_at'] = Variable<DateTime>(createdAt.value);
|
||||||
}
|
}
|
||||||
|
if (updatedAt.present) {
|
||||||
|
map['updated_at'] = Variable<DateTime>(updatedAt.value);
|
||||||
|
}
|
||||||
|
if (size.present) {
|
||||||
|
map['size'] = Variable<int>(size.value);
|
||||||
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('LocalTrashedAssetEntityCompanion(')
|
return (StringBuffer('TrashedLocalAssetEntityCompanion(')
|
||||||
..write('id: $id, ')
|
..write('id: $id, ')
|
||||||
..write('remoteId: $remoteId, ')
|
..write('albumId: $albumId, ')
|
||||||
..write('createdAt: $createdAt')
|
..write('checksum: $checksum, ')
|
||||||
|
..write('name: $name, ')
|
||||||
|
..write('type: $type, ')
|
||||||
|
..write('createdAt: $createdAt, ')
|
||||||
|
..write('updatedAt: $updatedAt, ')
|
||||||
|
..write('size: $size')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
@ -7336,15 +7518,15 @@ class DatabaseAtV11 extends GeneratedDatabase {
|
||||||
late final PersonEntity personEntity = PersonEntity(this);
|
late final PersonEntity personEntity = PersonEntity(this);
|
||||||
late final AssetFaceEntity assetFaceEntity = AssetFaceEntity(this);
|
late final AssetFaceEntity assetFaceEntity = AssetFaceEntity(this);
|
||||||
late final StoreEntity storeEntity = StoreEntity(this);
|
late final StoreEntity storeEntity = StoreEntity(this);
|
||||||
late final LocalTrashedAssetEntity localTrashedAssetEntity =
|
late final TrashedLocalAssetEntity trashedLocalAssetEntity =
|
||||||
LocalTrashedAssetEntity(this);
|
TrashedLocalAssetEntity(this);
|
||||||
late final Index idxLatLng = Index(
|
late final Index idxLatLng = Index(
|
||||||
'idx_lat_lng',
|
'idx_lat_lng',
|
||||||
'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)',
|
'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)',
|
||||||
);
|
);
|
||||||
late final Index idxLocalTrashedAssetRemoteId = Index(
|
late final Index idxTrashedLocalAssetChecksum = Index(
|
||||||
'idx_local_trashed_asset_remote_id',
|
'idx_trashed_local_asset_checksum',
|
||||||
'CREATE INDEX IF NOT EXISTS idx_local_trashed_asset_remote_id ON local_trashed_asset_entity (remote_id)',
|
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo<Table, Object?>> get allTables =>
|
Iterable<TableInfo<Table, Object?>> get allTables =>
|
||||||
|
|
@ -7374,9 +7556,9 @@ class DatabaseAtV11 extends GeneratedDatabase {
|
||||||
personEntity,
|
personEntity,
|
||||||
assetFaceEntity,
|
assetFaceEntity,
|
||||||
storeEntity,
|
storeEntity,
|
||||||
localTrashedAssetEntity,
|
trashedLocalAssetEntity,
|
||||||
idxLatLng,
|
idxLatLng,
|
||||||
idxLocalTrashedAssetRemoteId,
|
idxTrashedLocalAssetChecksum,
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 11;
|
int get schemaVersion => 11;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue