refactor(macos): share pairing and ui dedupe utilities

This commit is contained in:
Peter Steinberger
2026-03-02 12:13:35 +00:00
parent d85d3c88d5
commit 87316e07d8
13 changed files with 196 additions and 161 deletions

View File

@@ -70,13 +70,7 @@ private struct ChatBubbleShape: InsettableShape {
to: baseBottom,
control1: CGPoint(x: bubbleMaxX + self.tailWidth * 0.95, y: midY + baseH * 0.15),
control2: CGPoint(x: bubbleMaxX + self.tailWidth * 0.2, y: baseBottomY - baseH * 0.05))
path.addQuadCurve(
to: CGPoint(x: bubbleMaxX - r, y: bubbleMaxY),
control: CGPoint(x: bubbleMaxX, y: bubbleMaxY))
path.addLine(to: CGPoint(x: bubbleMinX + r, y: bubbleMaxY))
path.addQuadCurve(
to: CGPoint(x: bubbleMinX, y: bubbleMaxY - r),
control: CGPoint(x: bubbleMinX, y: bubbleMaxY))
self.addBottomEdge(path: &path, bubbleMinX: bubbleMinX, bubbleMaxX: bubbleMaxX, bubbleMaxY: bubbleMaxY, radius: r)
path.addLine(to: CGPoint(x: bubbleMinX, y: bubbleMinY + r))
path.addQuadCurve(
to: CGPoint(x: bubbleMinX + r, y: bubbleMinY),
@@ -108,13 +102,7 @@ private struct ChatBubbleShape: InsettableShape {
to: CGPoint(x: bubbleMaxX, y: bubbleMinY + r),
control: CGPoint(x: bubbleMaxX, y: bubbleMinY))
path.addLine(to: CGPoint(x: bubbleMaxX, y: bubbleMaxY - r))
path.addQuadCurve(
to: CGPoint(x: bubbleMaxX - r, y: bubbleMaxY),
control: CGPoint(x: bubbleMaxX, y: bubbleMaxY))
path.addLine(to: CGPoint(x: bubbleMinX + r, y: bubbleMaxY))
path.addQuadCurve(
to: CGPoint(x: bubbleMinX, y: bubbleMaxY - r),
control: CGPoint(x: bubbleMinX, y: bubbleMaxY))
self.addBottomEdge(path: &path, bubbleMinX: bubbleMinX, bubbleMaxX: bubbleMaxX, bubbleMaxY: bubbleMaxY, radius: r)
path.addLine(to: baseBottom)
path.addCurve(
to: tip,
@@ -131,6 +119,22 @@ private struct ChatBubbleShape: InsettableShape {
return path
}
private func addBottomEdge(
path: inout Path,
bubbleMinX: CGFloat,
bubbleMaxX: CGFloat,
bubbleMaxY: CGFloat,
radius: CGFloat)
{
path.addQuadCurve(
to: CGPoint(x: bubbleMaxX - radius, y: bubbleMaxY),
control: CGPoint(x: bubbleMaxX, y: bubbleMaxY))
path.addLine(to: CGPoint(x: bubbleMinX + radius, y: bubbleMaxY))
path.addQuadCurve(
to: CGPoint(x: bubbleMinX, y: bubbleMaxY - radius),
control: CGPoint(x: bubbleMinX, y: bubbleMaxY))
}
}
@MainActor

View File

@@ -1,4 +1,5 @@
import Foundation
import OpenClawProtocol
public enum GatewayDeviceAuthPayload {
public static func buildV3(
@@ -52,4 +53,24 @@ public enum GatewayDeviceAuthPayload {
}
return output
}
public static func signedDeviceDictionary(
payload: String,
identity: DeviceIdentity,
signedAtMs: Int,
nonce: String) -> [String: OpenClawProtocol.AnyCodable]?
{
guard let signature = DeviceIdentityStore.signPayload(payload, identity: identity),
let publicKey = DeviceIdentityStore.publicKeyBase64Url(identity)
else {
return nil
}
return [
"id": OpenClawProtocol.AnyCodable(identity.deviceId),
"publicKey": OpenClawProtocol.AnyCodable(publicKey),
"signature": OpenClawProtocol.AnyCodable(signature),
"signedAt": OpenClawProtocol.AnyCodable(signedAtMs),
"nonce": OpenClawProtocol.AnyCodable(nonce),
]
}
}

View File

@@ -406,15 +406,12 @@ public actor GatewayChannelActor {
nonce: connectNonce,
platform: platform,
deviceFamily: InstanceIdentity.deviceFamily)
if let signature = DeviceIdentityStore.signPayload(payload, identity: identity),
let publicKey = DeviceIdentityStore.publicKeyBase64Url(identity) {
let device: [String: ProtoAnyCodable] = [
"id": ProtoAnyCodable(identity.deviceId),
"publicKey": ProtoAnyCodable(publicKey),
"signature": ProtoAnyCodable(signature),
"signedAt": ProtoAnyCodable(signedAtMs),
"nonce": ProtoAnyCodable(connectNonce),
]
if let device = GatewayDeviceAuthPayload.signedDeviceDictionary(
payload: payload,
identity: identity,
signedAtMs: signedAtMs,
nonce: connectNonce)
{
params["device"] = ProtoAnyCodable(device)
}
}

View File

@@ -53,7 +53,7 @@ public enum LoopbackHost {
return self.isLocalNetworkIPv4(ipv4)
}
private static func parseIPv4(_ host: String) -> (UInt8, UInt8, UInt8, UInt8)? {
static func parseIPv4(_ host: String) -> (UInt8, UInt8, UInt8, UInt8)? {
let parts = host.split(separator: ".", omittingEmptySubsequences: false)
guard parts.count == 4 else { return nil }
let bytes: [UInt8] = parts.compactMap { UInt8($0) }
@@ -61,7 +61,7 @@ public enum LoopbackHost {
return (bytes[0], bytes[1], bytes[2], bytes[3])
}
private static func isLocalNetworkIPv4(_ ip: (UInt8, UInt8, UInt8, UInt8)) -> Bool {
static func isLocalNetworkIPv4(_ ip: (UInt8, UInt8, UInt8, UInt8)) -> Bool {
let (a, b, _, _) = ip
// 10.0.0.0/8
if a == 10 { return true }