66//
77
88import SwiftUI
9+ import Combine
910
1011struct TasksCommands : Commands {
1112 @UpdatingWindowController var windowController : CodeEditWindowController ?
@@ -14,29 +15,41 @@ struct TasksCommands: Commands {
1415 windowController? . workspace? . taskManager
1516 }
1617
17- var selectedTask : CETask ? {
18- taskManager ? . availableTasks . first ( where : { $0 . id == taskManager ? . selectedTaskID } )
19- }
18+ @ State private var activeTaskStatus : CETaskStatus = . notRunning
19+ @ State private var taskManagerListener : AnyCancellable ?
20+ @ State private var statusListener : AnyCancellable ?
2021
2122 var body : some Commands {
2223 CommandMenu ( " Tasks " ) {
23- let selectedTaskName : String ? = if let selectedTask {
24+ let selectedTaskName : String = if let selectedTask = taskManager ? . selectedTask {
2425 " \" " + selectedTask. name + " \" "
2526 } else {
26- nil
27+ " (No Selected Task) "
2728 }
2829
29- Button ( " Run \( selectedTaskName ?? " (No Selected Task) " ) " ) {
30+ Button ( " Run \( selectedTaskName) " , systemImage : " play.fill " ) {
3031 taskManager? . executeActiveTask ( )
32+ showOutput ( )
3133 }
32- . keyboardShortcut ( " r " , modifiers : . command )
34+ . keyboardShortcut ( " R " )
3335 . disabled ( taskManager? . selectedTaskID == nil )
3436
35- Button ( " Stop \( selectedTaskName ?? " (No Selected Task) " ) " ) {
36- taskManager? . terminateSelectedTask ( )
37+ Button ( " Stop \( selectedTaskName) " , systemImage: " stop.fill " ) {
38+ taskManager? . terminateActiveTask ( )
39+ }
40+ . keyboardShortcut ( " . " )
41+ . onChange ( of: windowController) { _ in
42+ taskManagerListener = taskManager? . objectWillChange. sink {
43+ updateStatusListener ( )
44+ }
45+ }
46+ . disabled ( activeTaskStatus != . running)
47+
48+ Button ( " Show \( selectedTaskName) Output " ) {
49+ showOutput ( )
3750 }
38- . keyboardShortcut ( " . " , modifiers : . command )
39- . disabled ( taskManager? . activeTasks. isEmpty == true )
51+ // Disable when there's no output yet
52+ . disabled ( taskManager? . activeTasks [ taskManager ? . selectedTaskID ?? UUID ( ) ] == nil )
4053
4154 Divider ( )
4255
@@ -48,19 +61,54 @@ struct TasksCommands: Commands {
4861 }
4962 }
5063 }
64+
65+ if taskManager? . availableTasks. isEmpty ?? true {
66+ Button ( " Create Tasks " ) {
67+ openSettings ( )
68+ }
69+ }
5170 } label: {
5271 Text ( " Choose Task... " )
5372 }
5473 . disabled ( taskManager? . availableTasks. isEmpty == true )
5574
5675 Button ( " Manage Tasks... " ) {
57- NSApp . sendAction (
58- #selector( CodeEditWindowController . openWorkspaceSettings ( _: ) ) ,
59- to: windowController,
60- from: nil
61- )
76+ openSettings ( )
6277 }
6378 . disabled ( windowController == nil )
6479 }
6580 }
81+
82+ /// Update the ``statusListener`` to listen to a potentially new active task.
83+ private func updateStatusListener( ) {
84+ statusListener? . cancel ( )
85+ guard let taskManager else { return }
86+
87+ activeTaskStatus = taskManager. activeTasks [ taskManager. selectedTaskID ?? UUID ( ) ] ? . status ?? . notRunning
88+ guard let id = taskManager. selectedTaskID else { return }
89+
90+ statusListener = taskManager. activeTasks [ id] ? . $status. sink { newValue in
91+ activeTaskStatus = newValue
92+ }
93+ }
94+
95+ private func showOutput( ) {
96+ guard let utilityAreaModel = windowController? . workspace? . utilityAreaModel else {
97+ return
98+ }
99+ if utilityAreaModel. isCollapsed {
100+ // Open the utility area
101+ utilityAreaModel. isCollapsed. toggle ( )
102+ }
103+ utilityAreaModel. selectedTab = . debugConsole // Switch to the correct tab
104+ taskManager? . taskShowingOutput = taskManager? . selectedTaskID // Switch to the selected task
105+ }
106+
107+ private func openSettings( ) {
108+ NSApp . sendAction (
109+ #selector( CodeEditWindowController . openWorkspaceSettings ( _: ) ) ,
110+ to: windowController,
111+ from: nil
112+ )
113+ }
66114}
0 commit comments