Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide dialog with connection status #3305

Merged
merged 1 commit into from
Jan 6, 2025
Merged
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
44 changes: 43 additions & 1 deletion appinventor/aicompanionapp/src/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public class ViewController: UINavigationController, UITextFieldDelegate {
@objc public var Height: Int32 = 0
@objc public var Width: Int32 = 0
private static var controller: ViewController?
private var connectProgressDialog: UIAlertController?
private var connectProgressView: UIProgressView?

@objc public func setChildHeight(of component: ViewComponent, height: Int32) {

Expand Down Expand Up @@ -216,6 +218,18 @@ public class ViewController: UINavigationController, UITextFieldDelegate {
RetValManager.shared().usingWebRTC = phoneStatus.WebRTC
form.startHTTPD(false)
form.application?.makeCurrent()
let alertView = UIAlertController(title: "Connecting", message: nil, preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "Cancel", style: .cancel))
present(alertView, animated: true) {
let rect = CGRect(x: 8.0, y: 72.0, width: alertView.view.frame.width - 16.0, height: 2.0)
let progressView = UIProgressView(frame: rect)
self.connectProgressView = progressView
progressView.progress = 0.05
progressView.tintColor = self.view.tintColor
alertView.view.addSubview(progressView)
alertView.message = "Initial Rendezvous"
}
self.connectProgressDialog = alertView
let code = phoneStatus.setHmacSeedReturnCode(text)
NSLog("Seed = \(text)")
NSLog("Code = \(code)")
Expand Down Expand Up @@ -245,9 +259,12 @@ public class ViewController: UINavigationController, UITextFieldDelegate {
return
}
DispatchQueue.main.async {
self.phoneStatus.startWebRTC(kDefaultRendezvousServer, responseContent)
self.connectProgressDialog?.message = "Waiting for remote..."
self.connectProgressView?.progress = 0.15
self.phoneStatus.startWebRTC(kDefaultRendezvousServer, responseContent, self)
}
} else {
self.connectProgressDialog?.dismiss(animated: true)
var responseContent = ""
if let data = data {
guard let responseContentStr = String(data: data, encoding: .utf8) else {
Expand Down Expand Up @@ -404,3 +421,28 @@ extension ViewController: UINavigationControllerDelegate {
return nil
}
}

extension ViewController: WebRTCConnectionDelegate {
public func webRTCDidGetLocalOffer() {
connectProgressView?.progress = 0.4
connectProgressDialog?.message = "Generating routes..."
}

public func webRTCDidGetRemoteOffer() {
connectProgressView?.progress = 0.3
connectProgressDialog?.message = "Sending local answer..."
}

public func webRTCDidGenerateICECandidate() {
guard let progressView = connectProgressView else {
return
}
progressView.progress = min(0.01 + progressView.progress, 0.9)
}

public func webRTCDataChannelOpened() {
connectProgressDialog?.dismiss(animated: true)
connectProgressView = nil
connectProgressDialog = nil
}
}
3 changes: 2 additions & 1 deletion appinventor/components-ios/src/PhoneStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ open class PhoneStatus : NonvisibleComponent {
return false
}

@objc open func startWebRTC(_ rendezvousServer: String, _ iceServers: String) {
@objc open func startWebRTC(_ rendezvousServer: String, _ iceServers: String, _ delegate: WebRTCConnectionDelegate) {
guard WebRTC else {
return
}
guard let firstSeed = self.firstSeed else {
return
}
let manager = WebRTCNativeManager(rendezvousServer, iceServers)
manager.delegate = delegate
manager.initiate(_form as! ReplForm, firstSeed)
}

Expand Down
28 changes: 25 additions & 3 deletions appinventor/components-ios/src/WebRTCNativeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ import WebRTC

public let kDefaultRendezvousServer = "rendezvous.appinventor.mit.edu"

@objc public protocol WebRTCConnectionDelegate {
func webRTCDidGetLocalOffer()
func webRTCDidGetRemoteOffer()
func webRTCDidGenerateICECandidate()
func webRTCDataChannelOpened()
}

struct Offer: Codable {
var sdp: String
var type: String
Expand Down Expand Up @@ -98,6 +105,7 @@ struct WebRTCMessage: Codable {
private var haveOffer = false
private var haveLocalDescription = false
private let constraints: RTCMediaConstraints
public weak var delegate: WebRTCConnectionDelegate? = nil

public init(_ rendezvousServer: String, _ rendezvousResult: String) {
RTCInitializeSSL()
Expand Down Expand Up @@ -190,7 +198,11 @@ struct WebRTCMessage: Codable {
] as [String: Any?]
] as [String : Any]
print("Sending ice candidate = \(response)")
sendRendezvous(data: response)
sendRendezvous(data: response) {
DispatchQueue.main.async {
self.delegate?.webRTCDidGenerateICECandidate()
}
}
}

func peerConnection(_ peerConnection: RTCPeerConnection, didRemove candidates: [RTCIceCandidate]) {
Expand All @@ -201,6 +213,10 @@ struct WebRTCMessage: Codable {
print("opened data channel")
dataChannel.delegate = self
self.dataChannel = dataChannel
DispatchQueue.main.async {
self.delegate?.webRTCDataChannelOpened()
self.delegate = nil
}
keepPolling = false
timer.invalidate()
timer = nil
Expand Down Expand Up @@ -248,6 +264,7 @@ struct WebRTCMessage: Codable {
}
self.haveOffer = true
DispatchQueue.main.async {
self.delegate?.webRTCDidGetRemoteOffer()
print("Have remote offer: \(offer.sdp)")
self.peerConnection.setRemoteDescription(offer.description) { error in
if let error = error {
Expand Down Expand Up @@ -279,7 +296,11 @@ struct WebRTCMessage: Codable {

private func sendAnswer(_ description: RTCSessionDescription) {
haveLocalDescription = true
sendRendezvous(data: ["offer": ["type": "answer", "sdp": description.sdp]])
sendRendezvous(data: ["offer": ["type": "answer", "sdp": description.sdp]]) {
DispatchQueue.main.async {
self.delegate?.webRTCDidGetLocalOffer()
}
}
}

private func processCandidates(candidates: [WebRTCMessage]) {
Expand Down Expand Up @@ -315,7 +336,7 @@ struct WebRTCMessage: Codable {
dataChannel.sendData(RTCDataBuffer(data: data, isBinary: isBinary))
}

private func sendRendezvous(data: [String:Any]) {
private func sendRendezvous(data: [String:Any], completion: (() -> ())? = nil) {
guard let rendezvousServer2 = rendezvousServer2 else {
print("rendezvousServer2 is nil")
return
Expand All @@ -336,6 +357,7 @@ struct WebRTCMessage: Codable {
// pass
if let data = data {
print("sendRendezvous response: \(data)")
completion?()
} else if let error = error {
print("sendRendezvous error: \(error)")
}
Expand Down