Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions BetterCapture/Model/SettingsStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,26 @@ enum VideoCodec: String, CaseIterable, Identifiable {
return false
}
}

/// Whether alpha channel is always enabled (cannot be disabled)
var alwaysHasAlpha: Bool {
switch self {
case .proRes4444:
return true
case .hevc, .h264, .proRes422:
return false
}
}

/// Whether alpha channel can be toggled by the user
var canToggleAlpha: Bool {
switch self {
case .hevc:
return true
case .h264, .proRes422, .proRes4444:
return false
}
}
}

/// Container format for output files
Expand Down Expand Up @@ -86,10 +106,15 @@ final class SettingsStore {
}
set {
videoCodecRaw = newValue.rawValue
// Reset alpha channel setting if the new codec doesn't support it
if !newValue.supportsAlphaChannel {
// Set alpha channel based on codec capabilities
if newValue.alwaysHasAlpha {
// ProRes 4444 always has alpha
captureAlphaChannel = true
} else if !newValue.supportsAlphaChannel {
// H.264 and ProRes 422 never have alpha
captureAlphaChannel = false
}
// HEVC can toggle alpha, so leave it as-is
}
}

Expand Down
16 changes: 10 additions & 6 deletions BetterCapture/View/MenuBarSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,27 @@ struct MenuBarDivider: View {
struct MenuBarToggle: View {
let name: String
@Binding var isOn: Bool
var isDisabled: Bool = false
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isDisabled is view input state and doesn’t appear to be mutated; prefer let isDisabled: Bool = false to better communicate immutability and avoid accidental mutation in a value-type View.

Suggested change
var isDisabled: Bool = false
let isDisabled: Bool = false

Copilot uses AI. Check for mistakes.
@State private var isHovered = false

var body: some View {
HStack {
Text(name)
.font(.system(size: 13, weight: .medium))
.foregroundStyle(.primary)
.foregroundStyle(isDisabled ? .secondary : .primary)
Spacer()
Toggle("", isOn: $isOn)
.toggleStyle(.switch)
.tint(.blue)
.scaleEffect(0.8)
.disabled(isDisabled)
Comment on lines 59 to +67
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Toggle has an empty label (\"\"), which can lead to an unlabeled control for VoiceOver. Consider giving the toggle an accessibility label (e.g., .accessibilityLabel(Text(name))) or restructuring to use Toggle(isOn:) { Text(name) } and then style/layout accordingly.

Copilot uses AI. Check for mistakes.
}
.padding(.horizontal, 12)
.padding(.vertical, 4)
.contentShape(.rect)
.background(
RoundedRectangle(cornerRadius: 4)
.fill(isHovered ? .gray.opacity(0.1) : .clear)
.fill(isHovered && !isDisabled ? .gray.opacity(0.1) : .clear)
.padding(.horizontal, 4)
)
.onHover { hovering in
Expand Down Expand Up @@ -421,10 +423,12 @@ struct VideoSettingsSection: View {
options: ContainerFormat.allCases.map { ($0, $0.rawValue.uppercased()) }
)

// Alpha Channel Toggle (only for supported codecs)
if settings.videoCodec.supportsAlphaChannel {
MenuBarToggle(name: "Capture Alpha Channel", isOn: $settings.captureAlphaChannel)
}
// Alpha Channel Toggle (always visible, but disabled for non-toggleable codecs)
MenuBarToggle(
name: "Capture Alpha Channel",
isOn: $settings.captureAlphaChannel,
isDisabled: !settings.videoCodec.canToggleAlpha
)
}
}
}
Expand Down
20 changes: 15 additions & 5 deletions BetterCapture/View/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ struct SettingsView: View {
struct VideoSettingsView: View {
@Bindable var settings: SettingsStore

private var alphaChannelHelpText: String {
switch settings.videoCodec {
case .proRes4444:
return "ProRes 4444 always includes alpha channel support"
case .hevc:
return "Enable transparency support for HEVC"
case .h264, .proRes422:
return "Alpha channel not supported by this codec"
Comment on lines +40 to +44
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor grammar tweaks would make these help strings read more naturally (e.g., add an article and/or verb): "ProRes 4444 always includes an alpha channel" and "Alpha channel is not supported by this codec."

Suggested change
return "ProRes 4444 always includes alpha channel support"
case .hevc:
return "Enable transparency support for HEVC"
case .h264, .proRes422:
return "Alpha channel not supported by this codec"
return "ProRes 4444 always includes an alpha channel."
case .hevc:
return "Enable transparency support for HEVC."
case .h264, .proRes422:
return "The alpha channel is not supported by this codec."

Copilot uses AI. Check for mistakes.
}
}

var body: some View {
Form {
Section("Recording") {
Expand All @@ -56,11 +67,10 @@ struct VideoSettingsView: View {
}
}

if settings.videoCodec.supportsAlphaChannel {
Section("Advanced") {
Toggle("Capture Alpha Channel", isOn: $settings.captureAlphaChannel)
.help("Enable transparency support (requires HEVC or ProRes 4444)")
}
Section("Advanced") {
Toggle("Capture Alpha Channel", isOn: $settings.captureAlphaChannel)
.disabled(!settings.videoCodec.canToggleAlpha)
.help(alphaChannelHelpText)
}
}
.formStyle(.grouped)
Expand Down