Fix HEIC preview + clean up EXIF unverified messages
PhotoPreviewDialog: always use sips-converted JPEG from cache for display. On cache miss: pull file, run sips --setProperty format jpeg to convert, cache the JPEG. HEIC now displays inline without QuickTime. Verify/VerifyRow: replace 'Make: absent — not a confirmed camera original' with 'Origin unknown' (row) and 'Origin unknown — may not be your photo' (preview dialog). Less developer-jargon, more understandable.
This commit is contained in:
@@ -365,23 +365,32 @@ private fun PhotoPreviewDialog(
|
||||
|
||||
LaunchedEffect(photo.devicePath) {
|
||||
val bytes = withContext(Dispatchers.IO) {
|
||||
// Use cached thumbnail if available
|
||||
// Always use the cached JPEG (sips-converted) — works for HEIC too
|
||||
if (cachePath.toFile().exists() && cachePath.toFile().length() > 0) {
|
||||
java.nio.file.Files.readAllBytes(cachePath)
|
||||
} else {
|
||||
// Pull fresh for preview
|
||||
// Pull to temp, convert to JPEG via sips, cache it
|
||||
val tmpDir = Paths.get(System.getProperty("java.io.tmpdir"), "photophetch-preview")
|
||||
tmpDir.toFile().mkdirs()
|
||||
val tmpFile = tmpDir.resolve("preview-${photo.filename}")
|
||||
val ok = pullFn(photo.devicePath, tmpFile)
|
||||
if (ok && tmpFile.toFile().exists()) java.nio.file.Files.readAllBytes(tmpFile) else null
|
||||
if (ok && tmpFile.toFile().exists()) {
|
||||
val sips = ProcessBuilder("sips", "--resampleWidth", "800",
|
||||
"--setProperty", "format", "jpeg",
|
||||
tmpFile.toString(), "--out", cachePath.toString())
|
||||
.redirectErrorStream(true).start()
|
||||
sips.inputStream.readBytes()
|
||||
sips.waitFor()
|
||||
tmpFile.toFile().delete()
|
||||
if (cachePath.toFile().exists()) java.nio.file.Files.readAllBytes(cachePath) else null
|
||||
} else null
|
||||
}
|
||||
}
|
||||
if (bytes != null) {
|
||||
runCatching { bitmap = SkiaImage.makeFromEncoded(bytes).toComposeImageBitmap() }
|
||||
}
|
||||
|
||||
// For Live Photos: also open the companion MOV in system viewer
|
||||
// For Live Photos: open the companion MOV in system viewer
|
||||
if (photo.isLivePhotoStill && photo.companionDevicePath != null) {
|
||||
val tmpDir = Paths.get(System.getProperty("java.io.tmpdir"), "photophetch-preview")
|
||||
val movFilename = photo.companionDevicePath.substringAfterLast("/")
|
||||
|
||||
@@ -310,7 +310,7 @@ private fun VerifyResultRow(
|
||||
Text(
|
||||
when {
|
||||
isFailed -> result.error ?: "Failed"
|
||||
exifUnverified -> "⚠ Make: '${result.exifMake?.ifEmpty { "absent" } ?: "absent"}'" +
|
||||
exifUnverified -> "⚠ Origin unknown" +
|
||||
if (showCheckbox) " — kept on phone" else ""
|
||||
exifUnavailable -> "${result.photo.sizeBytes / 1024} KB"
|
||||
else -> "✓ ${result.exifMake} · ${result.photo.sizeBytes / 1024} KB"
|
||||
@@ -381,8 +381,8 @@ private fun ResultPreviewDialog(result: CopyResult, onDismiss: () -> Unit) {
|
||||
Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Text(result.photo.filename, fontWeight = FontWeight.SemiBold)
|
||||
Text(when (result.exifVerified) {
|
||||
true -> "✓ EXIF Make: ${result.exifMake}"
|
||||
false -> "⚠ Make: '${result.exifMake?.ifEmpty { "(absent)" } ?: "(absent)"}' — not a confirmed camera original"
|
||||
true -> "✓ Camera original — Make: ${result.exifMake}"
|
||||
false -> "⚠ Origin unknown — may not be your photo${if (!result.exifMake.isNullOrBlank()) " (Make: ${result.exifMake})" else ""}"
|
||||
null -> "EXIF not checked (install exiftool)"
|
||||
}, style = MaterialTheme.typography.bodySmall,
|
||||
color = when (result.exifVerified) {
|
||||
|
||||
Reference in New Issue
Block a user