mirror of
https://github.com/kean/Pulse.git
synced 2026-05-30 21:07:33 +00:00
157 lines
5.2 KiB
Swift
157 lines
5.2 KiB
Swift
// The MIT License (MIT)
|
||
//
|
||
// Copyright (c) 2020–2022 Alexander Grebenyuk (github.com/kean).
|
||
|
||
import SwiftUI
|
||
import Pulse
|
||
|
||
struct ConsoleMessageDetailsView: View {
|
||
let viewModel: ConsoleMessageDetailsViewModel
|
||
@Environment(\.colorScheme) var colorScheme: ColorScheme
|
||
@State private var isShowingShareSheet = false
|
||
var onClose: (() -> Void)?
|
||
|
||
#if os(iOS)
|
||
var body: some View {
|
||
contents
|
||
.navigationBarTitle("", displayMode: .inline)
|
||
.navigationBarItems(trailing: trailingNavigationBarItems)
|
||
.sheet(isPresented: $isShowingShareSheet) {
|
||
ShareView(activityItems: [self.viewModel.prepareForSharing()])
|
||
}
|
||
}
|
||
|
||
@ViewBuilder
|
||
private var trailingNavigationBarItems: some View {
|
||
HStack(spacing: 10) {
|
||
if let badge = viewModel.badge {
|
||
BadgeView(viewModel: BadgeViewModel(title: badge.title, color: badge.color.opacity(colorScheme == .light ? 0.25 : 0.5)))
|
||
}
|
||
NavigationLink(destination: ConsoleMessageMetadataView(message: viewModel.message)) {
|
||
Image(systemName: "info.circle")
|
||
}
|
||
PinButton(viewModel: viewModel.pin, isTextNeeded: false)
|
||
ShareButton {
|
||
self.isShowingShareSheet = true
|
||
}
|
||
}
|
||
}
|
||
#elseif os(watchOS)
|
||
var body: some View {
|
||
ScrollView {
|
||
VStack(spacing: 8) {
|
||
NavigationLink(destination: ConsoleMessageMetadataView(message: viewModel.message)) {
|
||
Label("Details", systemImage: "info.circle")
|
||
}
|
||
contents
|
||
}
|
||
}
|
||
}
|
||
#elseif os(tvOS)
|
||
var body: some View {
|
||
contents
|
||
}
|
||
#elseif os(macOS)
|
||
@State var isMetaVisible = false
|
||
|
||
var body: some View {
|
||
VStack(spacing: 0) {
|
||
HStack(spacing: 12) {
|
||
Button(action: { isMetaVisible = true }) {
|
||
Image(systemName: "info.circle")
|
||
}.padding(.leading, 4)
|
||
if let badge = viewModel.badge {
|
||
BadgeView(viewModel: BadgeViewModel(title: badge.title, color: badge.color.opacity(colorScheme == .light ? 0.25 : 0.5)))
|
||
}
|
||
Spacer()
|
||
if let onClose = onClose {
|
||
Button(action: onClose) {
|
||
Image(systemName: "xmark").foregroundColor(.secondary)
|
||
}.buttonStyle(.plain)
|
||
}
|
||
}
|
||
.padding([.leading, .trailing], 6)
|
||
.frame(height: 27, alignment: .center)
|
||
Divider()
|
||
textView
|
||
.background(colorScheme == .dark ? Color(NSColor(red: 30/255.0, green: 30/255.0, blue: 30/255.0, alpha: 1)) : .clear)
|
||
}
|
||
.sheet(isPresented: $isMetaVisible, content: {
|
||
VStack(spacing: 0) {
|
||
HStack {
|
||
Text("Message Details")
|
||
.font(.headline)
|
||
.foregroundColor(.secondary)
|
||
Spacer()
|
||
Button("Close") { isMetaVisible = false }
|
||
.keyboardShortcut(.cancelAction)
|
||
}.padding()
|
||
ConsoleMessageMetadataView(message: viewModel.message)
|
||
}.frame(width: 440, height: 600)
|
||
})
|
||
}
|
||
#endif
|
||
|
||
private var contents: some View {
|
||
VStack {
|
||
textView
|
||
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||
}
|
||
|
||
private var textView: some View {
|
||
RichTextView(viewModel: viewModel.textViewModel)
|
||
}
|
||
|
||
#if os(watchOS) || os(tvOS)
|
||
private var tags: some View {
|
||
VStack(alignment: .leading) {
|
||
if let badge = viewModel.badge {
|
||
BadgeView(viewModel: BadgeViewModel(title: badge.title, color: badge.color.opacity(colorScheme == .light ? 0.25 : 0.5)))
|
||
}
|
||
ForEach(viewModel.tags, id: \.title) { tag in
|
||
HStack {
|
||
Text(tag.title)
|
||
.font(.caption)
|
||
.foregroundColor(.secondary)
|
||
Text(tag.value)
|
||
.font(.caption)
|
||
.foregroundColor(.primary)
|
||
}
|
||
}
|
||
}
|
||
.padding()
|
||
.frame(maxWidth: .infinity, alignment: .leading)
|
||
.background(Color.gray.opacity(0.15))
|
||
.cornerRadius(8)
|
||
}
|
||
#endif
|
||
}
|
||
|
||
#if DEBUG
|
||
struct ConsoleMessageDetailsView_Previews: PreviewProvider {
|
||
static var previews: some View {
|
||
NavigationView {
|
||
ConsoleMessageDetailsView(viewModel: .init(message: makeMockMessage()), onClose: {})
|
||
}
|
||
}
|
||
}
|
||
|
||
func makeMockMessage() -> LoggerMessageEntity {
|
||
let entity = LoggerMessageEntity(context: LoggerStore.mock.viewContext)
|
||
entity.text = "test"
|
||
entity.createdAt = Date()
|
||
|
||
let label = LoggerLabelEntity(context: LoggerStore.mock.viewContext)
|
||
label.name = "auth"
|
||
entity.label = label
|
||
|
||
entity.level = LoggerStore.Level.critical.rawValue
|
||
entity.session = UUID()
|
||
entity.file = "LoggerStore.swift"
|
||
entity.function = "createMockMessage()"
|
||
entity.line = 12
|
||
entity.rawMetadata = "customKey: customValue"
|
||
return entity
|
||
}
|
||
#endif
|