edit
This commit is contained in:
@@ -154,6 +154,7 @@
|
||||
isBookLoaded: false,
|
||||
fb2CurrentPage: 0,
|
||||
fb2TotalPages: 1,
|
||||
toc: []
|
||||
};
|
||||
|
||||
// ========== УТИЛИТЫ ==========
|
||||
@@ -287,16 +288,17 @@
|
||||
|
||||
try {
|
||||
const toc = state.book.navigation.toc || [];
|
||||
const chapters = toc.map(ch => ({
|
||||
state.toc = toc.map(ch => ({
|
||||
label: (ch.label || '').trim(),
|
||||
href: ch.href || ''
|
||||
}));
|
||||
sendMessage('chaptersLoaded', { chapters });
|
||||
sendMessage('chaptersLoaded', { chapters: state.toc });
|
||||
} catch (e) {
|
||||
debugLog('TOC error: ' + e.message);
|
||||
}
|
||||
const charsPerScreen = Math.max(600, Math.floor((window.innerWidth * window.innerHeight) / 400));
|
||||
|
||||
return state.book.locations.generate(1600);
|
||||
return state.book.locations.generate(charsPerScreen);
|
||||
})
|
||||
.then(() => {
|
||||
state.totalPages = state.book.locations.length();
|
||||
@@ -309,13 +311,29 @@
|
||||
state.rendition.on('relocated', location => {
|
||||
if (!location || !location.start) return;
|
||||
state.currentCfi = location.start.cfi;
|
||||
// 1. Достаем страницы ВНУТРИ главы
|
||||
// Если epub.js не успел посчитать (бывает на долю секунды), ставим 1
|
||||
const chapterPage = location.start.displayed ? location.start.displayed.page : 1;
|
||||
const chapterTotal = location.start.displayed ? location.start.displayed.total : 1;
|
||||
|
||||
// 2. Ищем красивое название главы по её href
|
||||
const currentHref = location.start.href || '';
|
||||
let chapterName = currentHref; // По умолчанию системное имя
|
||||
|
||||
// Пытаемся найти точное совпадение в сохраненном оглавлении
|
||||
const foundChapter = state.toc.find(ch => currentHref.includes(ch.href));
|
||||
if (foundChapter) {
|
||||
chapterName = foundChapter.label;
|
||||
}
|
||||
try {
|
||||
sendMessage('progressUpdate', {
|
||||
progress: state.book.locations.percentageFromCfi(state.currentCfi) || 0,
|
||||
cfi: state.currentCfi,
|
||||
currentPage: location.start.location || 0,
|
||||
totalPages: state.totalPages,
|
||||
chapter: location.start.href || ''
|
||||
currentPage: location.start.location || 0, // Глобальная страница
|
||||
totalPages: state.totalPages, // Всего глобальных страниц
|
||||
chapterCurrentPage: chapterPage, // <--- Страница в главе!
|
||||
chapterTotalPages: chapterTotal, // <--- Всего страниц в главе!
|
||||
chapter: chapterName // <--- Красивое имя главы
|
||||
});
|
||||
} catch (e) {
|
||||
debugLog('Relocated error: ' + e.message);
|
||||
|
||||
@@ -33,6 +33,19 @@ public partial class ReaderViewModel : BaseViewModel
|
||||
[ObservableProperty]
|
||||
private string? _selectedChapter;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _chapterCurrentPage = 1;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _chapterTotalPages = 1;
|
||||
|
||||
// Это свойство будет обновляться автоматически при изменении любого из полей выше
|
||||
public string ChapterProgressText => $"{ChapterCurrentPage} из {ChapterTotalPages}";
|
||||
|
||||
// Чтобы ChapterProgressText уведомлял интерфейс, добавим частичные методы (особенность Toolkit)
|
||||
partial void OnChapterCurrentPageChanged(int value) => OnPropertyChanged(nameof(ChapterProgressText));
|
||||
partial void OnChapterTotalPagesChanged(int value) => OnPropertyChanged(nameof(ChapterProgressText));
|
||||
|
||||
public List<string> AvailableFonts { get; } = new()
|
||||
{
|
||||
"serif",
|
||||
|
||||
@@ -20,6 +20,21 @@
|
||||
DefaultFile="index.html"
|
||||
HorizontalOptions="Fill"
|
||||
VerticalOptions="Fill" />
|
||||
<VerticalStackLayout VerticalOptions="End"
|
||||
HorizontalOptions="Center"
|
||||
Padding="10"
|
||||
InputTransparent="True">
|
||||
<Frame BackgroundColor="#AA000000"
|
||||
CornerRadius="15"
|
||||
Padding="10,2"
|
||||
BorderColor="Transparent"
|
||||
HasShadow="False">
|
||||
<Label Text="{Binding ChapterProgressText}"
|
||||
TextColor="White"
|
||||
FontSize="12"
|
||||
HorizontalTextAlignment="Center" />
|
||||
</Frame>
|
||||
</VerticalStackLayout>
|
||||
|
||||
<!-- Overlay Menu -->
|
||||
<Grid IsVisible="{Binding IsMenuVisible}"
|
||||
|
||||
@@ -18,10 +18,6 @@ public partial class ReaderPage : ContentPage
|
||||
_viewModel = viewModel;
|
||||
BindingContext = viewModel;
|
||||
_viewModel.OnJavaScriptRequested += OnJavaScriptRequested;
|
||||
//Microsoft.Maui.Controls.Application.Current.Deactivated += async (s, e) =>
|
||||
//{
|
||||
// if (_isActive) await SaveCurrentProgress();
|
||||
//};
|
||||
}
|
||||
|
||||
protected override async void OnAppearing()
|
||||
@@ -207,6 +203,15 @@ public partial class ReaderPage : ContentPage
|
||||
var chapter = data["chapter"]?.ToString();
|
||||
var currentPage = data["currentPage"]?.Value<int>() ?? 0;
|
||||
var totalPages = data["totalPages"]?.Value<int>() ?? 0;
|
||||
|
||||
// Ловим новые данные по главе
|
||||
var chapterPage = data["chapterCurrentPage"]?.Value<int>() ?? 1;
|
||||
var chapterTotal = data["chapterTotalPages"]?.Value<int>() ?? 1;
|
||||
// Обновляем ViewModel на главном потоке
|
||||
MainThread.BeginInvokeOnMainThread(() => {
|
||||
_viewModel.ChapterCurrentPage = chapterPage;
|
||||
_viewModel.ChapterTotalPages = chapterTotal;
|
||||
});
|
||||
await _viewModel.SaveProgressAsync(progress, cfi, chapter, currentPage, totalPages);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user