mirror of
https://github.com/yJason/ClashX-Dashboard.git
synced 2026-03-01 00:35:19 +08:00
feat: config view
This commit is contained in:
@@ -60,6 +60,7 @@
|
|||||||
01CD0A9229E93ABB00F4C17E /* DifferenceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 01CD0A9129E93ABB00F4C17E /* DifferenceKit */; };
|
01CD0A9229E93ABB00F4C17E /* DifferenceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 01CD0A9129E93ABB00F4C17E /* DifferenceKit */; };
|
||||||
01DCEFB12A150E8B00DBBDB3 /* RuleProvidersRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DCEFB02A150E8B00DBBDB3 /* RuleProvidersRowView.swift */; };
|
01DCEFB12A150E8B00DBBDB3 /* RuleProvidersRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DCEFB02A150E8B00DBBDB3 /* RuleProvidersRowView.swift */; };
|
||||||
01DCEFB32A150FB300DBBDB3 /* ProxyProvidersRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DCEFB22A150FB300DBBDB3 /* ProxyProvidersRowView.swift */; };
|
01DCEFB32A150FB300DBBDB3 /* ProxyProvidersRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DCEFB22A150FB300DBBDB3 /* ProxyProvidersRowView.swift */; };
|
||||||
|
01F5E3F42A1E53F4008F3DEB /* ConfigItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F5E3F32A1E53F4008F3DEB /* ConfigItemView.swift */; };
|
||||||
01F885CF29DFD8DF008241EB /* CollectionsTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F885CE29DFD8DF008241EB /* CollectionsTableView.swift */; };
|
01F885CF29DFD8DF008241EB /* CollectionsTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F885CE29DFD8DF008241EB /* CollectionsTableView.swift */; };
|
||||||
01F885D129E03F20008241EB /* CollectionTableCellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01F885D029E03F20008241EB /* CollectionTableCellView.xib */; };
|
01F885D129E03F20008241EB /* CollectionTableCellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01F885D029E03F20008241EB /* CollectionTableCellView.xib */; };
|
||||||
01F885D329E04E21008241EB /* ProxyGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F885D229E04E21008241EB /* ProxyGroupView.swift */; };
|
01F885D329E04E21008241EB /* ProxyGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F885D229E04E21008241EB /* ProxyGroupView.swift */; };
|
||||||
@@ -115,6 +116,7 @@
|
|||||||
01A3EF032A120103003038B5 /* DBProxyStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBProxyStorage.swift; sourceTree = "<group>"; };
|
01A3EF032A120103003038B5 /* DBProxyStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBProxyStorage.swift; sourceTree = "<group>"; };
|
||||||
01DCEFB02A150E8B00DBBDB3 /* RuleProvidersRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleProvidersRowView.swift; sourceTree = "<group>"; };
|
01DCEFB02A150E8B00DBBDB3 /* RuleProvidersRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleProvidersRowView.swift; sourceTree = "<group>"; };
|
||||||
01DCEFB22A150FB300DBBDB3 /* ProxyProvidersRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyProvidersRowView.swift; sourceTree = "<group>"; };
|
01DCEFB22A150FB300DBBDB3 /* ProxyProvidersRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyProvidersRowView.swift; sourceTree = "<group>"; };
|
||||||
|
01F5E3F32A1E53F4008F3DEB /* ConfigItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigItemView.swift; sourceTree = "<group>"; };
|
||||||
01F885CE29DFD8DF008241EB /* CollectionsTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionsTableView.swift; sourceTree = "<group>"; };
|
01F885CE29DFD8DF008241EB /* CollectionsTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionsTableView.swift; sourceTree = "<group>"; };
|
||||||
01F885D029E03F20008241EB /* CollectionTableCellView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CollectionTableCellView.xib; sourceTree = "<group>"; };
|
01F885D029E03F20008241EB /* CollectionTableCellView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CollectionTableCellView.xib; sourceTree = "<group>"; };
|
||||||
01F885D229E04E21008241EB /* ProxyGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyGroupView.swift; sourceTree = "<group>"; };
|
01F885D229E04E21008241EB /* ProxyGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyGroupView.swift; sourceTree = "<group>"; };
|
||||||
@@ -356,6 +358,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
0192317D29DD5E0100539EDD /* ConfigView.swift */,
|
0192317D29DD5E0100539EDD /* ConfigView.swift */,
|
||||||
|
01F5E3F32A1E53F4008F3DEB /* ConfigItemView.swift */,
|
||||||
);
|
);
|
||||||
path = Config;
|
path = Config;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -480,6 +483,7 @@
|
|||||||
01F885D529E053DE008241EB /* ProxyItemView.swift in Sources */,
|
01F885D529E053DE008241EB /* ProxyItemView.swift in Sources */,
|
||||||
0192B5D029DE5151002CDBF3 /* ClashRuleProvider.swift in Sources */,
|
0192B5D029DE5151002CDBF3 /* ClashRuleProvider.swift in Sources */,
|
||||||
01DCEFB12A150E8B00DBBDB3 /* RuleProvidersRowView.swift in Sources */,
|
01DCEFB12A150E8B00DBBDB3 /* RuleProvidersRowView.swift in Sources */,
|
||||||
|
01F5E3F42A1E53F4008F3DEB /* ConfigItemView.swift in Sources */,
|
||||||
0192317129DD566000539EDD /* SidebarView.swift in Sources */,
|
0192317129DD566000539EDD /* SidebarView.swift in Sources */,
|
||||||
0192B5D129DE5151002CDBF3 /* ClashRule.swift in Sources */,
|
0192B5D129DE5151002CDBF3 /* ClashRule.swift in Sources */,
|
||||||
0192317C29DD5DF200539EDD /* ConnectionsView.swift in Sources */,
|
0192317C29DD5DF200539EDD /* ConnectionsView.swift in Sources */,
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// ConfigItemView.swift
|
||||||
|
// ClashX Dashboard
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ConfigItemView<Content: View>: View {
|
||||||
|
|
||||||
|
@State var name: String
|
||||||
|
var content: () -> Content
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
HStack {
|
||||||
|
Text(name)
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
HStack(content: content)
|
||||||
|
}
|
||||||
|
.padding(EdgeInsets(top: 10, leading: 13, bottom: 10, trailing: 13))
|
||||||
|
.background(Color(nsColor: .textBackgroundColor))
|
||||||
|
.cornerRadius(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ConfigItemView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
ConfigItemView(name: "test") {
|
||||||
|
Text("label")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,117 +12,239 @@ struct ConfigView: View {
|
|||||||
@State var socks5Port: Int = 0
|
@State var socks5Port: Int = 0
|
||||||
@State var mixedPort: Int = 0
|
@State var mixedPort: Int = 0
|
||||||
@State var redirPort: Int = 0
|
@State var redirPort: Int = 0
|
||||||
@State var mode: String = "Rule"
|
@State var mode: ClashProxyMode = .direct
|
||||||
@State var logLevel: String = "Debug"
|
@State var logLevel: ClashLogLevel = .unknow
|
||||||
@State var allowLAN: Bool = false
|
@State var allowLAN: Bool = false
|
||||||
@State var sniffer: Bool = false
|
@State var sniffer: Bool = false
|
||||||
|
@State var ipv6: Bool = false
|
||||||
|
|
||||||
@State var enableTUNDevice: Bool = false
|
@State var enableTUNDevice: Bool = false
|
||||||
@State var tunIPStack: String = "System"
|
@State var tunIPStack: String = "System"
|
||||||
@State var deviceName: String = "utun9"
|
@State var deviceName: String = "utun9"
|
||||||
@State var interfaceName: String = "en0"
|
@State var interfaceName: String = "en0"
|
||||||
|
|
||||||
@State var disableAll = true
|
@State private var configInited = false
|
||||||
|
|
||||||
|
private let toggleStyle = SwitchToggleStyle()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVGrid(columns: [
|
modeView
|
||||||
GridItem(.flexible()),
|
|
||||||
GridItem(.flexible())
|
content1
|
||||||
]) {
|
.padding()
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text("Http Port")
|
|
||||||
TextField("0", value: $httpPort, formatter: NumberFormatter())
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text("Socks5 Port")
|
|
||||||
TextField("0", value: $socks5Port, formatter: NumberFormatter())
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text("Mixed Port")
|
|
||||||
TextField("0", value: $mixedPort, formatter: NumberFormatter())
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text("Redir Port")
|
|
||||||
TextField("0", value: $redirPort, formatter: NumberFormatter())
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text("Mode")
|
|
||||||
Picker("", selection: $mode) {
|
|
||||||
ForEach(["Direct", "Rule", "Script", "Global"], id: \.self) {
|
|
||||||
Text($0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.pickerStyle(.menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text("Log Level")
|
|
||||||
Picker("", selection: $logLevel) {
|
|
||||||
ForEach(["Silent", "Error", "Warning", "Info", "Debug"], id: \.self) {
|
|
||||||
Text($0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.pickerStyle(.menu)
|
|
||||||
}
|
|
||||||
Toggle("Allow LAN", isOn: $allowLAN)
|
|
||||||
Toggle("Sniffer", isOn: $sniffer)
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
LazyVGrid(columns: [
|
tunView
|
||||||
GridItem(.flexible()),
|
.padding()
|
||||||
GridItem(.flexible())
|
|
||||||
]) {
|
Divider()
|
||||||
Toggle("Enable TUN Device", isOn: $enableTUNDevice)
|
.padding()
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
content2
|
||||||
Text("TUN IP Stack")
|
.padding()
|
||||||
Picker("", selection: $tunIPStack) {
|
|
||||||
ForEach(["gVisor", "System", "LWIP"], id: \.self) {
|
|
||||||
Text($0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.pickerStyle(.menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text("Device Name")
|
|
||||||
TextField("utun9", text: $deviceName)
|
|
||||||
}
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text("Interface Name")
|
|
||||||
TextField("en0", text: $interfaceName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
}
|
||||||
.disabled(disableAll)
|
.disabled(!configInited)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
configInited = false
|
||||||
ApiRequest.requestConfig { config in
|
ApiRequest.requestConfig { config in
|
||||||
httpPort = config.port
|
httpPort = config.port
|
||||||
socks5Port = config.socksPort
|
socks5Port = config.socksPort
|
||||||
mixedPort = config.mixedPort
|
mixedPort = config.mixedPort
|
||||||
redirPort = config.redirPort
|
redirPort = config.redirPort
|
||||||
mode = config.mode.rawValue.capitalized
|
mode = config.mode
|
||||||
logLevel = config.logLevel.rawValue.capitalized
|
logLevel = config.logLevel
|
||||||
|
|
||||||
allowLAN = config.allowLan
|
allowLAN = config.allowLan
|
||||||
sniffer = config.sniffing
|
sniffer = config.sniffing
|
||||||
|
ipv6 = config.ipv6
|
||||||
|
|
||||||
enableTUNDevice = config.tun.enable
|
enableTUNDevice = config.tun.enable
|
||||||
tunIPStack = config.tun.stack
|
tunIPStack = config.tun.stack
|
||||||
deviceName = config.tun.device
|
deviceName = config.tun.device
|
||||||
interfaceName = config.interfaceName
|
interfaceName = config.interfaceName
|
||||||
|
|
||||||
|
configInited = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
configInited = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var modeView: some View {
|
||||||
|
Picker("", selection: $mode) {
|
||||||
|
ForEach([
|
||||||
|
ClashProxyMode.direct,
|
||||||
|
.rule,
|
||||||
|
.global
|
||||||
|
], id: \.self) {
|
||||||
|
Text($0.name).tag($0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: mode) { newValue in
|
||||||
|
guard configInited else { return }
|
||||||
|
ApiRequest.updateOutBoundMode(mode: newValue)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.controlSize(.large)
|
||||||
|
.labelsHidden()
|
||||||
|
.pickerStyle(.segmented)
|
||||||
|
}
|
||||||
|
|
||||||
|
var content1: some View {
|
||||||
|
LazyVGrid(columns: [
|
||||||
|
GridItem(.flexible()),
|
||||||
|
GridItem(.flexible())
|
||||||
|
], alignment: .leading) {
|
||||||
|
|
||||||
|
ConfigItemView(name: "Http Port") {
|
||||||
|
Text(String(httpPort))
|
||||||
|
.font(.system(size: 17))
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigItemView(name: "Socks5 Port") {
|
||||||
|
Text(String(socks5Port))
|
||||||
|
.font(.system(size: 17))
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigItemView(name: "Mixed Port") {
|
||||||
|
Text(String(mixedPort))
|
||||||
|
.font(.system(size: 17))
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigItemView(name: "Redir Port") {
|
||||||
|
Text(String(redirPort))
|
||||||
|
.font(.system(size: 17))
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigItemView(name: "Log Level") {
|
||||||
|
Text(logLevel.rawValue.capitalized)
|
||||||
|
.font(.system(size: 17))
|
||||||
|
|
||||||
|
// Picker("", selection: $logLevel) {
|
||||||
|
// ForEach([
|
||||||
|
// ClashLogLevel.silent,
|
||||||
|
// .error,
|
||||||
|
// .warning,
|
||||||
|
// .info,
|
||||||
|
// .debug,
|
||||||
|
// .unknow
|
||||||
|
// ], id: \.self) {
|
||||||
|
// Text($0.rawValue.capitalized).tag($0)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .disabled(true)
|
||||||
|
// .pickerStyle(.menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigItemView(name: "ipv6") {
|
||||||
|
Toggle("", isOn: $ipv6)
|
||||||
|
.toggleStyle(toggleStyle)
|
||||||
|
.disabled(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tunView: some View {
|
||||||
|
LazyVGrid(columns: [
|
||||||
|
GridItem(.flexible()),
|
||||||
|
GridItem(.flexible())
|
||||||
|
], alignment: .leading) {
|
||||||
|
|
||||||
|
|
||||||
|
ConfigItemView(name: "Enable TUN Device") {
|
||||||
|
Toggle("", isOn: $enableTUNDevice)
|
||||||
|
.toggleStyle(toggleStyle)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ConfigItemView(name: "TUN IP Stack") {
|
||||||
|
// Picker("", selection: $tunIPStack) {
|
||||||
|
// ForEach(["gVisor", "System", "LWIP"], id: \.self) {
|
||||||
|
// Text($0)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .pickerStyle(.menu)
|
||||||
|
|
||||||
|
Text(tunIPStack)
|
||||||
|
.font(.system(size: 17))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ConfigItemView(name: "Device Name") {
|
||||||
|
Text(deviceName)
|
||||||
|
.font(.system(size: 17))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ConfigItemView(name: "Interface Name") {
|
||||||
|
Text(interfaceName)
|
||||||
|
.font(.system(size: 17))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var content2: some View {
|
||||||
|
LazyVGrid(columns: [
|
||||||
|
GridItem(.flexible()),
|
||||||
|
GridItem(.flexible())
|
||||||
|
], alignment: .leading) {
|
||||||
|
|
||||||
|
ConfigItemView(name: "Allow LAN") {
|
||||||
|
Toggle("", isOn: $allowLAN)
|
||||||
|
.toggleStyle(toggleStyle)
|
||||||
|
.onChange(of: allowLAN) { newValue in
|
||||||
|
guard configInited else { return }
|
||||||
|
ApiRequest.updateAllowLan(allow: newValue) {
|
||||||
|
ApiRequest.requestConfig { config in
|
||||||
|
allowLAN = config.allowLan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigItemView(name: "Sniffer") {
|
||||||
|
Toggle("", isOn: $sniffer)
|
||||||
|
.toggleStyle(toggleStyle)
|
||||||
|
.onChange(of: sniffer) { newValue in
|
||||||
|
guard configInited else { return }
|
||||||
|
ApiRequest.updateSniffing(enable: newValue) {
|
||||||
|
ApiRequest.requestConfig { config in
|
||||||
|
sniffer = config.sniffing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ConfigItemView(name: "Reload") {
|
||||||
|
Button {
|
||||||
|
AppDelegate.shared.updateConfig()
|
||||||
|
} label: {
|
||||||
|
Text("Reload config file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
ConfigItemView(name: "GEO Databases") {
|
||||||
|
Button {
|
||||||
|
ApiRequest.updateGEO()
|
||||||
|
} label: {
|
||||||
|
Text("Update GEO Databases")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigItemView(name: "FakeIP") {
|
||||||
|
Button {
|
||||||
|
ApiRequest.flushFakeipCache()
|
||||||
|
} label: {
|
||||||
|
Text("Flush fake-iP data")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user