reduce number of native calls

This commit is contained in:
shenlong-tanwen 2025-05-07 19:34:08 +05:30
parent c0acd863cf
commit 09e5503fb1
10 changed files with 344 additions and 440 deletions

View File

@ -5,10 +5,8 @@ import SyncDelta
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import android.provider.MediaStore import android.provider.MediaStore
import android.provider.MediaStore.VOLUME_EXTERNAL
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.annotation.RequiresExtension import androidx.annotation.RequiresExtension
import androidx.core.content.edit
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import java.io.File import java.io.File
import java.time.Instant import java.time.Instant
@ -33,80 +31,48 @@ class MediaManager(context: Context) {
@RequiresApi(Build.VERSION_CODES.Q) @RequiresApi(Build.VERSION_CODES.Q)
fun shouldFullSync(callback: (Result<Boolean>) -> Unit) { fun shouldFullSync(callback: (Result<Boolean>) -> Unit) {
val prefs = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
val currVersion = MediaStore.getVersion(ctx) val currVersion = MediaStore.getVersion(ctx)
val lastVersion = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE) val lastVersion = prefs.getString(SHARED_PREF_MEDIA_STORE_VERSION_KEY, null)
.getString(SHARED_PREF_MEDIA_STORE_VERSION_KEY, null)
callback(Result.success(currVersion != lastVersion)) callback(Result.success(currVersion != lastVersion))
} }
@RequiresApi(Build.VERSION_CODES.Q)
@RequiresExtension(extension = Build.VERSION_CODES.R, version = 1)
fun hasMediaChanges(callback: (Result<Boolean>) -> Unit) {
val genMap = getSavedGenerationMap(ctx)
val currentVolumes = MediaStore.getExternalVolumeNames(ctx)
if (currentVolumes != genMap.keys) {
callback(Result.success(true))
return
}
val hasChanged = currentVolumes.any { volume ->
val currentGen = MediaStore.getGeneration(ctx, volume)
currentGen != genMap[volume]
}
callback(Result.success(hasChanged))
}
@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)
fun checkpointSync(callback: (Result<Unit>) -> Unit) { fun checkpointSync(callback: (Result<Unit>) -> Unit) {
val genMap = MediaStore.getExternalVolumeNames(ctx).associateWith { val genMap =
MediaStore.getGeneration(ctx, it) MediaStore.getExternalVolumeNames(ctx).associateWith { MediaStore.getGeneration(ctx, it) }
}.let { Json.encodeToString(it) } val prefs = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
prefs.edit().apply {
ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE).edit {
putString(SHARED_PREF_MEDIA_STORE_VERSION_KEY, MediaStore.getVersion(ctx)) putString(SHARED_PREF_MEDIA_STORE_VERSION_KEY, MediaStore.getVersion(ctx))
putString(SHARED_PREF_MEDIA_STORE_GEN_KEY, genMap) putString(SHARED_PREF_MEDIA_STORE_GEN_KEY, Json.encodeToString(genMap))
apply()
} }
callback(Result.success(Unit)) callback(Result.success(Unit))
} }
@RequiresApi(Build.VERSION_CODES.Q) @RequiresApi(Build.VERSION_CODES.Q)
fun getAssetIdsForAlbum( fun getAssetIdsForAlbum(albumId: String, callback: (Result<List<String>>) -> Unit) {
albumId: String,
callback: (Result<List<String>>) -> Unit
) {
try { try {
val currentIds = mutableListOf<String>() val uri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
val uri = MediaStore.Files.getContentUri(VOLUME_EXTERNAL)
val projection = arrayOf(MediaStore.Files.FileColumns._ID) val projection = arrayOf(MediaStore.Files.FileColumns._ID)
val selection = """ val selection =
${MediaStore.Files.FileColumns.BUCKET_ID} = ? "${MediaStore.Files.FileColumns.BUCKET_ID} = ? AND (${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?)"
AND (
${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?
OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?
)
""".trimIndent()
val selectionArgs = arrayOf( val selectionArgs = arrayOf(
albumId, albumId,
MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(), MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(),
MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString() MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString()
) )
val sortOrder = null
ctx.contentResolver.query( val ids =
uri, ctx.contentResolver.query(uri, projection, selection, selectionArgs, null)?.use { cursor ->
projection, val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)
selection, generateSequence {
selectionArgs, if (cursor.moveToNext()) cursor.getLong(idColumn).toString() else null
sortOrder }.toList()
)?.use { cursor -> } ?: emptyList()
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)
while (cursor.moveToNext()) {
currentIds.add(cursor.getLong(idColumn).toString())
}
}
callback(Result.success(currentIds)) callback(Result.success(ids))
} catch (e: Exception) { } catch (e: Exception) {
callback(Result.failure(e)) callback(Result.failure(e))
} }
@ -120,70 +86,57 @@ class MediaManager(context: Context) {
val currentVolumes = MediaStore.getExternalVolumeNames(ctx) val currentVolumes = MediaStore.getExternalVolumeNames(ctx)
val changed = mutableListOf<Asset>() val changed = mutableListOf<Asset>()
val deleted = mutableListOf<String>() val deleted = mutableListOf<String>()
val formatter = DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneOffset.UTC)
var hasChanges = genMap.keys != currentVolumes
for (volume in currentVolumes) { for (volume in currentVolumes) {
val currentGen = MediaStore.getGeneration(ctx, volume) val currentGen = MediaStore.getGeneration(ctx, volume)
val storedGen = genMap[volume] val storedGen = genMap[volume]
if (storedGen != null && currentGen <= storedGen) {
if (storedGen != null && currentGen < storedGen) {
continue continue
} }
hasChanges = true
val queryUri = MediaStore.Files.getContentUri(volume) val uri = MediaStore.Files.getContentUri(volume)
val projection = arrayOf( val projection = arrayOf(
MediaStore.MediaColumns._ID, MediaStore.MediaColumns._ID,
MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DATA,
MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.DISPLAY_NAME,
MediaStore.MediaColumns.TITLE,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.MediaColumns.BUCKET_ID,
MediaStore.MediaColumns.DURATION,
MediaStore.MediaColumns.DATE_TAKEN, MediaStore.MediaColumns.DATE_TAKEN,
MediaStore.MediaColumns.DATE_ADDED, MediaStore.MediaColumns.DATE_ADDED,
MediaStore.MediaColumns.DATE_MODIFIED, MediaStore.MediaColumns.DATE_MODIFIED,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.MediaColumns.BUCKET_ID,
MediaStore.MediaColumns.DURATION
) )
val selectionParts = mutableListOf<String>() val selection =
val selectionArgsList = mutableListOf<String>() "(${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?) AND (${MediaStore.MediaColumns.GENERATION_MODIFIED} > ? OR ${MediaStore.MediaColumns.GENERATION_ADDED} > ?)"
val selectionArgs = arrayOf(
selectionParts.add( MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(),
"(${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?)" MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString(),
storedGen?.toString() ?: "0",
storedGen?.toString() ?: "0"
) )
selectionArgsList.add(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString())
selectionArgsList.add(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString())
if (storedGen != null) {
selectionParts.add(
"(${MediaStore.MediaColumns.GENERATION_MODIFIED} > ? OR ${MediaStore.MediaColumns.GENERATION_ADDED} > ?)"
)
selectionArgsList.add(storedGen.toString())
selectionArgsList.add(storedGen.toString())
}
val selection = selectionParts.joinToString(" AND ")
val selectionArgs = selectionArgsList.toTypedArray()
val sortOrder = null
ctx.contentResolver.query( ctx.contentResolver.query(
queryUri, uri,
projection, projection,
selection, selection,
selectionArgs, selectionArgs,
sortOrder null
)?.use { cursor -> )?.use { cursor ->
val idColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID) val idColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)
val mediaTypeColumn =
cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MEDIA_TYPE)
val nameColumn =
cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)
val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA) val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
val dateTakeColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_TAKEN) val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)
val dateTakenColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_TAKEN)
val dateAddedColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_ADDED) val dateAddedColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_ADDED)
val dateModifiedColumn = val dateModifiedColumn =
cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_MODIFIED) cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_MODIFIED)
val durationColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DURATION) val mediaTypeColumn =
cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MEDIA_TYPE)
val bucketIdColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.BUCKET_ID) val bucketIdColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.BUCKET_ID)
val formatter = DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneOffset.UTC) val durationColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DURATION)
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
val id = cursor.getLong(idColumn).toString() val id = cursor.getLong(idColumn).toString()
@ -195,14 +148,11 @@ class MediaManager(context: Context) {
val mediaType = cursor.getInt(mediaTypeColumn) val mediaType = cursor.getInt(mediaTypeColumn)
val name = cursor.getString(nameColumn) val name = cursor.getString(nameColumn)
// Date taken is milliseconds since epoch // Date taken is milliseconds since epoch, Date added is seconds since epoch
var takenAt = cursor.getLong(dateTakeColumn) val takenAt = cursor.getLong(dateTakenColumn).takeIf { it > 0 } ?: (cursor.getLong(
if (takenAt == 0L) { dateAddedColumn
// Date added is seconds since epoch ) * 1000)
takenAt = cursor.getLong(dateAddedColumn) * 1000 val createdAt = formatter.format(Instant.ofEpochMilli(takenAt))
}
val takenInstant = Instant.ofEpochMilli(takenAt)
val createdAt = formatter.format(takenInstant)
// Date modified is seconds since epoch // Date modified is seconds since epoch
val modifiedAt = val modifiedAt =
formatter.format(Instant.ofEpochMilli(cursor.getLong(dateModifiedColumn) * 1000)) formatter.format(Instant.ofEpochMilli(cursor.getLong(dateModifiedColumn) * 1000))
@ -228,9 +178,8 @@ class MediaManager(context: Context) {
} }
} }
// Unmounted volumes are handled in dart when the album is removed // Unmounted volumes are handled in dart when the album is removed
val syncDelta = SyncDelta(updates = changed, deletes = deleted)
callback(Result.success(syncDelta))
callback(Result.success(SyncDelta(hasChanges, changed, deleted)))
} catch (e: Exception) { } catch (e: Exception) {
callback(Result.failure(e)) callback(Result.failure(e))
} }

