Advertisement
Desbrina

UpdateScreenView.swift

Jun 29th, 2025
277
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 10.12 KB | None | 0 0
  1. //
  2. //  UpdateScreen.swift
  3. //  Diamond Painting Logbook
  4. //
  5. //  Created by Ceri Turner on 27/01/2024.
  6. //
  7.  
  8. import SwiftUI
  9. import CoreData
  10.  
  11. struct UpdateScreenView: View {
  12.     @Environment(\.managedObjectContext) private var viewContext
  13.    
  14.     @Binding var isActive: Bool
  15.    
  16.     @State private var leftToUpdate = 0
  17.     @State private var currentProjectImage : UIImage!
  18.     @State private var currentProjectName = ""
  19.     @State private var currentPicNumber = 0
  20.     @State private var projectPicNumber = 0
  21.    
  22.     private let prefs: UserDefaults = UserDefaults.standard
  23.    
  24.     var body: some View {
  25.         VStack {
  26.             if getHowManyProjectsToUpdate() > 0 {
  27.                 if currentProjectImage != nil {
  28.                     Image(uiImage: currentProjectImage)
  29.                         .renderingMode(.original)
  30.                         .resizable()
  31.                         .scaledToFit()
  32.                         .frame(height: 200.0)
  33.                         .border(.black)
  34.                 }
  35.                 ProgressView()
  36.                     .frame(width: 100, height: 100)
  37.                     .background(Color.white)
  38.                     .cornerRadius(20)
  39.                     .opacity(1)
  40.                     .shadow(color: Color.gray.opacity(0.5), radius: 4.0, x: 1.0, y: 2.0)
  41.                 Text("Total Projects left to Update: \(leftToUpdate)")
  42.                 Text("Current Project: \(currentProjectName)")
  43.                 Text("Picture: \(currentPicNumber) \\ \(projectPicNumber)")
  44.             }
  45.         }
  46.         .onAppear() {
  47.             DispatchQueue.global(qos: .background).async {
  48.                 while (getHowManyProjectsToUpdate() > 0) {
  49.                     leftToUpdate = getHowManyProjectsToUpdate()
  50.                     updateLocal()
  51.                 }
  52.                 if getHowManyProjectsToUpdate() == 0 {
  53.                     while (getNumberOfFilesInDocumentsDirectory() > 0) {
  54.                         deleteImagesFromDocumentsDirectory()
  55.                     }
  56.                     if getNumberOfFilesInDocumentsDirectory() == 0 {
  57.                         DispatchQueue.main.asyncAfter(deadline: .now()) {
  58.                             withAnimation {
  59.                                 self.isActive = true
  60.                             }
  61.                         }
  62.                     }
  63.                 }
  64.             }
  65.         }
  66.     }
  67.    
  68.     func getNumberOfFilesInDocumentsDirectory() -> Int {
  69.         let fileManager = FileManager.default
  70.         let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
  71.         let content = try? fileManager.contentsOfDirectory(atPath: path)
  72.        
  73.         return content?.count ?? 0
  74.     }
  75.    
  76.     func deleteImagesFromDocumentsDirectory() {
  77.         // Remove all images from Documents Directory
  78.         let documentsUrl = URL.documentsDirectory
  79.        
  80.         do {
  81.             let fileURLs = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
  82.             for fileURL in fileURLs {
  83.                 try FileManager.default.removeItem(at: fileURL)
  84.             }
  85.         } catch  { print(error) }
  86.        
  87.         let fileManager = FileManager.default
  88.         let temporaryDirectory = fileManager.temporaryDirectory
  89.         try? fileManager
  90.             .contentsOfDirectory(at: temporaryDirectory, includingPropertiesForKeys: nil, options: .skipsSubdirectoryDescendants)
  91.             .forEach { file in
  92.                 try? fileManager.removeItem(atPath: file.path)
  93.             }
  94.     }
  95.    
  96.     func getHowManyProjectsToUpdate() -> Int {
  97.         let fetchRequest: NSFetchRequest<Project> = Project.fetchRequest()
  98.         fetchRequest.predicate = NSPredicate(format: "converted = %d", false)
  99.        
  100.         do {
  101.             let pictures = try viewContext.fetch(fetchRequest)
  102.             return pictures.count
  103.         } catch {
  104.             print("Fetching Failed")
  105.         }
  106.        
  107.         return 0
  108.     }
  109.    
  110.     func updateLocal() {
  111.         autoreleasepool {
  112.             let fetchRequest: NSFetchRequest<Project> = Project.fetchRequest()
  113.             fetchRequest.predicate = NSPredicate(format: "converted = %d", false)
  114.             fetchRequest.fetchLimit = 1
  115.             fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Project.name, ascending: true), NSSortDescriptor(keyPath: \Project.name, ascending: true)]
  116.            
  117.             do {
  118.                 let projects = try viewContext.fetch(fetchRequest)
  119.                 for project in projects {
  120.                     currentPicNumber = 0
  121.                     currentProjectName = project.name ?? "Error loading project"
  122.                     if let projectMain = project.mainPicture {
  123.                         currentProjectImage = getUIImage(picture: projectMain)
  124.                     }
  125.                     if let pictures = project.pictures {
  126.                         projectPicNumber = pictures.count
  127.                         // Get main image
  128.                         if let projectMain = project.mainPicture {
  129.                             if let imgThumbData = convertImageThumb(picture: projectMain) {
  130.                                 project.mainPictureData = imgThumbData
  131.                             }
  132.                         }
  133.                        
  134.                         while (getTotalImagesToConvertForProject(project: project ) > 0) {
  135.                             convertImageBatch(project: project)
  136.                         }
  137.                        
  138.                         project.converted = true
  139.                         saveContext()
  140.                         viewContext.refreshAllObjects()
  141.                     }
  142.                 }
  143.             } catch {
  144.                 print("Fetch Failed")
  145.             }
  146.         }
  147.     }
  148.    
  149.     func getTotalImagesToConvertForProject(project: Project) -> Int {
  150.         let fetchRequestPic: NSFetchRequest<Picture> = Picture.fetchRequest()
  151.        
  152.         let projectPredicate = NSPredicate(format: "project = %@", project)
  153.         let dataPredicate = NSPredicate(format: "pictureData == NULL")
  154.        
  155.         fetchRequestPic.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [projectPredicate, dataPredicate])
  156.        
  157.         do {
  158.             let pictures = try viewContext.fetch(fetchRequestPic)
  159.             return pictures.count
  160.         } catch {
  161.             print("Fetching Failed")
  162.         }
  163.         return 0
  164.     }
  165.    
  166.     func convertImageBatch(project: Project) {
  167.         autoreleasepool {
  168.             let fetchRequestPic: NSFetchRequest<Picture> = Picture.fetchRequest()
  169.             let projectPredicate = NSPredicate(format: "project = %@", project)
  170.             let dataPredicate = NSPredicate(format: "pictureData == NULL")
  171.            
  172.             fetchRequestPic.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [projectPredicate, dataPredicate])
  173.             fetchRequestPic.fetchLimit = 5
  174.             fetchRequestPic.sortDescriptors = [NSSortDescriptor(keyPath: \Picture.dateTaken, ascending: true)]
  175.            
  176.             do {
  177.                 let pictures = try viewContext.fetch(fetchRequestPic)
  178.                 for picture in pictures {
  179.                     currentPicNumber = currentPicNumber + 1
  180.                    
  181.                     if let imgData = convertImage(picture: picture), let imgThumbData = convertImageThumb(picture: picture) {
  182.                         // Save Converted
  183.                         picture.pictureData = imgData
  184.                         picture.pictureThumbnailData = imgThumbData
  185.                        
  186.                         // Save Image
  187.                         saveContext()
  188.                         viewContext.refreshAllObjects()
  189.                     } else {
  190.                         viewContext.delete(picture)
  191.                         saveContext()
  192.                         viewContext.refreshAllObjects()
  193.                     }
  194.                 }
  195.                
  196.             } catch {
  197.                 print("Fetch Failed")
  198.             }
  199.         }
  200.     }
  201.    
  202.     func getUIImage(picture : Picture)-> UIImage? {
  203.         let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
  204.         let path = paths[0]
  205.         if let picName = picture.pictureName {
  206.             let imagePath = path.appendingPathComponent(picName)
  207.             if let uiImage = UIImage(contentsOfFile: imagePath.path) {
  208.                 return uiImage
  209.             }
  210.         }
  211.         return nil
  212.     }
  213.    
  214.     func deleteImage(fileName: String) {
  215.         let fileManager = FileManager.default
  216.         do {
  217.             let filePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(fileName)
  218.             if fileManager.fileExists(atPath: filePath){
  219.                 guard let url = URL(string: filePath) else { return }
  220.                 try fileManager.removeItem(at: url)
  221.             }
  222.         } catch {
  223.             print(error)
  224.         }
  225.     }
  226.    
  227.     func convertImage(picture : Picture)-> Data? {
  228.         let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
  229.         let path = paths[0]
  230.         if let picName = picture.pictureName {
  231.             let imagePath = path.appendingPathComponent(picName)
  232.             if let uiImage = UIImage(contentsOfFile: imagePath.path) {
  233.                 if let imageData = uiImage.jpegData(compressionQuality: 1) {
  234.                     return imageData
  235.                 }
  236.             }
  237.         }
  238.         return nil
  239.     }
  240.    
  241.     func convertImageThumb(picture : Picture)-> Data? {
  242.         let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
  243.         let path = paths[0]
  244.         if let picName = picture.pictureName {
  245.             let imagePath = path.appendingPathComponent(picName)
  246.             if let uiImage = UIImage(contentsOfFile: imagePath.path) {
  247.                 let resized = uiImage.scale(newWidth: 300)
  248.                 if let imageData = resized.jpegData(compressionQuality: 1) {
  249.                     return imageData
  250.                 }
  251.             }
  252.         }
  253.         return nil
  254.     }
  255.    
  256.     func saveContext() {
  257.         do {
  258.             try viewContext.save()
  259.         } catch {
  260.             let nsError = error as NSError
  261.             fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
  262.         }
  263.     }
  264.    
  265. }
  266.  
  267.  
  268.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement