Skip to content

Commit 0b7e162

Browse files
committed
feat: Major UI improvements and feature enhancements
- Removed scrollbar from footnotes container, made it expandable - Updated Bible translation names in settings for clarity - Fixed reference Bible translation setting visibility - Made dark/light mode button responsive for mobile - Eliminated horizontal scrollbar when sidebar collapsed - Fixed sidebar collapse toggle stickiness issue - Resolved text concatenation in BSB by fixing line break handling - Removed all PDF functionality (kept download links, added more translations) - Added chapter title header support - Added audio Bible support for BSB translation
1 parent 896e7b4 commit 0b7e162

26 files changed

Lines changed: 949 additions & 1816 deletions

dev_tools/Minify-JS.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ $fileMappings = @(
1111
@{ Source = "../src/modules/api.js"; Destination = "../www/modules/api.js" },
1212
@{ Source = "../src/modules/navigation.js"; Destination = "../www/modules/navigation.js" },
1313
@{ Source = "../src/modules/passage.js"; Destination = "../www/modules/passage.js" },
14-
@{ Source = "../src/modules/pdf.js"; Destination = "../www/modules/pdf.js" },
1514
@{ Source = "../src/modules/settings.js"; Destination = "../www/modules/settings.js" },
1615
@{ Source = "../src/modules/state.js"; Destination = "../www/modules/state.js" },
1716
@{ Source = "../src/modules/strongs.js"; Destination = "../www/modules/strongs.js" },

index.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

main.js

Lines changed: 51 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import {
2-
getCurrentTranslation,
2+
playChapterAudio,
3+
pauseChapterAudio,
4+
resumeChapterAudio,
5+
stopChapterAudio
6+
} from './modules/api.js';
7+
import {
38
initBookChapterControls,
49
loadSelectedChapter,
510
navigateFromURL,
@@ -14,17 +19,6 @@ import {
1419
scrollToVerse,
1520
setupFootnoteHandlers
1621
} from './modules/passage.js'
17-
import {
18-
clearSearch,
19-
currentSearch,
20-
handlePDFUpload,
21-
navigateToSearchResult,
22-
renderPage,
23-
searchPDF,
24-
setupPDFCleanup,
25-
updateCustomPdfInfo,
26-
updatePDFZoom
27-
} from './modules/pdf.js'
2822
import {
2923
clearCache,
3024
closeSettings,
@@ -41,8 +35,7 @@ import {
4135
loadFromStorage,
4236
saveToCookies,
4337
saveToStorage,
44-
state,
45-
updateURL
38+
state
4639
} from './modules/state.js'
4740
import { closeStrongsPopup } from './modules/strongs.js'
4841
import {
@@ -60,10 +53,6 @@ import {
6053
updateMarkdownPreview,
6154
updateReferencePanel
6255
} from './modules/ui.js'
63-
if (typeof pdfjsLib !== 'undefined') {
64-
pdfjsLib.GlobalWorkerOptions.workerSrc =
65-
'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
66-
}
6756
if (typeof marked !== 'undefined') {
6857
marked.setOptions({
6958
breaks: true,
@@ -117,20 +106,46 @@ function setupEventListeners() {
117106
.addEventListener('click', nextPassage);
118107
document.getElementById('randomPassageBtn')
119108
.addEventListener('click', randomPassage);
109+
const playBtn = document.querySelector('.play-audio-btn');
110+
const pauseBtn = document.querySelector('.pause-audio-btn');
111+
const stopBtn = document.querySelector('.stop-audio-btn');
112+
const narratorSelect = document.querySelector('.narrator-select');
113+
if (playBtn) {
114+
playBtn.addEventListener('click', () => {
115+
if (state.audioPlayer?.isPaused) {
116+
resumeChapterAudio();
117+
} else if (state.audioPlayer?.isPlaying) {
118+
pauseChapterAudio();
119+
} else {
120+
const narrator = narratorSelect?.value || state.settings.audioNarrator || 'gilbert';
121+
playChapterAudio(narrator);
122+
}
123+
});
124+
}
125+
if (pauseBtn) {
126+
pauseBtn.addEventListener('click', pauseChapterAudio);
127+
}
128+
if (stopBtn) {
129+
stopBtn.addEventListener('click', stopChapterAudio);
130+
}
131+
if (narratorSelect) {
132+
narratorSelect.addEventListener('change', (e) => {
133+
const newNarrator = e.target.value;
134+
state.settings.audioNarrator = newNarrator;
135+
saveToStorage();
136+
if (state.audioPlayer) {
137+
stopChapterAudio();
138+
}
139+
playChapterAudio(newNarrator);
140+
});
141+
}
120142
document.getElementById('referencePanelToggle')
121143
.addEventListener('click', toggleReferencePanel);
122144
document.querySelectorAll('.sidebar-section-header')
123145
.forEach(h => h.addEventListener('click', () => {
124146
const sec = h.dataset.section;
125147
toggleSection(sec);
126148
}));
127-
document.getElementById('referenceTranslation').addEventListener('change', function() {
128-
const tempTranslation = this.value;
129-
const oldTranslation = state.settings.referenceVersion;
130-
state.settings.referenceVersion = tempTranslation;
131-
updateBibleGatewayVersion();
132-
state.settings.referenceVersion = oldTranslation;
133-
});
134149
document.addEventListener('DOMContentLoaded', makeToggleSticky);
135150
document.querySelectorAll('.collapse-toggle')
136151
.forEach(btn => btn.addEventListener('click', function () {
@@ -139,86 +154,18 @@ function setupEventListeners() {
139154
}));
140155
document.getElementById('referenceSource')
141156
.addEventListener('change', updateReferencePanel);
142-
document.getElementById('referenceTranslation')
143-
.addEventListener('change', updateReferencePanel);
144-
document.querySelector('.reference-panel-close')
145-
.addEventListener('click', toggleReferencePanel);
146-
document.getElementById('prevPage').addEventListener('click', async () => {
147-
if (!state.pdf.doc || state.pdf.currentPage <= 1) return;
148-
try {
149-
if (state.pdf.renderTask) {
150-
await state.pdf.renderTask.cancel();
151-
state.pdf.renderTask = null;
152-
}
153-
state.pdf.currentPage--;
154-
await renderPage(state.pdf.currentPage);
155-
} catch (err) {
156-
console.warn('Error navigating to previous page:', err);
157-
await loadPDF();
158-
}
159-
});
160-
document.getElementById('nextPage').addEventListener('click', async () => {
161-
if (!state.pdf.doc || state.pdf.currentPage >= state.pdf.doc.numPages) return;
162-
try {
163-
if (state.pdf.renderTask) {
164-
await state.pdf.renderTask.cancel();
165-
state.pdf.renderTask = null;
166-
}
167-
state.pdf.currentPage++;
168-
await renderPage(state.pdf.currentPage);
169-
} catch (err) {
170-
console.warn('Error navigating to next page:', err);
171-
await loadPDF();
172-
}
173-
});
174-
document.getElementById('pageInput').addEventListener('change', async () => {
175-
if (!state.pdf.doc) {
176-
document.getElementById('pageInput').value = state.pdf.currentPage;
177-
return;
178-
}
179-
const inp = document.getElementById('pageInput');
180-
let p = parseInt(inp.value, 10);
181-
if (Number.isNaN(p)) {
182-
inp.value = state.pdf.currentPage;
183-
return;
184-
}
185-
p = Math.max(1, Math.min(p, state.pdf.doc.numPages));
186-
try {
187-
state.pdf.currentPage = p;
188-
await renderPage(p);
189-
} catch (err) {
190-
console.warn('Error navigating to page:', err);
191-
inp.value = state.pdf.currentPage;
192-
await loadPDF();
157+
document.getElementById('referenceTranslation').addEventListener('change', function() {
158+
state.settings.referenceVersion = this.value;
159+
updateBibleGatewayVersion();
160+
saveToStorage();
161+
const settingsDropdown = document.getElementById('referenceVersionSetting');
162+
if (settingsDropdown) {
163+
settingsDropdown.value = this.value;
193164
}
165+
updateReferencePanel();
194166
});
195-
document.getElementById('zoomIn').addEventListener('click', () => {
196-
if (!state.pdf.doc) return;
197-
const newZoom = Math.min(state.pdf.zoomLevel + 0.25, 3.0);
198-
updatePDFZoom(newZoom);
199-
});
200-
document.getElementById('zoomOut').addEventListener('click', () => {
201-
if (!state.pdf.doc) return;
202-
const newZoom = Math.max(state.pdf.zoomLevel - 0.25, 0.5);
203-
updatePDFZoom(newZoom);
204-
});
205-
document.getElementById('pdfSearchBtn').addEventListener('click', searchPDF);
206-
document.getElementById('pdfSearchInput').addEventListener('keypress', (e) => {
207-
if (e.key === 'Enter') searchPDF();
208-
});
209-
document.getElementById('clearSearchBtn').addEventListener('click', clearSearch);
210-
const nextSearchBtn = document.getElementById('nextSearchResult');
211-
const prevSearchBtn = document.getElementById('prevSearchResult');
212-
if (nextSearchBtn) {
213-
nextSearchBtn.addEventListener('click', () => {
214-
navigateToSearchResult(currentSearch.currentResult + 1);
215-
});
216-
}
217-
if (prevSearchBtn) {
218-
prevSearchBtn.addEventListener('click', () => {
219-
navigateToSearchResult(currentSearch.currentResult - 1);
220-
});
221-
}
167+
document.querySelector('.reference-panel-close')
168+
.addEventListener('click', toggleReferencePanel);
222169
document.getElementById('notesInput')
223170
.addEventListener('input', e => {
224171
state.notes = e.target.value;
@@ -288,12 +235,6 @@ function setupEventListeners() {
288235
.addEventListener('click', clearCache);
289236
document.getElementById('deleteAllDataBtn')
290237
.addEventListener('click', deleteAllData);
291-
document.getElementById('settingsPdfUploadBtn')
292-
.addEventListener('click', () => {
293-
document.getElementById('settingsPdfUpload').click();
294-
});
295-
document.getElementById('settingsPdfUpload')
296-
.addEventListener('change', handlePDFUpload);
297238
document.querySelectorAll('.color-theme-option')
298239
.forEach(opt => opt.addEventListener('click', () => {
299240
const theme = opt.dataset.theme;
@@ -316,34 +257,6 @@ function setupEventListeners() {
316257
}
317258
});
318259
}
319-
export function arrayBufferToBase64(buf) {
320-
let binary = '';
321-
const bytes = new Uint8Array(buf);
322-
const chunk = 0x8000;
323-
for (let i = 0; i < bytes.length; i += chunk) {
324-
binary += String.fromCharCode.apply(
325-
null,
326-
Array.from(bytes.subarray(i, i + chunk))
327-
);
328-
}
329-
return btoa(binary);
330-
}
331-
export function base64ToArrayBuffer(b64) {
332-
const bin = atob(b64);
333-
const arr = new Uint8Array(bin.length);
334-
for (let i = 0; i < bin.length; i++) {
335-
arr[i] = bin.charCodeAt(i);
336-
}
337-
return arr.buffer;
338-
}
339-
export function readFileAsArrayBuffer(file) {
340-
return new Promise((resolve, reject) => {
341-
const r = new FileReader();
342-
r.onload = e => resolve(e.target.result);
343-
r.onerror = () => reject(new Error('Failed to read file'));
344-
r.readAsArrayBuffer(file);
345-
});
346-
}
347260
export function showLoading(flag) {
348261
document.getElementById('loadingOverlay').classList.toggle('active', flag);
349262
}
@@ -550,8 +463,6 @@ function navigateToHighlightedVerse(reference) {
550463
const [, book, chapter, verse] = match;
551464
state.settings.manualBook = book;
552465
state.settings.manualChapter = parseInt(chapter);
553-
const translation = getCurrentTranslation();
554-
updateURL(translation, book, chapter);
555466
loadSelectedChapter(book, chapter);
556467
setTimeout(() => scrollToVerse(verse), 500);
557468
}
@@ -589,9 +500,9 @@ function refreshHighlightsModalTheme() {
589500
}
590501
}
591502
async function init() {
503+
console.log('Initializing app...');
592504
await loadFromStorage();
593505
loadFromCookies();
594-
setupPDFCleanup();
595506
const style = document.createElement('style');
596507
style.textContent = offlineStyles;
597508
document.head.appendChild(style);
@@ -608,27 +519,10 @@ async function init() {
608519
restorePanelStates();
609520
updateDateTime();
610521
initResizeHandles();
611-
updateCustomPdfInfo();
612522
switchNotesView(state.settings.notesView || 'text');
613523
updateBibleGatewayVersion();
614524
setupEventListeners();
615525
setInterval(updateDateTime, 1_000);
616-
const navigatedFromURL = navigateFromURL();
617-
if (!navigatedFromURL) {
618-
if (window.location.pathname !== '/') {
619-
const defaultParams = {
620-
translation: 'BSB',
621-
book: 'Genesis',
622-
chapter: 1
623-
};
624-
window.history.replaceState(
625-
defaultParams,
626-
'',
627-
`?p=bsb/gen/1`
628-
);
629-
loadPassage();
630-
}
631-
}
632526
console.log('App initialized successfully');
633527
}
634528
if (document.readyState === 'loading') {

0 commit comments

Comments
 (0)