Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
2904536334
commit
6d3837022d
@ -1,5 +1,5 @@
|
||||
//
|
||||
// NoisePlayer.swift
|
||||
// SoundPlayer.swift
|
||||
// AudioPlaybackKit
|
||||
//
|
||||
// Created by Matt Bruce on 9/8/25.
|
||||
@ -8,13 +8,13 @@
|
||||
import AVFoundation
|
||||
import Observation
|
||||
|
||||
/// Audio playback service for white noise and ambient sounds
|
||||
/// Audio playback service for sounds and ambient audio
|
||||
@available(iOS 17.0, tvOS 17.0, *)
|
||||
@Observable
|
||||
public class NoisePlayer {
|
||||
public class SoundPlayer {
|
||||
|
||||
// MARK: - Singleton
|
||||
public static let shared = NoisePlayer()
|
||||
public static let shared = SoundPlayer()
|
||||
|
||||
// MARK: - Properties
|
||||
private var players: [String: AVAudioPlayer] = [:]
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// NoiseViewModel.swift
|
||||
// SoundViewModel.swift
|
||||
// AudioPlaybackKit
|
||||
//
|
||||
// Created by Matt Bruce on 9/8/25.
|
||||
@ -8,19 +8,19 @@
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
/// ViewModel for noise/audio playback
|
||||
/// ViewModel for sound/audio playback
|
||||
@available(iOS 17.0, tvOS 17.0, *)
|
||||
@Observable
|
||||
public class NoiseViewModel {
|
||||
public class SoundViewModel {
|
||||
|
||||
// MARK: - Properties
|
||||
private let noisePlayer: NoisePlayer
|
||||
private let soundPlayer: SoundPlayer
|
||||
private let soundConfigurationService: SoundConfigurationService
|
||||
public var isPreviewing: Bool = false
|
||||
public var previewSound: Sound?
|
||||
|
||||
public var isPlaying: Bool {
|
||||
noisePlayer.isPlaying
|
||||
soundPlayer.isPlaying
|
||||
}
|
||||
|
||||
public var availableSounds: [Sound] {
|
||||
@ -28,18 +28,18 @@ public class NoiseViewModel {
|
||||
}
|
||||
|
||||
// MARK: - Initialization
|
||||
public init(noisePlayer: NoisePlayer = NoisePlayer.shared, soundConfigurationService: SoundConfigurationService = SoundConfigurationService.shared) {
|
||||
self.noisePlayer = noisePlayer
|
||||
public init(soundPlayer: SoundPlayer = SoundPlayer.shared, soundConfigurationService: SoundConfigurationService = SoundConfigurationService.shared) {
|
||||
self.soundPlayer = soundPlayer
|
||||
self.soundConfigurationService = soundConfigurationService
|
||||
}
|
||||
|
||||
// MARK: - Public Interface
|
||||
public func playSound(_ sound: Sound) {
|
||||
noisePlayer.playSound(sound)
|
||||
soundPlayer.playSound(sound)
|
||||
}
|
||||
|
||||
public func stopSound() {
|
||||
noisePlayer.stopSound()
|
||||
soundPlayer.stopSound()
|
||||
}
|
||||
|
||||
public func selectSound(_ sound: Sound) {
|
||||
@ -61,7 +61,7 @@ public class NoiseViewModel {
|
||||
isPreviewing = true
|
||||
|
||||
// Play preview (3 seconds)
|
||||
noisePlayer.playSound(sound)
|
||||
soundPlayer.playSound(sound)
|
||||
|
||||
// Auto-stop preview after 3 seconds
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
|
||||
@ -71,7 +71,7 @@ public class NoiseViewModel {
|
||||
|
||||
public func stopPreview() {
|
||||
if isPreviewing {
|
||||
noisePlayer.stopSound()
|
||||
soundPlayer.stopSound()
|
||||
isPreviewing = false
|
||||
previewSound = nil
|
||||
}
|
||||
231
PRD.md
231
PRD.md
@ -63,7 +63,7 @@ TheNoiseClock is a SwiftUI-based iOS application that combines a customizable di
|
||||
- **Multiple sound options**:
|
||||
- White Noise (`white-noise.mp3`)
|
||||
- Heavy Rain White Noise (`heavy-rain-white-noise.mp3`)
|
||||
- Fan White Noise (`fan-white-noise-heater-303207.mp3`)
|
||||
- Fan White Noise (`fan-white-noise-heater.mp3`)
|
||||
- **Continuous playback**: Sounds loop indefinitely
|
||||
- **Advanced sound selection**: Category-based grid with search and preview
|
||||
- **Simple controls**: Play/Stop button with visual feedback
|
||||
@ -77,17 +77,18 @@ TheNoiseClock is a SwiftUI-based iOS application that combines a customizable di
|
||||
- **Wake lock integration**: Prevents device sleep while audio is playing
|
||||
- **Bluetooth audio support**: Works with AirPods and other Bluetooth audio devices
|
||||
- **Responsive layout**: Optimized for both portrait and landscape orientations
|
||||
- **AudioPlaybackKit integration**: Powered by reusable Swift package for audio functionality
|
||||
|
||||
### 6. Advanced Alarm System
|
||||
- **Multiple alarms**: Create and manage unlimited alarms
|
||||
- **Rich alarm editor**: Full-featured alarm creation and editing interface
|
||||
- **Time selection**: Wheel-style date picker with optimized font sizing for maximum readability
|
||||
- **Dynamic alarm sounds**: Configurable alarm sounds loaded from JSON configuration
|
||||
- **Dynamic alarm sounds**: Configurable alarm sounds loaded from dedicated alarm-sounds.json configuration
|
||||
- **Sound preview**: Play/stop functionality for testing alarm sounds before selection
|
||||
- **Sound organization**: Alarm sounds organized in bundles with categories
|
||||
- **Sound organization**: Alarm sounds organized in dedicated AlarmSounds.bundle with categories
|
||||
- **Custom labels**: User-defined alarm names and descriptions
|
||||
- **Repeat schedules**: Set alarms to repeat on specific weekdays or daily
|
||||
- **Sound selection**: Choose from extensive system sounds with live preview
|
||||
- **Sound selection**: Choose from extensive alarm sounds with live preview
|
||||
- **Volume control**: Adjustable alarm volume (0-100%)
|
||||
- **Vibration settings**: Enable/disable vibration for each alarm
|
||||
- **Snooze functionality**: Configurable snooze duration (5, 7, 8, 9, 10, 15, 20 minutes)
|
||||
@ -98,6 +99,7 @@ TheNoiseClock is a SwiftUI-based iOS application that combines a customizable di
|
||||
- **Alarm management**: Add, edit, delete, and duplicate alarms
|
||||
- **Next trigger preview**: Shows when the next alarm will fire
|
||||
- **Responsive time picker**: Font sizes adapt to available space and orientation
|
||||
- **AlarmSoundService integration**: Dedicated service for alarm-specific sound management
|
||||
|
||||
## Advanced Clock Display Features
|
||||
|
||||
@ -139,6 +141,40 @@ TheNoiseClock is a SwiftUI-based iOS application that combines a customizable di
|
||||
|
||||
## Technical Architecture
|
||||
|
||||
### Swift Package Architecture
|
||||
|
||||
TheNoiseClock has been refactored to use a modular Swift Package architecture for improved code reusability and maintainability:
|
||||
|
||||
#### AudioPlaybackKit Package
|
||||
- **Purpose**: Reusable audio playback functionality for iOS and tvOS applications
|
||||
- **Platform Support**: iOS 17.0+ and tvOS 17.0+
|
||||
- **Core Components**:
|
||||
- `Sound` model: Generic sound data structure with Codable support and GUID generation
|
||||
- `SoundConfiguration` models: Configuration structures for sound management
|
||||
- `SoundConfigurationService`: Generic sound configuration service with JSON loading
|
||||
- `NoisePlayer`: Audio playback service with background support
|
||||
- `WakeLockService`: Screen wake lock management
|
||||
- `NoiseViewModel`: Audio playback state management
|
||||
- `AudioConstants`: Audio-related constants and configuration
|
||||
- **Key Features**:
|
||||
- Generic sound management (no alarm-specific functionality)
|
||||
- Fatal error handling for missing configuration files
|
||||
- Platform-conditional compilation for tvOS compatibility
|
||||
- Modern @Observable state management
|
||||
- Background audio support with interruption handling
|
||||
|
||||
#### Package Integration
|
||||
- **Local Package**: AudioPlaybackKit is included as a local Swift package dependency
|
||||
- **Xcode Integration**: Properly configured in project.pbxproj with XCLocalSwiftPackageReference
|
||||
- **Import Usage**: Main app imports AudioPlaybackKit for audio functionality
|
||||
- **Separation of Concerns**: Generic audio functionality in package, app-specific logic in main app
|
||||
|
||||
#### App-Specific Extensions
|
||||
- **AlarmSoundService**: Dedicated service in main app for alarm-specific sound management
|
||||
- **Configuration Separation**: Alarm sounds use separate alarm-sounds.json file
|
||||
- **Category Constants**: Hardcoded alarm category ID to avoid magic strings
|
||||
- **Service Pattern**: Extension pattern for app-specific functionality
|
||||
|
||||
### Code Organization Principles
|
||||
|
||||
**TOP PRIORITY:** The codebase must be built with the following architectural principles from the beginning:
|
||||
@ -200,8 +236,17 @@ These principles are fundamental to the project's long-term success and must be
|
||||
- Sound name with volume control
|
||||
- Vibration settings
|
||||
- Snooze duration configuration
|
||||
- **Sound**: Simple struct for noise file management
|
||||
- **Sound** (AudioPlaybackKit): Generic sound data model with Codable support
|
||||
- Unique GUID identifier (auto-generated)
|
||||
- Display name and file name
|
||||
- Category and description
|
||||
- Optional bundle name for organization
|
||||
- Optional isDefault flag for default sound selection
|
||||
- Custom Codable implementation with GUID generation
|
||||
- **SoundConfiguration** (AudioPlaybackKit): Configuration structure for sound management
|
||||
- Array of Sound objects
|
||||
- Sound categories and audio settings
|
||||
- JSON-based configuration loading
|
||||
- **LegacyAlarm**: Backward compatibility struct for old alarm data
|
||||
|
||||
### Data Persistence
|
||||
@ -210,17 +255,21 @@ These principles are fundamental to the project's long-term success and must be
|
||||
- **Bundle resources**: Audio files stored in app bundle
|
||||
|
||||
### Audio System
|
||||
- **AudioPlaybackKit Package**: Reusable audio functionality in Swift package
|
||||
- **AVFoundation**: AVAudioPlayer for noise playback
|
||||
- **@Observable NoisePlayer**: Modern state management with preloading
|
||||
- **Looping playback**: Infinite loop for ambient sounds
|
||||
- **Audio session management**: Proper audio session configuration with background support
|
||||
- **Error handling**: Graceful handling of missing audio files
|
||||
- **Error handling**: Fatal error handling for missing configuration files
|
||||
- **AlarmTonePlayer**: Dedicated player for alarm sound previews
|
||||
- **Background audio**: Continues playback when app is backgrounded
|
||||
- **Interruption handling**: Automatic resume after phone calls and route changes
|
||||
- **Wake lock integration**: Prevents device sleep during audio playback
|
||||
- **Focus mode awareness**: Monitors and respects Focus mode settings
|
||||
- **Notification compatibility**: Ensures alarms work with Focus modes enabled
|
||||
- **Configuration separation**: Separate JSON files for ambient sounds (sounds.json) and alarm sounds (alarm-sounds.json)
|
||||
- **Generic sound management**: AudioPlaybackKit provides generic sound functionality
|
||||
- **App-specific extensions**: AlarmSoundService handles alarm-specific sound management
|
||||
|
||||
### Battery System
|
||||
- **@Observable BatteryService**: Modern state management for battery monitoring
|
||||
@ -283,83 +332,95 @@ These principles are fundamental to the project's long-term success and must be
|
||||
## File Structure and Organization
|
||||
|
||||
### Recommended File Organization
|
||||
Following the separation of concerns principle, the codebase should be organized into focused, single-responsibility files:
|
||||
Following the separation of concerns principle, the codebase is organized into focused, single-responsibility files with Swift Package integration:
|
||||
|
||||
```
|
||||
TheNoiseClock/
|
||||
├── App/
|
||||
│ ├── TheNoiseClockApp.swift # App entry point and configuration
|
||||
│ └── ContentView.swift # Main tab navigation coordinator
|
||||
├── Core/
|
||||
│ ├── Constants/
|
||||
│ │ ├── AppConstants.swift # App-wide constants and configuration
|
||||
│ │ ├── UIConstants.swift # UI-specific constants (colors, sizes, etc.)
|
||||
│ │ └── AudioConstants.swift # Audio-related constants
|
||||
│ ├── Extensions/
|
||||
│ │ ├── Color+Extensions.swift # Color utilities and extensions
|
||||
│ │ ├── Date+Extensions.swift # Date formatting and utilities
|
||||
│ │ └── View+Extensions.swift # Common view modifiers and responsive utilities
|
||||
│ └── Utilities/
|
||||
│ ├── ColorUtils.swift # Color manipulation utilities
|
||||
│ ├── FontUtils.swift # Font sizing, typography, and customization utilities
|
||||
│ └── NotificationUtils.swift # Notification helper functions
|
||||
├── Models/
|
||||
│ ├── ClockStyle.swift # Clock customization data model
|
||||
│ ├── Alarm.swift # Alarm data model
|
||||
│ ├── Sound.swift # Sound data model
|
||||
│ └── LegacyAlarm.swift # Backward compatibility model
|
||||
├── ViewModels/
|
||||
│ ├── ClockViewModel.swift # Clock display logic and state
|
||||
│ ├── AlarmViewModel.swift # Alarm management logic
|
||||
│ └── NoiseViewModel.swift # Audio playback state management
|
||||
├── Views/
|
||||
│ ├── Clock/
|
||||
│ │ ├── ClockView.swift # Main clock display view
|
||||
│ │ ├── ClockSettingsView.swift # Clock customization interface
|
||||
│ │ └── Components/
|
||||
│ │ ├── TimeDisplayView.swift # Advanced segmented time display with fixed-width digits
|
||||
│ │ ├── BatteryOverlayView.swift # Battery level overlay
|
||||
│ │ ├── DateOverlayView.swift # Date display overlay
|
||||
│ │ └── TopOverlayView.swift # Combined overlay container
|
||||
│ ├── Alarms/
|
||||
│ │ ├── AlarmView.swift # Main alarm management view
|
||||
│ │ ├── AddAlarmView.swift # Alarm creation interface
|
||||
│ │ └── Components/
|
||||
│ │ ├── AlarmRowView.swift # Individual alarm row component
|
||||
│ │ ├── TimePickerSection.swift # Time selection component
|
||||
│ │ ├── TimeUntilAlarmSection.swift # Time calculation display
|
||||
│ │ ├── SoundSelectionView.swift # Sound selection with preview
|
||||
│ │ ├── LabelEditView.swift # Label editing interface
|
||||
│ │ └── SnoozeSelectionView.swift # Snooze duration selection
|
||||
│ └── Noise/
|
||||
│ ├── NoiseView.swift # Main white noise player interface
|
||||
│ └── Components/
|
||||
│ ├── SoundCategoryView.swift # Advanced grid-based sound selection
|
||||
│ └── SoundControlView.swift # Playback controls component
|
||||
├── Services/
|
||||
│ ├── NoisePlayer.swift # Audio playback service with background support
|
||||
│ ├── AlarmService.swift # Alarm management service with Focus mode integration
|
||||
│ ├── NotificationService.swift # Notification handling service
|
||||
│ ├── WakeLockService.swift # Screen wake lock management service
|
||||
│ ├── FocusModeService.swift # Focus mode integration and notification management
|
||||
│ └── BatteryService.swift # Battery monitoring and state management service
|
||||
└── Resources/
|
||||
├── sounds.json # Sound configuration and definitions
|
||||
├── Ambient.bundle/ # Ambient sound category
|
||||
│ └── white-noise.mp3
|
||||
├── Nature.bundle/ # Nature sound category
|
||||
│ └── heavy-rain-white-noise.mp3
|
||||
├── Mechanical.bundle/ # Mechanical sound category
|
||||
│ └── fan-white-noise-heater.mp3
|
||||
├── AlarmSounds.bundle/ # Alarm sound category
|
||||
│ ├── digital-alarm.mp3
|
||||
│ ├── iphone-alarm.mp3
|
||||
│ ├── classic-alarm.mp3
|
||||
│ ├── beep-alarm.mp3
|
||||
│ ├── siren-alarm.mp3
|
||||
│ └── voice-wakeup.mp3
|
||||
└── Assets.xcassets/
|
||||
└── [Asset catalogs]
|
||||
├── AudioPlaybackKit/ # Swift Package for reusable audio functionality
|
||||
│ ├── Package.swift # Package configuration (iOS 17.0+, tvOS 17.0+)
|
||||
│ └── Sources/AudioPlaybackKit/
|
||||
│ ├── Models/
|
||||
│ │ ├── Sound.swift # Generic sound data model with Codable support
|
||||
│ │ └── SoundConfiguration.swift # Sound configuration models and service
|
||||
│ ├── Services/
|
||||
│ │ ├── NoisePlayer.swift # Audio playback service
|
||||
│ │ └── WakeLockService.swift # Screen wake lock management
|
||||
│ ├── ViewModels/
|
||||
│ │ └── NoiseViewModel.swift # Audio playback state management
|
||||
│ └── Constants/
|
||||
│ └── AudioConstants.swift # Audio-related constants
|
||||
├── TheNoiseClock/ # Main application
|
||||
│ ├── App/
|
||||
│ │ ├── TheNoiseClockApp.swift # App entry point and configuration
|
||||
│ │ └── ContentView.swift # Main tab navigation coordinator
|
||||
│ ├── Core/
|
||||
│ │ ├── Constants/
|
||||
│ │ │ ├── AppConstants.swift # App-wide constants and configuration
|
||||
│ │ │ └── UIConstants.swift # UI-specific constants (colors, sizes, etc.)
|
||||
│ │ ├── Extensions/
|
||||
│ │ │ ├── Color+Extensions.swift # Color utilities and extensions
|
||||
│ │ │ ├── Date+Extensions.swift # Date formatting and utilities
|
||||
│ │ │ └── View+Extensions.swift # Common view modifiers and responsive utilities
|
||||
│ │ └── Utilities/
|
||||
│ │ ├── ColorUtils.swift # Color manipulation utilities
|
||||
│ │ ├── FontUtils.swift # Font sizing, typography, and customization utilities
|
||||
│ │ └── NotificationUtils.swift # Notification helper functions
|
||||
│ ├── Models/
|
||||
│ │ ├── ClockStyle.swift # Clock customization data model
|
||||
│ │ ├── Alarm.swift # Alarm data model
|
||||
│ │ └── LegacyAlarm.swift # Backward compatibility model
|
||||
│ ├── ViewModels/
|
||||
│ │ ├── ClockViewModel.swift # Clock display logic and state
|
||||
│ │ └── AlarmViewModel.swift # Alarm management logic
|
||||
│ ├── Views/
|
||||
│ │ ├── Clock/
|
||||
│ │ │ ├── ClockView.swift # Main clock display view
|
||||
│ │ │ ├── ClockSettingsView.swift # Clock customization interface
|
||||
│ │ │ └── Components/
|
||||
│ │ │ ├── TimeDisplayView.swift # Advanced segmented time display with fixed-width digits
|
||||
│ │ │ ├── BatteryOverlayView.swift # Battery level overlay
|
||||
│ │ │ ├── DateOverlayView.swift # Date display overlay
|
||||
│ │ │ └── TopOverlayView.swift # Combined overlay container
|
||||
│ │ ├── Alarms/
|
||||
│ │ │ ├── AlarmView.swift # Main alarm management view
|
||||
│ │ │ ├── AddAlarmView.swift # Alarm creation interface
|
||||
│ │ │ └── Components/
|
||||
│ │ │ ├── AlarmRowView.swift # Individual alarm row component
|
||||
│ │ │ ├── TimePickerSection.swift # Time selection component
|
||||
│ │ │ ├── TimeUntilAlarmSection.swift # Time calculation display
|
||||
│ │ │ ├── SoundSelectionView.swift # Sound selection with preview
|
||||
│ │ │ ├── LabelEditView.swift # Label editing interface
|
||||
│ │ │ └── SnoozeSelectionView.swift # Snooze duration selection
|
||||
│ │ └── Noise/
|
||||
│ │ ├── NoiseView.swift # Main white noise player interface
|
||||
│ │ └── Components/
|
||||
│ │ ├── SoundCategoryView.swift # Advanced grid-based sound selection
|
||||
│ │ └── SoundControlView.swift # Playback controls component
|
||||
│ ├── Services/
|
||||
│ │ ├── AlarmService.swift # Alarm management service with Focus mode integration
|
||||
│ │ ├── NotificationService.swift # Notification handling service
|
||||
│ │ ├── FocusModeService.swift # Focus mode integration and notification management
|
||||
│ │ ├── BatteryService.swift # Battery monitoring and state management service
|
||||
│ │ └── AlarmSoundService.swift # Alarm-specific sound management service
|
||||
│ └── Resources/
|
||||
│ ├── sounds.json # Ambient sound configuration and definitions
|
||||
│ ├── alarm-sounds.json # Alarm sound configuration and definitions
|
||||
│ ├── Ambient.bundle/ # Ambient sound category
|
||||
│ │ └── white-noise.mp3
|
||||
│ ├── Nature.bundle/ # Nature sound category
|
||||
│ │ └── heavy-rain-white-noise.mp3
|
||||
│ ├── Mechanical.bundle/ # Mechanical sound category
|
||||
│ │ └── fan-white-noise-heater.mp3
|
||||
│ ├── AlarmSounds.bundle/ # Alarm sound category
|
||||
│ │ ├── digital-alarm.caf
|
||||
│ │ ├── classic-alarm.caf
|
||||
│ │ ├── beep-alarm.caf
|
||||
│ │ ├── siren-alarm.caf
|
||||
│ │ └── buzzing-alarm.caf
|
||||
│ └── Assets.xcassets/
|
||||
│ └── [Asset catalogs]
|
||||
└── TheNoiseClock.xcodeproj/ # Xcode project with AudioPlaybackKit dependency
|
||||
└── project.pbxproj # Project configuration with local package reference
|
||||
```
|
||||
|
||||
### File Naming Conventions
|
||||
@ -464,6 +525,12 @@ The following changes **automatically require** PRD updates:
|
||||
- **iOS 26 Features**: Latest platform capabilities where available
|
||||
|
||||
### Dependencies
|
||||
- **AudioPlaybackKit**: Local Swift package for reusable audio functionality
|
||||
- iOS 17.0+ and tvOS 17.0+ support
|
||||
- Generic sound management and configuration
|
||||
- Audio playback with background support
|
||||
- Wake lock management
|
||||
- Modern @Observable state management
|
||||
- **SwiftUI**: Native iOS UI framework with latest features
|
||||
- **AVFoundation**: Audio playback with modern async patterns and background support
|
||||
- **UserNotifications**: Alarm notifications with rich content support
|
||||
@ -514,11 +581,13 @@ The following changes **automatically require** PRD updates:
|
||||
### Project Information
|
||||
- **Created**: September 7, 2025
|
||||
- **Framework**: SwiftUI with iOS 18.0+ target (latest stable features)
|
||||
- **Architecture**: Modern SwiftUI with @Observable pattern and MVVM
|
||||
- **Architecture**: Modern SwiftUI with @Observable pattern, MVVM, and Swift Package modularity
|
||||
- **Package Architecture**: AudioPlaybackKit Swift package for reusable audio functionality
|
||||
- **Testing**: Comprehensive unit and UI test targets with Swift Testing
|
||||
- **Version control**: Git repository with feature branch workflow
|
||||
- **Performance**: Optimized for battery life and smooth operation
|
||||
- **Modern iOS**: Uses latest iOS 18+ and iOS 26 features with Swift 6 language improvements
|
||||
- **Code Reusability**: Modular Swift package architecture enables code reuse across projects
|
||||
|
||||
### Modern iOS Development Practices
|
||||
- **Swift 6**: Latest language features including strict concurrency checking
|
||||
|
||||
@ -14,7 +14,7 @@ struct SoundSelectionView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
// Use shared player instance to avoid audio conflicts
|
||||
private let noisePlayer = NoisePlayer.shared
|
||||
private let soundPlayer = SoundPlayer.shared
|
||||
private let alarmSounds = AlarmSoundService.shared.getAlarmSounds().sorted { $0.name < $1.name }
|
||||
|
||||
@State private var isPlaying = false
|
||||
@ -73,13 +73,13 @@ struct SoundSelectionView: View {
|
||||
stopSound()
|
||||
|
||||
// Start playing the new sound
|
||||
noisePlayer.playSound(sound)
|
||||
soundPlayer.playSound(sound)
|
||||
isPlaying = true
|
||||
currentlyPlayingSound = selectedSound
|
||||
}
|
||||
|
||||
private func stopSound() {
|
||||
noisePlayer.stopSound()
|
||||
soundPlayer.stopSound()
|
||||
isPlaying = false
|
||||
currentlyPlayingSound = nil
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ struct SoundCategoryView: View {
|
||||
@Binding var selectedSound: Sound?
|
||||
@State private var selectedCategory: String = "all"
|
||||
@State private var searchText: String = ""
|
||||
@State private var viewModel = NoiseViewModel()
|
||||
@State private var viewModel = SoundViewModel()
|
||||
|
||||
// MARK: - Computed Properties
|
||||
private var filteredSounds: [Sound] {
|
||||
|
||||
@ -12,7 +12,7 @@ import AudioPlaybackKit
|
||||
struct NoiseView: View {
|
||||
|
||||
// MARK: - Properties
|
||||
@State private var viewModel = NoiseViewModel()
|
||||
@State private var viewModel = SoundViewModel()
|
||||
@State private var selectedSound: Sound? {
|
||||
didSet {
|
||||
// Stop current playback when selecting a new sound
|
||||
|
||||
Loading…
Reference in New Issue
Block a user