mirror of
https://github.com/bitwarden/ios.git
synced 2025-12-11 04:34:55 -06:00
[PM-26062] Consolidate Loading Overlay (#2044)
This commit is contained in:
parent
39b11f17ae
commit
c9bc35bf96
@ -1,3 +1,5 @@
|
||||
import BitwardenKit
|
||||
|
||||
// MARK: - AnyCoordinator
|
||||
|
||||
/// A type erased wrapper for a coordinator.
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
/// State used to configure the display of a `LoadingOverlayView`.
|
||||
///
|
||||
public struct LoadingOverlayState: Equatable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The title of the loading overlay, displayed below the activity indicator.
|
||||
let title: String
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
// swiftlint:disable:this file_name
|
||||
import SnapshotTesting
|
||||
import XCTest
|
||||
|
||||
@testable import AuthenticatorShared
|
||||
|
||||
class LoadingOverlayViewTests: BitwardenTestCase {
|
||||
// MARK: Tests
|
||||
|
||||
/// Test a snapshot of the loading overlay.
|
||||
func disabletest_snapshot_loadingOverlay() {
|
||||
assertSnapshots(
|
||||
of: LoadingOverlayView(state: .init(title: "Loading...")),
|
||||
as: [.defaultPortrait, .defaultPortraitDark],
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
import SwiftUI
|
||||
|
||||
/// A loading overlay view which shows an activity indicator with text below it.
|
||||
///
|
||||
struct LoadingOverlayView: View {
|
||||
// MARK: Properties
|
||||
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
/// The state used to configure the display of the view.
|
||||
let state: LoadingOverlayState
|
||||
|
||||
var body: some View {
|
||||
ProgressView {
|
||||
Text(state.title)
|
||||
.foregroundColor(Asset.Colors.textPrimary.swiftUIColor)
|
||||
.font(.headline)
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
.padding(16)
|
||||
.frame(width: 270, alignment: .center)
|
||||
.background(
|
||||
ZStack {
|
||||
Asset.Colors.materialRegularBase.swiftUIColor
|
||||
Asset.Colors.materialRegularBlend.swiftUIColor
|
||||
.blendMode(colorScheme == .light ? .colorDodge : .overlay)
|
||||
}
|
||||
.compositingGroup(),
|
||||
)
|
||||
.cornerRadius(14)
|
||||
.controlSize(.large)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
|
||||
.background(Asset.Colors.backgroundDimmed.swiftUIColor.ignoresSafeArea())
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#Preview {
|
||||
LoadingOverlayView(state: LoadingOverlayState(title: "Progress..."))
|
||||
}
|
||||
|
||||
#Preview {
|
||||
LoadingOverlayView(state: LoadingOverlayState(title: "Progress..."))
|
||||
.preferredColorScheme(.dark)
|
||||
}
|
||||
#endif
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 76 KiB |
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenResources
|
||||
import SwiftUI
|
||||
import XCTest
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import AVFoundation
|
||||
import BitwardenKit
|
||||
import BitwardenKitMocks
|
||||
import SwiftUI
|
||||
import XCTest
|
||||
|
||||
@ -3,7 +3,7 @@ import SwiftUI
|
||||
|
||||
/// A spinning circular activity indicator.
|
||||
///
|
||||
struct CircularActivityIndicator: View {
|
||||
public struct CircularActivityIndicator: View {
|
||||
// MARK: Properties
|
||||
|
||||
/// Whether the activity indicator is spinning.
|
||||
@ -14,7 +14,7 @@ struct CircularActivityIndicator: View {
|
||||
|
||||
// MARK: View
|
||||
|
||||
var body: some View {
|
||||
public var body: some View {
|
||||
ZStack {
|
||||
Circle()
|
||||
.stroke(SharedAsset.Colors.backgroundTertiary.swiftUIColor, style: strokeStyle)
|
||||
@ -31,6 +31,11 @@ struct CircularActivityIndicator: View {
|
||||
}
|
||||
.frame(width: 56, height: 56)
|
||||
}
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initializes a `CircularActivityIndicator`.
|
||||
public init() {}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
@ -1,10 +1,10 @@
|
||||
import BitwardenKit
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
/// A helper to configure showing and hiding the `LoadingOverlayView` within a view controller.
|
||||
///
|
||||
enum LoadingOverlayDisplayHelper {
|
||||
@MainActor
|
||||
public enum LoadingOverlayDisplayHelper {
|
||||
// MARK: Type Properties
|
||||
|
||||
/// The duration in seconds of the show and hide transitions.
|
||||
@ -12,7 +12,7 @@ enum LoadingOverlayDisplayHelper {
|
||||
|
||||
/// A value that is used to identify the loading overlay view within the view hierarchy in
|
||||
/// order to remove it.
|
||||
static let overlayViewTag = 1000
|
||||
public static let overlayViewTag = 1000
|
||||
|
||||
// MARK: Type Methods
|
||||
|
||||
@ -22,7 +22,7 @@ enum LoadingOverlayDisplayHelper {
|
||||
/// - parentViewController: The parent view controller that the overlay should be shown above.
|
||||
/// - state: State used to configure the display of the loading overlay view.
|
||||
///
|
||||
static func show(in parentViewController: UIViewController, state: LoadingOverlayState) {
|
||||
public static func show(in parentViewController: UIViewController, state: LoadingOverlayState) {
|
||||
guard parentViewController.view.window?.viewWithTag(overlayViewTag) == nil,
|
||||
let window = parentViewController.view.window
|
||||
else {
|
||||
@ -46,7 +46,7 @@ enum LoadingOverlayDisplayHelper {
|
||||
///
|
||||
/// - Parameter parentViewController: The parent view controller that the overlay is shown above.
|
||||
///
|
||||
static func hide(from parentViewController: UIViewController) {
|
||||
public static func hide(from parentViewController: UIViewController) {
|
||||
guard let view = parentViewController.view.window?.viewWithTag(overlayViewTag) else { return }
|
||||
|
||||
UIView.animate(withDuration: UI.duration(transitionDuration)) {
|
||||
@ -1,10 +1,10 @@
|
||||
import BitwardenKit
|
||||
import SwiftUI
|
||||
import XCTest
|
||||
|
||||
@testable import AuthenticatorShared
|
||||
|
||||
class LoadingOverlayDisplayHelperTests: BitwardenTestCase {
|
||||
/// `show(in:state:)` shows the loading overlay in the parent view controller.
|
||||
@MainActor
|
||||
func test_show() throws {
|
||||
let parentViewController = UIViewController()
|
||||
let window = UIWindow()
|
||||
@ -25,6 +25,7 @@ class LoadingOverlayDisplayHelperTests: BitwardenTestCase {
|
||||
}
|
||||
|
||||
/// `hide(from:)` hides the loading overlay in the parent view controller.
|
||||
@MainActor
|
||||
func test_hide() throws {
|
||||
let parentViewController = UIViewController()
|
||||
let window = UIWindow()
|
||||
@ -0,0 +1,18 @@
|
||||
/// State used to configure the display of a `LoadingOverlayView`.
|
||||
///
|
||||
public struct LoadingOverlayState: Equatable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The title of the loading overlay, displayed below the activity indicator.
|
||||
public let title: String
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initializes a `LoadingOverlayState`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - title: The title of the loading overlay, displayed below the activity indicator.
|
||||
public init(title: String) {
|
||||
self.title = title
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenKitMocks
|
||||
import BitwardenResources
|
||||
import TestHelpers
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenKitMocks
|
||||
import BitwardenResources
|
||||
import BitwardenSdk
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - LoadingView
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import Foundation
|
||||
|
||||
// MARK: - AnyCoordinator
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
import BitwardenKit
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
/// A helper to configure showing and hiding the `LoadingOverlayView` within a view controller.
|
||||
///
|
||||
enum LoadingOverlayDisplayHelper {
|
||||
// MARK: Type Properties
|
||||
|
||||
/// The duration in seconds of the show and hide transitions.
|
||||
static let transitionDuration: TimeInterval = 0.2
|
||||
|
||||
/// A value that is used to identify the loading overlay view within the view hierarchy in
|
||||
/// order to remove it.
|
||||
static let overlayViewTag = 1000
|
||||
|
||||
// MARK: Type Methods
|
||||
|
||||
/// Shows the loading overlay view as a full-screen view over the specified view controller.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - parentViewController: The parent view controller that the overlay should be shown above.
|
||||
/// - state: State used to configure the display of the loading overlay view.
|
||||
///
|
||||
static func show(in parentViewController: UIViewController, state: LoadingOverlayState) {
|
||||
guard parentViewController.view.window?.viewWithTag(overlayViewTag) == nil,
|
||||
let window = parentViewController.view.window
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
let viewController = UIHostingController(rootView: LoadingOverlayView(state: state))
|
||||
viewController.view.layer.backgroundColor = nil
|
||||
viewController.view.layer.opacity = 0
|
||||
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
viewController.view.frame = window.frame
|
||||
viewController.view.tag = overlayViewTag
|
||||
window.addSubview(viewController.view)
|
||||
|
||||
UIView.animate(withDuration: UI.duration(transitionDuration)) {
|
||||
viewController.view.layer.opacity = 1
|
||||
}
|
||||
}
|
||||
|
||||
/// Hides the loading overlay view from showing over the specified view controller
|
||||
///
|
||||
/// - Parameter parentViewController: The parent view controller that the overlay is shown above.
|
||||
///
|
||||
static func hide(from parentViewController: UIViewController) {
|
||||
guard let view = parentViewController.view.window?.viewWithTag(overlayViewTag) else { return }
|
||||
|
||||
UIView.animate(withDuration: UI.duration(transitionDuration)) {
|
||||
view.layer.opacity = 0
|
||||
} completion: { _ in
|
||||
view.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
import SwiftUI
|
||||
import XCTest
|
||||
|
||||
@testable import BitwardenShared
|
||||
|
||||
class LoadingOverlayDisplayHelperTests: BitwardenTestCase {
|
||||
/// `show(in:state:)` shows the loading overlay in the parent view controller.
|
||||
func test_show() throws {
|
||||
let parentViewController = UIViewController()
|
||||
let window = UIWindow()
|
||||
window.rootViewController = parentViewController
|
||||
window.makeKeyAndVisible()
|
||||
|
||||
LoadingOverlayDisplayHelper.show(
|
||||
in: parentViewController,
|
||||
state: LoadingOverlayState(title: "Loading..."),
|
||||
)
|
||||
|
||||
let overlayView = try XCTUnwrap(window.viewWithTag(LoadingOverlayDisplayHelper.overlayViewTag))
|
||||
XCTAssertEqual(overlayView.layer.opacity, 1)
|
||||
guard #unavailable(iOS 26) else {
|
||||
return
|
||||
}
|
||||
XCTAssertNil(overlayView.layer.backgroundColor)
|
||||
}
|
||||
|
||||
/// `hide(from:)` hides the loading overlay in the parent view controller.
|
||||
func test_hide() throws {
|
||||
let parentViewController = UIViewController()
|
||||
let window = UIWindow()
|
||||
window.rootViewController = parentViewController
|
||||
window.makeKeyAndVisible()
|
||||
|
||||
LoadingOverlayDisplayHelper.show(
|
||||
in: parentViewController,
|
||||
state: LoadingOverlayState(title: "Loading..."),
|
||||
)
|
||||
let overlayView = try XCTUnwrap(window.viewWithTag(LoadingOverlayDisplayHelper.overlayViewTag))
|
||||
|
||||
LoadingOverlayDisplayHelper.hide(from: parentViewController)
|
||||
|
||||
waitFor { overlayView.superview == nil }
|
||||
|
||||
XCTAssertNil(overlayView.superview)
|
||||
XCTAssertEqual(overlayView.layer.opacity, 0)
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
/// State used to configure the display of a `LoadingOverlayView`.
|
||||
///
|
||||
public struct LoadingOverlayState: Equatable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The title of the loading overlay, displayed below the activity indicator.
|
||||
let title: String
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenKitMocks
|
||||
import BitwardenResources
|
||||
import SwiftUI
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenKitMocks
|
||||
import BitwardenResources
|
||||
import SwiftUI
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import SwiftUI
|
||||
import XCTest
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import AVFoundation
|
||||
import BitwardenKit
|
||||
import BitwardenKitMocks
|
||||
import SwiftUI
|
||||
import XCTest
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenResources
|
||||
|
||||
// MARK: - EditCollectionsProcessorDelegate
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenKitMocks
|
||||
import BitwardenResources
|
||||
import BitwardenSdk
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenResources
|
||||
import BitwardenSdk
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import BitwardenKitMocks
|
||||
import BitwardenResources
|
||||
import BitwardenSdk
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import BitwardenKit
|
||||
import XCTest
|
||||
|
||||
@testable import AuthenticatorShared
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user