iOS thumbnails: progress logging + newest-first loading order
Sort photos by dateTaken descending before pre-fetching so most recent photos get thumbnails first — the ones most likely to import. Log progress after each batch: 'iOS thumbnails: 30/600 loaded (batch 1/20)'. Log skip count for already-cached photos on subsequent launches.
This commit is contained in:
@@ -183,8 +183,10 @@ class AppState(private val configStore: ConfigStore) {
|
|||||||
val tmpDir = java.nio.file.Paths.get(System.getProperty("java.io.tmpdir"), "photophetch-thumbs")
|
val tmpDir = java.nio.file.Paths.get(System.getProperty("java.io.tmpdir"), "photophetch-thumbs")
|
||||||
if (!tmpDir.toFile().exists()) tmpDir.toFile().mkdirs()
|
if (!tmpDir.toFile().exists()) tmpDir.toFile().mkdirs()
|
||||||
|
|
||||||
// Only fetch photos not already cached
|
// Only fetch photos not already cached, sorted newest first
|
||||||
val needed = photos.filter { photo ->
|
val needed = photos
|
||||||
|
.sortedByDescending { it.dateTaken }
|
||||||
|
.filter { photo ->
|
||||||
val ext = photo.filename.substringAfterLast(".", "").lowercase()
|
val ext = photo.filename.substringAfterLast(".", "").lowercase()
|
||||||
if (ext in setOf("mp4", "mov", "3gp", "avi", "mkv", "m4v", "webm")) return@filter false
|
if (ext in setOf("mp4", "mov", "3gp", "avi", "mkv", "m4v", "webm")) return@filter false
|
||||||
val hash = (cacheKey + photo.devicePath).hashCode().toString(16)
|
val hash = (cacheKey + photo.devicePath).hashCode().toString(16)
|
||||||
@@ -192,11 +194,17 @@ class AppState(private val configStore: ConfigStore) {
|
|||||||
!cachePath.toFile().exists() || cachePath.toFile().length() == 0L
|
!cachePath.toFile().exists() || cachePath.toFile().length() == 0L
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needed.isEmpty()) return
|
if (needed.isEmpty()) {
|
||||||
log.info("Pre-fetching ${needed.size} iOS thumbnails...")
|
log.info("iOS thumbnails: all ${photos.size} already cached")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.info("iOS thumbnails: pre-fetching ${needed.size} / ${photos.size} (${photos.size - needed.size} already cached)")
|
||||||
|
|
||||||
|
var loaded = 0
|
||||||
|
val batchSize = 30
|
||||||
|
|
||||||
// Build pairs JSON and run batch-thumbs command
|
// Build pairs JSON and run batch-thumbs command
|
||||||
needed.chunked(30).forEach { batch ->
|
needed.chunked(batchSize).forEachIndexed { batchIdx, batch ->
|
||||||
val pairs = batch.joinToString(",") { photo ->
|
val pairs = batch.joinToString(",") { photo ->
|
||||||
val ext = photo.filename.substringAfterLast(".", "").lowercase()
|
val ext = photo.filename.substringAfterLast(".", "").lowercase()
|
||||||
val hash = (cacheKey + photo.devicePath).hashCode().toString(16)
|
val hash = (cacheKey + photo.devicePath).hashCode().toString(16)
|
||||||
@@ -210,11 +218,12 @@ class AppState(private val configStore: ConfigStore) {
|
|||||||
try {
|
try {
|
||||||
val process = ProcessBuilder(connector.pythonBin, connector.helperScript, "batch-thumbs", pairsJson)
|
val process = ProcessBuilder(connector.pythonBin, connector.helperScript, "batch-thumbs", pairsJson)
|
||||||
.redirectErrorStream(false).start()
|
.redirectErrorStream(false).start()
|
||||||
process.inputStream.readBytes() // stdout
|
process.inputStream.readBytes()
|
||||||
process.errorStream.readBytes() // stderr
|
process.errorStream.readBytes()
|
||||||
process.waitFor()
|
process.waitFor()
|
||||||
|
|
||||||
// Run sips on each successfully pulled file
|
// Run sips on each successfully pulled file
|
||||||
|
var batchLoaded = 0
|
||||||
batch.forEach { photo ->
|
batch.forEach { photo ->
|
||||||
val ext = photo.filename.substringAfterLast(".", "").lowercase()
|
val ext = photo.filename.substringAfterLast(".", "").lowercase()
|
||||||
val hash = (cacheKey + photo.devicePath).hashCode().toString(16)
|
val hash = (cacheKey + photo.devicePath).hashCode().toString(16)
|
||||||
@@ -227,13 +236,16 @@ class AppState(private val configStore: ConfigStore) {
|
|||||||
sips.inputStream.readBytes()
|
sips.inputStream.readBytes()
|
||||||
sips.waitFor()
|
sips.waitFor()
|
||||||
tmpFile.toFile().delete()
|
tmpFile.toFile().delete()
|
||||||
|
if (cachePath.toFile().exists()) batchLoaded++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loaded += batchLoaded
|
||||||
|
log.info("iOS thumbnails: $loaded / ${needed.size} loaded (batch ${batchIdx + 1}/${(needed.size + batchSize - 1) / batchSize})")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
log.warn("iOS thumbnail batch failed: ${e.message}")
|
log.warn("iOS thumbnail batch ${batchIdx + 1} failed: ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.info("iOS thumbnail pre-fetch complete")
|
log.info("iOS thumbnails: done — $loaded / ${needed.size} loaded successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selectFolder(folderName: String?) {
|
fun selectFolder(folderName: String?) {
|
||||||
|
|||||||
Reference in New Issue
Block a user