mirror of
https://github.com/pawelorzech/MacTorn.git
synced 2026-03-31 20:25:43 +00:00
Create wiki/ directory with 11 markdown pages covering: - Home, Installation, Getting Started guides - Features documentation for all tabs - API Setup with permissions and security - Configuration options and settings - Troubleshooting and FAQ - Development guide with architecture overview - Changelog with version history - Sidebar navigation
250 lines
5.7 KiB
Markdown
250 lines
5.7 KiB
Markdown
# Development
|
|
|
|
This guide covers building MacTorn from source and contributing to the project.
|
|
|
|
## Prerequisites
|
|
|
|
- **macOS 13.0+** (Ventura or later)
|
|
- **Xcode 15+** (with Swift 5)
|
|
- **Git**
|
|
|
|
## Getting the Source
|
|
|
|
```bash
|
|
git clone https://github.com/pawelorzech/MacTorn.git
|
|
cd MacTorn/MacTorn
|
|
```
|
|
|
|
## Building
|
|
|
|
### Using Xcode
|
|
|
|
```bash
|
|
open MacTorn.xcodeproj
|
|
```
|
|
|
|
Press `Cmd + R` to build and run.
|
|
|
|
### Using Make
|
|
|
|
MacTorn includes a Makefile for common operations:
|
|
|
|
```bash
|
|
# Build Debug version
|
|
make build
|
|
|
|
# Build Release (Universal Binary)
|
|
make release
|
|
|
|
# Run unit tests
|
|
make test
|
|
|
|
# Run UI tests
|
|
make test-ui
|
|
|
|
# Run all tests
|
|
make test-all
|
|
|
|
# Clean build artifacts
|
|
make clean
|
|
```
|
|
|
|
All make commands use `xcodebuild` with code signing disabled (`CODE_SIGN_IDENTITY="-"`).
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
MacTorn/
|
|
├── MacTorn/ # Main app target
|
|
│ ├── MacTornApp.swift # App entry point
|
|
│ ├── ViewModels/
|
|
│ │ └── AppState.swift # Central state manager
|
|
│ ├── Models/
|
|
│ │ └── TornModels.swift # Data models & API config
|
|
│ ├── Views/
|
|
│ │ ├── ContentView.swift # Main tab container
|
|
│ │ ├── StatusView.swift # Status tab
|
|
│ │ ├── TravelView.swift # Travel tab
|
|
│ │ ├── MoneyView.swift # Money tab
|
|
│ │ ├── AttacksView.swift # Attacks tab
|
|
│ │ ├── FactionView.swift # Faction tab
|
|
│ │ ├── WatchlistView.swift # Watchlist tab
|
|
│ │ ├── SettingsView.swift # Settings tab
|
|
│ │ └── Components/ # Reusable components
|
|
│ ├── Utilities/
|
|
│ │ ├── NotificationManager.swift
|
|
│ │ ├── LaunchAtLoginManager.swift
|
|
│ │ ├── ShortcutsManager.swift
|
|
│ │ └── SoundManager.swift
|
|
│ ├── Networking/
|
|
│ │ └── NetworkSession.swift # Network abstraction
|
|
│ └── Helpers/
|
|
│ └── TransparencyEnvironment.swift
|
|
├── MacTornTests/ # Unit tests
|
|
│ ├── Models/
|
|
│ ├── ViewModels/
|
|
│ ├── Mocks/
|
|
│ │ └── MockNetworkSession.swift
|
|
│ └── Fixtures/
|
|
│ └── TornAPIFixtures.swift
|
|
└── MacTornUITests/ # UI tests
|
|
```
|
|
|
|
## Architecture Overview
|
|
|
|
### App Structure
|
|
|
|
MacTorn uses SwiftUI with the `@main` attribute and `MenuBarExtra` scene for the menu bar interface.
|
|
|
|
### State Management
|
|
|
|
**AppState** (`AppState.swift`) is the central state manager:
|
|
- Uses `@MainActor` for thread safety
|
|
- Handles API polling via Combine's `Timer.publish`
|
|
- Manages data parsing, notifications, and watchlist
|
|
- Uses dependency injection via `NetworkSession` protocol
|
|
|
|
### Networking
|
|
|
|
The `NetworkSession` protocol abstracts network calls:
|
|
|
|
```swift
|
|
protocol NetworkSession {
|
|
func data(from url: URL) async throws -> (Data, URLResponse)
|
|
}
|
|
```
|
|
|
|
This allows injecting `URLSession` for production and `MockNetworkSession` for testing.
|
|
|
|
### Data Models
|
|
|
|
All models are in `TornModels.swift`:
|
|
- `TornResponse` - Main API response
|
|
- `Bar` - Energy/Nerve/Happy/Life bar
|
|
- `Travel` - Travel status
|
|
- `Status` - Player status
|
|
- `Chain` - Faction chain
|
|
- `WatchlistItem` - Watched item with price
|
|
|
|
`TornAPI` enum contains endpoint configurations.
|
|
|
|
## Testing
|
|
|
|
### Writing Unit Tests
|
|
|
|
Tests use `MockNetworkSession` for API testing:
|
|
|
|
```swift
|
|
import XCTest
|
|
@testable import MacTorn
|
|
|
|
final class MyTests: XCTestCase {
|
|
func testExample() async throws {
|
|
let mockSession = MockNetworkSession()
|
|
let appState = AppState(session: mockSession)
|
|
|
|
try mockSession.setSuccessResponse(json: TornAPIFixtures.validFullResponse)
|
|
|
|
await appState.refreshNow()
|
|
|
|
XCTAssertNotNil(appState.data)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Test Fixtures
|
|
|
|
`TornAPIFixtures.swift` contains sample JSON responses for testing.
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
# Unit tests only
|
|
make test
|
|
|
|
# UI tests only
|
|
make test-ui
|
|
|
|
# All tests
|
|
make test-all
|
|
```
|
|
|
|
## Key Patterns
|
|
|
|
### API Polling
|
|
|
|
`AppState.startPolling()` uses Combine's Timer:
|
|
|
|
```swift
|
|
func startPolling() {
|
|
timerCancellable?.cancel()
|
|
timerCancellable = Timer.publish(every: TimeInterval(refreshInterval), on: .main, in: .common)
|
|
.autoconnect()
|
|
.sink { [weak self] _ in
|
|
Task { @MainActor in
|
|
await self?.fetchData()
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Live Countdown
|
|
|
|
Travel timer updates every second independently of API polling:
|
|
|
|
```swift
|
|
travelTimerCancellable = Timer.publish(every: 1, on: .main, in: .common)
|
|
.autoconnect()
|
|
.sink { [weak self] _ in
|
|
self?.updateTravelCountdown()
|
|
}
|
|
```
|
|
|
|
### Accessibility
|
|
|
|
`TransparencyEnvironment.swift` provides a custom environment key:
|
|
|
|
```swift
|
|
@Environment(\.reduceTransparency) private var reduceTransparency
|
|
```
|
|
|
|
Views use this to adjust backgrounds based on accessibility settings.
|
|
|
|
### State Persistence
|
|
|
|
- `@AppStorage` for simple values (API key, refresh interval, appearance)
|
|
- `UserDefaults` for complex data (notification rules, watchlist)
|
|
|
|
## Contributing
|
|
|
|
### Workflow
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch (`git checkout -b feature/my-feature`)
|
|
3. Make changes
|
|
4. Run tests (`make test-all`)
|
|
5. Commit with descriptive message
|
|
6. Push to your fork
|
|
7. Create a Pull Request
|
|
|
|
### Code Style
|
|
|
|
- Use Swift standard naming conventions
|
|
- Keep views focused and extract components
|
|
- Add tests for new functionality
|
|
- Update documentation as needed
|
|
|
|
### Pull Request Guidelines
|
|
|
|
- Describe what changes were made and why
|
|
- Reference any related issues
|
|
- Ensure all tests pass
|
|
- Keep changes focused (one feature/fix per PR)
|
|
|
|
## License
|
|
|
|
MacTorn is released under the MIT License. See [LICENSE](https://github.com/pawelorzech/MacTorn/blob/main/LICENSE) for details.
|
|
|
|
---
|
|
|
|
**See Also:** [[Changelog]] for version history
|