Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metadata View #81

Merged
merged 6 commits into from
May 14, 2022
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Pulse 1.x

## Pulse 1.1.0

*May 14, 2022*

- [iOS, watchOS] Update message details design, display custom metadata – [#81](https://github.com/kean/Pulse/pull/81)
- [iOS] Fix an issue with search toolbar not showing up during searching

## Pulse 1.0.3

*May 3, 2022*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,16 @@
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "32">
<RemoteRunnable
runnableDebuggingMode = "2"
BundleIdentifier = "com.apple.Carousel"
RemotePath = "/Pulse">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0CEAB3D925FE862D00F09B0F"
BuildableName = "Pulse Demo watchOS.app"
BlueprintName = "Pulse Demo watchOS"
ReferencedContainer = "container:Pulse.xcodeproj">
</BuildableReference>
</RemoteRunnable>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand All @@ -75,27 +73,16 @@
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
launchAutomaticallySubstyle = "32">
<RemoteRunnable
runnableDebuggingMode = "2"
BundleIdentifier = "com.apple.Carousel"
RemotePath = "/Pulse">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0CEAB3D925FE862D00F09B0F"
BuildableName = "Pulse Demo watchOS.app"
BlueprintName = "Pulse Demo watchOS"
ReferencedContainer = "container:Pulse.xcodeproj">
</BuildableReference>
</RemoteRunnable>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0CEAB3D925FE862D00F09B0F"
BuildableName = "Pulse Demo watchOS.app"
BlueprintName = "Pulse Demo watchOS"
ReferencedContainer = "container:Pulse.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
Expand Down
25 changes: 6 additions & 19 deletions Pulse.xcodeproj/xcshareddata/xcschemes/Pulse Demo watchOS.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -54,46 +54,33 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<RemoteRunnable
runnableDebuggingMode = "2"
BundleIdentifier = "com.apple.Carousel"
RemotePath = "/Pulse">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0CEAB3D925FE862D00F09B0F"
BuildableName = "Pulse Demo watchOS.app"
BlueprintName = "Pulse Demo watchOS"
ReferencedContainer = "container:Pulse.xcodeproj">
</BuildableReference>
</RemoteRunnable>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<RemoteRunnable
runnableDebuggingMode = "2"
BundleIdentifier = "com.apple.Carousel"
RemotePath = "/Pulse">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0CEAB3D925FE862D00F09B0F"
BuildableName = "Pulse Demo watchOS.app"
BlueprintName = "Pulse Demo watchOS"
ReferencedContainer = "container:Pulse.xcodeproj">
</BuildableReference>
</RemoteRunnable>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0CEAB3D925FE862D00F09B0F"
BuildableName = "Pulse Demo watchOS.app"
BlueprintName = "Pulse Demo watchOS"
ReferencedContainer = "container:Pulse.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ struct ConsoleMessageDetailsView: View {
var body: some View {
contents
.navigationBarTitle("", displayMode: .inline)
.navigationBarItems(trailing: HStack(spacing: 18) {
.navigationBarItems(trailing: HStack(spacing: 14) {
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
Expand All @@ -32,10 +35,21 @@ struct ConsoleMessageDetailsView: View {
#elseif os(watchOS)
var body: some View {
ScrollView {
contents
}.toolbar(content: {
PinButton(viewModel: viewModel.pin, isTextNeeded: false)
})
VStack {
HStack {
PinButton3(viewModel: viewModel.pin)
NavigationLink(destination: ConsoleMessageMetadataView(message: viewModel.message)) {
VStack(spacing: 4) {
Image(systemName: "info.circle")
.foregroundColor(.blue)
Text("Details")
.font(.caption2)
}.frame(height: 42)
}
}
contents
}
}
}
#elseif os(tvOS)
var body: some View {
Expand All @@ -45,7 +59,6 @@ struct ConsoleMessageDetailsView: View {

private var contents: some View {
VStack {
tags
textView
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
}
Expand Down Expand Up @@ -76,25 +89,40 @@ struct ConsoleMessageDetailsView: View {
.background(Color.gray.opacity(0.15))
.cornerRadius(8)
}
#else
private var tags: some View {
VStack(alignment: .leading) {
ForEach(viewModel.tags, id: \.title) { tag in
HStack {
Text(tag.title)
.font(.caption)
.foregroundColor(.secondary)
Text(tag.value)
.font(.caption)
.bold()
.foregroundColor(.secondary)
}
#endif
}

#if DEBUG
@available(iOS 13.0, tvOS 14.0, watchOS 7.0, *)
struct ConsoleMessageDetailsView_Previews: PreviewProvider {
static var previews: some View {
Group {
NavigationView {
ConsoleMessageDetailsView(viewModel: .init(store: LoggerStore.mock, message: makeMockMessage()))
}
}
.padding(16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color.gray.opacity(0.15))
}
#endif
}

func makeMockMessage() -> LoggerMessageEntity {
let entity = LoggerMessageEntity(context: LoggerStore.mock.container.viewContext)
entity.text = "test"
entity.createdAt = Date()
entity.label = "auth"
entity.level = "critical"
entity.session = UUID().uuidString
entity.file = "~/Develop/Pulse/LoggerStore.swift"
entity.filename = "LoggerStore.swift"
entity.function = "createMockMessage()"
entity.line = 12

let meta = LoggerMetadataEntity(context: LoggerStore.mock.container.viewContext)
meta.key = "customKey"
meta.value = "customValue"

entity.metadata = Set([meta])
return entity
}
#endif

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class ConsoleMessageDetailsViewModel {
let text: String
let badge: BadgeViewModel?

private let message: LoggerMessageEntity
let message: LoggerMessageEntity
private let store: LoggerStore

static let dateFormatter: DateFormatter = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// The MIT License (MIT)
//
// Copyright (c) 2020–2022 Alexander Grebenyuk (github.com/kean).

import SwiftUI
import PulseCore

#if os(iOS) || os(tvOS) || os(watchOS)
@available(iOS 13.0, tvOS 14.0, watchOS 7.0, *)
struct ConsoleMessageMetadataView: View {
let message: LoggerMessageEntity

@State private var isMetadataRawLinkActive = false

var body: some View {
contents
.background(linksView)
#if os(iOS)
.navigationBarTitle("Details", displayMode: .inline)
#endif
}

@ViewBuilder
private var contents: some View {
ScrollView {
#if os(iOS) || os(tvOS)
VStack {
stackContents
}.padding()
#elseif os(watchOS)
VStack(spacing: 16) {
stackContents
}
#endif
}
}

@ViewBuilder
private var stackContents: some View {
KeyValueSectionView(viewModel: .init(title: "Summary", color: message.tintColor, items: [
("Date", dateFormatter.string(from: message.createdAt)),
("Level", message.level),
("Label", message.label.nonEmpty)
]))
KeyValueSectionView(viewModel: .init(title: "Details", color: .secondary, items: [
("Session", message.session.nonEmpty),
("File", message.file.nonEmpty),
("Filename", message.filename.nonEmpty),
("Function", message.function.nonEmpty),
("Line", message.line == 0 ? nil : "\(message.line)"),
]))
KeyValueSectionView(viewModel: metadataViewModel)
}

private var metadataViewModel: KeyValueSectionViewModel {
KeyValueSectionViewModel(title: "Metadata", color: .indigo, action: .init(action: {
isMetadataRawLinkActive = true
}, title: "View"), items: metadataItems)
}

private var metadataItems: [(String, String?)] {
message.metadata.sorted(by: { $0.key < $1.key }).map { ($0.key, $0.value )}
}

private var linksView: some View {
NavigationLink(destination: NetworkHeadersDetailsView(viewModel: metadataViewModel), isActive: $isMetadataRawLinkActive) {
EmptyView()
}.opacity(0)
}
}

@available(iOS 13.0, tvOS 14.0, watchOS 7.0, *)
private extension LoggerMessageEntity {
var tintColor: Color {
Color.badgeColor(for: .init(rawValue: level) ?? .debug)
}
}

private extension String {
var nonEmpty: String? {
isEmpty ? nil : self
}
}

private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm:ss.SSS, yyyy-MM-dd"
return formatter
}()

#if DEBUG
@available(iOS 13.0, tvOS 14.0, watchOS 7.0, *)
struct ConsoleMessageMetadataView_Previews: PreviewProvider {
static var previews: some View {
Group {
NavigationView {
ConsoleMessageMetadataView(message: makeMockMessage())
}
}
}
}
#endif

#endif
18 changes: 18 additions & 0 deletions Sources/PulseUI/Views/PinButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ struct PinButton2: View {
}
}

#if os(watchOS)
@available(iOS 14.0, tvOS 14.0, watchOS 7.0, *)
struct PinButton3: View {
@ObservedObject var viewModel: PinButtonViewModel

var body: some View {
Button(action: viewModel.togglePin) {
VStack(spacing: 4) {
Image(systemName: viewModel.isPinned ? "pin.slash" : "pin")
.foregroundColor(.blue)
Text(viewModel.isPinned ? "Remove Pin" : "Pin")
.font(.caption2)
}.frame(height: 42)
}
}
}
#endif

#if os(iOS)
@available(iOS 13.0, *)
extension UIAction {
Expand Down
4 changes: 2 additions & 2 deletions Sources/PulseUI/Views/SearchBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ struct SearchBar: UIViewRepresentable {
}

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {

self.onEditingChanged?(true)
}

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {

self.onEditingChanged?(false)
}
}

Expand Down