From 1a54abef0c20ef7d283ae1c498342d007feab9fc Mon Sep 17 00:00:00 2001 From: 1ris_W Date: Fri, 25 Aug 2023 06:05:34 +0800 Subject: [PATCH 1/2] New: Add function "drop to import" --- .../Components/WallpaperExplorer.swift | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/Open Wallpaper Engine/ContentView/Components/WallpaperExplorer.swift b/Open Wallpaper Engine/ContentView/Components/WallpaperExplorer.swift index 323cdfa..0200302 100644 --- a/Open Wallpaper Engine/ContentView/Components/WallpaperExplorer.swift +++ b/Open Wallpaper Engine/ContentView/Components/WallpaperExplorer.swift @@ -6,13 +6,44 @@ // import SwiftUI +import Foundation +import UniformTypeIdentifiers + +struct WallpaperExplorer: SubviewOfContentView,DropDelegate { + + func dropUpdated(info: DropInfo) -> DropProposal? { + let proposal = DropProposal(operation: .copy) + return proposal + } + + func performDrop(info: DropInfo) -> Bool { + guard let itemProvider = info.itemProviders(for: [UTType.fileURL]).first else { return false } + itemProvider.loadItem(forTypeIdentifier: UTType.fileURL.identifier, options: nil) { item, _ in + guard let data = item as? Data, let url = URL(dataRepresentation: data, relativeTo: nil) else { return } + // Do something with the file url + // remember to dispatch on main in case of a @State change + guard let wallpaperFolder = try? FileWrapper(url: url) + else{print("1");return} + guard wallpaperFolder.fileWrappers?["project.json"] != nil + else{print("2");return} + DispatchQueue.main.async { + try? FileManager.default.copyItem( + at: url, + to: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + .appending(path: url.lastPathComponent) + ) + } + } + return true + } -struct WallpaperExplorer: SubviewOfContentView { @ObservedObject var viewModel: ContentViewModel @ObservedObject var wallpaperViewModel: WallpaperViewModel @State var imageScaleIndex: Int = -1 @State var selectedIndex: Int! + + @State var fileURL: URL? init(contentViewModel viewModel: ContentViewModel, wallpaperViewModel: WallpaperViewModel) { self.viewModel = viewModel @@ -96,7 +127,9 @@ struct WallpaperExplorer: SubviewOfContentView { } .padding(.bottom) } - } } + } + .onDrop(of: [UTType.fileURL], delegate: self) + } } // MARK: - View Modifiers Extension From 87bec01a2b5475bc0adb07415f70a4c04ef17c55 Mon Sep 17 00:00:00 2001 From: Haren Date: Fri, 25 Aug 2023 12:10:26 +0800 Subject: [PATCH 2/2] Fix: Alert When Error Detected & Code Restructure btw, always remember to add `[weak self]` when you intend to reach self property in the closures, or it maybe lead to memory leaks --- .../Components/WallpaperExplorer.swift | 31 +------------ .../ContentView/ContentView.swift | 1 + .../ViewModels/ContentViewModel.swift | 43 ++++++++++++++++++- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/Open Wallpaper Engine/ContentView/Components/WallpaperExplorer.swift b/Open Wallpaper Engine/ContentView/Components/WallpaperExplorer.swift index 0200302..fc4b3ae 100644 --- a/Open Wallpaper Engine/ContentView/Components/WallpaperExplorer.swift +++ b/Open Wallpaper Engine/ContentView/Components/WallpaperExplorer.swift @@ -6,36 +6,8 @@ // import SwiftUI -import Foundation -import UniformTypeIdentifiers -struct WallpaperExplorer: SubviewOfContentView,DropDelegate { - - func dropUpdated(info: DropInfo) -> DropProposal? { - let proposal = DropProposal(operation: .copy) - return proposal - } - - func performDrop(info: DropInfo) -> Bool { - guard let itemProvider = info.itemProviders(for: [UTType.fileURL]).first else { return false } - itemProvider.loadItem(forTypeIdentifier: UTType.fileURL.identifier, options: nil) { item, _ in - guard let data = item as? Data, let url = URL(dataRepresentation: data, relativeTo: nil) else { return } - // Do something with the file url - // remember to dispatch on main in case of a @State change - guard let wallpaperFolder = try? FileWrapper(url: url) - else{print("1");return} - guard wallpaperFolder.fileWrappers?["project.json"] != nil - else{print("2");return} - DispatchQueue.main.async { - try? FileManager.default.copyItem( - at: url, - to: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] - .appending(path: url.lastPathComponent) - ) - } - } - return true - } +struct WallpaperExplorer: SubviewOfContentView { @ObservedObject var viewModel: ContentViewModel @ObservedObject var wallpaperViewModel: WallpaperViewModel @@ -128,7 +100,6 @@ struct WallpaperExplorer: SubviewOfContentView,DropDelegate { .padding(.bottom) } } - .onDrop(of: [UTType.fileURL], delegate: self) } } diff --git a/Open Wallpaper Engine/ContentView/ContentView.swift b/Open Wallpaper Engine/ContentView/ContentView.swift index c355632..509d62b 100644 --- a/Open Wallpaper Engine/ContentView/ContentView.swift +++ b/Open Wallpaper Engine/ContentView/ContentView.swift @@ -49,6 +49,7 @@ struct ContentView: View { .animation(.spring(), value: viewModel.isFilterReveal) WallpaperExplorer(contentViewModel: viewModel, wallpaperViewModel: wallpaperViewModel) + .onDrop(of: [.fileURL], delegate: viewModel) .contextMenu { ExplorerGlobalMenu(contentViewModel: viewModel, wallpaperViewModel: wallpaperViewModel) } diff --git a/Open Wallpaper Engine/ContentView/ViewModels/ContentViewModel.swift b/Open Wallpaper Engine/ContentView/ViewModels/ContentViewModel.swift index 667876f..8a17620 100644 --- a/Open Wallpaper Engine/ContentView/ViewModels/ContentViewModel.swift +++ b/Open Wallpaper Engine/ContentView/ViewModels/ContentViewModel.swift @@ -6,8 +6,9 @@ // import SwiftUI +import UniformTypeIdentifiers -class ContentViewModel: ObservableObject { +class ContentViewModel: ObservableObject, DropDelegate { @AppStorage("FilterReveal") var isFilterReveal = false @AppStorage("WallpaperURLs") var wallpaperUrls = [URL]() @AppStorage("SelectedIndex") var selectedIndex = 0 @@ -104,6 +105,46 @@ class ContentViewModel: ObservableObject { self.importAlertError = error self.importAlertPresented = true } + + func dropUpdated(info: DropInfo) -> DropProposal? { + let proposal = DropProposal(operation: .copy) + return proposal + } + + func performDrop(info: DropInfo) -> Bool { + guard let itemProvider = info.itemProviders(for: [UTType.fileURL]).first + else { + alertImportModal(which: .unkown) + return false + } + itemProvider.loadItem(forTypeIdentifier: UTType.fileURL.identifier, options: nil) { [weak self] item, _ in + guard let data = item as? Data, let url = URL(dataRepresentation: data, relativeTo: nil) + else { + self?.alertImportModal(which: .unkown) + return + } + // Do something with the file url + // remember to dispatch on main in case of a @State change + guard let wallpaperFolder = try? FileWrapper(url: url) + else{ + self?.alertImportModal(which: .unkown) + return + } + guard wallpaperFolder.fileWrappers?["project.json"] != nil + else{ + self?.alertImportModal(which: .doesNotContainWallpaper) + return + } + DispatchQueue.main.async { + try? FileManager.default.copyItem( + at: url, + to: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + .appending(path: url.lastPathComponent) + ) + } + } + return true + } } extension Array: RawRepresentable where Element: Codable {