Merge branch 'feat/quiet-updates' into main
Merge branch 'feat/quiet-updates' into main
5 files changed,
+44
−7
native/apple/Package.resolved+1 −1native/apple/Package.swift+1 −1native/apple/Sources/CallsKit/CallsSettingsView.swift+22 −0native/apple/Sources/CallsMac/CallsMac.swift+18 −4native/mac-updates.json+2 −1
CI passed — run details
diff --git a/native/apple/Package.resolved b/native/apple/Package.resolved| index 84e1d49..adb9d82 100644 |
| --- a/native/apple/Package.resolved |
| +++ b/native/apple/Package.resolved |
| @@ -5,7 +5,7 @@ |
| "kind" : "remoteSourceControl", |
| "location" : "https://amadan.net/rastrillo/native", |
| "state" : { |
| - "revision" : "2a5d07b2c8d3dfb3fd8526dc7e1c802f97865c67" |
| + "revision" : "b8098cd09c2641467f4dad71057e4a733b610649" |
| } |
| }, |
| { |
diff --git a/native/apple/Package.swift b/native/apple/Package.swift| index d87ec97..d4e64e2 100644 |
| --- a/native/apple/Package.swift |
| +++ b/native/apple/Package.swift |
| @@ -3,7 +3,7 @@ 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: "2a5d07b2c8d3dfb3fd8526dc7e1c802f97865c67") |
| + ?? .package(url: "https://amadan.net/rastrillo/native", revision: "b8098cd09c2641467f4dad71057e4a733b610649") |
| let package = Package( |
| name: "CallsNative", |
diff --git a/native/apple/Sources/CallsKit/CallsSettingsView.swift b/native/apple/Sources/CallsKit/CallsSettingsView.swift| index fa2791e..7eea294 100644 |
| --- a/native/apple/Sources/CallsKit/CallsSettingsView.swift |
| +++ b/native/apple/Sources/CallsKit/CallsSettingsView.swift |
| @@ -55,6 +55,19 @@ |
| Text("During a call") |
| } |
| ServerSettingsSection(model: model) |
| + if let automaticUpdates { |
| + Section { |
| + Toggle(isOn: automaticUpdates) { |
| + Text("Update Calls automatically") |
| + Text( |
| + "Updates download in the background and install when you quit Calls, never during a call." |
| + ) |
| + } |
| + .accessibilityIdentifier("automaticUpdates") |
| + } header: { |
| + Text("Updates") |
| + } |
| + } |
| } |
| .formStyle(.grouped) |
| .frame(width: 480) |
| @@ -62,6 +75,15 @@ |
| .tint(CallsAppearance.accent) |
| } |
| + /// Nil where the build cannot update itself: development builds, and iPhone. |
| + private var automaticUpdates: Binding<Bool>? |
| + |
| + /// Adds the automatic-update switch, from the Mac app that owns the updater. |
| + public init(model: CallsModel, automaticUpdates: Binding<Bool>?) { |
| + self.model = model |
| + self.automaticUpdates = automaticUpdates |
| + } |
| + |
| private var placementNote: String { |
| switch placement { |
| case .corners: |
diff --git a/native/apple/Sources/CallsMac/CallsMac.swift b/native/apple/Sources/CallsMac/CallsMac.swift| index ca5c22d..8360c11 100644 |
| --- a/native/apple/Sources/CallsMac/CallsMac.swift |
| +++ b/native/apple/Sources/CallsMac/CallsMac.swift |
| @@ -9,19 +9,23 @@ import LiveKitWebRTC |
| @main struct CallsMacApp: App { |
| #if os(macOS) |
| - @State private var updater = NativeUpdater() |
| + // Quiet: an update downloads in the background and installs when Calls quits, |
| + // and nothing it finds opens a window. `isBusy` follows the call, so no check |
| + // or download starts during one and the restart waits until it ends. |
| + @State private var updater = NativeUpdater(policy: .quiet) |
| #endif |
| @NSApplicationDelegateAdaptor(CallsAppDelegate.self) private var appDelegate |
| @StateObject private var model = CallsModel() |
| var body: some Scene { |
| Window("Calls", id: "main") { |
| - ContentView(model: model).frame(minWidth: 760, minHeight: 540).onDisappear { model.leave() } |
| + ContentView(model: model, updater: updater).frame(minWidth: 760, minHeight: 540).onDisappear { model.leave() } |
| .onOpenURL { model.openMeetingURL($0) } |
| .onAppear { |
| CallsAppDelegate.model = model |
| model.restore() |
| } |
| .miniWindow(for: model) |
| + .onChange(of: model.joining, initial: true) { updater.isBusy = model.joining } |
| } |
| .defaultSize(width: 1000, height: 760) |
| .commands { |
| @@ -29,7 +33,13 @@ import LiveKitWebRTC |
| NativeUpdateCommands(updater: updater) |
| CommandMenu("Call") { CallMenuItems(model: model) } |
| } |
| - Settings { CallsSettingsView(model: model) } |
| + Settings { |
| + CallsSettingsView( |
| + model: model, |
| + automaticUpdates: updater.canInstallUpdatesAutomatically |
| + ? Binding(get: { updater.automaticallyInstallsUpdates }, set: { updater.automaticallyInstallsUpdates = $0 }) |
| + : nil) |
| + } |
| } |
| } |
| @@ -106,12 +116,16 @@ private struct MuteMenuItem: View { |
| struct ContentView: View { |
| @ObservedObject var model: CallsModel |
| + let updater: NativeUpdater |
| var body: some View { |
| Group { |
| if model.joining { |
| MacCallView(call: model.call, leave: model.leave, rejoin: model.join).padding(24) |
| } else { |
| - CallsLobby(model: model) |
| + // The home screen is the only place an update is mentioned: never the call. |
| + CallsLobby(model: model).safeAreaInset(edge: .bottom) { |
| + if updater.canInstallPendingUpdate { NativeUpdateNotice(updater: updater).padding(.bottom, 12) } |
| + } |
| } |
| }.tint(CallsAppearance.accent) |
| } |
diff --git a/native/mac-updates.json b/native/mac-updates.json| index bad934c..2dbacce 100644 |
| --- a/native/mac-updates.json |
| +++ b/native/mac-updates.json |
| @@ -2,5 +2,6 @@ |
| "bundle_id": "net.amadan.oficina.calls", |
| "feed_url": "https://raw.amadan.net/oficina/native-releases/main/calls/appcast.xml", |
| "public_ed_key": "/FxO7cZnM7P5c9ZrUPUJvpCnR65sNmrzte+I5vHarE8=", |
| - "keychain_account": "oficina" |
| + "keychain_account": "oficina", |
| + "install": "automatic" |
| } |