Skip to content

Commit 29f05f8

Browse files
committed
perf: prefetch file tags after paginating
and fix some caching behavior. This eliminates tag-resolving network requests each time when a file is opened. + also prepare multi-file upload feature
1 parent 7c58a2a commit 29f05f8

6 files changed

Lines changed: 142 additions & 282 deletions

File tree

CommonsFinder.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,10 @@
224224
"Views/Extensions/MediaFile+localizedDisplayCaption.swift",
225225
"Views/Extensions/MediaFileDraftModel+ImageRequest.swift",
226226
"Views/Extensions/UserDefaults+accessors.swift",
227-
Views/FileCreateView/FileCreateView.swift,
227+
Views/FileCreateView/DraftSheetModifer.swift,
228228
Views/FileCreateView/FilenameTip.swift,
229229
Views/FileCreateView/LicensePicker.swift,
230-
Views/FileCreateView/Model/FileCreateViewModel.swift,
230+
Views/FileCreateView/Model/FileImportModel.swift,
231231
Views/FileCreateView/Model/FileItem.swift,
232232
Views/FileCreateView/Model/MediaFileDraftModel.swift,
233233
Views/FileCreateView/SingleImageDraftView.swift,

CommonsFinder/Localizable.xcstrings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,9 @@
13671367
}
13681368
}
13691369
}
1370+
},
1371+
"Multiple files" : {
1372+
13701373
},
13711374
"Nearby Locations" : {
13721375

CommonsFinder/Observable Models/Navigation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ import os.log
7373
}
7474

7575
// var isViewingFileSheetOpen: MediaFile.ID?
76-
var isEditingDraft: FileCreateViewModel?
76+
var isEditingDraft: FileImportModel?
7777
var isAuthSheetOpen: AuthNavigationDestination?
7878

7979
enum DraftSheetNavItem: Identifiable, Equatable {
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
//
2+
// DraftSheetModifer.swift
3+
// CommonsFinder
4+
//
5+
// Created by Tom Brewe on 08.10.24.
6+
//
7+
8+
import Nuke
9+
import NukeUI
10+
import OrderedCollections
11+
import PhotosUI
12+
import SwiftUI
13+
import os.log
14+
15+
struct DraftSheetModifer: ViewModifier {
16+
@Binding var importModel: FileImportModel?
17+
18+
@State private var draftedFileModels: [MediaFileDraftModel]?
19+
20+
21+
@Environment(\.appDatabase) private var appDatabase
22+
@Environment(\.dismiss) private var dismiss
23+
24+
var isPhotosPickerPresented: Binding<Bool> {
25+
.init(
26+
get: {
27+
importModel?.isPhotosPickerPresented ?? false
28+
},
29+
set: { isPresented in
30+
importModel?.isPhotosPickerPresented = isPresented
31+
})
32+
}
33+
34+
var photosPickerSelection: Binding<[PhotosPickerItem]> {
35+
.init(
36+
get: {
37+
importModel?.photosPickerSelection ?? []
38+
},
39+
set: { newValue in
40+
importModel?.photosPickerSelection = newValue
41+
})
42+
}
43+
44+
var isFileImporterPresented: Binding<Bool> {
45+
.init(
46+
get: {
47+
importModel?.isFileImporterPresented ?? false
48+
},
49+
set: { newValue in
50+
importModel?.isFileImporterPresented = newValue
51+
})
52+
}
53+
54+
var isCameraPresented: Binding<Bool> {
55+
.init(
56+
get: {
57+
importModel?.isCameraPresented ?? false
58+
},
59+
set: { newValue in
60+
importModel?.isCameraPresented = newValue
61+
})
62+
}
63+
64+
65+
func body(content: Content) -> some View {
66+
content
67+
.sheet(item: $draftedFileModels, onDismiss: { importModel = nil }) { draftedFileModels in
68+
69+
NavigationStack {
70+
if draftedFileModels.count == 1, let draftedFileModel = draftedFileModels.first {
71+
SingleImageDraftView(model: draftedFileModel)
72+
} else if draftedFileModels.count > 1 {
73+
Color.red.overlay {
74+
Text("Multiple files")
75+
}
76+
}
77+
78+
}
79+
}
80+
.photosPicker(
81+
isPresented: isPhotosPickerPresented,
82+
selection: photosPickerSelection,
83+
// NOTE: For now only allow 1 image until
84+
// multi-upload is refined.
85+
// maxSelectionCount: 1,
86+
matching: .any(of: [.images]),
87+
preferredItemEncoding: .compatible,
88+
photoLibrary: .shared()
89+
)
90+
.fileImporter(
91+
isPresented: isFileImporterPresented,
92+
// https://commons.wikimedia.org/wiki/Commons:File_types
93+
allowedContentTypes: [
94+
// .mp3, .wav, .midi,
95+
.svg, .png, .webP, .gif, .jpeg,
96+
// .mpeg,
97+
// .pdf,
98+
// .geoJSON,
99+
],
100+
allowsMultipleSelection: false,
101+
onCompletion: { result in
102+
importModel?.handleFileImport(result: result)
103+
}
104+
)
105+
.fullScreenCover(isPresented: isCameraPresented) {
106+
CameraImagePicker { image, metadata in
107+
do {
108+
try importModel?.handleCameraImage(image, metadata: metadata)
109+
} catch {
110+
logger.error("Failed to handle camera input \(error)")
111+
}
112+
}
113+
.ignoresSafeArea(.container)
114+
}
115+
.onChange(of: importModel?.importStatus) {
116+
guard let importModel, importModel.importStatus == .finished else { return }
117+
let fileCount = importModel.editedDrafts.count
118+
if fileCount == 1, let newDraftModel = importModel.editedDrafts.values.first {
119+
draftedFileModels = [newDraftModel]
120+
} else if fileCount > 1 {
121+
draftedFileModels = Array(importModel.editedDrafts.values)
122+
}
123+
124+
}
125+
}
126+
}
127+
128+
extension [MediaFileDraftModel]: @retroactive Identifiable {
129+
public var id: String {
130+
self.reduce("") { partialResult, next in
131+
partialResult + next.id
132+
}
133+
}
134+
}

0 commit comments

Comments
 (0)