Skip to content

Commit c612497

Browse files
authored
Merge pull request #52 from playola-radio/develop
0.8.0
2 parents f2ac0e3 + d9765e1 commit c612497

23 files changed

Lines changed: 939 additions & 667 deletions

.circleci/config.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,27 @@ orbs:
44
ruby: circleci/ruby@2.0.0
55

66
jobs:
7+
swiftlint_check:
8+
macos:
9+
xcode: 16.2.0
10+
steps:
11+
- checkout
12+
- run:
13+
name: Install Bundler
14+
command: gem install bundler
15+
- run:
16+
name: Install Fastlane
17+
command: bundle install
18+
- run:
19+
name: Install SwiftLint (Homebrew)
20+
command: brew install swiftlint
21+
- run:
22+
name: Run SwiftLint via Fastlane
23+
command: bundle exec fastlane lint_code
24+
- run:
25+
name: Run swift-format lint check
26+
command: bundle exec fastlane format_check
27+
728
test:
829
macos:
930
xcode: 16.2.0
@@ -27,6 +48,10 @@ jobs:
2748

2849
workflows:
2950
version: 2
51+
lint-codebase:
52+
jobs:
53+
- swiftlint_check
54+
3055
build-test:
3156
jobs:
3257
- test

.github/workflows/ci.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
lint:
11+
runs-on: macos-latest
12+
name: SwiftLint
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Install SwiftLint
17+
run: brew install swiftlint
18+
19+
- name: Install Fastlane
20+
run: |
21+
gem install bundler
22+
bundle install
23+
24+
- name: Run SwiftLint
25+
run: bundle exec fastlane lint_code
26+
27+
build-and-test:
28+
runs-on: macos-latest
29+
name: Build and Test
30+
steps:
31+
- uses: actions/checkout@v4
32+
33+
- name: Select Xcode version
34+
run: sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
35+
36+
- name: Install dependencies
37+
run: |
38+
gem install bundler
39+
bundle install
40+
41+
- name: Run tests
42+
run: bundle exec fastlane tests

.swiftlint.yml

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
1+
# SwiftLint Configuration
12
disabled_rules:
23
- trailing_whitespace
3-
- line_length
4-
5-
opt_in_rules:
6-
- empty_count
7-
- empty_string
8-
- redundant_nil_coalescing
4+
- trailing_comma
5+
- opening_brace
6+
- closure_parameter_position
7+
- todo
98

109
excluded:
1110
- Carthage
1211
- Pods
1312
- .build
13+
- DerivedData
1414

15-
function_parameter_count:
16-
warning: 6
17-
error: 8
15+
# General configuration
16+
line_length:
17+
warning: 120
18+
error: 200
1819

20+
# Allow shorter variable names in specific contexts
1921
identifier_name:
20-
min_length: 2
21-
allowed_symbols: "_"
22-
23-
type_name:
24-
min_length: 3
22+
min_length:
23+
warning: 2
24+
error: 1
25+
excluded:
26+
- "to" # Common parameter name in Mail.swift
27+
- "fm" # Enum case in RadioStation.swift
28+
- "i" # Common loop index
29+
- "j" # Common loop index
30+
- "k" # Common loop index
31+
allowed_symbols:
32+
- "_" # Common in variable names
2533

26-
vertical_whitespace:
27-
max_empty_lines: 2
34+
type_body_length:
35+
warning: 1000
36+
error: 1000
2837

29-
cyclomatic_complexity:
30-
warning: 15
31-
error: 25
38+
file_length:
39+
warning: 1000
40+
error: 1000

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ let package = Package(
2626
name: "PlayolaPlayer",
2727
resources: [.copy("MockData")],
2828
plugins: [
29-
// .plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLintPlugins")
29+
.plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLintPlugins")
3030
]
3131
),
3232
.testTarget(
3333
name: "PlayolaPlayerTests",
3434
dependencies: ["PlayolaPlayer"],
3535
plugins: [
36-
// .plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLintPlugins")
36+
.plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLintPlugins")
3737
]
3838
),
3939
]

