-
-
Notifications
You must be signed in to change notification settings - Fork 38
Implement audio download #1069
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
TheNonPirate
wants to merge
25
commits into
sillsdev:main
Choose a base branch
from
TheNonPirate:feature/download-audio-offline/1036
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Implement audio download #1069
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
6a2e76c
Make Audio Download modal
TheNonPirate 17e95d2
Create DB of downloaded audio files
TheNonPirate 35fa5ef
Implement audio downloading
TheNonPirate 37e661e
Change when it asks for download to match native
TheNonPirate ff66c98
Create audio download loading screen
TheNonPirate b4e8cd1
Minor tweaks
TheNonPirate 50ab0ec
Switch to storing audio using service worker cache
TheNonPirate 0c4d570
Revert "Switch to storing audio using service worker cache"
TheNonPirate dd121a2
Cause audio to not play while downloading
TheNonPirate e05d7e4
Fix error with audioclips DB naming
TheNonPirate b49bb11
Fix lint errors
TheNonPirate bce2349
Download audio as stream that can be cancelled
TheNonPirate e1999fd
Fix TypeScript error
TheNonPirate dbd302a
Minor fixes
TheNonPirate a46d9d3
Fix Modal styling bug
TheNonPirate d0fdb85
Various tweaks
TheNonPirate 619bd4c
Update AudioDownloadModal styling
TheNonPirate 72c8ecc
Move audio clips DB into a separate file
TheNonPirate f27690c
Replace audio URL map with MRUCache
TheNonPirate 74c1ff1
Move checkAudioAvailability to audio.ts
TheNonPirate eaf96d4
Minor lint fix
TheNonPirate 79db6c3
Implement Bible Brain audio download
TheNonPirate cd6a377
Minor tweaks
TheNonPirate 5358dc3
Fix bug with audio stuck playing wrong chapter
TheNonPirate f63f92d
Minor tweak
TheNonPirate File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| <!-- | ||
| @component | ||
| Audio Download Modal Dialog component. | ||
| --> | ||
|
|
||
| <script lang="ts"> | ||
| import { updateAudioPlayer } from '$lib/data/audio'; | ||
| import { addAudioClip } from '$lib/data/audioclipsDB'; | ||
| import { refs, t, userSettings } from '$lib/data/stores'; | ||
| import { CheckboxIcon, CheckboxOutlineIcon } from '$lib/icons'; | ||
| import { tick } from 'svelte'; | ||
| import Modal from './Modal.svelte'; | ||
| const modalId = 'audioDownloadModal'; | ||
| let modal: Modal | undefined = $state(undefined); | ||
| let downloadAutomatically: boolean = $state(false); | ||
| let audioUrl: string = ''; | ||
| let error = $state(''); | ||
| export function showModal(url: string) { | ||
| audioUrl = url; | ||
| modal?.showModal(); | ||
| } | ||
| export async function downloadAudio(url: string) { | ||
| try { | ||
| if (downloadAutomatically) { | ||
| $userSettings['audio-auto-download'] = 'auto'; | ||
| } | ||
| downloadProgress = 1; | ||
| abortController = new AbortController(); | ||
| let addedAudioClip = await addAudioClip( | ||
| { | ||
| docSet: $refs.docSet, | ||
| collection: $refs.collection, | ||
| book: $refs.book, | ||
| chapter: $refs.chapter | ||
| }, | ||
| url, | ||
| abortController, | ||
| (percent) => { | ||
| tick().then(() => (downloadProgress = percent)); | ||
| } | ||
| ); | ||
| downloadProgress = 0; | ||
| if (!addedAudioClip) { | ||
| return false; | ||
| } | ||
| updateAudioPlayer($refs); | ||
| return addedAudioClip; | ||
| } catch (err) { | ||
| console.error('Error downloading audio: ', err); | ||
| return false; | ||
| } | ||
| } | ||
| async function finishModal() { | ||
| const addedAudioClip = await downloadAudio(audioUrl); | ||
| if (!addedAudioClip && !abortController?.signal.aborted) { | ||
| error = 'Audio clip could not be downloaded'; | ||
| setTimeout(() => { | ||
| error = ''; | ||
| }, 2000); | ||
| return false; | ||
| } | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| let downloadProgress = $state(0); | ||
| let abortController: AbortController | undefined = undefined; | ||
| let audioDownloadingMessage = $derived( | ||
| $t['Audio_Downloading'] | ||
| .replace('%book', $refs.name || $refs.book) | ||
| .replace('%chapter', $refs.chapter) | ||
| ); | ||
| </script> | ||
|
|
||
| <Modal bind:this={modal} id={modalId}> | ||
| <div id="container" class="message"> | ||
| <div class="message-body" id="message-body"> | ||
| <div class="message-header"></div> | ||
| <div class="message-title"> | ||
| {$t['Audio_Download_Title']} | ||
| </div> | ||
| <div class="message-text"> | ||
| {$t['Audio_Download_Confirm']} | ||
| </div> | ||
| <!-- svelte-ignore a11y_click_events_have_key_events --> | ||
| <!-- svelte-ignore a11y_no_static_element_interactions --> | ||
| <div | ||
| class="message-checkbox flex w-full" | ||
| onclick={() => { | ||
| downloadAutomatically = !downloadAutomatically; | ||
| }} | ||
| > | ||
| <div class="message-checkbox-left"> | ||
| {#if downloadAutomatically} | ||
| <CheckboxIcon></CheckboxIcon> | ||
| {:else} | ||
| <CheckboxOutlineIcon></CheckboxOutlineIcon> | ||
| {/if} | ||
| </div> | ||
| <div class="message-checkbox-caption">{$t['Audio_Download_Auto']}</div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div class="left-0 dy-modal-action message-footer pointer-events-none"> | ||
| <div class="message-buttons"> | ||
| <button class="dy-btn message-button pointer-events-auto" id="no"> | ||
| {$t['Button_No']} | ||
| </button> | ||
|
TheNonPirate marked this conversation as resolved.
|
||
| <button | ||
| class="dy-btn message-button pointer-events-auto" | ||
| id="yes" | ||
| onclick={() => finishModal()} | ||
| > | ||
| {$t['Button_Yes']} | ||
| </button> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </Modal> | ||
| {#if error} | ||
| <div class="absolute inset-0 flex items-center justify-center z-50 pointer-events-none"> | ||
| <div | ||
| class="dy-modal-box overflow-y-visible relative opacity-100 text-red-500 text-center pointer-events-auto" | ||
| > | ||
| {error} | ||
| </div> | ||
| </div> | ||
| {/if} | ||
| {#if downloadProgress > 0} | ||
| <div class="fixed inset-0 bg-black/50 backdrop-blur-xs flex items-center justify-center z-50"> | ||
| <div class="message" id="container"> | ||
| <div class="w-70 md:w-100 message-body"> | ||
| <div class="message-header h-5"></div> | ||
| <div class="message-title">{$t['Audio_Download_Title']}</div> | ||
| <div class="message-text">{audioDownloadingMessage}</div> | ||
|
|
||
| <div | ||
| class="message-progress" | ||
| style="padding-left: 20px; padding-right: 20px; padding-top: 20px; padding-bottom: 20px;" | ||
| > | ||
| <div class="w-full h-1 dy-progress bg-[#e4e4e4]"> | ||
| <div class="h-full bg-black" style="width: {downloadProgress}%"></div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| <div class="flex justify-end"> | ||
| <button | ||
| class="dy-btn dy-btn-sm message-button" | ||
| onclick={() => { | ||
| downloadProgress = 0; | ||
| abortController?.abort(); | ||
| }}>{$t['Button_Cancel']}</button | ||
| > | ||
| </div> | ||
| </div> | ||
| </div> | ||
| {/if} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooh. Not in this PR, but you may want to look into adding AbortController to some of the non-audio downloads (i.e. Verse-on-Image)