Skip to content

Commit

Permalink
Merge pull request #36 from apivideo/feature/ios_task_cancellation
Browse files Browse the repository at this point in the history
Feature/ios task cancellation
  • Loading branch information
bot-api-video committed Dec 6, 2022
2 parents 9d23f63 + 57541e1 commit d9ed14b
Show file tree
Hide file tree
Showing 29 changed files with 576 additions and 417 deletions.
8 changes: 4 additions & 4 deletions .openapi-generator/FILES
Expand Up @@ -95,10 +95,10 @@ Sources/Models/WebhooksCreationPayload.swift
Sources/Models/WebhooksListResponse.swift
Sources/OpenISO8601DateFormatter.swift
Sources/SynchronizedDictionary.swift
Sources/Upload/ChunkInputStream.swift
Sources/Upload/FileChunksBuilder.swift
Sources/Upload/FileReaders.swift
Sources/Upload/ProgressiveUploadSessioning.swift
Sources/Upload/FileChunkInputStream.swift
Sources/Upload/ProgressiveUploadSessionProtocol.swift
Sources/Upload/RequestTaskQueue.swift
Sources/Upload/UploadChunkRequestTaskQueue.swift
docs/AccessToken.md
docs/AuthenticatePayload.md
docs/AuthenticationAPI.md
Expand Down
4 changes: 2 additions & 2 deletions ApiVideoClient.podspec
Expand Up @@ -4,8 +4,8 @@ Pod::Spec.new do |s|
s.osx.deployment_target = '10.12'
s.tvos.deployment_target = '10.0'
s.watchos.deployment_target = '3.0'
s.version = '1.0.6'
s.source = { :git => 'https://github.com/apivideo/api.video-ios-client', :tag => 'v1.0.6' }
s.version = '1.1.0'
s.source = { :git => 'https://github.com/apivideo/api.video-ios-client', :tag => 'v1.1.0' }
s.authors = { 'Ecosystem Team' => 'ecosystem@api.video' }
s.license = { :type => 'MIT' }
s.homepage = 'https://docs.api.video'
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
All changes to this project will be documented in this file.

## [1.1.0] - 2022-12-06
- Refactor upload by chunk and progressive upload. It is now possible to cancel an upload.
- Add timeout API

## [1.0.6] - 2022-09-13
- period parameter is now mandatory in analytics endpoints

