Skip to content

Commit

Permalink
Rename and organize UI into proper folders
Browse files Browse the repository at this point in the history
  • Loading branch information
zenangst committed Nov 8, 2024
1 parent d47763c commit ef924a9
Show file tree
Hide file tree
Showing 103 changed files with 544 additions and 692 deletions.
File renamed without changes.
40 changes: 20 additions & 20 deletions App/Sources/Core/Core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<KeyShortcut>()
lazy private(set) var applicationTriggerSelectionManager = SelectionManager<DetailViewModel.ApplicationTrigger>()
lazy private(set) var commandSelectionManager = SelectionManager<CommandViewModel>()
lazy private(set) var keyboardShortcutSelection = SelectionManager<KeyShortcut>()
lazy private(set) var applicationTriggerSelection = SelectionManager<DetailViewModel.ApplicationTrigger>()
lazy private(set) var commandSelection = SelectionManager<CommandViewModel>()

lazy private(set) var configSelectionManager = SelectionManager<ConfigurationViewModel>(initialSelection: [AppStorageContainer.shared.configId]) {
lazy private(set) var configSelection = SelectionManager<ConfigurationViewModel>(initialSelection: [AppStorageContainer.shared.configId]) {
AppStorageContainer.shared.configId = $0.first ?? ""
}

lazy private(set) var groupSelectionManager = SelectionManager<GroupViewModel>(initialSelection: AppStorageContainer.shared.groupIds) {
lazy private(set) var groupSelection = SelectionManager<GroupViewModel>(initialSelection: AppStorageContainer.shared.groupIds) {
AppStorageContainer.shared.groupIds = $0
}

lazy private(set) var contentSelectionManager = SelectionManager<ContentViewModel>(initialSelection: AppStorageContainer.shared.workflowIds) {
lazy private(set) var workflowsSelection = SelectionManager<GroupDetailViewModel>(initialSelection: AppStorageContainer.shared.workflowIds) {
AppStorageContainer.shared.workflowIds = $0
}

Expand Down Expand Up @@ -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)
})
Expand Down
14 changes: 7 additions & 7 deletions App/Sources/Core/KeyboardCowboyApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,25 @@ 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
windowOpener.openNewCommandWindow(.newCommand(workflowId: id))
}
)
.environmentObject(core.contentStore.groupStore)
.environmentObject(core.detailCoordinator.statePublisher)
.environmentObject(core.detailCoordinator.infoPublisher)
.environmentObject(core.workflowCoordinator.statePublisher)
.environmentObject(core.workflowCoordinator.infoPublisher)
}

CommandGroup(replacing: .toolbar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@ import Combine
import SwiftUI

@MainActor
final class ContentCoordinator {
final class GroupCoordinator {
private let applicationStore: ApplicationStore
private let contentSelectionManager: SelectionManager<ContentViewModel>
private let groupSelectionManager: SelectionManager<GroupViewModel>
private let mapper: ContentModelMapper
private let workflowsSelectionManager: SelectionManager<GroupDetailViewModel>
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<ContentViewModel>,
groupSelectionManager: SelectionManager<GroupViewModel>) {
groupSelectionManager: SelectionManager<GroupViewModel>,
workflowsSelectionManager: SelectionManager<GroupDetailViewModel>) {
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) {
Expand All @@ -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)
}
}
}
Expand All @@ -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 {
Expand Down Expand Up @@ -112,10 +112,10 @@ final class ContentCoordinator {
Benchmark.shared.start("ContentCoordinator.render")
defer { Benchmark.shared.stop("ContentCoordinator.render") }

var viewModels = [ContentViewModel]()
var newSelections = Set<ContentViewModel.ID>()
var selectedWorkflowIds = contentSelectionManager.selections
var firstViewModel: ContentViewModel?
var viewModels = [GroupDetailViewModel]()
var newSelections = Set<GroupDetailViewModel.ID>()
var selectedWorkflowIds = workflowsSelectionManager.selections
var firstViewModel: GroupDetailViewModel?

for offset in store.groups.indices {
let group = store.groups[offset]
Expand Down Expand Up @@ -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)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion App/Sources/UI/Coordinators/SidebarCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ final class SidebarCoordinator {
}
selectionManager.publish([groupId])
if storeWasEmpty {
withAnimation(WorkflowCommandListView.animation) {
withAnimation(CommandList.animation) {
render(store.groups)
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import Combine
import SwiftUI

@MainActor
final class DetailCoordinator {
final class WorkflowCoordinator {
private let applicationStore: ApplicationStore
private let applicationTriggerSelectionManager: SelectionManager<DetailViewModel.ApplicationTrigger>
private let applicationTriggerSelection: SelectionManager<DetailViewModel.ApplicationTrigger>
private let commandRunner: CommandRunner
private let commandSelectionManager: SelectionManager<CommandViewModel>
private let contentSelectionManager: SelectionManager<ContentViewModel>
private let commandSelection: SelectionManager<CommandViewModel>
private let workflowsSelection: SelectionManager<GroupDetailViewModel>
private let contentStore: ContentStore
private let groupSelectionManager: SelectionManager<GroupViewModel>
private let groupSelection: SelectionManager<GroupViewModel>
private let groupStore: GroupStore
private let keyboardCowboyEngine: KeyboardCowboyEngine
private let keyboardShortcutSelectionManager: SelectionManager<KeyShortcut>
private let keyboardShortcutSelection: SelectionManager<KeyShortcut>

let updateTransaction: UpdateTransaction = .init(groupID: "", workflowID: "")
let infoPublisher: InfoPublisher = .init(.init(id: "empty", name: "", isEnabled: false))
Expand All @@ -24,53 +24,53 @@ final class DetailCoordinator {
let statePublisher: DetailStatePublisher = .init(.empty)

init(applicationStore: ApplicationStore,
applicationTriggerSelectionManager: SelectionManager<DetailViewModel.ApplicationTrigger>,
applicationTriggerSelection: SelectionManager<DetailViewModel.ApplicationTrigger>,
commandRunner: CommandRunner,
commandSelectionManager: SelectionManager<CommandViewModel>,
contentSelectionManager: SelectionManager<ContentViewModel>,
commandSelection: SelectionManager<CommandViewModel>,
workflowsSelection: SelectionManager<GroupDetailViewModel>,
contentStore: ContentStore,
groupSelectionManager: SelectionManager<GroupViewModel>,
groupSelection: SelectionManager<GroupViewModel>,
keyboardCowboyEngine: KeyboardCowboyEngine,
keyboardShortcutSelectionManager: SelectionManager<KeyShortcut>,
keyboardShortcutSelection: SelectionManager<KeyShortcut>,
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(_:)))
}

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<ContentViewModel.ID>()
var workflowIds = Set<GroupDetailViewModel.ID>()

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 {
Expand All @@ -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)
}
}

Expand All @@ -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)
}
}
Expand Down
Loading

0 comments on commit ef924a9

Please sign in to comment.