Skip to content

Commit 711bf31

Browse files
committed
feat: menubar refine
pass global commandClient as Enviroment Object show clash outbound in menubar use MenuDisclosureSection to save space of Profile and Outbound
1 parent 9d53043 commit 711bf31

File tree

4 files changed

+74
-13
lines changed

4 files changed

+74
-13
lines changed

ApplicationLibrary/Views/Dashboard/ClashModeView.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,17 @@ import SwiftUI
55
@MainActor
66
public struct ClashModeView: View {
77
@Environment(\.scenePhase) private var scenePhase
8-
@StateObject private var commandClient = CommandClient(.clashMode)
9-
@State private var clashMode = ""
8+
@EnvironmentObject private var commandClient: CommandClient
109
@State private var alert: Alert?
1110

1211
public init() {}
1312
public var body: some View {
1413
VStack {
1514
if commandClient.clashModeList.count > 1 {
1615
Picker("", selection: Binding(get: {
17-
clashMode
16+
commandClient.clashMode
1817
}, set: { newMode in
19-
clashMode = newMode
18+
commandClient.clashMode = newMode
2019
Task {
2120
await setClashMode(newMode)
2221
}
@@ -29,9 +28,6 @@ public struct ClashModeView: View {
2928
.padding([.top], 8)
3029
}
3130
}
32-
.onReceive(commandClient.$clashMode) { newMode in
33-
clashMode = newMode
34-
}
3531
.padding([.leading, .trailing])
3632
.onAppear {
3733
commandClient.connect()

ApplicationLibrary/Views/Dashboard/OverviewView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public struct OverviewView: View {
3636
if ApplicationLibrary.inPreview || profile.status.isConnected {
3737
ExtensionStatusView()
3838
ClashModeView()
39+
.environmentObject(environments.logClient)
3940
}
4041
if profileList.isEmpty {
4142
Text("Empty profiles")

MacLibrary/MacApplication.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public struct MacApplication: Scene {
4646
MenuBarExtra(isInserted: $showMenuBarExtra) {
4747
MenuView(isMenuPresented: $isMenuPresented)
4848
.environmentObject(environments)
49+
.environmentObject(environments.logClient)
4950
} label: {
5051
Image("MenuIcon")
5152
}

MacLibrary/MenuView.swift

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ public struct MenuView: View {
1111
@Environment(\.openWindow) private var openWindow
1212

1313
private static let sliderWidth: CGFloat = 270
14+
public static let MenuDisclosureSectionPaddingFix: CGFloat = -14.0
1415

1516
@Binding private var isMenuPresented: Bool
1617

1718
@State private var isLoading = true
1819
@State private var profile: ExtensionProfile?
20+
21+
@EnvironmentObject private var commandClient: CommandClient
1922

2023
public init(isMenuPresented: Binding<Bool>) {
2124
_isMenuPresented = isMenuPresented
@@ -41,6 +44,9 @@ public struct MenuView: View {
4144
if let profile {
4245
ProfilePicker(profile)
4346
}
47+
if( commandClient.clashModeList.count > 0) {
48+
ClashOutboundPicker()
49+
}
4450
Divider()
4551
MenuCommand {
4652
NSApp.setActivationPolicy(.regular)
@@ -118,6 +124,7 @@ public struct MenuView: View {
118124
@State private var selectedProfileID: Int64 = 0
119125
@State private var reasserting = false
120126
@State private var alert: Alert?
127+
@State private var isExpanded = false
121128

122129
private var selectedProfileIDLocal: Binding<Int64> {
123130
$selectedProfileID.withSetter { newValue in
@@ -140,14 +147,22 @@ public struct MenuView: View {
140147
if profileList.isEmpty {
141148
Text("Empty profiles")
142149
} 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+
}
147160
}
161+
.pickerStyle(.inline)
162+
.disabled(!profile.status.isSwitchable || reasserting)
148163
}
149-
.pickerStyle(.inline)
150-
.disabled(!profile.status.isSwitchable || reasserting)
164+
.padding(.leading, MenuView.MenuDisclosureSectionPaddingFix)
165+
.padding(.trailing, MenuView.MenuDisclosureSectionPaddingFix)
151166
}
152167
}
153168
}
@@ -204,4 +219,52 @@ public struct MenuView: View {
204219
try LibboxNewStandaloneCommandClient()?.serviceReload()
205220
}
206221
}
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+
}
207270
}

0 commit comments

Comments
 (0)