Files
praca_inzynierska/Implementation/Peered/NoteEditor/NoteEditingSessionServer.swift
T

124 lines
2.8 KiB
Swift

import MultipeerConnectivity
import Foundation
import Combine
struct OwnPeer {
let peer: MCPeerID
static var fallback: Self { Self(peer: .init(displayName: "fallback_user")) }
}
struct Peer: Identifiable {
enum ConnectionState {
case available
case joined
case rejected
case invitationPending
}
var id: String { mcPeer.displayName }
let mcPeer: MCPeerID
var state: ConnectionState
}
@Observable
final class NoteEditingSessionServer: NSObject {
private let session: MCSession
private let browser: MCNearbyServiceBrowser
private let ownPeer: OwnPeer
var visiblePeers: [Peer] = []
let noteChangesEmitter = PassthroughSubject<String, Never>()
init(peer: OwnPeer) {
ownPeer = peer
browser = .init(peer: peer.peer, serviceType: "peered")
session = .init(peer: peer.peer)
super.init()
browser.delegate = self
session.delegate = self
}
func startServer() {
browser.startBrowsingForPeers()
}
func stopServer() {
browser.stopBrowsingForPeers()
session.disconnect()
}
func invite(peer: Peer, to note: NoteInvitation.NoteContent) {
guard peer.state == .available else { return }
browser.invitePeer(
peer.mcPeer,
to: session,
withContext: try! JSONEncoder().encode(note),
timeout: 5
)
let idxToUpdate = visiblePeers.firstIndex(where: { $0.mcPeer == peer.mcPeer })!
visiblePeers[idxToUpdate].state = .invitationPending
}
}
extension NoteEditingSessionServer: MCNearbyServiceBrowserDelegate {
func browser(
_ browser: MCNearbyServiceBrowser,
foundPeer peerID: MCPeerID,
withDiscoveryInfo info: [String : String]?
) {
guard !visiblePeers.contains(where: { $0.mcPeer == peerID }) && peerID.displayName != ownPeer.peer.displayName else { return }
let newPeer = Peer(mcPeer: peerID, state: .available)
visiblePeers.append(newPeer)
}
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
guard let peerIdx = visiblePeers.firstIndex(where: { $0.mcPeer == peerID }) else { return }
visiblePeers.remove(at: peerIdx)
}
}
extension NoteEditingSessionServer: MCSessionDelegate {
func session(
_ session: MCSession,
peer peerID: MCPeerID,
didChange state: MCSessionState
) {
}
func session(
_ session: MCSession,
didReceive stream: InputStream,
withName streamName: String,
fromPeer peerID: MCPeerID
) {
}
func session(
_ session: MCSession,
didStartReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID,
with progress: Progress
) {
}
func session(
_ session: MCSession,
didFinishReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID,
at localURL: URL?,
withError error: (any Error)?
) {
}
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
guard let note = String(data: data, encoding: .utf8) else { fatalError() }
noteChangesEmitter.send(note)
}
}