View File

@ -125,19 +125,22 @@ data class Asset (
/** Generated class from Pigeon that represents data sent in messages. */ /** Generated class from Pigeon that represents data sent in messages. */
data class SyncDelta ( data class SyncDelta (
val hasChanges: Boolean,
val updates: List<Asset>, val updates: List<Asset>,
val deletes: List<String> val deletes: List<String>
) )
{ {
companion object { companion object {
fun fromList(pigeonVar_list: List<Any?>): SyncDelta { fun fromList(pigeonVar_list: List<Any?>): SyncDelta {
val updates = pigeonVar_list[0] as List<Asset> val hasChanges = pigeonVar_list[0] as Boolean
val deletes = pigeonVar_list[1] as List<String> val updates = pigeonVar_list[1] as List<Asset>
return SyncDelta(updates, deletes) val deletes = pigeonVar_list[2] as List<String>
return SyncDelta(hasChanges, updates, deletes)
} }
} }
fun toList(): List<Any?> { fun toList(): List<Any?> {
return listOf( return listOf(
hasChanges,
updates, updates,
deletes, deletes,
) )
@ -188,7 +191,6 @@ private open class MessagesPigeonCodec : StandardMessageCodec() {
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface ImHostService { interface ImHostService {
fun shouldFullSync(callback: (Result<Boolean>) -> Unit) fun shouldFullSync(callback: (Result<Boolean>) -> Unit)
fun hasMediaChanges(callback: (Result<Boolean>) -> Unit)
fun getMediaChanges(callback: (Result<SyncDelta>) -> Unit) fun getMediaChanges(callback: (Result<SyncDelta>) -> Unit)
fun checkpointSync(callback: (Result<Unit>) -> Unit) fun checkpointSync(callback: (Result<Unit>) -> Unit)
fun getAssetIdsForAlbum(albumId: String, callback: (Result<List<String>>) -> Unit) fun getAssetIdsForAlbum(albumId: String, callback: (Result<List<String>>) -> Unit)
@ -221,24 +223,6 @@ interface ImHostService {
channel.setMessageHandler(null) channel.setMessageHandler(null)
} }
} }
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.ImHostService.hasMediaChanges$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
api.hasMediaChanges{ result: Result<Boolean> ->
val error = result.exceptionOrNull()
if (error != null) {
reply.reply(MessagesPigeonUtils.wrapError(error))
} else {
val data = result.getOrNull()
reply.reply(MessagesPigeonUtils.wrapResult(data))
}
}
}
} else {
channel.setMessageHandler(null)
}
}
run { run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.ImHostService.getMediaChanges$separatedMessageChannelSuffix", codec, taskQueue) val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.ImHostService.getMediaChanges$separatedMessageChannelSuffix", codec, taskQueue)
if (api != null) { if (api != null) {

View File

@ -10,6 +10,16 @@ class MessagesImpl(context: Context) : ImHostService {
private val ctx: Context = context.applicationContext private val ctx: Context = context.applicationContext
private val mediaManager: MediaManager = MediaManager(ctx) private val mediaManager: MediaManager = MediaManager(ctx)
companion object {
private fun isMediaChangesSupported(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= 1
}
private fun unsupportedFeatureException() =
IllegalStateException("Method not supported on this Android version.")
}
override fun shouldFullSync(callback: (Result<Boolean>) -> Unit) { override fun shouldFullSync(callback: (Result<Boolean>) -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
mediaManager.shouldFullSync(callback) mediaManager.shouldFullSync(callback)
@ -18,24 +28,16 @@ class MessagesImpl(context: Context) : ImHostService {
} }
} }
override fun hasMediaChanges(callback: (Result<Boolean>) -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= 1) {
mediaManager.hasMediaChanges(callback)
} else {
callback(Result.failure(IllegalStateException("hasMediaChanges changes not supported on this Android version.")))
}
}
override fun getMediaChanges(callback: (Result<SyncDelta>) -> Unit) { override fun getMediaChanges(callback: (Result<SyncDelta>) -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= 1) { if (isMediaChangesSupported()) {
mediaManager.getMediaChanges(callback) mediaManager.getMediaChanges(callback)
} else { } else {
callback(Result.failure(IllegalStateException("getMediaChanges not supported on this Android version."))) callback(Result.failure(unsupportedFeatureException()))
} }
} }
override fun checkpointSync(callback: (Result<Unit>) -> Unit) { override fun checkpointSync(callback: (Result<Unit>) -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= 1) { if (isMediaChangesSupported()) {
mediaManager.checkpointSync(callback) mediaManager.checkpointSync(callback)
} else { } else {
callback(Result.success(Unit)) callback(Result.success(Unit))
@ -46,10 +48,10 @@ class MessagesImpl(context: Context) : ImHostService {
albumId: String, albumId: String,
callback: (Result<List<String>>) -> Unit callback: (Result<List<String>>) -> Unit
) { ) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) >= 1) { if (isMediaChangesSupported()) {
mediaManager.getAssetIdsForAlbum(albumId, callback) mediaManager.getAssetIdsForAlbum(albumId, callback)
} else { } else {
callback(Result.failure(IllegalStateException("getAssetIdsForAlbum not supported on this Android version."))) callback(Result.failure(unsupportedFeatureException()))
} }
} }
} }

View File