PlayolaPlayerExample/PlayolaPlayerExample/ContentView.swift

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,13 @@ struct ContentView: View {
180180
// Main playback controls
181181
HStack(spacing: 40) {
182182
// Station picker
183-
Button(action: { showingStationPicker.toggle() }) {
184-
Image(systemName: "list.bullet")
185-
.font(.title2)
186-
.foregroundColor(.white.opacity(0.8))
187-
}
183+
Button(
184+
action: { showingStationPicker.toggle() },
185+
label: {
186+
Image(systemName: "list.bullet")
187+
.font(.title2)
188+
.foregroundColor(.white.opacity(0.8))
189+
})
188190

189191
// Play/Stop button (current time)
190192
Button(action: playOrPause) {
@@ -293,23 +295,25 @@ struct StationPickerView: View {
293295
var body: some View {
294296
NavigationView {
295297
List(stations, id: \.0) { station in
296-
Button(action: {
297-
Task {
298-
do {
299-
try await PlayolaStationPlayer.shared.play(stationId: station.0)
300-
} catch {
301-
print("Failed to start playback: \(error)")
298+
Button(
299+
action: {
300+
Task {
301+
do {
302+
try await PlayolaStationPlayer.shared.play(stationId: station.0)
303+
} catch {
304+
print("Failed to start playback: \(error)")
305+
}
302306
}
303-
}
304-
dismiss()
305-
}) {
306-
HStack {
307-
Image(systemName: "radio")
308-
.foregroundColor(.blue)
309-
Text(station.1)
310-
Spacer()
311-
}
312-
}
307+
dismiss()
308+
},
309+
label: {
310+
HStack {
311+
Image(systemName: "radio")
312+
.foregroundColor(.blue)
313+
Text(station.1)
314+
Spacer()
315+
}
316+
})
313317
}
314318
.navigationTitle("Select Station")
315319
.navigationBarItems(trailing: Button("Done") { dismiss() })

PlayolaPlayerExample/PlayolaPlayerExampleTests/PlayolaPlayerExampleTests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ final class PlayolaPlayerExampleTests: XCTestCase {
2424
// Use XCTAssert and related functions to verify your tests produce the correct results.
2525
// Any test you write for XCTest can be annotated as throws and async.
2626
// Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
27-
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
27+
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions
28+
// afterwards.
2829
}
2930

3031
func testPerformanceExample() throws {

PlayolaPlayerExample/PlayolaPlayerExampleUITests/PlayolaPlayerExampleUITests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ final class PlayolaPlayerExampleUITests: XCTestCase {
1515
// In UI tests it is usually best to stop immediately when a failure occurs.
1616
continueAfterFailure = false
1717

18-
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
18+
// In UI tests it's important to set the initial state - such as interface orientation - required for your tests
19+
// before they run. The setUp method is a good place to do this.
1920
}
2021

2122
override func tearDownWithError() throws {

PlayolaPlayerExample/PlayolaPlayerExampleUITests/PlayolaPlayerExampleUITestsLaunchTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import XCTest
99

1010
final class PlayolaPlayerExampleUITestsLaunchTests: XCTestCase {
1111

12-
override class var runsForEachTargetApplicationUIConfiguration: Bool {
12+
override static var runsForEachTargetApplicationUIConfiguration: Bool {
1313
true
1414
}
1515

Sources/PlayolaPlayer/Models/RelatedText.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,16 @@ extension RelatedText {
3030
return RelatedText(
3131
title: "Why I chose this song",
3232
body:
33-
"So John Mayer was, I forget which CD it was, it was, you know, John Mayer's gone through a bunch of different phases, and he went through this phase, I can picture the front of the record. It's got something like Olivia on it. Something like Olivia. Born and Raised, I think is the record it was on. He's gone through so many different phases in his career. He's bopped in and out of every musical genre you can be in. He's done it all. He's obviously one of the top five guitar players of all time, and I think he's a better songwriter than he is a guitar player. And it's like, you know, it's, he's just this person who transcends what we call music. He's just so far on his own level that it is nearly inhuman, you know. It's like just something totally different that, that we're just kind of lucky to be existing at the same time. So this is a song by John Mayer."
33+
"So John Mayer was, I forget which CD it was, it was, you know, John Mayer's gone through a bunch of different "
34+
+ "phases, and he went through this phase, I can picture the front of the record. It's got something like "
35+
+ "Olivia "
36+
+ "on it. Something like Olivia. Born and Raised, I think is the record it was on. He's gone through so many "
37+
+ "different phases in his career. He's bopped in and out of every musical genre you can be in. He's done it "
38+
+ "all. He's obviously one of the top five guitar players of all time, and I think he's a better songwriter "
39+
+ "than he is a guitar player. And it's like, you know, it's, he's just this person who transcends what we "
40+
+ "call music. He's just so far on his own level that it is nearly inhuman, you know. It's like just "
41+
+ "something totally different that, that we're just kind of lucky to be existing at the same time. So this "
42+
+ "is a song by John Mayer."
3443
)
3544
}
3645
public static var mocks: [RelatedText] {

Sources/PlayolaPlayer/Models/Schedule.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,14 @@ public struct Schedule: Sendable {
5757

5858
extension Schedule {
5959
public static let mock: Schedule = {
60-
let url = Bundle.module.url(
61-
forResource: "MockSchedule", withExtension: "json", subdirectory: "MockData")!
62-
let data = try! Data(contentsOf: url, options: .dataReadingMapped)
63-
let spins = try! JSONDecoderWithIsoFull().decode([Spin].self, from: data)
60+
guard
61+
let url = Bundle.module.url(
62+
forResource: "MockSchedule", withExtension: "json", subdirectory: "MockData"),
63+
let data = try? Data(contentsOf: url, options: .dataReadingMapped),
64+
let spins = try? JSONDecoderWithIsoFull().decode([Spin].self, from: data)
65+
else {
66+
fatalError("Failed to load mock schedule data")
67+
}
6468
return Schedule(stationId: spins[0].stationId, spins: spins)
6569
}()
6670
}

0 commit comments

Comments
 (0)