@@ -250,10 +250,16 @@ final class RepoViewModel: ObservableObject {
250250 throw NSError ( domain: " RepoFetcher " , code: http. statusCode, userInfo: [ NSLocalizedDescriptionKey: " HTTP \( http. statusCode) " ] )
251251 }
252252 let decoder = JSONDecoder ( )
253+
254+ // Case 1: AltSource with apps property
253255 if let source = try ? decoder. decode ( AltSource . self, from: data) , let rawApps = source. apps {
254256 let repoName = source. META? . repoName ?? source. name
255257 let mapped = rawApps. map { raw -> AltApp in
256- AltApp (
258+ // prefer download URL from versions (first non-nil), else fallback to top-level downloadURL
259+ let preferredDownloadString = raw. versions? . compactMap { $0. downloadURL } . first ?? raw. downloadURL
260+ let preferredDownloadURL = preferredDownloadString. flatMap { URL ( string: $0) }
261+
262+ return AltApp (
257263 name: raw. name,
258264 bundleIdentifier: raw. bundleIdentifier,
259265 developerName: raw. developerName,
@@ -265,16 +271,21 @@ final class RepoViewModel: ObservableObject {
265271 size: raw. size,
266272 versionDate: raw. versionDate,
267273 fullDate: raw. fullDate,
268- downloadURL: raw . downloadURL . flatMap { URL ( string : $0 ) } ,
274+ downloadURL: preferredDownloadURL ,
269275 repositoryName: repoName
270276 )
271277 }
272278 combinedApps. append ( contentsOf: mapped)
273279 continue
274280 }
281+
282+ // Case 2: top-level array of AppRaw
275283 if let rawArray = try ? decoder. decode ( [ AppRaw ] . self, from: data) {
276284 let mapped = rawArray. map { raw -> AltApp in
277- AltApp (
285+ let preferredDownloadString = raw. versions? . compactMap { $0. downloadURL } . first ?? raw. downloadURL
286+ let preferredDownloadURL = preferredDownloadString. flatMap { URL ( string: $0) }
287+
288+ return AltApp (
278289 name: raw. name,
279290 bundleIdentifier: raw. bundleIdentifier,
280291 developerName: raw. developerName,
@@ -286,19 +297,24 @@ final class RepoViewModel: ObservableObject {
286297 size: raw. size,
287298 versionDate: raw. versionDate,
288299 fullDate: raw. fullDate,
289- downloadURL: raw . downloadURL . flatMap { URL ( string : $0 ) } ,
300+ downloadURL: preferredDownloadURL ,
290301 repositoryName: nil
291302 )
292303 }
293304 combinedApps. append ( contentsOf: mapped)
294305 continue
295306 }
307+
308+ // Case 3: JSON object with "apps" fragment
296309 if let jsonObject = try JSONSerialization . jsonObject ( with: data) as? [ String : Any ] ,
297310 let appsFragment = jsonObject [ " apps " ] {
298311 let fragmentData = try JSONSerialization . data ( withJSONObject: appsFragment)
299312 let rawArray = try decoder. decode ( [ AppRaw ] . self, from: fragmentData)
300313 let mapped = rawArray. map { raw -> AltApp in
301- AltApp (
314+ let preferredDownloadString = raw. versions? . compactMap { $0. downloadURL } . first ?? raw. downloadURL
315+ let preferredDownloadURL = preferredDownloadString. flatMap { URL ( string: $0) }
316+
317+ return AltApp (
302318 name: raw. name,
303319 bundleIdentifier: raw. bundleIdentifier,
304320 developerName: raw. developerName,
@@ -310,18 +326,20 @@ final class RepoViewModel: ObservableObject {
310326 size: raw. size,
311327 versionDate: raw. versionDate,
312328 fullDate: raw. fullDate,
313- downloadURL: raw . downloadURL . flatMap { URL ( string : $0 ) } ,
329+ downloadURL: preferredDownloadURL ,
314330 repositoryName: nil
315331 )
316332 }
317333 combinedApps. append ( contentsOf: mapped)
318334 continue
319335 }
336+
320337 throw NSError ( domain: " RepoFetcher " , code: - 1 , userInfo: [ NSLocalizedDescriptionKey: " Unexpected JSON format. " ] )
321338 } catch {
322339 errors. append ( " Failed \( url) : \( error. localizedDescription) " )
323340 }
324341 }
342+
325343 // dedupe by bundleIdentifier (keep first occurrence)
326344 var seen : Set < String > = [ ]
327345 let deduped = combinedApps. filter { app in
0 commit comments