Skip to content

Commit 8525da7

Browse files
committed
Add DebugAnalyticsView
1 parent c804e1d commit 8525da7

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2020–2023 Alexander Grebenyuk (github.com/kean).
4+
5+
import SwiftUI
6+
import Pulse
7+
8+
struct DebugAnalyticsView: View {
9+
@FetchRequest(
10+
sortDescriptors: [NSSortDescriptor(keyPath: \LoggerMessageEntity.createdAt, ascending: true)],
11+
predicate: makePredicate(searchText: "")
12+
) var messages: FetchedResults<LoggerMessageEntity>
13+
14+
@State private var searchText = ""
15+
16+
var body: some View {
17+
List(messages, id: \.objectID) { message in
18+
VStack(alignment: .leading) {
19+
HStack {
20+
Text(timeFormatter.string(from: message.createdAt))
21+
.font(.footnote)
22+
.foregroundColor(.secondary)
23+
Spacer()
24+
ListDisclosureIndicator()
25+
}
26+
Text(message.text)
27+
.lineLimit(2)
28+
}
29+
.background(NavigationLink("", destination: DebugAnalyticsDetailsView(message: message)).opacity(0))
30+
}
31+
.searchable(text: $searchText)
32+
.onChange(of: searchText) {
33+
messages.nsPredicate = makePredicate(searchText: $0)
34+
}
35+
.navigationTitle("Analyics")
36+
.listStyle(.plain)
37+
}
38+
}
39+
40+
private func makePredicate(searchText: String) -> NSPredicate {
41+
let basePredicate = NSPredicate(format: "label == %@ && session == %@", "analytics", LoggerStore.shared.session.id as NSUUID)
42+
let searchTerms = searchText
43+
.trimmingCharacters(in: .whitespaces)
44+
.components(separatedBy: .whitespaces)
45+
.filter { !$0.isEmpty }
46+
guard !searchTerms.isEmpty else { return basePredicate }
47+
let searchPredicates = NSCompoundPredicate(andPredicateWithSubpredicates: searchTerms.map {
48+
NSPredicate(format: "text CONTAINS[cd] %@", $0)
49+
})
50+
return NSCompoundPredicate(andPredicateWithSubpredicates: [basePredicate, searchPredicates])
51+
}
52+
53+
private struct DebugAnalyticsDetailsView: View {
54+
let message: LoggerMessageEntity
55+
56+
@State private var searchText = ""
57+
58+
var body: some View {
59+
List {
60+
Section {
61+
makeRow(title: "Event", value: message.text)
62+
makeRow(title: "Date", value: message.createdAt.description)
63+
}
64+
let metadata = self.metadata
65+
if !metadata.isEmpty {
66+
Section("Metadata") {
67+
ForEach(metadata, id: \.0, content: makeRow)
68+
}
69+
}
70+
}
71+
.searchable(text: $searchText)
72+
.navigationTitle("Event")
73+
.navigationBarTitleDisplayMode(.inline)
74+
}
75+
76+
private var metadata: [(String, String)] {
77+
Array(message.metadata).sorted {
78+
$0.key.localizedCaseInsensitiveCompare($1.key) == .orderedAscending
79+
}.filter {
80+
guard !searchText.isEmpty else { return true }
81+
return $0.key.localizedCaseInsensitiveContains(searchText) ||
82+
$0.value.localizedCaseInsensitiveContains(searchText)
83+
}
84+
}
85+
86+
private func makeRow(title: String, value: String) -> some View {
87+
VStack(alignment: .leading) {
88+
Text(higlighted(title, searchText: searchText))
89+
Text(higlighted(value, searchText: searchText))
90+
.foregroundStyle(.secondary)
91+
}
92+
}
93+
}
94+
95+
private struct ListDisclosureIndicator: View {
96+
var body: some View {
97+
Image(systemName: "chevron.right")
98+
.foregroundColor(Color(UIColor.separator))
99+
.lineLimit(1)
100+
.font(.caption)
101+
.foregroundColor(.secondary)
102+
.padding(.trailing, -12)
103+
}
104+
}
105+
106+
private func higlighted(_ string: String, searchText: String) -> AttributedString {
107+
var output = AttributedString(string)
108+
if !searchText.isEmpty, let range = output.range(of: searchText, options: [.caseInsensitive, .diacriticInsensitive]) {
109+
output[range].backgroundColor = .yellow.opacity(0.33)
110+
}
111+
return output
112+
}
113+
114+
private let timeFormatter: DateFormatter = {
115+
let formatter = DateFormatter()
116+
formatter.dateFormat = "HH:mm:ss.SSS"
117+
return formatter
118+
}()
119+
120+
#if DEBUG
121+
struct Previews_ShareView_Previews: PreviewProvider {
122+
static var previews: some View {
123+
Group {
124+
NavigationView {
125+
DebugAnalyticsView()
126+
.environment(\.managedObjectContext, LoggerStore.mock.viewContext)
127+
}
128+
NavigationView {
129+
DebugAnalyticsDetailsView(message: try! LoggerStore.mock.allMessages()[0])
130+
}
131+
}
132+
}
133+
}
134+
#endif

