diff --git a/BookReader/Resources/Raw/wwwroot/index.html b/BookReader/Resources/Raw/wwwroot/index.html index b86587c..ee44ead 100644 --- a/BookReader/Resources/Raw/wwwroot/index.html +++ b/BookReader/Resources/Raw/wwwroot/index.html @@ -1,4 +1,4 @@ - + @@ -154,12 +154,12 @@ rendition: null, // Объект отображения epub.js currentCfi: null, // Текущая позиция (идентификатор) в EPUB totalPages: 0, // Всего страниц - currentPage: 0, // Текущая страница bookFormat: '', // epub или fb2 isBookLoaded: false, fb2CurrentPage: 0, fb2TotalPages: 1, - toc: [] // Оглавление + toc: [], // Оглавление + lastCfi: null // Последний CFI }; // ========== УТИЛИТЫ ========== @@ -284,6 +284,7 @@ if (typeof ePub === 'undefined') { showError('epub.js not loaded!'); return; } state.book = ePub(arrayBuffer); // Создание объекта книги из данных + state.lastCfi = null; els.fb2Content.style.display = 'none'; els.bookContent.style.display = 'block'; @@ -322,15 +323,17 @@ debugLog("Загрузка из кэша..."); state.book.locations.load(cachedLocations); state.totalPages = state.book.locations.length(); + state.lastCfi = null; sendMessage('bookReady', { totalPages: state.totalPages }); } else { // Используем setTimeout, чтобы не блокировать поток отрисовки const dynamicSize = calculateOptimalLocationSize(); // Запускаем генерацию с динамическим размером setTimeout(() => { - state.book.locations.generate(dynamicSize).then(() => { + state.book.locations.generate(1000).then(() => { state.totalPages = state.book.locations.length(); const locationsToSave = state.book.locations.save(); + state.lastCfi = null; // Отправляем в C#, чтобы сохранить на будущее sendMessage('saveLocations', { locations: locationsToSave }); @@ -343,7 +346,13 @@ // Событие при смене страницы state.rendition.on('relocated', location => { if (!location || !location.start) return; - state.currentCfi = location.start.cfi; + const newCfi = location.start.cfi; + + // Получаем процент прогресса + const progress = state.book.locations.percentageFromCfi(newCfi) || 0; + + // Обновляем lastCfi + state.lastCfi = newCfi; const chapterPage = location.start.displayed ? location.start.displayed.page : 1; const chapterTotal = location.start.displayed ? location.start.displayed.total : 1; @@ -355,11 +364,12 @@ if (foundChapter) chapterName = foundChapter.label; // Отправка прогресса в приложение + // currentPage теперь показывает процент (округлённый до целого) sendMessage('progressUpdate', { - progress: state.book.locations.percentageFromCfi(state.currentCfi) || 0, - cfi: state.currentCfi, - currentPage: location.start.location || 0, - totalPages: state.totalPages, + progress: progress, + cfi: newCfi, + currentPage: Math.round(progress * 100), // Процент вместо номера страницы + totalPages: 100, // 100% chapterCurrentPage: chapterPage, chapterTotalPages: chapterTotal, chapter: chapterName @@ -387,6 +397,7 @@ xmlText = new TextDecoder(encMatch[1]).decode(bytes); } + state.lastCfi = null; els.bookContent.style.display = 'none'; els.fb2Content.style.display = 'block'; @@ -597,7 +608,9 @@ }; window.nextPage = function () { // Листать вперед - if (state.bookFormat === 'epub' && state.rendition) state.rendition.next(); + if (state.bookFormat === 'epub' && state.rendition) { + state.rendition.next(); + } else if (state.bookFormat === 'fb2' && state.fb2CurrentPage < state.fb2TotalPages - 1) { showFb2Page(state.fb2CurrentPage + 1); updateFb2Progress(); @@ -605,7 +618,9 @@ }; window.prevPage = function () { // Листать назад - if (state.bookFormat === 'epub' && state.rendition) state.rendition.prev(); + if (state.bookFormat === 'epub' && state.rendition) { + state.rendition.prev(); + } else if (state.bookFormat === 'fb2' && state.fb2CurrentPage > 0) { showFb2Page(state.fb2CurrentPage - 1); updateFb2Progress(); @@ -673,4 +688,4 @@ })(); - \ No newline at end of file + diff --git a/BookReader/ViewModels/ReaderViewModel.cs b/BookReader/ViewModels/ReaderViewModel.cs index 629590f..b196d15 100644 --- a/BookReader/ViewModels/ReaderViewModel.cs +++ b/BookReader/ViewModels/ReaderViewModel.cs @@ -46,17 +46,11 @@ public partial class ReaderViewModel : BaseViewModel [ObservableProperty] private int _totalPages = 1; - [ObservableProperty] - private bool _isLocationsLoaded; - // Это свойство будет обновляться автоматически при изменении любого из полей выше public string ChapterProgressText => $"{ChapterCurrentPage} из {ChapterTotalPages}"; - // Это свойство будет обновляться автоматически при изменении любого из полей выше - // Пока страницы не посчитаны, показываем 0% - public string ProgressText => !_isLocationsLoaded || TotalPages <= 0 - ? "0%" - : $"{CurrentPage} из {TotalPages}"; + // Это свойство показывает процент прогресса + public string ProgressText => $"{CurrentPage}%"; // Чтобы ChapterProgressText уведомлял интерфейс, добавим частичные методы (особенность Toolkit) partial void OnChapterCurrentPageChanged(int value) => OnPropertyChanged(nameof(ChapterProgressText)); @@ -65,7 +59,6 @@ public partial class ReaderViewModel : BaseViewModel // Чтобы ProgressText уведомлял интерфейс, добавим частичные методы (особенность Toolkit) partial void OnCurrentPageChanged(int value) => OnPropertyChanged(nameof(ProgressText)); partial void OnTotalPagesChanged(int value) => OnPropertyChanged(nameof(ProgressText)); - partial void OnIsLocationsLoadedChanged(bool value) => OnPropertyChanged(nameof(ProgressText)); public List AvailableFonts { get; } = new() { @@ -116,25 +109,6 @@ public partial class ReaderViewModel : BaseViewModel return; } - // Проверяем, есть ли сохранённые локации (кэш) - var hasCachedLocations = !string.IsNullOrEmpty(Book.Locations); - - // Если есть кэш - сразу показываем реальный прогресс - IsLocationsLoaded = hasCachedLocations; - - // Если есть кэш - восстанавливаем прогресс из книги - if (hasCachedLocations) - { - CurrentPage = Book.CurrentPage > 0 ? Book.CurrentPage : 0; - TotalPages = Book.TotalPages > 0 ? Book.TotalPages : 0; - } - else - { - // Сбрасываем прогресс в 0% пока идёт подсчёт страниц - CurrentPage = 0; - TotalPages = 0; - } - var savedFontSize = await _settingsService.GetIntAsync(SettingsKeys.DefaultFontSize, Constants.Reader.DefaultFontSize); var savedFontFamily = await _settingsService.GetAsync(SettingsKeys.DefaultFontFamily, "serif"); @@ -197,13 +171,6 @@ public partial class ReaderViewModel : BaseViewModel } Book.Locations = locations; await _databaseService.UpdateBookAsync(Book); - - // Локации сохранены - теперь показываем реальный прогресс - // (если ещё не был показан из кэша) - if (!IsLocationsLoaded) - { - IsLocationsLoaded = true; - } } public async Task SaveProgressAsync(double progress, string? cfi, string? chapter, int currentPage, int totalPages) diff --git a/BookReader/Views/BookshelfPage.xaml b/BookReader/Views/BookshelfPage.xaml index a326bb7..c56d37d 100644 --- a/BookReader/Views/BookshelfPage.xaml +++ b/BookReader/Views/BookshelfPage.xaml @@ -16,7 +16,7 @@