@ -1,26 +1,24 @@
import Photos import Photos
class MediaManager { class MediaManager {
let _defaults: UserDefaults private let _defaults: UserDefaults
private let _changeTokenKey = "immich:changeToken"
let _changeTokenKey = "immich:changeToken";
init(with defaults: UserDefaults = .standard) { init(with defaults: UserDefaults = .standard) {
_defaults = defaults self._defaults = defaults
} }
@available(iOS 16, *) @available(iOS 16, *)
func _getChangeToken() -> PHPersistentChangeToken? { func _getChangeToken() -> PHPersistentChangeToken? {
guard let encodedToken = _defaults.data(forKey: _changeTokenKey) else { guard let encodedToken = _defaults.data(forKey: _changeTokenKey) else {
print("_getChangeToken: Change token not available in UserDefaults") print("MediaManager::_getChangeToken: Change token not available in UserDefaults")
return nil return nil
} }
do { do {
let changeToken = try NSKeyedUnarchiver.unarchivedObject(ofClass: PHPersistentChangeToken.self, from: encodedToken) return try NSKeyedUnarchiver.unarchivedObject(ofClass: PHPersistentChangeToken.self, from: encodedToken)
return changeToken
} catch { } catch {
print("_getChangeToken: Cannot decode the token from UserDefaults") print("MediaManager::_getChangeToken: Cannot decode the token from UserDefaults")
return nil return nil
} }
} }
@ -30,9 +28,9 @@ class MediaManager {
do { do {
let encodedToken = try NSKeyedArchiver.archivedData(withRootObject: token, requiringSecureCoding: true) let encodedToken = try NSKeyedArchiver.archivedData(withRootObject: token, requiringSecureCoding: true)
_defaults.set(encodedToken, forKey: _changeTokenKey) _defaults.set(encodedToken, forKey: _changeTokenKey)
print("_setChangeToken: Change token saved to UserDefaults") print("MediaManager::_setChangeToken: Change token saved to UserDefaults")
} catch { } catch {
print("_setChangeToken: Failed to persist the token to UserDefaults: \(error)") print("MediaManager::_setChangeToken: Failed to persist the token to UserDefaults: \(error)")
} }
} }
@ -52,7 +50,7 @@ class MediaManager {
guard let storedToken = _getChangeToken() else { guard let storedToken = _getChangeToken() else {
// No token exists, perform the initial full sync // No token exists, perform the initial full sync
print("shouldUseOldSync: No token found") print("MediaManager::shouldUseOldSync: No token found. Full sync required")
completion(.success(true)) completion(.success(true))
return return
} }
@ -62,44 +60,40 @@ class MediaManager {
completion(.success(false)) completion(.success(false))
} catch { } catch {
// fallback to using old sync when we cannot detect changes using the available token // fallback to using old sync when we cannot detect changes using the available token
print("shouldUseOldSync: fetchPersistentChanges failed with error (\(error))") print("MediaManager::shouldUseOldSync: fetchPersistentChanges failed with error (\(error))")
completion(.success(true)) completion(.success(true))
} }
} }
@available(iOS 16, *)
func hasMediaChanges(completion: @escaping (Result<Bool, Error>) -> Void) {
guard PHPhotoLibrary.authorizationStatus(for: .readWrite) == .authorized else {
completion(.failure(PigeonError(code: "1", message: "No photo library access", details: nil)))
return
}
let storedToken = _getChangeToken()
let currentToken = PHPhotoLibrary.shared().currentChangeToken
completion(.success(storedToken != currentToken))
}
@available(iOS 16, *) @available(iOS 16, *)
func getMediaChanges(completion: @escaping (Result<SyncDelta, Error>) -> Void) { func getMediaChanges(completion: @escaping (Result<SyncDelta, Error>) -> Void) {
guard PHPhotoLibrary.authorizationStatus(for: .readWrite) == .authorized else { guard PHPhotoLibrary.authorizationStatus(for: .readWrite) == .authorized else {
completion(.failure(PigeonError(code: "1", message: "No photo library access", details: nil))) completion(.failure(PigeonError(code: "NO_AUTH", message: "No photo library access", details: nil)))
return return
} }
guard let storedToken = _getChangeToken() else { guard let storedToken = _getChangeToken() else {
// No token exists, definitely need a full sync // No token exists, definitely need a full sync
print("getMediaChanges: No token found") print("MediaManager::getMediaChanges: No token found")
completion(.failure(PigeonError(code: "2", message: "No stored change token", details: nil))) completion(.failure(PigeonError(code: "NO_TOKEN", message: "No stored change token", details: nil)))
return return
} }
let currentToken = PHPhotoLibrary.shared().currentChangeToken
if storedToken == currentToken {
completion(.success(SyncDelta(hasChanges: false, updates: [], deletes: [])))
return
}
do { do {
let result = try PHPhotoLibrary.shared().fetchPersistentChanges(since: storedToken) let result = try PHPhotoLibrary.shared().fetchPersistentChanges(since: storedToken)
let dateFormatter = ISO8601DateFormatter() let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
var delta = SyncDelta(updates: [], deletes: [])
var updatedArr: [Asset] = []
var deletedArr: [String] = []
for changes in result { for changes in result {
let details = try changes.changeDetails(for: PHObjectType.asset) let details = try changes.changeDetails(for: PHObjectType.asset)
let updated = details.updatedLocalIdentifiers.union(details.insertedLocalIdentifiers) let updated = details.updatedLocalIdentifiers.union(details.insertedLocalIdentifiers)
@ -108,8 +102,7 @@ class MediaManager {
let options = PHFetchOptions() let options = PHFetchOptions()
options.includeHiddenAssets = true options.includeHiddenAssets = true
let updatedAssets = PHAsset.fetchAssets(withLocalIdentifiers: Array(updated), options: options) let updatedAssets = PHAsset.fetchAssets(withLocalIdentifiers: Array(updated), options: options)
var updates: [Asset] = []
updatedAssets.enumerateObjects { (asset, _, _) in updatedAssets.enumerateObjects { (asset, _, _) in
let id = asset.localIdentifier let id = asset.localIdentifier
let name = PHAssetResource.assetResources(for: asset).first?.originalFilename ?? asset.title() let name = PHAssetResource.assetResources(for: asset).first?.originalFilename ?? asset.title()
@ -118,33 +111,41 @@ class MediaManager {
let updatedAt = asset.modificationDate.map { dateFormatter.string(from: $0) } let updatedAt = asset.modificationDate.map { dateFormatter.string(from: $0) }
let durationInSeconds: Int64 = Int64(asset.duration) let durationInSeconds: Int64 = Int64(asset.duration)
let dAsset = Asset(id: id, name: name, type: type, createdAt: createdAt, updatedAt: updatedAt, durationInSeconds: durationInSeconds, albumIds: self._getAlbumIdsForAsset(asset: asset)) let domainAsset = Asset(
updates.append(dAsset) id: id,
name: name,
type: type,
createdAt: createdAt,
updatedAt: updatedAt,
durationInSeconds: durationInSeconds,
albumIds: self._getAlbumIds(forAsset: asset)
)
updatedArr.append(domainAsset)
} }
delta.updates.append(contentsOf: updates) deletedArr.append(contentsOf: details.deletedLocalIdentifiers)
delta.deletes.append(contentsOf: deleted)
} }
let delta = SyncDelta(hasChanges: true, updates: updatedArr, deletes: deletedArr)
completion(.success(delta)) completion(.success(delta))
return return
} catch { } catch {
print("getMediaChanges: Error fetching persistent changes: \(error)") print("MediaManager::getMediaChanges: Error fetching persistent changes: \(error)")
completion(.failure(PigeonError(code: "3", message: error.localizedDescription, details: nil))) completion(.failure(PigeonError(code: "3", message: error.localizedDescription, details: nil)))
return return
} }
} }
@available(iOS 16, *) @available(iOS 16, *)
func _getAlbumIdsForAsset(asset: PHAsset) -> [String] { func _getAlbumIds(forAsset: PHAsset) -> [String] {
var albumIds: [String] = [] var albumIds: [String] = []
var albums = PHAssetCollection.fetchAssetCollectionsContaining(asset, with: .album, options: nil) let albumTypes: [PHAssetCollectionType] = [.album, .smartAlbum]
albums.enumerateObjects { (album, _, _) in
albumIds.append(album.localIdentifier) albumTypes.forEach { type in
} let collections = PHAssetCollection.fetchAssetCollectionsContaining(forAsset, with: type, options: nil)
albums = PHAssetCollection.fetchAssetCollectionsContaining(asset, with: .smartAlbum, options: nil) collections.enumerateObjects { (album, _, _) in
albums.enumerateObjects { (album, _, _) in
albumIds.append(album.localIdentifier) albumIds.append(album.localIdentifier)
}
} }
return albumIds return albumIds
} }

View File

@ -179,22 +179,26 @@ struct Asset: Hashable {
/// Generated class from Pigeon that represents data sent in messages. /// Generated class from Pigeon that represents data sent in messages.
struct SyncDelta: Hashable { struct SyncDelta: Hashable {
var hasChanges: Bool
var updates: [Asset] var updates: [Asset]
var deletes: [String] var deletes: [String]
// swift-format-ignore: AlwaysUseLowerCamelCase // swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ pigeonVar_list: [Any?]) -> SyncDelta? { static func fromList(_ pigeonVar_list: [Any?]) -> SyncDelta? {
let updates = pigeonVar_list[0] as! [Asset] let hasChanges = pigeonVar_list[0] as! Bool
let deletes = pigeonVar_list[1] as! [String] let updates = pigeonVar_list[1] as! [Asset]
let deletes = pigeonVar_list[2] as! [String]
return SyncDelta( return SyncDelta(
hasChanges: hasChanges,
updates: updates, updates: updates,
deletes: deletes deletes: deletes
) )
} }
func toList() -> [Any?] { func toList() -> [Any?] {
return [ return [
hasChanges,
updates, updates,
deletes, deletes,
] ]
@ -251,7 +255,6 @@ class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
/// Generated protocol from Pigeon that represents a handler of messages from Flutter. /// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol ImHostService { protocol ImHostService {
func shouldFullSync(completion: @escaping (Result<Bool, Error>) -> Void) func shouldFullSync(completion: @escaping (Result<Bool, Error>) -> Void)
func hasMediaChanges(completion: @escaping (Result<Bool, Error>) -> Void)
func getMediaChanges(completion: @escaping (Result<SyncDelta, Error>) -> Void) func getMediaChanges(completion: @escaping (Result<SyncDelta, Error>) -> Void)
func checkpointSync(completion: @escaping (Result<Void, Error>) -> Void) func checkpointSync(completion: @escaping (Result<Void, Error>) -> Void)
func getAssetIdsForAlbum(albumId: String, completion: @escaping (Result<[String], Error>) -> Void) func getAssetIdsForAlbum(albumId: String, completion: @escaping (Result<[String], Error>) -> Void)
@ -283,21 +286,6 @@ class ImHostServiceSetup {
} else { } else {
shouldFullSyncChannel.setMessageHandler(nil) shouldFullSyncChannel.setMessageHandler(nil)
} }
let hasMediaChangesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ImHostService.hasMediaChanges\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
hasMediaChangesChannel.setMessageHandler { _, reply in
api.hasMediaChanges { result in
switch result {
case .success(let res):
reply(wrapResult(res))
case .failure(let error):
reply(wrapError(error))
}
}
}
} else {
hasMediaChangesChannel.setMessageHandler(nil)
}
let getMediaChangesChannel = taskQueue == nil let getMediaChangesChannel = taskQueue == nil
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ImHostService.getMediaChanges\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) ? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ImHostService.getMediaChanges\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ImHostService.getMediaChanges\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue) : FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ImHostService.getMediaChanges\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)

