Skip to content

Commit 3887f47

Browse files
committed
file preview detail support, attempt fixing info plist
1 parent 128d0b7 commit 3887f47

File tree

3 files changed

+274
-42
lines changed

3 files changed

+274
-42
lines changed

Django Files/API/Files.swift

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,73 @@ public struct DFFile: Codable, Hashable, Equatable {
2727
public let raw: String
2828
public let date: String
2929
public let albums: [Int]
30+
public let exif: [String: AnyCodable]?
31+
public let meta: [String: AnyCodable]?
3032

3133
// Skip nested JSON structures
3234
enum CodingKeys: String, CodingKey {
33-
case id, user, size, mime, name, info, expr, view, maxv, password, `private`, avatar, userName, userUsername, url, thumb, raw, date, albums
35+
case id, user, size, mime, name, info, expr, view, maxv, password, `private`, avatar, userName, userUsername, url, thumb, raw, date, albums, exif, meta
36+
}
37+
38+
public init(from decoder: Decoder) throws {
39+
let container = try decoder.container(keyedBy: CodingKeys.self)
40+
id = try container.decode(Int.self, forKey: .id)
41+
user = try container.decode(Int.self, forKey: .user)
42+
size = try container.decode(Int.self, forKey: .size)
43+
mime = try container.decode(String.self, forKey: .mime)
44+
name = try container.decode(String.self, forKey: .name)
45+
userName = try container.decode(String.self, forKey: .userName)
46+
userUsername = try container.decode(String.self, forKey: .userUsername)
47+
info = try container.decode(String.self, forKey: .info)
48+
expr = try container.decode(String.self, forKey: .expr)
49+
view = try container.decode(Int.self, forKey: .view)
50+
maxv = try container.decode(Int.self, forKey: .maxv)
51+
password = try container.decode(String.self, forKey: .password)
52+
`private` = try container.decode(Bool.self, forKey: .private)
53+
avatar = try container.decode(Bool.self, forKey: .avatar)
54+
url = try container.decode(String.self, forKey: .url)
55+
thumb = try container.decode(String.self, forKey: .thumb)
56+
raw = try container.decode(String.self, forKey: .raw)
57+
date = try container.decode(String.self, forKey: .date)
58+
albums = try container.decode([Int].self, forKey: .albums)
59+
60+
// Decode exif and meta as dynamic JSON objects
61+
if let exifContainer = try? container.decode([String: AnyCodable].self, forKey: .exif) {
62+
exif = exifContainer
63+
} else {
64+
exif = nil
65+
}
66+
67+
if let metaContainer = try? container.decode([String: AnyCodable].self, forKey: .meta) {
68+
meta = metaContainer
69+
} else {
70+
meta = nil
71+
}
72+
}
73+
74+
public func encode(to encoder: Encoder) throws {
75+
var container = encoder.container(keyedBy: CodingKeys.self)
76+
try container.encode(id, forKey: .id)
77+
try container.encode(user, forKey: .user)
78+
try container.encode(size, forKey: .size)
79+
try container.encode(mime, forKey: .mime)
80+
try container.encode(name, forKey: .name)
81+
try container.encode(userName, forKey: .userName)
82+
try container.encode(userUsername, forKey: .userUsername)
83+
try container.encode(info, forKey: .info)
84+
try container.encode(expr, forKey: .expr)
85+
try container.encode(view, forKey: .view)
86+
try container.encode(maxv, forKey: .maxv)
87+
try container.encode(password, forKey: .password)
88+
try container.encode(`private`, forKey: .private)
89+
try container.encode(avatar, forKey: .avatar)
90+
try container.encode(url, forKey: .url)
91+
try container.encode(thumb, forKey: .thumb)
92+
try container.encode(raw, forKey: .raw)
93+
try container.encode(date, forKey: .date)
94+
try container.encode(albums, forKey: .albums)
95+
try container.encode(exif, forKey: .exif)
96+
try container.encode(meta, forKey: .meta)
3497
}
3598

3699
// Helper property to get a Date object when needed
@@ -78,6 +141,72 @@ public struct DFFile: Codable, Hashable, Equatable {
78141
}
79142
}
80143

