Skip to content

Commit e4347b1

Browse files
committed
album list, short list, more context menu, zoomable preview
1 parent b5ee780 commit e4347b1

File tree

14 files changed

+789
-161
lines changed

14 files changed

+789
-161
lines changed

Django Files.xcodeproj/project.pbxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,11 @@
7979
4CA2E47D2D6D22CA006EF3F0 /* Exceptions for "Django Files" folder in "UploadAndCopy" target */ = {
8080
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
8181
membershipExceptions = (
82+
API/Albums.swift,
8283
API/DFAPI.swift,
8384
API/Error.swift,
8485
API/Files.swift,
86+
API/Gallery.swift,
8587
API/Short.swift,
8688
API/Stats.swift,
8789
API/Upload.swift,

Django Files/API/Albums.swift

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//
2+
// Albums.swift
3+
// Django Files
4+
//
5+
// Created by Ralph Luaces on 4/29/25.
6+
//
7+
8+
import Foundation
9+
10+
// Album model that matches the JSON payload
11+
struct DFAlbum: Identifiable, Decodable, Hashable {
12+
let id: Int
13+
let user: Int
14+
let name: String
15+
let password: String
16+
let `private`: Bool
17+
let info: String
18+
let view: Int
19+
let maxv: Int
20+
let expr: String
21+
let date: String
22+
let url: String
23+
24+
// Format date for display
25+
func formattedDate() -> String {
26+
let dateFormatter = DateFormatter()
27+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
28+
29+
if let date = dateFormatter.date(from: date) {
30+
let displayFormatter = DateFormatter()
31+
displayFormatter.dateStyle = .medium
32+
displayFormatter.timeStyle = .short
33+
return displayFormatter.string(from: date)
34+
}
35+
36+
return date
37+
}
38+
}
39+
40+
// Response structure for album API call
41+
struct AlbumsResponse: Decodable {
42+
let albums: [DFAlbum]
43+
let next: Int?
44+
let count: Int
45+
}
46+
47+
extension DFAPI {
48+
// Fetch albums with pagination
49+
func getAlbums(page: Int = 1) async -> AlbumsResponse? {
50+
guard var components = URLComponents(string: "\(url)/api/albums/") else {
51+
return nil
52+
}
53+
54+
components.queryItems = [URLQueryItem(name: "page", value: "\(page)")]
55+
56+
guard let requestURL = components.url else {
57+
return nil
58+
}
59+
60+
var request = URLRequest(url: requestURL)
61+
request.httpMethod = "GET"
62+
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
63+
64+
do {
65+
let (data, response) = try await URLSession.shared.data(for: request)
66+
67+
guard let httpResponse = response as? HTTPURLResponse,
68+
(200...299).contains(httpResponse.statusCode) else {
69+
return nil
70+
}
71+
72+
let decoder = JSONDecoder()
73+
let albumsResponse = try decoder.decode(AlbumsResponse.self, from: data)
74+
return albumsResponse
75+
76+
} catch {
77+
print("Error fetching albums: \(error)")
78+
return nil
79+
}
80+
}
81+
}
82+

Django Files/API/DFAPI.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct DFAPI {
2323
case auth_methods = "auth/methods/"
2424
case login = "auth/token/"
2525
case files = "files/"
26+
case shorts = "shorts/"
2627
}
2728

2829
let url: URL
@@ -165,6 +166,28 @@ struct DFAPI {
165166
}
166167
}
167168

169+
public func getShorts(amount: Int = 50, start: Int? = nil) async -> ShortsResponse? {
170+
var parameters: [String: String] = ["amount": "\(amount)"]
171+
if let start = start {
172+
parameters["start"] = "\(start)"
173+
}
174+
175+
do {
176+
let responseBody = try await makeAPIRequest(
177+
path: getAPIPath(.shorts),
178+
parameters: parameters,
179+
method: .get
180+
)
181+
182+
let shorts = try decoder.decode([DFShort].self, from: responseBody)
183+
return ShortsResponse(shorts: shorts)
184+
185+
} catch {
186+
print("Error fetching shorts: \(error)")
187+
return nil
188+
}
189+
}
190+
168191
public func getAuthMethods() async -> DFAuthMethodsResponse? {
169192
do {
170193
let responseBody = try await makeAPIRequest(
@@ -343,10 +366,12 @@ struct DFAPI {
343366
let specialDecoder = JSONDecoder()
344367
specialDecoder.keyDecodingStrategy = .convertFromSnakeCase
345368
return try specialDecoder.decode(DFFilesResponse.self, from: responseBody)
369+
} catch let DecodingError.keyNotFound(key, context) {
370+
print("Missing key: \(key.stringValue) in context: \(context.debugDescription)")
346371
} catch {
347372
print("Request failed \(error)")
348-
return nil
349373
}
374+
return nil
350375
}
351376
}
352377

Django Files/API/Files.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ public struct DFFile: Codable, Hashable, Equatable {
1313
public let size: Int
1414
public let mime: String
1515
public let name: String
16-
public let userName: String
17-
public let userUsername: String
16+
public let userName: String? = ""
17+
public let userUsername: String? = ""
1818
public let info: String
1919
public let expr: String
2020
public let view: Int

Django Files/API/Gallery.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//
2+
// Gallery.swift
3+
// Django Files
4+
//
5+
// Created by Ralph Luaces on 4/29/25.
6+
//
7+
8+
import Foundation

Django Files/API/Short.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,30 @@ struct DFShortResponse: Codable{
3939
url = try container.decode(String.self, forKey: .url)
4040
}
4141
}
42+
43+
struct DFShort: Identifiable, Codable, Hashable {
44+
let id: Int
45+
let short: String
46+
let url: String
47+
let max: Int
48+
let views: Int
49+
let user: Int
50+
let fullUrl: String
51+
52+
enum CodingKeys: String, CodingKey {
53+
case id, short, url, max, views, user, fullUrl
54+
}
55+
}
56+
57+
// Response structure for shorts API call
58+
struct ShortsResponse: Codable {
59+
let shorts: [DFShort]
60+
61+
init(shorts: [DFShort]) {
62+
self.shorts = shorts
63+
}
64+
65+
enum CodingKeys: String, CodingKey {
66+
case shorts
67+
}
68+
}

0 commit comments

Comments
 (0)