Former-commit-id: add57f52da5608b8d5b71ee0c5bb3cc407d89da1
This commit is contained in:
troyeguo
2021-11-28 12:58:08 +08:00
parent bb7fa09d3a
commit 0c77abb4c7
16 changed files with 174 additions and 77 deletions

View File

File diff suppressed because one or more lines are too long

View File

@@ -15,8 +15,6 @@ class PopupMenu extends React.Component<PopupMenuProps, PopupMenuStates> {
mode: string;
showNote: boolean;
isFirstShow: boolean;
cfiRange: any;
contents: any;
rect: any;
constructor(props: PopupMenuProps) {
super(props);
@@ -26,8 +24,6 @@ class PopupMenu extends React.Component<PopupMenuProps, PopupMenuStates> {
this.mode = "";
this.state = {
deleteKey: "",
cfiRange: this.props.cfiRange,
contents: this.props.contents,
rect: this.props.rect,
};
}
@@ -48,11 +44,9 @@ class PopupMenu extends React.Component<PopupMenuProps, PopupMenuStates> {
});
}
componentWillReceiveProps(nextProps: PopupMenuProps) {
if (nextProps.cfiRange !== this.props.cfiRange) {
if (nextProps.rect !== this.props.rect) {
this.setState(
{
cfiRange: nextProps.cfiRange,
contents: nextProps.contents,
rect: nextProps.rect,
},
() => {
@@ -133,14 +127,14 @@ class PopupMenu extends React.Component<PopupMenuProps, PopupMenuStates> {
? rect.x
: StorageUtil.getReaderConfig("readerMode") === "scroll"
? rect.right
: rect.x % this.props.currentEpub.rendition._layout.width;
let y = rect.y % this.props.currentEpub.rendition._layout.height;
: rect.x % this.props.pageWidth;
let y = rect.y % this.props.pageHeight;
let posX = x + rect.width / 2 - 20;
//防止menu超出图书
let rightEdge =
this.props.menuMode === "note" || this.props.menuMode === "trans"
? this.props.currentEpub.rendition._layout.width - 310
: this.props.currentEpub.rendition._layout.width - 200;
? this.props.pageWidth - 310
: this.props.pageWidth - 200;
let posY: number;
//控制menu方向
if (y < height) {
@@ -159,16 +153,14 @@ class PopupMenu extends React.Component<PopupMenuProps, PopupMenuStates> {
//渲染高亮
renderHighlighters = () => {
let highlighters: any = this.props.notes;
console.log(this.props.notes, "highlighters");
if (!highlighters) return;
if (!this.props.rendition || !this.props.rendition.currentLocation) {
return;
}
const currentLocation = this.props.rendition.currentLocation();
if (!currentLocation || !currentLocation.start) return;
let chapterIndex = currentLocation.start.index;
let highlightersByChapter = highlighters.filter(
(item: any) => item.chapterIndex === chapterIndex
(item: any) =>
item.chapterIndex === this.props.chapterIndex &&
item.chapter === this.props.chapter
);
console.log(highlightersByChapter);
let iframe = document.getElementsByTagName("iframe")[0];
let iWin = iframe.contentWindow || iframe.contentDocument?.defaultView;
this.highlighter && this.highlighter.removeAllHighlights(); // 为了避免下次反序列化失败,必须先清除已有的高亮
@@ -270,9 +262,10 @@ class PopupMenu extends React.Component<PopupMenuProps, PopupMenuStates> {
this.handleHighlight();
}
const PopupProps = {
cfiRange: this.props.cfiRange,
contents: this.props.contents,
rect: this.props.rect,
pageWidth: this.props.pageWidth,
pageHeight: this.props.pageHeight,
chapterIndex: this.props.chapterIndex,
chapter: this.props.chapter,
};
return (
<div>

View File

@@ -11,10 +11,13 @@ export interface PopupMenuProps {
notes: NoteModel[];
color: number;
rendition: any;
cfiRange: any;
contents: any;
// cfiRange: any;
rect: any;
noteKey: string;
pageWidth: number;
pageHeight: number;
chapterIndex: number;
chapter: string;
handleNoteKey: (key: string) => void;
t: (title: string) => string;
handleOpenMenu: (isOpenMenu: boolean) => void;
@@ -23,7 +26,6 @@ export interface PopupMenuProps {
}
export interface PopupMenuStates {
deleteKey: string;
cfiRange: string;
contents: any;
// cfiRange: string;
rect: DOMRect | null;
}

View File

@@ -45,17 +45,13 @@ class PopupNote extends React.Component<PopupNoteProps, PopupNoteState> {
} else {
//创建笔记
let bookKey = this.props.currentBook.key;
const currentLocation = this.props.currentEpub.rendition.currentLocation();
let chapterHref = currentLocation.start.href;
let chapterIndex = currentLocation.start.index;
let chapter = "Unknown Chapter";
let currentChapter = this.props.flattenChapters.filter(
(item: any) => item.href.split("#")[0] === chapterHref
)[0];
if (currentChapter) {
chapter = currentChapter.label.trim(" ");
let cfi = "";
if (this.props.currentBook.format === "EPUB") {
cfi = RecordLocation.getCfi(this.props.currentBook.key).cfi;
} else {
cfi = JSON.stringify(RecordLocation.getScrollHeight);
}
const cfi = RecordLocation.getCfi(this.props.currentBook.key).cfi;
let iframe = document.getElementsByTagName("iframe")[0];
if (!iframe) return;
let doc = iframe.contentDocument;
@@ -84,8 +80,8 @@ class PopupNote extends React.Component<PopupNoteProps, PopupNoteState> {
let tag = this.state.tag;
let note = new Note(
bookKey,
chapter,
chapterIndex,
this.props.chapter,
this.props.chapterIndex,
text,
cfi,
range,

View File

@@ -7,6 +7,10 @@ export interface PopupNoteProps {
flattenChapters: any;
color: number;
noteKey: string;
pageWidth: number;
pageHeight: number;
chapterIndex: number;
chapter: string;
handleNoteKey: (key: string) => void;
handleOpenMenu: (isOpenMenu: boolean) => void;
handleMenuMode: (menu: string) => void;

View File

@@ -26,7 +26,7 @@ class PopupOption extends React.Component<PopupOptionProps> {
let posY = popupMenu?.style.top;
posX = parseInt(posX.substr(0, posX.length - 2));
posY = parseInt(posY.substr(0, posY.length - 2));
let rightEdge = this.props.currentEpub.rendition._layout.width - 310;
let rightEdge = this.props.pageWidth - 310;
if (posX > rightEdge) {
popupMenu.setAttribute("style", `left:${rightEdge}px;top:${posY}px`);
}
@@ -48,18 +48,14 @@ class PopupOption extends React.Component<PopupOptionProps> {
};
handleDigest = () => {
let bookKey = this.props.currentBook.key;
const currentLocation = this.props.currentEpub.rendition.currentLocation();
let chapterHref = currentLocation.start.href;
let chapterIndex = currentLocation.start.index;
let chapter = "Unknown Chapter";
let currentChapter = this.props.flattenChapters.filter(
(item: any) => item.href.split("#")[0] === chapterHref
)[0];
if (currentChapter) {
chapter = currentChapter.label.trim(" ");
let cfi = "";
if (this.props.currentBook.format === "EPUB") {
cfi = RecordLocation.getCfi(this.props.currentBook.key).cfi;
} else {
cfi = JSON.stringify(
RecordLocation.getScrollHeight(this.props.currentBook.key)
);
}
const cfi = RecordLocation.getCfi(this.props.currentBook.key).cfi;
let percentage = RecordLocation.getCfi(this.props.currentBook.key)
.percentage
? RecordLocation.getCfi(this.props.currentBook.key).percentage
@@ -83,8 +79,8 @@ class PopupOption extends React.Component<PopupOptionProps> {
text = text.replace(/\f/g, "");
let digest = new Note(
bookKey,
chapter,
chapterIndex,
this.props.chapter,
this.props.chapterIndex,
text,
cfi,
range,

View File

@@ -10,7 +10,10 @@ export interface PopupOptionProps {
color: number;
rect: DOMRect;
cfiRange: string;
contents: any;
pageWidth: number;
pageHeight: number;
chapterIndex: number;
chapter: string;
handleOpenMenu: (isOpenMenu: boolean) => void;
handleMenuMode: (menu: string) => void;
handleFetchNotes: () => void;

View File

@@ -15,9 +15,12 @@ class EpubViewer extends React.Component<ViewAreaProps, ViewAreaStates> {
constructor(props: ViewAreaProps) {
super(props);
this.state = {
cfiRange: null,
contents: null,
// cfiRange: null,
rect: null,
chapterIndex: 0,
chapter: "",
pageWidth: 0,
pageHeight: 0,
};
this.isFirst = true;
}
@@ -63,6 +66,22 @@ class EpubViewer extends React.Component<ViewAreaProps, ViewAreaStates> {
if (!doc) {
return;
}
const currentLocation = this.props.rendition.currentLocation();
let chapterHref = currentLocation.start.href;
if (!currentLocation || !currentLocation.start) return;
this.setState({
chapterIndex: currentLocation.start.index,
pageWidth: this.props.currentEpub.rendition._layout.width,
pageHeight: this.props.currentEpub.rendition._layout.height,
});
let chapter = "Unknown Chapter";
let currentChapter = this.props.flattenChapters.filter(
(item: any) => item.href.split("#")[0] === chapterHref
)[0];
if (currentChapter) {
chapter = currentChapter.label.trim(" ");
}
this.setState({ chapter });
StyleUtil.addDefaultCss();
this.props.rendition.themes.default(StyleUtil.getCustomCss(false));
if (
@@ -86,7 +105,7 @@ class EpubViewer extends React.Component<ViewAreaProps, ViewAreaStates> {
this.props.rendition.on("selected", (cfiRange: any, contents: any) => {
var range = contents.range(cfiRange);
var rect = range.getBoundingClientRect();
this.setState({ cfiRange, contents, rect });
this.setState({ rect });
});
this.props.rendition.themes.default(StyleUtil.getCustomCss(false));
this.props.rendition.display(
@@ -99,9 +118,11 @@ class EpubViewer extends React.Component<ViewAreaProps, ViewAreaStates> {
render() {
const popupMenuProps = {
rendition: this.props.rendition,
cfiRange: this.state.cfiRange,
contents: this.state.contents,
rect: this.state.rect,
pageWidth: this.state.pageWidth,
pageHeight: this.state.pageHeight,
chapterIndex: this.state.chapterIndex,
chapter: this.state.chapter,
};
const imageViewerProps = {
isShow: this.props.isShow,

View File

@@ -16,6 +16,7 @@ const mapStateToProps = (state: stateType) => {
currentEpub: state.book.currentEpub,
currentBook: state.book.currentBook,
locations: state.progressPanel.locations,
flattenChapters: state.reader.flattenChapters,
bookmarks: state.reader.bookmarks,
isShowBookmark: state.viewArea.isShowBookmark,
};

View File

@@ -6,6 +6,7 @@ export interface ViewAreaProps {
currentBook: BookModel;
currentEpub: any;
bookmarks: BookmarkModel[];
flattenChapters: any;
locations: any;
isShowBookmark: boolean;
chapters: any[];
@@ -18,8 +19,10 @@ export interface ViewAreaProps {
handleReadingEpub: (epub: object) => void;
}
export interface ViewAreaStates {
cfiRange: any;
contents: any;
// rendition: any;
// cfiRange: any;
rect: any;
chapterIndex: number;
chapter: string;
pageWidth: number;
pageHeight: number;
}

View File

@@ -7,11 +7,12 @@ import BookUtil from "../../utils/fileUtils/bookUtil";
import iconv from "iconv-lite";
import chardet from "chardet";
import rtfToHTML from "@iarna/rtf-to-html";
import PopupMenu from "../../components/popups/popupMenu";
import { xmlBookTagFilter, xmlBookToObj } from "../../utils/fileUtils/xmlUtil";
import StorageUtil from "../../utils/storageUtil";
import RecordLocation from "../../utils/readUtils/recordLocation";
import { mimetype } from "../../constants/mimetype";
import BackgroundWidget from "../../components/background";
import Background from "../../components/background";
import toast from "react-hot-toast";
import StyleUtil from "../../utils/readUtils/styleUtil";
import "./index.css";
@@ -19,6 +20,7 @@ import { HtmlMouseEvent } from "../../utils/mouseEvent";
import untar from "js-untar";
import ImageViewer from "../../components/imageViewer";
import Chinese from "chinese-s2t";
import _ from "underscore";
declare var window: any;
@@ -33,6 +35,9 @@ class Viewer extends React.Component<ViewerProps, ViewerState> {
constructor(props: ViewerProps) {
super(props);
this.state = {
cfiRange: null,
contents: null,
rect: null,
key: "",
isFirst: true,
scale: StorageUtil.getReaderConfig("scale") || 1,
@@ -41,10 +46,18 @@ class Viewer extends React.Component<ViewerProps, ViewerState> {
.chapterTitle || "",
readerMode: StorageUtil.getReaderConfig("readerMode") || "double",
margin: parseInt(StorageUtil.getReaderConfig("margin")) || 30,
chapterIndex: 0,
chapter: "",
pageWidth: 0,
pageHeight: 0,
};
this.lock = false;
}
componentWillMount() {
this.props.handleFetchBookmarks();
this.props.handleFetchNotes();
this.props.handleFetchBooks();
}
componentDidMount() {
this.handleRenderBook();
@@ -104,15 +117,15 @@ class Viewer extends React.Component<ViewerProps, ViewerState> {
handleRest = (rendition: any) => {
StyleUtil.addDefaultCss();
rendition.setStyle(StyleUtil.getCustomCss(true));
let bookLocation = RecordLocation.getScrollHeight(
this.props.currentBook.key
);
let bookLocation: { text: string; count: string; chapterTitle: string } =
RecordLocation.getScrollHeight(this.props.currentBook.key);
rendition.goToPosition(
bookLocation.text,
bookLocation.chapterTitle,
bookLocation.count
);
window.frames[0].document.addEventListener("click", (event) => {
this.props.handleLeaveReader("left");
this.props.handleLeaveReader("right");
@@ -132,16 +145,39 @@ class Viewer extends React.Component<ViewerProps, ViewerState> {
subitems: [],
rendition: rendition,
});
this.setState({
pageWidth: rendition.getPageSize().width,
pageHeight: rendition.getPageSize().height,
});
if (this.props.currentBook.format.startsWith("CB")) {
this.setState({
chapter:
this.props.htmlBook.chapters[parseInt(bookLocation.count)].label,
chapterIndex: parseInt(bookLocation.count),
});
} else {
this.setState({
chapter: bookLocation.chapterTitle,
chapterIndex: _.findLastIndex(this.props.htmlBook.chapters, {
label: bookLocation.chapterTitle,
}),
});
}
let iframe = document.getElementsByTagName("iframe")[0];
if (!iframe) return;
let doc = iframe.contentDocument;
if (!doc) {
return;
}
doc.addEventListener("mouseup", () => {
if (!doc!.getSelection()) return;
var rect = doc!.getSelection()!.getRangeAt(0).getBoundingClientRect();
this.setState({ rect });
});
if (
StorageUtil.getReaderConfig("convertChinese") &&
StorageUtil.getReaderConfig("convertChinese") !== "Default"
) {
let iframe = document.getElementsByTagName("iframe")[0];
if (!iframe) return;
let doc = iframe.contentDocument;
if (!doc) {
return;
}
if (
StorageUtil.getReaderConfig("convertChinese") ===
"Simplified To Traditional"
@@ -377,8 +413,20 @@ class Viewer extends React.Component<ViewerProps, ViewerState> {
></div>
{StorageUtil.getReaderConfig("isHideBackground") === "yes" ? null : this
.props.currentBook.key ? (
<BackgroundWidget />
<Background />
) : null}
{this.props.htmlBook && (
<PopupMenu
{...{
rendition: this.props.htmlBook.rendition,
rect: this.state.rect,
pageWidth: this.state.pageWidth,
pageHeight: this.state.pageHeight,
chapterIndex: this.state.chapterIndex,
chapter: this.state.chapter,
}}
/>
)}
{this.props.htmlBook && (
<ImageViewer
{...{

View File

@@ -8,6 +8,10 @@ import {
handleRenderFunc,
handleFetchBooks,
handleCurrentChapter,
handleFetchNotes,
handleFetchBookmarks,
handleFetchChapters,
handleFetchPercentage,
} from "../../store/actions";
import Viewer from "./component";
import { stateType } from "../../store";
@@ -31,6 +35,10 @@ const actionCreator = {
handleRenderFunc,
handleFetchBooks,
handleCurrentChapter,
handleFetchNotes,
handleFetchBookmarks,
handleFetchChapters,
handleFetchPercentage,
};
export default connect(
mapStateToProps,

View File

@@ -17,7 +17,8 @@ export interface ViewerProps {
handleLeaveReader: (position: string) => void;
handleEnterReader: (position: string) => void;
handleFetchBooks: () => void;
handleCurrentChapter: (currentChapter) => void;
handleFetchNotes: () => void;
handleFetchBookmarks: () => void;
}
export interface ViewerState {
key: string;
@@ -26,4 +27,11 @@ export interface ViewerState {
chapterTitle: string;
margin: number;
readerMode: string;
chapter: string;
chapterIndex: number;
pageWidth: number;
pageHeight: number;
cfiRange: any;
contents: any;
rect: any;
}

View File

@@ -12,6 +12,7 @@ import NoteTag from "../../../components/noteTag";
import BookUtil from "../../../utils/fileUtils/bookUtil";
import toast from "react-hot-toast";
import StorageUtil from "../../../utils/storageUtil";
import BookModel from "../../../model/Book";
class CardList extends React.Component<CardListProps, CardListStates> {
constructor(props: CardListProps) {
super(props);
@@ -34,7 +35,7 @@ class CardList extends React.Component<CardListProps, CardListStates> {
};
handleJump = (cfi: string, bookKey: string, percentage: number) => {
let { books } = this.props;
let book: any;
let book: BookModel | null = null;
//根据bookKey获取指定的book和epub
for (let i = 0; i < books.length; i++) {
if (books[i].key === bookKey) {
@@ -46,7 +47,18 @@ class CardList extends React.Component<CardListProps, CardListStates> {
toast(this.props.t("Book not exist"));
return;
}
RecordLocation.recordCfi(bookKey, cfi, percentage);
if (book.format === "EPUB") {
RecordLocation.recordCfi(bookKey, cfi, percentage);
} else {
let bookLocation = JSON.parse(cfi) || {};
RecordLocation.recordScrollHeight(
bookKey,
bookLocation.text,
bookLocation.chapterTitle,
bookLocation.count
);
}
if (StorageUtil.getReaderConfig("isOpenInMain") === "yes") {
this.props.history.push(BookUtil.getBookUrl(book));
} else {

View File

@@ -43,6 +43,7 @@ export function handleFetchNotes() {
noteArr = value;
}
let keyArr = AddTrash.getAllTrash();
console.log(noteArr, "noteArr");
dispatch(handleNotes(handleKeyRemove(noteArr, keyArr)));
dispatch(
handleDigests(

View File

@@ -90,6 +90,7 @@ const bindEvent = (
) => {
doc.addEventListener("keydown", (event) => {
arrowKeys(rendition, event.keyCode);
//使用Key判断是否是htmlBook
if (key) {
let postion = rendition.getPosition();
RecordLocation.recordScrollHeight(