View File

@ -4,33 +4,24 @@ class ImHostServiceImpl: ImHostService {
let _mediaManager: MediaManager let _mediaManager: MediaManager
init() { init() {
_mediaManager = MediaManager() self._mediaManager = MediaManager()
} }
func shouldFullSync(completion: @escaping (Result<Bool, Error>) -> Void) { func shouldFullSync(completion: @escaping (Result<Bool, Error>) -> Void) {
if #available(iOS 16, *) { if #available(iOS 16, *) {
_mediaManager.shouldFullSync(completion: completion) _mediaManager.shouldFullSync(completion: completion)
return;
} else { } else {
// Always fall back to full sync on older iOS versions // Always fall back to full sync on older iOS versions
completion(.success(true)) completion(.success(true))
} }
} }
func hasMediaChanges(completion: @escaping (Result<Bool, Error>) -> Void) {
if #available(iOS 16, *) {
_mediaManager.hasMediaChanges(completion: completion)
} else {
completion(.failure(PigeonError(code: "-1", message: "Not supported", details: nil)))
}
}
func getMediaChanges(completion: @escaping (Result<SyncDelta, Error>) -> Void) { func getMediaChanges(completion: @escaping (Result<SyncDelta, Error>) -> Void) {
if #available(iOS 16, *) { guard #available(iOS 16, *) else {
_mediaManager.getMediaChanges(completion: completion) completion(.failure(PigeonError(code: "UNSUPPORTED_OS", message: "This feature requires iOS 16 or later.", details: nil)))
} else { return
completion(.failure(PigeonError(code: "-1", message: "Not supported", details: nil)))
} }
_mediaManager.getMediaChanges(completion: completion)
} }
func checkpointSync(completion: @escaping (Result<Void, any Error>) -> Void) { func checkpointSync(completion: @escaping (Result<Void, any Error>) -> Void) {
@ -42,7 +33,7 @@ class ImHostServiceImpl: ImHostService {
} }
func getAssetIdsForAlbum(albumId: String, completion: @escaping (Result<[String], any Error>) -> Void) { func getAssetIdsForAlbum(albumId: String, completion: @escaping (Result<[String], any Error>) -> Void) {
// Android specific, ignore the call with an empty list // Android specific, empty list is safe no-op
completion(.success([])) completion(.success([]))
} }
} }

View File

