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:
2025-09-30 08:23:22 +00:00
parent 44831a096f
commit fee36dfdad
7 changed files with 424 additions and 178 deletions

View File

@@ -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))
}
}