Fix EXIF verification for non-Apple devices + sticky preserve folder
EXIF verification: any non-blank Make is now considered verified. Only absent/empty Make triggers 'Origin unknown' warning. Samsung, Google, etc. are all legitimate camera makes. Also cache exifMake to avoid calling exiftool twice per file. Preserve folder structure: add defaultPreserveFolderStructure to AppConfig. Toggling in ImportScreen saves it as the new default. prepareImport() reads from config instead of always resetting to true.
This commit is contained in:
@@ -17,6 +17,8 @@ data class AppConfig(
|
||||
val defaultStripLivePhotoMotion: Boolean = true,
|
||||
/** Default: do not delete from phone (safer default) */
|
||||
val defaultDeleteAfterVerify: Boolean = false,
|
||||
/** Default: preserve folder structure on import */
|
||||
val defaultPreserveFolderStructure: Boolean = true,
|
||||
/** Whether the user has been warned about HEIC phone settings */
|
||||
val heicWarningDismissed: Boolean = false,
|
||||
/** Path to adb binary, or null to use PATH */
|
||||
|
||||
@@ -154,6 +154,8 @@ class Copier(
|
||||
}
|
||||
}
|
||||
|
||||
val exifMake = readExifMake(finalFile)
|
||||
|
||||
CopyResult(
|
||||
photo = photo,
|
||||
destinationPath = finalFile,
|
||||
@@ -161,11 +163,8 @@ class Copier(
|
||||
destSha256 = destHash,
|
||||
verified = verified,
|
||||
convertedFromHeic = wasConverted,
|
||||
exifVerified = readExifMake(finalFile)?.let { make ->
|
||||
make.contains("apple", ignoreCase = true) ||
|
||||
make.contains(photo.exifMake ?: "apple", ignoreCase = true)
|
||||
},
|
||||
exifMake = readExifMake(finalFile),
|
||||
exifVerified = exifMake?.let { it.isNotBlank() },
|
||||
exifMake = exifMake,
|
||||
error = when {
|
||||
!verified && remoteHash != null -> "Hash mismatch — file may be corrupt"
|
||||
!verified -> "Copy failed — file missing or size mismatch"
|
||||
|
||||
@@ -371,11 +371,11 @@ class AppState(private val configStore: ConfigStore) {
|
||||
StagingPath.uniqueFolderName(Paths.get(cfg.stagingRoot), baseName)
|
||||
} else baseName
|
||||
|
||||
// Multi-folder selection → preserve structure by default
|
||||
// Multi-folder selection → preserve structure; otherwise use saved config default
|
||||
val multipleSourceFolders = _selectedPhotos.value.map { it.sourceFolder }.distinct().size > 1
|
||||
_importConfig.update { it.copy(
|
||||
folderName = folderName,
|
||||
preserveFolderStructure = multipleSourceFolders,
|
||||
preserveFolderStructure = if (multipleSourceFolders) true else cfg.defaultPreserveFolderStructure,
|
||||
) }
|
||||
navigateTo(Screen.IMPORT_CONFIG)
|
||||
}
|
||||
@@ -469,6 +469,11 @@ class AppState(private val configStore: ConfigStore) {
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
fun updateDefaultPreserveFolderStructure(value: Boolean) {
|
||||
_config.update { it.copy(defaultPreserveFolderStructure = value) }
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
fun dismissHeicWarning() {
|
||||
_config.update { it.copy(heicWarningDismissed = true) }
|
||||
saveConfig()
|
||||
|
||||
@@ -154,7 +154,10 @@ fun ImportScreen(state: AppState) {
|
||||
label = "Preserve folder structure",
|
||||
description = "Files go into subfolders matching their source (Camera/, Screenshots/, etc.).",
|
||||
checked = importConfig.preserveFolderStructure,
|
||||
onCheckedChange = { state.updateImportConfig { copy(preserveFolderStructure = it) } },
|
||||
onCheckedChange = {
|
||||
state.updateImportConfig { copy(preserveFolderStructure = it) }
|
||||
state.updateDefaultPreserveFolderStructure(it)
|
||||
},
|
||||
)
|
||||
ToggleRow(
|
||||
label = "Delete from phone after verification",
|
||||
|
||||
Reference in New Issue
Block a user