Skip to content

Commit

Permalink
Merge pull request #1764 from wallisch/CATTY-688
Browse files Browse the repository at this point in the history
CATTY-688 Adapt media library to updated API
  • Loading branch information
wallisch authored Nov 25, 2022
2 parents ef26011 + 9073068 commit 757c7c5
Show file tree
Hide file tree
Showing 17 changed files with 711 additions and 699 deletions.
40 changes: 20 additions & 20 deletions src/Catty.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions src/Catty/Defines/NetworkDefines.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,13 @@ class NetworkDefines: NSObject {

static let tagLanguage = "language"

// MARK: MediaLibrary

static var mediaLibraryBackgroundsIndex: String { baseUrl.appending("/api/media/package/Backgrounds/json") }
static var mediaLibraryLooksIndex: String { baseUrl.appending("/api/media/package/Looks/json") }
static var mediaLibrarySoundsIndex: String { baseUrl.appending("/api/media/package/Sounds/json") }
static var mediaLibraryDownloadBaseUrl: String { baseUrl.replacingOccurrences(of: "/pocketcode/", with: "") }

// MARK: API

static var apiEndpointMediaPackage = apiBaseUrl.appending("media/package")
static var apiEndpointMediaPackageBackgrounds = apiEndpointMediaPackage.appending("/Backgrounds")
static var apiEndpointMediaPackageLooks = apiEndpointMediaPackage.appending("/Looks")
static var apiEndpointMediaPackageSounds = apiEndpointMediaPackage.appending("/Sounds")

static var apiEndpointProject = apiBaseUrl.appending("project")
static var apiEndpointProjects = apiBaseUrl.appending("projects")
static var apiEndpointProjectsFeatured = apiEndpointProjects.appending("/featured")
Expand All @@ -98,6 +96,8 @@ class NetworkDefines: NSObject {

static let searchLookupDelayInSeconds = 0.3

static let mediaPackageMaxItems = 10000

static let currentPlatform = "ios"

@objc static let reportProjectNoteMaxLength = 100
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ extension LooksTableViewController {
extension LooksTableViewController: MediaLibraryViewControllerImportDelegate {
func mediaLibraryViewController(_ mediaLibraryViewController: MediaLibraryViewController, didPickItemsForImport items: [MediaItem]) {
for item in items {
guard let data = item.cachedData else { self.showImportAlert(itemName: item.name); continue }
guard let itemName = item.name else { continue }
guard let data = item.cachedData else { self.showImportAlert(itemName: itemName); continue }

if let image = UIImage(data: data) {
self.addMediaLibraryLoadedImage(image, withName: item.name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,19 @@ extension SoundsTableViewController: MediaLibraryViewControllerImportDelegate {
let documents = URL(fileURLWithPath:
CBFileManager.shared().documentsDirectory)
for item in items {
guard let data = item.cachedData else { self.showImportAlert(itemName: item.name); continue }
guard let itemName = item.name, let itemFileExtension = item.fileExtension else { continue }
guard let data = item.cachedData else { self.showImportAlert(itemName: itemName); continue }

let fileName = UUID().uuidString
let fileURL = documents
.appendingPathComponent(fileName)
.appendingPathExtension(item.fileExtension)
let sound = Sound(name: item.name, fileName: fileURL.lastPathComponent)
.appendingPathExtension(itemFileExtension)
let sound = Sound(name: itemName, fileName: fileURL.lastPathComponent)
do {
try data.write(to: fileURL, options: .atomic)
self.showDownloadSoundAlert(sound)
} catch {
self.showImportAlert(itemName: item.name)
self.showImportAlert(itemName: itemName)
}
}
}
Expand Down
63 changes: 51 additions & 12 deletions src/Catty/ViewController/MediaLibrary/MediaItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,64 @@
*/

struct MediaItem: Codable {
let name: String
let fileExtension: String
let category: String
let relativePath: String
let id: Int
let name: String?
let flavours: [String]?
let packages: [String]?
let category: String?
let author: String?
let fileExtension: String?
let downloadURLString: String?
let size: Int?
let fileType: String?

/// Since the API doesn't offer previews of items it would
/// be a waste to not keep the already downloaded data
/// in case the user decides to import the item.
var cachedData: Data?

private enum CodingKeys: String, CodingKey {
case name
case id = "id"
case name = "name"
case flavours = "flavours"
case packages = "packages"
case category = "category"
case author = "author"
case fileExtension = "extension"
case category
case relativePath = "download_url"
case downloadURLString = "download_url"
case size = "size"
case fileType = "file_type"
}

static var defaultQueryParameters: [String] {
[CodingKeys.id.rawValue,
CodingKeys.name.rawValue,
CodingKeys.category.rawValue,
CodingKeys.fileExtension.rawValue,
CodingKeys.downloadURLString.rawValue]
}

init(id: Int, name: String? = nil, flavours: [String]? = nil, packages: [String]? = nil,
category: String? = nil, author: String? = nil, fileExtension: String? = nil,
downloadURLString: String? = nil, size: Int? = nil, fileType: String? = nil, cachedData: Data? = nil) {
self.id = id
self.name = name
self.flavours = flavours
self.packages = packages
self.category = category
self.author = author
self.fileExtension = fileExtension
self.downloadURLString = downloadURLString
self.size = size
self.fileType = fileType
self.cachedData = cachedData
}
}

extension MediaItem {
var downloadURL: URL {
guard let baseURL = URL(string: NetworkDefines.mediaLibraryDownloadBaseUrl) else { fatalError("Media Library base URL constant misconfiguration") }
return baseURL.appendingPathComponent(self.relativePath)
var downloadURL: URL? {
guard let downloadPath = self.downloadURLString else { return nil }
return URL(string: downloadPath)
}
}

Expand All @@ -67,13 +103,16 @@ extension Sequence where Iterator.Element == MediaItem {
}

for item in self {
if let categoryIndex = categories[item.category] {
guard let itemCategory = item.category else {
continue
}
if let categoryIndex = categories[itemCategory] {
// category exists, add the item to the list
groupedItems[categoryIndex].append(item)
} else {
// add the category with a list containing the current item
let categoryIndex = categories.count
categories[item.category] = categoryIndex
categories[itemCategory] = categoryIndex
groupedItems.append([item])
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,12 @@ final class ImagesLibraryCollectionViewDataSource: MediaLibraryCollectionViewDat
// MARK: - Helper Methods

private func fetchData(for item: MediaItem, completion: @escaping (Data?) -> Void) {
guard let downloadURL = item.downloadURL else {
completion(nil)
return
}
// try to get the image from cache
let resource = ImageResource(downloadURL: item.downloadURL)
let resource = ImageResource(downloadURL: downloadURL)
let options: KingfisherOptionsInfo = [.onlyFromCache]
if ImageCache.default.imageCachedType(forKey: resource.cacheKey).cached {
ImageCache.default.retrieveImage(forKey: resource.cacheKey, options: options) { result in
Expand Down
30 changes: 23 additions & 7 deletions src/Catty/ViewController/MediaLibrary/MediaLibraryDownloader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,37 @@ final class MediaLibraryDownloader: MediaLibraryDownloaderProtocol {
}

func downloadIndex(for mediaType: MediaType, completion: @escaping ([[MediaItem]]?, MediaLibraryDownloadError?) -> Void) {
self.session.dataTask(with: URLRequest(url: mediaType.indexURL)) { data, response, error in
var indexURLComponents = URLComponents(string: mediaType.indexURLString)
indexURLComponents?.queryItems = [
URLQueryItem(name: NetworkDefines.apiParameterLimit, value: String(NetworkDefines.mediaPackageMaxItems)),
URLQueryItem(name: NetworkDefines.apiParameterOffset, value: String(0)),
URLQueryItem(name: NetworkDefines.apiParameterAttributes, value: MediaItem.defaultQueryParameters.joined(separator: ","))
]

guard let indexURL = indexURLComponents?.url else {
completion(nil, .unexpectedError)
return
}

self.session.dataTask(with: URLRequest(url: indexURL)) { data, response, error in

let handleDataTaskCompletion: (Data?, URLResponse?, Error?) -> (items: [[MediaItem]]?, error: MediaLibraryDownloadError?)
handleDataTaskCompletion = { data, response, error in
guard let response = response as? HTTPURLResponse else {
let errorInfo = MediaLibraryDownloadFailureInfo(url: mediaType.indexURL.absoluteString, description: error?.localizedDescription ?? "")
let errorInfo = MediaLibraryDownloadFailureInfo(url: indexURL.absoluteString, description: error?.localizedDescription ?? "")
NotificationCenter.default.post(name: .mediaLibraryDownloadIndexFailure, object: errorInfo)
return (nil, .unexpectedError)
}
guard let data = data, response.statusCode == 200, error == nil else {
let errorInfo = MediaLibraryDownloadFailureInfo(url: mediaType.indexURL.absoluteString, statusCode: response.statusCode, description: error?.localizedDescription ?? "")
let errorInfo = MediaLibraryDownloadFailureInfo(url: indexURL.absoluteString, statusCode: response.statusCode, description: error?.localizedDescription ?? "")
NotificationCenter.default.post(name: .mediaLibraryDownloadIndexFailure, object: errorInfo)
return (nil, .request(error: error, statusCode: response.statusCode))
}
let items: [[MediaItem]]?
do {
items = try JSONDecoder().decode([MediaItem].self, from: data).groupedByCategories
} catch {
let errorInfo = MediaLibraryDownloadFailureInfo(url: mediaType.indexURL.absoluteString, statusCode: response.statusCode, description: error.localizedDescription)
let errorInfo = MediaLibraryDownloadFailureInfo(url: indexURL.absoluteString, statusCode: response.statusCode, description: error.localizedDescription)
NotificationCenter.default.post(name: .mediaLibraryDownloadIndexFailure, object: errorInfo)
return (nil, .parse(error: error))
}
Expand All @@ -67,17 +79,21 @@ final class MediaLibraryDownloader: MediaLibraryDownloaderProtocol {
}

func downloadData(for mediaItem: MediaItem, completion: @escaping (Data?, MediaLibraryDownloadError?) -> Void) {
self.session.dataTask(with: URLRequest(url: mediaItem.downloadURL)) { data, response, error in
guard let downloadURL = mediaItem.downloadURL else {
completion(nil, .unexpectedError)
return
}
self.session.dataTask(with: URLRequest(url: downloadURL)) { data, response, error in
DispatchQueue.main.async {
guard let response = response as? HTTPURLResponse else {
completion(nil, .unexpectedError)
let errorInfo = MediaLibraryDownloadFailureInfo(url: mediaItem.downloadURL.absoluteString, description: error?.localizedDescription ?? "")
let errorInfo = MediaLibraryDownloadFailureInfo(url: downloadURL.absoluteString, description: error?.localizedDescription ?? "")
NotificationCenter.default.post(name: .mediaLibraryDownloadDataFailure, object: errorInfo)
return
}
guard let data = data, response.statusCode == 200, error == nil else {
completion(nil, .request(error: error, statusCode: response.statusCode))
let errorInfo = MediaLibraryDownloadFailureInfo(url: mediaItem.downloadURL.absoluteString, statusCode: response.statusCode, description: error?.localizedDescription ?? "")
let errorInfo = MediaLibraryDownloadFailureInfo(url: downloadURL.absoluteString, statusCode: response.statusCode, description: error?.localizedDescription ?? "")
NotificationCenter.default.post(name: .mediaLibraryDownloadDataFailure, object: errorInfo)
return
}
Expand Down
11 changes: 4 additions & 7 deletions src/Catty/ViewController/MediaLibrary/MediaType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,14 @@ enum MediaType: String {
}

extension MediaType {
var indexURL: URL {
var indexURLString: String {
switch self {
case .backgrounds:
guard let indexURL = URL(string: NetworkDefines.mediaLibraryBackgroundsIndex) else { fatalError("Media Library backgrounds URL constant misconfiguration") }
return indexURL
return NetworkDefines.apiEndpointMediaPackageBackgrounds
case .looks:
guard let indexURL = URL(string: NetworkDefines.mediaLibraryLooksIndex) else { fatalError("Media Library looks URL constant misconfiguration") }
return indexURL
return NetworkDefines.apiEndpointMediaPackageLooks
case .sounds:
guard let indexURL = URL(string: NetworkDefines.mediaLibrarySoundsIndex) else { fatalError("Media Library sounds URL constant misconfiguration") }
return indexURL
return NetworkDefines.apiEndpointMediaPackageSounds
}
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
{
"interactions" : [
{
"recorded_at" : 1666094788.6289361,
"request" : {
"url" : "https:\/\/web-test.catrob.at\/app\/download-media\/99999",
"method" : "GET"
},
"response" : {
"status" : 404,
"url" : "https:\/\/web-test.catrob.at\/app\/download-media\/99999",
"body" : "",
"headers" : {
"Content-Type" : "application\/json",
"Set-Cookie" : "PHPSESSID=rkidg0r1et92gc232gquhvbaj1; path=\/",
"Expires" : "-1",
"Pragma" : "no-cache",
"Server" : "nginx",
"Date" : "Fri, 09 Feb 2018 10:17:32 GMT",
"Cache-Control" : "private, must-revalidate"
},
"body" : {
"error" : {
"message" : "Not Found",
"code" : 404
}
"Strict-Transport-Security" : "max-age=0; includeSubDomains; preload",
"Set-Cookie" : "PHPSESSID=029c8aln5t0edi6bh8rkjqlmbl; path=\/; secure; httponly; samesite=lax, dtCookie=v_4_srv_15_sn_91C2B0F60E5639C1760B4F92A01E88B9_perc_100000_ol_0_mul_1_app-3A95f731861a1a1696_1; Path=\/; Domain=.catrob.at",
"Date" : "Tue, 18 Oct 2022 12:06:28 GMT",
"report-to" : "{\"endpoints\":[{\"url\":\"https:\\\/\\\/a.nel.cloudflare.com\\\/report\\\/v3?s=enfzYus2JmV%2FsdRXpQtpc9N1%2B5jghpW%2FzMbMHfYr6%2BpoBdxFMe%2FGeblOBHI2%2F5SsUKb6uW%2F0qpjyPesYHBwLQfuBT%2FrKfsRw3NNLx3UgFlfovwRJmkXd2EKQiaABbenQSGNPOYqWeSzHFtdrk2w%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}",
"Accept-Ranges" : "bytes",
"Cache-Control" : "max-age=0, must-revalidate, private",
"Etag" : "\"1597349444:dtagent10251220909040818Ngr9\"",
"cf-ray" : "75c125ec9f7acb9c-VIE",
"Content-Length" : "0",
"Last-Modified" : "Thu, 13 Aug 2020 20:10:43 GMT",
"Server" : "cloudflare",
"cf-cache-status" : "DYNAMIC",
"Expires" : "Tue, 18 Oct 2022 12:06:28 GMT",
"server-timing" : "dtSInfo;desc=\"0\", dtRpid;desc=\"874054250\"",
"nel" : "{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}"
},
"url" : "https:\/\/web-test.catrob.at\/pocketcode\/download-media\/99999"
},
"recorded_at" : 1518171451.8201509,
"request" : {
"method" : "GET",
"url" : "https:\/\/web-test.catrob.at\/pocketcode\/download-media\/99999"
"status" : 404
}
}
],
Expand Down
Loading

0 comments on commit 757c7c5

Please sign in to comment.