Skip to content

Commit

Permalink
Add download buttons, custom titles option
Browse files Browse the repository at this point in the history
  • Loading branch information
jonbitgood committed Dec 19, 2024
1 parent 9ef543e commit b6e86e4
Show file tree
Hide file tree
Showing 7 changed files with 550 additions and 168 deletions.
7 changes: 2 additions & 5 deletions src/AudioPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { mergeClasses, mergeIcons, mergeArt } from "./AudioPlayerStyles.js";
import { loadProviders } from "./AudioPlayerProviders.js";
import { elem } from "./AudioPlayerHelpers.js";
import { createAudioElement } from "./AudioPlayerMedia.js";
import {
initBibleList,
handleBibleButtonClick,
initBookList,
} from "./AudioPlayerBibleList.js";
import { initBibleList, handleBibleButtonClick, initBookList } from "./AudioPlayerBibleList.js";
import { chapterList, handleBookChange, updateBookList } from "./AudioPlayerChapterList.js";

export default class AudioPlayer {
Expand All @@ -26,6 +22,7 @@ export default class AudioPlayer {
this.art = mergeArt(options.art);
this.results = [];
this.query = "";
this.titles = options?.titles ?? [];
this.view = "bible";
this.idPrefix = options?.idPrefix ?? "audio-player";
this.views = {
Expand Down
56 changes: 48 additions & 8 deletions src/AudioPlayerBibleList.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { elem } from './AudioPlayerHelpers.js'
import { fuzzySearch } from './AudioPlayerSearch.js';
import {selectBible, setCurrentChapter} from './AudioPlayerProviders.js'
import { updateCurrentBibleBlock, updateBookList, handleChapterChange, chapterList } from './AudioPlayerChapterList.js';
import { selectBible } from './AudioPlayerProviders.js'
import { updateCurrentBibleBlock, updateBookList } from './AudioPlayerChapterList.js';

export function initBibleList(ctx) {
ctx.bibleListContainer.innerHTML = '';
Expand Down Expand Up @@ -36,10 +36,10 @@ function updateBibleGrid(ctx) {
}

function createBibleButton(ctx, bible) {
const button = elem('button', {
className: ctx.class.bibleButton.wrapper,
onclick: () => handleBibleButtonClick(ctx, bible)
});
const buttonWrap = elem('div', {className: ctx.class.bibleButton.wrapper});

const button = elem('button', {className: ctx.class.bibleButton.button, onclick: () => handleBibleButtonClick(ctx, bible)});
buttonWrap.appendChild(button)
button.dataset.testId = bible.id;
button.setAttribute('aria-label', bible.tv ?? bible.tt);

Expand All @@ -61,10 +61,51 @@ function createBibleButton(ctx, bible) {
button.appendChild(bibleListButtonLanguage);
button.appendChild(bibleListButtonTitle);

return button;
if(bible.dl) {
const downloadButton = elem('button', {
className: ctx.class.bibleButton.download,
innerHTML: ctx.icons.download,
onclick:() => handleBibleDownload(ctx, bible)})
buttonWrap.appendChild(downloadButton)
}

return buttonWrap;
}

export async function handleBibleDownload(ctx, bible) {
try {
if (!bible.dl) {
console.log("Bible object does not contain a valid download URL");
return;
}
const dialog = elem('dialog', {className: ctx.class.bibleDownloadDialog.wrapper});
const message = elem("div", {innerHTML: ctx?.download_text ?? `<div class="text-sm max-w-sm"></div>`});
const copyright = elem("div", { innerHTML: `
<p class="${ctx.class.bibleDownloadDialog.audio_copyright}">${bible.audio_copyright}</p>
<p class="${ctx.class.bibleDownloadDialog.text_copyright}">${bible.text_copyright}</p>`
});
dialog.append(message, copyright);
const downloadButton = elem("button",{className: ctx.class.bibleDownloadDialog.button_download,textContent: `Download ${bible.dl_size ?? ''}`});
downloadButton.addEventListener("click", () => {
const anchor = document.body.appendChild(elem('a', { href: bible.dl, download: '' }));
anchor.click();
anchor.remove();
dialog.close();
dialog.remove();
});
dialog.appendChild(downloadButton);
const cancelButton = elem("button", {className: ctx.class.bibleDownloadDialog.cancel, textContent: "Cancel"});
cancelButton.addEventListener("click", () => {dialog.close();document.body.removeChild(dialog);});
dialog.appendChild(cancelButton);
document.body.appendChild(dialog);
dialog.showModal();
} catch (error) {
console.error("An error occurred while trying to display the dialog:", error);
}
}

export async function handleBibleButtonClick(ctx, bible) {

if (bible.tp === "hark") {
ctx.view = "book";
ctx.currentBible = bible;
Expand All @@ -79,7 +120,6 @@ export async function handleBibleButtonClick(ctx, bible) {
}
}


export function initBookList(ctx) {
const searchInput = elem('input', {
type: 'search',
Expand Down
14 changes: 11 additions & 3 deletions src/AudioPlayerHelpers.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
export function elem(tag, props = {}) {
const el = document.createElement(tag);

for (const [key, val] of Object.entries(props)) {
if (key === 'style' && typeof val === 'object') {
Object.assign(el.style, val);
} else {
el[key] = val;
}
}

return el;
}

Expand All @@ -21,4 +19,14 @@ export function formatTime(timeInSeconds) {
export const parseTimestampToSeconds = (timestampStr) => {
const [hours, minutes, seconds] = timestampStr.split(':');
return (parseInt(hours, 10) * 3600) + (parseInt(minutes, 10) * 60) + parseFloat(seconds);
};
}

HTMLDialogElement.prototype.triggerShow = HTMLDialogElement.prototype.showModal;
HTMLDialogElement.prototype.showModal = function() {
this.triggerShow();
this.onclick = event => {
let rect = this.getBoundingClientRect();
if(event.clientY < rect.top || event.clientY > rect.bottom) return this.close();
if(event.clientX < rect.left || event.clientX > rect.right) return this.close();
}
}
58 changes: 13 additions & 45 deletions src/AudioPlayerProviders.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,53 +13,22 @@ export async function loadProviders(player) {
player.bibles = player.bibles.concat(await providerFunctions[provider]());
}
}
}

export async function harkList(country_id = 'all', provider = 'all') {
const baseBibles = await fetch(`${BASE_API_URL}/api/bibles`).then(response => response.json());
let bibles = await fetch(`${BASE_CONTENT_URL}/bibles/audio-new/index.txt`).then(response => response.text());

let output = [];

bibles = bibles.split('\n');
let unmatchedBibles = [];
bibles.forEach(bible => {
let bible_id = bible.split('_')[0];
if (bible_id.includes('-')) {
bible_id = bible.split('-')[0];
}
let found = false;

for (let i = 0; i < baseBibles.length; i++) {
const baseBible = baseBibles[i];
if (bible_id === baseBible.id) {
output.push({
id: bible,
abbr: baseBible.id,
iso: baseBible.iso,
ln: baseBible.ln,
tt: baseBible.tt,
tv: baseBible.tv,
ci: baseBible.ci,
cn: baseBible.cn,
tp: "hark"
});
found = true;
break; // Exit loop once match is found
}
for (let i = 0; i < player.bibles.length; i++) {
let customTitle = player.titles[player.bibles[i].id];
if(customTitle) {
player.bibles[i].tt = customTitle.tt;
player.bibles[i].tv = customTitle.tv;
}

if (!found) {
unmatchedBibles.push(bible_id); // Add unmatched bible_id to array
}
});

if (unmatchedBibles.length > 0) {
//console.log("Unmatched bible_ids:", unmatchedBibles);
} else {
//console.log("All bible_ids matched in output.");
}
}

export async function harkList(country_id = 'all', provider = 'all') {
const bibles = await fetch(`${BASE_CONTENT_URL}/bibles/audio-new/index.json`).then(response => response.json());
const output = bibles.map(bible => ({
...bible,
tp: "hark",
dl: (bible.dl) ? `${BASE_CONTENT_URL}/bibles/audio-new/${bible.id}.zip` : ""
}));
if (country_id !== 'all') {
output = output.filter(bible => bible.ci === country_id);
}
Expand Down Expand Up @@ -130,7 +99,6 @@ export async function harkSelect(id) {
}

export async function dbpList(country_id) {

let initial_path = `https://4.dbt.io/api/bibles?v=4&key=${key}&media=audio`;
if (country_id) {
initial_path += '&country=' + country_id;
Expand Down
Loading

0 comments on commit b6e86e4

Please sign in to comment.