CR: inject state to MoveToSheetStateStore, avoid complex workarounds

This commit is contained in:
Jacek Krasiukianis
2025-08-28 15:32:22 +02:00
parent 5e68121c8c
commit bfa952c181
7 changed files with 54 additions and 55 deletions
@@ -22,3 +22,9 @@ struct MoveToState: Copying {
var moveToCustomFolderActions: [MoveToCustomFolder]
var createFolderLabelPresented: Bool
}
extension MoveToState {
static var initial: Self {
.init(moveToSystemFolderActions: [], moveToCustomFolderActions: [], createFolderLabelPresented: false)
}
}
@@ -23,6 +23,7 @@ import InboxCore
struct MoveToSheet: View {
@EnvironmentObject var toastStateStore: ToastStateStore
private let initialState: MoveToState
private let input: ActionSheetInput
private let mailbox: Mailbox
private let availableMoveToActions: AvailableMoveToActions
@@ -30,9 +31,8 @@ struct MoveToSheet: View {
private let navigation: (MoveToSheetNavigation) -> Void
private let mailUserSession: MailUserSession
var didLoad: (() -> Void)?
init(
initialState: MoveToState = .initial,
input: ActionSheetInput,
mailbox: Mailbox,
availableMoveToActions: AvailableMoveToActions,
@@ -40,6 +40,7 @@ struct MoveToSheet: View {
navigation: @escaping (MoveToSheetNavigation) -> Void,
mailUserSession: MailUserSession
) {
self.initialState = initialState
self.input = input
self.mailbox = mailbox
self.availableMoveToActions = availableMoveToActions
@@ -51,6 +52,7 @@ struct MoveToSheet: View {
var body: some View {
StoreView(
store: MoveToSheetStateStore(
state: initialState,
input: input,
mailbox: mailbox,
availableMoveToActions: availableMoveToActions,
@@ -71,12 +73,7 @@ struct MoveToSheet: View {
.background(DS.Color.BackgroundInverted.norm)
.navigationTitle(L10n.Action.moveTo.string)
.navigationBarTitleDisplayMode(.inline)
.onLoad {
Task {
await store.handle(action: .viewAppear)
didLoad?()
}
}
.onAppear { store.handle(action: .viewAppear) }
.sheet(isPresented: store.binding(\.createFolderLabelPresented)) {
CreateFolderOrLabelScreen()
}
@@ -23,25 +23,42 @@ enum MoveToSheetPreviewProvider {
static var availableMoveToActions: AvailableMoveToActions {
.init(
message: { _, _ in
.ok([
.systemFolder(.init(localId: .init(value: 1), name: .inbox)),
.systemFolder(.init(localId: .init(value: 2), name: .archive)),
.customFolder(customFoldersTree),
.customFolder(
.init(
localId: .init(value: 6),
name: "4",
color: .init(value: "#9E221A"),
children: []
)),
])
.ok(systemFolderActions + customFolderActions)
},
conversation: { _, _ in .ok([]) }
)
}
static func state() -> MoveToState {
.init(
moveToSystemFolderActions: systemFolderActions.compactMap(\.moveToSystemFolder),
moveToCustomFolderActions: customFolderActions.compactMap(\.moveToCustomFolder),
createFolderLabelPresented: false
)
}
// MARK: - Private
private static var systemFolderActions: [MoveAction] {
[
.systemFolder(.init(localId: .init(value: 1), name: .inbox)),
.systemFolder(.init(localId: .init(value: 2), name: .archive)),
]
}
private static var customFolderActions: [MoveAction] {
[
.customFolder(customFoldersTree),
.customFolder(
.init(
localId: .init(value: 6),
name: "4",
color: .init(value: "#9E221A"),
children: []
)),
]
}
private static var customFoldersTree: CustomFolderAction {
.init(
localId: .init(value: 3),
@@ -24,7 +24,7 @@ import SwiftUI
@MainActor
class MoveToSheetStateStore: StateStore {
@Published var state: MoveToState = .initial
@Published var state: MoveToState
private let input: ActionSheetInput
private let moveToActionsProvider: MoveToActionsProvider
@@ -34,6 +34,7 @@ class MoveToSheetStateStore: StateStore {
private let mailUserSession: MailUserSession
init(
state: MoveToState,
input: ActionSheetInput,
mailbox: Mailbox,
availableMoveToActions: AvailableMoveToActions,
@@ -42,6 +43,7 @@ class MoveToSheetStateStore: StateStore {
navigation: @escaping (MoveToSheetNavigation) -> Void,
mailUserSession: MailUserSession
) {
self.state = state
self.input = input
self.moveToActionsProvider = .init(mailbox: mailbox, availableMoveToActions: availableMoveToActions)
self.toastStateStore = toastStateStore
@@ -105,7 +107,7 @@ class MoveToSheetStateStore: StateStore {
}
}
private extension MoveAction {
extension MoveAction {
var moveToSystemFolder: MoveToSystemFolder? {
guard case .systemFolder(let model) = self else {
@@ -135,9 +137,3 @@ private extension CustomFolderAction {
}
}
private extension MoveToState {
static var initial: Self {
.init(moveToSystemFolderActions: [], moveToCustomFolderActions: [], createFolderLabelPresented: false)
}
}
@@ -18,41 +18,23 @@
@testable import ProtonMail
import InboxCoreUI
import InboxSnapshotTesting
import SwiftUI
import Testing
@MainActor
final class MoveToSheetSnapshotTests {
@Test
func actionSheetLayoutsCorrectly() async {
var moveToSheet = MoveToSheet(
let sut = MoveToSheet(
initialState: MoveToSheetPreviewProvider.state(),
input: .init(sheetType: .moveTo, ids: [], mailboxItem: .message(isLastMessageInCurrentLocation: false)),
mailbox: .dummy,
availableMoveToActions: MoveToSheetPreviewProvider.availableMoveToActions,
moveToActions: .dummy,
navigation: { _ in },
mailUserSession: .dummy)
for style in [UIUserInterfaceStyle.light, .dark] {
let viewController = await renderAndWait { continuation in
moveToSheet.didLoad = continuation.resume
return moveToSheet.environmentObject(ToastStateStore(initialState: .initial))
}
viewController.overrideUserInterfaceStyle = style
assertSnapshotOnIPhoneX(of: viewController, style: style, named: "move_to_sheet")
}
mailUserSession: .dummy
).environmentObject(ToastStateStore(initialState: .initial))
assertSnapshotsOnIPhoneX(of: sut, named: "move_to_sheet")
}
private func renderAndWait<Content: View>(contentBuilder: (CheckedContinuation<Void, Never>) -> Content) async -> UIViewController {
var viewController: UIViewController!
await withCheckedContinuation { continuation in
let sut = contentBuilder(continuation)
viewController = UIHostingController(rootView: sut)
viewController.view.snapshotView(afterScreenUpdates: true)
}
return viewController
}
}
@@ -152,6 +152,7 @@ final class MoveToSheetStateStoreTests {
private func sut(input: ActionSheetInput) -> MoveToSheetStateStore {
.init(
state: .initial,
input: input,
mailbox: .init(noPointer: .init()),
availableMoveToActions: .init(
@@ -161,7 +161,9 @@ public func assertSnapshotsOnIPhoneX(
}
}
public func assertSnapshotOnIPhoneX(
// MARK: - Private
private func assertSnapshotOnIPhoneX(
of controller: UIViewController,
style: UIUserInterfaceStyle = .light,
drawHierarchyInKeyWindow: Bool = false,
@@ -194,8 +196,6 @@ public func assertSnapshotOnIPhoneX(
)
}
// MARK: - Private
private func suffixedName(name: String?, withStyle style: UIUserInterfaceStyle) -> String? {
[name, style.humanReadable]
.compactMap { $0 }