Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ excluded:
analyzer_rules:
- unused_declaration
- unused_import
enabled_rules:
opt_in_rules:
- accessibility_label_for_image
- accessibility_trait_for_button
- array_init
Expand Down Expand Up @@ -104,8 +104,6 @@ enabled_rules:
- unneeded_parentheses_in_closure_argument
- unowned_variable_capture
- untyped_error_in_catch
- unused_declaration
- unused_import
- unused_parameter
- vertical_parameter_alignment_on_call
- vertical_whitespace_opening_braces
Expand Down Expand Up @@ -176,8 +174,6 @@ number_separator:
minimum_length: 5
redundant_type_annotation:
consider_default_literal_types_redundant: true
trailing_comma:
mandatory_comma: true
type_body_length: 400
unneeded_override:
affect_initializers: true
4 changes: 2 additions & 2 deletions Bulkhead.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 14.6;
MARKETING_VERSION = 0.0.5;
MARKETING_VERSION = 0.0.6;
PRODUCT_BUNDLE_IDENTIFIER = co.fwoar.dockerui.DockerUI;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down Expand Up @@ -310,7 +310,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 14.6;
MARKETING_VERSION = 0.0.5;
MARKETING_VERSION = 0.0.6;
PRODUCT_BUNDLE_IDENTIFIER = co.fwoar.dockerui.DockerUI;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down
2 changes: 0 additions & 2 deletions Bulkhead/Docker/DockerExecutor.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import Foundation
import Network
import SwiftUI // For URL

