qwen edit
This commit is contained in:
@@ -19,6 +19,12 @@ public partial class BookshelfViewModel : BaseViewModel
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _isEmpty;
|
private bool _isEmpty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isRefreshing;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _searchText = string.Empty;
|
||||||
|
|
||||||
public BookshelfViewModel(
|
public BookshelfViewModel(
|
||||||
IDatabaseService databaseService,
|
IDatabaseService databaseService,
|
||||||
IBookParserService bookParserService,
|
IBookParserService bookParserService,
|
||||||
@@ -43,6 +49,17 @@ public partial class BookshelfViewModel : BaseViewModel
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var books = await _databaseService.GetAllBooksAsync();
|
var books = await _databaseService.GetAllBooksAsync();
|
||||||
|
|
||||||
|
// Применяем фильтр поиска если есть
|
||||||
|
if (!string.IsNullOrWhiteSpace(SearchText))
|
||||||
|
{
|
||||||
|
var searchLower = SearchText.ToLowerInvariant();
|
||||||
|
books = books.Where(b =>
|
||||||
|
b.Title.ToLowerInvariant().Contains(searchLower) ||
|
||||||
|
b.Author.ToLowerInvariant().Contains(searchLower)
|
||||||
|
).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
Books.Clear();
|
Books.Clear();
|
||||||
foreach (var book in books)
|
foreach (var book in books)
|
||||||
{
|
{
|
||||||
@@ -60,6 +77,28 @@ public partial class BookshelfViewModel : BaseViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
public async Task RefreshBooksAsync()
|
||||||
|
{
|
||||||
|
if (IsRefreshing) return;
|
||||||
|
IsRefreshing = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await LoadBooksAsync();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsRefreshing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
public async Task SearchAsync()
|
||||||
|
{
|
||||||
|
await LoadBooksAsync();
|
||||||
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
public async Task AddBookFromFileAsync()
|
public async Task AddBookFromFileAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ public partial class CalibreLibraryViewModel : BaseViewModel
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string _downloadStatus = string.Empty;
|
private string _downloadStatus = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _isRefreshing;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _connectionErrorMessage = string.Empty;
|
||||||
|
|
||||||
private int _currentPage;
|
private int _currentPage;
|
||||||
|
|
||||||
public CalibreLibraryViewModel(
|
public CalibreLibraryViewModel(
|
||||||
@@ -67,6 +73,7 @@ public partial class CalibreLibraryViewModel : BaseViewModel
|
|||||||
if (IsBusy || !IsConfigured) return;
|
if (IsBusy || !IsConfigured) return;
|
||||||
IsBusy = true;
|
IsBusy = true;
|
||||||
_currentPage = 0;
|
_currentPage = 0;
|
||||||
|
ConnectionErrorMessage = string.Empty;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -79,7 +86,8 @@ public partial class CalibreLibraryViewModel : BaseViewModel
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await _navigationService.DisplayAlertAsync("Error", $"Failed to load library: {ex.Message}", "OK");
|
ConnectionErrorMessage = "No connection to Calibre server";
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error loading Calibre library: {ex.Message}");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -87,6 +95,22 @@ public partial class CalibreLibraryViewModel : BaseViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
public async Task RefreshBooksAsync()
|
||||||
|
{
|
||||||
|
if (IsRefreshing || !IsConfigured) return;
|
||||||
|
IsRefreshing = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await LoadBooksAsync();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsRefreshing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
public async Task LoadMoreBooksAsync()
|
public async Task LoadMoreBooksAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,10 +30,20 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Shell.TitleView>
|
</Shell.TitleView>
|
||||||
|
|
||||||
<Grid RowDefinitions="*,Auto" BackgroundColor="#3E2723">
|
<Grid RowDefinitions="Auto,*,Auto" BackgroundColor="#3E2723">
|
||||||
|
|
||||||
|
<!-- Search Bar -->
|
||||||
|
<SearchBar Grid.Row="0"
|
||||||
|
Text="{Binding SearchText}"
|
||||||
|
SearchCommand="{Binding SearchCommand}"
|
||||||
|
Placeholder="Search by title or author..."
|
||||||
|
PlaceholderColor="#A1887F"
|
||||||
|
TextColor="White"
|
||||||
|
BackgroundColor="#4E342E"
|
||||||
|
Margin="10,5" />
|
||||||
|
|
||||||
<!-- Bookshelf Background -->
|
<!-- Bookshelf Background -->
|
||||||
<Grid Grid.Row="0">
|
<Grid Grid.Row="1">
|
||||||
<!-- Empty state -->
|
<!-- Empty state -->
|
||||||
<VerticalStackLayout IsVisible="{Binding IsEmpty}"
|
<VerticalStackLayout IsVisible="{Binding IsEmpty}"
|
||||||
VerticalOptions="Center"
|
VerticalOptions="Center"
|
||||||
@@ -54,9 +64,11 @@
|
|||||||
HorizontalTextAlignment="Center" />
|
HorizontalTextAlignment="Center" />
|
||||||
</VerticalStackLayout>
|
</VerticalStackLayout>
|
||||||
|
|
||||||
<!-- Book Collection -->
|
<!-- Book Collection with PullToRefresh -->
|
||||||
|
<RefreshView Command="{Binding RefreshBooksCommand}"
|
||||||
|
IsRefreshing="{Binding IsRefreshing}"
|
||||||
|
IsVisible="{Binding IsEmpty, Converter={StaticResource InvertedBoolConverter}}">
|
||||||
<CollectionView ItemsSource="{Binding Books}"
|
<CollectionView ItemsSource="{Binding Books}"
|
||||||
IsVisible="{Binding IsEmpty, Converter={StaticResource InvertedBoolConverter}}"
|
|
||||||
SelectionMode="None"
|
SelectionMode="None"
|
||||||
Margin="10">
|
Margin="10">
|
||||||
|
|
||||||
@@ -144,6 +156,7 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</CollectionView.ItemTemplate>
|
</CollectionView.ItemTemplate>
|
||||||
</CollectionView>
|
</CollectionView>
|
||||||
|
</RefreshView>
|
||||||
|
|
||||||
<!-- Loading Indicator -->
|
<!-- Loading Indicator -->
|
||||||
<ActivityIndicator IsRunning="{Binding IsBusy}"
|
<ActivityIndicator IsRunning="{Binding IsBusy}"
|
||||||
@@ -156,7 +169,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Bottom Shelf / Action Bar -->
|
<!-- Bottom Shelf / Action Bar -->
|
||||||
<Grid Grid.Row="1"
|
<Grid Grid.Row="2"
|
||||||
BackgroundColor="#4E342E"
|
BackgroundColor="#4E342E"
|
||||||
Padding="15,10"
|
Padding="15,10"
|
||||||
ColumnDefinitions="*,Auto,Auto">
|
ColumnDefinitions="*,Auto,Auto">
|
||||||
|
|||||||
@@ -38,6 +38,32 @@
|
|||||||
HorizontalOptions="Center" />
|
HorizontalOptions="Center" />
|
||||||
</VerticalStackLayout>
|
</VerticalStackLayout>
|
||||||
|
|
||||||
|
<!-- Connection Error Message (Offline Mode) -->
|
||||||
|
<VerticalStackLayout Grid.Row="0"
|
||||||
|
IsVisible="{Binding IsConfigured}"
|
||||||
|
Padding="30"
|
||||||
|
Spacing="15"
|
||||||
|
VerticalOptions="Center">
|
||||||
|
<Label Text="⚠️ Connection failed"
|
||||||
|
FontSize="20"
|
||||||
|
TextColor="#FF7043"
|
||||||
|
HorizontalOptions="Center"
|
||||||
|
IsVisible="{Binding ConnectionErrorMessage, Converter={StaticResource IsNotNullOrEmptyConverter}}" />
|
||||||
|
<Label Text="{Binding ConnectionErrorMessage}"
|
||||||
|
FontSize="14"
|
||||||
|
TextColor="#B0B0B0"
|
||||||
|
HorizontalOptions="Center"
|
||||||
|
HorizontalTextAlignment="Center"
|
||||||
|
IsVisible="{Binding ConnectionErrorMessage, Converter={StaticResource IsNotNullOrEmptyConverter}}" />
|
||||||
|
<Button Text="🔄 Retry"
|
||||||
|
BackgroundColor="#5D4037"
|
||||||
|
TextColor="White"
|
||||||
|
CornerRadius="8"
|
||||||
|
Command="{Binding RefreshBooksCommand}"
|
||||||
|
HorizontalOptions="Center"
|
||||||
|
IsVisible="{Binding ConnectionErrorMessage, Converter={StaticResource IsNotNullOrEmptyConverter}}" />
|
||||||
|
</VerticalStackLayout>
|
||||||
|
|
||||||
<!-- Search Bar -->
|
<!-- Search Bar -->
|
||||||
<SearchBar Grid.Row="1"
|
<SearchBar Grid.Row="1"
|
||||||
IsVisible="{Binding IsConfigured}"
|
IsVisible="{Binding IsConfigured}"
|
||||||
@@ -49,9 +75,11 @@
|
|||||||
SearchCommand="{Binding SearchCommand}" />
|
SearchCommand="{Binding SearchCommand}" />
|
||||||
|
|
||||||
<!-- Book List -->
|
<!-- Book List -->
|
||||||
<CollectionView Grid.Row="2"
|
<RefreshView Grid.Row="2"
|
||||||
IsVisible="{Binding IsConfigured}"
|
IsVisible="{Binding ConnectionErrorMessage, Converter={StaticResource InvertedBoolConverter}}"
|
||||||
ItemsSource="{Binding Books}"
|
Command="{Binding RefreshBooksCommand}"
|
||||||
|
IsRefreshing="{Binding IsRefreshing}">
|
||||||
|
<CollectionView ItemsSource="{Binding Books}"
|
||||||
SelectionMode="None"
|
SelectionMode="None"
|
||||||
RemainingItemsThreshold="5"
|
RemainingItemsThreshold="5"
|
||||||
RemainingItemsThresholdReachedCommand="{Binding LoadMoreBooksCommand}">
|
RemainingItemsThresholdReachedCommand="{Binding LoadMoreBooksCommand}">
|
||||||
@@ -113,6 +141,7 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</CollectionView.ItemTemplate>
|
</CollectionView.ItemTemplate>
|
||||||
</CollectionView>
|
</CollectionView>
|
||||||
|
</RefreshView>
|
||||||
|
|
||||||
<!-- Status Bar -->
|
<!-- Status Bar -->
|
||||||
<Grid Grid.Row="3"
|
<Grid Grid.Row="3"
|
||||||
|
|||||||
Reference in New Issue
Block a user