diff --git a/App/Sources/UI/Views/AppUpdater.swift b/App/Sources/Core/AppUpdater.swift similarity index 100% rename from App/Sources/UI/Views/AppUpdater.swift rename to App/Sources/Core/AppUpdater.swift diff --git a/App/Sources/Core/Core.swift b/App/Sources/Core/Core.swift index 98da96eef..51fff9987 100644 --- a/App/Sources/Core/Core.swift +++ b/App/Sources/Core/Core.swift @@ -10,48 +10,48 @@ final class Core { lazy private(set) var configCoordinator = ConfigurationCoordinator( contentStore: contentStore, configurationUpdater: configurationUpdater, - selectionManager: configSelectionManager, + selectionManager: configSelection, store: configurationStore) lazy private(set) var sidebarCoordinator = SidebarCoordinator( groupStore, applicationStore: ApplicationStore.shared, - groupSelectionManager: groupSelectionManager) + groupSelectionManager: groupSelection) - lazy private(set) var contentCoordinator = ContentCoordinator( + lazy private(set) var groupCoordinator = GroupCoordinator( groupStore, applicationStore: ApplicationStore.shared, - contentSelectionManager: contentSelectionManager, - groupSelectionManager: groupSelectionManager + groupSelectionManager: groupSelection, + workflowsSelectionManager: workflowsSelection ) - lazy private(set) var detailCoordinator = DetailCoordinator( + lazy private(set) var workflowCoordinator = WorkflowCoordinator( applicationStore: ApplicationStore.shared, - applicationTriggerSelectionManager: applicationTriggerSelectionManager, + applicationTriggerSelection: applicationTriggerSelection, commandRunner: commandRunner, - commandSelectionManager: commandSelectionManager, - contentSelectionManager: contentSelectionManager, + commandSelection: commandSelection, + workflowsSelection: workflowsSelection, contentStore: contentStore, - groupSelectionManager: groupSelectionManager, + groupSelection: groupSelection, keyboardCowboyEngine: engine, - keyboardShortcutSelectionManager: keyboardShortcutSelectionManager, + keyboardShortcutSelection: keyboardShortcutSelection, groupStore: contentStore.groupStore) // MARK: - Selection managers - lazy private(set) var keyboardShortcutSelectionManager = SelectionManager() - lazy private(set) var applicationTriggerSelectionManager = SelectionManager() - lazy private(set) var commandSelectionManager = SelectionManager() + lazy private(set) var keyboardShortcutSelection = SelectionManager() + lazy private(set) var applicationTriggerSelection = SelectionManager() + lazy private(set) var commandSelection = SelectionManager() - lazy private(set) var configSelectionManager = SelectionManager(initialSelection: [AppStorageContainer.shared.configId]) { + lazy private(set) var configSelection = SelectionManager(initialSelection: [AppStorageContainer.shared.configId]) { AppStorageContainer.shared.configId = $0.first ?? "" } - lazy private(set) var groupSelectionManager = SelectionManager(initialSelection: AppStorageContainer.shared.groupIds) { + lazy private(set) var groupSelection = SelectionManager(initialSelection: AppStorageContainer.shared.groupIds) { AppStorageContainer.shared.groupIds = $0 } - lazy private(set) var contentSelectionManager = SelectionManager(initialSelection: AppStorageContainer.shared.workflowIds) { + lazy private(set) var workflowsSelection = SelectionManager(initialSelection: AppStorageContainer.shared.workflowIds) { AppStorageContainer.shared.workflowIds = $0 } @@ -140,12 +140,12 @@ final class Core { onRender: { [weak self] configuration, commit, animation in guard let self else { return } groupStore.updateGroups(Set(configuration.groups)) - detailCoordinator.handle(.selectGroups([commit.groupID])) + workflowCoordinator.handle(.selectGroups([commit.groupID])) }, onStorageUpdate: { [weak self] configuration, commit in guard let self else { return } - withAnimation { [contentCoordinator] in - contentCoordinator.handle(.refresh([commit.groupID])) + withAnimation { [groupCoordinator] in + groupCoordinator.handle(.refresh([commit.groupID])) } configurationStore.update(configuration) }) diff --git a/App/Sources/Core/KeyboardCowboyApp.swift b/App/Sources/Core/KeyboardCowboyApp.swift index 61ce116f6..aa4c03b8d 100644 --- a/App/Sources/Core/KeyboardCowboyApp.swift +++ b/App/Sources/Core/KeyboardCowboyApp.swift @@ -67,16 +67,16 @@ struct KeyboardCowboyApp: App { let action = SidebarView.Action.addConfiguration(name: "New Configuration") core.configCoordinator.handle(action) core.sidebarCoordinator.handle(action) - core.contentCoordinator.handle(action) - core.detailCoordinator.handle(action) + core.groupCoordinator.handle(action) + core.workflowCoordinator.handle(action) }, onNewGroup: { windowOpener.openGroup(.add(WorkflowGroup.empty())) }, onNewWorkflow: { - let action = ContentView.Action.addWorkflow(workflowId: UUID().uuidString) - core.contentCoordinator.handle(action) - core.detailCoordinator.handle(action) + let action = GroupDetailView.Action.addWorkflow(workflowId: UUID().uuidString) + core.groupCoordinator.handle(action) + core.workflowCoordinator.handle(action) // focus = .detail(.name) }, onNewCommand: { id in @@ -84,8 +84,8 @@ struct KeyboardCowboyApp: App { } ) .environmentObject(core.contentStore.groupStore) - .environmentObject(core.detailCoordinator.statePublisher) - .environmentObject(core.detailCoordinator.infoPublisher) + .environmentObject(core.workflowCoordinator.statePublisher) + .environmentObject(core.workflowCoordinator.infoPublisher) } CommandGroup(replacing: .toolbar) { diff --git a/App/Sources/UI/Coordinators/ContentCoordinator.swift b/App/Sources/UI/Coordinators/GroupCoordinator.swift similarity index 75% rename from App/Sources/UI/Coordinators/ContentCoordinator.swift rename to App/Sources/UI/Coordinators/GroupCoordinator.swift index e6b2b1353..317dd9c9e 100644 --- a/App/Sources/UI/Coordinators/ContentCoordinator.swift +++ b/App/Sources/UI/Coordinators/GroupCoordinator.swift @@ -3,28 +3,28 @@ import Combine import SwiftUI @MainActor -final class ContentCoordinator { +final class GroupCoordinator { private let applicationStore: ApplicationStore - private let contentSelectionManager: SelectionManager private let groupSelectionManager: SelectionManager - private let mapper: ContentModelMapper + private let workflowsSelectionManager: SelectionManager + private let mapper: GroupDetailViewModelMapper private let store: GroupStore let groupPublisher: GroupPublisher = GroupPublisher( .init(id: UUID().uuidString, name: "", icon: nil, color: "", symbol: "", userModes: [], count: 0) ) - let contentPublisher: ContentPublisher = ContentPublisher() + let contentPublisher: GroupDetailPublisher = GroupDetailPublisher() init(_ store: GroupStore, applicationStore: ApplicationStore, - contentSelectionManager: SelectionManager, - groupSelectionManager: SelectionManager) { + groupSelectionManager: SelectionManager, + workflowsSelectionManager: SelectionManager) { self.applicationStore = applicationStore self.store = store self.groupSelectionManager = groupSelectionManager - self.mapper = ContentModelMapper() - self.contentSelectionManager = contentSelectionManager + self.mapper = GroupDetailViewModelMapper() + self.workflowsSelectionManager = workflowsSelectionManager } func handle(_ action: SidebarView.Action) { @@ -48,17 +48,17 @@ final class ContentCoordinator { handle(.refresh(ids)) if shouldRemoveLastSelection { if let firstId = contentPublisher.data.first?.id { - contentSelectionManager.setLastSelection(firstId) + workflowsSelectionManager.setLastSelection(firstId) } else { - contentSelectionManager.removeLastSelection() + workflowsSelectionManager.removeLastSelection() } - } else if let lastSelection = contentSelectionManager.lastSelection { + } else if let lastSelection = workflowsSelectionManager.lastSelection { // Check for invalid selections, reset the last selection to the first one. // Otherwise, the focus updates won't work properly because it is looking for an // identifier that does not exist in the current group. if !contentPublisher.data.contains(where: { $0.id == lastSelection }) { if let firstId = contentPublisher.data.first?.id { - contentSelectionManager.setLastSelection(firstId) + workflowsSelectionManager.setLastSelection(firstId) } } } @@ -76,15 +76,15 @@ final class ContentCoordinator { } } - func handle(_ action: ContentView.Action) { + func handle(_ action: GroupDetailView.Action) { // TODO: We should get rid of this guard. guard let id = groupSelectionManager.selections.first, var group = store.group(withId: id) else { return } - ContentViewActionReducer.reduce( + GroupDetailViewActionReducer.reduce( action, groupStore: store, - selectionManager: contentSelectionManager, + selectionManager: workflowsSelectionManager, group: &group) switch action { @@ -112,10 +112,10 @@ final class ContentCoordinator { Benchmark.shared.start("ContentCoordinator.render") defer { Benchmark.shared.stop("ContentCoordinator.render") } - var viewModels = [ContentViewModel]() - var newSelections = Set() - var selectedWorkflowIds = contentSelectionManager.selections - var firstViewModel: ContentViewModel? + var viewModels = [GroupDetailViewModel]() + var newSelections = Set() + var selectedWorkflowIds = workflowsSelectionManager.selections + var firstViewModel: GroupDetailViewModel? for offset in store.groups.indices { let group = store.groups[offset] @@ -147,16 +147,16 @@ final class ContentCoordinator { if newSelections.isEmpty, let first = viewModels.first { newSelections = [first.id] } - } else if !contentSelectionManager.selections.intersection(viewModels.map(\.id)).isEmpty { - newSelections = contentSelectionManager.selections + } else if !workflowsSelectionManager.selections.intersection(viewModels.map(\.id)).isEmpty { + newSelections = workflowsSelectionManager.selections } else if newSelections.isEmpty, let first = firstViewModel { newSelections = [first.id] } - contentSelectionManager.publish(newSelections) + workflowsSelectionManager.publish(newSelections) } else if let selectionOverrides { - contentSelectionManager.publish(selectionOverrides) + workflowsSelectionManager.publish(selectionOverrides) if let first = selectionOverrides.first { - contentSelectionManager.setLastSelection(first) + workflowsSelectionManager.setLastSelection(first) } } } diff --git a/App/Sources/UI/Coordinators/SidebarCoordinator.swift b/App/Sources/UI/Coordinators/SidebarCoordinator.swift index 185861b9d..a03c22d9d 100644 --- a/App/Sources/UI/Coordinators/SidebarCoordinator.swift +++ b/App/Sources/UI/Coordinators/SidebarCoordinator.swift @@ -44,7 +44,7 @@ final class SidebarCoordinator { } selectionManager.publish([groupId]) if storeWasEmpty { - withAnimation(WorkflowCommandListView.animation) { + withAnimation(CommandList.animation) { render(store.groups) } } else { diff --git a/App/Sources/UI/Coordinators/DetailCoordinator.swift b/App/Sources/UI/Coordinators/WorkflowCoordinator.swift similarity index 65% rename from App/Sources/UI/Coordinators/DetailCoordinator.swift rename to App/Sources/UI/Coordinators/WorkflowCoordinator.swift index 6d3522740..f7d69a948 100644 --- a/App/Sources/UI/Coordinators/DetailCoordinator.swift +++ b/App/Sources/UI/Coordinators/WorkflowCoordinator.swift @@ -3,17 +3,17 @@ import Combine import SwiftUI @MainActor -final class DetailCoordinator { +final class WorkflowCoordinator { private let applicationStore: ApplicationStore - private let applicationTriggerSelectionManager: SelectionManager + private let applicationTriggerSelection: SelectionManager private let commandRunner: CommandRunner - private let commandSelectionManager: SelectionManager - private let contentSelectionManager: SelectionManager + private let commandSelection: SelectionManager + private let workflowsSelection: SelectionManager private let contentStore: ContentStore - private let groupSelectionManager: SelectionManager + private let groupSelection: SelectionManager private let groupStore: GroupStore private let keyboardCowboyEngine: KeyboardCowboyEngine - private let keyboardShortcutSelectionManager: SelectionManager + private let keyboardShortcutSelection: SelectionManager let updateTransaction: UpdateTransaction = .init(groupID: "", workflowID: "") let infoPublisher: InfoPublisher = .init(.init(id: "empty", name: "", isEnabled: false)) @@ -24,26 +24,26 @@ final class DetailCoordinator { let statePublisher: DetailStatePublisher = .init(.empty) init(applicationStore: ApplicationStore, - applicationTriggerSelectionManager: SelectionManager, + applicationTriggerSelection: SelectionManager, commandRunner: CommandRunner, - commandSelectionManager: SelectionManager, - contentSelectionManager: SelectionManager, + commandSelection: SelectionManager, + workflowsSelection: SelectionManager, contentStore: ContentStore, - groupSelectionManager: SelectionManager, + groupSelection: SelectionManager, keyboardCowboyEngine: KeyboardCowboyEngine, - keyboardShortcutSelectionManager: SelectionManager, + keyboardShortcutSelection: SelectionManager, groupStore: GroupStore) { self.applicationStore = applicationStore self.commandRunner = commandRunner - self.commandSelectionManager = commandSelectionManager - self.contentSelectionManager = contentSelectionManager + self.commandSelection = commandSelection + self.workflowsSelection = workflowsSelection self.contentStore = contentStore - self.groupSelectionManager = groupSelectionManager + self.groupSelection = groupSelection self.groupStore = groupStore self.keyboardCowboyEngine = keyboardCowboyEngine self.mapper = DetailModelMapper(applicationStore) - self.keyboardShortcutSelectionManager = keyboardShortcutSelectionManager - self.applicationTriggerSelectionManager = applicationTriggerSelectionManager + self.keyboardShortcutSelection = keyboardShortcutSelection + self.applicationTriggerSelection = applicationTriggerSelection enableInjection(self, selector: #selector(injected(_:))) } @@ -51,26 +51,26 @@ final class DetailCoordinator { func handle(_ action: SidebarView.Action) { switch action { case .addConfiguration: - render(contentSelectionManager.selections, - groupIds: groupSelectionManager.selections) + render(workflowsSelection.selections, + groupIds: groupSelection.selections) case .refresh, .updateConfiguration, .openScene, .deleteConfiguration, .userMode: // NOOP break case .moveWorkflows, .copyWorkflows: - render(contentSelectionManager.selections, - groupIds: groupSelectionManager.selections) + render(workflowsSelection.selections, + groupIds: groupSelection.selections) case .moveGroups, .removeGroups: - render(contentSelectionManager.selections, - groupIds: groupSelectionManager.selections) + render(workflowsSelection.selections, + groupIds: groupSelection.selections) case .selectConfiguration: - render(contentSelectionManager.selections, - groupIds: groupSelectionManager.selections) + render(workflowsSelection.selections, + groupIds: groupSelection.selections) case .selectGroups(let ids): if let firstId = ids.first, let group = groupStore.group(withId: firstId) { - var workflowIds = Set() + var workflowIds = Set() - let matches = group.workflows.filter { contentSelectionManager.selections.contains($0.id) } + let matches = group.workflows.filter { workflowsSelection.selections.contains($0.id) } .map(\.id) if !matches.isEmpty { @@ -80,32 +80,32 @@ final class DetailCoordinator { } render(workflowIds, groupIds: Set(ids)) - applicationTriggerSelectionManager.removeLastSelection() - keyboardShortcutSelectionManager.removeLastSelection() - commandSelectionManager.removeLastSelection() + applicationTriggerSelection.removeLastSelection() + keyboardShortcutSelection.removeLastSelection() + commandSelection.removeLastSelection() } } } - func handle(_ action: ContentView.Action) { + func handle(_ action: GroupDetailView.Action) { switch action { case .refresh, .moveWorkflowsToGroup, .reorderWorkflows, .duplicate: return case .moveCommandsToWorkflow(_, let workflowId, _): - guard let groupId = groupSelectionManager.selections.first else { return } + guard let groupId = groupSelection.selections.first else { return } render([workflowId], groupIds: [groupId]) case .selectWorkflow(let workflowIds): - render(workflowIds, groupIds: groupSelectionManager.selections) + render(workflowIds, groupIds: groupSelection.selections) case .removeWorkflows: - guard let first = groupSelectionManager.selections.first, + guard let first = groupSelection.selections.first, let group = groupStore.group(withId: first) else { return } if group.workflows.isEmpty { - render([], groupIds: groupSelectionManager.selections) + render([], groupIds: groupSelection.selections) } case .addWorkflow(let workflowId): - render([workflowId], groupIds: groupSelectionManager.selections) + render([workflowId], groupIds: groupSelection.selections) } } @@ -114,8 +114,8 @@ final class DetailCoordinator { @objc private func injected(_ notification: Notification) { guard didInject(self, notification: notification) else { return } withAnimation(.easeInOut(duration: 0.2)) { - render(contentSelectionManager.selections, - groupIds: groupSelectionManager.selections, + render(workflowsSelection.selections, + groupIds: groupSelection.selections, animation: .default) } } diff --git a/App/Sources/UI/Reducers/ContentViewActionReducer.swift b/App/Sources/UI/Reducers/GroupDetailViewActionReducer.swift similarity index 93% rename from App/Sources/UI/Reducers/ContentViewActionReducer.swift rename to App/Sources/UI/Reducers/GroupDetailViewActionReducer.swift index 7890dbf40..efbf6a9e1 100644 --- a/App/Sources/UI/Reducers/ContentViewActionReducer.swift +++ b/App/Sources/UI/Reducers/GroupDetailViewActionReducer.swift @@ -1,10 +1,10 @@ import Foundation -final class ContentViewActionReducer { +final class GroupDetailViewActionReducer { @MainActor - static func reduce(_ action: ContentView.Action, + static func reduce(_ action: GroupDetailView.Action, groupStore: GroupStore, - selectionManager: SelectionManager, + selectionManager: SelectionManager, group: inout WorkflowGroup) { switch action { case .refresh, .selectWorkflow: diff --git a/App/Sources/UI/Views/AddButtonView.swift b/App/Sources/UI/Views/AddButtonView.swift deleted file mode 100644 index ceb4556e1..000000000 --- a/App/Sources/UI/Views/AddButtonView.swift +++ /dev/null @@ -1,53 +0,0 @@ -import SwiftUI - -struct AddButtonView: View { - @State private var isHovered = false - - let text: String - let action: () -> Void - let hoverEffectIsEnabled: Bool - - init(_ text: String, - hoverEffectIsEnabled: Bool = true, - action: @escaping () -> Void) { - self.text = text - self.action = action - self.hoverEffectIsEnabled = hoverEffectIsEnabled - _isHovered = .init(initialValue: hoverEffectIsEnabled ? false : true) - } - - var body: some View { - Button(action: action) { - HStack(spacing: 2) { - Image(systemName: "plus.circle") - .padding(2) - .background( - ZStack { - RoundedRectangle(cornerRadius: 16) - .fill( - LinearGradient(stops: [ - .init(color: Color(.systemGreen), location: 0.0), - .init(color: Color(.systemGreen.blended(withFraction: 0.5, of: .black)!), location: 1.0), - ], startPoint: .top, endPoint: .bottom) - ) - .opacity(isHovered ? 1.0 : 0.3) - RoundedRectangle(cornerRadius: 16) - .stroke(Color(.systemGreen)) - .opacity(isHovered ? 0.4 : 0.1) - } - ) - .grayscale(isHovered ? 0 : 1) - .foregroundColor( - Color(.labelColor) - ) - .animation(.easeOut(duration: 0.2), value: isHovered) - Text(text) - } - } - .buttonStyle(.plain) - .onHover(perform: { value in - guard hoverEffectIsEnabled else { return } - self.isHovered = value - }) - } -} diff --git a/App/Sources/UI/Views/AppLoadingView.swift b/App/Sources/UI/Views/AppLoadingView.swift deleted file mode 100644 index 265881484..000000000 --- a/App/Sources/UI/Views/AppLoadingView.swift +++ /dev/null @@ -1,30 +0,0 @@ -import SwiftUI - -struct AppLoadingView: View { - private let namespace: Namespace.ID - @State var done: Bool = false - - init(namespace: Namespace.ID) { - self.namespace = namespace - } - - var body: some View { - VStack { - KeyboardCowboyAsset.applicationIcon.swiftUIImage - .resizable() - .frame(width: 64, height: 64) - .matchedGeometryEffect(id: "initial-item", in: namespace) - Text("Loading ...") - } - .padding() - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(SplashView(done: $done)) - } -} - -struct AppLoadingView_Previews: PreviewProvider { - @Namespace static var namespace - static var previews: some View { - AppLoadingView(namespace: namespace) - } -} diff --git a/App/Sources/UI/Views/NumberTextField.swift b/App/Sources/UI/Views/Components/NumberTextField.swift similarity index 100% rename from App/Sources/UI/Views/NumberTextField.swift rename to App/Sources/UI/Views/Components/NumberTextField.swift diff --git a/App/Sources/UI/Views/ConfigurationContainerView.swift b/App/Sources/UI/Views/Configuration/ConfigurationContainerView.swift similarity index 73% rename from App/Sources/UI/Views/ConfigurationContainerView.swift rename to App/Sources/UI/Views/Configuration/ConfigurationContainerView.swift index 27f0ec1d5..88c6e56d0 100644 --- a/App/Sources/UI/Views/ConfigurationContainerView.swift +++ b/App/Sources/UI/Views/Configuration/ConfigurationContainerView.swift @@ -1,19 +1,19 @@ import SwiftUI struct ConfigurationContainerView: View { - private let configSelectionManager: SelectionManager + private let configSelection: SelectionManager private let onAction: (SidebarView.Action) -> Void - init(configSelectionManager: SelectionManager, + init(configSelection: SelectionManager, onAction: @escaping (SidebarView.Action) -> Void) { - self.configSelectionManager = configSelectionManager + self.configSelection = configSelection self.onAction = onAction } var body: some View { ConfigurationHeaderView() .padding(.horizontal, 12) - ConfigurationView(configSelectionManager) { action in + ConfigurationView(configSelection) { action in switch action { case .deleteConfiguration(let id): onAction(.deleteConfiguration(id: id)) diff --git a/App/Sources/UI/Views/ConfigurationHeaderView.swift b/App/Sources/UI/Views/Configuration/ConfigurationHeaderView.swift similarity index 100% rename from App/Sources/UI/Views/ConfigurationHeaderView.swift rename to App/Sources/UI/Views/Configuration/ConfigurationHeaderView.swift diff --git a/App/Sources/UI/Views/ConfigurationView.swift b/App/Sources/UI/Views/Configuration/ConfigurationView.swift similarity index 100% rename from App/Sources/UI/Views/ConfigurationView.swift rename to App/Sources/UI/Views/Configuration/ConfigurationView.swift diff --git a/App/Sources/UI/Views/ContainerView.swift b/App/Sources/UI/Views/ContainerView.swift index 63c7151f8..17e694f01 100644 --- a/App/Sources/UI/Views/ContainerView.swift +++ b/App/Sources/UI/Views/ContainerView.swift @@ -6,7 +6,7 @@ struct ContainerView: View { enum Action { case openScene(AppScene) case sidebar(SidebarView.Action) - case content(ContentView.Action) + case content(GroupDetailView.Action) } @ObserveInjection var inject @@ -15,13 +15,13 @@ struct ContainerView: View { @Binding private var contentState: ContentStore.State private let onAction: (Action, UndoManager?) -> Void - private let applicationTriggerSelectionManager: SelectionManager - private let commandSelectionManager: SelectionManager - private let configSelectionManager: SelectionManager - private let contentSelectionManager: SelectionManager - private let groupsSelectionManager: SelectionManager - private let keyboardShortcutSelectionManager: SelectionManager - private let publisher: ContentPublisher + private let applicationTriggerSelection: SelectionManager + private let commandSelection: SelectionManager + private let configSelection: SelectionManager + private let contentSelection: SelectionManager + private let groupsSelection: SelectionManager + private let keyboardShortcutSelection: SelectionManager + private let publisher: GroupDetailPublisher private let triggerPublisher: TriggerPublisher private let infoPublisher: InfoPublisher private let commandPublisher: CommandsPublisher @@ -32,13 +32,13 @@ struct ContainerView: View { init(_ focus: FocusState.Binding, contentState: Binding, detailUpdateTransaction: UpdateTransaction, - publisher: ContentPublisher, - applicationTriggerSelectionManager: SelectionManager, - commandSelectionManager: SelectionManager, - configSelectionManager: SelectionManager, - contentSelectionManager: SelectionManager, - groupsSelectionManager: SelectionManager, - keyboardShortcutSelectionManager: SelectionManager, + publisher: GroupDetailPublisher, + applicationTriggerSelection: SelectionManager, + commandSelection: SelectionManager, + configSelection: SelectionManager, + contentSelection: SelectionManager, + groupsSelection: SelectionManager, + keyboardShortcutSelection: SelectionManager, triggerPublisher: TriggerPublisher, infoPublisher: InfoPublisher, commandPublisher: CommandsPublisher, @@ -46,12 +46,12 @@ struct ContainerView: View { _contentState = contentState self.focus = focus self.publisher = publisher - self.applicationTriggerSelectionManager = applicationTriggerSelectionManager - self.commandSelectionManager = commandSelectionManager - self.configSelectionManager = configSelectionManager - self.contentSelectionManager = contentSelectionManager - self.groupsSelectionManager = groupsSelectionManager - self.keyboardShortcutSelectionManager = keyboardShortcutSelectionManager + self.applicationTriggerSelection = applicationTriggerSelection + self.commandSelection = commandSelection + self.configSelection = configSelection + self.contentSelection = contentSelection + self.groupsSelection = groupsSelection + self.keyboardShortcutSelection = keyboardShortcutSelection self.triggerPublisher = triggerPublisher self.infoPublisher = infoPublisher self.commandPublisher = commandPublisher @@ -65,22 +65,22 @@ struct ContainerView: View { sidebar: { SidebarView( focus, - configSelectionManager: configSelectionManager, - groupSelectionManager: groupsSelectionManager, - contentSelectionManager: contentSelectionManager, + configSelection: configSelection, + groupSelection: groupsSelection, + workflowSelection: contentSelection, onAction: { onAction(.sidebar($0), undoManager) }) .onChange(of: contentState, perform: { newValue in guard newValue == .initialized else { return } - guard let groupId = groupsSelectionManager.lastSelection else { return } + guard let groupId = groupsSelection.lastSelection else { return } onAction(.sidebar(.selectGroups([groupId])), undoManager) }) .navigationSplitViewColumnWidth(ideal: 250) }, content: { - ContentView( + GroupDetailView( focus, - groupId: groupsSelectionManager.lastSelection ?? groupsSelectionManager.selections.first ?? "empty", - contentSelectionManager: contentSelectionManager, + groupId: groupsSelection.lastSelection ?? groupsSelection.selections.first ?? "empty", + workflowSelection: contentSelection, onAction: { onAction(.content($0), undoManager) @@ -93,9 +93,9 @@ struct ContainerView: View { detail: { DetailView( focus, - applicationTriggerSelectionManager: applicationTriggerSelectionManager, - commandSelectionManager: commandSelectionManager, - keyboardShortcutSelectionManager: keyboardShortcutSelectionManager, + applicationTriggerSelection: applicationTriggerSelection, + commandSelection: commandSelection, + keyboardShortcutSelection: keyboardShortcutSelection, triggerPublisher: triggerPublisher, infoPublisher: infoPublisher, commandPublisher: commandPublisher) @@ -117,12 +117,12 @@ struct ContainerView_Previews: PreviewProvider { contentState: .readonly(.initialized), detailUpdateTransaction: .init(groupID: "", workflowID: ""), publisher: DesignTime.contentPublisher, - applicationTriggerSelectionManager: .init(), - commandSelectionManager: .init(), - configSelectionManager: .init(), - contentSelectionManager: .init(), - groupsSelectionManager: .init(), - keyboardShortcutSelectionManager: .init(), + applicationTriggerSelection: .init(), + commandSelection: .init(), + configSelection: .init(), + contentSelection: .init(), + groupsSelection: .init(), + keyboardShortcutSelection: .init(), triggerPublisher: DesignTime.triggerPublisher, infoPublisher: DesignTime.infoPublisher, commandPublisher: DesignTime.commandsPublisher diff --git a/App/Sources/UI/Views/ContentKeyboardImageView.swift b/App/Sources/UI/Views/ContentKeyboardImageView.swift deleted file mode 100644 index c4169bfce..000000000 --- a/App/Sources/UI/Views/ContentKeyboardImageView.swift +++ /dev/null @@ -1,24 +0,0 @@ -import SwiftUI - -struct ContentKeyboardImageView: View { - let keys: [KeyShortcut] - var body: some View { - ZStack { - ForEach(keys) { key in - RegularKeyIcon(letter: key.key, width: 22, height: 22) - .fixedSize() - } - } - } -} - -struct ContentKeyboardImageView_Previews: PreviewProvider { - static var previews: some View { - ContentKeyboardImageView(keys: [ - .init(key: "", modifiers: [.command]), - .init(key: "C", modifiers: []), - ]) - .frame(minWidth: 200, minHeight: 120) - .padding() - } -} diff --git a/App/Sources/UI/Views/ContentTypeImageView.swift b/App/Sources/UI/Views/ContentTypeImageView.swift deleted file mode 100644 index 8a9a35d50..000000000 --- a/App/Sources/UI/Views/ContentTypeImageView.swift +++ /dev/null @@ -1,18 +0,0 @@ -import SwiftUI - -struct ContentTypeImageView: View { - var body: some View { - RegularKeyIcon(letter: "(...)", width: 22, height: 22) - .fixedSize() - } -} - -struct ContentTypeImageView_Previews: PreviewProvider { - static var previews: some View { - Group { - ContentTypeImageView() - } - .frame(minWidth: 200, minHeight: 120) - .padding() - } -} diff --git a/App/Sources/UI/Views/DesignTime/DesignTimePublishers.swift b/App/Sources/UI/Views/DesignTime/DesignTimePublishers.swift index bd43e0c55..a945f12e4 100644 --- a/App/Sources/UI/Views/DesignTime/DesignTimePublishers.swift +++ b/App/Sources/UI/Views/DesignTime/DesignTimePublishers.swift @@ -51,86 +51,86 @@ enum DesignTime { Self.typeCommand.model ], execution: .concurrent)) - static var contentPublisher = ContentPublisher { + static var contentPublisher = GroupDetailPublisher { [ - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Application Trigger", images: [], overlayImages: [], badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open News", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/News.app", path: "/System/Applications/News.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Application Trigger", images: [], overlayImages: [], badge: 0, badgeOpacity: 0, isEnabled: true), + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open News", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/News.app", path: "/System/Applications/News.app"))) ], overlayImages: [], trigger: .keyboard("ƒSpace"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Podcast", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Podcasts.app", path: "/System/Applications/Podcasts.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Podcast", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Podcasts.app", path: "/System/Applications/Podcasts.app"))) ], overlayImages: [], trigger: .keyboard("ƒU"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Music", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Music.app", path: "/System/Applications/Music.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Music", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Music.app", path: "/System/Applications/Music.app"))) ], overlayImages: [], trigger: .keyboard("ƒY"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Home", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Home.app", path: "/System/Applications/Home.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Home", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Home.app", path: "/System/Applications/Home.app"))) ], overlayImages: [], trigger: .keyboard("ƒH"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Twitterific", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Twitterrific.app", path: "/Applications/Twitterrific.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Twitterific", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Twitterrific.app", path: "/Applications/Twitterrific.app"))) ], overlayImages: [], trigger: .keyboard("ƒT"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open System Settings", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/System Settings.app", path: "/System/Applications/System Settings.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open System Settings", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/System Settings.app", path: "/System/Applications/System Settings.app"))) ], overlayImages: [], trigger: .keyboard("ƒ."), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Contacts", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Contacts.app", path: "/System/Applications/Contacts.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Contacts", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Contacts.app", path: "/System/Applications/Contacts.app"))) ], overlayImages: [], trigger: .keyboard("ƒA"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Terminal", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Utilities/Terminal.app", path: "/System/Applications/Utilities/Terminal.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Terminal", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Utilities/Terminal.app", path: "/System/Applications/Utilities/Terminal.app"))) ], overlayImages: [], trigger: .keyboard("ƒ§"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Discord", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Discord.app", path: "/Applications/Discord.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Discord", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Discord.app", path: "/Applications/Discord.app"))) ], overlayImages: [], trigger: .keyboard("ƒD"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Preview", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Preview.app", path: "/System/Applications/Preview.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Preview", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Preview.app", path: "/System/Applications/Preview.app"))) ], overlayImages: [], trigger: .keyboard("ƒP"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Teams", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Microsoft Teams.app", path: "/Applications/Microsoft Teams.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Teams", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Microsoft Teams.app", path: "/Applications/Microsoft Teams.app"))) ], overlayImages: [], trigger: .keyboard("ƒG"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Slack", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Slack.app", path: "/Applications/Slack.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Slack", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Slack.app", path: "/Applications/Slack.app"))) ], overlayImages: [], trigger: .keyboard("ƒV"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Find My", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/FindMy.app", path: "/System/Applications/FindMy.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Find My", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/FindMy.app", path: "/System/Applications/FindMy.app"))) ], overlayImages: [], trigger: .keyboard("ƒB"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Messages", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Messages.app", path: "/System/Applications/Messages.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Messages", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Messages.app", path: "/System/Applications/Messages.app"))) ], overlayImages: [], trigger: .keyboard("ƒD"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Mail", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Mail.app", path: "/System/Applications/Mail.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Mail", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Mail.app", path: "/System/Applications/Mail.app"))) ], overlayImages: [], trigger: .keyboard("ƒM"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Calendar", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Calendar.app", path: "/System/Applications/Calendar.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Calendar", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Calendar.app", path: "/System/Applications/Calendar.app"))) ], overlayImages: [], trigger: .keyboard("ƒC"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Reminders", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Reminders.app", path: "/System/Applications/Reminders.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Reminders", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Reminders.app", path: "/System/Applications/Reminders.app"))) ], overlayImages: [], trigger: .keyboard("ƒR"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Notes", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Notes.app", path: "/System/Applications/Notes.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Notes", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Notes.app", path: "/System/Applications/Notes.app"))) ], overlayImages: [], trigger: .keyboard("ƒN"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Finder", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Library/CoreServices/Finder.app", path: "/System/Library/CoreServices/Finder.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Finder", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Library/CoreServices/Finder.app", path: "/System/Library/CoreServices/Finder.app"))) ], overlayImages: [], trigger: .keyboard("ƒF"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Photos", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Photos.app", path: "/System/Applications/Photos.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Photos", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Photos.app", path: "/System/Applications/Photos.app"))) ], overlayImages: [], trigger: .keyboard("ƒI"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Stocks", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Stocks.app", path: "/System/Applications/Stocks.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Stocks", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Stocks.app", path: "/System/Applications/Stocks.app"))) ], overlayImages: [], trigger: .keyboard("ƒS"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Keyboard Cowboy", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Keyboard Cowboy.app", path: "/Applications/Keyboard Cowboy.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Keyboard Cowboy", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/Applications/Keyboard Cowboy.app", path: "/Applications/Keyboard Cowboy.app"))) ], overlayImages: [], trigger: .keyboard("⌥ƒ0"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Numbers", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Numbers.app", path: "/System/Applications/Numbers.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Numbers", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Numbers.app", path: "/System/Applications/Numbers.app"))) ], overlayImages: [], trigger: .keyboard("⌥ƒN"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Pages", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Pages.app", path: "/System/Applications/Pages.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Pages", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Pages.app", path: "/System/Applications/Pages.app"))) ], overlayImages: [], trigger: .keyboard("⌥ƒP"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Keynote", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Keynote.app", path: "/System/Applications/Keynote.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Keynote", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Keynote.app", path: "/System/Applications/Keynote.app"))) ], overlayImages: [], trigger: .keyboard("⌥ƒK"), badge: 0, badgeOpacity: 0, isEnabled: true), - ContentViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Quick Run", images: [ - ContentViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Stocks.app", path: "/System/Applications/Stocks.app"))) + GroupDetailViewModel(id: UUID().uuidString, groupId: UUID().uuidString, name: "Open Quick Run", images: [ + GroupDetailViewModel.ImageModel(id: UUID().uuidString, offset: 0, kind: .icon(.init(bundleIdentifier: "/System/Applications/Stocks.app", path: "/System/Applications/Stocks.app"))) ], overlayImages: [], trigger: .keyboard("ƒK"), badge: 0, badgeOpacity: 0, isEnabled: true), ] } diff --git a/App/Sources/UI/Views/Groups/ColorPalette.swift b/App/Sources/UI/Views/EditGroup/ColorPalette.swift similarity index 100% rename from App/Sources/UI/Views/Groups/ColorPalette.swift rename to App/Sources/UI/Views/EditGroup/ColorPalette.swift diff --git a/App/Sources/UI/Views/Groups/EditConfigurationView.swift b/App/Sources/UI/Views/EditGroup/EditConfigurationView.swift similarity index 100% rename from App/Sources/UI/Views/Groups/EditConfigurationView.swift rename to App/Sources/UI/Views/EditGroup/EditConfigurationView.swift diff --git a/App/Sources/UI/Views/Groups/EditGroupIconView.swift b/App/Sources/UI/Views/EditGroup/EditGroupIconView.swift similarity index 100% rename from App/Sources/UI/Views/Groups/EditGroupIconView.swift rename to App/Sources/UI/Views/EditGroup/EditGroupIconView.swift diff --git a/App/Sources/UI/Views/Groups/EditWorfklowGroupView.swift b/App/Sources/UI/Views/EditGroup/EditWorfklowGroupView.swift similarity index 100% rename from App/Sources/UI/Views/Groups/EditWorfklowGroupView.swift rename to App/Sources/UI/Views/EditGroup/EditWorfklowGroupView.swift diff --git a/App/Sources/UI/Views/Groups/RuleHeaderView.swift b/App/Sources/UI/Views/EditGroup/RuleHeaderView.swift similarity index 100% rename from App/Sources/UI/Views/Groups/RuleHeaderView.swift rename to App/Sources/UI/Views/EditGroup/RuleHeaderView.swift diff --git a/App/Sources/UI/Views/Groups/RuleListView.swift b/App/Sources/UI/Views/EditGroup/RuleListView.swift similarity index 100% rename from App/Sources/UI/Views/Groups/RuleListView.swift rename to App/Sources/UI/Views/EditGroup/RuleListView.swift diff --git a/App/Sources/UI/Views/Groups/SymbolPalette.swift b/App/Sources/UI/Views/EditGroup/SymbolPalette.swift similarity index 100% rename from App/Sources/UI/Views/Groups/SymbolPalette.swift rename to App/Sources/UI/Views/EditGroup/SymbolPalette.swift diff --git a/App/Sources/UI/Views/Groups/WorkflowGroupIconView.swift b/App/Sources/UI/Views/EditGroup/WorkflowGroupIconView.swift similarity index 100% rename from App/Sources/UI/Views/Groups/WorkflowGroupIconView.swift rename to App/Sources/UI/Views/EditGroup/WorkflowGroupIconView.swift diff --git a/App/Sources/UI/Views/ContentAddWorkflowHeaderView.swift b/App/Sources/UI/Views/GroupDetail/GroupDetailAddButton.swift similarity index 84% rename from App/Sources/UI/Views/ContentAddWorkflowHeaderView.swift rename to App/Sources/UI/Views/GroupDetail/GroupDetailAddButton.swift index 8d401ac25..82dc3d4d9 100644 --- a/App/Sources/UI/Views/ContentAddWorkflowHeaderView.swift +++ b/App/Sources/UI/Views/GroupDetail/GroupDetailAddButton.swift @@ -1,8 +1,8 @@ import SwiftUI import Bonzai -struct ContentAddWorkflowHeaderView: View { - @EnvironmentObject private var contentPublisher: ContentPublisher +struct GroupDetailAddButton: View { + @EnvironmentObject private var contentPublisher: GroupDetailPublisher @Binding var isVisible: Bool private let namespace: Namespace.ID @@ -35,7 +35,7 @@ struct ContentAddWorkflowHeaderView: View { struct ContentAddWorkflowHeaderView_Previews: PreviewProvider { @Namespace static var namespace static var previews: some View { - ContentAddWorkflowHeaderView(namespace, isVisible: .constant(true)) {} + GroupDetailAddButton(namespace, isVisible: .constant(true)) {} .designTime() .padding(.all) } diff --git a/App/Sources/UI/Views/ContentHeaderView.swift b/App/Sources/UI/Views/GroupDetail/GroupDetailHeaderView.swift similarity index 81% rename from App/Sources/UI/Views/ContentHeaderView.swift rename to App/Sources/UI/Views/GroupDetail/GroupDetailHeaderView.swift index c0670735a..ee68f9f0d 100644 --- a/App/Sources/UI/Views/ContentHeaderView.swift +++ b/App/Sources/UI/Views/GroupDetail/GroupDetailHeaderView.swift @@ -1,17 +1,17 @@ import Bonzai import SwiftUI -struct ContentHeaderView: View { - @EnvironmentObject private var contentPublisher: ContentPublisher +struct GroupDetailHeaderView: View { + @EnvironmentObject private var groupDetailPublisher: GroupDetailPublisher @EnvironmentObject private var groupPublisher: GroupPublisher @Binding private var showAddButton: Bool private let namespace: Namespace.ID - private let onAction: (ContentView.Action) -> Void + private let onAction: (GroupDetailView.Action) -> Void init(namespace: Namespace.ID, showAddButton: Binding, - onAction: @escaping (ContentView.Action) -> Void) { + onAction: @escaping (GroupDetailView.Action) -> Void) { _showAddButton = showAddButton self.namespace = namespace self.onAction = onAction @@ -33,12 +33,12 @@ struct ContentHeaderView: View { VStack(alignment: .leading) { Text(groupPublisher.data.name) .font(.headline) - Text("Workflows: \(contentPublisher.data.count)") + Text("Workflows: \(groupDetailPublisher.data.count)") .font(.caption) } .frame(maxWidth: .infinity, alignment: .leading) - ContentAddWorkflowHeaderView( + GroupDetailAddButton( namespace, isVisible: $showAddButton, onAction: { onAction(.addWorkflow(workflowId: UUID().uuidString)) }) diff --git a/App/Sources/UI/Views/ContentView.swift b/App/Sources/UI/Views/GroupDetail/GroupDetailView.swift similarity index 77% rename from App/Sources/UI/Views/ContentView.swift rename to App/Sources/UI/Views/GroupDetail/GroupDetailView.swift index fbcb715ef..8d2d77414 100644 --- a/App/Sources/UI/Views/ContentView.swift +++ b/App/Sources/UI/Views/GroupDetail/GroupDetailView.swift @@ -4,11 +4,11 @@ import Inject import SwiftUI struct ContentDebounce: DebounceSnapshot { - let workflows: Set + let workflows: Set } @MainActor -struct ContentView: View { +struct GroupDetailView: View { enum Match { case unmatched case typeMatch(Kind) @@ -34,43 +34,43 @@ struct ContentView: View { } enum Action: Hashable { - case duplicate(workflowIds: Set) + case duplicate(workflowIds: Set) case refresh(_ groupIds: Set) - case moveWorkflowsToGroup(_ groupId: WorkflowGroup.ID, workflows: Set) - case moveCommandsToWorkflow(_ workflowId: ContentViewModel.ID, fromWorkflowId: ContentViewModel.ID, commands: Set) - case selectWorkflow(workflowIds: Set) - case removeWorkflows(Set) + case moveWorkflowsToGroup(_ groupId: WorkflowGroup.ID, workflows: Set) + case moveCommandsToWorkflow(_ workflowId: GroupDetailViewModel.ID, fromWorkflowId: GroupDetailViewModel.ID, commands: Set) + case selectWorkflow(workflowIds: Set) + case removeWorkflows(Set) case reorderWorkflows(source: IndexSet, destination: Int) case addWorkflow(workflowId: Workflow.ID) } @ObserveInjection var inject - @FocusState var focus: LocalFocus? + @FocusState var focus: LocalFocus? @EnvironmentObject private var groupsPublisher: GroupsPublisher - @EnvironmentObject private var publisher: ContentPublisher + @EnvironmentObject private var publisher: GroupDetailPublisher @Namespace private var namespace @State private var searchTerm: String = "" private let appFocus: FocusState.Binding - private let contentSelectionManager: SelectionManager + private let workflowSelection: SelectionManager private let groupId: String private let debounce: DebounceController private let onAction: (Action) -> Void init(_ appFocus: FocusState.Binding, groupId: String, - contentSelectionManager: SelectionManager, + workflowSelection: SelectionManager, onAction: @escaping (Action) -> Void) { self.appFocus = appFocus - self.contentSelectionManager = contentSelectionManager + self.workflowSelection = workflowSelection self.groupId = groupId self.onAction = onAction - let initialDebounce = ContentDebounce(workflows: contentSelectionManager.selections) + let initialDebounce = ContentDebounce(workflows: workflowSelection.selections) self.debounce = .init(initialDebounce, milliseconds: 150, onUpdate: { snapshot in onAction(.selectWorkflow(workflowIds: snapshot.workflows)) }) } - private func search(_ workflow: ContentViewModel) -> Bool { + private func search(_ workflow: GroupDetailViewModel) -> Bool { guard !searchTerm.isEmpty else { return true } var freetext = searchTerm.lowercased() @@ -154,12 +154,12 @@ struct ContentView: View { @ViewBuilder var body: some View { ScrollViewReader { proxy in - ContentHeaderView(namespace: namespace, - showAddButton: .readonly(!publisher.data.isEmpty), - onAction: onAction) + GroupDetailHeaderView(namespace: namespace, + showAddButton: .readonly(!publisher.data.isEmpty), + onAction: onAction) - ContentListFilterView(appFocus, onClear: { - let match = contentSelectionManager.lastSelection ?? contentSelectionManager.selections.first ?? "" + WorkflowsFilterView(appFocus, onClear: { + let match = workflowSelection.lastSelection ?? workflowSelection.selections.first ?? "" appFocus.wrappedValue = .workflows DispatchQueue.main.async { proxy.scrollTo(match) @@ -179,17 +179,17 @@ struct ContentView: View { } if publisher.data.isEmpty { - ContentListEmptyView(namespace, onAction: onAction) + EmptyWorkflowList(namespace, onAction: onAction) .frame(maxHeight: .infinity) .toolbar(content: { toolbarContent() }) } else { CompatList { let items = publisher.data.filter({ search($0) }) ForEach(items.lazy, id: \.id) { element in - ContentItemView( + WorkflowView( workflow: element, publisher: publisher, - contentSelectionManager: contentSelectionManager, + contentSelectionManager: workflowSelection, onAction: onAction ) .modifier(LegacyOnTapFix(onTap: { @@ -201,7 +201,7 @@ struct ContentView: View { }) .focusable($focus, as: .element(element.id)) { if let keyCode = LocalEventMonitor.shared.event?.keyCode, keyCode == kVK_Tab, - let lastSelection = contentSelectionManager.lastSelection, + let lastSelection = workflowSelection.lastSelection, let match = publisher.data.first(where: { $0.id == lastSelection }) { focus = .element(match.id) } else { @@ -210,7 +210,7 @@ struct ContentView: View { } } } - .dropDestination(for: ContentViewModel.self, action: { collection, destination in + .dropDestination(for: GroupDetailViewModel.self, action: { collection, destination in var indexSet = IndexSet() for item in collection { guard let index = publisher.data.firstIndex(of: item) else { continue } @@ -232,15 +232,15 @@ struct ContentView: View { .onCommand(#selector(NSResponder.selectAll(_:)), perform: { let newSelections = Set(publisher.data.map(\.id)) - contentSelectionManager.publish(newSelections) + workflowSelection.publish(newSelections) if let elementID = publisher.data.first?.id, - let lastSelection = contentSelectionManager.lastSelection { + let lastSelection = workflowSelection.lastSelection { focus = .element(elementID) focus = .element(lastSelection) } }) .onMoveCommand(perform: { direction in - if let elementID = contentSelectionManager.handle( + if let elementID = workflowSelection.handle( direction, publisher.data.filter({ search($0) }), proxy: proxy, @@ -249,13 +249,13 @@ struct ContentView: View { } }) .onDeleteCommand { - if contentSelectionManager.selections.count == publisher.data.count { + if workflowSelection.selections.count == publisher.data.count { withAnimation { - onAction(.removeWorkflows(contentSelectionManager.selections)) + onAction(.removeWorkflows(workflowSelection.selections)) } } else { - onAction(.removeWorkflows(contentSelectionManager.selections)) - if let first = contentSelectionManager.selections.first { + onAction(.removeWorkflows(workflowSelection.selections)) + if let first = workflowSelection.selections.first { let index = max(publisher.data.firstIndex(where: { $0.id == first }) ?? 0, 0) let newId = publisher.data[index].id focus = .element(newId) @@ -275,7 +275,7 @@ struct ContentView: View { .padding(.bottom, 24) } - .onChange(of: contentSelectionManager.selections) { newValue in + .onChange(of: workflowSelection.selections) { newValue in let ids = Set(publisher.data.map(\.id)) let newIds = Set(newValue) let result = ids.intersection(newIds) @@ -284,7 +284,7 @@ struct ContentView: View { } } .onAppear { - guard let initialSelection = contentSelectionManager.initialSelection else { return } + guard let initialSelection = workflowSelection.initialSelection else { return } focus = .element(initialSelection) proxy.scrollTo(initialSelection) } @@ -292,12 +292,12 @@ struct ContentView: View { .onChange(of: searchTerm, perform: { newValue in if !searchTerm.isEmpty { if let firstSelection = publisher.data.filter({ search($0) }).first { - contentSelectionManager.publish([firstSelection.id]) + workflowSelection.publish([firstSelection.id]) } else { - contentSelectionManager.publish([]) + workflowSelection.publish([]) } - debounce.process(.init(workflows: contentSelectionManager.selections)) + debounce.process(.init(workflows: workflowSelection.selections)) } }) .toolbar(content: { toolbarContent() }) @@ -328,24 +328,24 @@ struct ContentView: View { } } - private func onTap(_ element: ContentViewModel) { - contentSelectionManager.handleOnTap(publisher.data, element: element) - debounce.process(.init(workflows: contentSelectionManager.selections)) + private func onTap(_ element: GroupDetailViewModel) { + workflowSelection.handleOnTap(publisher.data, element: element) + debounce.process(.init(workflows: workflowSelection.selections)) } @ViewBuilder - private func contextualMenu(_ selectedId: ContentViewModel.ID) -> some View { + private func contextualMenu(_ selectedId: GroupDetailViewModel.ID) -> some View { Button("Duplicate", action: { - if contentSelectionManager.selections.contains(selectedId) { - onAction(.duplicate(workflowIds: contentSelectionManager.selections)) + if workflowSelection.selections.contains(selectedId) { + onAction(.duplicate(workflowIds: workflowSelection.selections)) } else { onAction(.duplicate(workflowIds: [selectedId])) } - contentSelectionManager.publish([selectedId]) - contentSelectionManager.setLastSelection(selectedId) + workflowSelection.publish([selectedId]) + workflowSelection.setLastSelection(selectedId) - if contentSelectionManager.selections.count == 1 { + if workflowSelection.selections.count == 1 { appFocus.wrappedValue = .detail(.name) } }) @@ -355,27 +355,26 @@ struct ContentView: View { // .filter({ !groupSelectionManager.selections.contains($0.id) })) { group in ForEach(groupsPublisher.data, id: \.self) { group in Button(group.name) { - onAction(.moveWorkflowsToGroup(group.id, workflows: contentSelectionManager.selections)) + onAction(.moveWorkflowsToGroup(group.id, workflows: workflowSelection.selections)) } } } Button("Delete", action: { - onAction(.removeWorkflows(contentSelectionManager.selections)) + onAction(.removeWorkflows(workflowSelection.selections)) }) } } -struct ContentListView_Previews: PreviewProvider { +struct WorkflowsView_Previews: PreviewProvider { @FocusState static var focus: AppFocus? static var previews: some View { - ContentView($focus, groupId: UUID().uuidString, - contentSelectionManager: .init()) { _ in } + GroupDetailView($focus, groupId: UUID().uuidString, workflowSelection: .init()) { _ in } .designTime() } } fileprivate extension CommandViewModel.Kind { - var match: ContentView.Match.Kind { + var match: GroupDetailView.Match.Kind { switch self { case .application: .application case .builtIn: .builtIn @@ -383,7 +382,6 @@ fileprivate extension CommandViewModel.Kind { case .open: .open case .keyboard: .keyboard case .script: .script - case .plain: .plain case .shortcut: .shortcut case .text: .text case .systemCommand: .systemCommand diff --git a/App/Sources/UI/Views/ContentItemBadgeOverlayView.swift b/App/Sources/UI/Views/GroupDetail/WorkflowBadge.swift similarity index 94% rename from App/Sources/UI/Views/ContentItemBadgeOverlayView.swift rename to App/Sources/UI/Views/GroupDetail/WorkflowBadge.swift index 7639bcfbf..a94835292 100644 --- a/App/Sources/UI/Views/ContentItemBadgeOverlayView.swift +++ b/App/Sources/UI/Views/GroupDetail/WorkflowBadge.swift @@ -1,6 +1,6 @@ import SwiftUI -struct ContentItemBadgeOverlayView: View { +struct WorkflowBadge: View { @Binding private var isHovered: Bool private let text: String private let badgeOpacity: Double diff --git a/App/Sources/UI/Views/ContentItemIsDisabledOverlayView.swift b/App/Sources/UI/Views/GroupDetail/WorkflowDisabledOverlay.swift similarity index 89% rename from App/Sources/UI/Views/ContentItemIsDisabledOverlayView.swift rename to App/Sources/UI/Views/GroupDetail/WorkflowDisabledOverlay.swift index 490e6832a..382977eee 100644 --- a/App/Sources/UI/Views/ContentItemIsDisabledOverlayView.swift +++ b/App/Sources/UI/Views/GroupDetail/WorkflowDisabledOverlay.swift @@ -1,6 +1,6 @@ import SwiftUI -struct ContentItemIsDisabledOverlayView: View { +struct WorkflowDisabledOverlay: View { private let isEnabled: Bool init(isEnabled: Bool) { diff --git a/App/Sources/UI/Views/ContentImageView.swift b/App/Sources/UI/Views/GroupDetail/WorkflowImage.swift similarity index 90% rename from App/Sources/UI/Views/ContentImageView.swift rename to App/Sources/UI/Views/GroupDetail/WorkflowImage.swift index d2638141a..f45ca3c81 100644 --- a/App/Sources/UI/Views/ContentImageView.swift +++ b/App/Sources/UI/Views/GroupDetail/WorkflowImage.swift @@ -1,8 +1,8 @@ import Bonzai import SwiftUI -struct ContentImageView: View { - let image: ContentViewModel.ImageModel +struct WorkflowImage: View { + let image: GroupDetailViewModel.ImageModel let size: CGFloat @Binding var stacked: Bool @@ -28,7 +28,7 @@ struct ContentImageView: View { case .plain: EmptyView() case .shortcut: - ContentShortcutImageView(size: iconSize) + WorkflowShortcutImage(size: iconSize) case .text: TypingIconView(size: iconSize) case .systemCommand(let kind): diff --git a/App/Sources/UI/Views/ContentImagesView.swift b/App/Sources/UI/Views/GroupDetail/WorkflowImages.swift similarity index 76% rename from App/Sources/UI/Views/ContentImagesView.swift rename to App/Sources/UI/Views/GroupDetail/WorkflowImages.swift index 7de5bf651..7b77244a0 100644 --- a/App/Sources/UI/Views/ContentImagesView.swift +++ b/App/Sources/UI/Views/GroupDetail/WorkflowImages.swift @@ -1,7 +1,7 @@ import SwiftUI -struct ContentImagesView: View { - let images: [ContentViewModel.ImageModel] +struct WorkflowImages: View { + let images: [GroupDetailViewModel.ImageModel] let size: CGFloat @State var stacked: Bool = false @@ -17,7 +17,7 @@ struct ContentImagesView: View { .opacity(images.isEmpty ? 0.5 : 0) ForEach(images) { image in - ContentImageView(image: image, size: size, stacked: $stacked) + WorkflowImage(image: image, size: size, stacked: $stacked) } } .frame(width: size, height: size) diff --git a/App/Sources/UI/Views/ContentShortcutImageView.swift b/App/Sources/UI/Views/GroupDetail/WorkflowShortcutImage.swift similarity index 67% rename from App/Sources/UI/Views/ContentShortcutImageView.swift rename to App/Sources/UI/Views/GroupDetail/WorkflowShortcutImage.swift index 485f18b85..931007bd1 100644 --- a/App/Sources/UI/Views/ContentShortcutImageView.swift +++ b/App/Sources/UI/Views/GroupDetail/WorkflowShortcutImage.swift @@ -1,7 +1,7 @@ import Bonzai import SwiftUI -struct ContentShortcutImageView: View { +struct WorkflowShortcutImage: View { let size: CGFloat var body: some View { @@ -15,12 +15,8 @@ struct ContentShortcutImageView: View { } } -struct ContentShortcutImageView_Previews: PreviewProvider { - static var previews: some View { - Group { - ContentShortcutImageView(size: 32) - } +#Preview { + WorkflowShortcutImage(size: 32) .frame(minWidth: 200, minHeight: 120) .padding() - } } diff --git a/App/Sources/UI/Views/ContentItemView.swift b/App/Sources/UI/Views/GroupDetail/WorkflowView.swift similarity index 75% rename from App/Sources/UI/Views/ContentItemView.swift rename to App/Sources/UI/Views/GroupDetail/WorkflowView.swift index 053d5b8fc..7908aa4fb 100644 --- a/App/Sources/UI/Views/ContentItemView.swift +++ b/App/Sources/UI/Views/GroupDetail/WorkflowView.swift @@ -1,16 +1,16 @@ import Bonzai import SwiftUI -struct ContentItemView: View { - private let contentSelectionManager: SelectionManager - private let publisher: ContentPublisher - private let workflow: ContentViewModel - private let onAction: (ContentView.Action) -> Void - - init(workflow: ContentViewModel, - publisher: ContentPublisher, - contentSelectionManager: SelectionManager, - onAction: @escaping (ContentView.Action) -> Void) { +struct WorkflowView: View { + private let contentSelectionManager: SelectionManager + private let publisher: GroupDetailPublisher + private let workflow: GroupDetailViewModel + private let onAction: (GroupDetailView.Action) -> Void + + init(workflow: GroupDetailViewModel, + publisher: GroupDetailPublisher, + contentSelectionManager: SelectionManager, + onAction: @escaping (GroupDetailView.Action) -> Void) { self.contentSelectionManager = contentSelectionManager self.workflow = workflow self.publisher = publisher @@ -31,15 +31,15 @@ private struct ContentItemInternalView: View { @State private var isHovered: Bool = false @State private var isSelected: Bool = false - private let contentSelectionManager: SelectionManager - private let publisher: ContentPublisher - private let workflow: ContentViewModel - private let onAction: (ContentView.Action) -> Void + private let contentSelectionManager: SelectionManager + private let publisher: GroupDetailPublisher + private let workflow: GroupDetailViewModel + private let onAction: (GroupDetailView.Action) -> Void - init(workflow: ContentViewModel, - publisher: ContentPublisher, - contentSelectionManager: SelectionManager, - onAction: @escaping (ContentView.Action) -> Void) { + init(workflow: GroupDetailViewModel, + publisher: GroupDetailPublisher, + contentSelectionManager: SelectionManager, + onAction: @escaping (GroupDetailView.Action) -> Void) { self.contentSelectionManager = contentSelectionManager self.workflow = workflow self.publisher = publisher @@ -48,16 +48,16 @@ private struct ContentItemInternalView: View { var body: some View { HStack { - ContentImagesView(images: workflow.images, size: 32) + WorkflowImages(images: workflow.images, size: 32) .background( Color.black.opacity(0.3).cornerRadius(8, antialiased: false) ) .overlay(alignment: .bottomTrailing, content: { - ContentItemIsDisabledOverlayView(isEnabled: workflow.isEnabled) + WorkflowDisabledOverlay(isEnabled: workflow.isEnabled) }) .overlay(alignment: .topTrailing, content: { - ContentItemBadgeOverlayView(isHovered: $isHovered, + WorkflowBadge(isHovered: $isHovered, text: "\(workflow.badge)", badgeOpacity: workflow.badgeOpacity) .offset(x: 4, y: 0) @@ -87,7 +87,7 @@ private struct ContentItemInternalView: View { } private struct ContentExecutionView: View { - let execution: ContentViewModel.Execution + let execution: GroupDetailViewModel.Execution var body: some View { Group { switch execution { @@ -126,7 +126,7 @@ struct ItemBackgroundView: View where T.ID == String } private struct ContentItemAccessoryView: View { - let workflow: ContentViewModel + let workflow: GroupDetailViewModel @ViewBuilder var body: some View { @@ -162,10 +162,10 @@ private struct ContentItemAccessoryView: View { #Preview { ForEach(DesignTime.contentPublisher.data) { workflow in - ContentItemView( + WorkflowView( workflow: workflow, publisher: DesignTime.contentPublisher, - contentSelectionManager: SelectionManager() + contentSelectionManager: SelectionManager() ) { _ in } } diff --git a/App/Sources/UI/Views/ContentListFilterView.swift b/App/Sources/UI/Views/GroupDetail/WorkflowsFilterView.swift similarity index 93% rename from App/Sources/UI/Views/ContentListFilterView.swift rename to App/Sources/UI/Views/GroupDetail/WorkflowsFilterView.swift index 48a8fcef5..cb8de4c43 100644 --- a/App/Sources/UI/Views/ContentListFilterView.swift +++ b/App/Sources/UI/Views/GroupDetail/WorkflowsFilterView.swift @@ -1,9 +1,9 @@ import SwiftUI import Bonzai -struct ContentListFilterView: View { +struct WorkflowsFilterView: View { @State private var searchTerm: String = "" - @EnvironmentObject private var publisher: ContentPublisher + @EnvironmentObject private var publisher: GroupDetailPublisher private let debounce: DebounceController private var focus: FocusState.Binding private let onClear: () -> Void @@ -72,7 +72,7 @@ struct ContentListFilterView: View { struct ContentListFilterView_Previews: PreviewProvider { @FocusState static var focus: AppFocus? static var previews: some View { - ContentListFilterView($focus, onClear: {}) { _ in } + WorkflowsFilterView($focus, onClear: {}) { _ in } .designTime() } } diff --git a/App/Sources/UI/Views/GroupsEmptyListView.swift b/App/Sources/UI/Views/Groups/EmptyGroupsList.swift similarity index 85% rename from App/Sources/UI/Views/GroupsEmptyListView.swift rename to App/Sources/UI/Views/Groups/EmptyGroupsList.swift index be49543db..d284f982e 100644 --- a/App/Sources/UI/Views/GroupsEmptyListView.swift +++ b/App/Sources/UI/Views/Groups/EmptyGroupsList.swift @@ -1,14 +1,14 @@ import SwiftUI import Bonzai -struct GroupsEmptyListView: View { +struct EmptyGroupsList: View { @Binding private var isVisible: Bool - private let onAction: (GroupsListView.Action) -> Void + private let onAction: (GroupsList.Action) -> Void private let namespace: Namespace.ID init(_ namespace: Namespace.ID, isVisible: Binding, - onAction: @escaping (GroupsListView.Action) -> Void) { + onAction: @escaping (GroupsList.Action) -> Void) { _isVisible = isVisible self.namespace = namespace self.onAction = onAction @@ -50,7 +50,7 @@ struct GroupsEmptyListView: View { struct GroupsEmptyListView_Previews: PreviewProvider { @Namespace static var namespace static var previews: some View { - GroupsEmptyListView(namespace, isVisible: .constant(true)) { _ in } + EmptyGroupsList(namespace, isVisible: .constant(true)) { _ in } .designTime() } } diff --git a/App/Sources/UI/Views/GroupIconView.swift b/App/Sources/UI/Views/Groups/GroupIconView.swift similarity index 100% rename from App/Sources/UI/Views/GroupIconView.swift rename to App/Sources/UI/Views/Groups/GroupIconView.swift diff --git a/App/Sources/UI/Views/GroupItemView.swift b/App/Sources/UI/Views/Groups/GroupListItem.swift similarity index 86% rename from App/Sources/UI/Views/GroupItemView.swift rename to App/Sources/UI/Views/Groups/GroupListItem.swift index c144efdb0..8a517e54a 100644 --- a/App/Sources/UI/Views/GroupItemView.swift +++ b/App/Sources/UI/Views/Groups/GroupListItem.swift @@ -1,14 +1,14 @@ import Bonzai import SwiftUI -struct GroupItemView: View { +struct GroupListItem: View { private let group: GroupViewModel - private let onAction: (GroupsListView.Action) -> Void + private let onAction: (GroupsList.Action) -> Void private let selectionManager: SelectionManager init(_ group: GroupViewModel, selectionManager: SelectionManager, - onAction: @escaping (GroupsListView.Action) -> Void) { + onAction: @escaping (GroupsList.Action) -> Void) { self.group = group self.selectionManager = selectionManager self.onAction = onAction @@ -27,11 +27,11 @@ private struct GroupItemInternalView: View { @State private var isTargeted: Bool = false private let selectionManager: SelectionManager private let group: GroupViewModel - private let onAction: (GroupsListView.Action) -> Void + private let onAction: (GroupsList.Action) -> Void init(_ group: GroupViewModel, selectionManager: SelectionManager, - onAction: @escaping (GroupsListView.Action) -> Void) { + onAction: @escaping (GroupsList.Action) -> Void) { self.selectionManager = selectionManager self.group = group self.onAction = onAction @@ -87,11 +87,11 @@ private struct GroupTextView: View { private struct ContextualMenuView: View { @ObservedObject private var selectionManager: SelectionManager private let group: GroupViewModel - private let onAction: (GroupsListView.Action) -> Void + private let onAction: (GroupsList.Action) -> Void init(selectionManager: SelectionManager, group: GroupViewModel, - onAction: @escaping (GroupsListView.Action) -> Void) { + onAction: @escaping (GroupsList.Action) -> Void) { self.selectionManager = selectionManager self.group = group self.onAction = onAction @@ -113,7 +113,7 @@ private struct ContextualMenuView: View { @ViewBuilder private func contextualMenu(for group: GroupViewModel, - onAction: @escaping (GroupsListView.Action) -> Void) -> some View { + onAction: @escaping (GroupsList.Action) -> Void) -> some View { Button("Edit", action: { onAction(.openScene(.editGroup(group.id))) }) Divider() Button("Remove", action: { diff --git a/App/Sources/UI/Views/GroupsListView.swift b/App/Sources/UI/Views/Groups/GroupsList.swift similarity index 75% rename from App/Sources/UI/Views/GroupsListView.swift rename to App/Sources/UI/Views/Groups/GroupsList.swift index 017b3f344..6928b503e 100644 --- a/App/Sources/UI/Views/GroupsListView.swift +++ b/App/Sources/UI/Views/Groups/GroupsList.swift @@ -6,13 +6,13 @@ struct GroupDebounce: DebounceSnapshot { let groups: Set } -struct GroupsListView: View { +struct GroupsList: View { enum Action { case openScene(AppScene) case selectGroups(Set) case moveGroups(source: IndexSet, destination: Int) - case moveWorkflows(workflowIds: Set, groupId: GroupViewModel.ID) - case copyWorkflows(workflowIds: Set, groupId: GroupViewModel.ID) + case moveWorkflows(workflowIds: Set, groupId: GroupViewModel.ID) + case copyWorkflows(workflowIds: Set, groupId: GroupViewModel.ID) case removeGroups(Set) } @@ -34,24 +34,24 @@ struct GroupsListView: View { @EnvironmentObject private var publisher: GroupsPublisher @State private var confirmDelete: Confirm? @State private var reorderId: UUID = .init() - private let contentSelectionManager: SelectionManager + private let workflowSelection: SelectionManager private let debounce: DebounceController private let namespace: Namespace.ID - private let onAction: (GroupsListView.Action) -> Void - private let selectionManager: SelectionManager + private let onAction: (GroupsList.Action) -> Void + private let groupSelection: SelectionManager private var appFocus: FocusState.Binding init(_ appFocus: FocusState.Binding, namespace: Namespace.ID, - selectionManager: SelectionManager, - contentSelectionManager: SelectionManager, - onAction: @escaping (GroupsListView.Action) -> Void) { + groupSelection: SelectionManager, + workflowSelection: SelectionManager, + onAction: @escaping (GroupsList.Action) -> Void) { self.appFocus = appFocus self.namespace = namespace - self.selectionManager = selectionManager - self.contentSelectionManager = contentSelectionManager + self.groupSelection = groupSelection + self.workflowSelection = workflowSelection self.onAction = onAction - self.debounce = .init(.init(groups: selectionManager.selections), + self.debounce = .init(.init(groups: groupSelection.selections), milliseconds: 150, onUpdate: { snapshot in onAction(.selectGroups(snapshot.groups)) @@ -61,11 +61,11 @@ struct GroupsListView: View { var body: some View { ScrollViewReader { proxy in if publisher.data.isEmpty { - GroupsEmptyListView(namespace, isVisible: .readonly(publisher.data.isEmpty), onAction: onAction) + EmptyGroupsList(namespace, isVisible: .readonly(publisher.data.isEmpty), onAction: onAction) } else { CompatList { ForEach(publisher.data.lazy, id: \.id) { group in - GroupItemView(group, selectionManager: selectionManager, onAction: onAction) + GroupListItem(group, selectionManager: groupSelection, onAction: onAction) .overlay(content: { confirmDeleteView(group) }) .modifier(LegacyOnTapFix(onTap: { focus = .element(group.id) @@ -76,7 +76,7 @@ struct GroupsListView: View { }) .focusable($focus, as: .element(group.id)) { if let keyCode = LocalEventMonitor.shared.event?.keyCode, keyCode == kVK_Tab, - let lastSelection = selectionManager.lastSelection, + let lastSelection = groupSelection.lastSelection, let match = publisher.data.first(where: { $0.id == lastSelection }) { focus = .element(match.id) } else { @@ -109,10 +109,10 @@ struct GroupsListView: View { }) .onCommand(#selector(NSResponder.insertBacktab(_:)), perform: {}) .onCommand(#selector(NSResponder.selectAll(_:)), perform: { - selectionManager.publish(Set(publisher.data.map(\.id))) + groupSelection.publish(Set(publisher.data.map(\.id))) }) .onMoveCommand(perform: { direction in - if let elementID = selectionManager.handle( + if let elementID = groupSelection.handle( direction, publisher.data, proxy: proxy, @@ -121,12 +121,12 @@ struct GroupsListView: View { } }) .onDeleteCommand { - confirmDelete = .multiple(ids: Array(selectionManager.selections)) + confirmDelete = .multiple(ids: Array(groupSelection.selections)) } .id(reorderId) } .onAppear { - guard let initialSelection = selectionManager.initialSelection else { return } + guard let initialSelection = groupSelection.initialSelection else { return } focus = .element(initialSelection) proxy.scrollTo(initialSelection) } @@ -138,9 +138,9 @@ struct GroupsListView: View { } private func onTap(_ element: GroupViewModel) { - selectionManager.handleOnTap(publisher.data, element: element) + groupSelection.handleOnTap(publisher.data, element: element) confirmDelete = nil - debounce.process(.init(groups: selectionManager.selections)) + debounce.process(.init(groups: groupSelection.selections)) } func confirmDeleteView(_ group: GroupViewModel) -> some View { @@ -155,7 +155,7 @@ struct GroupsListView: View { Button(action: { guard confirmDelete != nil else { return } confirmDelete = nil - onAction(.removeGroups(selectionManager.selections)) + onAction(.removeGroups(groupSelection.selections)) }, label: { Image(systemName: "trash") }) .buttonStyle(.calm(color: .systemRed, padding: .medium)) .keyboardShortcut(.defaultAction) @@ -168,7 +168,7 @@ struct GroupsListView: View { @ViewBuilder private func contextualMenu(for group: GroupViewModel, - onAction: @escaping (GroupsListView.Action) -> Void) -> some View { + onAction: @escaping (GroupsList.Action) -> Void) -> some View { Button("Edit", action: { onAction(.openScene(.editGroup(group.id))) }) Divider() Button("Remove", action: { @@ -181,10 +181,10 @@ struct GroupsListView_Previews: PreviewProvider { @FocusState static var focus: AppFocus? @Namespace static var namespace static var previews: some View { - GroupsListView($focus, + GroupsList($focus, namespace: namespace, - selectionManager: .init(), - contentSelectionManager: .init(), + groupSelection: .init(), + workflowSelection: .init(), onAction: { _ in }) .designTime() } diff --git a/App/Sources/UI/Views/GroupContainerView.swift b/App/Sources/UI/Views/Groups/GroupsView.swift similarity index 75% rename from App/Sources/UI/Views/GroupContainerView.swift rename to App/Sources/UI/Views/Groups/GroupsView.swift index 1cf1dde03..4d632781e 100644 --- a/App/Sources/UI/Views/GroupContainerView.swift +++ b/App/Sources/UI/Views/Groups/GroupsView.swift @@ -1,22 +1,22 @@ import Bonzai import SwiftUI -struct GroupContainerView: View { +struct GroupsView: View { @EnvironmentObject private var publisher: GroupsPublisher let namespace: Namespace.ID - private let contentSelectionManager: SelectionManager - private let groupSelectionManager: SelectionManager + private let workflowSelection: SelectionManager + private let groupSelection: SelectionManager private let onAction: (SidebarView.Action) -> Void private var focus: FocusState.Binding init(_ namespace: Namespace.ID, - contentSelectionManager: SelectionManager, - groupSelectionManager: SelectionManager, + groupSelection: SelectionManager, + workflowSelection: SelectionManager, onAction: @escaping (SidebarView.Action) -> Void, focus: FocusState.Binding) { self.namespace = namespace - self.contentSelectionManager = contentSelectionManager - self.groupSelectionManager = groupSelectionManager + self.groupSelection = groupSelection + self.workflowSelection = workflowSelection self.onAction = onAction self.focus = focus } @@ -28,10 +28,9 @@ struct GroupContainerView: View { .padding(.horizontal, 12) .padding(.vertical, 6) - GroupsListView(focus, - namespace: namespace, - selectionManager: groupSelectionManager, - contentSelectionManager: contentSelectionManager) { action in + GroupsList(focus, namespace: namespace, + groupSelection: groupSelection, + workflowSelection: workflowSelection) { action in switch action { case .selectGroups(let ids): onAction(.selectGroups(ids)) diff --git a/App/Sources/UI/Views/MainWindowView.swift b/App/Sources/UI/Views/MainView.swift similarity index 52% rename from App/Sources/UI/Views/MainWindowView.swift rename to App/Sources/UI/Views/MainView.swift index af11289ad..d92bb5020 100644 --- a/App/Sources/UI/Views/MainWindowView.swift +++ b/App/Sources/UI/Views/MainView.swift @@ -1,7 +1,7 @@ import SwiftUI @MainActor -struct MainWindowView: View { +struct MainView: View { @FocusState var focus: AppFocus? @Namespace var namespace private let core: Core @@ -16,17 +16,17 @@ struct MainWindowView: View { ContainerView( $focus, contentState: .readonly(core.contentStore.state), - detailUpdateTransaction: core.detailCoordinator.updateTransaction, - publisher: core.contentCoordinator.contentPublisher, - applicationTriggerSelectionManager: core.applicationTriggerSelectionManager, - commandSelectionManager: core.commandSelectionManager, - configSelectionManager: core.configSelectionManager, - contentSelectionManager: core.contentSelectionManager, - groupsSelectionManager: core.groupSelectionManager, - keyboardShortcutSelectionManager: core.keyboardShortcutSelectionManager, - triggerPublisher: core.detailCoordinator.triggerPublisher, - infoPublisher: core.detailCoordinator.infoPublisher, - commandPublisher: core.detailCoordinator.commandsPublisher + detailUpdateTransaction: core.workflowCoordinator.updateTransaction, + publisher: core.groupCoordinator.contentPublisher, + applicationTriggerSelection: core.applicationTriggerSelection, + commandSelection: core.commandSelection, + configSelection: core.configSelection, + contentSelection: core.workflowsSelection, + groupsSelection: core.groupSelection, + keyboardShortcutSelection: core.keyboardShortcutSelection, + triggerPublisher: core.workflowCoordinator.triggerPublisher, + infoPublisher: core.workflowCoordinator.infoPublisher, + commandPublisher: core.workflowCoordinator.commandsPublisher ) { action, undoManager in let oldConfiguration = core.configurationStore.selectedConfiguration @@ -40,12 +40,12 @@ struct MainWindowView: View { default: core.configCoordinator.handle(sidebarAction) core.sidebarCoordinator.handle(sidebarAction) - core.contentCoordinator.handle(sidebarAction) - core.detailCoordinator.handle(sidebarAction) + core.groupCoordinator.handle(sidebarAction) + core.workflowCoordinator.handle(sidebarAction) } case .content(let contentAction): - core.contentCoordinator.handle(contentAction) - core.detailCoordinator.handle(contentAction) + core.groupCoordinator.handle(contentAction) + core.workflowCoordinator.handle(contentAction) } undoManager?.registerUndo(withTarget: core.configurationStore, handler: { store in @@ -53,8 +53,8 @@ struct MainWindowView: View { store.update(oldConfiguration) core.contentStore.use(oldConfiguration) core.sidebarCoordinator.handle(.refresh) - core.contentCoordinator.handle(.refresh(core.groupSelectionManager.selections)) - core.detailCoordinator.handle(.selectWorkflow(workflowIds: core.contentSelectionManager.selections)) + core.groupCoordinator.handle(.refresh(core.groupSelection.selections)) + core.workflowCoordinator.handle(.selectWorkflow(workflowIds: core.workflowsSelection.selections)) } }) } @@ -66,12 +66,12 @@ struct MainWindowView: View { .environmentObject(core.configCoordinator.configurationsPublisher) .environmentObject(core.configCoordinator.configurationPublisher) .environmentObject(core.sidebarCoordinator.publisher) - .environmentObject(core.contentCoordinator.contentPublisher) - .environmentObject(core.contentCoordinator.groupPublisher) - .environmentObject(core.detailCoordinator.statePublisher) - .environmentObject(core.detailCoordinator.infoPublisher) - .environmentObject(core.detailCoordinator.triggerPublisher) - .environmentObject(core.detailCoordinator.commandsPublisher) + .environmentObject(core.groupCoordinator.contentPublisher) + .environmentObject(core.groupCoordinator.groupPublisher) + .environmentObject(core.workflowCoordinator.statePublisher) + .environmentObject(core.workflowCoordinator.infoPublisher) + .environmentObject(core.workflowCoordinator.triggerPublisher) + .environmentObject(core.workflowCoordinator.commandsPublisher) .environmentObject(core.snippetController) .environmentObject(OpenPanelController()) } diff --git a/App/Sources/UI/Views/Mappers/ContentModelMapper.swift b/App/Sources/UI/Views/Mappers/GroupDetailViewModelMapper.swift similarity index 85% rename from App/Sources/UI/Views/Mappers/ContentModelMapper.swift rename to App/Sources/UI/Views/Mappers/GroupDetailViewModelMapper.swift index 17ab1521f..89bfbb1fa 100644 --- a/App/Sources/UI/Views/Mappers/ContentModelMapper.swift +++ b/App/Sources/UI/Views/Mappers/GroupDetailViewModelMapper.swift @@ -1,15 +1,15 @@ import Bonzai import Foundation -final class ContentModelMapper { - func map(_ workflow: Workflow, groupId: String) -> ContentViewModel { +final class GroupDetailViewModelMapper { + func map(_ workflow: Workflow, groupId: String) -> GroupDetailViewModel { workflow.asViewModel(nil, groupId: groupId) } } private extension Array where Element == Workflow { - func asViewModels(_ groupName: String?, groupId: String) -> [ContentViewModel] { - var viewModels = [ContentViewModel]() + func asViewModels(_ groupName: String?, groupId: String) -> [GroupDetailViewModel] { + var viewModels = [GroupDetailViewModel]() viewModels.reserveCapacity(self.count) for (offset, model) in self.enumerated() { viewModels.append(model.asViewModel(offset == 0 ? groupName : nil, groupId: groupId)) @@ -47,9 +47,9 @@ private extension String { } private extension Workflow { - func asViewModel(_ groupName: String?, groupId: String) -> ContentViewModel { + func asViewModel(_ groupName: String?, groupId: String) -> GroupDetailViewModel { let commandCount = commands.count - let viewModelTrigger: ContentViewModel.Trigger? + let viewModelTrigger: GroupDetailViewModel.Trigger? viewModelTrigger = switch trigger { case .application: .application("foo") case .keyboardShortcuts(let trigger): .keyboard(trigger.shortcuts.binding ?? "") @@ -57,12 +57,12 @@ private extension Workflow { case .none: nil } - let execution: ContentViewModel.Execution = switch execution { + let execution: GroupDetailViewModel.Execution = switch execution { case .concurrent: .concurrent case .serial: .serial } - return ContentViewModel( + return GroupDetailViewModel( id: id, groupId: groupId, groupName: groupName, @@ -89,8 +89,8 @@ private extension Workflow.Trigger { } private extension Array where Element == Command { - func overlayImages(limit: Int) -> [ContentViewModel.ImageModel] { - var images = [ContentViewModel.ImageModel]() + func overlayImages(limit: Int) -> [GroupDetailViewModel.ImageModel] { + var images = [GroupDetailViewModel.ImageModel]() for (offset, element) in self.enumerated() where element.isEnabled { if offset == limit { break } @@ -99,7 +99,7 @@ private extension Array where Element == Command { switch element { case .open(let command): if let application = command.application { - images.append(ContentViewModel.ImageModel( + images.append(GroupDetailViewModel.ImageModel( id: command.id, offset: convertedOffset, kind: .icon(.init(bundleIdentifier: application.bundleIdentifier, @@ -113,8 +113,8 @@ private extension Array where Element == Command { return images } - func images(limit: Int) -> [ContentViewModel.ImageModel] { - var images = [ContentViewModel.ImageModel]() + func images(limit: Int) -> [GroupDetailViewModel.ImageModel] { + var images = [GroupDetailViewModel.ImageModel]() var offset: Int = 0 for element in self.reversed() where element.isEnabled { // Don't render icons for commands that are not enabled. @@ -126,7 +126,7 @@ private extension Array where Element == Command { switch element { case .application(let command): images.append( - ContentViewModel.ImageModel( + GroupDetailViewModel.ImageModel( id: command.id, offset: convertedOffset, kind: .icon(.init(bundleIdentifier: command.application.bundleIdentifier, @@ -154,7 +154,7 @@ private extension Array where Element == Command { } images.append( - ContentViewModel.ImageModel( + GroupDetailViewModel.ImageModel( id: command.id, offset: convertedOffset, kind: .icon(.init(bundleIdentifier: path, path: path))) diff --git a/App/Sources/UI/Views/Models/CommandViewModel.swift b/App/Sources/UI/Views/Models/CommandViewModel.swift index 4679f9b2c..b7773b483 100644 --- a/App/Sources/UI/Views/Models/CommandViewModel.swift +++ b/App/Sources/UI/Views/Models/CommandViewModel.swift @@ -50,7 +50,6 @@ struct CommandViewModel: Codable, Hashable, Identifiable, Transferable { case open(OpenModel) case keyboard(KeyboardModel) case script(ScriptModel) - case plain case shortcut(ShortcutModel) case text(TextModel) case systemCommand(SystemModel) diff --git a/App/Sources/UI/Views/Models/ContentListDropItem.swift b/App/Sources/UI/Views/Models/ContentListDropItem.swift index 92a2c970f..e29369c18 100644 --- a/App/Sources/UI/Views/Models/ContentListDropItem.swift +++ b/App/Sources/UI/Views/Models/ContentListDropItem.swift @@ -2,7 +2,7 @@ import CoreTransferable import Foundation enum ContentListDropItem: Codable, Transferable, Equatable { - case workflow(ContentViewModel) + case workflow(GroupDetailViewModel) case command(CommandViewModel) static var transferRepresentation: some TransferRepresentation { diff --git a/App/Sources/UI/Views/Models/ContentViewModel.swift b/App/Sources/UI/Views/Models/GroupDetailViewModel.swift similarity index 88% rename from App/Sources/UI/Views/Models/ContentViewModel.swift rename to App/Sources/UI/Views/Models/GroupDetailViewModel.swift index 8674ff601..ab5f06fd9 100644 --- a/App/Sources/UI/Views/Models/ContentViewModel.swift +++ b/App/Sources/UI/Views/Models/GroupDetailViewModel.swift @@ -1,8 +1,8 @@ import Bonzai import SwiftUI -struct ContentViewModel: Identifiable, Hashable, Codable, - Sendable, Transferable { +struct GroupDetailViewModel: Identifiable, Hashable, Codable, + Sendable, Transferable { static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .workflow) } @@ -30,16 +30,12 @@ struct ContentViewModel: Identifiable, Hashable, Codable, let isEnabled: Bool let execution: Execution - internal init(id: String, - groupId: String, - groupName: String? = nil, - name: String, - images: [ContentViewModel.ImageModel], - overlayImages: [ContentViewModel.ImageModel], - trigger: Trigger? = nil, - execution: Execution = .concurrent, - badge: Int, - badgeOpacity: Double, isEnabled: Bool) { + internal init(id: String, groupId: String, + groupName: String? = nil, name: String, + images: [GroupDetailViewModel.ImageModel], + overlayImages: [GroupDetailViewModel.ImageModel], + trigger: Trigger? = nil, execution: Execution = .concurrent, + badge: Int, badgeOpacity: Double, isEnabled: Bool) { self.id = id self.groupId = groupId self.groupName = groupName @@ -95,7 +91,7 @@ struct ContentViewModel: Identifiable, Hashable, Codable, } } - var match: ContentView.Match.Kind { + var match: GroupDetailView.Match.Kind { switch self { case .application: .application case .builtIn: .builtIn diff --git a/App/Sources/UI/Views/Models/SidebarListDropItem.swift b/App/Sources/UI/Views/Models/SidebarListDropItem.swift index 400f63d9c..5d9263113 100644 --- a/App/Sources/UI/Views/Models/SidebarListDropItem.swift +++ b/App/Sources/UI/Views/Models/SidebarListDropItem.swift @@ -2,7 +2,7 @@ import CoreTransferable import Foundation enum SidebarListDropItem: Codable, Transferable, Equatable { - case workflow(ContentViewModel) + case workflow(GroupDetailViewModel) case group(GroupViewModel) static var transferRepresentation: some TransferRepresentation { diff --git a/App/Sources/UI/Views/Notifications/WorkflowNotificationView.swift b/App/Sources/UI/Views/Notifications/WorkflowNotificationView.swift index 718ae13b0..2ea53d219 100644 --- a/App/Sources/UI/Views/Notifications/WorkflowNotificationView.swift +++ b/App/Sources/UI/Views/Notifications/WorkflowNotificationView.swift @@ -260,7 +260,7 @@ extension Command { placeholderView(size) } case .shortcut: - ContentShortcutImageView(size: size) + WorkflowShortcutImage(size: size) } } } diff --git a/App/Sources/UI/Views/Publishers/PublisherTypeAlias.swift b/App/Sources/UI/Views/Publishers/PublisherTypeAlias.swift index d95093c59..1958ac614 100644 --- a/App/Sources/UI/Views/Publishers/PublisherTypeAlias.swift +++ b/App/Sources/UI/Views/Publishers/PublisherTypeAlias.swift @@ -1,7 +1,7 @@ typealias ConfigurationsPublisher = ViewModelsPublisher typealias GroupsPublisher = ViewModelsPublisher typealias GroupPublisher = ViewModelPublisher -typealias ContentPublisher = ViewModelsPublisher +typealias GroupDetailPublisher = ViewModelsPublisher typealias DetailStatePublisher = ViewModelPublisher typealias BezelNotificationPublisher = ViewModelPublisher typealias WorkflowNotificationPublisher = ViewModelPublisher diff --git a/App/Sources/UI/Views/SidebarAddGroupButtonView.swift b/App/Sources/UI/Views/Sidebar/SidebarAddGroupButtonView.swift similarity index 100% rename from App/Sources/UI/Views/SidebarAddGroupButtonView.swift rename to App/Sources/UI/Views/Sidebar/SidebarAddGroupButtonView.swift diff --git a/App/Sources/UI/Views/SidebarDeleteConfigurationPopoverView.swift b/App/Sources/UI/Views/Sidebar/SidebarDeleteConfigurationPopoverView.swift similarity index 100% rename from App/Sources/UI/Views/SidebarDeleteConfigurationPopoverView.swift rename to App/Sources/UI/Views/Sidebar/SidebarDeleteConfigurationPopoverView.swift diff --git a/App/Sources/UI/Views/SidebarNewConfigurationPopoverView.swift b/App/Sources/UI/Views/Sidebar/SidebarNewConfigurationPopoverView.swift similarity index 100% rename from App/Sources/UI/Views/SidebarNewConfigurationPopoverView.swift rename to App/Sources/UI/Views/Sidebar/SidebarNewConfigurationPopoverView.swift diff --git a/App/Sources/UI/Views/SidebarUpdateConfigurationNamePopoverView.swift b/App/Sources/UI/Views/Sidebar/SidebarUpdateConfigurationNamePopoverView.swift similarity index 100% rename from App/Sources/UI/Views/SidebarUpdateConfigurationNamePopoverView.swift rename to App/Sources/UI/Views/Sidebar/SidebarUpdateConfigurationNamePopoverView.swift diff --git a/App/Sources/UI/Views/Sidebar/SidebarView.swift b/App/Sources/UI/Views/Sidebar/SidebarView.swift new file mode 100644 index 000000000..49da1c62a --- /dev/null +++ b/App/Sources/UI/Views/Sidebar/SidebarView.swift @@ -0,0 +1,65 @@ +import Bonzai +import SwiftUI + +struct SidebarView: View { + enum Action { + case refresh + case openScene(AppScene) + case addConfiguration(name: String) + case userMode(UserModesView.Action) + case updateConfiguration(name: String) + case deleteConfiguration(id: ConfigurationViewModel.ID) + case selectConfiguration(ConfigurationViewModel.ID) + case selectGroups(Set) + case moveGroups(source: IndexSet, destination: Int) + case removeGroups(Set) + case moveWorkflows(workflowIds: Set, groupId: GroupViewModel.ID) + case copyWorkflows(workflowIds: Set, groupId: GroupViewModel.ID) + } + + @EnvironmentObject private var publisher: GroupsPublisher + @Namespace private var namespace + private let configSelection: SelectionManager + private let workflowSelection: SelectionManager + private let groupSelection: SelectionManager + private let onAction: (Action) -> Void + private var focus: FocusState.Binding + + init(_ focus: FocusState.Binding, + configSelection: SelectionManager, + groupSelection: SelectionManager, + workflowSelection: SelectionManager, + onAction: @escaping (Action) -> Void) { + self.focus = focus + self.configSelection = configSelection + self.groupSelection = groupSelection + self.workflowSelection = workflowSelection + self.onAction = onAction + } + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + ConfigurationContainerView(configSelection: configSelection, + onAction: onAction) + + GroupsView(namespace, groupSelection: groupSelection, + workflowSelection: workflowSelection, + onAction: onAction, focus: focus) + + UserModeContainerView(onAction: onAction) + } + } +} + +#Preview { + @FocusState var focus: AppFocus? + return VStack(alignment: .leading) { + SidebarView( + $focus, + configSelection: .init(), + groupSelection: .init(), + workflowSelection: .init() + ) { _ in } + } + .designTime() +} diff --git a/App/Sources/UI/Views/SidebarView.swift b/App/Sources/UI/Views/SidebarView.swift deleted file mode 100644 index 1894f4cd4..000000000 --- a/App/Sources/UI/Views/SidebarView.swift +++ /dev/null @@ -1,69 +0,0 @@ -import Bonzai -import SwiftUI - -struct SidebarView: View { - enum Action { - case refresh - case openScene(AppScene) - case addConfiguration(name: String) - case userMode(UserModesView.Action) - case updateConfiguration(name: String) - case deleteConfiguration(id: ConfigurationViewModel.ID) - case selectConfiguration(ConfigurationViewModel.ID) - case selectGroups(Set) - case moveGroups(source: IndexSet, destination: Int) - case removeGroups(Set) - case moveWorkflows(workflowIds: Set, groupId: GroupViewModel.ID) - case copyWorkflows(workflowIds: Set, groupId: GroupViewModel.ID) - } - - @EnvironmentObject private var publisher: GroupsPublisher - @Namespace private var namespace - private let configSelectionManager: SelectionManager - private let contentSelectionManager: SelectionManager - private let groupSelectionManager: SelectionManager - private let onAction: (Action) -> Void - private var focus: FocusState.Binding - - init(_ focus: FocusState.Binding, - configSelectionManager: SelectionManager, - groupSelectionManager: SelectionManager, - contentSelectionManager: SelectionManager, - onAction: @escaping (Action) -> Void) { - self.focus = focus - self.configSelectionManager = configSelectionManager - self.groupSelectionManager = groupSelectionManager - self.contentSelectionManager = contentSelectionManager - self.onAction = onAction - } - - var body: some View { - VStack(alignment: .leading, spacing: 0) { - ConfigurationContainerView(configSelectionManager: configSelectionManager, - onAction: onAction) - - GroupContainerView(namespace, - contentSelectionManager: contentSelectionManager, - groupSelectionManager: groupSelectionManager, - onAction: onAction, - focus: focus) - - UserModeContainerView(onAction: onAction) - } - } -} - -struct SidebarView_Previews: PreviewProvider { - @FocusState static var focus: AppFocus? - static var previews: some View { - VStack(alignment: .leading) { - SidebarView( - $focus, - configSelectionManager: .init(), - groupSelectionManager: .init(), - contentSelectionManager: .init() - ) { _ in } - } - .designTime() - } -} diff --git a/App/Sources/UI/Views/AddUserModeView.swift b/App/Sources/UI/Views/UserMode/AddUserModeView.swift similarity index 100% rename from App/Sources/UI/Views/AddUserModeView.swift rename to App/Sources/UI/Views/UserMode/AddUserModeView.swift diff --git a/App/Sources/UI/Views/UserModeContainerView.swift b/App/Sources/UI/Views/UserMode/UserModeContainerView.swift similarity index 100% rename from App/Sources/UI/Views/UserModeContainerView.swift rename to App/Sources/UI/Views/UserMode/UserModeContainerView.swift diff --git a/App/Sources/UI/Views/UserModesView.swift b/App/Sources/UI/Views/UserMode/UserModesView.swift similarity index 100% rename from App/Sources/UI/Views/UserModesView.swift rename to App/Sources/UI/Views/UserMode/UserModesView.swift diff --git a/App/Sources/UI/Views/CommandView.swift b/App/Sources/UI/Views/WorkflowDetail/CommandView.swift similarity index 97% rename from App/Sources/UI/Views/CommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/CommandView.swift index 3241a7149..9acbdc878 100644 --- a/App/Sources/UI/Views/CommandView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/CommandView.swift @@ -63,7 +63,6 @@ struct CommandResolverView: View { var body: some View { let iconSize = CGSize(width: 24, height: 24) switch command.kind { - case .plain: UnknownView(command: .constant(command)) case .application(let model): ApplicationCommandView(command.meta, model: model, iconSize: iconSize) .fixedSize(horizontal: false, vertical: true) case .builtIn(let model): BuiltInCommandView(command.meta, model: model, iconSize: iconSize) diff --git a/App/Sources/UI/Views/WorkflowCommandListView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandList.swift similarity index 91% rename from App/Sources/UI/Views/WorkflowCommandListView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandList.swift index 751023766..f606e55b2 100644 --- a/App/Sources/UI/Views/WorkflowCommandListView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandList.swift @@ -2,7 +2,7 @@ import Bonzai import SwiftUI import UniformTypeIdentifiers -struct WorkflowCommandListView: View { +struct CommandList: View { static let animation: Animation = .spring(response: 0.3, dampingFraction: 0.65, blendDuration: 0.2) @Binding private var isPrimary: Bool @@ -36,13 +36,13 @@ struct WorkflowCommandListView: View { @ViewBuilder var body: some View { if publisher.data.commands.isEmpty { - WorkflowCommandEmptyListView(focus, + EmptyCommandList(focus, namespace: namespace, workflowId: publisher.data.id, isPrimary: $isPrimary) } else { - WorkflowCommandListHeaderView(namespace: namespace) - WorkflowCommandListScrollView(focus, + CommandListHeader(namespace: namespace) + CommandListScrollView(focus, publisher: publisher, triggerPublisher: triggerPublisher, namespace: namespace, @@ -57,7 +57,7 @@ struct WorkflowCommandListView_Previews: PreviewProvider { @Namespace static var namespace @FocusState static var focus: AppFocus? static var previews: some View { - WorkflowCommandListView($focus, + CommandList($focus, namespace: namespace, workflowId: "workflowId", isPrimary: .constant(true), diff --git a/App/Sources/UI/Views/WorkflowCommandListContextMenuView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandListContextualMenu.swift similarity index 96% rename from App/Sources/UI/Views/WorkflowCommandListContextMenuView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandListContextualMenu.swift index 4d410c93e..35ccca248 100644 --- a/App/Sources/UI/Views/WorkflowCommandListContextMenuView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandListContextualMenu.swift @@ -1,6 +1,6 @@ import SwiftUI -struct WorkflowCommandListContextMenuView: View { +struct CommandListContextualMenu: View { @EnvironmentObject var updater: ConfigurationUpdater @EnvironmentObject var transaction: UpdateTransaction diff --git a/App/Sources/UI/Views/WorkflowCommandListHeaderView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandListHeader.swift similarity index 89% rename from App/Sources/UI/Views/WorkflowCommandListHeaderView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandListHeader.swift index 907cd6b9e..739e899d2 100644 --- a/App/Sources/UI/Views/WorkflowCommandListHeaderView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandListHeader.swift @@ -1,7 +1,7 @@ import Bonzai import SwiftUI -struct WorkflowCommandListHeaderView: View { +struct CommandListHeader: View { @EnvironmentObject var updater: ConfigurationUpdater @EnvironmentObject var transaction: UpdateTransaction @EnvironmentObject var publisher: CommandsPublisher @@ -32,7 +32,7 @@ struct WorkflowCommandListHeaderView: View { }) .menuStyle(.zen(.init(color: .systemGray, padding: .large))) .fixedSize(horizontal: true, vertical: true) - WorkflowCommandListHeaderAddView(namespace) + CommandListHeaderAddButton(namespace) } .padding(.leading, 24) .padding(.trailing, 16) @@ -42,7 +42,7 @@ struct WorkflowCommandListHeaderView: View { struct WorkflowCommandListHeaderView_Previews: PreviewProvider { @Namespace static var namespace static var previews: some View { - WorkflowCommandListHeaderView(namespace: namespace) + CommandListHeader(namespace: namespace) .designTime() } } diff --git a/App/Sources/UI/Views/WorkflowCommandListHeaderAddView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandListHeaderAddButton.swift similarity index 75% rename from App/Sources/UI/Views/WorkflowCommandListHeaderAddView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandListHeaderAddButton.swift index 2fa58f3df..981331878 100644 --- a/App/Sources/UI/Views/WorkflowCommandListHeaderAddView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandListHeaderAddButton.swift @@ -1,7 +1,7 @@ import SwiftUI import Bonzai -struct WorkflowCommandListHeaderAddView: View { +struct CommandListHeaderAddButton: View { @EnvironmentObject var transaction: UpdateTransaction @EnvironmentObject var openWindow: WindowOpener private let namespace: Namespace.ID @@ -29,11 +29,9 @@ struct WorkflowCommandListHeaderAddView: View { } } -struct WorkflowCommandListHeaderAddView_Previews: PreviewProvider { - @Namespace static var namespace - static var previews: some View { - WorkflowCommandListHeaderAddView(namespace) - .designTime() - .padding() - } +#Preview { + @Namespace var namespace + return CommandListHeaderAddButton(namespace) + .designTime() + .padding() } diff --git a/App/Sources/UI/Views/WorkflowCommandListScrollView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandListScrollView.swift similarity index 95% rename from App/Sources/UI/Views/WorkflowCommandListScrollView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandListScrollView.swift index a9aa539ac..44877663f 100644 --- a/App/Sources/UI/Views/WorkflowCommandListScrollView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandListScrollView.swift @@ -1,7 +1,7 @@ import Bonzai import SwiftUI -struct WorkflowCommandListScrollView: View { +struct CommandListScrollView: View { @EnvironmentObject private var updater: ConfigurationUpdater @EnvironmentObject private var transaction: UpdateTransaction @EnvironmentObject private var applicationStore: ApplicationStore @@ -52,7 +52,7 @@ struct WorkflowCommandListScrollView: View { return false } - withAnimation(WorkflowCommandListView.animation) { + withAnimation(CommandList.animation) { publisher.data.commands.move(fromOffsets: from, toOffset: destination) } updater.modifyWorkflow(using: transaction) { workflow in @@ -73,7 +73,7 @@ struct WorkflowCommandListScrollView: View { }) .contentShape(Rectangle()) .contextMenu(menuItems: { - WorkflowCommandListContextMenuView(command, publisher: publisher, selectionManager: selectionManager) + CommandListContextualMenu(command, publisher: publisher, selectionManager: selectionManager) }) .focusable(focus, as: .detail(.command(command.id))) { selectionManager.handleOnTap(publisher.data.commands, element: command) diff --git a/App/Sources/UI/Views/AppFocusCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/AppFocusCommandView.swift similarity index 100% rename from App/Sources/UI/Views/AppFocusCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/AppFocusCommandView.swift diff --git a/App/Sources/UI/Views/Commands/ApplicationCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/ApplicationCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/ApplicationCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/ApplicationCommandView.swift diff --git a/App/Sources/UI/Views/Commands/BuiltInCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/BuiltInCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/BuiltInCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/BuiltInCommandView.swift diff --git a/App/Sources/UI/Views/Commands/BundledCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/BundledCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/BundledCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/BundledCommandView.swift diff --git a/App/Sources/UI/Views/Commands/CommandContainerDelayPopoverView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/CommandContainerDelayPopoverView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/CommandContainerDelayPopoverView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/CommandContainerDelayPopoverView.swift diff --git a/App/Sources/UI/Views/Commands/CommandContainerDelayView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/CommandContainerDelayView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/CommandContainerDelayView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/CommandContainerDelayView.swift diff --git a/App/Sources/UI/Views/Commands/CommandContainerView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/CommandContainerView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/CommandContainerView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/CommandContainerView.swift diff --git a/App/Sources/UI/Views/Commands/KeyboardCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/KeyboardCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/KeyboardCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/KeyboardCommandView.swift diff --git a/App/Sources/UI/Views/Commands/MenuBarCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/MenuBarCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/MenuBarCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/MenuBarCommandView.swift diff --git a/App/Sources/UI/Views/Commands/MouseCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/MouseCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/MouseCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/MouseCommandView.swift diff --git a/App/Sources/UI/Views/Commands/OpenCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/OpenCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/OpenCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/OpenCommandView.swift diff --git a/App/Sources/UI/Views/Commands/ScriptCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/ScriptCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/ScriptCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/ScriptCommandView.swift diff --git a/App/Sources/UI/Views/Commands/ShortcutCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/ShortcutCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/ShortcutCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/ShortcutCommandView.swift diff --git a/App/Sources/UI/Views/Commands/SystemCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/SystemCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/SystemCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/SystemCommandView.swift diff --git a/App/Sources/UI/Views/Commands/TextCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/TextCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/TextCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/TextCommandView.swift diff --git a/App/Sources/UI/Views/Commands/TypeCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/TypeCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/TypeCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/TypeCommandView.swift diff --git a/App/Sources/UI/Views/Commands/UIElementCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/UIElementCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/UIElementCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/UIElementCommandView.swift diff --git a/App/Sources/UI/Views/Commands/WindowManagementAnimationDurationView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/WindowManagementAnimationDurationView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/WindowManagementAnimationDurationView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/WindowManagementAnimationDurationView.swift diff --git a/App/Sources/UI/Views/Commands/WindowManagementAnimationPopoverView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/WindowManagementAnimationPopoverView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/WindowManagementAnimationPopoverView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/WindowManagementAnimationPopoverView.swift diff --git a/App/Sources/UI/Views/Commands/WindowManagementCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/WindowManagementCommandView.swift similarity index 100% rename from App/Sources/UI/Views/Commands/WindowManagementCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/WindowManagementCommandView.swift diff --git a/App/Sources/UI/Views/WorkspaceCommandView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/WorkspaceCommandView.swift similarity index 100% rename from App/Sources/UI/Views/WorkspaceCommandView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/CommandTypes/WorkspaceCommandView.swift diff --git a/App/Sources/UI/Views/WorkflowCommandEmptyListView.swift b/App/Sources/UI/Views/WorkflowDetail/Commands/EmptyCommandList.swift similarity index 97% rename from App/Sources/UI/Views/WorkflowCommandEmptyListView.swift rename to App/Sources/UI/Views/WorkflowDetail/Commands/EmptyCommandList.swift index e3299394b..17af6f876 100644 --- a/App/Sources/UI/Views/WorkflowCommandEmptyListView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Commands/EmptyCommandList.swift @@ -2,7 +2,7 @@ import Bonzai import Inject import SwiftUI -struct WorkflowCommandEmptyListView: View { +struct EmptyCommandList: View { @ObserveInjection var inject @EnvironmentObject var applicationStore: ApplicationStore @EnvironmentObject var updater: ConfigurationUpdater @@ -89,7 +89,7 @@ struct WorkflowCommandEmptyListView_Previews: PreviewProvider { @FocusState static var focus: AppFocus? @Namespace static var namespace static var previews: some View { - WorkflowCommandEmptyListView( + EmptyCommandList( $focus, namespace: namespace, workflowId: UUID().uuidString, diff --git a/App/Sources/UI/Views/DetailEmptyView.swift b/App/Sources/UI/Views/WorkflowDetail/DetailEmptyView.swift similarity index 100% rename from App/Sources/UI/Views/DetailEmptyView.swift rename to App/Sources/UI/Views/WorkflowDetail/DetailEmptyView.swift diff --git a/App/Sources/UI/Views/DetailView.swift b/App/Sources/UI/Views/WorkflowDetail/DetailView.swift similarity index 75% rename from App/Sources/UI/Views/DetailView.swift rename to App/Sources/UI/Views/WorkflowDetail/DetailView.swift index 2c2bb7ad0..dca2eaf8d 100644 --- a/App/Sources/UI/Views/DetailView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/DetailView.swift @@ -3,25 +3,25 @@ import SwiftUI struct DetailView: View { @EnvironmentObject var statePublisher: DetailStatePublisher - private let applicationTriggerSelectionManager: SelectionManager + private let applicationTriggerSelection: SelectionManager private let commandPublisher: CommandsPublisher - private let commandSelectionManager: SelectionManager + private let commandSelection: SelectionManager private let infoPublisher: InfoPublisher - private let keyboardShortcutSelectionManager: SelectionManager + private let keyboardShortcutSelection: SelectionManager private let triggerPublisher: TriggerPublisher private var focus: FocusState.Binding init(_ focus: FocusState.Binding, - applicationTriggerSelectionManager: SelectionManager, - commandSelectionManager: SelectionManager, - keyboardShortcutSelectionManager: SelectionManager, + applicationTriggerSelection: SelectionManager, + commandSelection: SelectionManager, + keyboardShortcutSelection: SelectionManager, triggerPublisher: TriggerPublisher, infoPublisher: InfoPublisher, commandPublisher: CommandsPublisher) { self.focus = focus - self.commandSelectionManager = commandSelectionManager - self.applicationTriggerSelectionManager = applicationTriggerSelectionManager - self.keyboardShortcutSelectionManager = keyboardShortcutSelectionManager + self.commandSelection = commandSelection + self.applicationTriggerSelection = applicationTriggerSelection + self.keyboardShortcutSelection = keyboardShortcutSelection self.triggerPublisher = triggerPublisher self.infoPublisher = infoPublisher self.commandPublisher = commandPublisher @@ -39,9 +39,9 @@ struct DetailView: View { SingleDetailView( viewModel, focus: focus, - applicationTriggerSelectionManager: applicationTriggerSelectionManager, - commandSelectionManager: commandSelectionManager, - keyboardShortcutSelectionManager: keyboardShortcutSelectionManager, + applicationTriggerSelectionManager: applicationTriggerSelection, + commandSelectionManager: commandSelection, + keyboardShortcutSelectionManager: keyboardShortcutSelection, triggerPublisher: triggerPublisher, infoPublisher: infoPublisher, commandPublisher: commandPublisher) @@ -91,9 +91,9 @@ private struct DevTagView: View { struct DetailView_Previews: PreviewProvider { @FocusState static var focus: AppFocus? static var previews: some View { - DetailView($focus, applicationTriggerSelectionManager: .init(), - commandSelectionManager: .init(), - keyboardShortcutSelectionManager: .init(), + DetailView($focus, applicationTriggerSelection: .init(), + commandSelection: .init(), + keyboardShortcutSelection: .init(), triggerPublisher: DesignTime.triggerPublisher, infoPublisher: DesignTime.infoPublisher, commandPublisher: DesignTime.commandsPublisher) diff --git a/App/Sources/UI/Views/ContentListEmptyView.swift b/App/Sources/UI/Views/WorkflowDetail/EmptyWorkflowList.swift similarity index 75% rename from App/Sources/UI/Views/ContentListEmptyView.swift rename to App/Sources/UI/Views/WorkflowDetail/EmptyWorkflowList.swift index e2aea96a1..3fe796c7a 100644 --- a/App/Sources/UI/Views/ContentListEmptyView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/EmptyWorkflowList.swift @@ -1,13 +1,13 @@ import SwiftUI import Bonzai -struct ContentListEmptyView: View { - @EnvironmentObject private var publisher: ContentPublisher +struct EmptyWorkflowList: View { + @EnvironmentObject private var publisher: GroupDetailPublisher private let namespace: Namespace.ID - private let onAction: (ContentView.Action) -> Void + private let onAction: (GroupDetailView.Action) -> Void - init(_ namespace: Namespace.ID, onAction: @escaping (ContentView.Action) -> Void) { + init(_ namespace: Namespace.ID, onAction: @escaping (GroupDetailView.Action) -> Void) { self.namespace = namespace self.onAction = onAction } @@ -49,10 +49,9 @@ struct ContentListEmptyView: View { } } -struct ContentListEmptyView_Previews: PreviewProvider { - @Namespace static var namespace - static var previews: some View { - ContentListEmptyView(namespace) { _ in } +#Preview { + @Namespace var namespace + return EmptyWorkflowList(namespace) { _ in } .designTime() - } + .frame(width: 200, height: 100) } diff --git a/App/Sources/UI/Views/SingleDetailBackgroundView.swift b/App/Sources/UI/Views/WorkflowDetail/SingleDetailBackgroundView.swift similarity index 100% rename from App/Sources/UI/Views/SingleDetailBackgroundView.swift rename to App/Sources/UI/Views/WorkflowDetail/SingleDetailBackgroundView.swift diff --git a/App/Sources/UI/Views/SingleDetailView.swift b/App/Sources/UI/Views/WorkflowDetail/SingleDetailView.swift similarity index 99% rename from App/Sources/UI/Views/SingleDetailView.swift rename to App/Sources/UI/Views/WorkflowDetail/SingleDetailView.swift index b181ab656..8226bb50e 100644 --- a/App/Sources/UI/Views/SingleDetailView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/SingleDetailView.swift @@ -71,7 +71,7 @@ struct SingleDetailView: View { SingleDetailBackgroundView() }) - WorkflowCommandListView( + CommandList( focus, namespace: namespace, workflowId: infoPublisher.data.id, diff --git a/App/Sources/UI/Views/WorkflowApplicationTriggerItemView.swift b/App/Sources/UI/Views/WorkflowDetail/Triggers/ApplicationTriggerItem.swift similarity index 95% rename from App/Sources/UI/Views/WorkflowApplicationTriggerItemView.swift rename to App/Sources/UI/Views/WorkflowDetail/Triggers/ApplicationTriggerItem.swift index a808e4381..abf1fceaf 100644 --- a/App/Sources/UI/Views/WorkflowApplicationTriggerItemView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Triggers/ApplicationTriggerItem.swift @@ -2,7 +2,7 @@ import Bonzai import Inject import SwiftUI -struct WorkflowApplicationTriggerItemView: View { +struct ApplicationTriggerItem: View { @EnvironmentObject private var updater: ConfigurationUpdater @EnvironmentObject private var transaction: UpdateTransaction @ObserveInjection var inject @@ -48,7 +48,7 @@ struct WorkflowApplicationTriggerItemView: View { ZenDivider(.vertical) Button( action: { - withAnimation(WorkflowCommandListView.animation) { + withAnimation(CommandList.animation) { if let index = data.firstIndex(of: element) { data.remove(at: index) } diff --git a/App/Sources/UI/Views/WorkflowApplicationTriggerView.swift b/App/Sources/UI/Views/WorkflowDetail/Triggers/WorkflowApplicationTrigger.swift similarity index 89% rename from App/Sources/UI/Views/WorkflowApplicationTriggerView.swift rename to App/Sources/UI/Views/WorkflowDetail/Triggers/WorkflowApplicationTrigger.swift index bd08e22bc..b53e19888 100644 --- a/App/Sources/UI/Views/WorkflowApplicationTriggerView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Triggers/WorkflowApplicationTrigger.swift @@ -3,7 +3,7 @@ import Bonzai import Inject import SwiftUI -struct WorkflowApplicationTriggerView: View { +struct WorkflowApplicationTrigger: View { @ObserveInjection var inject @EnvironmentObject private var updater: ConfigurationUpdater @EnvironmentObject private var transaction: UpdateTransaction @@ -32,7 +32,7 @@ struct WorkflowApplicationTriggerView: View { Button(action: { let uuid = UUID() let anyApplication = Application.anyApplication() - withAnimation(WorkflowCommandListView.animation) { + withAnimation(CommandList.animation) { data.append(.init(id: uuid.uuidString, name: anyApplication.displayName, application: anyApplication, contexts: [])) } @@ -43,7 +43,7 @@ struct WorkflowApplicationTriggerView: View { ForEach(applicationStore.applications.lazy, id: \.path) { application in Button(action: { let uuid = UUID() - withAnimation(WorkflowCommandListView.animation) { + withAnimation(CommandList.animation) { data.append(.init(id: uuid.uuidString, name: application.displayName, application: application, contexts: [])) } @@ -68,7 +68,7 @@ struct WorkflowApplicationTriggerView: View { LazyVStack(spacing: 0) { let lastID = $data.lazy.last?.id ForEach($data.lazy, id: \.id) { element in - WorkflowApplicationTriggerItemView(element, data: $data, selectionManager: selectionManager) + ApplicationTriggerItem(element, data: $data, selectionManager: selectionManager) .contentShape(Rectangle()) .dropDestination(DetailViewModel.ApplicationTrigger.self, color: .accentColor, onDrop: { items, location in let ids = Array(selectionManager.selections) @@ -151,23 +151,6 @@ struct WorkflowApplicationTriggerView: View { } } -struct WorkflowApplicationTriggerView_Previews: PreviewProvider { - @FocusState static var focus: AppFocus? - static var previews: some View { - WorkflowApplicationTriggerView( - $focus, - data: [ - .init(id: "1", name: "Application 1", application: .finder(), - contexts: []), - ], - selectionManager: SelectionManager(), - onTab: { } - ) - .environmentObject(ApplicationStore.shared) - .padding() - } -} - fileprivate extension DetailViewModel.ApplicationTrigger.Context { var appTriggerContext: ApplicationTrigger.Context { switch self { @@ -178,3 +161,18 @@ fileprivate extension DetailViewModel.ApplicationTrigger.Context { } } } + +#Preview { + @FocusState var focus: AppFocus? + return WorkflowApplicationTrigger( + $focus, + data: [ + .init(id: "1", name: "Application 1", application: .finder(), + contexts: []), + ], + selectionManager: SelectionManager(), + onTab: { } + ) + .environmentObject(ApplicationStore.shared) + .padding() +} diff --git a/App/Sources/UI/Views/WorkflowTriggerView.swift b/App/Sources/UI/Views/WorkflowDetail/Triggers/WorkflowTrigger.swift similarity index 94% rename from App/Sources/UI/Views/WorkflowTriggerView.swift rename to App/Sources/UI/Views/WorkflowDetail/Triggers/WorkflowTrigger.swift index 4b9c02696..3e32237d1 100644 --- a/App/Sources/UI/Views/WorkflowTriggerView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/Triggers/WorkflowTrigger.swift @@ -2,7 +2,7 @@ import Bonzai import Inject import SwiftUI -struct WorkflowTriggerView: View { +struct WorkflowTrigger: View { @EnvironmentObject var updater: ConfigurationUpdater @EnvironmentObject var transaction: UpdateTransaction @ObserveInjection var inject @@ -129,9 +129,8 @@ struct WorkflowTriggerView: View { } } -struct WorkflowTriggerView_Previews: PreviewProvider { - @FocusState static var focus: AppFocus? - static var previews: some View { - WorkflowTriggerView($focus, isGrayscale: .constant(true)) - } +#Preview { + @FocusState var focus: AppFocus? + return WorkflowTrigger($focus, isGrayscale: .constant(true)) + .designTime() } diff --git a/App/Sources/UI/Views/WorkflowInfoView.swift b/App/Sources/UI/Views/WorkflowDetail/WorkflowInfoView.swift similarity index 100% rename from App/Sources/UI/Views/WorkflowInfoView.swift rename to App/Sources/UI/Views/WorkflowDetail/WorkflowInfoView.swift diff --git a/App/Sources/UI/Views/WorkflowKeyboardTriggerView.swift b/App/Sources/UI/Views/WorkflowDetail/WorkflowKeyboardTriggerView.swift similarity index 100% rename from App/Sources/UI/Views/WorkflowKeyboardTriggerView.swift rename to App/Sources/UI/Views/WorkflowDetail/WorkflowKeyboardTriggerView.swift diff --git a/App/Sources/UI/Views/WorkflowOuputView.swift b/App/Sources/UI/Views/WorkflowDetail/WorkflowOuputView.swift similarity index 100% rename from App/Sources/UI/Views/WorkflowOuputView.swift rename to App/Sources/UI/Views/WorkflowDetail/WorkflowOuputView.swift diff --git a/App/Sources/UI/Views/WorkflowShortcutsView.swift b/App/Sources/UI/Views/WorkflowDetail/WorkflowShortcutsView.swift similarity index 100% rename from App/Sources/UI/Views/WorkflowShortcutsView.swift rename to App/Sources/UI/Views/WorkflowDetail/WorkflowShortcutsView.swift diff --git a/App/Sources/UI/Views/WorkflowSnippetTriggerView.swift b/App/Sources/UI/Views/WorkflowDetail/WorkflowSnippetTriggerView.swift similarity index 100% rename from App/Sources/UI/Views/WorkflowSnippetTriggerView.swift rename to App/Sources/UI/Views/WorkflowDetail/WorkflowSnippetTriggerView.swift diff --git a/App/Sources/UI/Views/WorkflowTriggerListView.swift b/App/Sources/UI/Views/WorkflowDetail/WorkflowTriggerListView.swift similarity index 97% rename from App/Sources/UI/Views/WorkflowTriggerListView.swift rename to App/Sources/UI/Views/WorkflowDetail/WorkflowTriggerListView.swift index aa1d96375..c7594f8e3 100644 --- a/App/Sources/UI/Views/WorkflowTriggerListView.swift +++ b/App/Sources/UI/Views/WorkflowDetail/WorkflowTriggerListView.swift @@ -42,7 +42,7 @@ struct WorkflowTriggerListView: View { case .applications(let triggers): WorkflowTriggerHeaderView("Application Trigger") .matchedGeometryEffect(id: "workflow-trigger-header", in: namespace) - WorkflowApplicationTriggerView(focus, data: triggers, + WorkflowApplicationTrigger(focus, data: triggers, selectionManager: applicationTriggerSelectionManager, onTab: onTab) .matchedGeometryEffect(id: "workflow-triggers", in: namespace) @@ -54,7 +54,7 @@ struct WorkflowTriggerListView: View { case .empty: WorkflowTriggerHeaderView("Add Trigger", showRemoveButton: false) .matchedGeometryEffect(id: "workflow-trigger-header", in: namespace) - WorkflowTriggerView(focus, isGrayscale: .readonly(publisher.data != .empty)) + WorkflowTrigger(focus, isGrayscale: .readonly(publisher.data != .empty)) .matchedGeometryEffect(id: "workflow-triggers", in: namespace) } } diff --git a/App/Sources/UI/Windows/GroupWindow.swift b/App/Sources/UI/Windows/GroupWindow.swift index bb472cefe..301bc167a 100644 --- a/App/Sources/UI/Windows/GroupWindow.swift +++ b/App/Sources/UI/Windows/GroupWindow.swift @@ -22,13 +22,13 @@ final class GroupWindow: NSObject, NSWindowDelegate { private let context: Context private let applicationStore: ApplicationStore private let configurationPublisher: ConfigurationPublisher - private let contentPublisher: ContentPublisher - private let contentCoordinator: ContentCoordinator + private let contentPublisher: GroupDetailPublisher + private let contentCoordinator: GroupCoordinator private let sidebarCoordinator: SidebarCoordinator init(context: Context, applicationStore: ApplicationStore, - configurationPublisher: ConfigurationPublisher, contentPublisher: ContentPublisher, - contentCoordinator: ContentCoordinator, sidebarCoordinator: SidebarCoordinator) { + configurationPublisher: ConfigurationPublisher, contentPublisher: GroupDetailPublisher, + contentCoordinator: GroupCoordinator, sidebarCoordinator: SidebarCoordinator) { self.context = context self.applicationStore = applicationStore self.configurationPublisher = configurationPublisher diff --git a/App/Sources/UI/Windows/MainWindow.swift b/App/Sources/UI/Windows/MainWindow.swift index 88ba3962d..898256436 100644 --- a/App/Sources/UI/Windows/MainWindow.swift +++ b/App/Sources/UI/Windows/MainWindow.swift @@ -21,7 +21,7 @@ final class MainWindow: NSObject, NSWindowDelegate { return } - let content = MainWindowView(core: core, onSceneAction: onSceneAction(_:)) + let content = MainView(core: core, onSceneAction: onSceneAction(_:)) .environmentObject(windowOpener) .environmentObject(core.configurationUpdater) let styleMask: NSWindow.StyleMask = [ diff --git a/App/Sources/UI/Windows/WindowOpener.swift b/App/Sources/UI/Windows/WindowOpener.swift index 2a5f2be32..3fa1c33ea 100644 --- a/App/Sources/UI/Windows/WindowOpener.swift +++ b/App/Sources/UI/Windows/WindowOpener.swift @@ -20,8 +20,8 @@ final class WindowOpener: ObservableObject { context: context, applicationStore: ApplicationStore.shared, configurationPublisher: core.configCoordinator.configurationPublisher, - contentPublisher: core.contentCoordinator.contentPublisher, - contentCoordinator: core.contentCoordinator, + contentPublisher: core.groupCoordinator.contentPublisher, + contentCoordinator: core.groupCoordinator, sidebarCoordinator: core.sidebarCoordinator ) .open(context) @@ -44,9 +44,9 @@ final class WindowOpener: ObservableObject { contentStore: core.contentStore, uiElementCaptureStore: core.uiElementCaptureStore, configurationPublisher: core.configCoordinator.configurationPublisher) { [core] workflowId, commandId, title, payload in - let groupIds = core.groupSelectionManager.selections + let groupIds = core.groupSelection.selections Task { - let transaction = core.detailCoordinator.updateTransaction + let transaction = core.workflowCoordinator.updateTransaction let updater = core.configurationUpdater updater.modifyWorkflow(using: transaction) { workflow in @@ -141,8 +141,8 @@ final class WindowOpener: ObservableObject { } workflow.updateOrAddCommand(command) } - core.contentCoordinator.handle(.selectWorkflow(workflowIds: [workflowId])) - core.contentCoordinator.handle(.refresh(groupIds)) + core.groupCoordinator.handle(.selectWorkflow(workflowIds: [workflowId])) + core.groupCoordinator.handle(.refresh(groupIds)) } }.open() } diff --git a/UnitTests/Sources/Models/ContentViewActionReducerTests.swift b/UnitTests/Sources/Models/ContentViewActionReducerTests.swift index bc7c3d313..c4cf6904b 100644 --- a/UnitTests/Sources/Models/ContentViewActionReducerTests.swift +++ b/UnitTests/Sources/Models/ContentViewActionReducerTests.swift @@ -9,14 +9,14 @@ final class ContentViewActionReducerTests: XCTestCase { var subject = subject(id) // Nothing should happen because `.rerender` is no-op. - ContentViewActionReducer.reduce(.refresh([id]), groupStore: ctx.store, + GroupDetailViewActionReducer.reduce(.refresh([id]), groupStore: ctx.store, selectionManager: ctx.selector, group: &subject.original) XCTAssertEqual(subject.original, subject.copy) // Nothing should happen because `.selectWorkflow` is no-op. - ContentViewActionReducer.reduce(.selectWorkflow(workflowIds: []), groupStore: ctx.store, + GroupDetailViewActionReducer.reduce(.selectWorkflow(workflowIds: []), groupStore: ctx.store, selectionManager: ctx.selector, group: &subject.original) @@ -31,11 +31,11 @@ final class ContentViewActionReducerTests: XCTestCase { ]), .init(id: "group-2-id", name: "group-2-name", workflows: []) ]) - let action: ContentView.Action = .moveWorkflowsToGroup("group-2-id", + let action: GroupDetailView.Action = .moveWorkflowsToGroup("group-2-id", workflows: ["workflow-1-id", "workflow-2-id"]) var subject = ctx.store.groups[0] - ContentViewActionReducer.reduce(action, groupStore: ctx.store, + GroupDetailViewActionReducer.reduce(action, groupStore: ctx.store, selectionManager: ctx.selector, group: &subject) @@ -54,14 +54,14 @@ final class ContentViewActionReducerTests: XCTestCase { ]), .init(id: "group-2-id", name: "group-2-name", workflows: []) ]) - let action: ContentView.Action = .addWorkflow(workflowId: "workflow-3-id") + let action: GroupDetailView.Action = .addWorkflow(workflowId: "workflow-3-id") var subject = ctx.store.groups[0] XCTAssertEqual(subject.workflows[0].id, "workflow-1-id") XCTAssertEqual(subject.workflows[1].id, "workflow-2-id") XCTAssertEqual(subject.workflows.count, 2) - ContentViewActionReducer.reduce(action, groupStore: ctx.store, + GroupDetailViewActionReducer.reduce(action, groupStore: ctx.store, selectionManager: ctx.selector, group: &subject) @@ -85,7 +85,7 @@ final class ContentViewActionReducerTests: XCTestCase { XCTAssertEqual(subject.workflows.count, 2) // Remove workflow-1-id and check that there is still one left. - ContentViewActionReducer.reduce(.removeWorkflows(["workflow-1-id"]), groupStore: ctx.store, + GroupDetailViewActionReducer.reduce(.removeWorkflows(["workflow-1-id"]), groupStore: ctx.store, selectionManager: ctx.selector, group: &subject) @@ -94,7 +94,7 @@ final class ContentViewActionReducerTests: XCTestCase { XCTAssertEqual(subject.workflows[0].id, "workflow-2-id") // Remove workflow-2-id and check that the workflows are removed. - ContentViewActionReducer.reduce(.removeWorkflows(["workflow-2-id"]), groupStore: ctx.store, + GroupDetailViewActionReducer.reduce(.removeWorkflows(["workflow-2-id"]), groupStore: ctx.store, selectionManager: ctx.selector, group: &subject) XCTAssertTrue(subject.workflows.isEmpty) @@ -113,10 +113,10 @@ final class ContentViewActionReducerTests: XCTestCase { var indexSet = IndexSet() indexSet.insert(2) - let action: ContentView.Action = .reorderWorkflows(source: indexSet, destination: 0) + let action: GroupDetailView.Action = .reorderWorkflows(source: indexSet, destination: 0) var subject = ctx.store.groups[0] - ContentViewActionReducer.reduce(action, groupStore: ctx.store, + GroupDetailViewActionReducer.reduce(action, groupStore: ctx.store, selectionManager: ctx.selector, group: &subject) @@ -136,7 +136,7 @@ final class ContentViewActionReducerTests: XCTestCase { } private func context(_ groups: [WorkflowGroup] = []) -> (store: GroupStore, - selector: SelectionManager) { + selector: SelectionManager) { (store: GroupStore(groups), selector: SelectionManager()) } }