struct DockerHTTPRequest {
let path: String
Expand Down
21 changes: 10 additions & 11 deletions Bulkhead/Docker/DockerManager.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Combine
import Foundation
import SwiftUI

class DockerPublication: ObservableObject {
@Published var containers: [DockerContainer] = []
Expand Down Expand Up @@ -39,10 +38,10 @@ class DockerPublication: ObservableObject {
clearImageListError()
}

@MainActor
func updateSocketPath(_ new: String) {
socketPath = new
}
// @MainActor
// func updateSocketPath(_ new: String) {
// socketPath = new
// }

@MainActor
func clearContainerListError() {
Expand Down Expand Up @@ -146,12 +145,12 @@ class DockerManager {
return enriched
}

func clearEnrichmentCache() {
// Write operation with barrier
cacheQueue.async(flags: .barrier) {
self.enrichmentCache.removeAll()
}
}
// func clearEnrichmentCache() {
// // Write operation with barrier
// cacheQueue.async(flags: .barrier) {
// self.enrichmentCache.removeAll()
// }
// }

// Now async again to await the Task from tryCommand
func fetchImages() async {
Expand Down
2 changes: 0 additions & 2 deletions Bulkhead/Docker/LogFetcher.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Foundation

final class LogFetcher {
private let executor: DockerExecutor

Expand Down
1 change: 0 additions & 1 deletion Bulkhead/Docker/LogManager.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Foundation
import OSLog
import os.log

func getDateFormatter() -> DateFormatter {
Expand Down
56 changes: 2 additions & 54 deletions Bulkhead/UI/ContainerDetailView.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import SwiftUI

struct FilesystemLocation: Hashable {
let container: DockerContainer
let path: String
}

extension ContainerState {
fileprivate var color: Color {
switch self {
Expand Down Expand Up @@ -35,46 +30,14 @@ extension ContainerState {
}
}

extension HealthStatus {
fileprivate var color: Color {
switch self {
case .healthy: return .green
case .unhealthy: return .red
case .starting: return .orange
case .none: return .secondary
case .unknown: return .secondary
}
}

fileprivate var icon: String {
switch self {
case .healthy: return "checkmark.circle.fill"
case .unhealthy: return "xmark.circle.fill"
case .starting: return "arrow.triangle.2.circlepath.circle.fill"
case .none: return "minus.circle.fill"
case .unknown: return "questionmark.circle.fill"
}
}

fileprivate var label: String {
switch self {
case .healthy: return "Healthy"
case .unhealthy: return "Unhealthy"
case .starting: return "Starting"
case .none: return "No Health Check"
case .unknown: return "Unknown"
}
}
}

struct ContainerDetailViewInner: View {
@EnvironmentObject var publication: DockerPublication
private let appEnv: ApplicationEnvironment
@ObservedObject var logManager: LogManager
@StateObject private var model: ContainerDetailModel
let container: DockerContainer
@State private var selectedPath: String?
@Environment(\.colorScheme) var colorScheme

@Environment(\.isGlobalErrorShowing) private var isGlobalErrorShowing

private var manager: DockerManager { appEnv.manager }
Expand Down Expand Up @@ -255,21 +218,6 @@ struct ContainerDetailViewInner: View {
}
}

@ViewBuilder
private func pathDetailRow(_ label: String, _ paths: [String]) -> some View {
HStack(alignment: .firstTextBaseline) {
Text("\(label):")
.fontWeight(.semibold)
.frame(width: 200, alignment: .leading)
VStack(alignment: .leading) {
ForEach(paths, id: \.self) { path in
Text(path)
.font(.system(.body, design: .monospaced))
}
}
}
}

@ViewBuilder
private func environmentSection(_ env: [String]) -> some View {
sectionHeader("Environment")
Expand Down Expand Up @@ -299,6 +247,7 @@ struct ContainerDetailViewInner: View {
}
} else {
envDetailRow(key, value)

}
} else {
envDetailRow("", envVar)
Expand Down Expand Up @@ -328,7 +277,6 @@ struct ContainerDetailView: View {
let container: DockerContainer
let appEnv: ApplicationEnvironment
@EnvironmentObject var logManager: LogManager
private var manager: DockerManager { appEnv.manager }

var body: some View {
ContainerDetailViewInner(appEnv: appEnv, container: container, logManager: logManager)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,72 +1,30 @@
import Foundation
import SwiftUI

struct ContainerListView: View {
@Environment(\.openWindow) private var openWindow
@EnvironmentObject var publication: DockerPublication
let containers: [DockerContainer]
@Binding var selectedContainer: DockerContainer?
@Binding var searchFocused: Bool
struct ContainerSummaryView: View {
var container: DockerContainer

var backgroundColor: Color
var shadowColor: Color
let manager: DockerManager
let appEnv: ApplicationEnvironment

private var containerSearchConfig: SearchConfiguration<DockerContainer> {
SearchConfiguration(
placeholder: "Search containers...",
filter: { container, query in
let searchQuery = query.lowercased()
// Search in container name
if let name = container.names.first?.lowercased(), name.contains(searchQuery) {
return true
}
// Search in image name
if container.image.lowercased().contains(searchQuery) {
return true
}
// Search in status
return container.status.lowercased().contains(searchQuery)
}
)
}

var body: some View {
ListView(
items: containers,
selectedItem: $selectedContainer,
backgroundColor: backgroundColor,
shadowColor: shadowColor,
searchConfig: containerSearchConfig,
listError: publication.containerListError,
listErrorTitle: "Failed to Load Containers",
searchFocused: $searchFocused
) { container in
// Type erase the content view

HStack {
VStack(alignment: .leading, spacing: 2) {
HStack(spacing: 8) {
Text(container.names.first ?? "Unnamed")
.font(.headline)
}
if container.status.lowercased().contains("up") {
StatusBadgeView(text: container.status, color: .green)
} else {
StatusBadgeView(text: container.status, color: .secondary)
}
Text(container.image)
.font(.subheadline)
.foregroundStyle(.secondary)
HStack {
VStack(alignment: .leading, spacing: 2) {
HStack(spacing: 8) {
Text(container.names.first ?? "Unnamed")
.font(.headline)
}
if container.status.lowercased().contains("up") {
StatusBadgeView(text: container.status, color: .green)
} else {
StatusBadgeView(text: container.status, color: .secondary)
}
Spacer()
ContainerActionsView(container: container, manager: manager)
Text(container.image)
.font(.subheadline)
.foregroundStyle(.secondary)
}

} detail: { container in
// Type erase the detail view
ContainerDetailView(container: container, appEnv: appEnv)
Spacer()
ContainerActionsView(container: container, manager: manager)
}
}
}
Expand Down Expand Up @@ -96,7 +54,7 @@ struct ContainerActionsView: View {
@Environment(\.openWindow) private var openWindow
let container: DockerContainer
let manager: DockerManager
@EnvironmentObject var publication: DockerPublication // Use ObservedObject if manager might change

@State private var isActionPending = false // State for loading indicator

var body: some View {
Expand Down
Loading
Loading