Skip to content

Modernize codebase: Swift 6, tests, and cleanup#137

Merged
karbassi merged 22 commits intomichaelvillar:masterfrom
karbassi:fix/deployment-target-and-occlusion
Feb 7, 2026
Merged

Modernize codebase: Swift 6, tests, and cleanup#137
karbassi merged 22 commits intomichaelvillar:masterfrom
karbassi:fix/deployment-target-and-occlusion

Conversation

@karbassi
Copy link
Collaborator

@karbassi karbassi commented Feb 7, 2026

Summary

  • Upgrade to Swift 6 with async/await concurrency
  • Raise deployment target to macOS 14
  • Add 43 unit tests and 38 UI tests
  • Add dark mode and VoiceOver accessibility
  • Expand SwiftLint opt-in rules from 6 to 73
  • General cleanup: cache allocations, extract logic, split large files, remove dead code

Issues

Test plan

  • make build — clean build, 0 errors
  • make lint — 0 SwiftLint violations
  • make test — 43 unit tests pass
  • make uitest — 38 UI tests pass

- Raise MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.13 (Xcode minimum)
- Use occlusionState instead of isVisible in handleOcclusionChange
- Remove redundant #available(OSX 10.13, *) check
- Update MACOSX_DEPLOYMENT_TARGET from 10.13 to 14.0
- Remove redundant #available(OSX 10.14, *) check in isDarkMode
Save selected sound index on change and restore it on launch.
Menu checkmark state also reflects the saved preference.
…nto TimerLogic

Move progress scale conversion, display string formatting, badge
formatting, keyboard input processing, and sound filename mapping
into a new TimerLogic enum with static functions. This makes the
core logic unit-testable without requiring UI instantiation.
- Remove blank line after opening brace in TimerLogic and TimerTests
- Sort imports in TimerTests (@testable before XCTest)
- Replace arc4random_uniform with Int.random(in:) in MVTimerController
- Fix comment spacing in MVTimerController
- Remove superfluous swiftlint:disable for unused_setter_value in MVMainView
- Move explicit_self and unused_import to analyzer_rules in config
- Remove defunct anyobject_protocol rule from config
- Replace `import Cocoa` with `import AppKit` in all view/controller files
- Add explicit `self.` prefix to instance members per `explicit_self` analyzer rule
- Update CI workflow to trigger on main branch instead of master
- Update README deployment target from macOS 10.11 to macOS 14 (Sonoma)
- Use async/await for notification authorization, log errors
- Extract NSGradient to static constant in MVMainView (allocated every draw call)
- Cache NSBezierPath for clock face hit testing in MVClockView (allocated every hitTest)
- Cache NSImage resources as static constants in MVClockProgressView and MVClockFaceView
- Remove unnecessary window focus notification observers from MVMainView
- Scope MVClockView focus notifications to own window via viewDidMoveToWindow
- Add VoiceOver accessibility to MVClockView (timer state announcements)
NSTextView is a heavyweight rich text editor with text storage, layout manager,
and input handling. NSTextField with isEditable=false is far lighter for
read-only labels. Adds string/setFont bridge properties for API compatibility.
- Set CURRENT_PROJECT_VERSION = 1 (CFBundleVersion was empty)
- Update objectVersion 46 → 56, compatibilityVersion to Xcode 14.0
- Update developmentRegion English → en, deduplicate knownRegions
- Update LastSwiftUpdateCheck/LastUpgradeCheck to 1600
- Update GCC_C_LANGUAGE_STANDARD gnu99 → gnu11
- Update CLANG_CXX_LANGUAGE_STANDARD gnu++0x → gnu++14
- Remove deprecated ALWAYS_SEARCH_USER_PATHS, GCC_DYNAMIC_NO_PIC, ENABLE_STRICT_OBJC_MSGSEND
- Add explicit SWIFT_OPTIMIZATION_LEVEL = -O for Release
- Add 5 asset catalog color sets with light/dark variants for timer colors
- Replace inline NSColor(srgbRed:...) with NSColor(resource:) for compile-time safety
- Add VoiceOver accessibility to MVClockArrowView (slider role with duration value)
Add @mainactor to AppDelegate, replace Foundation.Timer with
Task.sleep, and convert NotificationCenter observers to async
sequences — eliminating all MainActor.assumeIsolated workarounds
in callbacks.
…t config

- Split MVClockView.swift into MVClockView.swift + MVClockView+Behavior.swift
  to comply with default file_length threshold
- Split TimerUITests.swift into 7 focused test files with shared base class
  to comply with default file_length and type_body_length thresholds
- Replace virtual keycode constants with event.charactersIgnoringModifiers,
  eliminating Keycodes.swift entirely (also improves international keyboard support)
- Remove SwiftLint excluded section and disabled_rules
- Enable number_separator opt-in rule
- Extract AppDelegate notification observers into observeNotifications()
Extract shared accessibility time formatting to TimerLogic, make
minutes/progress computed properties, replace currentImage with state
enum, inline applySoundIndex, remove soundMenuItems stored array,
remove docktile/timerTimeLabelFontSize properties, rename unused
parameters, replace && with condition lists, and fix superfluous else.
@karbassi karbassi force-pushed the fix/deployment-target-and-occlusion branch from 5db3244 to d1b7d16 Compare February 7, 2026 07:52
@karbassi karbassi merged commit 1359570 into michaelvillar:master Feb 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Keep the last sound alert in memory Play/pause issues on Big Sur Drop support for anything before macOS 10.13 Add option to disable timer sound

1 participant