Skip to content

Commit

Permalink
feat: menubar refine
Browse files Browse the repository at this point in the history
pass global commandClient as Enviroment Object
show clash outbound in menubar
use MenuDisclosureSection to save space of Profile and Outbound
  • Loading branch information
qinyuhang committed Aug 4, 2024
1 parent 12f20d3 commit 832d784
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 13 deletions.
10 changes: 3 additions & 7 deletions ApplicationLibrary/Views/Dashboard/ClashModeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@ import SwiftUI
@MainActor
public struct ClashModeView: View {
@Environment(\.scenePhase) private var scenePhase
@StateObject private var commandClient = CommandClient(.clashMode)
@State private var clashMode = ""
@EnvironmentObject private var commandClient: CommandClient
@State private var alert: Alert?

public init() {}
public var body: some View {
VStack {
if commandClient.clashModeList.count > 1 {
Picker("", selection: Binding(get: {
clashMode
commandClient.clashMode
}, set: { newMode in
clashMode = newMode
commandClient.clashMode = newMode
Task {
await setClashMode(newMode)
}
Expand All @@ -29,9 +28,6 @@ public struct ClashModeView: View {
.padding([.top], 8)
}
}
.onReceive(commandClient.$clashMode) { newMode in
clashMode = newMode
}
.padding([.leading, .trailing])
.onAppear {
commandClient.connect()
Expand Down
1 change: 1 addition & 0 deletions ApplicationLibrary/Views/Dashboard/OverviewView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public struct OverviewView: View {
if ApplicationLibrary.inPreview || profile.status.isConnected {
ExtensionStatusView()
ClashModeView()
.environmentObject(environments.logClient)
}
if profileList.isEmpty {
Text("Empty profiles")
Expand Down
1 change: 1 addition & 0 deletions MacLibrary/MacApplication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public struct MacApplication: Scene {
MenuBarExtra(isInserted: $showMenuBarExtra) {
MenuView(isMenuPresented: $isMenuPresented)
.environmentObject(environments)
.environmentObject(environments.logClient)
} label: {
Image("MenuIcon")
}
Expand Down
73 changes: 67 additions & 6 deletions MacLibrary/MenuView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ public struct MenuView: View {
@Environment(\.openWindow) private var openWindow

private static let sliderWidth: CGFloat = 270
public static let MenuDisclosureSectionPaddingFix: CGFloat = -14.0

@Binding private var isMenuPresented: Bool

@State private var isLoading = true
@State private var profile: ExtensionProfile?

@EnvironmentObject private var commandClient: CommandClient

public init(isMenuPresented: Binding<Bool>) {
_isMenuPresented = isMenuPresented
Expand All @@ -41,6 +44,9 @@ public struct MenuView: View {
if let profile {
ProfilePicker(profile)
}
if( commandClient.clashModeList.count > 0) {
ClashOutboundPicker()
}
Divider()
MenuCommand {
NSApp.setActivationPolicy(.regular)
Expand Down Expand Up @@ -118,6 +124,7 @@ public struct MenuView: View {
@State private var selectedProfileID: Int64 = 0
@State private var reasserting = false
@State private var alert: Alert?
@State private var isExpanded = false

private var selectedProfileIDLocal: Binding<Int64> {
$selectedProfileID.withSetter { newValue in
Expand All @@ -140,14 +147,22 @@ public struct MenuView: View {
if profileList.isEmpty {
Text("Empty profiles")
} else {
MenuSection("Profile")
Picker("", selection: selectedProfileIDLocal) {
ForEach(profileList, id: \.id) { profile in
Text(profile.name)
Divider()
MenuDisclosureSection(
profileList.firstIndex(where: { $0.id == selectedProfileIDLocal.wrappedValue }).map { "Profile: \(profileList[$0].name)" } ?? "Profile",
divider: false,
isExpanded: $isExpanded
) {
Picker("", selection: selectedProfileIDLocal) {
ForEach(profileList, id: \.id) { profile in
Text(profile.name).frame(maxWidth: .infinity, alignment: .leading)
}
}
.pickerStyle(.inline)
.disabled(!profile.status.isSwitchable || reasserting)
}
.pickerStyle(.inline)
.disabled(!profile.status.isSwitchable || reasserting)
.padding(.leading, MenuView.MenuDisclosureSectionPaddingFix)
.padding(.trailing, MenuView.MenuDisclosureSectionPaddingFix)
}
}
}
Expand Down Expand Up @@ -204,4 +219,50 @@ public struct MenuView: View {
try LibboxNewStandaloneCommandClient()!.serviceReload()
}
}

private struct ClashOutboundPicker: View {
@EnvironmentObject private var commandClient: CommandClient
@State private var isclashModeExpanded = false
@State private var alert: Alert?

private var clashLists: [MenuEntry] {
commandClient.clashModeList.map { stringValue in
MenuEntry(name: stringValue, systemImage: "")
}
}

var body: some View {
viewBuilder {
Divider()
MenuDisclosureSection("Outbound: " + commandClient.clashMode, divider: false, isExpanded: $isclashModeExpanded) {
MenuScrollView(maxHeight: 135) {
ForEach(commandClient.clashModeList, id: \.self) { it in
MenuCommand {
commandClient.clashMode = it;
} label: {
if it == commandClient.clashMode {
Image(systemName: "play.fill")
}
Text(it)
}
.padding(.leading, MenuView.MenuDisclosureSectionPaddingFix)
.padding(.trailing, MenuView.MenuDisclosureSectionPaddingFix)
}
}
}
.padding(.leading, MenuView.MenuDisclosureSectionPaddingFix)
.padding(.trailing, MenuView.MenuDisclosureSectionPaddingFix)
}
.alertBinding($alert)
}
private nonisolated func setClashMode(_ newMode: String) async {
do {
try LibboxNewStandaloneCommandClient()!.setClashMode(newMode)
} catch {
await MainActor.run {
alert = Alert(error)
}
}
}
}
}

0 comments on commit 832d784

Please sign in to comment.