Restore recent accounts and return from native browser sign-in
Reviewed by GPT-6 Astra. Add saved account switching, app URL handlers, and domain-based Store bundle identifiers. Both Mac and iOS signed build 4 archives and exports verified under Team Tito.
13 files changed,
+308
−73
native/apple/Package.resolved+19 −19native/apple/Package.swift+3 −3native/apple/Sources/MeetKit/Call.swift+8 −0native/apple/Sources/MeetKit/MeetAccountRoot.swift+23 −0native/apple/Sources/MeetKit/MeetLobby.swift+6 −0native/apple/Sources/MeetKit/MeetModel.swift+105 −6native/apple/Sources/MeetMac/MeetMac.swift+11 −1native/ios/Info.plist+35 −0native/ios/Sources/MeetPhone.swift+15 −1native/ios/project.yml+44 −26native/macos/Info.plist+13 −0native/macos/MeetMacStore.xcodeproj/project.pbxproj+4 −2native/macos/project.yml+22 −15
CI passed — run details
diff --git a/native/apple/Package.resolved b/native/apple/Package.resolved| index dfd04e9..616b048 100644 |
| --- a/native/apple/Package.resolved |
| +++ b/native/apple/Package.resolved |
| @@ -1,31 +1,31 @@ |
| { |
| - "pins": [ |
| + "pins" : [ |
| { |
| - "identity": "native", |
| - "kind": "remoteSourceControl", |
| - "location": "https://amadan.net/rastrillo/native", |
| - "state": { |
| - "revision": "4c61d6283a188c95647e1d0e609e69d29c2e7fa1" |
| + "identity" : "native", |
| + "kind" : "remoteSourceControl", |
| + "location" : "https://amadan.net/rastrillo/native", |
| + "state" : { |
| + "revision" : "229525909e1d6ac3b6a353d1c4d022798b0e9a24" |
| } |
| }, |
| { |
| - "identity": "sparkle", |
| - "kind": "remoteSourceControl", |
| - "location": "https://github.com/sparkle-project/Sparkle", |
| - "state": { |
| - "revision": "ac2def288cbff5cfc7df3ffef6abdf45b72bcb0a", |
| - "version": "2.9.6" |
| + "identity" : "sparkle", |
| + "kind" : "remoteSourceControl", |
| + "location" : "https://github.com/sparkle-project/Sparkle", |
| + "state" : { |
| + "revision" : "ac2def288cbff5cfc7df3ffef6abdf45b72bcb0a", |
| + "version" : "2.9.6" |
| } |
| }, |
| { |
| - "identity": "webrtc", |
| - "kind": "remoteSourceControl", |
| - "location": "https://github.com/stasel/WebRTC.git", |
| - "state": { |
| - "revision": "1d04692697cb642bfebf6ad2dd99fe52649c3d6d", |
| - "version": "152.0.0" |
| + "identity" : "webrtc", |
| + "kind" : "remoteSourceControl", |
| + "location" : "https://github.com/stasel/WebRTC.git", |
| + "state" : { |
| + "revision" : "1d04692697cb642bfebf6ad2dd99fe52649c3d6d", |
| + "version" : "152.0.0" |
| } |
| } |
| ], |
| - "version": 2 |
| + "version" : 2 |
| } |
diff --git a/native/apple/Package.swift b/native/apple/Package.swift| index 9328049..c9d2082 100644 |
| --- a/native/apple/Package.swift |
| +++ b/native/apple/Package.swift |
| @@ -2,8 +2,8 @@ |
| import PackageDescription |
| import Foundation |
| -let sharedNative: Package.Dependency = ProcessInfo.processInfo.environment["OFICINA_NATIVE_PACKAGE_PATH"].map { .package(path: $0) } |
| - ?? .package(url: "https://amadan.net/rastrillo/native", revision: "4c61d6283a188c95647e1d0e609e69d29c2e7fa1") |
| +let sharedNative: Package.Dependency = ProcessInfo.processInfo.environment["OFICINA_NATIVE_PACKAGE_PATH"].map { .package(name: "native", path: $0) } |
| + ?? .package(url: "https://amadan.net/rastrillo/native", revision: "229525909e1d6ac3b6a353d1c4d022798b0e9a24") |
| let package = Package( |
| @@ -21,7 +21,7 @@ let package = Package( |
| targets: [ |
| .binaryTarget(name: "MeetBridge", path: "../build/MeetBridge.xcframework"), |
| .target( |
| - name: "MeetKit", dependencies: ["MeetBridge", .product(name: "WebRTC", package: "WebRTC")]), |
| + name: "MeetKit", dependencies: [.product(name: "RastrilloApple", package: "native"), "MeetBridge", .product(name: "WebRTC", package: "WebRTC")]), |
| .executableTarget(name: "MeetMac", dependencies: [.product(name: "RastrilloMacUpdates", package: "native", condition: .when(platforms: [.macOS])), "MeetKit"], resources: [.copy("Resources/AppIcon.png"), .copy("Resources/MacIcon.png")]), |
| .executableTarget(name: "MeetInterop", dependencies: ["MeetKit"]), |
| .testTarget(name: "MeetKitTests", dependencies: ["MeetKit"]), |
diff --git a/native/apple/Sources/MeetKit/Call.swift b/native/apple/Sources/MeetKit/Call.swift| index a1fdfe9..5064464 100644 |
| --- a/native/apple/Sources/MeetKit/Call.swift |
| +++ b/native/apple/Sources/MeetKit/Call.swift |
| @@ -86,6 +86,14 @@ private final class Events: NSObject, BridgeListenerProtocol { |
| localTrack = media.localVideo |
| try client.start() |
| } |
| + public func clearAccount() { |
| + close() |
| + chat = [] |
| + receivedChatCount = 0 |
| + title = "Meet" |
| + standing = "" |
| + status = "Ready to join" |
| + } |
| public func close() { |
| epoch = UUID() |
| let old = bridge |
diff --git a/native/apple/Sources/MeetKit/MeetAccountRoot.swift b/native/apple/Sources/MeetKit/MeetAccountRoot.swift| new file mode 100644 |
| index 0000000..8913007 |
| --- /dev/null |
| +++ b/native/apple/Sources/MeetKit/MeetAccountRoot.swift |
| @@ -0,0 +1,23 @@ |
| +import RastrilloApple |
| +import SwiftUI |
| + |
| +@MainActor public struct MeetAccountRoot<Content: View>: View { |
| + @ObservedObject private var model: MeetModel |
| + @ObservedObject private var connection: NativeConnection |
| + private let content: Content |
| + public init(model: MeetModel, @ViewBuilder content: () -> Content) { |
| + self.model = model |
| + self.connection = model.connection |
| + self.content = content() |
| + } |
| + public var body: some View { |
| + Group { |
| + if connection.client == nil && !model.addingAccount { |
| + NativeAccountsView("Oficina Meet", systemImage: "video", connection: connection, |
| + addAccount: model.addAccount) |
| + } else { |
| + content |
| + } |
| + }.onOpenURL(perform: model.handleOpenURL) |
| + } |
| +} |
diff --git a/native/apple/Sources/MeetKit/MeetLobby.swift b/native/apple/Sources/MeetKit/MeetLobby.swift| index d824e8c..6d98602 100644 |
| --- a/native/apple/Sources/MeetKit/MeetLobby.swift |
| +++ b/native/apple/Sources/MeetKit/MeetLobby.swift |
| @@ -61,6 +61,12 @@ import SwiftUI |
| #endif |
| .onSubmit(model.connect) |
| } |
| + if model.addingAccount { |
| + TextField("Account name (optional)", text: Binding( |
| + get: { model.connection.accountName }, |
| + set: { model.connection.accountName = $0 })) |
| + .textFieldStyle(.roundedBorder) |
| + } |
| Button("Continue", systemImage: "arrow.right", action: model.connect) |
| .buttonStyle(.borderedProminent).keyboardShortcut(.defaultAction) |
| .disabled(model.address.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) |
diff --git a/native/apple/Sources/MeetKit/MeetModel.swift b/native/apple/Sources/MeetKit/MeetModel.swift| index 86af864..e403a4c 100644 |
| --- a/native/apple/Sources/MeetKit/MeetModel.swift |
| +++ b/native/apple/Sources/MeetKit/MeetModel.swift |
| @@ -1,5 +1,6 @@ |
| import Combine |
| import Foundation |
| +import RastrilloApple |
| @preconcurrency import MeetBridge |
| #if os(iOS) |
| @@ -23,9 +24,49 @@ import Foundation |
| @Published public var origin = "" |
| public let call = Call() |
| private var cookies = "" |
| - public init() {} |
| + public let connection = NativeConnection(defaultServer: "https://meet.oficina.works") |
| + @Published public var addingAccount = false |
| + private let browser = NativeBrowserSignIn() |
| + private var accountChanges: AnyCancellable? |
| + public init() { |
| + accountChanges = connection.objectWillChange.sink { [weak self] _ in self?.objectWillChange.send() } |
| + } |
| + public func showAccounts() { |
| + guard !joining else { return } |
| + cancelSignIn() |
| + call.clearAccount() |
| + connection.showAccounts() |
| + signedIn = false |
| + addingAccount = false |
| + address = "" |
| + room = "" |
| + origin = "" |
| + cookies = "" |
| + } |
| + public func signOut() { |
| + guard !joining else { return } |
| + connection.signOut() |
| + showAccounts() |
| + } |
| + public func addAccount() { |
| + showAccounts() |
| + connection.accountName = "" |
| + addingAccount = true |
| + } |
| + public func handleOpenURL(_ url: URL) { |
| + guard let signin, let start = URLComponents(url: signin, resolvingAgainstBaseURL: false), |
| + let id = start.queryItems?.first(where: { $0.name == "id" })?.value, |
| + url.scheme == "works.oficina.meet", url.host == "signin", url.path.isEmpty, |
| + URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems == [URLQueryItem(name: "state", value: id)] else { return } |
| + browser.cancel() |
| + } |
| + |
| public func connect() { |
| + if let client = connection.client, !addingAccount { |
| + connectSavedAccount(client) |
| + return |
| + } |
| cancelSignIn() |
| authenticating = true |
| error = "" |
| @@ -66,6 +107,11 @@ import Foundation |
| guard epoch == authEpoch else { return } |
| let data = Data(result.utf8) |
| let response = try JSONDecoder().decode(SignInResult.self, from: data) |
| + guard response.cookies.count == 1, let approved = response.cookies.first, |
| + let server = URL(string: response.origin) else { throw NativeClientError.message("Invalid sign-in response.") } |
| + try connection.rememberSession(NativeSession(name: approved.name, value: approved.value), origin: server, name: connection.accountName) |
| + addingAccount = false |
| + browser.cancel() |
| cookies = String(data: try JSONEncoder().encode(response.cookies), encoding: .utf8)! |
| origin = response.origin |
| room = response.room |
| @@ -84,14 +130,16 @@ import Foundation |
| } |
| } |
| public func openBrowser(_ url: URL) async -> Bool { |
| - #if os(iOS) |
| - return await UIApplication.shared.open(url) |
| - #else |
| - return NSWorkspace.shared.open(url) |
| - #endif |
| + let epoch = authEpoch |
| + return browser.start(url: url, scheme: "works.oficina.meet") { [weak self] callback in |
| + guard let self, self.authEpoch == epoch else { return } |
| + if let callback { self.handleOpenURL(callback) } else { self.cancelSignIn() } |
| + } |
| } |
| + |
| public func cancelSignIn() { |
| authEpoch = UUID() |
| + browser.cancel() |
| authentication?.cancel() |
| authentication = nil |
| authenticating = false |
| @@ -107,6 +155,57 @@ import Foundation |
| let value: String |
| } |
| } |
| + private func connectSavedAccount(_ client: NativeHTTP) { |
| + cancelSignIn() |
| + let epoch = authEpoch |
| + error = "" |
| + authenticating = true |
| + let link = address.trimmingCharacters(in: .whitespacesAndNewlines) |
| + Task { |
| + do { |
| + guard var components = URLComponents(string: link), components.user == nil, |
| + components.password == nil, components.query == nil, components.fragment == nil else { |
| + throw NativeClientError.message("Enter a full meeting or invitation link.") |
| + } |
| + var target = components.path |
| + components.path = "" |
| + guard components.url == client.origin else { |
| + throw NativeClientError.message("Choose an account for this meeting’s server.") |
| + } |
| + if target.hasSuffix("/join") { target = String(target.dropLast(5)) } |
| + func roomID(_ path: String, prefix: String) -> String? { |
| + guard path.hasPrefix(prefix) else { return nil } |
| + let id = String(path.dropFirst(prefix.count)) |
| + guard !id.isEmpty, id.count <= 128, |
| + id.utf8.allSatisfy({ (65...90).contains($0) || (97...122).contains($0) || (48...57).contains($0) || $0 == 45 || $0 == 95 }) else { return nil } |
| + return id |
| + } |
| + if roomID(target, prefix: "/j/") != nil { |
| + let result = try await client.responseDetails(target) |
| + guard result.status == 303, let location = result.headers["Location"] ?? result.headers["location"], |
| + let redirected = URL(string: location), redirected.scheme == nil, redirected.host == nil, |
| + redirected.query == nil, redirected.fragment == nil, redirected.path.hasSuffix("/join") else { |
| + throw NativeClientError.message("This invitation is unavailable. Sign in again if your session has expired.") |
| + } |
| + target = String(redirected.path.dropLast(5)) |
| + } |
| + guard let room = roomID(target, prefix: "/m/"), let credential = client.credential else { |
| + throw NativeClientError.message("Enter a full meeting or invitation link.") |
| + } |
| + guard self.authEpoch == epoch else { return } |
| + self.cookies = String(decoding: try JSONEncoder().encode([credential]), as: UTF8.self) |
| + self.room = room |
| + self.origin = client.origin.absoluteString |
| + self.signedIn = true |
| + self.authenticating = false |
| + } catch { |
| + guard self.authEpoch == epoch else { return } |
| + self.error = error.localizedDescription |
| + self.authenticating = false |
| + } |
| + } |
| + } |
| + |
| public func join() { |
| callEpoch = UUID() |
| let operation = callEpoch |
diff --git a/native/apple/Sources/MeetMac/MeetMac.swift b/native/apple/Sources/MeetMac/MeetMac.swift| index c76862a..673f580 100644 |
| --- a/native/apple/Sources/MeetMac/MeetMac.swift |
| +++ b/native/apple/Sources/MeetMac/MeetMac.swift |
| @@ -15,7 +15,17 @@ import WebRTC |
| @StateObject private var model = MeetModel() |
| var body: some Scene { |
| Window("Meet", id: "main") { |
| - ContentView(model: model).frame(minWidth: 760, minHeight: 540).onDisappear { model.leave() } |
| + MeetAccountRoot(model: model) { |
| + NavigationStack { |
| + ContentView(model: model) |
| + .toolbar { |
| + if !model.joining { |
| + ToolbarItem(placement: .navigation) { Button("Accounts", systemImage: "chevron.backward", action: model.showAccounts) } |
| + ToolbarItem { Button("Sign out", action: model.signOut).disabled(model.connection.client == nil) } |
| + } |
| + } |
| + } |
| + }.frame(minWidth: 760, minHeight: 540).onDisappear { model.leave() } |
| } |
| .defaultSize(width: 1000, height: 760) |
| .commands { |
diff --git a/native/ios/Info.plist b/native/ios/Info.plist| new file mode 100644 |
| index 0000000..8d035b4 |
| --- /dev/null |
| +++ b/native/ios/Info.plist |
| @@ -0,0 +1,35 @@ |
| +<?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>CFBundleDevelopmentRegion</key> |
| + <string>$(DEVELOPMENT_LANGUAGE)</string> |
| + <key>CFBundleExecutable</key> |
| + <string>$(EXECUTABLE_NAME)</string> |
| + <key>CFBundleIdentifier</key> |
| + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
| + <key>CFBundleInfoDictionaryVersion</key> |
| + <string>6.0</string> |
| + <key>CFBundleName</key> |
| + <string>$(PRODUCT_NAME)</string> |
| + <key>CFBundlePackageType</key> |
| + <string>APPL</string> |
| + <key>CFBundleShortVersionString</key> |
| + <string>$(MARKETING_VERSION)</string> |
| + <key>CFBundleURLTypes</key> |
| + <array> |
| + <dict> |
| + <key>CFBundleTypeRole</key> |
| + <string>Editor</string> |
| + <key>CFBundleURLName</key> |
| + <string>works.oficina.meet.signin</string> |
| + <key>CFBundleURLSchemes</key> |
| + <array> |
| + <string>works.oficina.meet</string> |
| + </array> |
| + </dict> |
| + </array> |
| + <key>CFBundleVersion</key> |
| + <string>$(CURRENT_PROJECT_VERSION)</string> |
| +</dict> |
| +</plist> |
diff --git a/native/ios/Sources/MeetPhone.swift b/native/ios/Sources/MeetPhone.swift| index adf6cdb..b30e551 100644 |
| --- a/native/ios/Sources/MeetPhone.swift |
| +++ b/native/ios/Sources/MeetPhone.swift |
| @@ -7,7 +7,7 @@ import WebRTC |
| @Environment(\.scenePhase) private var scenePhase |
| var body: some Scene { |
| WindowGroup { |
| - PhoneHome(model: model) |
| + MeetAccountRoot(model: model) { PhoneHome(model: model) } |
| .onChange(of: scenePhase) { _, phase in |
| // This milestone is foreground-only. Browser sign-in is kept alive; |
| // an active call leaves cleanly instead of silently sending audio. |
| @@ -32,6 +32,20 @@ struct PhoneHome: View { |
| MeetLobby(model: model) |
| } |
| }.tint(MeetAppearance.accent).navigationTitle("Meet").navigationBarTitleDisplayMode(.inline) |
| + .toolbar { |
| + if !model.joining { |
| + ToolbarItem(placement: .topBarLeading) { |
| + Button("Accounts", systemImage: "chevron.backward", action: model.showAccounts) |
| + } |
| + ToolbarItem(placement: .topBarTrailing) { |
| + if model.connection.client != nil { |
| + Menu("More", systemImage: "ellipsis") { |
| + Button("Sign out", role: .destructive, action: model.signOut) |
| + } |
| + } |
| + } |
| + } |
| + } |
| } |
| } |
| } |
diff --git a/native/ios/project.yml b/native/ios/project.yml| index b3d8629..271439b 100644 |
| --- a/native/ios/project.yml |
| +++ b/native/ios/project.yml |
| @@ -10,55 +10,71 @@ settings: |
| base: |
| SWIFT_VERSION: '5.0' |
| CODE_SIGN_STYLE: Automatic |
| - MARKETING_VERSION: '0.2.0' |
| + MARKETING_VERSION: 0.2.0 |
| CURRENT_PROJECT_VERSION: '1' |
| targets: |
| MeetPhone: |
| type: application |
| platform: iOS |
| sources: |
| - - Sources |
| - - Assets.xcassets |
| - - path: ../LICENSE.lucide |
| - buildPhase: resources |
| - - path: ../PrivacyInfo.xcprivacy |
| - buildPhase: resources |
| + - Sources |
| + - Assets.xcassets |
| + - path: ../LICENSE.lucide |
| + buildPhase: resources |
| + - path: ../PrivacyInfo.xcprivacy |
| + buildPhase: resources |
| dependencies: |
| - - package: MeetNative |
| - product: MeetKit |
| + - package: MeetNative |
| + product: MeetKit |
| settings: |
| base: |
| ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon |
| - PRODUCT_BUNDLE_IDENTIFIER: net.amadan.oficina.meet.ios |
| - TARGETED_DEVICE_FAMILY: '1,2' |
| - GENERATE_INFOPLIST_FILE: YES |
| + PROVISIONING_PROFILE_SPECIFIER: $(OFICINA_PROVISIONING_PROFILE) |
| + PRODUCT_BUNDLE_IDENTIFIER: works.oficina.meet |
| + TARGETED_DEVICE_FAMILY: 1,2 |
| + GENERATE_INFOPLIST_FILE: true |
| INFOPLIST_KEY_CFBundleDisplayName: Meet |
| - INFOPLIST_KEY_NSCameraUsageDescription: Meet uses your camera so people in your meeting can see you. |
| - INFOPLIST_KEY_NSMicrophoneUsageDescription: Meet uses your microphone so people in your meeting can hear you. |
| - INFOPLIST_KEY_UILaunchScreen_Generation: YES |
| - INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown |
| + INFOPLIST_KEY_NSCameraUsageDescription: Meet uses your camera so people in |
| + your meeting can see you. |
| + INFOPLIST_KEY_NSMicrophoneUsageDescription: Meet uses your microphone so people |
| + in your meeting can hear you. |
| + INFOPLIST_KEY_UILaunchScreen_Generation: true |
| + INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait |
| + UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight |
| + UIInterfaceOrientationPortraitUpsideDown |
| + info: |
| + path: Info.plist |
| + properties: |
| + CFBundleURLTypes: |
| + - CFBundleURLName: works.oficina.meet.signin |
| + CFBundleURLSchemes: |
| + - works.oficina.meet |
| + CFBundleTypeRole: Editor |
| + CFBundleShortVersionString: $(MARKETING_VERSION) |
| + CFBundleVersion: $(CURRENT_PROJECT_VERSION) |
| MeetPhoneTests: |
| type: bundle.unit-test |
| platform: iOS |
| sources: |
| - - Tests |
| - - ../apple/Sources/MeetInterop/SyntheticVideo.swift |
| + - Tests |
| + - ../apple/Sources/MeetInterop/SyntheticVideo.swift |
| dependencies: |
| - - target: MeetPhone |
| - - package: MeetNative |
| - product: MeetKit |
| + - target: MeetPhone |
| + - package: MeetNative |
| + product: MeetKit |
| settings: |
| base: |
| - GENERATE_INFOPLIST_FILE: YES |
| + GENERATE_INFOPLIST_FILE: true |
| MeetPhoneUITests: |
| type: bundle.ui-testing |
| platform: iOS |
| - sources: [UITests] |
| + sources: |
| + - UITests |
| dependencies: |
| - - target: MeetPhone |
| + - target: MeetPhone |
| settings: |
| base: |
| - GENERATE_INFOPLIST_FILE: YES |
| + GENERATE_INFOPLIST_FILE: true |
| TEST_TARGET_NAME: MeetPhone |
| info: |
| path: ../build/ios-test-info.plist |
| @@ -71,4 +87,6 @@ schemes: |
| targets: |
| MeetPhone: all |
| test: |
| - targets: [MeetPhoneUITests, MeetPhoneTests] |
| + targets: |
| + - MeetPhoneUITests |
| + - MeetPhoneTests |
diff --git a/native/macos/Info.plist b/native/macos/Info.plist| index 9a21cb5..3a2bb38 100644 |
| --- a/native/macos/Info.plist |
| +++ b/native/macos/Info.plist |
| @@ -20,6 +20,19 @@ |
| <string>APPL</string> |
| <key>CFBundleShortVersionString</key> |
| <string>$(MARKETING_VERSION)</string> |
| + <key>CFBundleURLTypes</key> |
| + <array> |
| + <dict> |
| + <key>CFBundleTypeRole</key> |
| + <string>Editor</string> |
| + <key>CFBundleURLName</key> |
| + <string>works.oficina.meet.signin</string> |
| + <key>CFBundleURLSchemes</key> |
| + <array> |
| + <string>works.oficina.meet</string> |
| + </array> |
| + </dict> |
| + </array> |
| <key>CFBundleVersion</key> |
| <string>$(CURRENT_PROJECT_VERSION)</string> |
| <key>LSApplicationCategoryType</key> |
diff --git a/native/macos/MeetMacStore.xcodeproj/project.pbxproj b/native/macos/MeetMacStore.xcodeproj/project.pbxproj| index e1788bc..41f21c2 100644 |
| --- a/native/macos/MeetMacStore.xcodeproj/project.pbxproj |
| +++ b/native/macos/MeetMacStore.xcodeproj/project.pbxproj |
| @@ -196,7 +196,8 @@ |
| "$(inherited)", |
| "@executable_path/../Frameworks", |
| ); |
| - PRODUCT_BUNDLE_IDENTIFIER = net.amadan.oficina.meet; |
| + PRODUCT_BUNDLE_IDENTIFIER = works.oficina.meet; |
| + PROVISIONING_PROFILE_SPECIFIER = "$(OFICINA_PROVISIONING_PROFILE)"; |
| SDKROOT = macosx; |
| }; |
| name = Release; |
| @@ -339,7 +340,8 @@ |
| "$(inherited)", |
| "@executable_path/../Frameworks", |
| ); |
| - PRODUCT_BUNDLE_IDENTIFIER = net.amadan.oficina.meet; |
| + PRODUCT_BUNDLE_IDENTIFIER = works.oficina.meet; |
| + PROVISIONING_PROFILE_SPECIFIER = "$(OFICINA_PROVISIONING_PROFILE)"; |
| SDKROOT = macosx; |
| }; |
| name = Debug; |
diff --git a/native/macos/project.yml b/native/macos/project.yml| index 30444fc..f231f7c 100644 |
| --- a/native/macos/project.yml |
| +++ b/native/macos/project.yml |
| @@ -12,26 +12,26 @@ settings: |
| base: |
| SWIFT_VERSION: '5.0' |
| CODE_SIGN_STYLE: Automatic |
| - MARKETING_VERSION: '0.1.0' |
| + MARKETING_VERSION: 0.1.0 |
| CURRENT_PROJECT_VERSION: '3' |
| - ENABLE_HARDENED_RUNTIME: YES |
| + ENABLE_HARDENED_RUNTIME: true |
| targets: |
| MeetMacStore: |
| type: application |
| platform: macOS |
| sources: |
| - - ../apple/Sources/MeetMac |
| - - path: AppIcon.icns |
| - buildPhase: resources |
| - - path: ../LICENSE.lucide |
| - buildPhase: resources |
| - - path: ../PrivacyInfo.xcprivacy |
| - buildPhase: resources |
| + - ../apple/Sources/MeetMac |
| + - path: AppIcon.icns |
| + buildPhase: resources |
| + - path: ../LICENSE.lucide |
| + buildPhase: resources |
| + - path: ../PrivacyInfo.xcprivacy |
| + buildPhase: resources |
| dependencies: |
| - - package: MeetNative |
| - product: MeetKit |
| - - package: WebRTC |
| - product: WebRTC |
| + - package: MeetNative |
| + product: MeetKit |
| + - package: WebRTC |
| + product: WebRTC |
| info: |
| path: Info.plist |
| properties: |
| @@ -43,8 +43,15 @@ targets: |
| LSApplicationCategoryType: public.app-category.productivity |
| NSHighResolutionCapable: true |
| NSCameraUsageDescription: Meet uses your camera to share video in a meeting. |
| - NSMicrophoneUsageDescription: Meet uses your microphone so people in the meeting can hear you. |
| + NSMicrophoneUsageDescription: Meet uses your microphone so people in the meeting |
| + can hear you. |
| + CFBundleURLTypes: |
| + - CFBundleURLName: works.oficina.meet.signin |
| + CFBundleURLSchemes: |
| + - works.oficina.meet |
| + CFBundleTypeRole: Editor |
| settings: |
| base: |
| - PRODUCT_BUNDLE_IDENTIFIER: net.amadan.oficina.meet |
| + PROVISIONING_PROFILE_SPECIFIER: $(OFICINA_PROVISIONING_PROFILE) |
| + PRODUCT_BUNDLE_IDENTIFIER: works.oficina.meet |
| CODE_SIGN_ENTITLEMENTS: AppStore.entitlements |