Skip to content

Commit d52a2a6

Browse files
committed
misc fixes and onboarding screen
1 parent 5379d06 commit d52a2a6

File tree

8 files changed

+133
-18
lines changed

8 files changed

+133
-18
lines changed

Django Files/Django_FilesApp.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ struct Django_FilesApp: App {
4242
} else if hasExistingSessions {
4343
TabViewWindow(sessionManager: sessionManager)
4444
} else {
45-
SessionEditor(session: nil, onSessionCreated: { newSession in
45+
SessionEditor(onBoarding: true, session: nil, onSessionCreated: { newSession in
4646
sessionManager.selectedSession = newSession
4747
hasExistingSessions = true
4848
})

Django Files/Views/FileList.swift

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,12 @@ struct FileListView: View {
262262
}
263263

264264
if isLoading && hasNextPage {
265-
Spacer()
266-
LoadingView()
267-
Spacer()
265+
HStack {
266+
Spacer()
267+
LoadingView()
268+
.frame(width: 100, height: 100)
269+
Spacer()
270+
}
268271
}
269272
}
270273
.fullScreenCover(isPresented: $showingPreview) {
@@ -410,12 +413,6 @@ struct FileListView: View {
410413
.onAppear {
411414
loadFiles()
412415
}
413-
414-
if isLoading && hasNextPage {
415-
HStack {
416-
ProgressView()
417-
}
418-
}
419416
}
420417

421418
@MainActor

Django Files/Views/Preview.swift

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import SwiftUI
22
import AVKit
33
import HighlightSwift
44
import UIKit
5+
import PDFKit
56

67
struct ContentPreview: View {
78
let mimeType: String
@@ -54,6 +55,8 @@ struct ContentPreview: View {
5455
videoPreview
5556
} else if mimeType.starts(with: "audio/") {
5657
audioPreview
58+
} else if mimeType == "application/pdf" {
59+
pdfPreview
5760
} else {
5861
genericFilePreview
5962
}
@@ -112,6 +115,14 @@ struct ContentPreview: View {
112115
.padding()
113116
}
114117

118+
// PDF Preview
119+
private var pdfPreview: some View {
120+
PDFView(url: fileURL)
121+
.padding(.top, 45)
122+
.background(.black)
123+
124+
}
125+
115126
// Generic File Preview
116127
private var genericFilePreview: some View {
117128
VStack {
@@ -132,8 +143,8 @@ struct ContentPreview: View {
132143
private func loadContent() {
133144
isLoading = true
134145

135-
// For video, audio, and audio, we don't need to download the content as we'll use the URL directly
136-
if mimeType.starts(with: "video/") || mimeType.starts(with: "audio/") {
146+
// For video, audio, and PDF, we don't need to download the content as we'll use the URL directly
147+
if mimeType.starts(with: "video/") || mimeType.starts(with: "audio/") || mimeType == "application/pdf" {
137148
isLoading = false
138149
return
139150
}
@@ -759,7 +770,7 @@ struct FilePreviewView: View {
759770
} label: {
760771
Image(systemName: "square.and.arrow.up")
761772
.font(.system(size: 20))
762-
.offset(y: -3)
773+
.offset(y: -2)
763774
.padding()
764775
}
765776
.menuStyle(.button)
@@ -852,4 +863,23 @@ struct FilePreviewView: View {
852863
}
853864
}
854865

866+
// PDF View SwiftUI Wrapper
867+
struct PDFView: UIViewRepresentable {
868+
let url: URL
869+
870+
func makeUIView(context: Context) -> PDFKit.PDFView {
871+
let pdfView = PDFKit.PDFView()
872+
pdfView.autoScales = true
873+
pdfView.displayMode = .singlePageContinuous
874+
pdfView.displayDirection = .vertical
875+
return pdfView
876+
}
877+
878+
func updateUIView(_ pdfView: PDFKit.PDFView, context: Context) {
879+
if let document = PDFDocument(url: url) {
880+
pdfView.document = document
881+
}
882+
}
883+
}
884+
855885

Django Files/Views/SessionEditor.swift

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ struct SessionEditor: View {
1616
@State private var showLoginSheet: Bool = false
1717
@State private var tempSession: DjangoFilesSession?
1818

19+
let onBoarding: Bool
1920
let session: DjangoFilesSession?
2021
var onSessionCreated: ((DjangoFilesSession) -> Void)?
21-
22+
2223
private var editorTitle: String {
2324
session == nil ? "Add Server" : "Edit Server"
2425
}
@@ -41,7 +42,7 @@ struct SessionEditor: View {
4142

4243
// Create a temporary DFAPI instance to check auth methods
4344
let api = DFAPI(url: url!, token: "")
44-
if let authResponse = await api.getAuthMethods() {
45+
if let _ = await api.getAuthMethods() {
4546
isCheckingServer = false
4647

4748
// Server is valid, proceed with login
@@ -73,6 +74,26 @@ struct SessionEditor: View {
7374
var body: some View {
7475
NavigationStack {
7576
Form {
77+
if onBoarding {
78+
HStack {
79+
Spacer()
80+
Label("", systemImage: "hand.wave.fill")
81+
.font(.system(size: 50))
82+
.padding(.bottom)
83+
.shadow(color: .purple, radius: 20)
84+
.listRowSeparator(.hidden)
85+
Spacer()
86+
}
87+
Text("Welcome to Django Files!")
88+
.font(.system(size: 25))
89+
.padding(.bottom)
90+
.shadow(color: .purple, radius: 20)
91+
.listRowSeparator(.hidden)
92+
Text("Thanks for using our iOS app! If you don’t have a server set up yet, check out our GitHub README to get started.")
93+
.listRowSeparator(.hidden)
94+
Text("https://github.com/django-files/django-files")
95+
.listRowSeparator(.hidden)
96+
}
7697
Section(header: Text("Server URL")) {
7798
TextField("", text: Binding(
7899
get: {
@@ -197,5 +218,6 @@ struct SessionEditor: View {
197218
}
198219
}
199220
}
221+
.scrollDisabled(true)
200222
}
201223
}

Django Files/Views/ShortList.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct ShortListView: View {
2525
if server.wrappedValue != nil {
2626
NavigationStack {
2727
List {
28-
if shorts.isEmpty {
28+
if shorts.isEmpty && !isLoading {
2929
HStack {
3030
Spacer()
3131
VStack {
@@ -52,6 +52,14 @@ struct ShortListView: View {
5252
ToastManager.shared.showToast(message: "Short URL copied to clipboard")
5353
}
5454
}
55+
if isLoading {
56+
HStack {
57+
Spacer()
58+
LoadingView()
59+
.frame(width: 100, height: 100)
60+
Spacer()
61+
}
62+
}
5563
}
5664
.listStyle(.plain)
5765
.refreshable{

Django Files/Views/TabView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ struct ServerSelector: View {
222222
SessionSelector(session: session)
223223
}
224224
.sheet(isPresented: $showAddServerSheet) {
225-
SessionEditor(session: nil)
225+
SessionEditor(onBoarding: false, session: nil)
226226
}
227227
.confirmationDialog("Delete Server", isPresented: $showingDeleteAlert) {
228228
Button("Cancel", role: .cancel) {}

UploadAndCopy/Base.lproj/MainInterface.storyboard

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@
4040
<rect key="frame" x="169" y="117" width="20" height="20"/>
4141
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
4242
</activityIndicatorView>
43+
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="JQU-no-kae">
44+
<rect key="frame" x="24" y="37" width="311" height="217"/>
45+
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
46+
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
47+
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
48+
<color key="textColor" systemColor="labelColor"/>
49+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
50+
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
51+
</textView>
4352
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="T3b-pJ-MQ3">
4453
<rect key="frame" x="24" y="37" width="311" height="210"/>
4554
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
@@ -129,6 +138,7 @@
129138
<outlet property="shareLabel" destination="h6M-o6-yR9" id="IY1-ab-l1d"/>
130139
<outlet property="shortText" destination="etx-MM-w5d" id="HZN-xL-9My"/>
131140
<outlet property="shortTextLabel" destination="UaI-eI-l62" id="bAS-e8-jIr"/>
141+
<outlet property="textView" destination="JQU-no-kae" id="YMR-ww-xe8"/>
132142
<outlet property="viewOverlay" destination="mZN-4f-xCI" id="Lgi-2P-TJe"/>
133143
</connections>
134144
</viewController>
@@ -138,9 +148,15 @@
138148
</scene>
139149
</scenes>
140150
<resources>
151+
<systemColor name="labelColor">
152+
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
153+
</systemColor>
141154
<systemColor name="lightTextColor">
142155
<color white="1" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
143156
</systemColor>
157+
<systemColor name="systemBackgroundColor">
158+
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
159+
</systemColor>
144160
<systemColor name="systemGrayColor">
145161
<color red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
146162
</systemColor>

UploadAndCopy/ShareViewController.swift

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Social
1010
import SwiftData
1111
import CoreHaptics
1212

13-
class ShareViewController: UIViewController, UITextFieldDelegate, URLSessionTaskDelegate {
13+
class ShareViewController: UIViewController, UITextFieldDelegate, URLSessionTaskDelegate, UITextViewDelegate {
1414
var sharedModelContainer: ModelContainer = {
1515
let schema = Schema([
1616
DjangoFilesSession.self,
@@ -31,6 +31,7 @@ class ShareViewController: UIViewController, UITextFieldDelegate, URLSessionTask
3131
@IBOutlet weak var availableServers: UIButton!
3232
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
3333
@IBOutlet weak var shortTextLabel: UILabel!
34+
@IBOutlet weak var textView: UITextView!
3435
@IBOutlet weak var shortText: UITextField!
3536
@IBOutlet weak var shareLabel: UILabel!
3637

@@ -45,6 +46,7 @@ class ShareViewController: UIViewController, UITextFieldDelegate, URLSessionTask
4546
self.activityIndicator.hidesWhenStopped = true
4647

4748
shortText.delegate = self
49+
textView.delegate = self
4850

4951
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
5052
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
@@ -126,6 +128,36 @@ class ShareViewController: UIViewController, UITextFieldDelegate, URLSessionTask
126128
loaded = true
127129
break
128130
}
131+
else if itemProvider.hasItemConformingToTypeIdentifier("public.text") || itemProvider.hasItemConformingToTypeIdentifier("public.plain-text") {
132+
itemProvider.loadItem(forTypeIdentifier: itemProvider.registeredTypeIdentifiers[0], options: nil, completionHandler: { (item, error) in
133+
DispatchQueue.main.async {
134+
self.shortText.isHidden = true
135+
self.shortTextLabel.isHidden = true
136+
self.textView.isHidden = false
137+
138+
if let text = item as? String {
139+
// Show the text preview
140+
self.textView.text = text
141+
142+
// Create a temporary file to store the text
143+
let tempDirectoryURL = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)
144+
let targetURL = tempDirectoryURL.appendingPathComponent("\(UUID.init().uuidString).txt")
145+
do {
146+
try text.write(to: targetURL, atomically: true, encoding: .utf8)
147+
self.isTempFile = true
148+
self.shareURL = targetURL
149+
self.shareLabel.text = "Upload Text"
150+
} catch {
151+
self.showMessageAndDismiss(message: "Could not share text.")
152+
}
153+
}
154+
self.activityIndicator.stopAnimating()
155+
self.shareButton.isEnabled = true
156+
}
157+
})
158+
loaded = true
159+
break
160+
}
129161
else {
130162
itemProvider.loadItem(forTypeIdentifier: "public.data", options: nil, completionHandler: { (item, error) in
131163
DispatchQueue.main.async {
@@ -219,6 +251,16 @@ class ShareViewController: UIViewController, UITextFieldDelegate, URLSessionTask
219251
self.progressBar.isHidden = false
220252
self.progressBar.progress = 0
221253

254+
// If we're sharing text and it's been edited, update the file content
255+
if let text = textView.text, !textView.isHidden {
256+
do {
257+
try text.write(to: shareURL!, atomically: true, encoding: .utf8)
258+
} catch {
259+
self.showMessageAndDismiss(message: "Could not update text content.")
260+
return
261+
}
262+
}
263+
222264
let api = DFAPI(url: URL(string: session.url)!, token: session.token)
223265
Task{
224266
let task = await api.uploadFileStreamed(url: shareURL!, taskDelegate: self)

0 commit comments

Comments
 (0)