Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
a7d8e8b
first pass on setting up JS bridge with some performance tracking
jacksonhardaker Dec 23, 2025
67d7ba9
lint
jacksonhardaker Dec 23, 2025
0aa48a5
add dedicated webview testing card
jacksonhardaker Dec 24, 2025
3534b3b
remove native callbacks
jacksonhardaker Dec 24, 2025
945000d
update web vital js
jacksonhardaker Dec 24, 2025
74e6c6a
improve network log
jacksonhardaker Dec 24, 2025
12e59bb
represent web vitals as spans
jacksonhardaker Dec 24, 2025
5c1fffd
switch to `LoggerImpl` to control log type
jacksonhardaker Dec 29, 2025
f515e8d
add page view span as parent to web vital measurements
jacksonhardaker Dec 29, 2025
9f9b3e4
wire up error handling, click detection, console.log
jacksonhardaker Dec 29, 2025
1344b17
remove parent span attribute from unrelated logs
jacksonhardaker Dec 30, 2025
96ef393
add license headers
jacksonhardaker Dec 30, 2025
18512c0
swift lint
jacksonhardaker Dec 30, 2025
e084afd
fix swift
jacksonhardaker Dec 30, 2025
f6e1033
use model for kotlin
jacksonhardaker Dec 30, 2025
8338190
implement fallback injection method
jacksonhardaker Dec 31, 2025
2b06418
add simple re-initialization guard
jacksonhardaker Dec 31, 2025
684c04e
remove unused type
jacksonhardaker Dec 31, 2025
24cb84a
more tweaks
jacksonhardaker Dec 31, 2025
29e09af
improve rage click
jacksonhardaker Jan 9, 2026
b25f1b6
setup biome: lint, format
jacksonhardaker Jan 13, 2026
a9e3e99
ignore dist dir
jacksonhardaker Jan 13, 2026
20cba55
style convert to arrow functions
jacksonhardaker Jan 13, 2026
a09ecef
Run format
FranAguilera Jan 14, 2026
12f69a7
Append license header to gen files
FranAguilera Jan 14, 2026
7463462
webkit_compile_only + fixing bazel test build issues
FranAguilera Jan 14, 2026
1447a14
add test page to android test app (#826)
jacksonhardaker Jan 14, 2026
fd874ec
add convenience commands to makefile for ts fix/build
jacksonhardaker Jan 14, 2026
a1cd225
[Android] Add bottom nav to gradle-test-app (#828)
FranAguilera Jan 15, 2026
2247530
first pass on setting up JS bridge with some performance tracking
jacksonhardaker Dec 23, 2025
1aea10e
lint
jacksonhardaker Dec 23, 2025
ffa2eaf
add dedicated webview testing card
jacksonhardaker Dec 24, 2025
9cc4d24
remove native callbacks
jacksonhardaker Dec 24, 2025
778baec
update web vital js
jacksonhardaker Dec 24, 2025
d543ce8
improve network log
jacksonhardaker Dec 24, 2025
24b159f
represent web vitals as spans
jacksonhardaker Dec 24, 2025
60aaa16
switch to `LoggerImpl` to control log type
jacksonhardaker Dec 29, 2025
d34d7b0
add page view span as parent to web vital measurements
jacksonhardaker Dec 29, 2025
760eb50
wire up error handling, click detection, console.log
jacksonhardaker Dec 29, 2025
2a577bc
remove parent span attribute from unrelated logs
jacksonhardaker Dec 30, 2025
97c2b7c
add license headers
jacksonhardaker Dec 30, 2025
5d68943
swift lint
jacksonhardaker Dec 30, 2025
eaf5e4c
fix swift
jacksonhardaker Dec 30, 2025
777ea0d
use model for kotlin
jacksonhardaker Dec 30, 2025
502bb62
implement fallback injection method
jacksonhardaker Dec 31, 2025
ae7ec9b
add simple re-initialization guard
jacksonhardaker Dec 31, 2025
af40878
remove unused type
jacksonhardaker Dec 31, 2025
2980611
more tweaks
jacksonhardaker Dec 31, 2025
00fb38e
improve rage click
jacksonhardaker Jan 9, 2026
6d6bcd6
setup biome: lint, format
jacksonhardaker Jan 13, 2026
3652707
ignore dist dir
jacksonhardaker Jan 13, 2026
5fe6b55
style convert to arrow functions
jacksonhardaker Jan 13, 2026
c52c42f
Run format
FranAguilera Jan 14, 2026
dcfb8be
Append license header to gen files
FranAguilera Jan 14, 2026
53df9a9
webkit_compile_only + fixing bazel test build issues
FranAguilera Jan 14, 2026
07af96c
add test page to android test app (#826)
jacksonhardaker Jan 14, 2026
11df3ff
add convenience commands to makefile for ts fix/build
jacksonhardaker Jan 14, 2026
e375425
Bring bottom nav navigation
FranAguilera Jan 15, 2026
19ae059
Merge branch 'jh/js-bridge-webview' of https://github.com/bitdriftlab…
FranAguilera Jan 15, 2026
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
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ maven.install(

# Compile-only via wrapper target; not on runtime classpath
"com.squareup.retrofit2:retrofit:3.0.0",
"androidx.webkit:webkit:1.12.1",
],
repositories = [
"https://maven.google.com",
Expand Down
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,13 @@ xcframework:
.PHONY: test-gradle
test-gradle:
platform/jvm/gradlew :capture:testDebugUnitTest -p platform/jvm

.PHONY: fix-ts
fix-ts:
npm --prefix ./platform/webview run lint:fix
npm --prefix ./platform/webview run format

.PHONY: build-ts
build-ts:
npm --prefix ./platform/webview run build
npm --prefix ./platform/webview run generate
2 changes: 1 addition & 1 deletion ci/license_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
'./target/',
)

extensions_to_check = ('.rs', '.toml', '.kt', '.java', '.swift')
extensions_to_check = ('.rs', '.toml', '.kt', '.java', '.swift', '.js', '.ts')


def check_file(file_path):
Expand Down
1 change: 1 addition & 0 deletions examples/android/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ _maven_deps = [
artifact("org.jetbrains:annotations"),
artifact("androidx.metrics:metrics-performance"),
artifact("com.squareup.retrofit2:retrofit"),
artifact("androidx.webkit:webkit"),
]

aar_import(
Expand Down
9 changes: 9 additions & 0 deletions platform/jvm/capture/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ java_library(
exports = [artifact("com.squareup.retrofit2:retrofit")],
)

# WebKit compile-only wrapper: exposes API at compile time, excluded from runtime via neverlink.
java_library(
name = "webkit_compile_only",
neverlink = True,
visibility = ["//visibility:public"],
exports = [artifact("androidx.webkit:webkit")],
)

# export proguard library rules
exports_files(["consumer-rules.pro"])

Expand Down Expand Up @@ -71,6 +79,7 @@ bitdrift_kt_android_library(
artifact("androidx.metrics:metrics-performance"),
# Compile-only dependency (neverlink wrapper). Not packaged nor appearing in POM.
":retrofit_compile_only",
":webkit_compile_only",
],
)

Expand Down
1 change: 1 addition & 0 deletions platform/jvm/capture/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies {
implementation(project(":common"))
implementation(libs.androidx.core)
implementation(libs.androidx.startup.runtime)
implementation(libs.androidx.webkit)
implementation(libs.jsr305)
implementation(libs.gson)
implementation(libs.performance)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// capture-sdk - bitdrift's client SDK
// Copyright Bitdrift, Inc. All rights reserved.
//
// Use of this source code is governed by a source available license that can be found in the
// LICENSE file or at:
// https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt

package io.bitdrift.capture.webview

import com.google.gson.annotations.SerializedName

/**
* Base class for all WebView bridge messages.
* All messages have a version, type, and timestamp.
*/
internal data class WebViewBridgeMessage(
@SerializedName("v") val version: Int = 0,
val tag: String? = null,
val type: String? = null,
val timestamp: Long? = null,
// bridgeReady
val url: String? = null,
// webVital
val metric: WebVitalMetric? = null,
val parentSpanId: String? = null,
// networkRequest
val method: String? = null,
val statusCode: Int? = null,
val durationMs: Long? = null,
val success: Boolean? = null,
val error: String? = null,
val requestType: String? = null,
val timing: NetworkTiming? = null,
// navigation
val fromUrl: String? = null,
val toUrl: String? = null,
// pageView
val action: String? = null,
val spanId: String? = null,
val reason: String? = null,
// lifecycle
val event: String? = null,
val performanceTime: Double? = null,
val visibilityState: String? = null,
// error
val name: String? = null,
val message: String? = null,
val stack: String? = null,
val filename: String? = null,
val lineno: Int? = null,
val colno: Int? = null,
// longTask
val startTime: Double? = null,
val attribution: LongTaskAttribution? = null,
// resourceError
val resourceType: String? = null,
val tagName: String? = null,
// console
val level: String? = null,
val args: List<String>? = null,
// userInteraction
val interactionType: String? = null,
val elementId: String? = null,
val className: String? = null,
val textContent: String? = null,
val isClickable: Boolean? = null,
val clickCount: Int? = null,
val timeWindowMs: Int? = null,
)

/**
* Web Vital metric data from the web-vitals library.
*/
internal data class WebVitalMetric(
val name: String? = null,
val value: Double? = null,
val rating: String? = null,
val delta: Double? = null,
val id: String? = null,
val navigationType: String? = null,
val entries: List<WebVitalEntry>? = null,
)

/**
* Performance entry associated with a web vital metric.
* Contains different fields depending on the metric type.
*/
internal data class WebVitalEntry(
// Common fields
val startTime: Double? = null,
val entryType: String? = null,
// LCP-specific
val element: String? = null,
val url: String? = null,
val size: Long? = null,
val renderTime: Double? = null,
val loadTime: Double? = null,
// FCP-specific
val name: String? = null,
// TTFB-specific (PerformanceNavigationTiming)
val domainLookupStart: Double? = null,
val domainLookupEnd: Double? = null,
val connectStart: Double? = null,
val connectEnd: Double? = null,
val secureConnectionStart: Double? = null,
val requestStart: Double? = null,
val responseStart: Double? = null,
// INP-specific
val processingStart: Double? = null,
val processingEnd: Double? = null,
val duration: Double? = null,
val interactionId: Long? = null,
// CLS-specific
val value: Double? = null,
)

/**
* Network timing data from the Performance API.
*/
internal data class NetworkTiming(
val transferSize: Long? = null,
val dnsMs: Long? = null,
val tlsMs: Long? = null,
val connectMs: Long? = null,
val ttfbMs: Long? = null,
)

/**
* Long task attribution data.
*/
internal data class LongTaskAttribution(
val name: String? = null,
val containerType: String? = null,
val containerSrc: String? = null,
val containerId: String? = null,
val containerName: String? = null,
)

Large diffs are not rendered by default.

Loading
Loading