diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index c6a5740..1df96a7 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -14,6 +14,21 @@ env: XCODE_VERSION: '26.0' jobs: + lint: + name: Lint + runs-on: macos-26 + timeout-minutes: 5 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install SwiftLint + run: brew install swiftlint + + - name: Run SwiftLint + run: swiftlint lint --reporter github-actions-logging + build: name: Build runs-on: macos-26 diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..42a0248 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,54 @@ +included: + - BetterCapture + - BetterCaptureTests + +excluded: + - BetterCapture.xcodeproj + +opt_in_rules: + - array_init + - closure_spacing + - collection_alignment + - contains_over_filter_count + - empty_collection_literal + - empty_string + - explicit_init + - first_where + - flatmap_over_map_reduce + - identical_operands + - joined_default_parameter + - last_where + - legacy_multiple + - let_var_whitespace + - lower_acl_than_parent + - modifier_order + - operator_usage_whitespace + - overridden_super_call + - prefer_self_type_over_type_of_self + - prohibited_super_call + - redundant_nil_coalescing + - sorted_first_last + - toggle_bool + - trailing_closure + - unneeded_parentheses_in_closure_argument + - weak_delegate + - yoda_condition + +disabled_rules: + - todo + +analyzer_rules: + - unused_import + - unused_declaration + +line_length: + warning: 120 + error: 200 + +type_body_length: + warning: 300 + error: 500 + +file_length: + warning: 500 + error: 800 diff --git a/BetterCapture/View/AreaSelectionOverlay.swift b/BetterCapture/View/AreaSelectionOverlay.swift index f1f304f..96c3b72 100644 --- a/BetterCapture/View/AreaSelectionOverlay.swift +++ b/BetterCapture/View/AreaSelectionOverlay.swift @@ -566,19 +566,19 @@ final class AreaSelectionView: NSView { // MARK: - Handle Calculation private func allHandleRects() -> [ResizeHandle: CGRect] { - let r = selectionRect - let s = handleSize - let half = s / 2 + let rect = selectionRect + let size = handleSize + let half = size / 2 return [ - .topLeft: CGRect(x: r.minX - half, y: r.maxY - half, width: s, height: s), - .top: CGRect(x: r.midX - half, y: r.maxY - half, width: s, height: s), - .topRight: CGRect(x: r.maxX - half, y: r.maxY - half, width: s, height: s), - .left: CGRect(x: r.minX - half, y: r.midY - half, width: s, height: s), - .right: CGRect(x: r.maxX - half, y: r.midY - half, width: s, height: s), - .bottomLeft: CGRect(x: r.minX - half, y: r.minY - half, width: s, height: s), - .bottom: CGRect(x: r.midX - half, y: r.minY - half, width: s, height: s), - .bottomRight: CGRect(x: r.maxX - half, y: r.minY - half, width: s, height: s), + .topLeft: CGRect(x: rect.minX - half, y: rect.maxY - half, width: size, height: size), + .top: CGRect(x: rect.midX - half, y: rect.maxY - half, width: size, height: size), + .topRight: CGRect(x: rect.maxX - half, y: rect.maxY - half, width: size, height: size), + .left: CGRect(x: rect.minX - half, y: rect.midY - half, width: size, height: size), + .right: CGRect(x: rect.maxX - half, y: rect.midY - half, width: size, height: size), + .bottomLeft: CGRect(x: rect.minX - half, y: rect.minY - half, width: size, height: size), + .bottom: CGRect(x: rect.midX - half, y: rect.minY - half, width: size, height: size), + .bottomRight: CGRect(x: rect.maxX - half, y: rect.minY - half, width: size, height: size), ] } diff --git a/BetterCapture/View/MenuBarSettingsView.swift b/BetterCapture/View/MenuBarSettingsView.swift index 241c66d..9460697 100644 --- a/BetterCapture/View/MenuBarSettingsView.swift +++ b/BetterCapture/View/MenuBarSettingsView.swift @@ -82,11 +82,19 @@ struct MenuBarToggle: View { // MARK: - Expandable Picker Row +/// Represents a single option in a `MenuBarExpandablePicker` +struct PickerOption { + let value: Value + let label: String + var isDisabled: Bool = false + var disabledMessage: String? +} + /// A menu bar style picker that expands inline to show options with hover effect struct MenuBarExpandablePicker: View { let name: String @Binding var selection: SelectionValue - let options: [(value: SelectionValue, label: String, isDisabled: Bool, disabledMessage: String?)] + let options: [PickerOption] @State private var isExpanded = false @State private var isHovered = false @@ -98,14 +106,14 @@ struct MenuBarExpandablePicker: View { ) { self.name = name self._selection = selection - self.options = options.map { ($0.value, $0.label, false, nil) } + self.options = options.map { PickerOption(value: $0.value, label: $0.label) } } /// Full initializer with disabled state support init( name: String, selection: Binding, - optionsWithState: [(value: SelectionValue, label: String, isDisabled: Bool, disabledMessage: String?)] + optionsWithState: [PickerOption] ) { self.name = name self._selection = selection @@ -450,7 +458,7 @@ struct VideoSettingsSection: View { selection: $settings.videoCodec, optionsWithState: VideoCodec.allCases.map { codec in let isSupported = settings.containerFormat.supportedVideoCodecs.contains(codec) - return ( + return PickerOption( value: codec, label: codec.rawValue, isDisabled: !isSupported, @@ -517,7 +525,7 @@ struct AudioSettingsSection: View { selection: $settings.audioCodec, optionsWithState: AudioCodec.allCases.map { codec in let isSupported = settings.containerFormat.supportedAudioCodecs.contains(codec) - return ( + return PickerOption( value: codec, label: codec.rawValue, isDisabled: !isSupported,