Files
ios-gitea-prs/GiteaPR/Settings/LogsView.swift
T
Hermes b51b2ee5c8
Build iOS App / Build .ipa and publish source (push) Failing after 5m44s
Add in-app diagnostic logging + resilient inbox; bump to 1.2
- LogStore: bounded in-memory + persisted log of API calls and errors,
  viewable and shareable from Settings → View logs.
- GiteaClient: log every request/response status (esp. 404s).
- Inbox: a single failing repo no longer wipes the whole inbox — per-repo
  errors are caught, logged, and the rest still load.
- Bump to 1.2 so SideStore offers the update.
2026-08-12 18:46:08 +00:00

78 lines
2.8 KiB
Swift

import SwiftUI
import UIKit
/// Diagnostic log viewer. Shows the in-memory/persisted log entries with a
/// Share button (so the user can send logs to Hermes) and a Clear button.
struct LogsView: View {
@ObservedObject private var store = LogStore.shared
@State private var showShare = false
var body: some View {
Group {
if store.entries.isEmpty {
ContentUnavailableView(
"No logs yet",
systemImage: "doc.text",
description: Text("Run the app and reproduce the issue, then come back here."))
} else {
List {
ForEach(store.entries.reversed()) { entry in
VStack(alignment: .leading, spacing: 2) {
HStack {
Text(entry.level.rawValue)
.font(.caption2.weight(.bold))
.foregroundColor(color(for: entry.level))
Text(entry.timestamp, style: .time)
.font(.caption2)
.foregroundColor(.secondary)
}
Text(entry.message)
.font(.caption.monospaced())
.textSelection(.enabled)
}
.padding(.vertical, 2)
}
}
}
}
.navigationTitle("Logs")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
showShare = true
} label: {
Image(systemName: "square.and.arrow.up")
}
.disabled(store.entries.isEmpty)
}
ToolbarItem(placement: .cancellationAction) {
Button("Clear") { store.clear() }
.disabled(store.entries.isEmpty)
}
}
.sheet(isPresented: $showShare) {
ShareSheet(text: store.text)
}
}
private func color(for level: LogStore.Entry.Level) -> Color {
switch level {
case .info: return .secondary
case .warn: return .orange
case .error: return .red
}
}
}
/// Minimal share sheet wrapper (ShareLink is iOS 16+; this is explicit).
struct ShareSheet: UIViewControllerRepresentable {
let text: String
func makeUIViewController(context: Context) -> UIActivityViewController {
UIActivityViewController(activityItems: [text], applicationActivities: nil)
}
func updateUIViewController(_ uiViewController: UIActivityViewController,
context: Context) {}
}