feat: improve Bible reader UX with dropdown menu and enhanced offline features
- Replace three separate verse action icons with compact three-dot dropdown menu - Bookmark, Copy Verse, and Ask AI now in a single menu - Better space utilization on mobile, tablet, and desktop - Enhance offline Bible downloads UI - Move downloaded versions list to top for better visibility - Add inline progress bars during downloads - Show real-time download progress with chapter counts - Add refresh button for downloaded versions list - Remove duplicate header, keep only main header with online/offline status - Improve build performance - Add .eslintignore to speed up linting phase - Already excludes large directories (bibles/, scripts/, csv_bibles/) - Add debug logging for offline storage operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -125,10 +125,12 @@ class OfflineStorage {
|
||||
|
||||
async getAllVersions(): Promise<BibleVersion[]> {
|
||||
await this.init()
|
||||
return this.performTransaction('versions', 'readonly', (store) => {
|
||||
const versions = await this.performTransaction('versions', 'readonly', (store) => {
|
||||
const versionsStore = store as IDBObjectStore
|
||||
return versionsStore.getAll()
|
||||
})
|
||||
console.log('[OfflineStorage] getAllVersions result:', versions)
|
||||
return versions
|
||||
}
|
||||
|
||||
async deleteVersion(versionId: string): Promise<void> {
|
||||
@@ -409,6 +411,10 @@ export class BibleDownloadManager {
|
||||
}
|
||||
|
||||
const versionData = await versionResponse.json()
|
||||
if (!versionData.success) {
|
||||
throw new Error(versionData.error || 'Failed to fetch version books')
|
||||
}
|
||||
|
||||
const { version, books } = versionData
|
||||
|
||||
progress.totalBooks = books.length
|
||||
@@ -416,10 +422,11 @@ export class BibleDownloadManager {
|
||||
onProgress?.(progress)
|
||||
|
||||
// Save version info
|
||||
console.log('[Download] Saving version info:', version)
|
||||
await offlineStorage.saveVersion(version)
|
||||
|
||||
// Calculate total chapters
|
||||
progress.totalChapters = books.reduce((sum: number, book: any) => sum + book.chaptersCount, 0)
|
||||
// Calculate total chapters from the chapters array in each book
|
||||
progress.totalChapters = books.reduce((sum: number, book: any) => sum + (book.chapters?.length || 0), 0)
|
||||
await offlineStorage.saveDownloadProgress(progress)
|
||||
onProgress?.(progress)
|
||||
|
||||
@@ -427,26 +434,48 @@ export class BibleDownloadManager {
|
||||
for (const book of books) {
|
||||
console.log(`[Download] Downloading book: ${book.name}`)
|
||||
|
||||
await offlineStorage.saveBook(versionId, book)
|
||||
// Map the book data to match our interface
|
||||
const bookData = {
|
||||
id: book.id,
|
||||
name: book.name,
|
||||
abbreviation: book.bookKey,
|
||||
orderNum: book.orderNum,
|
||||
testament: book.testament,
|
||||
chaptersCount: book.chapters?.length || 0
|
||||
}
|
||||
|
||||
await offlineStorage.saveBook(versionId, bookData)
|
||||
progress.downloadedBooks++
|
||||
|
||||
// Download all chapters for this book
|
||||
for (let chapterNum = 1; chapterNum <= book.chaptersCount; chapterNum++) {
|
||||
const chapterResponse = await fetch(`/api/bible/chapter?book=${book.id}&chapter=${chapterNum}&version=${versionId}`)
|
||||
if (book.chapters) {
|
||||
for (const chapterInfo of book.chapters) {
|
||||
const chapterResponse = await fetch(`/api/bible/chapter?book=${book.id}&chapter=${chapterInfo.chapterNum}&version=${versionId}`)
|
||||
|
||||
if (chapterResponse.ok) {
|
||||
const chapterData = await chapterResponse.json()
|
||||
await offlineStorage.saveChapter(versionId, book.id, chapterData.chapter)
|
||||
if (chapterResponse.ok) {
|
||||
const chapterData = await chapterResponse.json()
|
||||
if (chapterData.chapter) {
|
||||
// Map the chapter data to match our interface
|
||||
const mappedChapter = {
|
||||
id: chapterData.chapter.id,
|
||||
bookId: book.id,
|
||||
chapterNum: chapterData.chapter.chapterNum,
|
||||
verseCount: chapterData.chapter.verses.length,
|
||||
verses: chapterData.chapter.verses
|
||||
}
|
||||
await offlineStorage.saveChapter(versionId, book.id, mappedChapter)
|
||||
}
|
||||
}
|
||||
|
||||
progress.downloadedChapters++
|
||||
progress.progress = Math.round((progress.downloadedChapters / progress.totalChapters) * 100)
|
||||
|
||||
await offlineStorage.saveDownloadProgress(progress)
|
||||
onProgress?.(progress)
|
||||
|
||||
// Small delay to prevent overwhelming the API
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
}
|
||||
|
||||
progress.downloadedChapters++
|
||||
progress.progress = Math.round((progress.downloadedChapters / progress.totalChapters) * 100)
|
||||
|
||||
await offlineStorage.saveDownloadProgress(progress)
|
||||
onProgress?.(progress)
|
||||
|
||||
// Small delay to prevent overwhelming the API
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user