+
@@ -127,14 +126,20 @@
-
+ ```
+
+ ---
+
+ ### JavaScript Логика
+
+ ```javascript
diff --git a/BookReader/Services/IDatabaseService.cs b/BookReader/Services/IDatabaseService.cs
index 99e659d..18a52e3 100644
--- a/BookReader/Services/IDatabaseService.cs
+++ b/BookReader/Services/IDatabaseService.cs
@@ -1,4 +1,6 @@
using BookReader.Models;
+using System.Net;
+using static Android.Provider.CallLog;
namespace BookReader.Services;
diff --git a/BookReader/ViewModels/ReaderViewModel.cs b/BookReader/ViewModels/ReaderViewModel.cs
index 899a319..5f9b0f3 100644
--- a/BookReader/ViewModels/ReaderViewModel.cs
+++ b/BookReader/ViewModels/ReaderViewModel.cs
@@ -39,13 +39,26 @@ public partial class ReaderViewModel : BaseViewModel
[ObservableProperty]
private int _chapterTotalPages = 1;
+ [ObservableProperty]
+ private int _currentPage = 1;
+
+ [ObservableProperty]
+ private int _totalPages = 1;
+
// Это свойство будет обновляться автоматически при изменении любого из полей выше
public string ChapterProgressText => $"{ChapterCurrentPage} из {ChapterTotalPages}";
+ // Это свойство будет обновляться автоматически при изменении любого из полей выше
+ public string ProgressText => $"{CurrentPage} из {TotalPages}";
+
// Чтобы ChapterProgressText уведомлял интерфейс, добавим частичные методы (особенность Toolkit)
partial void OnChapterCurrentPageChanged(int value) => OnPropertyChanged(nameof(ChapterProgressText));
partial void OnChapterTotalPagesChanged(int value) => OnPropertyChanged(nameof(ChapterProgressText));
+ // Чтобы ProgressText уведомлял интерфейс, добавим частичные методы (особенность Toolkit)
+ partial void OnCurrentPageChanged(int value) => OnPropertyChanged(nameof(ProgressText));
+ partial void OnTotalPagesChanged(int value) => OnPropertyChanged(nameof(ProgressText));
+
public List
AvailableFonts { get; } = new()
{
"serif",
@@ -130,6 +143,14 @@ public partial class ReaderViewModel : BaseViewModel
IsMenuVisible = false;
}
+ public async Task SaveLocationsAsync(string locations)
+ {
+ if (Book == null) return;
+ Book.Locations = locations;
+ // Сохраняем в базу данных
+ await _databaseService.UpdateBookAsync(Book);
+ }
+
public async Task SaveProgressAsync(double progress, string? cfi, string? chapter, int currentPage, int totalPages)
{
if (Book == null) return;
@@ -172,6 +193,11 @@ public partial class ReaderViewModel : BaseViewModel
return Book?.LastCfi;
}
+ public string? GetLocations()
+ {
+ return Book?.Locations;
+ }
+
private static string EscapeJs(string value)
{
return value.Replace("\\", "\\\\").Replace("'", "\\'").Replace("\n", "\\n").Replace("\r", "\\r");
diff --git a/BookReader/Views/ReaderPage.xaml b/BookReader/Views/ReaderPage.xaml
index f1cbc09..683eff9 100644
--- a/BookReader/Views/ReaderPage.xaml
+++ b/BookReader/Views/ReaderPage.xaml
@@ -23,7 +23,7 @@
@@ -33,10 +33,9 @@
VerticalOptions="Start"
HorizontalOptions="FillAndExpand"
Padding="20"
- HasShadow="True"
BorderColor="Transparent">
-
@@ -50,14 +49,11 @@
Clicked="OnBackToLibrary" />
-
-
+
@@ -159,7 +155,7 @@
Padding="10,2"
BorderColor="Transparent"
HasShadow="False">
-
diff --git a/BookReader/Views/ReaderPage.xaml.cs b/BookReader/Views/ReaderPage.xaml.cs
index 16ce375..4b5c18b 100644
--- a/BookReader/Views/ReaderPage.xaml.cs
+++ b/BookReader/Views/ReaderPage.xaml.cs
@@ -61,13 +61,11 @@ public partial class ReaderPage : ContentPage
var book = _viewModel.Book;
if (book == null)
{
- System.Diagnostics.Debug.WriteLine("[Reader] Book is null");
return;
}
if (_isBookLoaded)
{
- System.Diagnostics.Debug.WriteLine("[Reader] Already loaded");
return;
}
@@ -77,16 +75,13 @@ public partial class ReaderPage : ContentPage
return;
}
- System.Diagnostics.Debug.WriteLine($"[Reader] Loading: {book.Title} ({book.Format})");
- System.Diagnostics.Debug.WriteLine($"[Reader] Path: {book.FilePath}");
// Читаем файл и конвертируем в Base64
var fileBytes = await File.ReadAllBytesAsync(book.FilePath);
var base64 = Convert.ToBase64String(fileBytes);
var format = book.Format.ToLowerInvariant();
var lastCfi = _viewModel.GetLastCfi() ?? "";
-
- System.Diagnostics.Debug.WriteLine($"[Reader] File: {fileBytes.Length} bytes, Base64: {base64.Length} chars");
+ var locations=_viewModel.GetLocations() ?? "";
// Отправляем данные чанками чтобы не превысить лимит JS строки
const int chunkSize = 400_000;
@@ -94,25 +89,23 @@ public partial class ReaderPage : ContentPage
if (base64.Length > chunkSize)
{
var chunks = SplitString(base64, chunkSize);
- System.Diagnostics.Debug.WriteLine($"[Reader] Sending {chunks.Count} chunks");
await EvalJsAsync("window._bkChunks = [];");
for (int i = 0; i < chunks.Count; i++)
{
await EvalJsAsync($"window._bkChunks.push('{chunks[i]}');");
- System.Diagnostics.Debug.WriteLine($"[Reader] Chunk {i + 1}/{chunks.Count}");
}
await EvalJsAsync(
- $"window.loadBookFromBase64(window._bkChunks.join(''), '{format}', '{EscapeJs(lastCfi)}');"
+ $"window.loadBookFromBase64(window._bkChunks.join(''), '{format}', '{EscapeJs(lastCfi)}','{EscapeJs(locations)}');"
);
await EvalJsAsync("delete window._bkChunks;");
}
else
{
await EvalJsAsync(
- $"window.loadBookFromBase64('{base64}', '{format}', '{EscapeJs(lastCfi)}');"
+ $"window.loadBookFromBase64('{base64}', '{format}', '{EscapeJs(lastCfi)}','{EscapeJs(locations)}');"
);
}
@@ -143,9 +136,6 @@ public partial class ReaderPage : ContentPage
try
{
var result = await EvalJsWithResultAsync("window.getProgress()");
-
- System.Diagnostics.Debug.WriteLine($"[Reader] Progress raw: {result}");
-
if (string.IsNullOrEmpty(result) || result == "null" || result == "{}" || result == "undefined")
return;
@@ -183,7 +173,7 @@ public partial class ReaderPage : ContentPage
switch (action)
{
case "readerReady":
- System.Diagnostics.Debug.WriteLine("[Reader] JS is ready! Loading book...");
+
// Вызываем загрузку книги ТОЛЬКО после того, как JS подтвердил готовность
_ = MainThread.InvokeOnMainThreadAsync(LoadBookIntoWebView);
break;
@@ -211,6 +201,8 @@ public partial class ReaderPage : ContentPage
MainThread.BeginInvokeOnMainThread(() => {
_viewModel.ChapterCurrentPage = chapterPage;
_viewModel.ChapterTotalPages = chapterTotal;
+ _viewModel.TotalPages = totalPages;
+ _viewModel.CurrentPage = currentPage;
});
await _viewModel.SaveProgressAsync(progress, cfi, chapter, currentPage, totalPages);
}
@@ -233,11 +225,21 @@ public partial class ReaderPage : ContentPage
break;
case "bookReady":
- MainThread.BeginInvokeOnMainThread(async () =>
+ if (data != null)
{
- await EvalJsAsync($"window.setFontSize({_viewModel.FontSize})");
- await EvalJsAsync($"window.setFontFamily('{EscapeJs(_viewModel.FontFamily)}')");
- });
+ MainThread.BeginInvokeOnMainThread(async () =>
+ {
+ await EvalJsAsync($"window.setFontSize({_viewModel.FontSize})");
+ await EvalJsAsync($"window.setFontFamily('{EscapeJs(_viewModel.FontFamily)}')");
+ });
+ }
+ break;
+
+ case "saveLocations":
+ // Извлекаем строку локаций из данных
+ string locations = data["locations"]?.ToString();
+ // Сохраняем в базу данных
+ await _viewModel.SaveLocationsAsync(locations);
break;
}
}