Skip to content

Add custom alarm sounds#699

Open
bjorkert wants to merge 4 commits into
devfrom
feature/custom-alarm-sounds
Open

Add custom alarm sounds#699
bjorkert wants to merge 4 commits into
devfrom
feature/custom-alarm-sounds

Conversation

@bjorkert

@bjorkert bjorkert commented Jul 8, 2026

Copy link
Copy Markdown
Member

Adds user-imported alarm sounds alongside the built-in tones.

  • Import audio via the tone picker (Files) or by dropping a file into the app's shared Documents folder.
  • Custom sounds are validated (audio format, ≤2 MB, ≤30 s), stored on-device, and not included in settings export.
  • Alarms referencing a missing/deleted custom sound fall back to a built-in.

Users can now import their own audio for alarm tones via the tone picker
(document picker, `.audio` UTType) or by dropping files into the app's
Documents folder from the Files app. Imported files are copied into
`Documents/CustomSounds/`, validated with AVAudioPlayer, and capped at
2 MB / 30 s.

SoundFile is now an enum with `.builtin(String)` and `.custom(UUID)`
cases. Built-in values encode as a bare string so existing stored alarms
keep loading; custom values encode as a keyed object. Static aliases
(`.indeed`, `.wrongAnswer`, …) preserve all existing call sites.

AlarmSound.setSoundFile now resolves built-in via the bundle and custom
via CustomSoundStore, and falls back to the default built-in with a log
when a file is missing (deleted custom sound, etc.) instead of crashing.
Validate files dropped into Documents in place before moving them into the
store, applying the same size, duration, and format checks as the in-app
importer. This prevents a user's file from being deleted when it fails the
audio check and stops oversized files from bypassing the caps.

Reset the alarm's sound to the fallback built-in when the selected custom
sound is deleted, and avoid rewriting the index when nothing changed.
Move the picked file into the store instead of copying when it already lives
in the app's shared Documents folder, so absorbDroppedFiles() doesn't re-ingest
the leftover original as a second entry. Validate before the file operation so a
rejected import never deletes the user's original.
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.

1 participant