Skip to content

Commit

Permalink
feat: bookmark can custom title
Browse files Browse the repository at this point in the history
* feat: bookmark can custom title
  • Loading branch information
lee88688 authored Jan 17, 2024
1 parent 1afca01 commit b1f589c
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 23 deletions.
45 changes: 45 additions & 0 deletions src/components/dialogKb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from "react";
import Dialog, { type DialogProps } from "@mui/material/Dialog";
import useVirtualKeyboard from "y/hooks/useVirtualKeyboard";
import { makeStyles } from "y/utils/makesStyles";

const useStyles = makeStyles<{
isOpen: boolean;
bottom: string;
}>()((_, { isOpen, bottom }) => {
if (isOpen) {
return {
container: {
position: "relative",
},
root: {
position: "absolute",
bottom,
},
};
} else {
return {
container: {},
root: {},
};
}
});

export default function DialogKb(props: DialogProps) {
const { isSupported, isKeyboardOpen, boundingRect } = useVirtualKeyboard();

const { classes } = useStyles({
isOpen: isSupported && isKeyboardOpen,
bottom: boundingRect?.height ? `${boundingRect.height}px` : "50vh",
});

return (
<Dialog
{...props}
classes={{
container: classes.container,
root: classes.root,
}}
/>
);
}
46 changes: 46 additions & 0 deletions src/components/pages/reader/bookmarkTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useEffect, useState } from "react";
import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from "@mui/material/DialogContent";
import DialogActions from "@mui/material/DialogActions";
import Button from "@mui/material/Button";
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";
import DialogKb from "y/components/dialogKb";

type BookmarkTitleProps = {
open: boolean;
title: string;
onCancel: () => void;
onConfirm: (title: string) => void;
};

export default function BookmarkTitle(props: BookmarkTitleProps) {
const [title, setTitle] = useState(props.title);

useEffect(() => {
setTitle(props.title);
}, [props.title]);

return (
<DialogKb open={props.open} maxWidth="xs">
<DialogTitle>书签标题</DialogTitle>
<DialogContent>
<Box sx={{ pt: 1 }}>
<TextField
value={title}
onInput={(e) => setTitle(e.target.value as string)}
autoFocus
label="请输入标题"
fullWidth
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={props.onCancel}>取消</Button>
<Button color="primary" onClick={() => props.onConfirm(title)}>
确定
</Button>
</DialogActions>
</DialogKb>
);
}
8 changes: 6 additions & 2 deletions src/hooks/useVirtualKeyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ export default function useVirtualKeyboard() {
}
};
navigator.virtualKeyboard.addEventListener("geometrychange", fn);
navigator.virtualKeyboard.overlaysContent = true;
if (!navigator.virtualKeyboard.overlaysContent) {
navigator.virtualKeyboard.overlaysContent = true;
}

return () => {
navigator.virtualKeyboard.removeEventListener("geometrychange", fn);
navigator.virtualKeyboard.overlaysContent = false;
if (navigator.virtualKeyboard.overlaysContent) {
navigator.virtualKeyboard.overlaysContent = false;
}
};
}
}, [isSupported]);
Expand Down
68 changes: 47 additions & 21 deletions src/pages/reader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import { makeStyles } from "y/utils/makesStyles";
import { useReader } from "y/components/pages/reader/epubReader";
import BookmarkTitle from "y/components/pages/reader/bookmarkTitle";
import {
apiUpdateBookCurrent,
getFileUrl,
Expand Down Expand Up @@ -41,6 +42,7 @@ import {
} from "y/components/nestedList";
import { useMutation, useQuery } from "@tanstack/react-query";
import useScreenWakeLock from "y/hooks/useScreenWakeLock";
import { type CreateMarkParams } from "../api/mark/create";

const useStyles = makeStyles()((theme) => ({
root: { display: "flex", flexDirection: "row-reverse" },
Expand Down Expand Up @@ -163,27 +165,6 @@ export default function Reader(props: ReaderProps) {
void router.prefetch("/bookshelf");
}, [router]);

const addBookmark = async () => {
if (!epubReaderRef.current) return;

const location = await epubReaderRef.current.currentLocation();
const cfi = location.start.cfi;
const range = epubReaderRef.current.getRange(cfi);
const title = range.startContainer
? getElementHeading(range.startContainer as HTMLElement)
: "";
await addMark({
bookId: id,
type: MarkType.Bookmark,
selectedString: truncate(range.startContainer.textContent ?? ""),
epubcfi: cfi,
title,
color: "",
content: "",
});
await bookmarkListQuery.refetch();
};

const reportCurrentLocation = useCallback(async () => {
const location = await epubReaderRef.current?.currentLocation();
const cfi = location?.start?.cfi;
Expand Down Expand Up @@ -229,6 +210,45 @@ export default function Reader(props: ReaderProps) {
epubReaderRef.current?.removeHighlightById(mark.id);
};

// add or update bookmark
const [bookmarkTitleOpen, setBookmarkTitleOpen] = useState(false);
const [bookmarkTitle, setBookmarkTitle] = useState("");
const createBookmarkRef = useRef<CreateMarkParams | undefined>();

const addBookmark = async () => {
if (!epubReaderRef.current) return;

const location = await epubReaderRef.current.currentLocation();
const cfi = location.start.cfi;
const range = epubReaderRef.current.getRange(cfi);
const title = range.startContainer
? getElementHeading(range.startContainer as HTMLElement)
: "";
createBookmarkRef.current = {
bookId: id,
type: MarkType.Bookmark,
selectedString: truncate(range.startContainer.textContent ?? ""),
epubcfi: cfi,
title,
color: "",
content: "",
};
setBookmarkTitleOpen(true);
setBookmarkTitle(title);
};

const handleBookmarkTitleConfirm = async (title: string) => {
if (!createBookmarkRef.current) return;

setBookmarkTitleOpen(false);
await addMark({
...createBookmarkRef.current,
title,
});
createBookmarkRef.current = undefined;
await bookmarkListQuery.refetch();
};

return (
<div className={classes.root}>
<AppBar position="fixed" className={classes.appBar}>
Expand Down Expand Up @@ -285,6 +305,12 @@ export default function Reader(props: ReaderProps) {
className={cx(classes.pageIcon, classes.next)}
/>
</main>
<BookmarkTitle
open={bookmarkTitleOpen}
title={bookmarkTitle}
onCancel={() => setBookmarkTitleOpen(false)}
onConfirm={handleBookmarkTitleConfirm}
/>
</div>
);
}
Expand Down

0 comments on commit b1f589c

Please sign in to comment.