Expand Down
24 changes: 14 additions & 10 deletions Example/Example/Controller/UploaderViewController.swift
Expand Up @@ -194,18 +194,22 @@ class UploaderViewController: UIViewController, UIImagePickerControllerDelegate,
func upload(url: URL) {
VideosAPI.create(videoCreationPayload: VideoCreationPayload(title: "my video")) { video, error in
if let video = video {
VideosAPI.upload(
videoId: video.videoId,
file: url,
onProgressReady: { progress in
print("Progress: \(progress)")
}) { video, error in
do {
try VideosAPI.upload(
videoId: video.videoId,
file: url,
onProgressReady: { progress in
print("Progress: \(progress)")
}) { video, error in
if video != nil {
self.thumbnailImageView.image = nil
}
if let error = error {
print("Upload error: \(error)")
self.thumbnailImageView.image = nil
}
if let error = error {
print("Upload error: \(error)")
}
}
} catch {
print("Upload error: \(error)")
}
}
if let error = error {
Expand Down
22 changes: 13 additions & 9 deletions README.md
Expand Up @@ -42,14 +42,14 @@ api.video's iOS streamlines the coding process. Chunking files is handled for y
Specify it in your `Cartfile`:

```
github "apivideo/api.video-ios-client" ~> 1.0.6
github "apivideo/api.video-ios-client" ~> 1.1.0
```

Run `carthage update`

### CocoaPods

Add `pod 'ApiVideoClient', '1.0.6'` in your `Podfile`
Add `pod 'ApiVideoClient', '1.1.0'` in your `Podfile`

Run `pod install`

Expand All @@ -67,14 +67,18 @@ import ApiVideoClient

VideosAPI.create(videoCreationPayload: VideoCreationPayload(title: "my video")) { video, error in
if let video = video {
VideosAPI.upload(videoId: video.videoId,
file: url) { video, error in
if let video = video {
// Manage upload success here
}
if let error = error {
// Manage upload error here
do {
try VideosAPI.upload(videoId: video.videoId,
file: url) { video, error in
if let video = video {
// Manage upload success here
}
if let error = error {
// Manage upload error here
}
}
} catch {
// Manage error on file here
}
}
if let error = error {
Expand Down
21 changes: 9 additions & 12 deletions Sources/APIs.swift
Expand Up @@ -5,19 +5,15 @@
//

import Foundation
enum ApiVideoClientError: Error {
case invalidName
case invalidVersion
}

public class ApiVideoClient {
public static var apiKey: String? = nil
public static var basePath = "https://ws.api.video"
internal static var customHeaders:[String: String] = ["AV-Origin-Client": "ios:1.0.6"]
internal static var customHeaders:[String: String] = ["AV-Origin-Client": "ios:1.1.0"]
private static var chunkSize: Int = 50 * 1024 * 1024
internal static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory()
internal static var credential = ApiVideoCredential()
public static var apiResponseQueue: DispatchQueue = .main
public static var timeout: TimeInterval = 60

public static func setChunkSize(chunkSize: Int) throws {
if (chunkSize > 128 * 1024 * 1024) {
Expand Down Expand Up @@ -56,11 +52,11 @@ public class ApiVideoClient {

static func setName(key: String, name: String, version: String) throws {
if(!isValidName(name: name)) {
throw ApiVideoClientError.invalidName
throw ParameterError.invalidName
}

if(!isValidVersion(version: version)) {
throw ApiVideoClientError.invalidVersion
throw ParameterError.invalidVersion
}
ApiVideoClient.customHeaders[key] = name + ":" + version
}
Expand All @@ -77,12 +73,13 @@ public class ApiVideoClient {

open class RequestBuilder<T> {
var headers: [String: String]
public let parameters: [String: Any]?
public var parameters: [String: Any]?
public let method: String
public let URLString: String
public let requestTask: RequestTask = RequestTask()

/// Optional block to obtain a reference to the request's progress instance when available.
public let onProgressReady: ((Progress) -> Void)?
public var onProgressReady: ((Progress) -> Void)?

required public init(method: String, URLString: String, parameters: [String: Any]?, headers: [String: String] = [:], onProgressReady: ((Progress) -> Void)? = nil) {
self.method = method
Expand All @@ -101,8 +98,8 @@ open class RequestBuilder<T> {
}

@discardableResult
open func execute(_ apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result<Response<T>, ErrorResponse>) -> Void) -> URLSessionTask? {
return nil
open func execute(_ apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, _ completion: @escaping (_ result: Swift.Result<Response<T>, ErrorResponse>) -> Void) -> RequestTask {
return requestTask
}

public func addHeader(name: String, value: String) -> Self {
Expand Down
4 changes: 2 additions & 2 deletions Sources/APIs/AuthenticationAPI.swift
Expand Up @@ -20,7 +20,7 @@ open class AuthenticationAPI {
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func authenticate(authenticatePayload: AuthenticatePayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: AccessToken?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func authenticate(authenticatePayload: AuthenticatePayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: AccessToken?, _ error: Error?) -> Void)) -> RequestTask {
return authenticateWithRequestBuilder(authenticatePayload: authenticatePayload).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down Expand Up @@ -66,7 +66,7 @@ open class AuthenticationAPI {
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func refresh(refreshTokenPayload: RefreshTokenPayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: AccessToken?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func refresh(refreshTokenPayload: RefreshTokenPayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: AccessToken?, _ error: Error?) -> Void)) -> RequestTask {
return refreshWithRequestBuilder(refreshTokenPayload: refreshTokenPayload).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down
10 changes: 5 additions & 5 deletions Sources/APIs/CaptionsAPI.swift
Expand Up @@ -22,7 +22,7 @@ open class CaptionsAPI {
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func upload(videoId: String, language: String, file: URL, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Caption?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func upload(videoId: String, language: String, file: URL, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Caption?, _ error: Error?) -> Void)) -> RequestTask {
return uploadWithRequestBuilder(videoId: videoId, language: language, file: file).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down Expand Up @@ -81,7 +81,7 @@ open class CaptionsAPI {
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func get(videoId: String, language: String, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Caption?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func get(videoId: String, language: String, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Caption?, _ error: Error?) -> Void)) -> RequestTask {
return getWithRequestBuilder(videoId: videoId, language: language).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down Expand Up @@ -138,7 +138,7 @@ Tutorials that use the [captions endpoint](https://api.video/blog/endpoints/capt
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func update(videoId: String, language: String, captionsUpdatePayload: CaptionsUpdatePayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Caption?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func update(videoId: String, language: String, captionsUpdatePayload: CaptionsUpdatePayload, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Caption?, _ error: Error?) -> Void)) -> RequestTask {
return updateWithRequestBuilder(videoId: videoId, language: language, captionsUpdatePayload: captionsUpdatePayload).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down Expand Up @@ -193,7 +193,7 @@ Tutorials that use the [captions endpoint](https://api.video/blog/endpoints/capt
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func delete(videoId: String, language: String, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func delete(videoId: String, language: String, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) -> RequestTask {
return deleteWithRequestBuilder(videoId: videoId, language: language).execute(apiResponseQueue) { result in
switch result {
case .success:
Expand Down Expand Up @@ -248,7 +248,7 @@ Tutorials that use the [captions endpoint](https://api.video/blog/endpoints/capt
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func list(videoId: String, currentPage: Int? = nil, pageSize: Int? = nil, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: CaptionsListResponse?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func list(videoId: String, currentPage: Int? = nil, pageSize: Int? = nil, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: CaptionsListResponse?, _ error: Error?) -> Void)) -> RequestTask {
return listWithRequestBuilder(videoId: videoId, currentPage: currentPage, pageSize: pageSize).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down
8 changes: 4 additions & 4 deletions Sources/APIs/ChaptersAPI.swift
Expand Up @@ -22,7 +22,7 @@ open class ChaptersAPI {
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func upload(videoId: String, language: String, file: URL, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Chapter?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func upload(videoId: String, language: String, file: URL, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Chapter?, _ error: Error?) -> Void)) -> RequestTask {
return uploadWithRequestBuilder(videoId: videoId, language: language, file: file).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down Expand Up @@ -81,7 +81,7 @@ open class ChaptersAPI {
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func get(videoId: String, language: String, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Chapter?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func get(videoId: String, language: String, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Chapter?, _ error: Error?) -> Void)) -> RequestTask {
return getWithRequestBuilder(videoId: videoId, language: language).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down Expand Up @@ -135,7 +135,7 @@ open class ChaptersAPI {
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func delete(videoId: String, language: String, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func delete(videoId: String, language: String, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: Void?, _ error: Error?) -> Void)) -> RequestTask {
return deleteWithRequestBuilder(videoId: videoId, language: language).execute(apiResponseQueue) { result in
switch result {
case .success:
Expand Down Expand Up @@ -190,7 +190,7 @@ open class ChaptersAPI {
- parameter completion: completion handler to receive the data and the error objects.
*/
@discardableResult
open class func list(videoId: String, currentPage: Int? = nil, pageSize: Int? = nil, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: ChaptersListResponse?, _ error: Error?) -> Void)) -> URLSessionTask? {
open class func list(videoId: String, currentPage: Int? = nil, pageSize: Int? = nil, apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue, completion: @escaping ((_ data: ChaptersListResponse?, _ error: Error?) -> Void)) -> RequestTask {
return listWithRequestBuilder(videoId: videoId, currentPage: currentPage, pageSize: pageSize).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
Expand Down

0 comments on commit d9ed14b

Please sign in to comment.