@@ -37,19 +37,41 @@ struct EjectListView: View {
3737 refreshableListView
3838 . toolbar {
3939 ToolbarItem ( placement: . topBarTrailing) {
40- Button {
41- exportAll ( )
42- } label: {
43- if isExportingAll {
44- ProgressView ( )
45- . progressViewStyle ( CircularProgressViewStyle ( ) )
46- . transition ( . opacity)
47- } else {
48- Label ( NSLocalizedString ( " Export All " , comment: " " ) , systemImage: " square.and.arrow.up " )
49- . transition ( . opacity)
40+ if #available( iOS 16 . 4 , * ) {
41+ ShareLink (
42+ item: CompressedFileRepresentation (
43+ name: " \( ejectList. app. name) _ \( ejectList. app. id) _ \( UUID ( ) . uuidString. components ( separatedBy: " - " ) . last ?? " " ) .zip " ,
44+ urls: ejectList. injectedPlugIns. map ( \. url)
45+ ) ,
46+ preview: SharePreview (
47+ String ( format: NSLocalizedString ( " %ld Plug-Ins of “%@” " , comment: " " ) , ejectList. injectedPlugIns. count, ejectList. app. name)
48+ )
49+ ) {
50+ if isExportingAll {
51+ ProgressView ( )
52+ . progressViewStyle ( CircularProgressViewStyle ( ) )
53+ . transition ( . opacity)
54+ } else {
55+ Label ( NSLocalizedString ( " Export All " , comment: " " ) , systemImage: " square.and.arrow.up " )
56+ . transition ( . opacity)
57+ }
5058 }
59+ . disabled ( ejectList. injectedPlugIns. isEmpty)
60+ } else {
61+ Button {
62+ exportAll ( )
63+ } label: {
64+ if isExportingAll {
65+ ProgressView ( )
66+ . progressViewStyle ( CircularProgressViewStyle ( ) )
67+ . transition ( . opacity)
68+ } else {
69+ Label ( NSLocalizedString ( " Export All " , comment: " " ) , systemImage: " square.and.arrow.up " )
70+ . transition ( . opacity)
71+ }
72+ }
73+ . disabled ( ejectList. injectedPlugIns. isEmpty)
5174 }
52- . disabled ( ejectList. injectedPlugIns. isEmpty)
5375 }
5476 }
5577 . animation ( . easeOut, value: isExportingAll)
@@ -334,7 +356,7 @@ struct EjectListView: View {
334356 . appendingPathComponent (
335357 " \( ejectList. app. name) _ \( ejectList. app. id) _ \( UUID ( ) . uuidString. components ( separatedBy: " - " ) . last ?? " " ) .zip " )
336358
337- try fileMgr. zipItem ( at: exportURL, to: zipURL)
359+ try fileMgr. zipItem ( at: exportURL, to: zipURL, shouldKeepParent : false )
338360
339361 DispatchQueue . main. async {
340362 quickLookExport = zipURL
@@ -354,12 +376,30 @@ struct EjectListView: View {
354376 }
355377}
356378
357- final class EjectListSearchViewModel : NSObject , UISearchResultsUpdating , ObservableObject {
358- @Published var searchKeyword : String = " "
379+ @available ( iOS 16 . 0 , * )
380+ private struct CompressedFileRepresentation : Transferable {
381+ let name : String
382+ let urls : [ URL ]
383+
384+ static var transferRepresentation : some TransferRepresentation {
385+ FileRepresentation ( exportedContentType: . zip) { archive in
386+ let exportURL = InjectorV3 . temporaryRoot
387+ . appendingPathComponent ( " Exports_ \( UUID ( ) . uuidString) " , isDirectory: true )
359388
360- weak var searchController : UISearchController ?
389+ let fileMgr = FileManager . default
390+ try fileMgr. createDirectory ( at: exportURL, withIntermediateDirectories: true )
391+
392+ for url in archive. urls {
393+ let exportURL = exportURL. appendingPathComponent ( url. lastPathComponent)
394+ try fileMgr. copyItem ( at: url, to: exportURL)
395+ }
361396
362- func updateSearchResults( for searchController: UISearchController ) {
363- searchKeyword = searchController. searchBar. text ?? " "
397+ let zipURL = InjectorV3 . temporaryRoot
398+ . appendingPathComponent ( archive. name)
399+
400+ try fileMgr. zipItem ( at: exportURL, to: zipURL, shouldKeepParent: false )
401+
402+ return SentTransferredFile ( zipURL)
403+ }
364404 }
365405}
0 commit comments