Add bilingual action to book menu
This commit is contained in:
@@ -69,6 +69,7 @@
|
||||
"Imported {{count}} annotations_one": "Imported {{count}} annotation",
|
||||
"Imported {{count}} annotations_other": "Imported {{count}} annotations",
|
||||
"Recently read": "Recently read",
|
||||
"Bilingual": "Bilingual",
|
||||
"Show recently read": "Show recently read",
|
||||
"Your books will appear here": "Your books will appear here",
|
||||
"{{count}} results_one": "{{count}} result",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"Apply": "应用",
|
||||
"Auto Mode": "自动主题",
|
||||
"Behavior": "行为",
|
||||
"Bilingual": "双语拆分",
|
||||
"Book": "书籍",
|
||||
"Bookmark": "书签",
|
||||
"Cancel": "取消",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"Apply": "應用",
|
||||
"Auto Mode": "自動主題",
|
||||
"Behavior": "行為",
|
||||
"Bilingual": "雙語拆分",
|
||||
"Book": "書籍",
|
||||
"Bookmark": "書籤",
|
||||
"Cancel": "取消",
|
||||
|
||||
@@ -205,6 +205,7 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
const [showStatusAlert, setShowStatusAlert] = useState(false);
|
||||
const [showGroupingModal, setShowGroupingModal] = useState(false);
|
||||
const [showBilingualFilterAlert, setShowBilingualFilterAlert] = useState(false);
|
||||
const [bilingualFilterBook, setBilingualFilterBook] = useState<Book | null>(null);
|
||||
const [bilingualFilterProcessing, setBilingualFilterProcessing] = useState(false);
|
||||
const [importBookUrl] = useState(searchParams?.get('url') || '');
|
||||
|
||||
@@ -468,18 +469,37 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
const showBilingualFilterSelection = () => {
|
||||
const book = getSingleSelectedBook();
|
||||
if (!book || book.format !== 'EPUB') return;
|
||||
setBilingualFilterBook(null);
|
||||
setShowSelectModeActions(false);
|
||||
setShowBilingualFilterAlert(true);
|
||||
};
|
||||
|
||||
const showBilingualFilterBook = useCallback(
|
||||
(book: Book) => {
|
||||
if (book.format !== 'EPUB') {
|
||||
eventDispatcher.dispatch('toast', {
|
||||
type: 'warning',
|
||||
message: _('Only EPUB books can be filtered'),
|
||||
timeout: 2500,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setBilingualFilterBook(book);
|
||||
setShowSelectModeActions(false);
|
||||
setShowBilingualFilterAlert(true);
|
||||
},
|
||||
[_],
|
||||
);
|
||||
|
||||
const closeBilingualFilterSelection = () => {
|
||||
if (bilingualFilterProcessing) return;
|
||||
setShowBilingualFilterAlert(false);
|
||||
setShowSelectModeActions(true);
|
||||
setBilingualFilterBook(null);
|
||||
if (isSelectMode) setShowSelectModeActions(true);
|
||||
};
|
||||
|
||||
const runBilingualFilter = async (options: BilingualFilterOptions) => {
|
||||
const book = getSingleSelectedBook();
|
||||
const book = bilingualFilterBook ?? getSingleSelectedBook();
|
||||
if (!book || !appService) return;
|
||||
if (book.format !== 'EPUB') {
|
||||
eventDispatcher.dispatch('toast', {
|
||||
@@ -515,6 +535,7 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
await updateBooks(envConfig, [importedBook]);
|
||||
handlePushLibrary();
|
||||
setSelectedBooks([]);
|
||||
setBilingualFilterBook(null);
|
||||
setShowBilingualFilterAlert(false);
|
||||
handleSetSelectMode(false);
|
||||
eventDispatcher.dispatch('toast', {
|
||||
@@ -536,8 +557,9 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
message: _('Failed to filter bilingual EPUB'),
|
||||
timeout: 3000,
|
||||
});
|
||||
setBilingualFilterBook(null);
|
||||
setShowBilingualFilterAlert(false);
|
||||
setShowSelectModeActions(true);
|
||||
if (isSelectMode) setShowSelectModeActions(true);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setBilingualFilterProcessing(false);
|
||||
@@ -888,6 +910,7 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
handleBookDelete={handleBookDelete}
|
||||
handleSetSelectMode={handleSetSelectMode}
|
||||
handleShowDetailsBook={handleShowDetailsBook}
|
||||
handleBilingualFilterBook={showBilingualFilterBook}
|
||||
handleLibraryNavigation={handleLibraryNavigation}
|
||||
handleUpdateReadingStatus={handleUpdateReadingStatus}
|
||||
transferProgress={
|
||||
@@ -913,6 +936,7 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
handleBookDelete,
|
||||
handleSetSelectMode,
|
||||
handleShowDetailsBook,
|
||||
showBilingualFilterBook,
|
||||
handleLibraryNavigation,
|
||||
handleUpdateReadingStatus,
|
||||
],
|
||||
@@ -993,9 +1017,9 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
bilingualFilterEnabled={bilingualFilterEnabled}
|
||||
/>
|
||||
)}
|
||||
{showBilingualFilterAlert && selectedBilingualBook && (
|
||||
{showBilingualFilterAlert && (bilingualFilterBook || selectedBilingualBook) && (
|
||||
<BilingualFilterAlert
|
||||
bookTitle={selectedBilingualBook.title}
|
||||
bookTitle={(bilingualFilterBook || selectedBilingualBook)?.title || ''}
|
||||
safeAreaBottom={safeAreaInsets?.bottom || 0}
|
||||
processing={bilingualFilterProcessing}
|
||||
onCancel={closeBilingualFilterSelection}
|
||||
|
||||
@@ -117,6 +117,7 @@ interface BookshelfItemProps {
|
||||
handleBookDelete: (book: Book, syncBooks?: boolean) => Promise<boolean>;
|
||||
handleSetSelectMode: (selectMode: boolean) => void;
|
||||
handleShowDetailsBook: (book: Book) => void;
|
||||
handleBilingualFilterBook: (book: Book) => void;
|
||||
handleLibraryNavigation: (targetGroup: string) => void;
|
||||
handleUpdateReadingStatus: (book: Book, status: ReadingStatus | undefined) => void;
|
||||
}
|
||||
@@ -135,6 +136,7 @@ const BookshelfItem: React.FC<BookshelfItemProps> = ({
|
||||
handleBookDownload,
|
||||
handleSetSelectMode,
|
||||
handleShowDetailsBook,
|
||||
handleBilingualFilterBook,
|
||||
handleLibraryNavigation,
|
||||
handleUpdateReadingStatus,
|
||||
}) => {
|
||||
@@ -228,6 +230,12 @@ const BookshelfItem: React.FC<BookshelfItemProps> = ({
|
||||
showBookDetailsModal(book);
|
||||
},
|
||||
},
|
||||
bilingual: {
|
||||
text: _('Bilingual'),
|
||||
action: async () => {
|
||||
handleBilingualFilterBook(book);
|
||||
},
|
||||
},
|
||||
showInFinder: {
|
||||
text: _(fileRevealLabel),
|
||||
action: async () => {
|
||||
@@ -366,6 +374,7 @@ const BookshelfItem: React.FC<BookshelfItemProps> = ({
|
||||
appService?.isMobileApp,
|
||||
handleBookDownload,
|
||||
handleBookUpload,
|
||||
handleBilingualFilterBook,
|
||||
handleGroupBooks,
|
||||
handleSetSelectMode,
|
||||
handleUpdateReadingStatus,
|
||||
|
||||
@@ -651,6 +651,7 @@ export type BookContextMenuItemId =
|
||||
| 'markAbandoned'
|
||||
| 'clearStatus'
|
||||
| 'showDetails'
|
||||
| 'bilingual'
|
||||
| 'showInFinder'
|
||||
| 'searchGoodreads'
|
||||
| 'download'
|
||||
@@ -750,7 +751,9 @@ export const getBookContextMenuItemIds = (book: Book): BookContextMenuItemId[] =
|
||||
) {
|
||||
ids.push('clearStatus');
|
||||
}
|
||||
ids.push('showDetails', 'showInFinder', 'searchGoodreads');
|
||||
ids.push('showDetails');
|
||||
if (book.format === 'EPUB') ids.push('bilingual');
|
||||
ids.push('showInFinder', 'searchGoodreads');
|
||||
if (book.uploadedAt && !book.downloadedAt) ids.push('download');
|
||||
if (!book.uploadedAt && book.downloadedAt) ids.push('upload');
|
||||
// Share is offered for any local-or-uploaded book; the dialog uploads first
|
||||
|
||||
Reference in New Issue
Block a user