@ -35,15 +35,14 @@ class DeviceSyncService {
return await fullSync(); return await fullSync();
} }
if (!await _hostService.hasMediaChanges()) { final delta = await _hostService.getMediaChanges();
if (!delta.hasChanges) {
_log.fine("No media changes detected. Skipping sync"); _log.fine("No media changes detected. Skipping sync");
return; return;
} }
final deviceAlbums = await _albumMediaRepository.getAll(); final deviceAlbums = await _albumMediaRepository.getAll();
await _localAlbumRepository.updateAll(deviceAlbums); await _localAlbumRepository.updateAll(deviceAlbums);
final delta = await _hostService.getMediaChanges();
await _localAlbumRepository.handleSyncDelta(delta); await _localAlbumRepository.handleSyncDelta(delta);
if (_platform.isAndroid) { if (_platform.isAndroid) {

View File

@ -33,7 +33,12 @@ class Asset {
} }
class SyncDelta { class SyncDelta {
SyncDelta({this.updates = const [], this.deletes = const []}); SyncDelta({
this.hasChanges = false,
this.updates = const [],
this.deletes = const [],
});
bool hasChanges;
List<Asset> updates; List<Asset> updates;
List<String> deletes; List<String> deletes;
} }
@ -43,9 +48,6 @@ abstract class ImHostService {
@async @async
bool shouldFullSync(); bool shouldFullSync();
@async
bool hasMediaChanges();
@async @async
@TaskQueue(type: TaskQueueType.serialBackgroundThread) @TaskQueue(type: TaskQueueType.serialBackgroundThread)
SyncDelta getMediaChanges(); SyncDelta getMediaChanges();

View File

@ -14,21 +14,22 @@ PlatformException _createConnectionError(String channelName) {
message: 'Unable to establish connection on channel: "$channelName".', message: 'Unable to establish connection on channel: "$channelName".',
); );
} }
bool _deepEquals(Object? a, Object? b) { bool _deepEquals(Object? a, Object? b) {
if (a is List && b is List) { if (a is List && b is List) {
return a.length == b.length && return a.length == b.length &&
a.indexed a.indexed
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
} }
if (a is Map && b is Map) { if (a is Map && b is Map) {
return a.length == b.length && a.entries.every((MapEntry<Object?, Object?> entry) => return a.length == b.length &&
(b as Map<Object?, Object?>).containsKey(entry.key) && a.entries.every((MapEntry<Object?, Object?> entry) =>
_deepEquals(entry.value, b[entry.key])); (b as Map<Object?, Object?>).containsKey(entry.key) &&
_deepEquals(entry.value, b[entry.key]));
} }
return a == b; return a == b;
} }
class Asset { class Asset {
Asset({ Asset({
required this.id, required this.id,
@ -67,7 +68,8 @@ class Asset {
} }
Object encode() { Object encode() {
return _toList(); } return _toList();
}
static Asset decode(Object result) { static Asset decode(Object result) {
result as List<Object?>; result as List<Object?>;
@ -96,35 +98,40 @@ class Asset {
@override @override
// ignore: avoid_equals_and_hash_code_on_mutable_classes // ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList()) int get hashCode => Object.hashAll(_toList());
;
} }
class SyncDelta { class SyncDelta {
SyncDelta({ SyncDelta({
this.hasChanges = false,
this.updates = const [], this.updates = const [],
this.deletes = const [], this.deletes = const [],
}); });
bool hasChanges;
List<Asset> updates; List<Asset> updates;
List<String> deletes; List<String> deletes;
List<Object?> _toList() { List<Object?> _toList() {
return <Object?>[ return <Object?>[
hasChanges,
updates, updates,
deletes, deletes,
]; ];
} }
Object encode() { Object encode() {
return _toList(); } return _toList();
}
static SyncDelta decode(Object result) { static SyncDelta decode(Object result) {
result as List<Object?>; result as List<Object?>;
return SyncDelta( return SyncDelta(
updates: (result[0] as List<Object?>?)!.cast<Asset>(), hasChanges: result[0]! as bool,
deletes: (result[1] as List<Object?>?)!.cast<String>(), updates: (result[1] as List<Object?>?)!.cast<Asset>(),
deletes: (result[2] as List<Object?>?)!.cast<String>(),
); );
} }
@ -142,11 +149,9 @@ class SyncDelta {
@override @override
// ignore: avoid_equals_and_hash_code_on_mutable_classes // ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList()) int get hashCode => Object.hashAll(_toList());
;
} }
class _PigeonCodec extends StandardMessageCodec { class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec(); const _PigeonCodec();
@override @override
@ -154,10 +159,10 @@ class _PigeonCodec extends StandardMessageCodec {
if (value is int) { if (value is int) {
buffer.putUint8(4); buffer.putUint8(4);
buffer.putInt64(value); buffer.putInt64(value);
} else if (value is Asset) { } else if (value is Asset) {
buffer.putUint8(129); buffer.putUint8(129);
writeValue(buffer, value.encode()); writeValue(buffer, value.encode());
} else if (value is SyncDelta) { } else if (value is SyncDelta) {
buffer.putUint8(130); buffer.putUint8(130);
writeValue(buffer, value.encode()); writeValue(buffer, value.encode());
} else { } else {
@ -168,9 +173,9 @@ class _PigeonCodec extends StandardMessageCodec {
@override @override
Object? readValueOfType(int type, ReadBuffer buffer) { Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) { switch (type) {
case 129: case 129:
return Asset.decode(readValue(buffer)!); return Asset.decode(readValue(buffer)!);
case 130: case 130:
return SyncDelta.decode(readValue(buffer)!); return SyncDelta.decode(readValue(buffer)!);
default: default:
return super.readValueOfType(type, buffer); return super.readValueOfType(type, buffer);
@ -182,9 +187,11 @@ class ImHostService {
/// Constructor for [ImHostService]. The [binaryMessenger] named argument is /// Constructor for [ImHostService]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default /// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform. /// BinaryMessenger will be used which routes to the host platform.
ImHostService({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) ImHostService(
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
: pigeonVar_binaryMessenger = binaryMessenger, : pigeonVar_binaryMessenger = binaryMessenger,
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; pigeonVar_messageChannelSuffix =
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
final BinaryMessenger? pigeonVar_binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger;
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec(); static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
@ -192,36 +199,10 @@ class ImHostService {
final String pigeonVar_messageChannelSuffix; final String pigeonVar_messageChannelSuffix;
Future<bool> shouldFullSync() async { Future<bool> shouldFullSync() async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.immich_mobile.ImHostService.shouldFullSync$pigeonVar_messageChannelSuffix'; final String pigeonVar_channelName =
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>( 'dev.flutter.pigeon.immich_mobile.ImHostService.shouldFullSync$pigeonVar_messageChannelSuffix';
pigeonVar_channelName, final BasicMessageChannel<Object?> pigeonVar_channel =
pigeonChannelCodec, BasicMessageChannel<Object?>(
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
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 bool?)!;
}
}
Future<bool> hasMediaChanges() async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.immich_mobile.ImHostService.hasMediaChanges$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName, pigeonVar_channelName,
pigeonChannelCodec, pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger, binaryMessenger: pigeonVar_binaryMessenger,
@ -248,8 +229,10 @@ class ImHostService {
} }
Future<SyncDelta> getMediaChanges() async { Future<SyncDelta> getMediaChanges() async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.immich_mobile.ImHostService.getMediaChanges$pigeonVar_messageChannelSuffix'; final String pigeonVar_channelName =
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>( 'dev.flutter.pigeon.immich_mobile.ImHostService.getMediaChanges$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel =
BasicMessageChannel<Object?>(
pigeonVar_channelName, pigeonVar_channelName,
pigeonChannelCodec, pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger, binaryMessenger: pigeonVar_binaryMessenger,
@ -276,8 +259,10 @@ class ImHostService {
} }
Future<void> checkpointSync() async { Future<void> checkpointSync() async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.immich_mobile.ImHostService.checkpointSync$pigeonVar_messageChannelSuffix'; final String pigeonVar_channelName =
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>( 'dev.flutter.pigeon.immich_mobile.ImHostService.checkpointSync$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel =
BasicMessageChannel<Object?>(
pigeonVar_channelName, pigeonVar_channelName,
pigeonChannelCodec, pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger, binaryMessenger: pigeonVar_binaryMessenger,
@ -299,13 +284,16 @@ class ImHostService {
} }
Future<List<String>> getAssetIdsForAlbum(String albumId) async { Future<List<String>> getAssetIdsForAlbum(String albumId) async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.immich_mobile.ImHostService.getAssetIdsForAlbum$pigeonVar_messageChannelSuffix'; final String pigeonVar_channelName =
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>( 'dev.flutter.pigeon.immich_mobile.ImHostService.getAssetIdsForAlbum$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel =
BasicMessageChannel<Object?>(
pigeonVar_channelName, pigeonVar_channelName,
pigeonChannelCodec, pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger, binaryMessenger: pigeonVar_binaryMessenger,
); );
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[albumId]); final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[albumId]);
final List<Object?>? pigeonVar_replyList = final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?; await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) { if (pigeonVar_replyList == null) {

View File

@ -14,7 +14,7 @@ part of 'router.dart';
/// [ActivitiesPage] /// [ActivitiesPage]
class ActivitiesRoute extends PageRouteInfo<void> { class ActivitiesRoute extends PageRouteInfo<void> {
const ActivitiesRoute({List<PageRouteInfo>? children}) const ActivitiesRoute({List<PageRouteInfo>? children})
: super(ActivitiesRoute.name, initialChildren: children); : super(ActivitiesRoute.name, initialChildren: children);
static const String name = 'ActivitiesRoute'; static const String name = 'ActivitiesRoute';
@ -35,13 +35,13 @@ class AlbumAdditionalSharedUserSelectionRoute
required Album album, required Album album,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
AlbumAdditionalSharedUserSelectionRoute.name, AlbumAdditionalSharedUserSelectionRoute.name,
args: AlbumAdditionalSharedUserSelectionRouteArgs( args: AlbumAdditionalSharedUserSelectionRouteArgs(
key: key, key: key,
album: album, album: album,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'AlbumAdditionalSharedUserSelectionRoute'; static const String name = 'AlbumAdditionalSharedUserSelectionRoute';
@ -83,14 +83,14 @@ class AlbumAssetSelectionRoute
bool canDeselect = false, bool canDeselect = false,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
AlbumAssetSelectionRoute.name, AlbumAssetSelectionRoute.name,
args: AlbumAssetSelectionRouteArgs( args: AlbumAssetSelectionRouteArgs(
key: key, key: key,
existingAssets: existingAssets, existingAssets: existingAssets,
canDeselect: canDeselect, canDeselect: canDeselect,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'AlbumAssetSelectionRoute'; static const String name = 'AlbumAssetSelectionRoute';
@ -130,7 +130,7 @@ class AlbumAssetSelectionRouteArgs {
/// [AlbumOptionsPage] /// [AlbumOptionsPage]
class AlbumOptionsRoute extends PageRouteInfo<void> { class AlbumOptionsRoute extends PageRouteInfo<void> {
const AlbumOptionsRoute({List<PageRouteInfo>? children}) const AlbumOptionsRoute({List<PageRouteInfo>? children})
: super(AlbumOptionsRoute.name, initialChildren: children); : super(AlbumOptionsRoute.name, initialChildren: children);
static const String name = 'AlbumOptionsRoute'; static const String name = 'AlbumOptionsRoute';
@ -150,10 +150,10 @@ class AlbumPreviewRoute extends PageRouteInfo<AlbumPreviewRouteArgs> {
required Album album, required Album album,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
AlbumPreviewRoute.name, AlbumPreviewRoute.name,
args: AlbumPreviewRouteArgs(key: key, album: album), args: AlbumPreviewRouteArgs(key: key, album: album),
initialChildren: children, initialChildren: children,
); );
static const String name = 'AlbumPreviewRoute'; static const String name = 'AlbumPreviewRoute';
@ -188,10 +188,10 @@ class AlbumSharedUserSelectionRoute
required Set<Asset> assets, required Set<Asset> assets,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
AlbumSharedUserSelectionRoute.name, AlbumSharedUserSelectionRoute.name,
args: AlbumSharedUserSelectionRouteArgs(key: key, assets: assets), args: AlbumSharedUserSelectionRouteArgs(key: key, assets: assets),
initialChildren: children, initialChildren: children,
); );
static const String name = 'AlbumSharedUserSelectionRoute'; static const String name = 'AlbumSharedUserSelectionRoute';
@ -225,10 +225,10 @@ class AlbumViewerRoute extends PageRouteInfo<AlbumViewerRouteArgs> {
required int albumId, required int albumId,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
AlbumViewerRoute.name, AlbumViewerRoute.name,
args: AlbumViewerRouteArgs(key: key, albumId: albumId), args: AlbumViewerRouteArgs(key: key, albumId: albumId),
initialChildren: children, initialChildren: children,
); );
static const String name = 'AlbumViewerRoute'; static const String name = 'AlbumViewerRoute';
@ -258,7 +258,7 @@ class AlbumViewerRouteArgs {
/// [AlbumsPage] /// [AlbumsPage]
class AlbumsRoute extends PageRouteInfo<void> { class AlbumsRoute extends PageRouteInfo<void> {
const AlbumsRoute({List<PageRouteInfo>? children}) const AlbumsRoute({List<PageRouteInfo>? children})
: super(AlbumsRoute.name, initialChildren: children); : super(AlbumsRoute.name, initialChildren: children);
static const String name = 'AlbumsRoute'; static const String name = 'AlbumsRoute';
@ -274,7 +274,7 @@ class AlbumsRoute extends PageRouteInfo<void> {
/// [AllMotionPhotosPage] /// [AllMotionPhotosPage]
class AllMotionPhotosRoute extends PageRouteInfo<void> { class AllMotionPhotosRoute extends PageRouteInfo<void> {
const AllMotionPhotosRoute({List<PageRouteInfo>? children}) const AllMotionPhotosRoute({List<PageRouteInfo>? children})
: super(AllMotionPhotosRoute.name, initialChildren: children); : super(AllMotionPhotosRoute.name, initialChildren: children);
static const String name = 'AllMotionPhotosRoute'; static const String name = 'AllMotionPhotosRoute';
@ -290,7 +290,7 @@ class AllMotionPhotosRoute extends PageRouteInfo<void> {
/// [AllPeoplePage] /// [AllPeoplePage]
class AllPeopleRoute extends PageRouteInfo<void> { class AllPeopleRoute extends PageRouteInfo<void> {
const AllPeopleRoute({List<PageRouteInfo>? children}) const AllPeopleRoute({List<PageRouteInfo>? children})
: super(AllPeopleRoute.name, initialChildren: children); : super(AllPeopleRoute.name, initialChildren: children);
static const String name = 'AllPeopleRoute'; static const String name = 'AllPeopleRoute';
@ -306,7 +306,7 @@ class AllPeopleRoute extends PageRouteInfo<void> {
/// [AllPlacesPage] /// [AllPlacesPage]
class AllPlacesRoute extends PageRouteInfo<void> { class AllPlacesRoute extends PageRouteInfo<void> {
const AllPlacesRoute({List<PageRouteInfo>? children}) const AllPlacesRoute({List<PageRouteInfo>? children})
: super(AllPlacesRoute.name, initialChildren: children); : super(AllPlacesRoute.name, initialChildren: children);
static const String name = 'AllPlacesRoute'; static const String name = 'AllPlacesRoute';
@ -322,7 +322,7 @@ class AllPlacesRoute extends PageRouteInfo<void> {
/// [AllVideosPage] /// [AllVideosPage]
class AllVideosRoute extends PageRouteInfo<void> { class AllVideosRoute extends PageRouteInfo<void> {
const AllVideosRoute({List<PageRouteInfo>? children}) const AllVideosRoute({List<PageRouteInfo>? children})
: super(AllVideosRoute.name, initialChildren: children); : super(AllVideosRoute.name, initialChildren: children);
static const String name = 'AllVideosRoute'; static const String name = 'AllVideosRoute';
@ -342,10 +342,10 @@ class AppLogDetailRoute extends PageRouteInfo<AppLogDetailRouteArgs> {
required LogMessage logMessage, required LogMessage logMessage,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
AppLogDetailRoute.name, AppLogDetailRoute.name,
args: AppLogDetailRouteArgs(key: key, logMessage: logMessage), args: AppLogDetailRouteArgs(key: key, logMessage: logMessage),
initialChildren: children, initialChildren: children,
); );
static const String name = 'AppLogDetailRoute'; static const String name = 'AppLogDetailRoute';
@ -375,7 +375,7 @@ class AppLogDetailRouteArgs {
/// [AppLogPage] /// [AppLogPage]
class AppLogRoute extends PageRouteInfo<void> { class AppLogRoute extends PageRouteInfo<void> {
const AppLogRoute({List<PageRouteInfo>? children}) const AppLogRoute({List<PageRouteInfo>? children})
: super(AppLogRoute.name, initialChildren: children); : super(AppLogRoute.name, initialChildren: children);
static const String name = 'AppLogRoute'; static const String name = 'AppLogRoute';
@ -391,7 +391,7 @@ class AppLogRoute extends PageRouteInfo<void> {
/// [ArchivePage] /// [ArchivePage]
class ArchiveRoute extends PageRouteInfo<void> { class ArchiveRoute extends PageRouteInfo<void> {
const ArchiveRoute({List<PageRouteInfo>? children}) const ArchiveRoute({List<PageRouteInfo>? children})
: super(ArchiveRoute.name, initialChildren: children); : super(ArchiveRoute.name, initialChildren: children);
static const String name = 'ArchiveRoute'; static const String name = 'ArchiveRoute';
@ -407,7 +407,7 @@ class ArchiveRoute extends PageRouteInfo<void> {
/// [BackupAlbumSelectionPage] /// [BackupAlbumSelectionPage]
class BackupAlbumSelectionRoute extends PageRouteInfo<void> { class BackupAlbumSelectionRoute extends PageRouteInfo<void> {
const BackupAlbumSelectionRoute({List<PageRouteInfo>? children}) const BackupAlbumSelectionRoute({List<PageRouteInfo>? children})
: super(BackupAlbumSelectionRoute.name, initialChildren: children); : super(BackupAlbumSelectionRoute.name, initialChildren: children);
static const String name = 'BackupAlbumSelectionRoute'; static const String name = 'BackupAlbumSelectionRoute';
@ -423,7 +423,7 @@ class BackupAlbumSelectionRoute extends PageRouteInfo<void> {
/// [BackupControllerPage] /// [BackupControllerPage]
class BackupControllerRoute extends PageRouteInfo<void> { class BackupControllerRoute extends PageRouteInfo<void> {
const BackupControllerRoute({List<PageRouteInfo>? children}) const BackupControllerRoute({List<PageRouteInfo>? children})
: super(BackupControllerRoute.name, initialChildren: children); : super(BackupControllerRoute.name, initialChildren: children);
static const String name = 'BackupControllerRoute'; static const String name = 'BackupControllerRoute';
@ -439,7 +439,7 @@ class BackupControllerRoute extends PageRouteInfo<void> {
/// [BackupOptionsPage] /// [BackupOptionsPage]
class BackupOptionsRoute extends PageRouteInfo<void> { class BackupOptionsRoute extends PageRouteInfo<void> {
const BackupOptionsRoute({List<PageRouteInfo>? children}) const BackupOptionsRoute({List<PageRouteInfo>? children})
: super(BackupOptionsRoute.name, initialChildren: children); : super(BackupOptionsRoute.name, initialChildren: children);
static const String name = 'BackupOptionsRoute'; static const String name = 'BackupOptionsRoute';
@ -455,7 +455,7 @@ class BackupOptionsRoute extends PageRouteInfo<void> {
/// [ChangePasswordPage] /// [ChangePasswordPage]
class ChangePasswordRoute extends PageRouteInfo<void> { class ChangePasswordRoute extends PageRouteInfo<void> {
const ChangePasswordRoute({List<PageRouteInfo>? children}) const ChangePasswordRoute({List<PageRouteInfo>? children})
: super(ChangePasswordRoute.name, initialChildren: children); : super(ChangePasswordRoute.name, initialChildren: children);
static const String name = 'ChangePasswordRoute'; static const String name = 'ChangePasswordRoute';
@ -475,10 +475,10 @@ class CreateAlbumRoute extends PageRouteInfo<CreateAlbumRouteArgs> {
List<Asset>? assets, List<Asset>? assets,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
CreateAlbumRoute.name, CreateAlbumRoute.name,
args: CreateAlbumRouteArgs(key: key, assets: assets), args: CreateAlbumRouteArgs(key: key, assets: assets),
initialChildren: children, initialChildren: children,
); );
static const String name = 'CreateAlbumRoute'; static const String name = 'CreateAlbumRoute';
@ -515,10 +515,10 @@ class CropImageRoute extends PageRouteInfo<CropImageRouteArgs> {
required Asset asset, required Asset asset,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
CropImageRoute.name, CropImageRoute.name,
args: CropImageRouteArgs(key: key, image: image, asset: asset), args: CropImageRouteArgs(key: key, image: image, asset: asset),
initialChildren: children, initialChildren: children,
); );
static const String name = 'CropImageRoute'; static const String name = 'CropImageRoute';
@ -560,15 +560,15 @@ class EditImageRoute extends PageRouteInfo<EditImageRouteArgs> {
required bool isEdited, required bool isEdited,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
EditImageRoute.name, EditImageRoute.name,
args: EditImageRouteArgs( args: EditImageRouteArgs(
key: key, key: key,
asset: asset, asset: asset,
image: image, image: image,
isEdited: isEdited, isEdited: isEdited,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'EditImageRoute'; static const String name = 'EditImageRoute';
@ -612,7 +612,7 @@ class EditImageRouteArgs {
/// [FailedBackupStatusPage] /// [FailedBackupStatusPage]
class FailedBackupStatusRoute extends PageRouteInfo<void> { class FailedBackupStatusRoute extends PageRouteInfo<void> {
const FailedBackupStatusRoute({List<PageRouteInfo>? children}) const FailedBackupStatusRoute({List<PageRouteInfo>? children})
: super(FailedBackupStatusRoute.name, initialChildren: children); : super(FailedBackupStatusRoute.name, initialChildren: children);
static const String name = 'FailedBackupStatusRoute'; static const String name = 'FailedBackupStatusRoute';
@ -628,7 +628,7 @@ class FailedBackupStatusRoute extends PageRouteInfo<void> {
/// [FavoritesPage] /// [FavoritesPage]
class FavoritesRoute extends PageRouteInfo<void> { class FavoritesRoute extends PageRouteInfo<void> {
const FavoritesRoute({List<PageRouteInfo>? children}) const FavoritesRoute({List<PageRouteInfo>? children})
: super(FavoritesRoute.name, initialChildren: children); : super(FavoritesRoute.name, initialChildren: children);
static const String name = 'FavoritesRoute'; static const String name = 'FavoritesRoute';
@ -644,7 +644,7 @@ class FavoritesRoute extends PageRouteInfo<void> {
/// [FeatInDevPage] /// [FeatInDevPage]
class FeatInDevRoute extends PageRouteInfo<void> { class FeatInDevRoute extends PageRouteInfo<void> {
const FeatInDevRoute({List<PageRouteInfo>? children}) const FeatInDevRoute({List<PageRouteInfo>? children})
: super(FeatInDevRoute.name, initialChildren: children); : super(FeatInDevRoute.name, initialChildren: children);
static const String name = 'FeatInDevRoute'; static const String name = 'FeatInDevRoute';
@ -665,10 +665,10 @@ class FilterImageRoute extends PageRouteInfo<FilterImageRouteArgs> {
required Asset asset, required Asset asset,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
FilterImageRoute.name, FilterImageRoute.name,
args: FilterImageRouteArgs(key: key, image: image, asset: asset), args: FilterImageRouteArgs(key: key, image: image, asset: asset),
initialChildren: children, initialChildren: children,
); );
static const String name = 'FilterImageRoute'; static const String name = 'FilterImageRoute';
@ -712,10 +712,10 @@ class FolderRoute extends PageRouteInfo<FolderRouteArgs> {
RecursiveFolder? folder, RecursiveFolder? folder,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
FolderRoute.name, FolderRoute.name,
args: FolderRouteArgs(key: key, folder: folder), args: FolderRouteArgs(key: key, folder: folder),
initialChildren: children, initialChildren: children,
); );
static const String name = 'FolderRoute'; static const String name = 'FolderRoute';
@ -754,16 +754,16 @@ class GalleryViewerRoute extends PageRouteInfo<GalleryViewerRouteArgs> {
bool showStack = false, bool showStack = false,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
GalleryViewerRoute.name, GalleryViewerRoute.name,
args: GalleryViewerRouteArgs( args: GalleryViewerRouteArgs(
key: key, key: key,
renderList: renderList, renderList: renderList,
initialIndex: initialIndex, initialIndex: initialIndex,
heroOffset: heroOffset, heroOffset: heroOffset,
showStack: showStack, showStack: showStack,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'GalleryViewerRoute'; static const String name = 'GalleryViewerRoute';
@ -811,7 +811,7 @@ class GalleryViewerRouteArgs {
/// [HeaderSettingsPage] /// [HeaderSettingsPage]
class HeaderSettingsRoute extends PageRouteInfo<void> { class HeaderSettingsRoute extends PageRouteInfo<void> {
const HeaderSettingsRoute({List<PageRouteInfo>? children}) const HeaderSettingsRoute({List<PageRouteInfo>? children})
: super(HeaderSettingsRoute.name, initialChildren: children); : super(HeaderSettingsRoute.name, initialChildren: children);
static const String name = 'HeaderSettingsRoute'; static const String name = 'HeaderSettingsRoute';
@ -827,7 +827,7 @@ class HeaderSettingsRoute extends PageRouteInfo<void> {
/// [LibraryPage] /// [LibraryPage]
class LibraryRoute extends PageRouteInfo<void> { class LibraryRoute extends PageRouteInfo<void> {
const LibraryRoute({List<PageRouteInfo>? children}) const LibraryRoute({List<PageRouteInfo>? children})
: super(LibraryRoute.name, initialChildren: children); : super(LibraryRoute.name, initialChildren: children);
static const String name = 'LibraryRoute'; static const String name = 'LibraryRoute';
@ -843,7 +843,7 @@ class LibraryRoute extends PageRouteInfo<void> {
/// [LocalAlbumsPage] /// [LocalAlbumsPage]
class LocalAlbumsRoute extends PageRouteInfo<void> { class LocalAlbumsRoute extends PageRouteInfo<void> {
const LocalAlbumsRoute({List<PageRouteInfo>? children}) const LocalAlbumsRoute({List<PageRouteInfo>? children})
: super(LocalAlbumsRoute.name, initialChildren: children); : super(LocalAlbumsRoute.name, initialChildren: children);
static const String name = 'LocalAlbumsRoute'; static const String name = 'LocalAlbumsRoute';
@ -859,7 +859,7 @@ class LocalAlbumsRoute extends PageRouteInfo<void> {
/// [LoginPage] /// [LoginPage]
class LoginRoute extends PageRouteInfo<void> { class LoginRoute extends PageRouteInfo<void> {
const LoginRoute({List<PageRouteInfo>? children}) const LoginRoute({List<PageRouteInfo>? children})
: super(LoginRoute.name, initialChildren: children); : super(LoginRoute.name, initialChildren: children);
static const String name = 'LoginRoute'; static const String name = 'LoginRoute';
@ -879,13 +879,13 @@ class MapLocationPickerRoute extends PageRouteInfo<MapLocationPickerRouteArgs> {
LatLng initialLatLng = const LatLng(0, 0), LatLng initialLatLng = const LatLng(0, 0),
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
MapLocationPickerRoute.name, MapLocationPickerRoute.name,
args: MapLocationPickerRouteArgs( args: MapLocationPickerRouteArgs(
key: key, key: key,
initialLatLng: initialLatLng, initialLatLng: initialLatLng,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'MapLocationPickerRoute'; static const String name = 'MapLocationPickerRoute';
@ -923,11 +923,11 @@ class MapLocationPickerRouteArgs {
/// [MapPage] /// [MapPage]
class MapRoute extends PageRouteInfo<MapRouteArgs> { class MapRoute extends PageRouteInfo<MapRouteArgs> {
MapRoute({Key? key, LatLng? initialLocation, List<PageRouteInfo>? children}) MapRoute({Key? key, LatLng? initialLocation, List<PageRouteInfo>? children})
: super( : super(
MapRoute.name, MapRoute.name,
args: MapRouteArgs(key: key, initialLocation: initialLocation), args: MapRouteArgs(key: key, initialLocation: initialLocation),
initialChildren: children, initialChildren: children,
); );
static const String name = 'MapRoute'; static const String name = 'MapRoute';
@ -964,14 +964,14 @@ class MemoryRoute extends PageRouteInfo<MemoryRouteArgs> {
Key? key, Key? key,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
MemoryRoute.name, MemoryRoute.name,
args: MemoryRouteArgs( args: MemoryRouteArgs(
memories: memories, memories: memories,
memoryIndex: memoryIndex, memoryIndex: memoryIndex,
key: key, key: key,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'MemoryRoute'; static const String name = 'MemoryRoute';
@ -1018,16 +1018,16 @@ class NativeVideoViewerRoute extends PageRouteInfo<NativeVideoViewerRouteArgs> {
int playbackDelayFactor = 1, int playbackDelayFactor = 1,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
NativeVideoViewerRoute.name, NativeVideoViewerRoute.name,
args: NativeVideoViewerRouteArgs( args: NativeVideoViewerRouteArgs(
key: key, key: key,
asset: asset, asset: asset,
image: image, image: image,
showControls: showControls, showControls: showControls,
playbackDelayFactor: playbackDelayFactor, playbackDelayFactor: playbackDelayFactor,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'NativeVideoViewerRoute'; static const String name = 'NativeVideoViewerRoute';
@ -1079,10 +1079,10 @@ class PartnerDetailRoute extends PageRouteInfo<PartnerDetailRouteArgs> {
required UserDto partner, required UserDto partner,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
PartnerDetailRoute.name, PartnerDetailRoute.name,
args: PartnerDetailRouteArgs(key: key, partner: partner), args: PartnerDetailRouteArgs(key: key, partner: partner),
initialChildren: children, initialChildren: children,
); );
static const String name = 'PartnerDetailRoute'; static const String name = 'PartnerDetailRoute';
@ -1112,7 +1112,7 @@ class PartnerDetailRouteArgs {
/// [PartnerPage] /// [PartnerPage]
class PartnerRoute extends PageRouteInfo<void> { class PartnerRoute extends PageRouteInfo<void> {
const PartnerRoute({List<PageRouteInfo>? children}) const PartnerRoute({List<PageRouteInfo>? children})
: super(PartnerRoute.name, initialChildren: children); : super(PartnerRoute.name, initialChildren: children);
static const String name = 'PartnerRoute'; static const String name = 'PartnerRoute';
@ -1128,7 +1128,7 @@ class PartnerRoute extends PageRouteInfo<void> {
/// [PeopleCollectionPage] /// [PeopleCollectionPage]
class PeopleCollectionRoute extends PageRouteInfo<void> { class PeopleCollectionRoute extends PageRouteInfo<void> {
const PeopleCollectionRoute({List<PageRouteInfo>? children}) const PeopleCollectionRoute({List<PageRouteInfo>? children})
: super(PeopleCollectionRoute.name, initialChildren: children); : super(PeopleCollectionRoute.name, initialChildren: children);
static const String name = 'PeopleCollectionRoute'; static const String name = 'PeopleCollectionRoute';
@ -1144,7 +1144,7 @@ class PeopleCollectionRoute extends PageRouteInfo<void> {
/// [PermissionOnboardingPage] /// [PermissionOnboardingPage]
class PermissionOnboardingRoute extends PageRouteInfo<void> { class PermissionOnboardingRoute extends PageRouteInfo<void> {
const PermissionOnboardingRoute({List<PageRouteInfo>? children}) const PermissionOnboardingRoute({List<PageRouteInfo>? children})
: super(PermissionOnboardingRoute.name, initialChildren: children); : super(PermissionOnboardingRoute.name, initialChildren: children);
static const String name = 'PermissionOnboardingRoute'; static const String name = 'PermissionOnboardingRoute';
@ -1165,14 +1165,14 @@ class PersonResultRoute extends PageRouteInfo<PersonResultRouteArgs> {
required String personName, required String personName,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
PersonResultRoute.name, PersonResultRoute.name,
args: PersonResultRouteArgs( args: PersonResultRouteArgs(
key: key, key: key,
personId: personId, personId: personId,
personName: personName, personName: personName,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'PersonResultRoute'; static const String name = 'PersonResultRoute';
@ -1212,7 +1212,7 @@ class PersonResultRouteArgs {
/// [PhotosPage] /// [PhotosPage]
class PhotosRoute extends PageRouteInfo<void> { class PhotosRoute extends PageRouteInfo<void> {
const PhotosRoute({List<PageRouteInfo>? children}) const PhotosRoute({List<PageRouteInfo>? children})
: super(PhotosRoute.name, initialChildren: children); : super(PhotosRoute.name, initialChildren: children);
static const String name = 'PhotosRoute'; static const String name = 'PhotosRoute';
@ -1232,13 +1232,13 @@ class PlacesCollectionRoute extends PageRouteInfo<PlacesCollectionRouteArgs> {
LatLng? currentLocation, LatLng? currentLocation,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
PlacesCollectionRoute.name, PlacesCollectionRoute.name,
args: PlacesCollectionRouteArgs( args: PlacesCollectionRouteArgs(
key: key, key: key,
currentLocation: currentLocation, currentLocation: currentLocation,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'PlacesCollectionRoute'; static const String name = 'PlacesCollectionRoute';
@ -1273,7 +1273,7 @@ class PlacesCollectionRouteArgs {
/// [RecentlyTakenPage] /// [RecentlyTakenPage]
class RecentlyTakenRoute extends PageRouteInfo<void> { class RecentlyTakenRoute extends PageRouteInfo<void> {
const RecentlyTakenRoute({List<PageRouteInfo>? children}) const RecentlyTakenRoute({List<PageRouteInfo>? children})
: super(RecentlyTakenRoute.name, initialChildren: children); : super(RecentlyTakenRoute.name, initialChildren: children);
static const String name = 'RecentlyTakenRoute'; static const String name = 'RecentlyTakenRoute';
@ -1293,10 +1293,10 @@ class SearchRoute extends PageRouteInfo<SearchRouteArgs> {
SearchFilter? prefilter, SearchFilter? prefilter,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
SearchRoute.name, SearchRoute.name,
args: SearchRouteArgs(key: key, prefilter: prefilter), args: SearchRouteArgs(key: key, prefilter: prefilter),
initialChildren: children, initialChildren: children,
); );
static const String name = 'SearchRoute'; static const String name = 'SearchRoute';
@ -1328,7 +1328,7 @@ class SearchRouteArgs {
/// [SettingsPage] /// [SettingsPage]
class SettingsRoute extends PageRouteInfo<void> { class SettingsRoute extends PageRouteInfo<void> {
const SettingsRoute({List<PageRouteInfo>? children}) const SettingsRoute({List<PageRouteInfo>? children})
: super(SettingsRoute.name, initialChildren: children); : super(SettingsRoute.name, initialChildren: children);
static const String name = 'SettingsRoute'; static const String name = 'SettingsRoute';
@ -1348,10 +1348,10 @@ class SettingsSubRoute extends PageRouteInfo<SettingsSubRouteArgs> {
Key? key, Key? key,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
SettingsSubRoute.name, SettingsSubRoute.name,
args: SettingsSubRouteArgs(section: section, key: key), args: SettingsSubRouteArgs(section: section, key: key),
initialChildren: children, initialChildren: children,
); );
static const String name = 'SettingsSubRoute'; static const String name = 'SettingsSubRoute';
@ -1385,10 +1385,10 @@ class ShareIntentRoute extends PageRouteInfo<ShareIntentRouteArgs> {
required List<ShareIntentAttachment> attachments, required List<ShareIntentAttachment> attachments,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
ShareIntentRoute.name, ShareIntentRoute.name,
args: ShareIntentRouteArgs(key: key, attachments: attachments), args: ShareIntentRouteArgs(key: key, attachments: attachments),
initialChildren: children, initialChildren: children,
); );
static const String name = 'ShareIntentRoute'; static const String name = 'ShareIntentRoute';
@ -1424,15 +1424,15 @@ class SharedLinkEditRoute extends PageRouteInfo<SharedLinkEditRouteArgs> {
String? albumId, String? albumId,
List<PageRouteInfo>? children, List<PageRouteInfo>? children,
}) : super( }) : super(
SharedLinkEditRoute.name, SharedLinkEditRoute.name,
args: SharedLinkEditRouteArgs( args: SharedLinkEditRouteArgs(
key: key, key: key,
existingLink: existingLink, existingLink: existingLink,
assetsList: assetsList, assetsList: assetsList,
albumId: albumId, albumId: albumId,
), ),
initialChildren: children, initialChildren: children,
); );
static const String name = 'SharedLinkEditRoute'; static const String name = 'SharedLinkEditRoute';
@ -1478,7 +1478,7 @@ class SharedLinkEditRouteArgs {
/// [SharedLinkPage] /// [SharedLinkPage]
class SharedLinkRoute extends PageRouteInfo<void> { class SharedLinkRoute extends PageRouteInfo<void> {
const SharedLinkRoute({List<PageRouteInfo>? children}) const SharedLinkRoute({List<PageRouteInfo>? children})
: super(SharedLinkRoute.name, initialChildren: children); : super(SharedLinkRoute.name, initialChildren: children);
static const String name = 'SharedLinkRoute'; static const String name = 'SharedLinkRoute';
@ -1494,7 +1494,7 @@ class SharedLinkRoute extends PageRouteInfo<void> {
/// [SplashScreenPage] /// [SplashScreenPage]
class SplashScreenRoute extends PageRouteInfo<void> { class SplashScreenRoute extends PageRouteInfo<void> {
const SplashScreenRoute({List<PageRouteInfo>? children}) const SplashScreenRoute({List<PageRouteInfo>? children})
: super(SplashScreenRoute.name, initialChildren: children); : super(SplashScreenRoute.name, initialChildren: children);
static const String name = 'SplashScreenRoute'; static const String name = 'SplashScreenRoute';
@ -1510,7 +1510,7 @@ class SplashScreenRoute extends PageRouteInfo<void> {
/// [TabControllerPage] /// [TabControllerPage]
class TabControllerRoute extends PageRouteInfo<void> { class TabControllerRoute extends PageRouteInfo<void> {
const TabControllerRoute({List<PageRouteInfo>? children}) const TabControllerRoute({List<PageRouteInfo>? children})
: super(TabControllerRoute.name, initialChildren: children); : super(TabControllerRoute.name, initialChildren: children);
static const String name = 'TabControllerRoute'; static const String name = 'TabControllerRoute';
@ -1526,7 +1526,7 @@ class TabControllerRoute extends PageRouteInfo<void> {
/// [TrashPage] /// [TrashPage]
class TrashRoute extends PageRouteInfo<void> { class TrashRoute extends PageRouteInfo<void> {
const TrashRoute({List<PageRouteInfo>? children}) const TrashRoute({List<PageRouteInfo>? children})
: super(TrashRoute.name, initialChildren: children); : super(TrashRoute.name, initialChildren: children);
static const String name = 'TrashRoute'; static const String name = 'TrashRoute';