diff --git a/README.md b/README.md index 559c144..540ff43 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,16 @@ --- -tags: [] created: 2020-04-12T13:19:52.701Z modified: 2020-05-11T11:14:44.140Z --- ![](./public/logo192.png) -# 📝 Crossnote 交叉笔记 (beta) +# 📝 Crossnote 交叉笔记 -> You can still check the deprecated alpha version README.md [here](./README.alpha.md). - -**Attention: Breaking updates coming soon. Please check [this GitHub issue](https://github.com/0xGG/crossnote/issues/129) for more information.** https://crossnote.app -Or checkout our latest development version V3 that comes with many fancy changes: - -**V3**: https://0xgg.io/crossnote/ +Or checkout our latest development version: https://0xgg.io/crossnote/ --- @@ -25,31 +19,21 @@ Or checkout our latest development version V3 that comes with many fancy changes **Crossnote** is probably the world's first markdown notes reader & editor Progressive Web Application that works offline and supports syncing with arbitrary git repository right inside your browser. -We also offer an extension for VSCode (Still under development): [0xGG/vscode-crossnote](https://github.com/0xGG/vscode-crossnote) | [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=shd101wyy.crossnote) - Let's open the [Welcome Notebook](https://crossnote.app/?repo=https%3A%2F%2Fgithub.com%2F0xGG%2Fwelcome-notebook.git&branch=master&filePath=README.md) in crossnote for more information! (Just click the `ADD` button once the webpage is open to add this notebook) 让我们在交叉笔记中打开 [欢迎笔记本](https://crossnote.app/?repo=https%3A%2F%2Fgithub.com%2F0xGG%2Fwelcome-notebook.git&branch=master&filePath=README.md) 以查看更详尽的介绍!(在网页打开后点击 `ADD` 按钮直接添加该笔记本) 由于服务器目前位于境外,所以国内用户第一次打开速度会略慢,但是第一次打开后程序就会被缓存了以供离线使用,往后打开速度就快了。 -![Screenshot from 2020-05-20 22-19-46](https://i.loli.net/2020/05/20/avwbhzYotSFBPWL.png) -![Screenshot from 2020-05-20 22-18-43](https://i.loli.net/2020/05/20/9CDBljgFROm78eQ.png) +![Screenshot from 2021-02-28 22-47-35](https://user-images.githubusercontent.com/1908863/109422675-89d1da00-7a17-11eb-9163-c50126114ff1.png) + +![Screenshot from 2021-02-28 22-47-51](https://user-images.githubusercontent.com/1908863/109422670-876f8000-7a17-11eb-911f-8a8efee856ad.png) ## Development Please check [this documentation](https://github.com/0xGG/welcome-notebook/tree/master/development). -## Crossnote V3 - -Crossnote V3 is currently under development on the `develop` branch of this repository. -Please note that V3 is far from complete. -The Crossnote V3 website is currently hosted on GitHub Pages: https://0xgg.io/crossnote/ -The Crossnote V3 supports modifying local files powered by the Chrome's [File System Access API](https://web.dev/file-system-access/): - -![Peek 2021-02-15 15-30](https://user-images.githubusercontent.com/1908863/107917394-db538100-6fa2-11eb-8ef1-ea37844cb799.gif) - ## License AGPL3 diff --git a/src/components/ConfigureNotebookDialog.tsx b/src/components/ConfigureNotebookDialog.tsx index eb359ba..05e5630 100644 --- a/src/components/ConfigureNotebookDialog.tsx +++ b/src/components/ConfigureNotebookDialog.tsx @@ -1,13 +1,13 @@ import { + Accordion, + AccordionDetails, + AccordionSummary, Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, - ExpansionPanel, - ExpansionPanelDetails, - ExpansionPanelSummary, Input, InputAdornment, Link, @@ -15,7 +15,7 @@ import { Typography, } from "@material-ui/core"; import { ChevronDown } from "mdi-material-ui"; -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { CrossnoteContainer } from "../containers/crossnote"; import { Notebook } from "../lib/notebook"; @@ -45,8 +45,16 @@ export default function ConfigureNotebookDialog(props: Props) { const [clickHardResetCount, setClickHardResetCount] = useState( MaxClickDeleteCount, ); + const isMounted = useRef(false); const { t } = useTranslation(); + useEffect(() => { + isMounted.current = true; + return () => { + isMounted.current = false; + }; + }, []); + useEffect(() => { setClickDeleteCount(MaxClickDeleteCount); setClickHardResetCount(MaxClickDeleteCount); @@ -82,7 +90,9 @@ export default function ConfigureNotebookDialog(props: Props) { try { await crossnoteContainer.updateNotebook(notebook); } catch (error) {} - props.onClose(); + if (isMounted.current) { + props.onClose(); + } }, [ props, props.notebook, @@ -100,16 +110,20 @@ export default function ConfigureNotebookDialog(props: Props) { try { await crossnoteContainer.deleteNotebook(notebook); } catch (error) {} - props.onClose(); - }, [props.notebook]); + if (isMounted.current) { + props.onClose(); + } + }, [props.notebook, props]); const hardResetNotebook = useCallback(async () => { const notebook = props.notebook; try { await crossnoteContainer.hardResetNotebook(notebook); } catch (error) {} - props.onClose(); - }, [props.notebook]); + if (isMounted.current) { + props.onClose(); + } + }, [props.notebook, props]); useEffect(() => { setClickDeleteCount(MaxClickDeleteCount); @@ -134,17 +148,17 @@ export default function ConfigureNotebookDialog(props: Props) { autoCorrect={"off"} > {!props.notebook.isLocal && ( - setExpanded(!expanded)} > - }> + }> {`${t("general/git-repository")} (${t( "general/optional", )})`} - - + + ) : null} - - + + )} diff --git a/src/components/DeleteNoteDialog.tsx b/src/components/DeleteNoteDialog.tsx index 39734c9..69da928 100644 --- a/src/components/DeleteNoteDialog.tsx +++ b/src/components/DeleteNoteDialog.tsx @@ -7,7 +7,7 @@ import { DialogTitle, } from "@material-ui/core"; import { TabNode } from "flexlayout-react"; -import React from "react"; +import React, { useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; import { CrossnoteContainer } from "../containers/crossnote"; import { Note } from "../lib/note"; @@ -21,9 +21,17 @@ interface Props { export function DeleteNoteDialog(props: Props) { const { t } = useTranslation(); + const isMounted = useRef(false); const note = props.note; const crossnoteContainer = CrossnoteContainer.useContainer(); + useEffect(() => { + isMounted.current = true; + return () => { + isMounted.current = false; + }; + }, []); + return ( {t("delete-note-dialog/title")} @@ -41,7 +49,9 @@ export function DeleteNoteDialog(props: Props) { note.notebookPath, note.filePath, ); - props.onClose(); + if (isMounted.current) { + props.onClose(); + } }} > {t("general/Delete")} diff --git a/src/components/GraphView.tsx b/src/components/GraphView.tsx index 5dca307..8e845af 100644 --- a/src/components/GraphView.tsx +++ b/src/components/GraphView.tsx @@ -1,3 +1,4 @@ +import { debounce } from "@0xgg/echomd"; import { createStyles, makeStyles, @@ -61,12 +62,13 @@ export default function GraphView(props: Props) { setWidth(graphViewPanel.current.offsetWidth); setHeight(graphViewPanel.current.offsetHeight); }; - window.addEventListener("resize", resize); - props.tabNode.setEventListener("resize", resize); + const debouncedResize = debounce(resize, 1000); + window.addEventListener("resize", debouncedResize); + props.tabNode.setEventListener("resize", debouncedResize); resize(); return () => { - window.removeEventListener("resize", resize); + window.removeEventListener("resize", debouncedResize); props.tabNode.removeEventListener("resize"); }; }, [graphViewPanel, props.tabNode]); diff --git a/src/components/NoteCard.tsx b/src/components/NoteCard.tsx index 9176b29..74502e3 100644 --- a/src/components/NoteCard.tsx +++ b/src/components/NoteCard.tsx @@ -388,7 +388,7 @@ export default function NoteCard(props: Props) { notebook: crossnoteContainer.getNotebookAtPath( note.notebookPath, ), - reference, + reference: Object.assign({}, reference) as Reference, }, name: `📝 ` + note.title, }); diff --git a/src/components/NotePanel.tsx b/src/components/NotePanel.tsx index 2affeb4..b4f6e4b 100644 --- a/src/components/NotePanel.tsx +++ b/src/components/NotePanel.tsx @@ -625,7 +625,17 @@ export default function NotePanel(props: Props) { }, ); } - }*/ + }*/ else if ( + editor + ) { + const lineNo = (props.reference.parentToken.map || [])[0]; + if (typeof lineNo === "number") { + editor.setCursor({ line: editor.lastLine(), ch: 0 }); + setTimeout(function () { + editor.setCursor({ line: lineNo, ch: 0 }); + }, 10); + } + } } }, [props.reference, editorMode, editor, previewElement]); diff --git a/src/containers/crossnote.ts b/src/containers/crossnote.ts index c86dc6c..71215d1 100644 --- a/src/containers/crossnote.ts +++ b/src/containers/crossnote.ts @@ -490,7 +490,9 @@ function useCrossnoteContainer(initialState: InitialState) { notebookPath: notebook.dir, }); await crossnote.deleteNotebook(notebook._id); - } catch (error) {} + } catch (error) { + console.error(error); + } let selectedNotebook: Notebook = null; setNotebooks((notebooks) => notebooks.filter((n) => { diff --git a/src/lib/crossnote.ts b/src/lib/crossnote.ts index 8cd67b8..e04ce2a 100644 --- a/src/lib/crossnote.ts +++ b/src/lib/crossnote.ts @@ -274,7 +274,9 @@ export default class Crossnote { public async deleteNotebook(notebookID: string) { const notebook = await this.notebookDB.get(notebookID); - await pfs.rmdir(notebook.dir); + if (!notebook.directoryHandle) { + await pfs.rmdir(notebook.dir); + } await this.notebookDB.remove(notebook); } public async updateNotebook(notebook: Notebook) { diff --git a/src/lib/notebook.ts b/src/lib/notebook.ts index b59bace..f0a722e 100644 --- a/src/lib/notebook.ts +++ b/src/lib/notebook.ts @@ -168,7 +168,7 @@ export class Notebook { tokens[i + 1].type === "text" ) { if (token.attrs.length && token.attrs[0][0] === "href") { - const link = token.attrs[0][1]; + const link = decodeURI(token.attrs[0][1]); const text = tokens[i + 1].content.trim(); if ( link.match(/https?:\/\//) ||