Create repo, add feature to set username
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "tinted"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// CommunicationProvider.swift
|
||||
// Peered
|
||||
//
|
||||
// Created by Oskar Chybowski on 11/05/2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MultipeerConnectivity
|
||||
|
||||
@Observable
|
||||
final class CommunicationProvider: NSObject, MCNearbyServiceBrowserDelegate {
|
||||
private let session: MCSession
|
||||
private let browser: MCNearbyServiceBrowser
|
||||
private let advertiser: MCNearbyServiceAdvertiser
|
||||
|
||||
private(set) var availablePeers: [MCPeerID] = []
|
||||
|
||||
init(id: String) {
|
||||
let id = MCPeerID(displayName: id)
|
||||
session = MCSession(peer: id, securityIdentity: nil, encryptionPreference: .required)
|
||||
browser = MCNearbyServiceBrowser(peer: id, serviceType: "peered")
|
||||
advertiser = MCNearbyServiceAdvertiser(
|
||||
peer: browser.myPeerID,
|
||||
discoveryInfo: [:],
|
||||
serviceType: "peered"
|
||||
)
|
||||
super.init()
|
||||
browser.delegate = self
|
||||
start()
|
||||
}
|
||||
|
||||
func start() {
|
||||
advertiser.startAdvertisingPeer()
|
||||
browser.startBrowsingForPeers()
|
||||
}
|
||||
|
||||
func stop() {
|
||||
browser.stopBrowsingForPeers()
|
||||
advertiser.stopAdvertisingPeer()
|
||||
}
|
||||
|
||||
func browser(
|
||||
_ browser: MCNearbyServiceBrowser,
|
||||
foundPeer peerID: MCPeerID,
|
||||
withDiscoveryInfo info: [String: String]?
|
||||
) {
|
||||
availablePeers.append(peerID)
|
||||
browser.invitePeer(peerID, to: session, withContext: nil, timeout: 30)
|
||||
}
|
||||
|
||||
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
|
||||
availablePeers.removeAll { id in
|
||||
id == peerID
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// Peered
|
||||
//
|
||||
// Created by Oskar Chybowski on 11/05/2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@AppStorage("peered_username") private var username: String = ""
|
||||
@State var browser: CommunicationProvider? = nil
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
if let browser {
|
||||
ForEach(browser.availablePeers, id: \.displayName) { peer in
|
||||
Text(peer.displayName)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.sheet(isPresented: .constant(username.isEmpty)) {
|
||||
SetUserNameBottomSheetView(username: $username)
|
||||
}
|
||||
.onChange(of: username) { _, newValue in
|
||||
guard !newValue.isEmpty else { return }
|
||||
browser = .init(id: newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSBonjourServices</key>
|
||||
<array>
|
||||
<string>_peered._tcp</string>
|
||||
</array>
|
||||
<key>NSServices</key>
|
||||
<array>
|
||||
<dict/>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// PeeredApp.swift
|
||||
// Peered
|
||||
//
|
||||
// Created by Oskar Chybowski on 11/05/2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct PeeredApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SetUserNameBottomSheetView: View {
|
||||
@State private var proposedUsername: String = ""
|
||||
@Binding var username: String
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section("Set your username") {
|
||||
TextField("Username", text: $proposedUsername)
|
||||
}
|
||||
|
||||
Button("Save username") {
|
||||
username = proposedUsername
|
||||
}
|
||||
}
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user