144+
// Helper type to handle dynamic JSON values
145+
public struct AnyCodable: Codable {
146+
private let storage: Any
147+
148+
public init(_ value: Any) {
149+
self.storage = value
150+
}
151+
152+
public init(from decoder: Decoder) throws {
153+
let container = try decoder.singleValueContainer()
154+
155+
if container.decodeNil() {
156+
self.storage = NSNull()
157+
} else if let bool = try? container.decode(Bool.self) {
158+
self.storage = bool
159+
} else if let int = try? container.decode(Int.self) {
160+
self.storage = int
161+
} else if let double = try? container.decode(Double.self) {
162+
self.storage = double
163+
} else if let string = try? container.decode(String.self) {
164+
self.storage = string
165+
} else if let array = try? container.decode([AnyCodable].self) {
166+
self.storage = array.map { $0.value }
167+
} else if let dictionary = try? container.decode([String: AnyCodable].self) {
168+
self.storage = dictionary.mapValues { $0.value }
169+
} else {
170+
throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyCodable value cannot be decoded")
171+
}
172+
}
173+
174+
public func encode(to encoder: Encoder) throws {
175+
var container = encoder.singleValueContainer()
176+
177+
switch storage {
178+
case is NSNull:
179+
try container.encodeNil()
180+
case let bool as Bool:
181+
try container.encode(bool)
182+
case let int as Int:
183+
try container.encode(int)
184+
case let double as Double:
185+
try container.encode(double)
186+
case let string as String:
187+
try container.encode(string)
188+
case let array as [Any]:
189+
try container.encode(array.map { AnyCodable($0) })
190+
case let dict as [String: Any]:
191+
try container.encode(dict.mapValues { AnyCodable($0) })
192+
default:
193+
let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "AnyCodable value cannot be encoded")
194+
throw EncodingError.invalidValue(storage, context)
195+
}
196+
}
197+
198+
public var value: Any {
199+
switch storage {
200+
case let array as [AnyCodable]:
201+
return array.map { $0.value }
202+
case let dict as [String: AnyCodable]:
203+
return dict.mapValues { $0.value }
204+
default:
205+
return storage
206+
}
207+
}
208+
}
209+
81210
public struct DFFilesResponse: Codable {
82211
public let files: [DFFile]
83212
public let next: Int?
@@ -110,6 +239,26 @@ extension DFAPI {
110239
return nil
111240
}
112241

242+
public func getFileDetails(fileID: Int, selectedServer: DjangoFilesSession? = nil) async -> DFFile? {
243+
do {
244+
let responseBody = try await makeAPIRequest(
245+
body: Data(),
246+
path: getAPIPath(.file) + "\(fileID)",
247+
parameters: [:],
248+
method: .get,
249+
selectedServer: selectedServer
250+
)
251+
let specialDecoder = JSONDecoder()
252+
specialDecoder.keyDecodingStrategy = .convertFromSnakeCase
253+
return try specialDecoder.decode(DFFile.self, from: responseBody)
254+
} catch let DecodingError.keyNotFound(key, context) {
255+
print("Missing key: \(key.stringValue) in context: \(context.debugDescription)")
256+
} catch {
257+
print("Request failed \(error)")
258+
}
259+
return nil
260+
}
261+
113262
public func deleteFiles(fileIDs: [Int], selectedServer: DjangoFilesSession? = nil) async {
114263
do {
115264
let fileIDsData = try JSONSerialization.data(withJSONObject: ["ids": fileIDs])

Django Files/Info.plist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,11 @@
2929
<key>UIImageName</key>
3030
<string>LaunchScreenBackgroundImage</string>
3131
</dict>
32+
<key>UIRequiredDeviceCapabilities</key>
33+
<array>
34+
<string>arm64</string>
35+
<string>microphone</string>
36+
<string>camera</string>
37+
</array>
3238
</dict>
3339
</plist>

0 commit comments

Comments
 (0)