mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-09 11:55:53 +00:00
linting
This commit is contained in:
parent
a14d02e20f
commit
8768bb0eb3
24 changed files with 149 additions and 148 deletions
|
|
@ -89,7 +89,7 @@ final class LivePreviewManager {
|
|||
}
|
||||
}
|
||||
|
||||
case .exit(_):
|
||||
case .exit:
|
||||
subscription.isSessionActive = false
|
||||
|
||||
default:
|
||||
|
|
@ -190,4 +190,4 @@ extension View {
|
|||
func livePreview(for sessionId: String, enabled: Bool = true) -> some View {
|
||||
modifier(LivePreviewModifier(sessionId: sessionId, isEnabled: enabled))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,4 +121,4 @@ extension ReconnectionManager {
|
|||
|
||||
extension NetworkMonitor {
|
||||
static let statusChangedNotification = Notification.Name("NetworkStatusChanged")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,4 +163,4 @@ extension Task where Failure == Error {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,4 +276,4 @@ extension View {
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ struct EnhancedConnectionView: View {
|
|||
Spacer(minLength: 50)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
.scrollBounceBehavior(.basedOnSize)
|
||||
}
|
||||
.toolbar(.hidden, for: .navigationBar)
|
||||
|
|
@ -438,4 +438,4 @@ struct ServerProfileEditView: View {
|
|||
#Preview {
|
||||
EnhancedConnectionView()
|
||||
.environment(ConnectionManager())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,11 +116,10 @@ struct SessionCreateView: View {
|
|||
// Error Message
|
||||
if presentedError != nil {
|
||||
ErrorBanner(
|
||||
message: presentedError?.error.localizedDescription ?? "An error occurred",
|
||||
onDismiss: {
|
||||
message: presentedError?.error.localizedDescription ?? "An error occurred"
|
||||
) {
|
||||
presentedError = nil
|
||||
}
|
||||
)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: Theme.CornerRadius.small)
|
||||
.stroke(Theme.Colors.errorAccent.opacity(0.3), lineWidth: 1)
|
||||
|
|
|
|||
|
|
@ -388,7 +388,6 @@ struct SessionListView: View {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// View model for managing session list state and operations.
|
||||
@MainActor
|
||||
@Observable
|
||||
|
|
@ -463,8 +462,8 @@ struct SessionHeaderView: View {
|
|||
let onKillAll: () -> Void
|
||||
let onCleanupAll: () -> Void
|
||||
|
||||
private var runningCount: Int { sessions.count { $0.isRunning }}
|
||||
private var exitedCount: Int { sessions.count { !$0.isRunning }}
|
||||
private var runningCount: Int { sessions.count { $0.isRunning } }
|
||||
private var exitedCount: Int { sessions.count { !$0.isRunning } }
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: Theme.Spacing.medium) {
|
||||
|
|
|
|||
|
|
@ -293,8 +293,8 @@ struct AdvancedSettingsView: View {
|
|||
windowManager.setWindowStyle(style)
|
||||
}
|
||||
|
||||
Text(macWindowStyle == .inline ?
|
||||
"Traffic light buttons appear inline with content" :
|
||||
Text(macWindowStyle == .inline ?
|
||||
"Traffic light buttons appear inline with content" :
|
||||
"Standard macOS title bar with traffic lights")
|
||||
.font(Theme.Typography.terminalSystem(size: 12))
|
||||
.foregroundColor(Theme.Colors.terminalForeground.opacity(0.6))
|
||||
|
|
|
|||
|
|
@ -69,9 +69,8 @@ struct CtrlKeyGrid: View {
|
|||
ForEach(currentKeys, id: \.0) { key, description in
|
||||
CtrlGridKeyButton(
|
||||
key: key,
|
||||
description: description,
|
||||
onPress: { sendCtrlKey(key) }
|
||||
)
|
||||
description: description
|
||||
) { sendCtrlKey(key) }
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
|
|
@ -144,7 +143,7 @@ struct CtrlGridKeyButton: View {
|
|||
@State private var showingTooltip = false
|
||||
|
||||
var body: some View {
|
||||
Button(action: onPress, label: {
|
||||
Button(action: onPress) {
|
||||
VStack(spacing: 4) {
|
||||
Text("^" + key)
|
||||
.font(Theme.Typography.terminalSystem(size: 20, weight: .bold))
|
||||
|
|
@ -171,7 +170,7 @@ struct CtrlGridKeyButton: View {
|
|||
color: isPressed ? Theme.Colors.primaryAccent.opacity(0.3) : .clear,
|
||||
radius: isPressed ? 8 : 0
|
||||
)
|
||||
})
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
.scaleEffect(isPressed ? 0.95 : 1.0)
|
||||
.animation(.easeInOut(duration: 0.1), value: isPressed)
|
||||
|
|
@ -213,4 +212,4 @@ struct CtrlGridKeyButton: View {
|
|||
CtrlKeyGrid(isPresented: .constant(true)) { key in
|
||||
logger.debug("Ctrl key pressed: \(key)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,4 +211,4 @@ struct FullscreenTextInput: View {
|
|||
FullscreenTextInput(isPresented: .constant(true)) { text in
|
||||
logger.debug("Submitted: \(text)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,4 +73,4 @@ struct QuickFontSizeButtons: View {
|
|||
QuickFontSizeButtons(fontSize: .constant(14))
|
||||
.padding()
|
||||
.background(Theme.Colors.terminalBackground)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ struct TerminalBufferPreview: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
GeometryReader { _ in
|
||||
ScrollViewReader { scrollProxy in
|
||||
ScrollView([.horizontal, .vertical], showsIndicators: false) {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
|
|
@ -185,4 +185,4 @@ struct CompactTerminalPreview: View {
|
|||
|
||||
return lines
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -523,12 +523,11 @@ struct TerminalView: View {
|
|||
.focused($isInputFocused)
|
||||
.overlay(
|
||||
ScrollToBottomButton(
|
||||
isVisible: showScrollToBottom,
|
||||
action: {
|
||||
isVisible: showScrollToBottom
|
||||
) {
|
||||
viewModel.scrollToBottom()
|
||||
showScrollToBottom = false
|
||||
}
|
||||
)
|
||||
.padding(.bottom, Theme.Spacing.large)
|
||||
.padding(.leading, Theme.Spacing.large),
|
||||
alignment: .bottomLeading
|
||||
|
|
|
|||
|
|
@ -230,15 +230,14 @@ final class BunServer {
|
|||
}
|
||||
} catch {
|
||||
// Log more detailed error information
|
||||
let errorMessage: String
|
||||
if let bunError = error as? BunServerError {
|
||||
errorMessage = bunError.localizedDescription
|
||||
let errorMessage: String = if let bunError = error as? BunServerError {
|
||||
bunError.localizedDescription
|
||||
} else if let urlError = error as? URLError {
|
||||
errorMessage = "Network error: \(urlError.localizedDescription) (Code: \(urlError.code.rawValue))"
|
||||
"Network error: \(urlError.localizedDescription) (Code: \(urlError.code.rawValue))"
|
||||
} else if let posixError = error as? POSIXError {
|
||||
errorMessage = "System error: \(posixError.localizedDescription) (Code: \(posixError.code.rawValue))"
|
||||
"System error: \(posixError.localizedDescription) (Code: \(posixError.code.rawValue))"
|
||||
} else {
|
||||
errorMessage = error.localizedDescription
|
||||
error.localizedDescription
|
||||
}
|
||||
|
||||
logger.error("Failed to start Bun server: \(errorMessage)")
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ protocol NgrokTunnelProtocol {
|
|||
@MainActor
|
||||
final class NgrokService: NgrokTunnelProtocol {
|
||||
static let shared = NgrokService()
|
||||
|
||||
|
||||
/// Current tunnel status
|
||||
private(set) var tunnelStatus: NgrokTunnelStatus?
|
||||
|
||||
|
|
|
|||
|
|
@ -8,37 +8,37 @@ enum ServerError: LocalizedError {
|
|||
case repeatedCrashes(count: Int)
|
||||
case portInUse(port: Int)
|
||||
case startupFailed(String)
|
||||
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .repeatedCrashes:
|
||||
return "Server keeps crashing"
|
||||
"Server keeps crashing"
|
||||
case .portInUse(let port):
|
||||
return "Port \(port) is already in use"
|
||||
"Port \(port) is already in use"
|
||||
case .startupFailed(let reason):
|
||||
return "Server startup failed: \(reason)"
|
||||
"Server startup failed: \(reason)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var failureReason: String? {
|
||||
switch self {
|
||||
case .repeatedCrashes(let count):
|
||||
return "The server crashed \(count) times in a row"
|
||||
"The server crashed \(count) times in a row"
|
||||
case .portInUse(let port):
|
||||
return "Another process is using port \(port)"
|
||||
"Another process is using port \(port)"
|
||||
case .startupFailed:
|
||||
return nil
|
||||
nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var recoverySuggestion: String? {
|
||||
switch self {
|
||||
case .repeatedCrashes:
|
||||
return "Check the logs for errors or try a different port"
|
||||
"Check the logs for errors or try a different port"
|
||||
case .portInUse:
|
||||
return "Stop the other process or choose a different port"
|
||||
"Stop the other process or choose a different port"
|
||||
case .startupFailed:
|
||||
return "Check the server configuration and try again"
|
||||
"Check the server configuration and try again"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ enum ServerError: LocalizedError {
|
|||
@Observable
|
||||
class ServerManager {
|
||||
static let shared = ServerManager()
|
||||
|
||||
|
||||
var port: String {
|
||||
get { UserDefaults.standard.string(forKey: "serverPort") ?? "4020" }
|
||||
set { UserDefaults.standard.set(newValue, forKey: "serverPort") }
|
||||
|
|
@ -504,32 +504,32 @@ class ServerManager {
|
|||
|
||||
enum ServerManagerError: LocalizedError {
|
||||
case portInUseByApp(appName: String, port: Int, alternatives: [Int])
|
||||
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .portInUseByApp(let appName, let port, _):
|
||||
return "Port \(port) is in use by \(appName)"
|
||||
"Port \(port) is in use by \(appName)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var failureReason: String? {
|
||||
switch self {
|
||||
case .portInUseByApp:
|
||||
return "The port is being used by another application"
|
||||
"The port is being used by another application"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var recoverySuggestion: String? {
|
||||
switch self {
|
||||
case .portInUseByApp(_, _, let alternatives):
|
||||
return "Try one of these ports: \(alternatives.map(String.init).joined(separator: ", "))"
|
||||
"Try one of these ports: \(alternatives.map(String.init).joined(separator: ", "))"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var helpAnchor: String? {
|
||||
switch self {
|
||||
case .portInUseByApp:
|
||||
return "port-conflict"
|
||||
"port-conflict"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ struct ServerSessionInfo: Codable {
|
|||
@Observable
|
||||
final class SessionMonitor {
|
||||
static let shared = SessionMonitor()
|
||||
|
||||
|
||||
private(set) var sessions: [String: ServerSessionInfo] = [:]
|
||||
private(set) var lastError: Error?
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ struct ErrorAlertModifier: ViewModifier {
|
|||
@Binding var error: Error?
|
||||
let title: String
|
||||
let onDismiss: (() -> Void)?
|
||||
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.alert(
|
||||
|
|
@ -31,7 +31,9 @@ extension View {
|
|||
_ title: String = "Error",
|
||||
error: Binding<Error?>,
|
||||
onDismiss: (() -> Void)? = nil
|
||||
) -> some View {
|
||||
)
|
||||
-> some View
|
||||
{
|
||||
modifier(ErrorAlertModifier(error: error, title: title, onDismiss: onDismiss))
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +48,9 @@ extension Task where Failure == Error {
|
|||
priority: TaskPriority? = nil,
|
||||
errorBinding: Binding<Error?>,
|
||||
operation: @escaping () async throws -> T
|
||||
) -> Task<T, Error> {
|
||||
)
|
||||
-> Task<T, Error>
|
||||
{
|
||||
Task<T, Error>(priority: priority) {
|
||||
do {
|
||||
return try await operation()
|
||||
|
|
@ -77,26 +81,26 @@ struct ErrorRecoveryAction {
|
|||
struct ErrorToast: View {
|
||||
let error: Error
|
||||
let onDismiss: () -> Void
|
||||
|
||||
|
||||
@State private var opacity: Double = 0
|
||||
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 12) {
|
||||
Image(systemName: "exclamationmark.triangle.fill")
|
||||
.foregroundColor(.red)
|
||||
|
||||
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Error")
|
||||
.font(.headline)
|
||||
|
||||
|
||||
Text(error.localizedDescription)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(2)
|
||||
}
|
||||
|
||||
|
||||
Spacer()
|
||||
|
||||
|
||||
Button(action: onDismiss) {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
.foregroundColor(.secondary)
|
||||
|
|
@ -129,7 +133,7 @@ struct ErrorToast: View {
|
|||
struct AsyncErrorBoundary<Content: View>: View {
|
||||
@State private var error: Error?
|
||||
let content: () -> Content
|
||||
|
||||
|
||||
var body: some View {
|
||||
content()
|
||||
.environment(\.asyncErrorHandler, AsyncErrorHandler { error in
|
||||
|
|
@ -142,7 +146,7 @@ struct AsyncErrorBoundary<Content: View>: View {
|
|||
// MARK: - Environment Values
|
||||
|
||||
private struct AsyncErrorHandlerKey: EnvironmentKey {
|
||||
nonisolated(unsafe) static let defaultValue = AsyncErrorHandler(handler: { _ in })
|
||||
nonisolated(unsafe) static let defaultValue = AsyncErrorHandler { _ in }
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
|
|
@ -154,8 +158,8 @@ extension EnvironmentValues {
|
|||
|
||||
struct AsyncErrorHandler {
|
||||
let handler: (Error) -> Void
|
||||
|
||||
|
||||
func handle(_ error: Error) {
|
||||
handler(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ struct ServerStatusView: View {
|
|||
.foregroundColor(.primary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
|
||||
if isRunning {
|
||||
Text(accessText)
|
||||
.font(.system(size: 11))
|
||||
|
|
@ -219,12 +219,12 @@ struct ServerStatusView: View {
|
|||
|
||||
private var statusText: String {
|
||||
if isRunning {
|
||||
return "Server running"
|
||||
"Server running"
|
||||
} else {
|
||||
return "Server stopped"
|
||||
"Server stopped"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var accessText: String {
|
||||
let bindAddress = serverManager.bindAddress
|
||||
if bindAddress == "127.0.0.1" {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import SwiftUI
|
||||
import os
|
||||
import SwiftUI
|
||||
|
||||
/// View displaying detailed information about a specific terminal session
|
||||
struct SessionDetailView: View {
|
||||
let session: ServerSessionInfo
|
||||
@State private var windowTitle = ""
|
||||
|
||||
|
||||
private let logger = Logger(subsystem: "sh.vibetunnel.vibetunnel", category: "SessionDetailView")
|
||||
|
||||
var body: some View {
|
||||
|
|
|
|||
|
|
@ -210,11 +210,11 @@ struct DashboardSettingsView: View {
|
|||
} else {
|
||||
// Just password change, no network mode switch
|
||||
await updateServerForPasswordChange(action: .apply, logger: logger)
|
||||
|
||||
|
||||
// Restart server to apply new password
|
||||
logger.info("Restarting server to apply new password")
|
||||
await serverManager.restart()
|
||||
|
||||
|
||||
// Wait for server to be ready
|
||||
try? await Task.sleep(for: .seconds(1))
|
||||
}
|
||||
|
|
@ -372,11 +372,11 @@ private struct SecuritySection: View {
|
|||
// Go server handles authentication internally
|
||||
logger.info("Clearing auth cache to remove password")
|
||||
await serverManager.clearAuthCache()
|
||||
|
||||
|
||||
// Restart server to remove password protection
|
||||
logger.info("Restarting server to remove password protection")
|
||||
await serverManager.restart()
|
||||
|
||||
|
||||
// Wait for server to be ready
|
||||
try? await Task.sleep(for: .seconds(1))
|
||||
}
|
||||
|
|
@ -685,82 +685,82 @@ private struct PortConfigurationView: View {
|
|||
|
||||
// Port conflict warning
|
||||
if let conflict = portConflict {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "exclamationmark.triangle.fill")
|
||||
.foregroundColor(.orange)
|
||||
.font(.caption)
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "exclamationmark.triangle.fill")
|
||||
.foregroundColor(.orange)
|
||||
.font(.caption)
|
||||
|
||||
Text("Port \(conflict.port) is used by \(conflict.process.name)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.orange)
|
||||
}
|
||||
Text("Port \(conflict.port) is used by \(conflict.process.name)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.orange)
|
||||
}
|
||||
|
||||
HStack(spacing: 8) {
|
||||
if !conflict.alternativePorts.isEmpty {
|
||||
HStack(spacing: 4) {
|
||||
Text("Try port:")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
HStack(spacing: 8) {
|
||||
if !conflict.alternativePorts.isEmpty {
|
||||
HStack(spacing: 4) {
|
||||
Text("Try port:")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
ForEach(conflict.alternativePorts.prefix(3), id: \.self) { port in
|
||||
Button(String(port)) {
|
||||
serverPort = String(port)
|
||||
portNumber = port
|
||||
restartServerWithNewPort(port)
|
||||
ForEach(conflict.alternativePorts.prefix(3), id: \.self) { port in
|
||||
Button(String(port)) {
|
||||
serverPort = String(port)
|
||||
portNumber = port
|
||||
restartServerWithNewPort(port)
|
||||
}
|
||||
.buttonStyle(.link)
|
||||
.font(.caption)
|
||||
}
|
||||
|
||||
Button("Choose...") {
|
||||
showPortPicker()
|
||||
}
|
||||
.buttonStyle(.link)
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
|
||||
Button("Choose...") {
|
||||
showPortPicker()
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
Task {
|
||||
await forceQuitConflictingProcess(conflict)
|
||||
}
|
||||
} label: {
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
.font(.caption)
|
||||
Text("Kill Process")
|
||||
.font(.caption)
|
||||
}
|
||||
.buttonStyle(.link)
|
||||
.font(.caption)
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.controlSize(.small)
|
||||
.tint(.red)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
Task {
|
||||
await forceQuitConflictingProcess(conflict)
|
||||
}
|
||||
} label: {
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
.font(.caption)
|
||||
Text("Kill Process")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.controlSize(.small)
|
||||
.tint(.red)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
.padding(.horizontal, 12)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(Color.orange.opacity(0.1))
|
||||
.cornerRadius(6)
|
||||
} else if !serverManager.isRunning && serverManager.lastError != nil {
|
||||
// Show general server error if no specific port conflict
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "exclamationmark.circle.fill")
|
||||
.foregroundColor(.red)
|
||||
.font(.caption)
|
||||
.padding(.vertical, 8)
|
||||
.padding(.horizontal, 12)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(Color.orange.opacity(0.1))
|
||||
.cornerRadius(6)
|
||||
} else if !serverManager.isRunning && serverManager.lastError != nil {
|
||||
// Show general server error if no specific port conflict
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "exclamationmark.circle.fill")
|
||||
.foregroundColor(.red)
|
||||
.font(.caption)
|
||||
|
||||
Text("Server failed to start")
|
||||
Text("Server failed to start")
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
} else {
|
||||
Text("The server will automatically restart when the port is changed.")
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
} else {
|
||||
Text("The server will automatically restart when the port is changed.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.padding(.top, 4)
|
||||
.foregroundStyle(.secondary)
|
||||
.padding(.top, 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import SwiftUI
|
||||
import os
|
||||
import SwiftUI
|
||||
|
||||
/// Shared glowing app icon component with configurable animation and effects.
|
||||
///
|
||||
|
|
@ -7,9 +7,9 @@ import os
|
|||
/// floating animation, and interactive behaviors. It can be used in both the Welcome
|
||||
/// and About views with different configurations.
|
||||
struct GlowingAppIcon: View {
|
||||
// Configuration
|
||||
/// Configuration
|
||||
let size: CGFloat
|
||||
|
||||
|
||||
private let logger = Logger(subsystem: "sh.vibetunnel.vibetunnel", category: "GlowingAppIcon")
|
||||
let enableFloating: Bool
|
||||
let enableInteraction: Bool
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import AppKit
|
||||
import Foundation
|
||||
import Observation
|
||||
import os.log
|
||||
import SwiftUI
|
||||
import Observation
|
||||
|
||||
/// Terminal launch result with window/tab information
|
||||
struct TerminalLaunchResult {
|
||||
|
|
@ -689,7 +689,7 @@ final class TerminalLauncher {
|
|||
let fullCommand: String
|
||||
// Check if we have a Bun executable (it would be bundled as vibetunnel)
|
||||
let bunServerActive = Bundle.main.path(forResource: "vibetunnel", ofType: nil) != nil &&
|
||||
!command.contains("TTY_SESSION_ID=") // If command already has session ID, it's from Go server
|
||||
!command.contains("TTY_SESSION_ID=") // If command already has session ID, it's from Go server
|
||||
if bunServerActive {
|
||||
// For Bun server, use fwd command
|
||||
logger.info("Using Bun server session creation via fwd")
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, @preconcurrency UNUser
|
|||
}
|
||||
|
||||
// Initialize dock icon visibility through DockIconManager
|
||||
DockIconManager.initialize()
|
||||
DockIconManager.shared.updateDockVisibility()
|
||||
|
||||
// Show welcome screen when version changes
|
||||
|
|
@ -320,7 +321,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate, @preconcurrency UNUser
|
|||
@objc
|
||||
private func openDashboard() {
|
||||
if let serverManager = app?.serverManager,
|
||||
let url = URL(string: "http://localhost:\(serverManager.port)") {
|
||||
let url = URL(string: "http://localhost:\(serverManager.port)")
|
||||
{
|
||||
NSWorkspace.shared.open(url)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue