mirror of
https://github.com/koodo-reader/koodo-reader.git
synced 2026-06-20 22:00:56 -04:00
fix bug
Former-commit-id: 1c84dfabb826073dd4223cdf075826f8c2271690
This commit is contained in:
2
main.ts
2
main.ts
@@ -58,6 +58,8 @@ app.on("ready", () => {
|
||||
.getFonts()
|
||||
.then((fonts) => {
|
||||
event.returnValue = fonts;
|
||||
|
||||
const server = require("./server");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
|
||||
@@ -12,13 +12,19 @@
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.161",
|
||||
"axios": "^0.19.2",
|
||||
"body-parser": "^1.19.0",
|
||||
"copy-text-to-clipboard": "^2.2.0",
|
||||
"cors": "^2.8.5",
|
||||
"electron-is-dev": "^1.1.0",
|
||||
"express": "^4.17.1",
|
||||
"express-fileupload": "^1.2.0",
|
||||
"font-list": "^1.2.11",
|
||||
"i18next": "^19.4.4",
|
||||
"i18next-browser-languagedetector": "^4.2.0",
|
||||
"is-electron": "^2.2.0",
|
||||
"md5": "^2.3.0",
|
||||
"onedrive-api": "^0.5.0",
|
||||
"qs": "^6.9.4",
|
||||
"react-device-detect": "^1.12.1",
|
||||
"react-dropzone": "^11.0.1",
|
||||
"react-i18next": "^9.0.10"
|
||||
|
||||
199
server.js
Normal file
199
server.js
Normal file
@@ -0,0 +1,199 @@
|
||||
const express = require("express");
|
||||
const cors = require("cors");
|
||||
const axios = require("axios");
|
||||
const bodyParser = require("body-parser");
|
||||
const qs = require("qs");
|
||||
const fileUpload = require("express-fileupload");
|
||||
const oneDriveAPI = require("onedrive-api");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
var dirPath = "uploads";
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath);
|
||||
console.log("文件夹创建成功");
|
||||
} else {
|
||||
console.log("文件夹已存在");
|
||||
}
|
||||
const server = express();
|
||||
server.use(
|
||||
fileUpload({
|
||||
createParentPath: true,
|
||||
})
|
||||
);
|
||||
server.use(cors());
|
||||
server.use(bodyParser.json());
|
||||
server.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
server.get("/onedrive_refresh", (req, res) => {
|
||||
const { refresh_token, redirect_uri } = req.query;
|
||||
const requestBody = {
|
||||
client_id: "ac96f9bf-94f2-49c0-8418-999b919bc236",
|
||||
refresh_token,
|
||||
grant_type: "refresh_token",
|
||||
client_secret: "-Fb8Lees-b~4EzgB2O48H4r-bOo.yLwpcF",
|
||||
redirect_uri,
|
||||
};
|
||||
axios
|
||||
.post(
|
||||
"https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
||||
qs.stringify(requestBody),
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/x-www-form-urlencoded;charset=utf-8",
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
res.send(result.data);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
res.status(404).send("Something Wrong!");
|
||||
});
|
||||
});
|
||||
server.get("/onedrive_get", (req, res) => {
|
||||
const { code, redirect_uri } = req.query;
|
||||
console.log("test2");
|
||||
const requestBody = {
|
||||
client_id: "ac96f9bf-94f2-49c0-8418-999b919bc236",
|
||||
code,
|
||||
grant_type: "authorization_code",
|
||||
client_secret: "-Fb8Lees-b~4EzgB2O48H4r-bOo.yLwpcF",
|
||||
redirect_uri,
|
||||
};
|
||||
axios
|
||||
.post(
|
||||
"https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
||||
qs.stringify(requestBody),
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/x-www-form-urlencoded;charset=utf-8",
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
res.send(result.data);
|
||||
})
|
||||
.catch((err) => {
|
||||
res.status(404).send("Something Wrong!");
|
||||
});
|
||||
});
|
||||
server.post("/onedrive_download", (req, res) => {
|
||||
var fileStream = oneDriveAPI.items.download({
|
||||
accessToken: req.body.ACCESS_TOKEN,
|
||||
itemId: req.body.backupId,
|
||||
});
|
||||
const writeStream = fs.createWriteStream("uploads/data.zip");
|
||||
writeStream.on("close", () => {
|
||||
console.log("close");
|
||||
res.sendFile(path.resolve("./uploads/data.zip"));
|
||||
res.on("finish", function () {
|
||||
try {
|
||||
fs.unlink(path.resolve("./uploads/data.zip"), (err) => {
|
||||
if (err) throw err;
|
||||
console.log("successfully deleted");
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("error removing ");
|
||||
}
|
||||
});
|
||||
});
|
||||
fileStream.pipe(writeStream);
|
||||
});
|
||||
server.post("/onedrive_upload", async (req, res) => {
|
||||
try {
|
||||
if (!req.files) {
|
||||
res.send({
|
||||
status: false,
|
||||
message: "No file uploaded",
|
||||
});
|
||||
} else {
|
||||
const makeid = (length) => {
|
||||
var result = "";
|
||||
var characters =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var charactersLength = characters.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += characters.charAt(
|
||||
Math.floor(Math.random() * charactersLength)
|
||||
);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
let name = "data.zip";
|
||||
fs.writeFile(path.resolve("./uploads/" + name), "Hey there!", function (
|
||||
err
|
||||
) {
|
||||
if (err) {
|
||||
return console.log(err);
|
||||
}
|
||||
let file = req.files.file;
|
||||
file.mv("./uploads/" + name);
|
||||
console.log(name, "test1");
|
||||
oneDriveAPI.items
|
||||
.uploadSession({
|
||||
accessToken: req.body.ACCESS_TOKEN,
|
||||
filename: name,
|
||||
fileSize: file.size,
|
||||
parentPath: "/Apps/Koodo Reader/",
|
||||
readableStream: fs.createReadStream("./uploads/" + name),
|
||||
})
|
||||
.then((result) => {
|
||||
res.send({
|
||||
status: true,
|
||||
message: "File is uploaded",
|
||||
data: {
|
||||
name: file.name,
|
||||
mimetype: file.mimetype,
|
||||
size: file.size,
|
||||
id: result.id,
|
||||
},
|
||||
});
|
||||
res.on("finish", function () {
|
||||
fs.unlink(path.resolve("./uploads/" + name), (err) => {
|
||||
if (err) throw err;
|
||||
console.log("successfully deleted");
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("upload failed");
|
||||
res.status(401).send(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(500).send(err);
|
||||
}
|
||||
});
|
||||
|
||||
async function start() {
|
||||
try {
|
||||
const port = 3366;
|
||||
expressServer = await server.listen(port);
|
||||
const address = expressServer.address();
|
||||
serverInfo = {
|
||||
port: address.port,
|
||||
local: "localhost",
|
||||
url: `http://localhost:${address.port}`,
|
||||
};
|
||||
return serverInfo;
|
||||
// await reload(config, preload);
|
||||
|
||||
return serverInfo;
|
||||
} catch (e) {
|
||||
return { message: e.message };
|
||||
}
|
||||
}
|
||||
|
||||
async function startServer() {
|
||||
const { port, local, message } = await start();
|
||||
if (message) {
|
||||
console.error(message);
|
||||
} else {
|
||||
console.info(`启动成功,本地访问 http://${local}:${port}`);
|
||||
}
|
||||
}
|
||||
|
||||
startServer();
|
||||
@@ -7,6 +7,9 @@
|
||||
"My Favorites": "我的喜爱",
|
||||
"My Digests": "我的书摘",
|
||||
"My Shelves": "我的书架",
|
||||
"Please continue in desktop version": "仅客户端版本支持",
|
||||
"Book not exsit": "书籍不存在",
|
||||
"Delete Shelf": "删除书架",
|
||||
"Dont't use mimical background": "不使用仿真背景",
|
||||
"Auto hide cursor when reading": "阅读时自动隐藏鼠标",
|
||||
"Sort": "排序",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"Medium": "Mid",
|
||||
"Large": "Large",
|
||||
"Cancel Successfully": "Cancel Successfully",
|
||||
"Please continue in desktop version": "Please continue in desktop version",
|
||||
"Don't use mimical background": "Don't use mimical background",
|
||||
"Auto hide cursor when reading": "Auto hide cursor when reading",
|
||||
"Extra Large": "Extra",
|
||||
@@ -65,10 +66,12 @@
|
||||
"Sort by Name": "by Name",
|
||||
"Bind": "Bind",
|
||||
"Token": "Token",
|
||||
"Book not exsit": "Book not exsit",
|
||||
"Token Info": "Please copy the following link and open in your browser to finish authorizing, once it's over, you'll get a bunch of codes, then fill the following box with the codes",
|
||||
"Copy Link": "Copy Link",
|
||||
"Copy Token": "Copy Token",
|
||||
"Copied": "Copied",
|
||||
"Delete Shelf": "Delete Shelf",
|
||||
"Empty Shelf Title": "Empty Shelf Title",
|
||||
"Copy Link Successfully": "Copy Link Successfully",
|
||||
"Add Successfully": "Add Successfully",
|
||||
|
||||
@@ -119,9 +119,6 @@
|
||||
"Current Font Size": "目前大小",
|
||||
"Current Chapter": "目前章節",
|
||||
"Loading": "載入中",
|
||||
"Cancel Successfully": "取消成功",
|
||||
"Don't use realisc background": "不使用仿真背景",
|
||||
"Auto hide cursor when reading": "阅读时自动隐藏鼠标",
|
||||
"Pick Up Color": "選擇顏色",
|
||||
"Highlight Successfully": "高亮成功",
|
||||
"Take Notes": "筆記",
|
||||
@@ -173,5 +170,11 @@
|
||||
"Our Website": "歡迎造訪我們的網站",
|
||||
"What's New": "新增功能",
|
||||
"What's been fixed": "問題修復",
|
||||
"语言 / Language": "語言 / Language"
|
||||
"语言 / Language": "語言 / Language",
|
||||
"Cancel Successfully": "取消成功",
|
||||
"Don't use realisc background": "不使用仿真背景",
|
||||
"Please continue in desktop version": "仅客户端版本支持",
|
||||
"Auto hide cursor when reading": "阅读时自动隐藏鼠标",
|
||||
"Book not exsit": "书籍不存在",
|
||||
"Delete Shelf": "删除书架"
|
||||
}
|
||||
|
||||
@@ -123,7 +123,4 @@
|
||||
font-weight: bold;
|
||||
width: 106px;
|
||||
height: 38px;
|
||||
/* display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start; */
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
//卡片模式下的图书显示
|
||||
import React from "react";
|
||||
import RecentBooks from "../../utils/recordRecent";
|
||||
import "./book.css";
|
||||
import "./bookCardItem.css";
|
||||
import { BookProps, BookState } from "./interface";
|
||||
import AddFavorite from "../../utils/addFavorite";
|
||||
import ActionDialog from "../../containers/actionDialog";
|
||||
@@ -10,7 +10,7 @@ import localforage from "localforage";
|
||||
|
||||
declare var window: any;
|
||||
|
||||
class Book extends React.Component<BookProps, BookState> {
|
||||
class BookCardItem extends React.Component<BookProps, BookState> {
|
||||
epub: any;
|
||||
constructor(props: BookProps) {
|
||||
super(props);
|
||||
@@ -24,12 +24,14 @@ class Book extends React.Component<BookProps, BookState> {
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
//判断此书是否为喜爱的图书
|
||||
this.setState({
|
||||
isFavorite:
|
||||
AddFavorite.getAllFavorite().indexOf(this.props.book.key) > -1,
|
||||
});
|
||||
}
|
||||
componentDidMount() {
|
||||
//控制是否自动打开本书
|
||||
if (
|
||||
OtherUtil.getReaderConfig("isOpenBook") === "yes" &&
|
||||
RecentBooks.getAllRecent()[0] === this.props.book.key &&
|
||||
@@ -52,7 +54,7 @@ class Book extends React.Component<BookProps, BookState> {
|
||||
if (x > document.body.clientWidth - 100) {
|
||||
x = x - 80;
|
||||
}
|
||||
this.setState({ left: x - 210, top: e.clientY - 100 }, () => {
|
||||
this.setState({ left: x - 210, top: e.clientY - 120 }, () => {
|
||||
this.props.handleActionDialog(true);
|
||||
this.props.handleReadingBook(this.props.book);
|
||||
});
|
||||
@@ -147,4 +149,4 @@ class Book extends React.Component<BookProps, BookState> {
|
||||
);
|
||||
}
|
||||
}
|
||||
export default Book;
|
||||
export default BookCardItem;
|
||||
@@ -1,7 +1,7 @@
|
||||
//控制列表模式下的图书显示
|
||||
import React from "react";
|
||||
import RecentBooks from "../../utils/recordRecent";
|
||||
import "./bookItem.css";
|
||||
import "./bookListItem.css";
|
||||
import RecordLocation from "../../utils/recordLocation";
|
||||
import { BookItemProps, BookItemState } from "./interface";
|
||||
import { Trans } from "react-i18next";
|
||||
@@ -9,7 +9,7 @@ import localforage from "localforage";
|
||||
|
||||
declare var window: any;
|
||||
|
||||
class Book extends React.Component<BookItemProps, BookItemState> {
|
||||
class BookListItem extends React.Component<BookItemProps, BookItemState> {
|
||||
epub: any;
|
||||
constructor(props: BookItemProps) {
|
||||
super(props);
|
||||
@@ -101,4 +101,4 @@ class Book extends React.Component<BookItemProps, BookItemState> {
|
||||
}
|
||||
}
|
||||
|
||||
export default Book;
|
||||
export default BookListItem;
|
||||
@@ -1,4 +1,4 @@
|
||||
//我的书摘页面
|
||||
//我的书摘,笔记的卡片
|
||||
import React from "react";
|
||||
import "./cardList.css";
|
||||
import NoteModel from "../../model/Note";
|
||||
@@ -8,7 +8,6 @@ import DeleteIcon from "../../components/deleteIcon";
|
||||
import RecentBooks from "../../utils/recordRecent";
|
||||
import RecordLocation from "../../utils/recordLocation";
|
||||
import localforage from "localforage";
|
||||
import BookModel from "../../model/Book";
|
||||
|
||||
declare var window: any;
|
||||
|
||||
@@ -34,7 +33,7 @@ class CardList extends React.Component<CardListProps, CardListStates> {
|
||||
};
|
||||
handleJump = (cfi: string, bookKey: string, percentage: number) => {
|
||||
let { books } = this.props;
|
||||
let book: BookModel;
|
||||
let book: any;
|
||||
//根据bookKey获取指定的book和epub
|
||||
for (let i = 0; i < books.length; i++) {
|
||||
if (books[i].key === bookKey) {
|
||||
@@ -42,7 +41,12 @@ class CardList extends React.Component<CardListProps, CardListStates> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if (!book) return;
|
||||
if (!book) {
|
||||
this.props.handleMessage("Book not exsit");
|
||||
this.props.handleMessageBox(true);
|
||||
return;
|
||||
}
|
||||
|
||||
localforage.getItem(book!.key).then((result) => {
|
||||
this.props.handleReadingBook(book);
|
||||
this.props.handleReadingEpub(window.ePub(result, {}));
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
handleReadingBook,
|
||||
handleReadingEpub,
|
||||
} from "../../redux/actions/book";
|
||||
import { handleMessageBox, handleMessage } from "../../redux/actions/manager";
|
||||
|
||||
const mapStateToProps = (state: stateType) => {
|
||||
return {
|
||||
@@ -23,6 +24,8 @@ const actionCreator = {
|
||||
handleReadingState,
|
||||
handleReadingBook,
|
||||
handleReadingEpub,
|
||||
handleMessageBox,
|
||||
handleMessage,
|
||||
};
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
|
||||
@@ -13,6 +13,8 @@ export interface CardListProps {
|
||||
handleReadingState: (isReading: boolean) => void;
|
||||
handleReadingBook: (currentBook: BookModel) => void;
|
||||
handleReadingEpub: (currentEpub: any) => void;
|
||||
handleMessage: (message: string) => void;
|
||||
handleMessageBox: (isShow: boolean) => void;
|
||||
}
|
||||
export interface CardListStates {
|
||||
deleteKey: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//左下角的图标外链
|
||||
//高亮,下划线颜色选择
|
||||
import React from "react";
|
||||
import "./colorOption.css";
|
||||
import { ColorProps, ColorStates } from "./interface";
|
||||
|
||||
@@ -10,6 +10,7 @@ class ContentList extends React.Component<ContentListProps, ContentListState> {
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
//获取目录
|
||||
this.props.currentEpub.loaded.navigation
|
||||
.then((chapters: any) => {
|
||||
this.setState({ chapters: chapters.toc });
|
||||
|
||||
@@ -86,7 +86,7 @@ class ImportLocal extends React.Component<ImportLocalProps, ImportLocalState> {
|
||||
handleBook = (file: any, md5: string) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
//md5重复不导入
|
||||
let isRepeat= false;
|
||||
let isRepeat = false;
|
||||
if (this.props.books) {
|
||||
this.props.books.forEach((item) => {
|
||||
if (item.md5 === md5) {
|
||||
@@ -160,7 +160,7 @@ class ImportLocal extends React.Component<ImportLocalProps, ImportLocalState> {
|
||||
reject();
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -175,6 +175,7 @@ class ImportLocal extends React.Component<ImportLocalProps, ImportLocalState> {
|
||||
}
|
||||
|
||||
for (let i = 0; i < acceptedFiles.length; i++) {
|
||||
//异步解析文件
|
||||
await this.doIncrementalTest(acceptedFiles[i]);
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
//单双页切换
|
||||
//阅读模式切换
|
||||
import React from "react";
|
||||
import "./singleControl.css";
|
||||
import "./modeControl.css";
|
||||
import { Trans } from "react-i18next";
|
||||
import { SingleControlProps, SingleControlState } from "./interface";
|
||||
import { ModeControlProps, ModeControlState } from "./interface";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
|
||||
class SingleControl extends React.Component<
|
||||
SingleControlProps,
|
||||
SingleControlState
|
||||
> {
|
||||
constructor(props: SingleControlProps) {
|
||||
class ModeControl extends React.Component<ModeControlProps, ModeControlState> {
|
||||
constructor(props: ModeControlProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
readerMode: OtherUtil.getReaderConfig("readerMode") || "double",
|
||||
@@ -34,7 +31,7 @@ class SingleControl extends React.Component<
|
||||
>
|
||||
<span className="icon-single-page single-page-icon"></span>
|
||||
<div className="single-mode-text">
|
||||
<Trans>Single-Page Mode</Trans>
|
||||
<Trans>Mode-Page Mode</Trans>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -65,4 +62,4 @@ class SingleControl extends React.Component<
|
||||
);
|
||||
}
|
||||
}
|
||||
export default SingleControl;
|
||||
export default ModeControl;
|
||||
@@ -2,7 +2,7 @@
|
||||
import { connect } from "react-redux";
|
||||
import { handleMessageBox, handleMessage } from "../../redux/actions/manager";
|
||||
import { withNamespaces } from "react-i18next";
|
||||
import SingleControl from "./component";
|
||||
import ModeControl from "./component";
|
||||
import { stateType } from "../../redux/store";
|
||||
|
||||
const mapStateToProps = (state: stateType) => {
|
||||
@@ -12,4 +12,4 @@ const actionCreator = { handleMessageBox, handleMessage };
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
actionCreator
|
||||
)(withNamespaces()(SingleControl as any));
|
||||
)(withNamespaces()(ModeControl as any));
|
||||
@@ -1,8 +1,8 @@
|
||||
export interface SingleControlProps {
|
||||
export interface ModeControlProps {
|
||||
handleMessageBox: (isShow: boolean) => void;
|
||||
handleMessage: (message: string) => void;
|
||||
}
|
||||
|
||||
export interface SingleControlState {
|
||||
export interface ModeControlState {
|
||||
readerMode: string;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
//图书导航栏页面的书签页面
|
||||
//图书导航栏页面的书签,笔记,书摘页面
|
||||
import React from "react";
|
||||
import "./bookNavList.css";
|
||||
import "./navList.css";
|
||||
import { Trans } from "react-i18next";
|
||||
import { BookNavListProps, BookNavListState } from "./interface";
|
||||
import { NavListProps, NavListState } from "./interface";
|
||||
import DeleteIcon from "../deleteIcon";
|
||||
class BookNavList extends React.Component<BookNavListProps, BookNavListState> {
|
||||
constructor(props: BookNavListProps) {
|
||||
class NavList extends React.Component<NavListProps, NavListState> {
|
||||
constructor(props: NavListProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
deleteIndex: -1,
|
||||
@@ -92,4 +92,4 @@ class BookNavList extends React.Component<BookNavListProps, BookNavListState> {
|
||||
}
|
||||
}
|
||||
|
||||
export default BookNavList;
|
||||
export default NavList;
|
||||
@@ -2,7 +2,7 @@
|
||||
import { connect } from "react-redux";
|
||||
import { stateType } from "../../redux/store";
|
||||
import { withNamespaces } from "react-i18next";
|
||||
import BookNavList from "./component";
|
||||
import NavList from "./component";
|
||||
import { handleMessageBox, handleMessage } from "../../redux/actions/manager";
|
||||
const mapStateToProps = (state: stateType) => {
|
||||
return {
|
||||
@@ -17,4 +17,4 @@ const actionCreator = { handleMessageBox, handleMessage };
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
actionCreator
|
||||
)(withNamespaces()(BookNavList as any));
|
||||
)(withNamespaces()(NavList as any));
|
||||
@@ -1,7 +1,7 @@
|
||||
import BookmarkModel from "../../model/Bookmark";
|
||||
import BookModel from "../../model/Book";
|
||||
import NoteModel from "../../model/Note";
|
||||
export interface BookNavListProps {
|
||||
export interface NavListProps {
|
||||
currentBook: BookModel;
|
||||
currentEpub: any;
|
||||
bookmarks: BookmarkModel[];
|
||||
@@ -11,6 +11,6 @@ export interface BookNavListProps {
|
||||
handleMessage: (message: string) => void;
|
||||
handleMessageBox: (isShow: boolean) => void;
|
||||
}
|
||||
export interface BookNavListState {
|
||||
export interface NavListState {
|
||||
deleteIndex: number;
|
||||
}
|
||||
@@ -10,9 +10,9 @@
|
||||
.book-bookmark-digest {
|
||||
margin: 15px 5px 10px;
|
||||
width: 236px;
|
||||
max-height: 186px;
|
||||
max-height: 198px;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
line-height: 18px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
text-overflow: ellipsis;
|
||||
@@ -1,3 +1,4 @@
|
||||
//笔记书摘的标签
|
||||
import React from "react";
|
||||
import "./noteTag.css";
|
||||
import { NoteTagProps, NoteTagState } from "./interface";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//添加笔记的弹窗
|
||||
import React from "react";
|
||||
import "./popupNote.css";
|
||||
import Note from "../../model/Note";
|
||||
@@ -79,10 +80,10 @@ class PopupNote extends React.Component<PopupNoteProps, PopupNoteState> {
|
||||
text = text.replace(/\n/g, "");
|
||||
text = text.replace(/\t/g, "");
|
||||
text = text.replace(/\f/g, "");
|
||||
let percentage =
|
||||
RecordLocation.getCfi(this.props.currentBook.key) === null
|
||||
? 0
|
||||
: RecordLocation.getCfi(this.props.currentBook.key).percentage;
|
||||
let percentage = RecordLocation.getCfi(this.props.currentBook.key)
|
||||
.percentage
|
||||
? RecordLocation.getCfi(this.props.currentBook.key).percentage
|
||||
: 0;
|
||||
|
||||
let color = this.props.color || 0;
|
||||
let tag = this.state.tag;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//选中文字后的弹窗,四个按钮
|
||||
import React from "react";
|
||||
import "./popupOption.css";
|
||||
import localforage from "localforage";
|
||||
@@ -76,10 +77,10 @@ class PopupOption extends React.Component<PopupOptionProps> {
|
||||
}
|
||||
const cfi = RecordLocation.getCfi(this.props.currentBook.key).cfi;
|
||||
|
||||
let percentage =
|
||||
RecordLocation.getCfi(this.props.currentBook.key) === null
|
||||
? 0
|
||||
: RecordLocation.getCfi(this.props.currentBook.key).percentage;
|
||||
let percentage = RecordLocation.getCfi(this.props.currentBook.key)
|
||||
.percentage
|
||||
? RecordLocation.getCfi(this.props.currentBook.key).percentage
|
||||
: 0;
|
||||
let color = this.props.color;
|
||||
let notes = "";
|
||||
let iframe = document.getElementsByTagName("iframe")[0];
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//翻译弹窗
|
||||
import React from "react";
|
||||
import "./popupTrans.css";
|
||||
import { PopupTransProps, PopupTransState } from "./interface";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//搜索框
|
||||
import React from "react";
|
||||
import "./searchBox.css";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
|
||||
@@ -20,7 +20,6 @@ class SettingDialog extends React.Component<
|
||||
isOpenBook: OtherUtil.getReaderConfig("isOpenBook") === "yes",
|
||||
isUseFont: OtherUtil.getReaderConfig("isUseFont") === "yes",
|
||||
isUseBackground: OtherUtil.getReaderConfig("isUseBackground") === "yes",
|
||||
isHideCursor: OtherUtil.getReaderConfig("isHideCursor") === "yes",
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
@@ -81,17 +80,7 @@ class SettingDialog extends React.Component<
|
||||
: this.props.handleMessage("Turn On Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
handleChangeCursor = () => {
|
||||
this.setState({ isHideCursor: !this.state.isHideCursor });
|
||||
OtherUtil.setReaderConfig(
|
||||
"isHideCursor",
|
||||
this.state.isHideCursor ? "no" : "yes"
|
||||
);
|
||||
this.state.isHideCursor
|
||||
? this.props.handleMessage("Turn Off Successfully")
|
||||
: this.props.handleMessage("Turn On Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="setting-dialog-container">
|
||||
@@ -178,21 +167,7 @@ class SettingDialog extends React.Component<
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="setting-dialog-new-title">
|
||||
<Trans>Auto hide cursor when reading</Trans>
|
||||
<span
|
||||
className="single-control-switch"
|
||||
onClick={() => {
|
||||
this.handleChangeCursor();
|
||||
}}
|
||||
style={{ float: "right" }}
|
||||
>
|
||||
<span
|
||||
className="single-control-button"
|
||||
style={this.state.isHideCursor ? { float: "right" } : {}}
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="setting-dialog-new-title">
|
||||
<Trans>语言 / Language</Trans>
|
||||
<div className="setting-language">
|
||||
|
||||
@@ -8,6 +8,5 @@ export interface SettingInfoState {
|
||||
isTouch: boolean;
|
||||
isOpenBook: boolean;
|
||||
isUseFont: boolean;
|
||||
isHideCursor: boolean;
|
||||
isUseBackground: boolean;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//修改阅读器背景色
|
||||
import React from "react";
|
||||
import { themeList } from "../../utils/readerConfig";
|
||||
import ReaderConfig from "../../utils/readerConfig";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//添加图书到书架的对话框
|
||||
//绑定网盘的弹窗
|
||||
import React, { Component } from "react";
|
||||
import "./tokenDialog.css";
|
||||
import copy from "copy-text-to-clipboard";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//左下角的图标外链
|
||||
//更新提示弹窗
|
||||
import React from "react";
|
||||
import "./updateDialog.css";
|
||||
import { UpdateInfoProps, UpdateInfoState } from "./interface";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//左下角的图标外链
|
||||
//提示更新的文字
|
||||
import React from "react";
|
||||
import "./updateInfo.css";
|
||||
import { UpdateInfoProps, UpdateInfoState } from "./interface";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//对图书操作的菜单
|
||||
import React from "react";
|
||||
import "./actionDialog.css";
|
||||
import { Trans } from "react-i18next";
|
||||
|
||||
@@ -50,6 +50,7 @@ class AddDialog extends Component<AddDialogProps, AddDialogState> {
|
||||
this.props.handleMessage("Add Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
this.props.handleActionDialog(false);
|
||||
this.props.handleMode("shelf");
|
||||
};
|
||||
//如果是添加到已存在的书架就diable新建图书的input框
|
||||
handleChange = (shelfTitle: string) => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { handleAddDialog, handleActionDialog } from "../../redux/actions/book";
|
||||
import { stateType } from "../../redux/store";
|
||||
import { withNamespaces } from "react-i18next";
|
||||
import AddDialog from "./component";
|
||||
import { handleMode } from "../../redux/actions/sidebar";
|
||||
|
||||
const mapStateToProps = (state: stateType) => {
|
||||
return {
|
||||
@@ -21,6 +22,7 @@ const actionCreator = {
|
||||
handleActionDialog,
|
||||
handleMessageBox,
|
||||
handleMessage,
|
||||
handleMode,
|
||||
};
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface AddDialogProps {
|
||||
currentBook: BookModel;
|
||||
handleMessage: (message: string) => void;
|
||||
handleMessageBox: (isShow: boolean) => void;
|
||||
handleMode: (mode: string) => void;
|
||||
}
|
||||
export interface AddDialogState {
|
||||
isNew: boolean;
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
//备份和恢复页面
|
||||
import React from "react";
|
||||
import "./backupPage.css";
|
||||
import "./backupDialog.css";
|
||||
import { driveList } from "../../utils/readerConfig";
|
||||
import BackupUtil from "../../utils/backupUtil";
|
||||
import RestoreUtil from "../../utils/restoreUtil";
|
||||
import { Trans } from "react-i18next";
|
||||
import DropboxUtil from "../../utils/syncUtils/dropbox";
|
||||
import OnedriveUtil from "../../utils/syncUtils/onedrive";
|
||||
import { BackupPageProps, BackupPageState } from "./interface";
|
||||
import { BackupDialogProps, BackupDialogState } from "./interface";
|
||||
import TokenDialog from "../../components/tokenDialog";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
const isElectron = require("is-electron");
|
||||
|
||||
class BackupPage extends React.Component<BackupPageProps, BackupPageState> {
|
||||
constructor(props: BackupPageProps) {
|
||||
class BackupDialog extends React.Component<
|
||||
BackupDialogProps,
|
||||
BackupDialogState
|
||||
> {
|
||||
constructor(props: BackupDialogProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
currentStep: 0,
|
||||
@@ -73,6 +77,9 @@ class BackupPage extends React.Component<BackupPageProps, BackupPageState> {
|
||||
this.showMessage("Coming Soon");
|
||||
break;
|
||||
case 3:
|
||||
if (isElectron()) {
|
||||
this.showMessage("Please continue in desktop version");
|
||||
}
|
||||
if (!OtherUtil.getReaderConfig("onedrive_access_token")) {
|
||||
this.props.handleTokenDialog(true);
|
||||
break;
|
||||
@@ -256,4 +263,4 @@ class BackupPage extends React.Component<BackupPageProps, BackupPageState> {
|
||||
}
|
||||
}
|
||||
|
||||
export default BackupPage;
|
||||
export default BackupDialog;
|
||||
@@ -7,7 +7,7 @@ import { connect } from "react-redux";
|
||||
import { handleMessageBox, handleMessage } from "../../redux/actions/manager";
|
||||
import { stateType } from "../../redux/store";
|
||||
import { withNamespaces } from "react-i18next";
|
||||
import BackupPage from "./component";
|
||||
import BackupDialog from "./component";
|
||||
|
||||
const mapStateToProps = (state: stateType) => {
|
||||
return {
|
||||
@@ -27,4 +27,4 @@ const actionCreator = {
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
actionCreator
|
||||
)(withNamespaces()(BackupPage as any));
|
||||
)(withNamespaces()(BackupDialog as any));
|
||||
@@ -2,7 +2,7 @@ import BookModel from "../../model/Book";
|
||||
import NoteModel from "../../model/Note";
|
||||
import BookmarkModel from "../../model/Bookmark";
|
||||
|
||||
export interface BackupPageProps {
|
||||
export interface BackupDialogProps {
|
||||
handleBackupDialog: (isBackup: boolean) => void;
|
||||
handleTokenDialog: (isOpenTokenDialog: boolean) => void;
|
||||
handleMessage: (message: string) => void;
|
||||
@@ -13,7 +13,7 @@ export interface BackupPageProps {
|
||||
digests: NoteModel[];
|
||||
bookmarks: BookmarkModel[];
|
||||
}
|
||||
export interface BackupPageState {
|
||||
export interface BackupDialogState {
|
||||
currentStep: number | null;
|
||||
isBackup: string;
|
||||
currentDrive: number | null;
|
||||
@@ -3,7 +3,7 @@
|
||||
top: 115px;
|
||||
left: 200px;
|
||||
width: calc(100% - 200px);
|
||||
height: calc(100% - 75px);
|
||||
height: calc(100% - 110px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.book-list-container {
|
||||
@@ -75,3 +75,7 @@
|
||||
font-size: 15px;
|
||||
line-height: 31px;
|
||||
}
|
||||
.delete-shelf-icon {
|
||||
cursor: pointer;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
//全部图书,最近阅读,搜索结果,排序结果的数据
|
||||
import React from "react";
|
||||
import "./booklist.css";
|
||||
import Book from "../../components/book";
|
||||
import BookItem from "../../components/bookItem";
|
||||
import Book from "../../components/bookCardtem";
|
||||
import BookItem from "../../components/bookListItem";
|
||||
import AddFavorite from "../../utils/addFavorite";
|
||||
import RecordRecent from "../../utils/recordRecent";
|
||||
import ShelfUtil from "../../utils/shelfUtil";
|
||||
import SortUtil from "../../utils/sortUtil";
|
||||
import BookModel from "../../model/Book";
|
||||
import { Trans, NamespacesConsumer } from "react-i18next";
|
||||
import { BookListProps } from "./interface";
|
||||
import { BookListProps, BookListState } from "./interface";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
import localforage from "localforage";
|
||||
|
||||
declare var window: any;
|
||||
|
||||
class BookList extends React.Component<BookListProps> {
|
||||
class BookList extends React.Component<BookListProps, BookListState> {
|
||||
constructor(props: BookListProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shelfIndex: 0,
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
this.handleOldVersion();
|
||||
}
|
||||
@@ -121,7 +127,6 @@ class BookList extends React.Component<BookListProps> {
|
||||
arr.forEach((item) => {
|
||||
items[item] && itemArr.push(items[item]);
|
||||
});
|
||||
console.log(itemArr);
|
||||
return itemArr;
|
||||
};
|
||||
renderBookList = () => {
|
||||
@@ -159,11 +164,26 @@ class BookList extends React.Component<BookListProps> {
|
||||
);
|
||||
});
|
||||
};
|
||||
//切换书架
|
||||
handleShelfItem = (event: any) => {
|
||||
let index = event.target.value.split(",")[1];
|
||||
console.log(index, "index");
|
||||
this.setState({ shelfIndex: index });
|
||||
this.props.handleShelfIndex(index);
|
||||
if (index > 0) {
|
||||
this.props.handleMode("shelf");
|
||||
} else {
|
||||
this.props.handleMode("home");
|
||||
}
|
||||
};
|
||||
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");
|
||||
};
|
||||
renderShelfList = () => {
|
||||
@@ -230,6 +250,14 @@ class BookList extends React.Component<BookListProps> {
|
||||
>
|
||||
{this.renderShelfList()}
|
||||
</select>
|
||||
{this.state.shelfIndex > 0 ? (
|
||||
<span
|
||||
className="icon-trash delete-shelf-icon"
|
||||
onClick={() => {
|
||||
this.handleDeleteShelf();
|
||||
}}
|
||||
></span>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="book-list-container-parent">
|
||||
<div className="book-list-container">
|
||||
|
||||
@@ -13,3 +13,6 @@ export interface BookListProps {
|
||||
handleMode: (mode: string) => void;
|
||||
handleShelfIndex: (index: number) => void;
|
||||
}
|
||||
export interface BookListState {
|
||||
shelfIndex: number;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
top: 80px;
|
||||
left: 200px;
|
||||
width: calc(100% - 200px);
|
||||
height: calc(100% - 90px);
|
||||
height: calc(100% - 80px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.bookmark-page-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-right: 17px; /* Increase/decrease this value for cross-browser compatibility */
|
||||
box-sizing: content-box; /* So the width will be 100% + 17px */
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow-y: scroll;
|
||||
@@ -36,6 +38,7 @@
|
||||
height: 160px;
|
||||
min-width: 403px;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.bookmark-page-cover {
|
||||
@@ -50,10 +53,8 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
.bookmark-page-name {
|
||||
/* float: left; */
|
||||
height: 29px;
|
||||
width: 110px;
|
||||
/* margin-left: 10px; */
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
|
||||
@@ -89,29 +89,26 @@ class BookmarkPage extends React.Component<
|
||||
</li>
|
||||
));
|
||||
};
|
||||
const renderBookmarkPageItem = (item: BookModel, index: number) => {
|
||||
return (
|
||||
<li className="bookmark-page-item" key={item.key}>
|
||||
<img
|
||||
className="bookmark-page-cover"
|
||||
src={item.cover}
|
||||
alt=""
|
||||
onClick={() => {
|
||||
this.handleRedirect(item.key, "", 0);
|
||||
}}
|
||||
/>
|
||||
<p className="bookmark-page-name">{bookArr[index].name}</p>
|
||||
<div className="bookmark-page-bookmark-container-parent">
|
||||
<ul className="bookmark-page-bookmark-container">
|
||||
{renderBookmarklistItem(item)}
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
const renderBookmarkPage = () => {
|
||||
return bookArr.map((item, index) => {
|
||||
return <div key={item.key}>{renderBookmarkPageItem(item, index)}</div>;
|
||||
return (
|
||||
<li className="bookmark-page-item" key={item.key}>
|
||||
<img
|
||||
className="bookmark-page-cover"
|
||||
src={item.cover}
|
||||
alt=""
|
||||
onClick={() => {
|
||||
this.handleRedirect(item.key, "", 0);
|
||||
}}
|
||||
/>
|
||||
<p className="bookmark-page-name">{bookArr[index].name}</p>
|
||||
<div className="bookmark-page-bookmark-container-parent">
|
||||
<ul className="bookmark-page-bookmark-container">
|
||||
{renderBookmarklistItem(item)}
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
};
|
||||
return (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//图书导航栏
|
||||
//左侧图书导航面板
|
||||
import React from "react";
|
||||
import "./navigationPanel.css";
|
||||
import ContentList from "../../components/contentList";
|
||||
import BookNavList from "../../components/bookNavList";
|
||||
import BookNavList from "../../components/navList";
|
||||
import ReadingTime from "../../utils/readingTime";
|
||||
import { Trans } from "react-i18next";
|
||||
import { NavigationPanelProps, NavigationPanelState } from "./interface";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//图书操作页面
|
||||
//顶部图书操作面板
|
||||
import React from "react";
|
||||
import "./operationPanel.css";
|
||||
import Bookmark from "../../model/Bookmark";
|
||||
@@ -84,17 +84,17 @@ class OperationPanel extends React.Component<
|
||||
const cfiRange = `epubcfi(${cfibase}!,${cfistart},${cfiend})`;
|
||||
const cfi = RecordLocation.getCfi(this.props.currentBook.key).cfi;
|
||||
this.props.currentEpub.getRange(cfiRange).then((range: any) => {
|
||||
if (!range) return;
|
||||
let text = range.toString();
|
||||
text = text.replace(/\s\s/g, "");
|
||||
text = text.replace(/\r/g, "");
|
||||
text = text.replace(/\n/g, "");
|
||||
text = text.replace(/\t/g, "");
|
||||
text = text.replace(/\f/g, "");
|
||||
let percentage =
|
||||
RecordLocation.getCfi(this.props.currentBook.key) === null
|
||||
? 0
|
||||
: RecordLocation.getCfi(this.props.currentBook.key).percentage;
|
||||
|
||||
let percentage = RecordLocation.getCfi(this.props.currentBook.key)
|
||||
.percentage
|
||||
? RecordLocation.getCfi(this.props.currentBook.key).percentage
|
||||
: 0;
|
||||
let bookmark = new Bookmark(bookKey, cfi, text, percentage, chapter);
|
||||
let bookmarkArr = this.props.bookmarks ?? [];
|
||||
bookmarkArr.push(bookmark);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//选中文字后的弹窗
|
||||
import React from "react";
|
||||
import "./popupMenu.css";
|
||||
import PopupNote from "../../components/popupNote";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//底部阅读进度面板
|
||||
import React from "react";
|
||||
import "./progressPanel.css";
|
||||
import RecordLocation from "../../utils/recordLocation";
|
||||
@@ -51,10 +52,10 @@ class ProgressPanel extends React.Component<
|
||||
const section = this.props.currentEpub.section(chapterIndex - 1);
|
||||
if (section && section.href) {
|
||||
this.props.currentEpub.rendition.display(section.href).then(() => {
|
||||
let percentage =
|
||||
RecordLocation.getCfi(this.props.currentBook.key) === null
|
||||
? 0
|
||||
: RecordLocation.getCfi(this.props.currentBook.key).percentage;
|
||||
let percentage = RecordLocation.getCfi(this.props.currentBook.key)
|
||||
.percentage
|
||||
? RecordLocation.getCfi(this.props.currentBook.key).percentage
|
||||
: 0;
|
||||
this.setState({ displayPercentage: percentage });
|
||||
});
|
||||
}
|
||||
@@ -65,10 +66,10 @@ class ProgressPanel extends React.Component<
|
||||
const section = this.props.currentEpub.section(chapterIndex + 1);
|
||||
if (section && section.href) {
|
||||
this.props.currentEpub.rendition.display(section.href).then(() => {
|
||||
let percentage =
|
||||
RecordLocation.getCfi(this.props.currentBook.key) === null
|
||||
? 0
|
||||
: RecordLocation.getCfi(this.props.currentBook.key).percentage;
|
||||
let percentage = RecordLocation.getCfi(this.props.currentBook.key)
|
||||
.percentage
|
||||
? RecordLocation.getCfi(this.props.currentBook.key).percentage
|
||||
: 0;
|
||||
this.setState({ displayPercentage: percentage });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
//右侧阅读选项面板
|
||||
import React from "react";
|
||||
import "./settingPanel.css";
|
||||
import ThemeList from "../../components/themeList";
|
||||
import FontSizeList from "../../components/fontSizeList";
|
||||
import DropdownList from "../../components/dropdownList";
|
||||
import SingleControl from "../../components/singleControl";
|
||||
import ModeControl from "../../components/modeControl";
|
||||
import { SettingPanelProps, SettingPanelState } from "./interface";
|
||||
import { Trans } from "react-i18next";
|
||||
|
||||
@@ -78,7 +79,7 @@ class SettingPanel extends React.Component<
|
||||
<div className="setting-panel-title">
|
||||
<Trans>Reading Option</Trans>
|
||||
</div>
|
||||
<SingleControl />
|
||||
<ModeControl />
|
||||
{this.state.isSupported && this.props.locations ? (
|
||||
<div className="single-control-switch-container">
|
||||
<span className="single-control-switch-title">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//排序弹窗
|
||||
import React from "react";
|
||||
import "./sortDialog.css";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//阅读器图书内容区域
|
||||
import React from "react";
|
||||
import "./viewArea.css";
|
||||
import PopupMenu from "../popupMenu";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//欢迎页面
|
||||
import { withNamespaces } from "react-i18next";
|
||||
|
||||
import { handleFirst } from "../../redux/actions/manager";
|
||||
import { connect } from "react-redux";
|
||||
import WelcomePage from "./component";
|
||||
|
||||
@@ -12,7 +12,7 @@ import AddDialog from "../../containers/addDialog";
|
||||
import SortDialog from "../../containers/sortDialog";
|
||||
import MessageBox from "../../containers/messageBox";
|
||||
import LoadingPage from "../../containers/loadingPage";
|
||||
import BackupPage from "../../containers/backupPage";
|
||||
import BackupPage from "../../containers/backupDialog";
|
||||
import EmptyPage from "../../containers/emptyPage";
|
||||
import WelcomePage from "../../containers/welcomePage";
|
||||
import "./manager.css";
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import OtherUtil from "./otherUtil";
|
||||
import ReaderConfig from "./readerConfig";
|
||||
let Hammer = (window as any).Hammer;
|
||||
|
||||
export const MouseEvent = (rendition: any) => {
|
||||
@@ -94,16 +93,6 @@ export const MouseEvent = (rendition: any) => {
|
||||
doc.addEventListener("mousewheel", mouseChrome, false);
|
||||
}
|
||||
};
|
||||
const handleCursor = () => {
|
||||
if (lock) return;
|
||||
OtherUtil.setReaderConfig("isHideCursor", "yes");
|
||||
ReaderConfig.addDefaultCss();
|
||||
lock = true;
|
||||
setTimeout(function () {
|
||||
lock = false;
|
||||
}, 500);
|
||||
return false;
|
||||
};
|
||||
|
||||
rendition.on("rendered", () => {
|
||||
let iframe = document.getElementsByTagName("iframe")[0];
|
||||
@@ -118,7 +107,6 @@ export const MouseEvent = (rendition: any) => {
|
||||
gesture(event);
|
||||
});
|
||||
}
|
||||
doc.addEventListener("mousemove", handleCursor);
|
||||
|
||||
// 鼠标滚轮翻页
|
||||
window.addEventListener("keydown", arrowKeys);
|
||||
|
||||
@@ -30,19 +30,7 @@ class readerConfig {
|
||||
static getDefaultCss() {
|
||||
let colors = ["#FBF1D1", "#EFEEB0", "#CAEFC9", "#76BEE9"];
|
||||
let lines = ["#FF0000", "#000080", "#0000FF", "#2EFF2E"];
|
||||
let css1 = `::selection{background:#f3a6a68c}::-moz-selection{background:#f3a6a68c}[class*=color-]:hover{cursor:pointer;background-image:linear-gradient(0,rgba(0,0,0,.075),rgba(0,0,0,.075))}.color-0{background-color:${
|
||||
colors[0]
|
||||
}}.color-1{background-color:${colors[1]}}.color-2{background-color:${
|
||||
colors[2]
|
||||
}}.color-3{background-color:${colors[3]}}.line-0{border-bottom:2px solid ${
|
||||
lines[0]
|
||||
}}.line-1{border-bottom:2px solid ${
|
||||
lines[1]
|
||||
}}.line-2{border-bottom:2px solid ${
|
||||
lines[2]
|
||||
}}.line-3{border-bottom:2px solid ${lines[3]}}*{cursor:${
|
||||
OtherUtil.getReaderConfig("isHideCursor") === "yes" ? "none" : ""
|
||||
}}`;
|
||||
let css1 = `::selection{background:#f3a6a68c}::-moz-selection{background:#f3a6a68c}[class*=color-]:hover{cursor:pointer;background-image:linear-gradient(0,rgba(0,0,0,.075),rgba(0,0,0,.075))}.color-0{background-color:${colors[0]}}.color-1{background-color:${colors[1]}}.color-2{background-color:${colors[2]}}.color-3{background-color:${colors[3]}}.line-0{border-bottom:2px solid ${lines[0]}}.line-1{border-bottom:2px solid ${lines[1]}}.line-2{border-bottom:2px solid ${lines[2]}}.line-3{border-bottom:2px solid ${lines[3]}}}`;
|
||||
|
||||
return css1;
|
||||
}
|
||||
@@ -133,8 +121,8 @@ export const config = {
|
||||
: "http://localhost:3000",
|
||||
token_url:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "https://koodo.960960.xyz"
|
||||
: "http://localhost:3001",
|
||||
? "http://localhost:3366"
|
||||
: "http://localhost:3366",
|
||||
dropbox_client_id: "e3zgg310xbizvaf",
|
||||
googledrive_client_id:
|
||||
"99440516227-ifr1ann33f2j610i3ri17ej0i51c7m6e.apps.googleusercontent.com",
|
||||
|
||||
@@ -27,7 +27,7 @@ class ShelfUtil {
|
||||
let json = localStorage.getItem("shelfList");
|
||||
let obj = JSON.parse(json!) || defaultShelf;
|
||||
let shelfTitle = Object.keys(obj);
|
||||
let currentShelfTitle = shelfTitle[shelfIndex + 1];
|
||||
let currentShelfTitle = shelfTitle[shelfIndex];
|
||||
let index = obj[currentShelfTitle].indexOf(bookKey);
|
||||
obj[currentShelfTitle].splice(index, 1);
|
||||
localStorage.setItem("shelfList", JSON.stringify(obj));
|
||||
@@ -45,10 +45,10 @@ class ShelfUtil {
|
||||
});
|
||||
localStorage.setItem("shelfList", JSON.stringify(obj));
|
||||
}
|
||||
static removeShelf() {
|
||||
static removeShelf(shelfTitle: string) {
|
||||
let json = localStorage.getItem("shelfList");
|
||||
let obj = JSON.parse(json!) || defaultShelf;
|
||||
delete obj.shelfTitle;
|
||||
delete obj[shelfTitle];
|
||||
localStorage.setItem("shelfList", JSON.stringify(obj));
|
||||
}
|
||||
}
|
||||
|
||||
77
yarn.lock
77
yarn.lock
@@ -2824,6 +2824,11 @@ bluebird-lst@^1.0.9:
|
||||
dependencies:
|
||||
bluebird "^3.5.5"
|
||||
|
||||
bluebird@^2.3:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.npm.taobao.org/bluebird/download/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
|
||||
integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=
|
||||
|
||||
bluebird@^3.5.5:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||
@@ -2839,7 +2844,7 @@ bn.js@^5.1.1:
|
||||
resolved "https://registry.npm.taobao.org/bn.js/download/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
|
||||
integrity sha1-vsoAVAj2Quvr6oCwQrTRjSrA7ms=
|
||||
|
||||
body-parser@1.19.0:
|
||||
body-parser@1.19.0, body-parser@^1.19.0:
|
||||
version "1.19.0"
|
||||
resolved "https://registry.npm.taobao.org/body-parser/download/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
||||
integrity sha1-lrJwnlfJxOCab9Zqj9l5hE9p8Io=
|
||||
@@ -3094,6 +3099,13 @@ builtin-status-codes@^3.0.0:
|
||||
resolved "https://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||
integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
|
||||
|
||||
busboy@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.npm.taobao.org/busboy/download/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
||||
integrity sha1-FwiZJ0xb84quJ9XGK3EmjNWF/Rs=
|
||||
dependencies:
|
||||
dicer "0.3.0"
|
||||
|
||||
bytes@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||
@@ -3789,6 +3801,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
resolved "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cors@^2.8.5:
|
||||
version "2.8.5"
|
||||
resolved "https://registry.npm.taobao.org/cors/download/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
|
||||
integrity sha1-6sEdpRWS3Ya58G9uesKTs9+HXSk=
|
||||
dependencies:
|
||||
object-assign "^4"
|
||||
vary "^1"
|
||||
|
||||
cosmiconfig@^5.0.0, cosmiconfig@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-5.2.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcosmiconfig%2Fdownload%2Fcosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
|
||||
@@ -4352,6 +4372,13 @@ detect-port-alt@1.1.6:
|
||||
address "^1.0.1"
|
||||
debug "^2.6.0"
|
||||
|
||||
dicer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.npm.taobao.org/dicer/download/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
|
||||
integrity sha1-6s2Ys7+/kuirXC/bcaqsRLsGuHI=
|
||||
dependencies:
|
||||
streamsearch "0.1.2"
|
||||
|
||||
diff-sequences@^24.9.0:
|
||||
version "24.9.0"
|
||||
resolved "https://registry.npm.taobao.org/diff-sequences/download/diff-sequences-24.9.0.tgz?cache=0&sync_timestamp=1597057408594&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdiff-sequences%2Fdownload%2Fdiff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
||||
@@ -5110,6 +5137,13 @@ expect@^24.9.0:
|
||||
jest-message-util "^24.9.0"
|
||||
jest-regex-util "^24.9.0"
|
||||
|
||||
express-fileupload@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npm.taobao.org/express-fileupload/download/express-fileupload-1.2.0.tgz#356c4dfd645be71ab9fb2f4e6d84eeb00d247979"
|
||||
integrity sha1-NWxN/WRb5xq5+y9ObYTusA0keXk=
|
||||
dependencies:
|
||||
busboy "^0.3.1"
|
||||
|
||||
express@^4.17.1:
|
||||
version "4.17.1"
|
||||
resolved "https://registry.npm.taobao.org/express/download/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
||||
@@ -6604,6 +6638,11 @@ is-electron@^2.2.0:
|
||||
resolved "https://registry.npm.taobao.org/is-electron/download/is-electron-2.2.0.tgz#8943084f09e8b731b3a7a0298a7b5d56f6b7eef0"
|
||||
integrity sha1-iUMITwnotzGzp6ApintdVva37vA=
|
||||
|
||||
is-empty-object@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npm.taobao.org/is-empty-object/download/is-empty-object-1.1.1.tgz#86d5d4d5c5229cea31ec2772f528bf5efc519f23"
|
||||
integrity sha1-htXU1cUinOox7Cdy9Si/XvxRnyM=
|
||||
|
||||
is-extendable@^0.1.0, is-extendable@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
|
||||
@@ -7751,7 +7790,7 @@ lodash.uniq@^4.5.0:
|
||||
resolved "https://registry.npm.taobao.org/lodash.uniq/download/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||
|
||||
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@~4.17.10:
|
||||
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@^4.5.0, lodash@~4.17.10:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597336097104&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI=
|
||||
@@ -8463,7 +8502,7 @@ oauth-sign@~0.9.0:
|
||||
resolved "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU=
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
@@ -8590,6 +8629,15 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
onedrive-api@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.npm.taobao.org/onedrive-api/download/onedrive-api-0.5.0.tgz#197150da29b741e882bfd68a78ae14e8d8763f28"
|
||||
integrity sha1-GXFQ2im3QeiCv9aKeK4U6Nh2Pyg=
|
||||
dependencies:
|
||||
is-empty-object "^1.1.1"
|
||||
request "^2.88.0"
|
||||
request-promise "^2.0.1"
|
||||
|
||||
onetime@^5.1.0:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npm.taobao.org/onetime/download/onetime-5.1.2.tgz?cache=0&sync_timestamp=1597005190531&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fonetime%2Fdownload%2Fonetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
|
||||
@@ -9936,6 +9984,11 @@ qs@6.7.0:
|
||||
resolved "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
integrity sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=
|
||||
|
||||
qs@^6.9.4:
|
||||
version "6.9.4"
|
||||
resolved "https://registry.npm.taobao.org/qs/download/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687"
|
||||
integrity sha1-kJCykNH5FyjTwi5UhDykSupatoc=
|
||||
|
||||
qs@~6.5.2:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
@@ -10523,7 +10576,16 @@ request-promise-native@^1.0.5:
|
||||
stealthy-require "^1.1.1"
|
||||
tough-cookie "^2.3.3"
|
||||
|
||||
request@^2.87.0, request@^2.88.0:
|
||||
request-promise@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npm.taobao.org/request-promise/download/request-promise-2.0.1.tgz#acbd47b725e39372ede3174cf29c38d9ecf2b30d"
|
||||
integrity sha1-rL1HtyXjk3Lt4xdM8pw42ezysw0=
|
||||
dependencies:
|
||||
bluebird "^2.3"
|
||||
lodash "^4.5.0"
|
||||
request "^2.34"
|
||||
|
||||
request@^2.34, request@^2.87.0, request@^2.88.0:
|
||||
version "2.88.2"
|
||||
resolved "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
||||
integrity sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=
|
||||
@@ -11402,6 +11464,11 @@ stream-shift@^1.0.0:
|
||||
resolved "https://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
|
||||
integrity sha1-1wiCgVWasneEJCebCHfaPDktWj0=
|
||||
|
||||
streamsearch@0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.npm.taobao.org/streamsearch/download/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
||||
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
||||
|
||||
strict-uri-encode@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||
@@ -12252,7 +12319,7 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
vary@~1.1.2:
|
||||
vary@^1, vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
|
||||
|
||||
Reference in New Issue
Block a user