- Added offline detection logic with `OfflineContext` to improve app functionality in offline scenarios. - Integrated Tauri IPC functions to handle local tool settings and character attributes when offline. - Refined indentation logic in `TextEditor` for better compatibility with WebKit engines. - Removed unused `indent` property and related settings in editor components to simplify configuration. - Updated locale files with improved translation consistency and parameterized placeholders.
64 lines
2.5 KiB
TypeScript
64 lines
2.5 KiB
TypeScript
import React from "react";
|
|
import {isDesktop} from '@/lib/configs';
|
|
import {BookProps} from "@/lib/types/book";
|
|
import DeleteBook from "@/components/book/settings/DeleteBook";
|
|
import SyncBook from "@/components/SyncBook";
|
|
import {SyncType} from "@/context/BooksSyncContext";
|
|
import {useTranslations} from '@/lib/i18n';
|
|
|
|
interface BookCardProps {
|
|
book: BookProps;
|
|
onClickCallback: (bookId: string) => void;
|
|
index: number;
|
|
syncStatus?: SyncType;
|
|
}
|
|
|
|
export default function BookCard({book, onClickCallback, index, syncStatus}: BookCardProps) {
|
|
const t = useTranslations();
|
|
|
|
return (
|
|
<div
|
|
onClick={(): void => onClickCallback(book.bookId)}
|
|
className="group relative aspect-[2/3] rounded-xl overflow-hidden cursor-pointer transition-all duration-300 hover:ring-1 hover:ring-text-primary/20">
|
|
{book.coverImage ? (
|
|
<img
|
|
src={book.coverImage}
|
|
alt={book.title || t("bookCard.noCoverAlt")}
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
) : (
|
|
<div className="w-full h-full bg-secondary flex items-center justify-center">
|
|
<span className="text-muted text-5xl font-['ADLaM_Display']">
|
|
{book.title.charAt(0).toUpperCase()}
|
|
</span>
|
|
</div>
|
|
)}
|
|
|
|
{isDesktop && syncStatus && (
|
|
<div className="absolute top-2 left-2 cursor-default" onClick={(e: React.MouseEvent): void => e.stopPropagation()}>
|
|
<SyncBook status={syncStatus} bookId={book.bookId}/>
|
|
</div>
|
|
)}
|
|
|
|
<div className="absolute inset-x-0 bottom-0 bg-darkest-background/70 p-3">
|
|
<h3 className="text-text-primary font-bold text-sm truncate">
|
|
{book.title}
|
|
</h3>
|
|
{book.subTitle && (
|
|
<p className="text-text-secondary text-xs truncate mt-0.5">
|
|
{book.subTitle}
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
<div
|
|
className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
|
|
onClick={(e: React.MouseEvent): void => e.stopPropagation()}
|
|
{...(index === 0 && {'data-guide': 'bottom-book-card'})}
|
|
>
|
|
<DeleteBook bookId={book.bookId}/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|