Skip to content

Commit 30cc34b

Browse files
committed
update native replay integration with touch breadcrumb path
1 parent d9abf70 commit 30cc34b

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterReplayBreadcrumbConverter.kt

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class SentryFlutterReplayBreadcrumbConverter : DefaultReplayBreadcrumbConverter(
3030
"ui.click" ->
3131
newRRWebBreadcrumb(breadcrumb).apply {
3232
category = "ui.tap"
33-
message = breadcrumb.data["path"] as String?
33+
message = getTouchPathMessage(breadcrumb.data["path"])
3434
}
3535

3636
else -> {
@@ -83,4 +83,38 @@ class SentryFlutterReplayBreadcrumbConverter : DefaultReplayBreadcrumbConverter(
8383
}
8484
return rrWebEvent
8585
}
86+
87+
private fun getTouchPathMessage(maybePath: Any?): String? {
88+
if (maybePath !is List<*>) {
89+
return null
90+
}
91+
92+
if (maybePath.isEmpty()) {
93+
return null
94+
}
95+
96+
val message = StringBuilder()
97+
for (i in Math.min(3, maybePath.size - 1) downTo 0) {
98+
val item = maybePath[i]
99+
if (item !is Map<*, *>) {
100+
continue
101+
}
102+
103+
message.append(item["element"] ?: "?")
104+
105+
var identifier = item["label"] ?: item["name"]
106+
if (identifier is String && identifier.isNotEmpty()) {
107+
if (identifier.length > 20) {
108+
identifier = identifier.substring(0, 17) + "..."
109+
}
110+
message.append("(").append(identifier).append(")")
111+
}
112+
113+
if (i > 0) {
114+
message.append(" > ")
115+
}
116+
}
117+
118+
return message.toString()
119+
}
86120
}

flutter/ios/Classes/SentryFlutterReplayBreadcrumbConverter.m

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ - (instancetype _Nonnull)init {
3838
if ([breadcrumb.category isEqualToString:@"ui.click"]) {
3939
return [self convertFrom:breadcrumb
4040
withCategory:@"ui.tap"
41-
andMessage:breadcrumb.data[@"path"]];
41+
andMessage:[self getTouchPathMessage:breadcrumb.data[@"path"]]];
4242
}
4343

4444
SentryRRWebEvent *nativeBreadcrumb =
@@ -112,6 +112,42 @@ - (NSDate *_Nonnull)dateFrom:(NSNumber *_Nonnull)timestamp {
112112
return [NSDate dateWithTimeIntervalSince1970:(timestamp.doubleValue / 1000)];
113113
}
114114

115+
- (NSString * _Nullable)getTouchPathMessage:(id _Nullable)maybePath {
116+
if (![maybePath isKindOfClass:[NSArray class]]) {
117+
return nil;
118+
}
119+
120+
NSArray *path = (NSArray *)maybePath;
121+
if (path.count == 0) {
122+
return nil;
123+
}
124+
125+
NSMutableString *message = [NSMutableString string];
126+
for (NSInteger i = MIN(3, path.count - 1); i >= 0; i--) {
127+
id item = path[i];
128+
if (![item isKindOfClass:[NSDictionary class]]) {
129+
continue;
130+
}
131+
132+
NSDictionary *itemDict = (NSDictionary *)item;
133+
[message appendString:itemDict[@"element"] ?: @"?"];
134+
135+
id identifier = itemDict[@"label"] ?: itemDict[@"name"];
136+
if ([identifier isKindOfClass:[NSString class]] && [(NSString *)identifier length] > 0) {
137+
NSString *identifierStr = (NSString *)identifier;
138+
if (identifierStr.length > 20) {
139+
identifierStr = [[identifierStr substringToIndex:17] stringByAppendingString:@"..."];
140+
}
141+
[message appendFormat:@"(%@)", identifierStr];
142+
}
143+
144+
if (i > 0) {
145+
[message appendString:@" > "];
146+
}
147+
}
148+
149+
return message.length > 0 ? message : nil;
150+
}
115151
@end
116152

117153
#endif

0 commit comments

Comments
 (0)