@@ -14,6 +14,17 @@ struct UtilityAreaOutputView: View {
1414 case languageServer( LanguageServerLogContainer )
1515 case devOutput
1616
17+ var title : String {
18+ switch self {
19+ case . extensions( let source) :
20+ " Extension - \( source. extensionInfo. name) "
21+ case . languageServer( let source) :
22+ " Language Server - \( source. id) "
23+ case . devOutput:
24+ " Internal Development Output "
25+ }
26+ }
27+
1728 public static func == ( _ lhs: Sources , _ rhs: Sources ) -> Bool {
1829 switch ( lhs, rhs) {
1930 case let ( . extensions( lhs) , . extensions( rhs) ) :
@@ -41,160 +52,47 @@ struct UtilityAreaOutputView: View {
4152 }
4253 }
4354
44- @AppSettings ( \. developerSettings. showInternalDevelopmentInspector)
45- var showInternalDevelopmentInspector
46-
47- @EnvironmentObject private var workspace : WorkspaceDocument
4855 @EnvironmentObject private var utilityAreaViewModel : UtilityAreaViewModel
49- @ObservedObject var extensionManager = ExtensionManager . shared
50- @Service var lspService : LSPService
5156
5257 @State private var filterText : String = " "
5358 @State private var selectedSource : Sources ?
5459
55- var languageServerClients : [ LSPService . LanguageServerType ] {
56- lspService. languageClients. compactMap { ( key: LSPService . ClientKey , value: LSPService . LanguageServerType ) in
57- if key. workspacePath == workspace. fileURL? . absolutePath {
58- return value
59- }
60- return nil
61- }
62- }
63-
6460 var body : some View {
6561 UtilityAreaTabView ( model: utilityAreaViewModel. tabViewModel) { _ in
6662 Group {
6763 if let selectedSource {
6864 switch selectedSource {
6965 case . extensions( let source) :
70- OutputView ( source: source, filterText: $filterText)
66+ UtilityAreaOutputLogList ( source: source, filterText: $filterText) {
67+ UtilityAreaOutputSourcePicker ( selectedSource: $selectedSource)
68+ }
7169 case . languageServer( let source) :
72- OutputView ( source: source, filterText: $filterText)
70+ UtilityAreaOutputLogList ( source: source, filterText: $filterText) {
71+ UtilityAreaOutputSourcePicker ( selectedSource: $selectedSource)
72+ }
7373 case . devOutput:
74- OutputView ( source: InternalDevelopmentOutputSource . shared, filterText: $filterText)
74+ UtilityAreaOutputLogList (
75+ source: InternalDevelopmentOutputSource . shared,
76+ filterText: $filterText
77+ ) {
78+ UtilityAreaOutputSourcePicker ( selectedSource: $selectedSource)
79+ }
7580 }
7681 } else {
7782 Text ( " No output " )
7883 . font ( . system( size: 16 ) )
7984 . foregroundColor ( . secondary)
8085 . frame ( maxHeight: . infinity)
81- }
82- }
83- . paneToolbar {
84- Picker ( " Output Source " , selection: $selectedSource) {
85- if selectedSource == nil {
86- Text ( " No Selection " )
87- . tag ( nil as Sources ? )
88- }
89-
90- if extensionManager. extensions. isEmpty {
91- Text ( " No Extensions " )
92- }
93- ForEach ( extensionManager. extensions) { extensionInfo in
94- Text ( extensionInfo. name)
95- . tag ( Sources . extensions ( . init( extensionInfo: extensionInfo) ) )
96- }
97- Divider ( )
98-
99- if languageServerClients. isEmpty {
100- Text ( " No Language Servers " )
101- }
102- ForEach ( languageServerClients, id: \. languageId) { server in
103- Text ( server. languageId. rawValue)
104- . tag ( Sources . languageServer ( server. logContainer) )
105- }
106-
107- if showInternalDevelopmentInspector {
108- Divider ( )
109- Text ( " Development Output " )
110- . tag ( Sources . devOutput)
111- }
112- }
113- . buttonStyle ( . borderless)
114- . labelsHidden ( )
115- . controlSize ( . small)
116- Spacer ( )
117- UtilityAreaFilterTextField ( title: " Filter " , text: $filterText)
118- . frame ( maxWidth: 175 )
119- // Button {
120- // output = []
121- // } label: {
122- // Image(systemName: "trash")
123- // }
124- }
125- }
126- }
127-
128- struct OutputView < Source: UtilityAreaOutputSource > : View {
129- let source : Source
130-
131- @State var output : [ Source . Message ] = [ ]
132- @Binding var filterText : String
133-
134- var filteredOutput : [ Source . Message ] {
135- if filterText. isEmpty {
136- return output
137- }
138- return output. filter { item in
139- return filterText == " " ? true : item. message. contains ( filterText)
140- }
141- }
142-
143- var body : some View {
144- List ( filteredOutput. reversed ( ) ) { item in
145- VStack ( spacing: 2 ) {
146- HStack ( spacing: 0 ) {
147- Text ( item. message)
148- . fontDesign ( . monospaced)
149- . font ( . system( size: 12 , weight: . regular) . monospaced ( ) )
150- Spacer ( minLength: 0 )
151- }
152- HStack ( spacing: 6 ) {
153- HStack ( spacing: 4 ) {
154- Image ( systemName: item. level. iconName)
155- . foregroundColor ( . white)
156- . font ( . system( size: 7 , weight: . semibold) )
157- . frame ( width: 12 , height: 12 )
158- . background (
159- RoundedRectangle ( cornerRadius: 2 )
160- . fill ( item. level. color)
161- . aspectRatio ( 1.0 , contentMode: . fit)
162- )
163- Text ( item. date. logFormatted ( ) )
164- . fontWeight ( . medium)
165- }
166- if let subsystem = item. subsystem {
167- HStack ( spacing: 2 ) {
168- Image ( systemName: " gearshape.2 " )
169- . font ( . system( size: 8 , weight: . regular) )
170- Text ( subsystem)
86+ . paneToolbar {
87+ UtilityAreaOutputSourcePicker ( selectedSource: $selectedSource)
88+ Spacer ( )
89+ UtilityAreaFilterTextField ( title: " Filter " , text: $filterText)
90+ . frame ( maxWidth: 175 )
91+ Button { } label: {
92+ Image ( systemName: " trash " )
17193 }
94+ . disabled ( true )
17295 }
173- if let category = item. category {
174- HStack ( spacing: 2 ) {
175- Image ( systemName: " square.grid.3x3 " )
176- . font ( . system( size: 8 , weight: . regular) )
177- Text ( category)
178- }
179- }
180- Spacer ( minLength: 0 )
181- }
182- . foregroundStyle ( . secondary)
183- . font ( . system( size: 9 , weight: . semibold) . monospaced ( ) )
184- }
185- . rotationEffect ( . radians( . pi) )
186- . scaleEffect ( x: - 1 , y: 1 , anchor: . center)
187- . alignmentGuide ( . listRowSeparatorLeading) { _ in 0 }
188- . listRowBackground ( item. level. backgroundColor)
189- }
190- . listStyle ( . plain)
191- . listRowInsets ( EdgeInsets ( ) )
192- . rotationEffect ( . radians( . pi) )
193- . scaleEffect ( x: - 1 , y: 1 , anchor: . center)
194- . task ( id: source. id) {
195- output = source. cachedMessages ( )
196- for await item in source. streamMessages ( ) {
197- output. append ( item)
19896 }
19997 }
20098 }
0 commit comments