Add screenshot generator

This commit is contained in:
世界
2026-01-08 16:13:20 +08:00
parent 264c4eed81
commit 6b589cb771
57 changed files with 1931 additions and 109 deletions
@@ -39,14 +39,14 @@ import SwiftUI
#endif
} else {
content.onAppear {
guard !ApplicationLibrary.inPreview, profile.status.isConnected else {
guard !Variant.screenshotMode, profile.status.isConnected else {
return
}
Task {
await coordinator.reloadSystemProxy()
}
}.onChangeCompat(of: profile.status) { status in
guard !ApplicationLibrary.inPreview, status == .connected else {
guard !Variant.screenshotMode, status == .connected else {
return
}
Task {
@@ -60,7 +60,7 @@ import SwiftUI
Group {
#if os(iOS)
if useLegacyTabView {
if ApplicationLibrary.inPreview || profile.status.isConnectedStrict {
if Variant.screenshotMode || profile.status.isConnectedStrict {
VStack {
pageSelector
pageContent
@@ -126,11 +126,7 @@ import SwiftUI
#endif
#endif
.onAppear {
if ApplicationLibrary.inPreview {
environments.commandClient.connect()
} else {
environments.connect()
}
environments.connect()
}.onChangeCompat(of: scenePhase) { phase in
guard phase == .active else {
return
@@ -19,13 +19,19 @@ public struct ButtonVisibilityState {
return
}
groupsCount = commandClient.groups?.count ?? 0
let actualGroupsCount = commandClient.groups?.count ?? 0
let screenshotFallbackGroupsCount = 2
groupsCount = Variant.screenshotMode && actualGroupsCount == 0
? screenshotFallbackGroupsCount
: actualGroupsCount
connectionsCount = commandClient.connections?.count ?? 0
let isConnected = ApplicationLibrary.inPreview || profile.status.isConnectedStrict
let isConnected = Variant.screenshotMode || profile.status.isConnectedStrict
let hasGroups = Variant.screenshotMode || (commandClient.groups?.isEmpty == false)
showConnectionsButton = isConnected
showGroupsButton = isConnected && (commandClient.groups?.isEmpty == false)
showGroupsButton = isConnected && hasGroups
}
private mutating func reset() {
@@ -11,7 +11,7 @@ public struct ConnectionsCard: View {
DashboardCardView(title: "", isHalfWidth: true) {
VStack(alignment: .leading, spacing: 8) {
DashboardCardHeader(icon: "link.circle.fill", title: "Connections")
if ApplicationLibrary.inPreview {
if Variant.screenshotMode {
DashboardCardLine(String(localized: "Inbound"), "34")
DashboardCardLine(String(localized: "Outbound"), "28")
} else if let message = commandClient.status {
@@ -12,7 +12,7 @@ public struct DownloadTrafficCard: View {
VStack(alignment: .leading, spacing: 8) {
DashboardCardHeader(icon: "arrow.down.circle.fill", title: "Download")
if ApplicationLibrary.inPreview {
if Variant.screenshotMode {
Text("249 MB/s")
.font(.title2)
.fontWeight(.medium)
@@ -11,7 +11,7 @@ public struct StatusCard: View {
DashboardCardView(title: "", isHalfWidth: true) {
VStack(alignment: .leading, spacing: 8) {
DashboardCardHeader(icon: "info.circle.fill", title: "Status")
if ApplicationLibrary.inPreview {
if Variant.screenshotMode {
DashboardCardLine(String(localized: "Memory"), "6.4 MB")
DashboardCardLine(String(localized: "Goroutines"), "89")
} else if let message = commandClient.status {
@@ -12,7 +12,7 @@ public struct UploadTrafficCard: View {
VStack(alignment: .leading, spacing: 8) {
DashboardCardHeader(icon: "arrow.up.circle.fill", title: "Upload")
if ApplicationLibrary.inPreview {
if Variant.screenshotMode {
Text("38 B/s")
.font(.title2)
.fontWeight(.medium)
@@ -28,7 +28,7 @@ public struct ExtensionStatusView: View {
Group {
VStack {
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: columnCount), alignment: .leading) {
if ApplicationLibrary.inPreview {
if Variant.screenshotMode {
StatusItem(String(localized: "Status")) {
StatusLine(String(localized: "Memory"), "6.4 MB")
StatusLine(String(localized: "Goroutines"), "89")
@@ -10,16 +10,7 @@ public struct StartStopButton: View {
public var body: some View {
Group {
if ApplicationLibrary.inPreview {
Button {} label: {
#if os(tvOS)
Image(systemName: "stop.fill")
#else
Label("Stop", systemImage: "stop.fill")
#endif
}
.labelStyle(.iconOnly)
} else if let profile = environments.extensionProfile {
if let profile = environments.extensionProfile {
ToggleConnectionButton().environmentObject(profile)
} else {
Button {} label: {
@@ -108,6 +99,7 @@ public struct StartStopButton: View {
.disabled(!profile.status.isEnabled)
.alert($alert)
.onReceive(timer) { _ in
guard !Variant.screenshotMode else { return }
Task { @MainActor in
currentTime = Date()
}
@@ -140,7 +132,12 @@ public struct StartStopButton: View {
private var runtimeDuration: String? {
guard let connectedDate = profile.connectedDate else { return nil }
let interval = currentTime.timeIntervalSince(connectedDate)
let interval: TimeInterval
if Variant.screenshotMode {
interval = 3600
} else {
interval = currentTime.timeIntervalSince(connectedDate)
}
guard interval >= 0 else { return nil }
let hours = Int(interval) / 3600
@@ -77,9 +77,7 @@ public struct DashboardView: View {
@ViewBuilder
private var mainContent: some View {
if ApplicationLibrary.inPreview {
activeDashboardView
} else if environments.extensionProfileLoading {
if environments.extensionProfileLoading {
ProgressView()
} else if let profile = environments.extensionProfile {
activeDashboardView
@@ -48,7 +48,7 @@ public final class DashboardViewModel: BaseViewModel {
defer { isLoading = false }
if ApplicationLibrary.inPreview {
if Variant.screenshotMode {
profileList = [
ProfilePreview(Profile(id: 0, name: "profile local", type: .local, path: "")),
ProfilePreview(Profile(id: 1, name: "profile remote", type: .remote, path: "", lastUpdated: Date(timeIntervalSince1970: 0))),
@@ -41,7 +41,7 @@ public struct OverviewView: View {
}
}
.alert($coordinator.alert)
.disabled(!ApplicationLibrary.inPreview && (!profile.status.isSwitchable || coordinator.reasserting))
.disabled(!Variant.screenshotMode && (!profile.status.isSwitchable || coordinator.reasserting))
}
@ViewBuilder
@@ -85,9 +85,9 @@ public struct OverviewView: View {
private func shouldShowCard(_ card: DashboardCard) -> Bool {
switch card {
case .status, .connections, .uploadTraffic, .downloadTraffic, .clashMode:
return ApplicationLibrary.inPreview || profile.status.isConnected
return Variant.screenshotMode || profile.status.isConnected
case .httpProxy:
return (ApplicationLibrary.inPreview || profile.status.isConnectedStrict) && systemProxyAvailable
return (Variant.screenshotMode || profile.status.isConnectedStrict) && systemProxyAvailable
case .profile:
return true
}