@@ -11,11 +11,14 @@ public struct MenuView: View {
11
11
@Environment ( \. openWindow) private var openWindow
12
12
13
13
private static let sliderWidth : CGFloat = 270
14
+ public static let MenuDisclosureSectionPaddingFix : CGFloat = - 14.0
14
15
15
16
@Binding private var isMenuPresented : Bool
16
17
17
18
@State private var isLoading = true
18
19
@State private var profile : ExtensionProfile ?
20
+
21
+ @EnvironmentObject private var commandClient : CommandClient
19
22
20
23
public init ( isMenuPresented: Binding < Bool > ) {
21
24
_isMenuPresented = isMenuPresented
@@ -41,6 +44,9 @@ public struct MenuView: View {
41
44
if let profile {
42
45
ProfilePicker ( profile)
43
46
}
47
+ if ( commandClient. clashModeList. count > 0 ) {
48
+ ClashOutboundPicker ( )
49
+ }
44
50
Divider ( )
45
51
MenuCommand {
46
52
NSApp . setActivationPolicy ( . regular)
@@ -118,6 +124,7 @@ public struct MenuView: View {
118
124
@State private var selectedProfileID : Int64 = 0
119
125
@State private var reasserting = false
120
126
@State private var alert : Alert ?
127
+ @State private var isExpanded = false
121
128
122
129
private var selectedProfileIDLocal : Binding < Int64 > {
123
130
$selectedProfileID. withSetter { newValue in
@@ -140,14 +147,22 @@ public struct MenuView: View {
140
147
if profileList. isEmpty {
141
148
Text ( " Empty profiles " )
142
149
} else {
143
- MenuSection ( " Profile " )
144
- Picker ( " " , selection: selectedProfileIDLocal) {
145
- ForEach ( profileList, id: \. id) { profile in
146
- Text ( profile. name)
150
+ Divider ( )
151
+ MenuDisclosureSection (
152
+ profileList. firstIndex ( where: { $0. id == selectedProfileIDLocal. wrappedValue } ) . map { " Profile: \( profileList [ $0] . name) " } ?? " Profile " ,
153
+ divider: false ,
154
+ isExpanded: $isExpanded
155
+ ) {
156
+ Picker ( " " , selection: selectedProfileIDLocal) {
157
+ ForEach ( profileList, id: \. id) { profile in
158
+ Text ( profile. name) . frame ( maxWidth: . infinity, alignment: . leading)
159
+ }
147
160
}
161
+ . pickerStyle ( . inline)
162
+ . disabled ( !profile. status. isSwitchable || reasserting)
148
163
}
149
- . pickerStyle ( . inline )
150
- . disabled ( !profile . status . isSwitchable || reasserting )
164
+ . padding ( . leading , MenuView . MenuDisclosureSectionPaddingFix )
165
+ . padding ( . trailing , MenuView . MenuDisclosureSectionPaddingFix )
151
166
}
152
167
}
153
168
}
@@ -204,4 +219,52 @@ public struct MenuView: View {
204
219
try LibboxNewStandaloneCommandClient ( ) ? . serviceReload ( )
205
220
}
206
221
}
222
+
223
+ private struct ClashOutboundPicker : View {
224
+ @EnvironmentObject private var commandClient : CommandClient
225
+ @State private var isclashModeExpanded = false
226
+ @State private var alert : Alert ?
227
+
228
+ @State private var wifiSelection : MenuEntry . ID ? = " Wi-Fi Art Thou Romeo "
229
+
230
+ private var clashLists : [ MenuEntry ] {
231
+ commandClient. clashModeList. map { stringValue in
232
+ MenuEntry ( name: stringValue, systemImage: " " )
233
+ }
234
+ }
235
+
236
+ var body : some View {
237
+ viewBuilder {
238
+ Divider ( )
239
+ MenuDisclosureSection ( " Outbound: " + commandClient. clashMode, divider: false , isExpanded: $isclashModeExpanded) {
240
+ MenuScrollView ( maxHeight: 135 ) {
241
+ ForEach ( commandClient. clashModeList, id: \. self) { it in
242
+ MenuCommand {
243
+ commandClient. clashMode = it;
244
+ } label: {
245
+ if it == commandClient. clashMode {
246
+ Image ( systemName: " play.fill " )
247
+ }
248
+ Text ( it)
249
+ }
250
+ . padding ( . leading, MenuView . MenuDisclosureSectionPaddingFix)
251
+ . padding ( . trailing, MenuView . MenuDisclosureSectionPaddingFix)
252
+ }
253
+ }
254
+ }
255
+ . padding ( . leading, MenuView . MenuDisclosureSectionPaddingFix)
256
+ . padding ( . trailing, MenuView . MenuDisclosureSectionPaddingFix)
257
+ }
258
+ . alertBinding ( $alert)
259
+ }
260
+ private nonisolated func setClashMode( _ newMode: String ) async {
261
+ do {
262
+ try LibboxNewStandaloneCommandClient ( ) !. setClashMode ( newMode)
263
+ } catch {
264
+ await MainActor . run {
265
+ alert = Alert ( error)
266
+ }
267
+ }
268
+ }
269
+ }
207
270
}
0 commit comments