diff --git a/public/assets/styles/blue.css b/public/assets/styles/blue.css
index ded4cd02..3651dda7 100644
--- a/public/assets/styles/blue.css
+++ b/public/assets/styles/blue.css
@@ -4,7 +4,6 @@
.delete-dialog-comfirm,
.book-item-config,
.book-cover-item-config,
-.side-menu-selector-container,
.download-desk-button,
.edit-dialog-comfirm,
.change-location-button,
diff --git a/public/assets/styles/dark.css b/public/assets/styles/dark.css
index 5654f483..011de038 100644
--- a/public/assets/styles/dark.css
+++ b/public/assets/styles/dark.css
@@ -62,7 +62,6 @@ body,
.delete-dialog-comfirm,
.book-item-config,
.book-cover-item-config,
-.side-menu-selector-container,
.download-desk-button,
.edit-dialog-comfirm,
.change-location-button,
diff --git a/public/assets/styles/default.css b/public/assets/styles/default.css
index f86b1e8b..b59fb738 100644
--- a/public/assets/styles/default.css
+++ b/public/assets/styles/default.css
@@ -76,7 +76,6 @@ body,
.delete-dialog-comfirm,
.book-item-config,
.book-cover-item-config,
-.side-menu-selector-container,
.download-desk-button,
.edit-dialog-comfirm,
.change-location-button,
diff --git a/public/assets/styles/green.css b/public/assets/styles/green.css
index e5072f7a..1b9827af 100644
--- a/public/assets/styles/green.css
+++ b/public/assets/styles/green.css
@@ -4,7 +4,6 @@
.delete-dialog-comfirm,
.book-item-config,
.book-cover-item-config,
-.side-menu-selector-container,
.download-desk-button,
.edit-dialog-comfirm,
.change-location-button,
diff --git a/public/assets/styles/purple.css b/public/assets/styles/purple.css
index b93893ae..0314f22b 100644
--- a/public/assets/styles/purple.css
+++ b/public/assets/styles/purple.css
@@ -4,7 +4,6 @@
.delete-dialog-comfirm,
.book-item-config,
.book-cover-item-config,
-.side-menu-selector-container,
.download-desk-button,
.edit-dialog-comfirm,
.change-location-button,
diff --git a/public/assets/styles/red.css b/public/assets/styles/red.css
index 65648cfa..adfe35cf 100644
--- a/public/assets/styles/red.css
+++ b/public/assets/styles/red.css
@@ -13,7 +13,6 @@
.update-dialog-container-button,
.import-from-local,
.single-control-switch,
-.side-menu-selector-container,
.previous-chapter-single-container,
.next-chapter-single-container,
.book-bookmark-link,
diff --git a/src/assets/locales/cn/translation.json b/src/assets/locales/cn/translation.json
index 0076f2e1..efffcaa8 100644
--- a/src/assets/locales/cn/translation.json
+++ b/src/assets/locales/cn/translation.json
@@ -350,9 +350,10 @@
"Chinese Conversion": "繁简转换",
"Don't use first page as PDF cover": "不使用 PDF 首页作为封面",
"Don't crop book cover": "不裁剪图书封面",
- "Add to favorite": "添加到喜爱",
- "Remove from favorite": "从喜爱移除",
+ "Add to Favorite": "添加到喜爱",
+ "Remove from Favorite": "从喜爱移除",
"Details": "详细信息",
+ "Multiple Select": "多选",
"You may see this error when the book you're importing is not supported by Koodo Reader, try converting it with Calibre": "暂不支持此图书,请尝试使用 Calibre 转化之后重新导入",
"Shelf title can't be pure number": "书架名不能是纯数字",
"Open Console": "打开控制台",
diff --git a/src/assets/locales/en/translation.json b/src/assets/locales/en/translation.json
index 4943394e..6cf64321 100644
--- a/src/assets/locales/en/translation.json
+++ b/src/assets/locales/en/translation.json
@@ -128,6 +128,7 @@
"Add to favorite": "Add to favorite",
"Remove from favorite": "Remove from favorite",
"Details": "Details",
+ "Multiple Select": "Multiple Select",
"You may see this error when the book you're importing is not supported by Koodo Reader, try converting it with Calibre": "You may see this error when the book you're importing is not supported by Koodo Reader, try converting it with Calibre",
"Simplified To Traditional": "Simplified To Traditional",
"Traditional To Simplified": "Traditional To Simplified",
diff --git a/src/assets/styles/fonts/icomoon.eot b/src/assets/styles/fonts/icomoon.eot
index c1909b54..290881b9 100644
Binary files a/src/assets/styles/fonts/icomoon.eot and b/src/assets/styles/fonts/icomoon.eot differ
diff --git a/src/assets/styles/fonts/icomoon.svg b/src/assets/styles/fonts/icomoon.svg
index 5fb7b239..0f0205dd 100644
--- a/src/assets/styles/fonts/icomoon.svg
+++ b/src/assets/styles/fonts/icomoon.svg
@@ -74,4 +74,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/styles/fonts/icomoon.ttf b/src/assets/styles/fonts/icomoon.ttf
index edd948ff..01af9d2c 100644
Binary files a/src/assets/styles/fonts/icomoon.ttf and b/src/assets/styles/fonts/icomoon.ttf differ
diff --git a/src/assets/styles/fonts/icomoon.woff b/src/assets/styles/fonts/icomoon.woff
index 5834b3fb..892bdbea 100644
Binary files a/src/assets/styles/fonts/icomoon.woff and b/src/assets/styles/fonts/icomoon.woff differ
diff --git a/src/assets/styles/style.css b/src/assets/styles/style.css
index ffa9e29e..aac06ab6 100644
--- a/src/assets/styles/style.css
+++ b/src/assets/styles/style.css
@@ -1,10 +1,10 @@
@font-face {
font-family: 'icomoon';
- src: url('fonts/icomoon.eot?o3qvp2');
- src: url('fonts/icomoon.eot?o3qvp2#iefix') format('embedded-opentype'),
- url('fonts/icomoon.ttf?o3qvp2') format('truetype'),
- url('fonts/icomoon.woff?o3qvp2') format('woff'),
- url('fonts/icomoon.svg?o3qvp2#icomoon') format('svg');
+ src: url('fonts/icomoon.eot?43s8j0');
+ src: url('fonts/icomoon.eot?43s8j0#iefix') format('embedded-opentype'),
+ url('fonts/icomoon.ttf?43s8j0') format('truetype'),
+ url('fonts/icomoon.woff?43s8j0') format('woff'),
+ url('fonts/icomoon.svg?43s8j0#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
@@ -25,6 +25,39 @@
-moz-osx-font-smoothing: grayscale;
}
+.icon-bookshelf-line:before {
+ content: "\e94b";
+}
+.icon-highlight-line:before {
+ content: "\e94c";
+}
+.icon-select:before {
+ content: "\e94d";
+}
+.icon-trash-line:before {
+ content: "\e943";
+}
+.icon-detail:before {
+ content: "\e944";
+}
+.icon-bookshelf:before {
+ content: "\e945";
+}
+.icon-edit-line:before {
+ content: "\e946";
+}
+.icon-address-book:before {
+ content: "\e947";
+}
+.icon-idea-line:before {
+ content: "\e948";
+}
+.icon-heart:before {
+ content: "\e949";
+}
+.icon-home-line:before {
+ content: "\e94a";
+}
.icon-day:before {
content: "\e936";
}
diff --git a/src/components/dialogs/actionDialog/component.tsx b/src/components/dialogs/actionDialog/component.tsx
index 805a9253..b7c8dd08 100644
--- a/src/components/dialogs/actionDialog/component.tsx
+++ b/src/components/dialogs/actionDialog/component.tsx
@@ -55,6 +55,11 @@ class ActionDialog extends React.Component<
toast.success(this.props.t("Add Successfully"));
this.props.handleActionDialog(false);
};
+ handleMultiSelect = () => {
+ this.props.handleSelectBook(true);
+ this.props.handleSelectedBooks([this.props.currentBook.key]);
+ this.props.handleActionDialog(false);
+ };
handleCancelLoveBook = () => {
AddFavorite.clear(this.props.currentBook.key);
if (
@@ -125,14 +130,14 @@ class ActionDialog extends React.Component<
}
}}
>
-
+
{AddFavorite.getAllFavorite().indexOf(
this.props.currentBook.key
) > -1 ? (
- Remove from favorite
+ Remove from Favorite
) : (
- Add to favorite
+ Add to Favorite
)}
@@ -142,18 +147,29 @@ class ActionDialog extends React.Component<
this.handleAddShelf();
}}
>
-
+
Add to Shelf
+ {
+ this.handleMultiSelect();
+ }}
+ >
+
+
+ Multiple Select
+
+
{
this.handleDeleteBook();
}}
>
-
+
Delete
@@ -164,7 +180,7 @@ class ActionDialog extends React.Component<
this.handleEditBook();
}}
>
-
+
Edit
@@ -176,10 +192,10 @@ class ActionDialog extends React.Component<
}}
>
-
+
Details
@@ -206,8 +222,10 @@ class ActionDialog extends React.Component<
className="icon-more view-icon"
style={{
display: "inline-block",
- marginRight: "15px",
+ marginRight: "12px",
+ marginLeft: "3px",
transform: "rotate(90deg)",
+ fontSize: "12px",
}}
>
More Actions
diff --git a/src/components/dialogs/actionDialog/index.tsx b/src/components/dialogs/actionDialog/index.tsx
index 0a8d89c0..00c8495d 100644
--- a/src/components/dialogs/actionDialog/index.tsx
+++ b/src/components/dialogs/actionDialog/index.tsx
@@ -2,7 +2,9 @@ import { connect } from "react-redux";
import {
handleEditDialog,
handleDeleteDialog,
+ handleSelectBook,
handleAddDialog,
+ handleSelectedBooks,
handleActionDialog,
handleReadingBook,
handleFetchBooks,
@@ -19,6 +21,8 @@ const mapStateToProps = (state: stateType) => {
currentBook: state.book.currentBook,
books: state.manager.books,
notes: state.reader.notes,
+ isSelectBook: state.manager.isSelectBook,
+
deletedBooks: state.manager.deletedBooks,
};
};
@@ -30,6 +34,8 @@ const actionCreator = {
handleActionDialog,
handleFetchBooks,
handleDetailDialog,
+ handleSelectBook,
+ handleSelectedBooks,
};
export default connect(
mapStateToProps,
diff --git a/src/components/dialogs/actionDialog/interface.tsx b/src/components/dialogs/actionDialog/interface.tsx
index b33bee5c..3894ed5d 100644
--- a/src/components/dialogs/actionDialog/interface.tsx
+++ b/src/components/dialogs/actionDialog/interface.tsx
@@ -11,6 +11,8 @@ export interface ActionDialogProps extends RouteComponentProps {
left: number;
top: number;
mode: string;
+ isSelectBook: boolean;
+
handleFetchBooks: () => void;
handleDeleteDialog: (isShow: boolean) => void;
handleFetchBookmarks: () => void;
@@ -21,6 +23,8 @@ export interface ActionDialogProps extends RouteComponentProps {
handleAddDialog: (isShow: boolean) => void;
handleActionDialog: (isShow: boolean) => void;
handleDetailDialog: (isShow: boolean) => void;
+ handleSelectBook: (isSelectBook: boolean) => void;
+ handleSelectedBooks: (selectedBooks: string[]) => void;
}
export interface ActionDialogState {
isShowExport: boolean;
diff --git a/src/components/selectBook/component.tsx b/src/components/selectBook/component.tsx
index d7a9f697..31f4d039 100644
--- a/src/components/selectBook/component.tsx
+++ b/src/components/selectBook/component.tsx
@@ -35,7 +35,7 @@ class SelectBook extends React.Component {
}}
className="book-manage-title"
>
- {this.props.isSelectBook ? "Cancel" : "Select"}
+ {this.props.isSelectBook ? "Cancel" : ""}
{this.props.isSelectBook && (
<>
diff --git a/src/components/shelfSelector/component.tsx b/src/components/shelfSelector/component.tsx
index ca12988c..4898b6b0 100644
--- a/src/components/shelfSelector/component.tsx
+++ b/src/components/shelfSelector/component.tsx
@@ -42,6 +42,9 @@ class ShelfSelector extends React.Component<
this.props.handleMode("shelf");
});
};
+ handleDeletePopup = (isOpenDelete: boolean) => {
+ this.setState({ isOpenDelete });
+ };
renderShelfList = () => {
let shelfList = ShelfUtil.getShelf();
let shelfTitle = Object.keys(shelfList);
@@ -59,9 +62,7 @@ class ShelfSelector extends React.Component<
);
});
};
- handleDeletePopup = (isOpenDelete: boolean) => {
- this.setState({ isOpenDelete });
- };
+
render() {
if (isElectron) {
//兼容之前的版本
diff --git a/src/constants/sideMenu.tsx b/src/constants/sideMenu.tsx
index 41b4122d..dd509695 100644
--- a/src/constants/sideMenu.tsx
+++ b/src/constants/sideMenu.tsx
@@ -1,28 +1,28 @@
export const sideMenu = [
{
name: "Books",
- icon: "home",
+ icon: "home-line",
mode: "home",
},
{
name: "Favorites",
- icon: "love",
+ icon: "heart",
mode: "favorite",
},
{
name: "Notes",
- icon: "idea",
+ icon: "idea-line",
mode: "note",
},
{
name: "Highlights",
- icon: "digest",
+ icon: "highlight-line",
mode: "digest",
},
{
name: "Deleted Books",
- icon: "trash",
+ icon: "trash-line",
mode: "trash",
},
];
diff --git a/src/containers/lists/bookList/booklist.css b/src/containers/lists/bookList/booklist.css
index 3b39867e..d2c2f20f 100644
--- a/src/containers/lists/bookList/booklist.css
+++ b/src/containers/lists/bookList/booklist.css
@@ -1,6 +1,6 @@
.book-list-container-parent {
position: absolute;
- top: 125px;
+ top: 80px;
left: 220px;
width: calc(100% - 220px);
height: calc(100% - 125px);
@@ -11,7 +11,7 @@
align-items: center;
justify-content: space-between;
position: absolute;
- top: 85px;
+ bottom: 10px;
left: 220px;
width: calc(100% - 220px);
}
diff --git a/src/containers/lists/bookList/component.tsx b/src/containers/lists/bookList/component.tsx
index 3c39be2c..007929d4 100644
--- a/src/containers/lists/bookList/component.tsx
+++ b/src/containers/lists/bookList/component.tsx
@@ -16,7 +16,6 @@ import ViewMode from "../../../components/viewMode";
import { backup } from "../../../utils/syncUtils/backupUtil";
import { isElectron } from "react-device-detect";
import SelectBook from "../../../components/selectBook";
-import ShelfSelector from "../../../components/shelfSelector";
declare var window: any;
class BookList extends React.Component {
constructor(props: BookListProps) {
@@ -191,12 +190,11 @@ class BookList extends React.Component {
}
>
- */}
-
{
constructor(props: SidebarProps) {
super(props);
this.state = {
index: 0,
hoverIndex: -1,
+ hoverShelfIndex: -1,
+ isCollpaseShelf: false,
+ isOpenDelete: false,
+ shelfIndex: 0,
isCollapsed:
StorageUtil.getReaderConfig("isCollapsed") === "yes" || false,
};
@@ -35,6 +40,9 @@ class Sidebar extends React.Component
{
handleHover = (index: number) => {
this.setState({ hoverIndex: index });
};
+ handleShelfHover = (index: number) => {
+ this.setState({ hoverShelfIndex: index });
+ };
handleCollapse = (isCollapsed: boolean) => {
this.setState({ isCollapsed });
this.props.handleCollapse(isCollapsed);
@@ -43,6 +51,20 @@ class Sidebar extends React.Component {
handleJump = (url: string) => {
openExternalUrl(url);
};
+ handleDeleteShelf = () => {
+ if (this.state.shelfIndex < 1) return;
+ let shelfTitles = Object.keys(ShelfUtil.getShelf());
+ //获取当前书架名
+ let currentShelfTitle = shelfTitles[this.state.shelfIndex];
+ ShelfUtil.removeShelf(currentShelfTitle);
+ this.setState({ shelfIndex: 0 }, () => {
+ this.props.handleShelfIndex(0);
+ this.props.handleMode("shelf");
+ });
+ };
+ handleDeletePopup = (isOpenDelete: boolean) => {
+ this.setState({ isOpenDelete });
+ };
render() {
const renderSideMenu = () => {
return sideMenu.map((item, index) => {
@@ -50,7 +72,7 @@ class Sidebar extends React.Component {
{
}}
style={this.props.isCollapsed ? { width: 40, marginLeft: 15 } : {}}
>
- {this.state.index === index ? (
+ {this.state.index === index && this.props.mode !== "shelf" ? (
) : null}
- {this.state.hoverIndex === index ? (
+ {this.state.hoverIndex === index && this.props.mode !== "shelf" ? (
) : null}
{
>
@@ -111,36 +133,162 @@ class Sidebar extends React.Component
{
);
});
};
- return (
-
-
{
- this.handleCollapse(!this.state.isCollapsed);
- }}
- >
-
-
+ const renderSideShelf = () => {
+ let shelfList = ShelfUtil.getShelf();
+ let shelfTitle = Object.keys(shelfList);
-

{
- this.handleJump("https://koodo.960960.xyz");
- }}
- style={this.state.isCollapsed ? { display: "none" } : {}}
- className="logo"
- />
-
-
+ return shelfTitle.map((item, index) => {
+ return (
+
+ );
+ });
+ };
+ const deletePopupProps = {
+ mode: "shelf",
+ name: Object.keys(ShelfUtil.getShelf())[this.state.shelfIndex],
+ title: "Delete this shelf",
+ description: "This action will clear and remove this shelf",
+ handleDeletePopup: this.handleDeletePopup,
+ handleDeleteOpearion: this.handleDeleteShelf,
+ };
+ return (
+ <>
+ {" "}
+
+
{
+ this.handleCollapse(!this.state.isCollapsed);
+ }}
+ >
+
+
+
+

{
+ this.handleJump("https://koodo.960960.xyz");
+ }}
+ style={this.state.isCollapsed ? { display: "none" } : {}}
+ className="logo"
+ />
+
+
+
+
我的书架
+
{
+ this.setState({
+ isCollpaseShelf: !this.state.isCollpaseShelf,
+ });
+ }}
+ style={
+ this.state.isCollpaseShelf
+ ? { transform: "rotate(-90deg)" }
+ : {}
+ }
+ >
+
+
+ {!this.state.isCollpaseShelf && (
+
+ )}
+
+
{" "}
+ {this.state.isOpenDelete && }
+ >
);
}
}
diff --git a/src/containers/sidebar/index.tsx b/src/containers/sidebar/index.tsx
index 5960a511..25e4afd5 100644
--- a/src/containers/sidebar/index.tsx
+++ b/src/containers/sidebar/index.tsx
@@ -12,7 +12,11 @@ import { withTranslation } from "react-i18next";
import Sidebar from "./component";
const mapStateToProps = (state: stateType) => {
- return { mode: state.sidebar.mode, isCollapsed: state.sidebar.isCollapsed };
+ return {
+ mode: state.sidebar.mode,
+ isCollapsed: state.sidebar.isCollapsed,
+ shelfIndex: state.sidebar.shelfIndex,
+ };
};
const actionCreator = {
handleMode,
diff --git a/src/containers/sidebar/interface.tsx b/src/containers/sidebar/interface.tsx
index 6da23b31..d8b5c9d8 100644
--- a/src/containers/sidebar/interface.tsx
+++ b/src/containers/sidebar/interface.tsx
@@ -3,6 +3,8 @@ import { RouteComponentProps } from "react-router";
export interface SidebarProps extends RouteComponentProps {
mode: string;
isCollapsed: boolean;
+ shelfIndex: number;
+
handleMode: (mode: string) => void;
handleSearch: (isSearch: boolean) => void;
handleCollapse: (isCollapsed: boolean) => void;
@@ -15,5 +17,9 @@ export interface SidebarProps extends RouteComponentProps {
export interface SidebarState {
index: number;
hoverIndex: number;
+ hoverShelfIndex: number;
isCollapsed: boolean;
+ isCollpaseShelf: boolean;
+ shelfIndex: number;
+ isOpenDelete: boolean;
}
diff --git a/src/containers/sidebar/sidebar.css b/src/containers/sidebar/sidebar.css
index ccc1c94f..3c60b3d7 100644
--- a/src/containers/sidebar/sidebar.css
+++ b/src/containers/sidebar/sidebar.css
@@ -14,8 +14,22 @@
position: relative;
top: 85px;
width: 210px;
- height: 100%;
- overflow: hidden;
+ height: calc(100% - 100px);
+ overflow-x: hidden;
+ overflow-y: scroll;
+}
+.side-menu-container-parent:hover::-webkit-scrollbar-thumb,
+.side-menu-container-parent:active::-webkit-scrollbar-thumb,
+.side-menu-container-parent:focus::-webkit-scrollbar-thumb {
+ display: block;
+ width: 1px;
+}
+.side-menu-container-parent::-webkit-scrollbar-thumb {
+ display: none;
+}
+.side-menu-container-parent::-webkit-scrollbar {
+ width: 2px;
+ height: 0.5rem;
}
.sidebar-list {
margin-right: 5px;
@@ -42,8 +56,13 @@
.side-menu-container {
/* overflow: hidden; */
width: 100%;
- height: 100%;
- overflow-y: scroll;
+ padding-right: 17px; /* Increase/decrease this value for cross-browser compatibility */
+ box-sizing: content-box;
+ position: relative;
+}
+.side-shelf-container {
+ /* overflow: hidden; */
+ width: 100%;
padding-right: 17px; /* Increase/decrease this value for cross-browser compatibility */
box-sizing: content-box;
position: relative;
@@ -51,7 +70,7 @@
.side-menu-icon {
/* float: left; */
- font-size: 17px;
+ font-size: 22px;
margin: 9px 12px 7px 18px;
display: flex;
justify-content: center;
@@ -68,7 +87,7 @@
text-overflow: ellipsis;
white-space: nowrap;
margin-left: -20px;
- margin-bottom: 10px;
+ margin-bottom: 3px;
position: relative;
bottom: 1px;
overflow: hidden;
@@ -99,7 +118,27 @@
white-space: nowrap;
overflow-x: hidden;
}
-
+.side-shelf-title {
+ font-size: 17px;
+ font-weight: 600;
+ margin-bottom: 10px;
+ margin-top: 10px;
+ display: inline-block;
+}
+.side-shelf-title-container {
+ width: 70%;
+ margin-left: 10%;
+ border-bottom: 1px solid #ccc;
+}
+.side-shelf-title-icon {
+ margin-top: 13px;
+ float: right;
+ font-weight: 500;
+ font-size: 14px;
+ transform-origin: center center;
+ transition: transform 0.1s ease;
+ cursor: pointer;
+}
.side-menu-selector-container {
width: 100%;
height: 39px;