Playola Radio is a streaming radio app for iOS featuring curated artist stations, traditional FM radio, and a rewards system for listening time.
- 🎵 Stream curated artist radio stations and traditional FM stations
- 🎁 Earn rewards points based on listening time
- 🚗 Full CarPlay support
- 👤 User authentication (Apple Sign-In, Google Sign-In)
- 📊 Analytics tracking for listening sessions
- 🎨 Custom station artwork and branding
- UI Framework: SwiftUI
- Architecture: MV (Model-View) with Swift's @Observable framework
- Dependency Injection: Dependencies
- State Management: Sharing
- Streaming: FRadioPlayer + PlayolaPlayer
- Analytics: Mixpanel
- CI/CD: GitHub Actions + CircleCI + Fastlane
PlayolaRadio/
├── Assets.xcassets/ # Images, colors, and app icons
├── CarPlay/ # CarPlay scene delegates
├── Config/ # App configuration and secrets
├── Core/ # Core business logic and services
│ ├── Analytics/ # Analytics tracking
│ ├── API/ # API client
│ ├── Audio/ # Audio streaming and playback
│ ├── Auth/ # Authentication services
│ ├── ListeningTracker/ # Listening session tracking
│ ├── Mail/ # Email services
│ └── Navigation/ # Navigation coordination
├── Extensions/ # Swift extensions and utilities
├── Models/ # Data models
├── State/ # State management
└── Views/ # SwiftUI views and view models
├── Pages/ # Full-screen page views
└── Reusable Components/# Shared UI components
- Xcode 16.0+
- iOS 17.0+ deployment target
- Homebrew (for development tools)
- Ruby (for Fastlane)
-
Clone the repository
git clone https://github.com/playola-radio/playola-radio-ios.git cd playola-radio-ios -
Install Ruby dependencies
bundle install
-
Configure secrets
cp PlayolaRadio/Config/Secrets-Example.xcconfig PlayolaRadio/Config/Secrets-Local.xcconfig
Edit
Secrets-Local.xcconfigwith your API keys and tokens. EditSecrets-Staging.xcconfigwith your API keys and tokens. -
Install Git hooks
./.githooks/install-hooks.sh
-
Open in Xcode
open PlayolaRadio.xcodeproj
-
Select scheme and run
- Use
PlayolaRadioscheme for production - Use
PlayolaRadio-Localscheme for local development - Use
PlayolaRadio-Stagingscheme for staging environment
- Use
All page models inherit from a base ViewModel class that provides Hashable conformance:
@MainActor
@Observable
class MyPageModel: ViewModel {
@ObservationIgnored @Dependency(\.api) var api
@ObservationIgnored @Dependency(\.analytics) var analytics
// State properties
var isLoading = false
// Actions
func viewAppeared() async {
// Implementation
}
}Use @Shared property wrapper for cross-view state:
@Shared(.auth) var auth
@Shared(.nowPlaying) var nowPlayingDefine dependencies using the @DependencyClient macro:
@DependencyClient
struct APIClient: Sendable {
var getStations: @Sendable () async throws -> IdentifiedArrayOf<StationList>
}Tests use XCTest with @MainActor for UI-related tests:
@MainActor
final class MyPageTests: XCTestCase {
func testSomething() async {
let model = MyPageModel()
await model.viewAppeared()
XCTAssertTrue(model.someState)
}
}The project uses SwiftLint and swift-format for code consistency:
- SwiftLint rules are defined in
.swiftlint.yml - Code is automatically formatted on commit via Git hooks
- Force unwraps require SwiftLint exemption comments
bundle exec fastlane testbundle exec fastlane lint_code- Trigger workflow on
developwith new version (e.g.,5.4.0)- Go to Actions → Prepare Release → Run workflow
- Enter the new version number
- Click the CircleCI link to monitor progress
git pull→ Archive both schemes → Upload to TestFlight
- Create fix branch off
develop→ merge fix todevelop - Trigger workflow on
develop(leave version blank - build auto-increments) git pull→ Archive → Upload- Repeat until satisfied
- Merge
develop→mainvia PR - Tag (e.g.,
v5.4.0) is created automatically
The release workflow uses GitHub Actions to trigger CircleCI. Setup required:
1. CircleCI API Token → GitHub
- Go to CircleCI User Settings > Personal API Tokens
- Create a new token (name it "GitHub Actions")
- Copy the token
- Go to your GitHub repo → Settings → Secrets → Actions
- Add secret:
CCI_TOKEN= (paste token)
2. Give CircleCI Write Access to Push Commits
- Go to CircleCI Project Settings > SSH Keys
- Click "Authorize with GitHub" under "User Key"
- This allows CircleCI to push the version bump commit
Central service managing radio playback state and FRadioPlayer integration.
Tracks listening sessions for analytics and rewards calculation, persisting data locally.
Handles all network requests to the Playola backend.
Manages analytics tracking through Mixpanel.
Root view model managing app-wide navigation and sheet presentation.
auth: User authentication statenowPlaying: Current playback informationstationLists: Available radio stationsactiveTab: Current tab selectionlisteningTracker: Listening session tracking
- Ensure all dependencies are resolved: Product → Update to Latest Package Versions
- Clean build folder: Product → Clean Build Folder (⇧⌘K)
- Delete derived data if needed
Missing secrets will cause build failures. Ensure your Secrets-Local.xcconfig contains:
MIXPANEL_TOKENDEV_ENVIRONMENT- API endpoints configuration
- Create a feature branch from
develop - Make your changes following the coding conventions
- Ensure all tests pass
- Submit a pull request to
develop
Proprietary - All rights reserved