Pulse.xcodeproj/project.pbxproj

+6
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
0C40C09A296F77F1009ECF16 /* ConsoleSearchToggleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C40C099296F77F1009ECF16 /* ConsoleSearchToggleCell.swift */; };
7171
0C40C0A4296F849E009ECF16 /* ConsoleSearchTimePeriodCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C40C0A3296F849E009ECF16 /* ConsoleSearchTimePeriodCell.swift */; };
7272
0C4BF92D298817EC0086A6A7 /* IntlineTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C4BF92C298817EC0086A6A7 /* IntlineTabBar.swift */; };
73+
0C57511A2B01BA40001074E5 /* DebugAnalyticsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C5751182B01BA2B001074E5 /* DebugAnalyticsView.swift */; };
7374
0C603BD829E45A3C004FD4ED /* ConsoleListPinsSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C603BD729E45A3C004FD4ED /* ConsoleListPinsSectionView.swift */; };
7475
0C603BDA29E45DCC004FD4ED /* ConsoleListGroupedSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C603BD929E45DCC004FD4ED /* ConsoleListGroupedSectionView.swift */; };
7576
0C63A3782979FE3A00F6A6A5 /* ConsoleSearchTerm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C63A3772979FE3A00F6A6A5 /* ConsoleSearchTerm.swift */; };
@@ -522,6 +523,7 @@
522523
0C40C099296F77F1009ECF16 /* ConsoleSearchToggleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleSearchToggleCell.swift; sourceTree = "<group>"; };
523524
0C40C0A3296F849E009ECF16 /* ConsoleSearchTimePeriodCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleSearchTimePeriodCell.swift; sourceTree = "<group>"; };
524525
0C4BF92C298817EC0086A6A7 /* IntlineTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntlineTabBar.swift; sourceTree = "<group>"; };
526+
0C5751182B01BA2B001074E5 /* DebugAnalyticsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAnalyticsView.swift; sourceTree = "<group>"; };
525527
0C603BD729E45A3C004FD4ED /* ConsoleListPinsSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleListPinsSectionView.swift; sourceTree = "<group>"; };
526528
0C603BD929E45DCC004FD4ED /* ConsoleListGroupedSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleListGroupedSectionView.swift; sourceTree = "<group>"; };
527529
0C63A3772979FE3A00F6A6A5 /* ConsoleSearchTerm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsoleSearchTerm.swift; sourceTree = "<group>"; };
@@ -851,6 +853,7 @@
851853
0C25FB6725CDDC9700A895C2 /* IntegrationsExamples */ = {
852854
isa = PBXGroup;
853855
children = (
856+
0C5751182B01BA2B001074E5 /* DebugAnalyticsView.swift */,
854857
0C25FB6E25CDDCAB00A895C2 /* URLSessionManualIntegration.swift */,
855858
0C1221E525CE09C100B81D7A /* URLSessionAutomatedIntegration.swift */,
856859
49E82A8526D107A00070244F /* AlamofireIntegration.swift */,
@@ -1868,6 +1871,7 @@
18681871
0C0B31ED26D179A20045C9E1 /* AppDelegate.swift in Sources */,
18691872
0C0B31EF26D179A20045C9E1 /* SceneDelegate.swift in Sources */,
18701873
0C11EADB2971EBE80059786A /* MockStore.swift in Sources */,
1874+
0C57511A2B01BA40001074E5 /* DebugAnalyticsView.swift in Sources */,
18711875
);
18721876
runOnlyForDeploymentPostprocessing = 0;
18731877
};
@@ -2275,6 +2279,7 @@
22752279
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
22762280
CODE_SIGN_STYLE = Automatic;
22772281
INFOPLIST_FILE = Demo/Integrations/Info.plist;
2282+
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
22782283
LD_RUNPATH_SEARCH_PATHS = (
22792284
"$(inherited)",
22802285
"@executable_path/Frameworks",
@@ -2296,6 +2301,7 @@
22962301
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
22972302
CODE_SIGN_STYLE = Automatic;
22982303
INFOPLIST_FILE = Demo/Integrations/Info.plist;
2304+
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
22992305
LD_RUNPATH_SEARCH_PATHS = (
23002306
"$(inherited)",
23012307
"@executable_path/Frameworks",

0 commit comments

Comments
 (0)