Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  SessionsSettings.swift   Sprache: unbekannt

 
Spracherkennung für: .swift vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import AppKit
import SwiftUI

@MainActor
struct SessionsSettings: View {
    private let isPreview: Bool
    @State private var rows: [SessionRow]
    @State private var errorMessage: String?
    @State private var loading = false
    @State private var hasLoaded = false

    init(rows: [SessionRow]? = nil, isPreview: Bool = ProcessInfo.processInfo.isPreview) {
        self._rows = State(initialValue: rows ?? [])
        self.isPreview = isPreview
        if isPreview {
            self._hasLoaded = State(initialValue: true)
        }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 14) {
            self.header
            self.content
            Spacer()
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(.horizontal, 12)
        .task {
            guard !self.hasLoaded else { return }
            guard !self.isPreview else { return }
            self.hasLoaded = true
            await self.refresh()
        }
    }

    private var header: some View {
        HStack(alignment: .top, spacing: 12) {
            VStack(alignment: .leading, spacing: 4) {
                Text("Sessions")
                    .font(.headline)
                Text("Peek at the stored conversation buckets the CLI reuses for context and rate limits.")
                    .font(.footnote)
                    .foregroundStyle(.secondary)
                    .fixedSize(horizontal: false, vertical: true)
            }
            Spacer()
            SettingsRefreshButton(isLoading: self.loading) {
                Task { await self.refresh() }
            }
        }
    }

    private var content: some View {
        Group {
            if self.rows.isEmpty, self.errorMessage == nil {
                Text("No sessions yet. They appear after the first inbound message or heartbeat.")
                    .font(.footnote)
                    .foregroundStyle(.secondary)
                    .padding(.top, 6)
            } else {
                List(self.rows) { row in
                    self.sessionRow(row)
                }
                .listStyle(.inset)
                .overlay(alignment: .topLeading) {
                    if let errorMessage {
                        Text(errorMessage)
                            .font(.footnote)
                            .foregroundStyle(.red)
                            .padding(.leading, 4)
                            .padding(.top, 4)
                    }
                }
                // The view already applies horizontal padding; keep the list aligned with the text above.
                .padding(.horizontal, -12)
            }
        }
    }

    private func sessionRow(_ row: SessionRow) -> some View {
        VStack(alignment: .leading, spacing: 6) {
            HStack(alignment: .firstTextBaseline, spacing: 8) {
                Text(row.label)
                    .font(.subheadline.bold())
                    .lineLimit(1)
                    .truncationMode(.middle)
                Spacer()
                Text(row.ageText)
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }

            HStack(spacing: 6) {
                if row.kind != .direct {
                    SessionKindBadge(kind: row.kind)
                }
                if !row.flagLabels.isEmpty {
                    ForEach(row.flagLabels, id: \.self) { flag in
                        Badge(text: flag)
                    }
                }
            }

            VStack(alignment: .leading, spacing: 6) {
                HStack(spacing: 8) {
                    Text("Context")
                        .font(.caption.weight(.semibold))
                        .foregroundStyle(.secondary)
                    Spacer()
                    Text(row.tokens.contextSummaryShort)
                        .font(.caption.monospacedDigit())
                        .foregroundStyle(.secondary)
                }
                ContextUsageBar(
                    usedTokens: row.tokens.total,
                    contextTokens: row.tokens.contextTokens,
                    width: nil)
            }

            HStack(spacing: 10) {
                if let model = row.model, !model.isEmpty {
                    self.label(icon: "cpu", text: model)
                }
                self.label(icon: "arrow.down.left", text: "\(row.tokens.input) in")
                self.label(icon: "arrow.up.right", text: "\(row.tokens.output) out")
                if let sessionId = row.sessionId, !sessionId.isEmpty {
                    HStack(spacing: 4) {
                        Image(systemName: "number").foregroundStyle(.secondary).font(.caption)
                        Text(sessionId)
                            .font(.footnote.monospaced())
                            .foregroundStyle(.secondary)
                            .lineLimit(1)
                            .truncationMode(.middle)
                    }
                    .help(sessionId)
                }
            }
        }
        .padding(.vertical, 6)
    }

    private func label(icon: String, text: String) -> some View {
        HStack(spacing: 4) {
            Image(systemName: icon).foregroundStyle(.secondary).font(.caption)
            Text(text)
        }
        .font(.footnote)
        .foregroundStyle(.secondary)
    }

    private func refresh() async {
        guard !self.loading else { return }
        guard !self.isPreview else { return }
        self.loading = true
        self.errorMessage = nil

        do {
            let snapshot = try await SessionLoader.loadSnapshot()
            self.rows = snapshot.rows
        } catch {
            self.rows = []
            self.errorMessage = (error as? LocalizedError)?.errorDescription ?? error.localizedDescription
        }

        self.loading = false
    }
}

private struct SessionKindBadge: View {
    let kind: SessionKind

    var body: some View {
        Text(self.kind.label)
            .font(.caption2.weight(.bold))
            .padding(.horizontal, 7)
            .padding(.vertical, 4)
            .foregroundStyle(self.kind.tint)
            .background(self.kind.tint.opacity(0.15))
            .clipShape(Capsule())
    }
}

private struct Badge: View {
    let text: String

    var body: some View {
        Text(self.text)
            .font(.caption2.weight(.semibold))
            .padding(.horizontal, 6)
            .padding(.vertical, 3)
            .foregroundStyle(.secondary)
            .background(Color.secondary.opacity(0.12))
            .clipShape(Capsule())
    }
}

#if DEBUG
struct SessionsSettings_Previews: PreviewProvider {
    static var previews: some View {
        SessionsSettings(rows: SessionRow.previewRows, isPreview: true)
            .frame(width: SettingsTab.windowWidth, height: SettingsTab.windowHeight)
    }
}
#endif

[Dauer der Verarbeitung: 0.20 Sekunden, vorverarbeitet 2026-04-27]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge