From 53a7efc610a353057725293acf875b186ca78c14 Mon Sep 17 00:00:00 2001 From: Maurice Carrier Date: Thu, 11 Jan 2024 23:02:06 -0500 Subject: [PATCH 1/4] Update user agent to be more detailed --- Palace.xcodeproj/project.pbxproj | 6 +++ .../Library/Account+profileDocument.swift | 3 +- .../Tracker/AudiobookDataManager.swift | 2 + Palace/Book/Models/TPPBookCoverRegistry.swift | 12 +++--- Palace/Logging/TPPCirculationAnalytics.swift | 2 +- Palace/MyBooks/MyBooksDownloadCenter.swift | 10 ++--- .../Network/BundledHTMLViewController.swift | 2 +- Palace/Network/RemoteHTMLViewController.swift | 4 +- Palace/Network/TPPNetworkExecutor.swift | 1 + Palace/Network/TPPNetworkQueue.swift | 1 + .../Notifications/NotificationService.swift | 6 +-- .../LCP/LicensesService.swift | 2 +- .../SignInLogic/TPPSignInBusinessLogic.swift | 2 +- Palace/SignInLogic/TokenRequest.swift | 2 +- .../Networking/URLRequest+Extensions.swift | 43 +++++++++++++++++++ ios-audiobook-overdrive | 2 +- ios-audiobooktoolkit | 2 +- 17 files changed, 79 insertions(+), 23 deletions(-) create mode 100644 Palace/Utilities/Networking/URLRequest+Extensions.swift diff --git a/Palace.xcodeproj/project.pbxproj b/Palace.xcodeproj/project.pbxproj index 89c90acc6..7866e4b71 100644 --- a/Palace.xcodeproj/project.pbxproj +++ b/Palace.xcodeproj/project.pbxproj @@ -630,6 +630,8 @@ E5180ABA29A91D42002A18F8 /* AdaptableGridLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5180AB929A91D42002A18F8 /* AdaptableGridLayout.swift */; }; E5180ABB29A91D42002A18F8 /* AdaptableGridLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5180AB929A91D42002A18F8 /* AdaptableGridLayout.swift */; }; E51818442927FD8E00C03AD5 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E54DD4CF275C66F30013C200 /* Strings.swift */; }; + E51919D82B508EE400C08E86 /* URLRequest+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51919D72B508EE400C08E86 /* URLRequest+Extensions.swift */; }; + E51919D92B50902000C08E86 /* URLRequest+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51919D72B508EE400C08E86 /* URLRequest+Extensions.swift */; }; E51EB51529D5F46400022D24 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E57E798329D4D407006D0F87 /* String+Extensions.swift */; }; E523124B285C3828007D1DB5 /* TPPBookRegistry+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E523124A285C3828007D1DB5 /* TPPBookRegistry+Extensions.swift */; }; E523124D28641505007D1DB5 /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E523124C28641505007D1DB5 /* LoadingViewController.swift */; }; @@ -1555,6 +1557,7 @@ E5024A8E2A0EB9D6006BF653 /* AudiobookBookmarkBusinessLogicTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudiobookBookmarkBusinessLogicTests.swift; sourceTree = ""; }; E5037FE629A3FF83002DA132 /* ButtonStateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ButtonStateTests.swift; sourceTree = ""; }; E5180AB929A91D42002A18F8 /* AdaptableGridLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptableGridLayout.swift; sourceTree = ""; }; + E51919D72B508EE400C08E86 /* URLRequest+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLRequest+Extensions.swift"; sourceTree = ""; }; E523116928504B85007D1DB5 /* TPPBook+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TPPBook+Extensions.swift"; sourceTree = ""; }; E5231240285C291D007D1DB5 /* AudioBookmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioBookmark.swift; sourceTree = ""; }; E523124A285C3828007D1DB5 /* TPPBookRegistry+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TPPBookRegistry+Extensions.swift"; sourceTree = ""; }; @@ -2457,6 +2460,7 @@ 085D31DE1BE3CD3C007F7672 /* NSURLRequest+NYPLURLRequestAdditions.m */, 7340DA6124B7E45C00361387 /* URLResponse+NYPL.swift */, E7498A7D2A0E4F6A0037DD93 /* URL+Extensions.swift */, + E51919D72B508EE400C08E86 /* URLRequest+Extensions.swift */, ); path = Networking; sourceTree = ""; @@ -4170,6 +4174,7 @@ 217595DE27B680D400BA0FDD /* TPPReaderSettingsVC.swift in Sources */, E7862A252773927900BE8AB8 /* Font+Extensions.swift in Sources */, 73EB0B2125821DF4006BC997 /* TPPLocalization.m in Sources */, + E51919D92B50902000C08E86 /* URLRequest+Extensions.swift in Sources */, 73D8D27D25A68D4300DF5F69 /* TPPReaderTOCBusinessLogic.swift in Sources */, 73EB0B2225821DF4006BC997 /* TPPSecrets.swift in Sources */, E50D684426AB235400F1042B /* TPPReaderTOCCell.swift in Sources */, @@ -4531,6 +4536,7 @@ E73549DE28A53982001B0D0A /* TPPPDFPageBookmark.swift in Sources */, E53573DC2965E606008BDCA4 /* TPPMyBooksViewController.swift in Sources */, 73B501C524F48D4C00FBAD7D /* TPPUserAccountFrontEndValidation.swift in Sources */, + E51919D82B508EE400C08E86 /* URLRequest+Extensions.swift in Sources */, E501710F27A3948C004B3392 /* TPPBookmarkFactory.swift in Sources */, E5180ABA29A91D42002A18F8 /* AdaptableGridLayout.swift in Sources */, ); diff --git a/Palace/Accounts/Library/Account+profileDocument.swift b/Palace/Accounts/Library/Account+profileDocument.swift index 125485ec6..2c5fe210e 100644 --- a/Palace/Accounts/Library/Account+profileDocument.swift +++ b/Palace/Accounts/Library/Account+profileDocument.swift @@ -19,7 +19,8 @@ extension Account { return } - TPPNetworkExecutor.shared.executeRequest(URLRequest(url: profileUrl), useTokenIfAvailable: false) { result in + var request = URLRequest(url: profileUrl) + TPPNetworkExecutor.shared.executeRequest(request.applyCustomUserAgent(), useTokenIfAvailable: false) { result in switch result { case .success(let data, _): do { diff --git a/Palace/Audiobooks/Tracker/AudiobookDataManager.swift b/Palace/Audiobooks/Tracker/AudiobookDataManager.swift index e77f96b25..d5f40fce4 100644 --- a/Palace/Audiobooks/Tracker/AudiobookDataManager.swift +++ b/Palace/Audiobooks/Tracker/AudiobookDataManager.swift @@ -164,6 +164,8 @@ class AudiobookDataManager { request.httpMethod = "POST" request.httpBody = requestBody request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.applyCustomUserAgent() + TPPNetworkExecutor.shared.POST(request, useTokenIfAvailable: true) { result, response, error in if let response = response as? HTTPURLResponse, !response.isSuccess() { TPPErrorLogger.logError(error, summary: "Error uploading audiobook tracker data", metadata: [ diff --git a/Palace/Book/Models/TPPBookCoverRegistry.swift b/Palace/Book/Models/TPPBookCoverRegistry.swift index 36c817555..537d27aa7 100644 --- a/Palace/Book/Models/TPPBookCoverRegistry.swift +++ b/Palace/Book/Models/TPPBookCoverRegistry.swift @@ -46,7 +46,8 @@ class TPPBookCoverRegistry { guard let imageUrl = book.imageURL else { return } - urlSession.dataTask(with: URLRequest(url: imageUrl)) { imageData, response, error in + var request = URLRequest(url: imageUrl) + urlSession.dataTask(with: request.applyCustomUserAgent()) { imageData, response, error in if let imageData = imageData, let image = UIImage(data: imageData) { DispatchQueue.main.async { handler(image) @@ -74,7 +75,8 @@ class TPPBookCoverRegistry { result[book.identifier] = self.generateBookCoverImage(book) return } - urlSession.dataTask(with: URLRequest(url: thumbnailUrl)) { imageData, response, error in + + urlSession.dataTask(with: URLRequest(url: thumbnailUrl, applyingCustomUserAgent: true)) { imageData, response, error in if let imageData = imageData, let image = UIImage(data: imageData) { DispatchQueue.main.async { result[book.identifier] = image @@ -93,7 +95,7 @@ class TPPBookCoverRegistry { /// - Returns: cover image, if one is available. func cachedThumbnailImageForBook(_ book: TPPBook) -> UIImage? { guard let thumbnailUrl = book.imageThumbnailURL, - let cachedData = urlSession.configuration.urlCache?.cachedResponse(for: URLRequest(url: thumbnailUrl))?.data + let cachedData = urlSession.configuration.urlCache?.cachedResponse(for: URLRequest(url: thumbnailUrl, applyingCustomUserAgent: true))?.data else { return nil } @@ -109,7 +111,7 @@ class TPPBookCoverRegistry { return } try? Data().write(to: fileUrl, options: .atomic) - urlSession.dataTask(with: URLRequest(url: thumbnailUrl)) { imageData, response, error in + urlSession.dataTask(with: URLRequest(url: thumbnailUrl, applyingCustomUserAgent: true)) { imageData, response, error in if let imageData = imageData { do { try imageData.write(to: fileUrl, options: .atomic) @@ -194,7 +196,7 @@ class TPPBookCoverRegistry { /// - handler: completion handler. /// - book: `TPPBook` object. private func getBookCoverImage(url: URL, fileUrl: URL?, handler: @escaping (_ image: UIImage?) -> (), forBook book: TPPBook) { - urlSession.dataTask(with: URLRequest(url: url)) { imageData, response, error in + urlSession.dataTask(with: URLRequest(url: url, applyingCustomUserAgent: true)) { imageData, response, error in if let imageData = imageData, let image = UIImage(data: imageData) { DispatchQueue.main.async { handler(image) diff --git a/Palace/Logging/TPPCirculationAnalytics.swift b/Palace/Logging/TPPCirculationAnalytics.swift index 67406b5e6..3734e7810 100644 --- a/Palace/Logging/TPPCirculationAnalytics.swift +++ b/Palace/Logging/TPPCirculationAnalytics.swift @@ -14,7 +14,7 @@ import Foundation private class func post(_ event: String, withURL url: URL) -> Void { - var request = URLRequest(url: url) + var request = URLRequest(url: url, applyingCustomUserAgent: true) request.httpMethod = "GET" let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in diff --git a/Palace/MyBooks/MyBooksDownloadCenter.swift b/Palace/MyBooks/MyBooksDownloadCenter.swift index 76c0eda41..3e1b80a32 100644 --- a/Palace/MyBooks/MyBooksDownloadCenter.swift +++ b/Palace/MyBooks/MyBooksDownloadCenter.swift @@ -291,7 +291,7 @@ import OverdriveProcessor if let initedRequest = initedRequest { request = initedRequest } else if let url = book.defaultAcquisition?.hrefURL { - request = TPPNetworkExecutor.bearerAuthorized(request: URLRequest(url: url)) + request = TPPNetworkExecutor.bearerAuthorized(request: URLRequest(url: url, applyingCustomUserAgent: true)) } else { logInvalidURLRequest(for: book, withState: state, url: nil, request: nil) return @@ -703,9 +703,8 @@ extension MyBooksDownloadCenter: URLSessionDownloadDelegate { if let data = try? Data(contentsOf: location) { if let dictionary = TPPJSONObjectFromData(data) as? [String: Any], let simplifiedBearerToken = MyBooksSimplifiedBearerToken.simplifiedBearerToken(with: dictionary) { - let mutableRequest = NSMutableURLRequest(url: simplifiedBearerToken.location) + var mutableRequest = URLRequest(url: simplifiedBearerToken.location, applyingCustomUserAgent: true) mutableRequest.setValue("Bearer \(simplifiedBearerToken.accessToken)", forHTTPHeaderField: "Authorization") - let task = session.downloadTask(with: mutableRequest as URLRequest) bookIdentifierToDownloadInfo[book.identifier] = MyBooksDownloadInfo( downloadProgress: 0.0, @@ -827,7 +826,7 @@ extension MyBooksDownloadCenter: URLSessionTaskDelegate { var mutableAllHTTPHeaderFields = request.allHTTPHeaderFields ?? [:] mutableAllHTTPHeaderFields[authorizationKey] = originalAuthorization - var mutableRequest = URLRequest(url: request.url!) + var mutableRequest = URLRequest(url: request.url!, applyingCustomUserAgent: true) mutableRequest.allHTTPHeaderFields = mutableAllHTTPHeaderFields completionHandler(mutableRequest) @@ -855,7 +854,8 @@ extension MyBooksDownloadCenter: URLSessionTaskDelegate { } private func addDownloadTask(with request: URLRequest, book: TPPBook) { - let task = self.session.downloadTask(with: request) + var modifiableRequest = request + let task = self.session.downloadTask(with: modifiableRequest.applyCustomUserAgent()) self.bookIdentifierToDownloadInfo[book.identifier] = MyBooksDownloadInfo(downloadProgress: 0.0, diff --git a/Palace/Network/BundledHTMLViewController.swift b/Palace/Network/BundledHTMLViewController.swift index c7608a70d..83748d373 100644 --- a/Palace/Network/BundledHTMLViewController.swift +++ b/Palace/Network/BundledHTMLViewController.swift @@ -42,7 +42,7 @@ import WebKit } override func viewWillAppear(_ animated: Bool) { - self.webView.load(URLRequest(url: self.fileURL)) + self.webView.load(URLRequest(url: self.fileURL, applyingCustomUserAgent: true)) } fileprivate class WebViewDelegate: NSObject, WKNavigationDelegate diff --git a/Palace/Network/RemoteHTMLViewController.swift b/Palace/Network/RemoteHTMLViewController.swift index f98b8d53f..cd921c3a8 100644 --- a/Palace/Network/RemoteHTMLViewController.swift +++ b/Palace/Network/RemoteHTMLViewController.swift @@ -62,8 +62,8 @@ import WebKit _ = self.navigationController?.popViewController(animated: true) } let action2 = UIAlertAction.init(title: Strings.Generic.reload, style: .destructive) { (reloadAction) in - let urlRequest = URLRequest(url: self.fileURL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) - webView.load(urlRequest) + var urlRequest = URLRequest(url: self.fileURL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) + webView.load(urlRequest.applyCustomUserAgent()) } alert.addAction(action1) diff --git a/Palace/Network/TPPNetworkExecutor.swift b/Palace/Network/TPPNetworkExecutor.swift index 90ab572f9..3e06a356b 100644 --- a/Palace/Network/TPPNetworkExecutor.swift +++ b/Palace/Network/TPPNetworkExecutor.swift @@ -139,6 +139,7 @@ extension TPPNetworkExecutor { var urlRequest = URLRequest(url: url, cachePolicy: urlSession.configuration.requestCachePolicy) + urlRequest.applyCustomUserAgent() if let authToken = TPPUserAccount.sharedAccount().authToken, useTokenIfAvailable { let headers = [ "Authorization" : "Bearer \(authToken)", diff --git a/Palace/Network/TPPNetworkQueue.swift b/Palace/Network/TPPNetworkQueue.swift index f6a3087cc..72f01e751 100644 --- a/Palace/Network/TPPNetworkQueue.swift +++ b/Palace/Network/TPPNetworkQueue.swift @@ -224,6 +224,7 @@ final class NetworkQueue: NSObject { var urlRequest = URLRequest(url: URL(string: requestRow[sqlUrl])!) urlRequest.httpMethod = requestRow[sqlMethod] urlRequest.httpBody = requestRow[sqlParameters] + urlRequest.applyCustomUserAgent() if let headerData = requestRow[sqlHeader], let headers = NSKeyedUnarchiver.unarchiveObject(with: headerData) as? [String:String] { diff --git a/Palace/Notifications/NotificationService.swift b/Palace/Notifications/NotificationService.swift index 5977f5d1f..1967daadb 100644 --- a/Palace/Notifications/NotificationService.swift +++ b/Palace/Notifications/NotificationService.swift @@ -93,7 +93,7 @@ class NotificationService: NSObject, UNUserNotificationCenterDelegate, Messaging else { return } - var request = URLRequest(url: requestUrl) + let request = URLRequest(url: requestUrl, applyingCustomUserAgent: true) _ = TPPNetworkExecutor.shared.addBearerAndExecute(request) { result, response, error in let status = (response as? HTTPURLResponse)?.statusCode // Token exists if status code is 200, doesn't exist if 404. @@ -111,7 +111,7 @@ class NotificationService: NSObject, UNUserNotificationCenterDelegate, Messaging guard let requestBody = TokenData(token: token).data else { return } - var request = URLRequest(url: endpointUrl) + var request = URLRequest(url: endpointUrl, applyingCustomUserAgent: true) request.httpMethod = "PUT" request.httpBody = requestBody _ = TPPNetworkExecutor.shared.addBearerAndExecute(request) { result, response, error in @@ -159,7 +159,7 @@ class NotificationService: NSObject, UNUserNotificationCenterDelegate, Messaging guard let requestBody = TokenData(token: token).data else { return } - var request = URLRequest(url: endpointUrl) + var request = URLRequest(url: endpointUrl, applyingCustomUserAgent: true) request.httpMethod = "DELETE" request.httpBody = requestBody _ = TPPNetworkExecutor.shared.addBearerAndExecute(request) { result, response, error in diff --git a/Palace/Reader2/ReaderStackConfiguration/LCP/LicensesService.swift b/Palace/Reader2/ReaderStackConfiguration/LCP/LicensesService.swift index ce99ee10d..6d4ccf6af 100644 --- a/Palace/Reader2/ReaderStackConfiguration/LCP/LicensesService.swift +++ b/Palace/Reader2/ReaderStackConfiguration/LCP/LicensesService.swift @@ -50,7 +50,7 @@ class TPPLicensesService: NSObject { // Background task identifier is unique to create unique download sessions for each class instance. // Otherwise, single download session calls one delegate class methods, // and only one book's status is updated. - let request = URLRequest(url: url) + let request = URLRequest(url: url, applyingCustomUserAgent: true) let backgroundIdentifier = (Bundle.main.bundleIdentifier ?? "").appending(".lcpBackgroundIdentifier.\(lcpl.hashValue)") let sessionConfiguration = URLSessionConfiguration.background(withIdentifier: backgroundIdentifier) let session = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: .main) diff --git a/Palace/SignInLogic/TPPSignInBusinessLogic.swift b/Palace/SignInLogic/TPPSignInBusinessLogic.swift index 1d8ef589c..ee7325072 100644 --- a/Palace/SignInLogic/TPPSignInBusinessLogic.swift +++ b/Palace/SignInLogic/TPPSignInBusinessLogic.swift @@ -236,7 +236,7 @@ class TPPSignInBusinessLogic: NSObject, TPPSignedInStateProvider, TPPCurrentLibr return nil } - var req = URLRequest(url: url) + var req = URLRequest(url: url, applyingCustomUserAgent: true) if let selectedAuth = selectedAuthentication, (selectedAuth.isOauth || selectedAuth.isSaml) { diff --git a/Palace/SignInLogic/TokenRequest.swift b/Palace/SignInLogic/TokenRequest.swift index c5088bc61..0d1e1ea55 100644 --- a/Palace/SignInLogic/TokenRequest.swift +++ b/Palace/SignInLogic/TokenRequest.swift @@ -38,7 +38,7 @@ import Foundation } func execute() async -> Result { - var request = URLRequest(url: url) + var request = URLRequest(url: url, applyingCustomUserAgent: true) request.httpMethod = HTTPMethodType.POST.rawValue let loginString = "\(username):\(password)" diff --git a/Palace/Utilities/Networking/URLRequest+Extensions.swift b/Palace/Utilities/Networking/URLRequest+Extensions.swift new file mode 100644 index 000000000..693e436a4 --- /dev/null +++ b/Palace/Utilities/Networking/URLRequest+Extensions.swift @@ -0,0 +1,43 @@ +// +// URLRequest+Extensions.swift +// Palace +// +// Created by Maurice Carrier on 1/11/24. +// Copyright © 2024 The Palace Project. All rights reserved. +// + +import Foundation + +extension URLRequest { + init(url: URL, applyingCustomUserAgent: Bool) { + self.init(url: url) + + if applyingCustomUserAgent { + let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String ?? "App" + let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0" + let customUserAgent = "\(appName)/\(appVersion) (iOS; \(UIDevice.current.systemVersion))" + + if let existingUserAgent = self.value(forHTTPHeaderField: "User-Agent") { + self.setValue("\(existingUserAgent) \(customUserAgent)", forHTTPHeaderField: "User-Agent") + } else { + self.setValue(customUserAgent, forHTTPHeaderField: "User-Agent") + } + } + } +} + +extension URLRequest { + @discardableResult mutating func applyCustomUserAgent() -> URLRequest { + let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String ?? "App" + let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0" + let customUserAgent = "\(appName)/\(appVersion) (iOS; \(UIDevice.current.systemVersion))" + + if let existingUserAgent = value(forHTTPHeaderField: "User-Agent") { + setValue("\(existingUserAgent) \(customUserAgent)", forHTTPHeaderField: "User-Agent") + } else { + setValue(customUserAgent, forHTTPHeaderField: "User-Agent") + } + + return self + } +} diff --git a/ios-audiobook-overdrive b/ios-audiobook-overdrive index f188cf53f..9cbc8810e 160000 --- a/ios-audiobook-overdrive +++ b/ios-audiobook-overdrive @@ -1 +1 @@ -Subproject commit f188cf53fb2d8f1f9b8817e3bfe2e8cf55be0a25 +Subproject commit 9cbc8810e0c6a754ad9b72f8dd32ceb718419c16 diff --git a/ios-audiobooktoolkit b/ios-audiobooktoolkit index fc125e668..f542fbba2 160000 --- a/ios-audiobooktoolkit +++ b/ios-audiobooktoolkit @@ -1 +1 @@ -Subproject commit fc125e66864de62621675fc6cfd6de4cf2d29abb +Subproject commit f542fbba2c72bba4c83445ef6b149d3c07a200a1 From 05708c140b46f4ccb43abaee6c2abe6152c88bbd Mon Sep 17 00:00:00 2001 From: Maurice Carrier Date: Thu, 11 Jan 2024 23:02:18 -0500 Subject: [PATCH 2/4] Prevent loading loop on sample downloads --- Palace/Samples/Sample.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Palace/Samples/Sample.swift b/Palace/Samples/Sample.swift index 7cba041c1..1400af889 100644 --- a/Palace/Samples/Sample.swift +++ b/Palace/Samples/Sample.swift @@ -35,7 +35,7 @@ extension Sample { var needsDownload: Bool { type.needsDownload } func fetchSample(completion: @escaping (NYPLResult) -> Void) { - let _ = TPPNetworkExecutor.shared.GET(url) { result in + let _ = TPPNetworkExecutor.shared.GET(url, useTokenIfAvailable: false) { result in completion(result) } } From 145c1d64f787bedffafd6a55515cd9995a64fdea Mon Sep 17 00:00:00 2001 From: Maurice Carrier Date: Thu, 11 Jan 2024 23:02:44 -0500 Subject: [PATCH 3/4] Update sample toolbar posiiton on Ipad --- Palace/Book/UI/TPPBookDetailView.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Palace/Book/UI/TPPBookDetailView.m b/Palace/Book/UI/TPPBookDetailView.m index e81f8029d..db081bcfc 100644 --- a/Palace/Book/UI/TPPBookDetailView.m +++ b/Palace/Book/UI/TPPBookDetailView.m @@ -442,7 +442,13 @@ - (void)setupAutolayoutConstraints if ([self.book showAudiobookToolbar] && self.isShowingSample) { [self.audiobookSampleToolbar autoPinEdgeToSuperviewEdge:ALEdgeLeft]; [self.audiobookSampleToolbar autoPinEdgeToSuperviewEdge:ALEdgeRight]; - [self.audiobookSampleToolbar autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset: TabBarHeight]; + + CGFloat bottomInset = 0; + if ([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad) { + bottomInset = TabBarHeight; + } + + [self.audiobookSampleToolbar autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset: bottomInset]; [self.audiobookSampleToolbar autoSetDimension:ALDimensionHeight toSize:SampleToolbarHeight relation:NSLayoutRelationLessThanOrEqual]; [self.audiobookSampleToolbar autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self]; self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, SampleToolbarHeight, 0); From 257120f3e227001321f7f84fd5f088f8f53c04d8 Mon Sep 17 00:00:00 2001 From: Maurice Carrier Date: Thu, 11 Jan 2024 23:03:18 -0500 Subject: [PATCH 4/4] Update project.pbxproj --- Palace.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Palace.xcodeproj/project.pbxproj b/Palace.xcodeproj/project.pbxproj index 7866e4b71..c50591abc 100644 --- a/Palace.xcodeproj/project.pbxproj +++ b/Palace.xcodeproj/project.pbxproj @@ -4782,7 +4782,7 @@ CODE_SIGN_IDENTITY = "Apple Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 231; + CURRENT_PROJECT_VERSION = 232; DEVELOPMENT_TEAM = 88CBA74T8K; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; ENABLE_BITCODE = NO; @@ -4840,7 +4840,7 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 231; + CURRENT_PROJECT_VERSION = 232; DEVELOPMENT_TEAM = 88CBA74T8K; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; ENABLE_BITCODE = NO; @@ -5024,7 +5024,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 231; + CURRENT_PROJECT_VERSION = 232; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; ENABLE_BITCODE = NO; @@ -5084,7 +5084,7 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES_ERROR; CODE_SIGN_ENTITLEMENTS = Palace/SimplyE.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 231; + CURRENT_PROJECT_VERSION = 232; DEVELOPMENT_TEAM = 88CBA74T8K; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 88CBA74T8K; ENABLE_BITCODE = NO;