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
50 changes: 1 addition & 49 deletions Sources/Stag/Views/PreferencesWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,54 +56,6 @@ private struct PreferencesView: View {
@ObservedObject var prefs: Preferences
@State private var selectedTab: SettingsTab = .general

enum SettingsTab: String, CaseIterable {
case general, capture, recording, overlays, shortcuts, advanced

var icon: String {
switch self {
case .general: return "gearshape.fill"
case .capture: return "camera.fill"
case .recording: return "video.fill"
case .overlays: return "square.on.square"
case .shortcuts: return "keyboard.fill"
case .advanced: return "wrench.and.screwdriver.fill"
}
}

var label: String {
switch self {
case .general: return "General"
case .capture: return "Capture"
case .recording: return "Recording"
case .overlays: return "Overlays"
case .shortcuts: return "Shortcuts"
case .advanced: return "Advanced"
}
}

var tint: Color {
switch self {
case .general: return .gray
case .capture: return .blue
case .recording: return .red
case .overlays: return .purple
case .shortcuts: return .orange
case .advanced: return .teal
}
}

var subtitle: String {
switch self {
case .general: return "Output format, saving, and after-capture behavior."
case .capture: return "Timer, preparation, and selection behavior."
case .recording: return "Video quality, audio, and recording overlays."
case .overlays: return "Webcam picture-in-picture and click effects."
case .shortcuts: return "Global hotkeys and editor tool keys."
case .advanced: return "Automation URL scheme and custom upload endpoint."
}
}
}

var body: some View {
HStack(spacing: 0) {
sidebar
Expand Down Expand Up @@ -663,7 +615,7 @@ private struct SidebarItem: View {

/// Scrollable page with a large title header and a centered, width-capped column.
private struct SettingsPage<Content: View>: View {
let tab: PreferencesView.SettingsTab
let tab: SettingsTab
@ViewBuilder var content: Content

var body: some View {
Expand Down
52 changes: 52 additions & 0 deletions Sources/Stag/Views/SettingsTab.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import SwiftUI

/// The panes of the Settings window. Owns each tab's presentation metadata —
/// sidebar icon/tint/label and the page subtitle — lifted out of PreferencesView
/// so the mapping is a plain, testable value type rather than view-private code.
enum SettingsTab: String, CaseIterable {
case general, capture, recording, overlays, shortcuts, advanced

var icon: String {
switch self {
case .general: return "gearshape.fill"
case .capture: return "camera.fill"
case .recording: return "video.fill"
case .overlays: return "square.on.square"
case .shortcuts: return "keyboard.fill"
case .advanced: return "wrench.and.screwdriver.fill"
}
}

var label: String {
switch self {
case .general: return "General"
case .capture: return "Capture"
case .recording: return "Recording"
case .overlays: return "Overlays"
case .shortcuts: return "Shortcuts"
case .advanced: return "Advanced"
}
}

var tint: Color {
switch self {
case .general: return .gray
case .capture: return .blue
case .recording: return .red
case .overlays: return .purple
case .shortcuts: return .orange
case .advanced: return .teal
}
}

var subtitle: String {
switch self {
case .general: return "Output format, saving, and after-capture behavior."
case .capture: return "Timer, preparation, and selection behavior."
case .recording: return "Video quality, audio, and recording overlays."
case .overlays: return "Webcam picture-in-picture and click effects."
case .shortcuts: return "Global hotkeys and editor tool keys."
case .advanced: return "Automation URL scheme and custom upload endpoint."
}
}
}
32 changes: 32 additions & 0 deletions Tests/StagTests/SettingsTabTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import XCTest
@testable import Stag

/// Tab presentation metadata extracted from PreferencesView.
final class SettingsTabTests: XCTestCase {

func testAllSixTabsPresentInOrder() {
XCTAssertEqual(SettingsTab.allCases.map(\.rawValue),
["general", "capture", "recording", "overlays", "shortcuts", "advanced"])
}

func testEveryTabHasNonEmptyMetadata() {
for tab in SettingsTab.allCases {
XCTAssertFalse(tab.icon.isEmpty, "\(tab) icon")
XCTAssertFalse(tab.label.isEmpty, "\(tab) label")
XCTAssertFalse(tab.subtitle.isEmpty, "\(tab) subtitle")
}
}

func testLabelsAndIconsAreUnique() {
let labels = SettingsTab.allCases.map(\.label)
XCTAssertEqual(Set(labels).count, labels.count)
let icons = SettingsTab.allCases.map(\.icon)
XCTAssertEqual(Set(icons).count, icons.count)
}

func testSpotChecks() {
XCTAssertEqual(SettingsTab.general.label, "General")
XCTAssertEqual(SettingsTab.recording.icon, "video.fill")
XCTAssertEqual(SettingsTab.shortcuts.subtitle, "Global hotkeys and editor tool keys.")
}
}
Loading