| 1 | #if os(macOS) |
| 2 | import SwiftUI |
| 3 | |
| 4 | /// Calls → Settings…. Sections rather than tabs: there are a few things |
| 5 | /// worth choosing, and the next preference belongs beside them. |
| 6 | public struct CallsSettingsView: View { |
| 7 | @ObservedObject private var model: CallsModel |
| 8 | @AppStorage(MiniWindowPreferences.enabledKey) private var miniWindow = |
| 9 | MiniWindowPreferences.defaultEnabled |
| 10 | @AppStorage(MiniWindowPreferences.cornerKey) private var corner = |
| 11 | MiniWindowPreferences.defaultCorner |
| 12 | @AppStorage(MiniWindowPreferences.placementKey) private var placement = |
| 13 | MiniWindowPreferences.defaultPlacement |
| 14 | @AppStorage(MiniWindowPreferences.positionsKey) private var positions: String? |
| 15 | @AppStorage(CallLayoutStyle.key) private var callLayout = CallLayoutStyle.defaultStyle |
| 16 | |
| 17 | public init(model: CallsModel) { self.model = model } |
| 18 | |
| 19 | public var body: some View { |
| 20 | Form { |
| 21 | Section { |
| 22 | Picker(selection: $callLayout) { |
| 23 | ForEach(CallLayoutStyle.allCases) { style in |
| 24 | Text(style.title).tag(style) |
| 25 | } |
| 26 | } label: { |
| 27 | Text("Call layout") |
| 28 | Text( |
| 29 | callLayout == .fullWindow |
| 30 | ? "The call fills the window. Move the pointer over it to show the controls." |
| 31 | : "The call sits above a row of controls that are always showing." |
| 32 | ) |
| 33 | } |
| 34 | .accessibilityIdentifier("callLayout") |
| 35 | Toggle(isOn: $miniWindow) { |
| 36 | Text("Show a mini window when you switch to another app") |
| 37 | Text( |
| 38 | "During a call, a small window of the call stays on top of other apps. The full call returns when you come back to Calls." |
| 39 | ) |
| 40 | } |
| 41 | Picker(selection: $placement) { |
| 42 | ForEach(MiniWindowPlacement.allCases) { placement in |
| 43 | Text(placement.title).tag(placement) |
| 44 | } |
| 45 | } label: { |
| 46 | Text("Mini window placement") |
| 47 | Text(placementNote) |
| 48 | } |
| 49 | .disabled(!miniWindow) |
| 50 | Picker(selection: $corner) { |
| 51 | ForEach(MiniWindowCorner.allCases) { corner in |
| 52 | Text(corner.title).tag(corner) |
| 53 | } |
| 54 | } label: { |
| 55 | Text("Mini window position") |
| 56 | Text( |
| 57 | placement == .corners |
| 58 | ? "You can also drag the mini window to another corner, and resize it from its edges." |
| 59 | : "Where it starts. Choosing a corner here moves it back into that corner." |
| 60 | ) |
| 61 | } |
| 62 | .disabled(!miniWindow) |
| 63 | .onChange(of: corner) { |
| 64 | // A corner chosen here is asked for: whatever position the |
| 65 | // window was left at, on any display, gives way to it. |
| 66 | positions = nil |
| 67 | } |
| 68 | } header: { |
| 69 | Text("During a call") |
| 70 | } |
| 71 | ServerSettingsSection(model: model) |
| 72 | QualityReportsSection() |
| 73 | if let automaticUpdates { |
| 74 | Section { |
| 75 | Toggle(isOn: automaticUpdates) { |
| 76 | Text("Update Calls automatically") |
| 77 | Text( |
| 78 | "Updates download in the background and install when you quit Calls, never during a call." |
| 79 | ) |
| 80 | } |
| 81 | .accessibilityIdentifier("automaticUpdates") |
| 82 | } header: { |
| 83 | Text("Updates") |
| 84 | } |
| 85 | } |
| 86 | } |
| 87 | .formStyle(.grouped) |
| 88 | .frame(width: 480) |
| 89 | .fixedSize(horizontal: false, vertical: true) |
| 90 | .tint(CallsAppearance.accent) |
| 91 | } |
| 92 | |
| 93 | /// Nil where the build cannot update itself: development builds, and iPhone. |
| 94 | private var automaticUpdates: Binding<Bool>? |
| 95 | |
| 96 | /// Adds the automatic-update switch, from the Mac app that owns the updater. |
| 97 | public init(model: CallsModel, automaticUpdates: Binding<Bool>?) { |
| 98 | self.model = model |
| 99 | self.automaticUpdates = automaticUpdates |
| 100 | } |
| 101 | |
| 102 | private var placementNote: String { |
| 103 | switch placement { |
| 104 | case .corners: |
| 105 | "A dragged mini window settles in the nearest corner. Hold ⌥ Option while dragging to leave it exactly where you drop it, for this call." |
| 106 | case .anywhere: |
| 107 | "The mini window stays exactly where you leave it, remembered for each display." |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | #endif |
| 112 | |