Skip to content
Open
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
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ let package = Package(
name: "OpenPanel",
platforms: [
.iOS(.v13),
.macOS(.v10_15)
.macOS(.v10_15),
.tvOS(.v13)
],
products: [
.library(
Expand Down
35 changes: 19 additions & 16 deletions Sources/OpenPanel/OpenPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Foundation
#if os(iOS)
import UIKit
import WebKit
#elseif os(tvOS)
import UIKit
#elseif os(macOS)
import AppKit
import WebKit
Expand Down Expand Up @@ -43,13 +45,11 @@ internal class DeviceInfo {

_ = semaphore.wait(timeout: .now() + 1.0)

userAgent += " OpenPanel/\(OpenPanel.sdkVersion)"

if userAgent.isEmpty {
userAgent = getBasicUserAgent()
return getBasicUserAgent()
}
return userAgent

return userAgent + " OpenPanel/\(OpenPanel.sdkVersion)"
Comment on lines 48 to +52

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify if getBasicUserAgent already appends the SDK version
rg -A 5 'func getBasicUserAgent' Sources/OpenPanel/OpenPanel.swift

Repository: Openpanel-dev/swift-sdk

Length of output: 381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='Sources/OpenPanel/OpenPanel.swift'

echo '--- outline ---'
ast-grep outline "$file" --view expanded || true

echo '--- numbered excerpt ---'
sed -n '1,220p' "$file" | cat -n

Repository: Openpanel-dev/swift-sdk

Length of output: 12146


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' Sources/OpenPanel/OpenPanel.swift | nl -ba

Repository: Openpanel-dev/swift-sdk

Length of output: 201


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
text = Path('Sources/OpenPanel/OpenPanel.swift').read_text()
for needle in ['getBasicUserAgent', 'sdkVersion', 'semaphore.wait', 'DispatchQueue.main.async', 'WKWebView']:
    print(f'--- {needle} ---')
    idx = text.find(needle)
    if idx == -1:
        print('not found')
        continue
    start = max(0, text.rfind('\n', 0, idx-400))
    end = min(len(text), idx+800)
    snippet = text[start:end]
    print(snippet)
PY

Repository: Openpanel-dev/swift-sdk

Length of output: 6343


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='Sources/OpenPanel/OpenPanel.swift'

echo '--- call sites for DeviceInfo.getUserAgent ---'
rg -n 'DeviceInfo\.getUserAgent|getUserAgent\(' Sources/OpenPanel/OpenPanel.swift

echo '--- OpenPanel.initialize excerpt ---'
sed -n '298,380p' "$file" | cat -n

Repository: Openpanel-dev/swift-sdk

Length of output: 3870


Sources/OpenPanel/OpenPanel.swift:30-52 — Avoid blocking initialize() while fetching the user agent. The fallback already appends OpenPanel/\(OpenPanel.sdkVersion), but this path can still block the caller for up to 1s if initialize() runs on the main thread, and WKWebView is created before the DispatchQueue.main.async hop. Make the lookup async or cache the result instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/OpenPanel/OpenPanel.swift` around lines 48 - 52, Update the
user-agent lookup used by initialize() so it does not synchronously fetch or
construct WKWebView on the caller thread, especially the main thread. Make the
lookup asynchronous or cache its result, ensuring initialize() remains
non-blocking while preserving the fallback user agent with the OpenPanel SDK
suffix.

} else {
return getBasicUserAgent()
}
Expand All @@ -72,12 +72,10 @@ internal class DeviceInfo {
#endif

private static func getMacOSUserAgent() -> String {
let processInfo = ProcessInfo.processInfo
let osVersion = processInfo.operatingSystemVersionString
let versionParts = osVersion.components(separatedBy: " ")
let version = versionParts.count > 1 ? versionParts[1] : "Unknown"

let userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X \(version.replacingOccurrences(of: ".", with: "_"))) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15"
let osVersion = ProcessInfo.processInfo.operatingSystemVersion
let version = "\(osVersion.majorVersion)_\(osVersion.minorVersion)_\(osVersion.patchVersion)"

let userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X \(version)) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15"

return userAgent + " OpenPanel/\(OpenPanel.sdkVersion)"
}
Expand Down Expand Up @@ -334,7 +332,7 @@ public class OpenPanel {
private var options: Options?

public static var sdkVersion: String {
return "0.0.1"
return "1.0.1"
}

private init() {
Expand Down Expand Up @@ -387,7 +385,9 @@ public class OpenPanel {
}

if options.waitForProfile == true, profileId == nil {
queue.append(payload)
globalQueue.async(flags: .barrier) {
self.queue.append(payload)
}
return
}

Expand Down Expand Up @@ -457,7 +457,7 @@ public class OpenPanel {
if let global = shared._global {
var mergedProperties = global
if let payloadProperties = payload.properties {
mergedProperties.merge(payloadProperties) { (_, new) in (new as AnyObject).value }
mergedProperties.merge(payloadProperties) { (_, new) in (new as? AnyCodable)?.value ?? new }
}
updatedPayload.properties = mergedProperties.mapValues { AnyCodable($0) }
}
Expand Down Expand Up @@ -486,8 +486,11 @@ public class OpenPanel {
}

public func flush() {
let currentQueue = queue
queue.removeAll()
let currentQueue = globalQueue.sync(flags: .barrier) { () -> [TrackHandlerPayload] in
let items = queue
queue.removeAll()
return items
}
for item in currentQueue {
send(item)
}
Expand Down