[Android] 1.9.2
All checks were successful
OpenClimb Docker Deploy / build-and-push (push) Successful in 2m29s

This commit is contained in:
2025-10-12 20:41:39 -06:00
parent 405fb06d5d
commit 30d2b3938e
23 changed files with 620 additions and 1721 deletions

View File

@@ -1,10 +1,12 @@
import Foundation
import ImageIO
import SwiftUI
import UIKit
class ImageManager {
static let shared = ImageManager()
private let thumbnailCache = NSCache<NSString, UIImage>()
private let fileManager = FileManager.default
private let appSupportDirectoryName = "OpenClimb"
private let imagesDirectoryName = "Images"
@@ -479,6 +481,51 @@ class ImageManager {
return nil
}
func loadThumbnail(fromPath path: String, targetSize: CGSize) async -> UIImage? {
let cacheKey = "\(path)-\(targetSize.width)x\(targetSize.height)" as NSString
if let cachedImage = thumbnailCache.object(forKey: cacheKey) {
return cachedImage
}
guard let imageData = loadImageData(fromPath: path) else {
return nil
}
let options: [CFString: Any] = [
kCGImageSourceCreateThumbnailFromImageIfAbsent: true,
kCGImageSourceCreateThumbnailWithTransform: true,
kCGImageSourceShouldCacheImmediately: true,
kCGImageSourceThumbnailMaxPixelSize: max(targetSize.width, targetSize.height)
* UIScreen.main.scale,
]
guard let imageSource = CGImageSourceCreateWithData(imageData as CFData, nil) else {
return UIImage(data: imageData)
}
let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [CFString: Any]
let orientation = properties?[kCGImagePropertyOrientation] as? UInt32 ?? 1
if let cgImage = CGImageSourceCreateThumbnailAtIndex(
imageSource, 0, options as CFDictionary)
{
let imageOrientation = UIImage.Orientation(rawValue: Int(orientation - 1)) ?? .up
let thumbnail = UIImage(
cgImage: cgImage, scale: UIScreen.main.scale, orientation: imageOrientation)
thumbnailCache.setObject(thumbnail, forKey: cacheKey)
return thumbnail
} else {
if let fallbackImage = UIImage(data: imageData) {
thumbnailCache.setObject(fallbackImage, forKey: cacheKey)
return fallbackImage
}
}
return nil
}
func imageExists(atPath path: String) -> Bool {
let primaryPath = getFullPath(from: path)
let backupPath = backupDirectory.appendingPathComponent(getRelativePath(from: path))
@@ -854,72 +901,4 @@ class ImageManager {
}
}
func migrateImageNamesToDeterministic(dataManager: ClimbingDataManager) {
print("Starting migration of image names to deterministic format...")
var migrationCount = 0
var updatedProblems: [Problem] = []
for problem in dataManager.problems {
guard !problem.imagePaths.isEmpty else { continue }
var newImagePaths: [String] = []
var problemNeedsUpdate = false
for (index, imagePath) in problem.imagePaths.enumerated() {
let currentFilename = URL(fileURLWithPath: imagePath).lastPathComponent
if ImageNamingUtils.isValidImageFilename(currentFilename) {
newImagePaths.append(imagePath)
continue
}
let deterministicName = ImageNamingUtils.generateImageFilename(
problemId: problem.id.uuidString, imageIndex: index)
let oldPath = imagesDirectory.appendingPathComponent(currentFilename)
let newPath = imagesDirectory.appendingPathComponent(deterministicName)
if fileManager.fileExists(atPath: oldPath.path) {
do {
try fileManager.moveItem(at: oldPath, to: newPath)
let oldBackupPath = backupDirectory.appendingPathComponent(currentFilename)
let newBackupPath = backupDirectory.appendingPathComponent(
deterministicName)
if fileManager.fileExists(atPath: oldBackupPath.path) {
try? fileManager.moveItem(at: oldBackupPath, to: newBackupPath)
}
newImagePaths.append(deterministicName)
problemNeedsUpdate = true
migrationCount += 1
print("Migrated: \(currentFilename)\(deterministicName)")
} catch {
print("Failed to migrate \(currentFilename): \(error)")
newImagePaths.append(imagePath)
}
} else {
print("Warning: Image file not found: \(currentFilename)")
newImagePaths.append(imagePath)
}
}
if problemNeedsUpdate {
let updatedProblem = problem.updated(imagePaths: newImagePaths)
updatedProblems.append(updatedProblem)
}
}
for updatedProblem in updatedProblems {
dataManager.updateProblem(updatedProblem)
}
print(
"Migration completed: \(migrationCount) images renamed, \(updatedProblems.count) problems updated"
)
}
}