Add swiftlint & Minor fixes

This commit is contained in:
世界
2025-11-27 16:10:55 +08:00
parent 8855e0eef9
commit 0bfb6d2516
29 changed files with 382 additions and 196 deletions
+21
View File
@@ -0,0 +1,21 @@
excluded:
- Frameworks
- Libbox.xcframework
- build
disabled_rules:
- identifier_name
- type_body_length
- file_length
- function_body_length
- cyclomatic_complexity
- large_tuple
- nesting
- line_length
- todo
- trailing_comma
- function_parameter_count
- type_name
- force_cast
- force_try
- opening_brace
@@ -27,20 +27,6 @@ public struct NavigationButtonsView: View {
public var body: some View {
HStack(spacing: 12) {
if showGroupsButton {
Divider()
Text(verbatim: "\(groupsCount)")
.font(.subheadline)
.foregroundStyle(.secondary)
.fixedSize()
Button {
onGroupsTap()
} label: {
Label("Groups", systemImage: "rectangle.3.group.fill")
}
.labelStyle(.iconOnly)
.foregroundStyle(.primary)
}
if showConnectionsButton {
Divider()
Text(verbatim: "\(connectionsCount)")
@@ -55,6 +41,20 @@ public struct NavigationButtonsView: View {
.labelStyle(.iconOnly)
.foregroundStyle(.primary)
}
if showGroupsButton {
Divider()
Text(verbatim: "\(groupsCount)")
.font(.subheadline)
.foregroundStyle(.secondary)
.fixedSize()
Button {
onGroupsTap()
} label: {
Label("Groups", systemImage: "rectangle.3.group.fill")
}
.labelStyle(.iconOnly)
.foregroundStyle(.primary)
}
}
}
}
@@ -24,13 +24,12 @@ public struct Connection: Codable {
public let outboundType: String
public let chain: [String]
var hashValue: Int {
var value = id.hashValue
(value, _) = value.addingReportingOverflow(upload.hashValue)
(value, _) = value.addingReportingOverflow(download.hashValue)
(value, _) = value.addingReportingOverflow(uploadTotal.hashValue)
(value, _) = value.addingReportingOverflow(downloadTotal.hashValue)
return value
func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(upload)
hasher.combine(download)
hasher.combine(uploadTotal)
hasher.combine(downloadTotal)
}
func performSearch(_ content: String) -> Bool {
@@ -17,7 +17,7 @@ public struct ConnectionListView: View {
} else {
ScrollView {
LazyVGrid(columns: [GridItem(.flexible())], alignment: .leading) {
ForEach(viewModel.filteredConnections(), id: \.hashValue) { it in
ForEach(viewModel.filteredConnections(), id: \.id) { it in
ConnectionView(it)
}
}
@@ -56,9 +56,19 @@ public struct ConnectionListView: View {
#endif
.alertBinding($viewModel.alert)
.onAppear {
viewModel.setCommandClient(environments.commandClient)
viewModel.connect()
}
.onReceive(environments.commandClient.$connections) { connections in
viewModel.setConnections(connections)
}
.onChangeCompat(of: viewModel.connectionStateFilter) { filter in
environments.commandClient.connectionStateFilter = filter
environments.commandClient.filterConnectionsNow()
}
.onChangeCompat(of: viewModel.connectionSort) { sort in
environments.commandClient.connectionSort = sort
environments.commandClient.filterConnectionsNow()
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
#if os(iOS)
.background(Color(uiColor: .systemGroupedBackground))
@@ -1,4 +1,3 @@
import Combine
import Libbox
import Library
import SwiftUI
@@ -11,8 +10,6 @@ public class ConnectionListViewModel: ObservableObject {
@Published public var alert: Alert?
@Published public var connectionStateFilter: ConnectionStateFilter {
didSet {
commandClient?.connectionStateFilter = connectionStateFilter
commandClient?.filterConnectionsNow()
saveStateFilterTask?.cancel()
saveStateFilterTask = Task {
await SharedPreferences.connectionStateFilter.set(connectionStateFilter.rawValue)
@@ -22,8 +19,6 @@ public class ConnectionListViewModel: ObservableObject {
@Published public var connectionSort: ConnectionSort {
didSet {
commandClient?.connectionSort = connectionSort
commandClient?.filterConnectionsNow()
saveSortTask?.cancel()
saveSortTask = Task {
await SharedPreferences.connectionSort.set(connectionSort.rawValue)
@@ -31,8 +26,6 @@ public class ConnectionListViewModel: ObservableObject {
}
}
private var commandClient: CommandClient?
private var cancellables = Set<AnyCancellable>()
private var connectTask: Task<Void, Never>?
private var saveStateFilterTask: Task<Void, Never>?
private var saveSortTask: Task<Void, Never>?
@@ -42,16 +35,6 @@ public class ConnectionListViewModel: ObservableObject {
connectionSort = .byDate
}
public func setCommandClient(_ client: CommandClient) {
commandClient = client
client.$connections
.compactMap { $0 }
.sink { [weak self] goConnections in
self?.setConnections(goConnections)
}
.store(in: &cancellables)
}
public func connect() {
if ApplicationLibrary.inPreview {
isLoading = false
@@ -97,7 +80,8 @@ public class ConnectionListViewModel: ObservableObject {
}
}
private func setConnections(_ goConnections: [LibboxConnection]) {
public func setConnections(_ goConnections: [LibboxConnection]?) {
guard let goConnections else { return }
connections = convertConnections(goConnections)
isLoading = false
}
@@ -111,22 +111,25 @@ public struct ActiveDashboardView: View {
#if os(iOS) || os(tvOS)
private func updateButtonVisibility() {
buttonState.update(profile: profile, commandClient: environments.commandClient)
buttonState.update(profile: profile, commandClient: environments.commandClient, requireAnyConnection: true)
}
#if os(iOS)
private var isTabViewBottomAccessoryAvailable: Bool {
if #available(iOS 26.0, *), !Variant.debugNoIOS26 {
return true
}
return false
}
#endif
@ToolbarContentBuilder
private var toolbar: some ToolbarContent {
#if os(tvOS)
ToolbarItem(placement: .topBarLeading) {
#if os(iOS)
if #available(iOS 26.0, *), !Variant.debugNoIOS26 {
EmptyView()
} else {
navigationButtons
}
#else
navigationButtons
#endif
}
ToolbarItem(placement: .topBarTrailing) {
if #available(iOS 16.0, tvOS 17.0, *) {
cardManagementButton
@@ -137,11 +140,8 @@ public struct ActiveDashboardView: View {
if #available(iOS 26.0, *), !Variant.debugNoIOS26 {
EmptyView()
} else {
HStack(spacing: 12) {
Divider()
StartStopButton()
}
}
#else
HStack(spacing: 12) {
Divider()
@@ -151,6 +151,7 @@ public struct ActiveDashboardView: View {
}
}
#if os(tvOS)
private var navigationButtons: some View {
NavigationButtonsView(
showGroupsButton: buttonState.showGroupsButton,
@@ -162,6 +163,7 @@ public struct ActiveDashboardView: View {
)
}
#endif
#endif
#if os(iOS) || os(tvOS)
private var groupsSheetContent: some View {
@@ -176,19 +178,42 @@ public struct ActiveDashboardView: View {
@ViewBuilder
private var cardManagementButton: some View {
Menu {
#if os(iOS)
if !isTabViewBottomAccessoryAvailable {
if buttonState.showGroupsButton {
Button {
showGroups = true
} label: {
Label("Groups (\(buttonState.groupsCount))", systemImage: "rectangle.3.group.fill")
}
}
if buttonState.showConnectionsButton {
Button {
showConnections = true
} label: {
Label("Connections (\(buttonState.connectionsCount))", systemImage: "list.bullet.rectangle.portrait.fill")
}
}
if buttonState.showGroupsButton || buttonState.showConnectionsButton {
Divider()
}
}
#endif
Button {
showCardManagement = true
} label: {
Label("Dashboard Items", systemImage: "square.grid.2x2")
}
} label: {
Label("Others", systemImage: "ellipsis.circle")
Label("Others", systemImage: "line.3.horizontal.circle")
}
.sheet(isPresented: $showCardManagement) {
CardManagementSheet(configurationVersion: $cardConfigurationVersion)
.sheet(isPresented: $showCardManagement, onDismiss: {
cardConfigurationVersion += 1
}, content: {
CardManagementSheet()
.presentationDetents([.large])
.presentationDragIndicator(.visible)
}
})
}
#endif
}
@@ -4,11 +4,8 @@ import SwiftUI
@MainActor public struct CardManagementSheet: View {
@Environment(\.dismiss) private var dismiss
@StateObject private var configuration = DashboardCardConfiguration()
@Binding private var configurationVersion: Int
public init(configurationVersion: Binding<Int>) {
_configurationVersion = configurationVersion
}
public init() {}
public var body: some View {
#if os(macOS)
@@ -41,7 +38,6 @@ import SwiftUI
Button("Reset", role: .destructive) {
Task {
await configuration.resetToDefault()
configurationVersion += 1
}
}
}
@@ -49,11 +45,9 @@ import SwiftUI
Button("Done") {
dismiss()
}
.keyboardShortcut(.escape, modifiers: [])
}
}
.onExitCommand {
dismiss()
}
}
#else
private var iOSBody: some View {
@@ -74,7 +68,6 @@ import SwiftUI
Button("Reset", role: .destructive) {
Task {
await configuration.resetToDefault()
configurationVersion += 1
}
}
}
@@ -91,13 +84,13 @@ import SwiftUI
isEnabled: configuration.isEnabled(card),
onToggle: {
configuration.toggleCard(card)
configurationVersion += 1
}
)
}
.onMove { source, destination in
configuration.moveCard(from: source, to: destination)
configurationVersion += 1
Task {
await configuration.moveCard(from: source, to: destination)
}
}
}
.applyContentMargins()
@@ -40,14 +40,10 @@ public final class DashboardCardConfiguration: ObservableObject {
}
}
public func moveCard(from source: IndexSet, to destination: Int) {
public func moveCard(from source: IndexSet, to destination: Int) async {
cardOrder.move(fromOffsets: source, toOffset: destination)
// Save asynchronously in background
Task {
await saveCardOrder()
}
}
public func resetToDefault() async {
await SharedPreferences.enabledDashboardCards.set([])
@@ -19,7 +19,11 @@ public struct HTTPProxyCard: View {
public var body: some View {
DashboardCardView(title: "", isHalfWidth: false) {
Toggle("System HTTP Proxy", isOn: $systemProxyEnabled)
HStack {
Text("System HTTP Proxy")
Spacer()
Toggle("", isOn: $systemProxyEnabled)
.labelsHidden()
.onChangeCompat(of: systemProxyEnabled) { newValue in
Task {
await onToggle(newValue)
@@ -28,3 +32,4 @@ public struct HTTPProxyCard: View {
}
}
}
}
@@ -34,10 +34,10 @@ public struct ProfileCard: View {
.disabled(viewModel.isUpdating)
.sheet(isPresented: $viewModel.showNewProfile, onDismiss: {
environments.profileUpdate.send()
}) {
}, content: {
NewProfileNavigationView()
.environmentObject(environments)
}
})
.sheet(isPresented: $viewModel.showManageProfiles) {
manageProfilesSheet
}
@@ -218,11 +218,12 @@ public struct ProfileCard: View {
NavigationSheet(
title: String(localized: "Manage profiles"),
showDoneButton: true,
onDismiss: { viewModel.showManageProfiles = false }
) {
onDismiss: { viewModel.showManageProfiles = false },
content: {
ManageProfilesView()
.environmentObject(environments)
}
)
}
@ViewBuilder
@@ -390,6 +391,7 @@ extension ProfileCard {
@ObservedObject private var viewModel: ProfileViewModel
@State private var profile: ProfilePreview
@State private var shareLinkPresented = false
@State private var isUpdating = false
init(_ viewModel: ProfileViewModel, _ profile: ProfilePreview) {
self.viewModel = viewModel
@@ -416,25 +418,26 @@ extension ProfileCard {
HStack(spacing: 8) {
if profile.type == .remote {
Button {
viewModel.isUpdating = true
isUpdating = true
Task {
await viewModel.updateProfile(profile.origin)
profile = ProfilePreview(profile.origin)
isUpdating = false
}
} label: {
Image(systemName: "arrow.clockwise")
.font(.system(size: 16))
.rotationEffect(.degrees(viewModel.isUpdating ? 360 : 0))
.rotationEffect(.degrees(isUpdating ? 360 : 0))
.animation(
viewModel.isUpdating
isUpdating
? .linear(duration: 1).repeatForever(autoreverses: false)
: .default,
value: viewModel.isUpdating
value: isUpdating
)
}
.buttonStyle(.plain)
.actionButtonStyle()
.disabled(viewModel.isUpdating)
.disabled(isUpdating)
Button {
shareLinkPresented = true
@@ -83,11 +83,9 @@ struct ProfileSelectorButton: View {
private func updateButtonContent(_ button: MenuAttachmentButton) {
// Remove existing subviews
for subview in button.subviews {
if subview is UIStackView {
for subview in button.subviews where subview is UIStackView {
subview.removeFromSuperview()
}
}
// Create content stack
let stackView = UIStackView()
@@ -42,12 +42,14 @@ public struct StartStopButton: View {
await switchProfile(!profile.status.isConnected)
}
} label: {
#if os(iOS)
HStack(spacing: 8) {
if profile.status.isConnectedStrict, let duration = runtimeDuration {
if showRuntimeDuration, profile.status.isConnectedStrict, let duration = runtimeDuration {
Text(duration)
.font(.caption)
.foregroundStyle(.secondary)
.monospacedDigit()
.fixedSize()
.transition(.asymmetric(
insertion: .move(edge: .trailing).combined(with: .opacity),
removal: .move(edge: .trailing).combined(with: .opacity)
@@ -61,9 +63,35 @@ public struct StartStopButton: View {
}
}
.animation(.spring(response: 0.35, dampingFraction: 0.75), value: profile.status.isConnectedStrict)
#else
HStack(spacing: 8) {
if profile.status.isConnectedStrict, let duration = runtimeDuration {
Text(duration)
.font(.caption)
.foregroundStyle(.secondary)
.monospacedDigit()
.fixedSize()
.transition(.asymmetric(
insertion: .move(edge: .trailing).combined(with: .opacity),
removal: .move(edge: .trailing).combined(with: .opacity)
))
}
if !profile.status.isConnected {
Label("Start", systemImage: "play.fill")
} else {
Label("Stop", systemImage: "stop.fill")
}
}
.animation(.spring(response: 0.35, dampingFraction: 0.75), value: profile.status.isConnectedStrict)
#endif
}
.labelStyle(.iconOnly)
#if os(iOS)
.modifier(PrimaryTintModifier())
#else
.tint(.primary)
#endif
.disabled(!profile.status.isEnabled)
.alertBinding($alert)
.onReceive(timer) { _ in
@@ -71,6 +99,15 @@ public struct StartStopButton: View {
}
}
#if os(iOS)
private var showRuntimeDuration: Bool {
if #available(iOS 26.0, *), !Variant.debugNoIOS26 {
return true
}
return false
}
#endif
private var runtimeDuration: String? {
guard let connectedDate = profile.connectedDate else { return nil }
let interval = currentTime.timeIntervalSince(connectedDate)
@@ -103,3 +140,15 @@ public struct StartStopButton: View {
}
}
}
#if os(iOS)
private struct PrimaryTintModifier: ViewModifier {
func body(content: Content) -> some View {
if #available(iOS 26.0, *), !Variant.debugNoIOS26 {
content.tint(.primary)
} else {
content
}
}
}
#endif
@@ -85,10 +85,10 @@ public struct DashboardView: View {
private func importRemoteProfileSheet(for request: NewProfileView.ImportRequest) -> some View {
NavigationSheet(title: "Import Profile", onDismiss: {
environments.profileUpdate.send()
}) {
}, content: {
NewProfileView(request)
.environmentObject(environments)
}
})
}
@ViewBuilder
@@ -111,11 +111,11 @@ public struct DashboardView: View {
@ViewBuilder
private var mainContent: some View {
if ApplicationLibrary.inPreview {
ActiveDashboardView(externalCardConfigurationVersion: cardConfigurationVersion)
activeDashboardView
} else if environments.extensionProfileLoading {
ProgressView()
} else if let profile = environments.extensionProfile {
ActiveDashboardView(externalCardConfigurationVersion: cardConfigurationVersion)
activeDashboardView
.environmentObject(profile)
.alertBinding($coordinator.alert)
.onChangeCompat(of: profile.status) { status in
@@ -129,4 +129,13 @@ public struct DashboardView: View {
}
}
}
@ViewBuilder
private var activeDashboardView: some View {
#if os(macOS)
ActiveDashboardView(externalCardConfigurationVersion: cardConfigurationVersion)
#else
ActiveDashboardView()
#endif
}
}
@@ -23,8 +23,10 @@ public struct GroupListView: View {
}
}
.onAppear {
viewModel.setCommandClient(environments.commandClient)
viewModel.connect()
}
.onReceive(environments.commandClient.$groups) { groups in
viewModel.setGroups(groups)
}
}
}
@@ -1,4 +1,3 @@
import Combine
import Libbox
import Library
import SwiftUI
@@ -8,21 +7,8 @@ public class GroupListViewModel: ObservableObject {
@Published public var isLoading = true
@Published public var groups: [OutboundGroup] = []
private var commandClient: CommandClient?
private var cancellables = Set<AnyCancellable>()
public init() {}
public func setCommandClient(_ client: CommandClient) {
commandClient = client
client.$groups
.compactMap { $0 }
.sink { [weak self] goGroups in
self?.setGroups(goGroups)
}
.store(in: &cancellables)
}
public func connect() {
if ApplicationLibrary.inPreview {
groups = [
@@ -40,7 +26,8 @@ public class GroupListViewModel: ObservableObject {
}
}
private func setGroups(_ goGroups: [LibboxOutboundGroup]) {
public func setGroups(_ goGroups: [LibboxOutboundGroup]?) {
guard let goGroups else { return }
var groups = [OutboundGroup]()
for goGroup in goGroups {
var items = [OutboundGroupItem]()
@@ -2,7 +2,7 @@ import Foundation
import Libbox
import SwiftUI
public struct OutboundGroup: Codable {
public struct OutboundGroup: Codable, Hashable {
let tag: String
let type: String
var selected: String
@@ -10,13 +10,16 @@ public struct OutboundGroup: Codable {
var isExpand: Bool
let items: [OutboundGroupItem]
var hashValue: Int {
var value = tag.hashValue
(value, _) = value.addingReportingOverflow(selected.hashValue)
public func hash(into hasher: inout Hasher) {
hasher.combine(tag)
hasher.combine(selected)
for item in items {
(value, _) = value.addingReportingOverflow(item.urlTestTime.hashValue)
hasher.combine(item.urlTestTime)
}
return value
}
public static func == (lhs: OutboundGroup, rhs: OutboundGroup) -> Bool {
lhs.hashValue == rhs.hashValue
}
}
+3 -3
View File
@@ -85,7 +85,7 @@ private struct LogViewContent: View {
.focusEffectDisabled()
.focusSection()
#else
let previewLogs = logList.enumerated().map { _, message in
let previewLogs = logList.map { message in
LogEntry(level: 4, message: message)
}
return LogTextView(
@@ -205,9 +205,9 @@ private struct LogViewContent: View {
Button(action: {
viewModel.prepareLogFile()
viewModel.showFileExporter = true
}) {
}, label: {
Label("To File", systemImage: "arrow.down.doc")
}
})
Button(action: viewModel.prepareLogFile) {
Label("Share", systemImage: "square.and.arrow.up")
}
@@ -18,14 +18,16 @@ public struct ProfileActionToolbar: View {
}
public var body: some View {
#if os(iOS) || os(tvOS)
#if os(iOS)
iosBody
#elseif os(tvOS)
tvOSBody
#elseif os(macOS)
macOSBody
#endif
}
#if os(iOS) || os(tvOS)
#if os(iOS)
private var iosBody: some View {
Section("Action") {
if profile.type != .remote {
@@ -65,6 +67,33 @@ public struct ProfileActionToolbar: View {
}
#endif
#if os(tvOS)
private var tvOSBody: some View {
Section("Action") {
if profile.type == .remote {
FormButton {
viewModel.isLoading = true
Task {
await viewModel.updateProfile(profile, environments: environments)
}
} label: {
Label("Update", systemImage: "arrow.clockwise")
}
.foregroundColor(.accentColor)
.disabled(viewModel.isLoading)
}
FormButton(role: .destructive) {
Task {
await viewModel.deleteProfile(profile, environments: environments, dismiss: dismiss)
}
} label: {
Label("Delete", systemImage: "trash.fill")
}
.foregroundColor(.red)
}
}
#endif
#if os(macOS)
private var macOSBody: some View {
VStack(spacing: 0) {
@@ -128,17 +128,17 @@ public struct ProfileView: View {
if viewModel.editMode == .inactive {
Button(action: {
viewModel.editMode = .active
}) {
}, label: {
Image(systemName: "square.and.pencil")
}
})
.tint(.accentColor)
.disabled(viewModel.profileList.isEmpty)
} else {
Button(action: {
viewModel.editMode = .inactive
}) {
}, label: {
Image(systemName: "checkmark.square.fill")
}
})
.tint(.accentColor)
}
}
@@ -57,20 +57,12 @@ public struct QRCodeSheet: View {
if #available(iOS 16.0, tvOS 17.0, *) {
NavigationStackCompat {
QRCodeContentView(profileName: profileName, remoteURL: remoteURL)
.navigationTitle("Share QR Code")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}
.presentationDetents([.medium])
.presentationDragIndicator(.visible)
} else {
NavigationStackCompat {
QRCodeContentView(profileName: profileName, remoteURL: remoteURL)
.navigationTitle("Share QR Code")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}
}
#endif
@@ -1,4 +1,3 @@
import Libbox
import Library
import SwiftUI
@@ -1,4 +1,3 @@
import Library
import SwiftUI
@@ -1,4 +1,3 @@
import Library
import SwiftUI
+68 -9
View File
@@ -197,7 +197,14 @@
}
},
"Cancel" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "取消"
}
}
}
},
"Chain" : {
"localizations" : {
@@ -330,6 +337,16 @@
}
}
},
"Connections (%lld)" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "连接 (%lld)"
}
}
}
},
"Copy" : {
"localizations" : {
"zh-Hans" : {
@@ -512,7 +529,14 @@
}
},
"Do you want to save the changes you made?" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "您要保存所做的更改吗?"
}
}
}
},
"Documentation" : {
"localizations" : {
@@ -535,7 +559,14 @@
}
},
"Don't Save" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "不保存"
}
}
}
},
"Done" : {
"localizations" : {
@@ -752,6 +783,16 @@
}
}
},
"Groups (%lld)" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "组 (%lld)"
}
}
}
},
"Handled unknown URL %@" : {
"localizations" : {
"zh-Hans" : {
@@ -1028,7 +1069,14 @@
"shouldTranslate" : false
},
"Manage profiles" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "管理配置"
}
}
}
},
"Match Rule" : {
"shouldTranslate" : false
@@ -1500,9 +1548,6 @@
}
}
}
},
"Share QR Code" : {
},
"Share URL as QR Code" : {
"localizations" : {
@@ -1761,7 +1806,14 @@
}
},
"Unsaved Changes" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "未保存的更改"
}
}
}
},
"Update" : {
"localizations" : {
@@ -1774,7 +1826,14 @@
}
},
"Update Failed" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "更新失败"
}
}
}
},
"Uplink" : {
"localizations" : {
-2
View File
@@ -63,8 +63,6 @@ open class ApplicationDelegate: NSObject, NSApplicationDelegate, UNUserNotificat
switch response.actionIdentifier {
case "COPY_URL":
NSPasteboard.general.setString(url, forType: .URL)
case "OPEN_URL":
fallthrough
default:
NSWorkspace.shared.open(URL(string: url)!)
}
+6 -4
View File
@@ -46,7 +46,7 @@ public struct MainView: View {
Label("Dashboard Items", systemImage: "square.grid.2x2")
}
} label: {
Label("Others", systemImage: "ellipsis.circle")
Label("Others", systemImage: "line.3.horizontal.circle")
}
}
}
@@ -65,9 +65,11 @@ public struct MainView: View {
.environment(\.profileEditor, profileEditor)
.handlesExternalEvents(preferring: [], allowing: ["*"])
.onOpenURL(perform: viewModel.openURL)
.sheet(isPresented: $showCardManagement) {
CardManagementSheet(configurationVersion: $cardConfigurationVersion)
.sheet(isPresented: $showCardManagement, onDismiss: {
cardConfigurationVersion += 1
}, content: {
CardManagementSheet()
.frame(minWidth: 400, minHeight: 400)
}
})
}
}
+25
View File
@@ -0,0 +1,25 @@
all: ios macos macos_standalone tvos
ios:
xcodebuild build -scheme SFI -configuration Debug -destination 'generic/platform=iOS' | xcbeautify | grep -A 3 -e "Build Succeeded" -e "BUILD FAILED" -e "❌"
macos:
xcodebuild build -scheme SFM -configuration Debug -destination 'generic/platform=macOS' | xcbeautify | grep -A 3 -e "Build Succeeded" -e "BUILD FAILED" -e "❌"
macos_standalone:
xcodebuild build -scheme SFM.System -configuration Debug -destination 'generic/platform=macOS' | xcbeautify | grep -A 3 -e "Build Succeeded" -e "BUILD FAILED" -e "❌"
tvos:
xcodebuild build -scheme SFT -configuration Debug -destination 'generic/platform=tvOS' | xcbeautify | grep -A 3 -e "Build Succeeded" -e "BUILD FAILED" -e "❌"
fmt:
swiftformat .
fmt_install:
brew install swiftformat
lint:
swiftlint
lint_install:
brew install swiftlint
-2
View File
@@ -44,8 +44,6 @@ class ApplicationDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCe
switch response.actionIdentifier {
case "COPY_URL":
UIPasteboard.general.string = url
case "OPEN_URL":
fallthrough
default:
await UIApplication.shared.open(URL(string: url)!)
}
+3 -1
View File
@@ -51,8 +51,8 @@ struct MainView: View {
HStack(spacing: 12) {
if let profile = environments.extensionProfile {
StatusText(profile: profile)
.frame(maxWidth: .infinity, alignment: .leading)
}
Spacer()
NavigationButtonsView(
showGroupsButton: buttonState.showGroupsButton,
showConnectionsButton: buttonState.showConnectionsButton,
@@ -187,6 +187,8 @@ struct MainView: View {
Text(statusText)
.font(.subheadline)
.foregroundStyle(.secondary)
.lineLimit(1)
.fixedSize()
}
private var statusText: String {