mirror of
https://github.com/vector-im/element-ios.git
synced 2024-10-01 00:32:41 +00:00
4af26062eb
* Server Offline Activity Indicator - implemented
153 lines
5.2 KiB
Swift
153 lines
5.2 KiB
Swift
//
|
|
// Copyright 2021 New Vector Ltd
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
import Foundation
|
|
import CommonKit
|
|
import MatrixSDK
|
|
import UIKit
|
|
|
|
/// A set of user interactors commonly used across the app
|
|
enum UserIndicatorType {
|
|
case loading(label: String, isInteractionBlocking: Bool)
|
|
case success(label: String)
|
|
case failure(label: String)
|
|
case custom(label: String, icon: UIImage?)
|
|
}
|
|
|
|
/// A presenter which can handle `UserIndicatorType` by creating the underlying `UserIndicator`
|
|
/// and adding it to its `UserIndicatorQueue`
|
|
protocol UserIndicatorTypePresenterProtocol {
|
|
/// Present a new type of user indicator, such as loading spinner or success message.
|
|
///
|
|
/// The presenter will internally convert the type into a `UserIndicator` and add it to its internal queue
|
|
/// of other indicators.
|
|
///
|
|
/// If the queue is empty, the indicator will be displayed immediately, otherwise it will be pending
|
|
/// until the previously added indicators have completed / been cancelled.
|
|
///
|
|
/// To remove an indicator, `cancel` or deallocate the returned `UserIndicator`
|
|
func present(_ type: UserIndicatorType) -> UserIndicator
|
|
|
|
/// The queue of user indicators owned by the presenter
|
|
///
|
|
/// Clients can access the queue to add custom `UserIndicatorRequest`s
|
|
/// above and beyond those defined by `UserIndicatorType`
|
|
var queue: UserIndicatorQueue { get }
|
|
}
|
|
|
|
class UserIndicatorTypePresenter: UserIndicatorTypePresenterProtocol {
|
|
private let presentationContext: UserIndicatorPresentationContext
|
|
let queue: UserIndicatorQueue
|
|
|
|
init(presentationContext: UserIndicatorPresentationContext) {
|
|
self.presentationContext = presentationContext
|
|
self.queue = UserIndicatorQueue()
|
|
}
|
|
|
|
convenience init(presentingViewController: UIViewController) {
|
|
let context = StaticUserIndicatorPresentationContext(viewController: presentingViewController)
|
|
self.init(presentationContext: context)
|
|
}
|
|
|
|
func present(_ type: UserIndicatorType) -> UserIndicator {
|
|
let request = userIndicatorRequest(for: type)
|
|
return queue.add(request)
|
|
}
|
|
|
|
private func userIndicatorRequest(for type: UserIndicatorType) -> UserIndicatorRequest {
|
|
switch type {
|
|
case .loading(let label, let isInteractionBlocking):
|
|
if isInteractionBlocking {
|
|
return fullScreenLoadingRequest(label: label)
|
|
} else {
|
|
return loadingRequest(label: label)
|
|
}
|
|
case .success(let label):
|
|
return successRequest(label: label)
|
|
case .failure(let label):
|
|
return failureRequest(label: label)
|
|
case .custom(let label, let icon):
|
|
return customRequest(label: label, icon: icon)
|
|
}
|
|
}
|
|
|
|
private func loadingRequest(label: String) -> UserIndicatorRequest {
|
|
let presenter = ToastViewPresenter(
|
|
viewState: .init(
|
|
style: .loading,
|
|
label: label
|
|
),
|
|
presentationContext: presentationContext
|
|
)
|
|
return UserIndicatorRequest(
|
|
presenter: presenter,
|
|
dismissal: .manual
|
|
)
|
|
}
|
|
|
|
private func fullScreenLoadingRequest(label: String) -> UserIndicatorRequest {
|
|
let presenter = FullscreenLoadingViewPresenter(
|
|
label: label,
|
|
presentationContext: presentationContext
|
|
)
|
|
return UserIndicatorRequest(
|
|
presenter: presenter,
|
|
dismissal: .manual
|
|
)
|
|
}
|
|
|
|
private func successRequest(label: String) -> UserIndicatorRequest {
|
|
let presenter = ToastViewPresenter(
|
|
viewState: .init(
|
|
style: .success,
|
|
label: label
|
|
),
|
|
presentationContext: presentationContext
|
|
)
|
|
return UserIndicatorRequest(
|
|
presenter: presenter,
|
|
dismissal: .timeout(1.5)
|
|
)
|
|
}
|
|
|
|
private func failureRequest(label: String) -> UserIndicatorRequest {
|
|
let presenter = ToastViewPresenter(
|
|
viewState: .init(
|
|
style: .failure,
|
|
label: label
|
|
),
|
|
presentationContext: presentationContext
|
|
)
|
|
return UserIndicatorRequest(
|
|
presenter: presenter,
|
|
dismissal: .timeout(1.5)
|
|
)
|
|
}
|
|
|
|
private func customRequest(label: String, icon: UIImage?) -> UserIndicatorRequest {
|
|
let presenter = ToastViewPresenter(
|
|
viewState: .init(
|
|
style: .custom(icon: icon),
|
|
label: label
|
|
),
|
|
presentationContext: presentationContext
|
|
)
|
|
return UserIndicatorRequest(
|
|
presenter: presenter,
|
|
dismissal: .manual
|
|
)
|
|
}
|
|
}
|