Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 5 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -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/

---

Expand All @@ -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
44 changes: 29 additions & 15 deletions src/components/ConfigureNotebookDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import {
Accordion,
AccordionDetails,
AccordionSummary,
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
ExpansionPanel,
ExpansionPanelDetails,
ExpansionPanelSummary,
Input,
InputAdornment,
Link,
TextField,
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";
Expand Down Expand Up @@ -45,8 +45,16 @@ export default function ConfigureNotebookDialog(props: Props) {
const [clickHardResetCount, setClickHardResetCount] = useState<number>(
MaxClickDeleteCount,
);
const isMounted = useRef<boolean>(false);
const { t } = useTranslation();

useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);

useEffect(() => {
setClickDeleteCount(MaxClickDeleteCount);
setClickHardResetCount(MaxClickDeleteCount);
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand All @@ -134,17 +148,17 @@ export default function ConfigureNotebookDialog(props: Props) {
autoCorrect={"off"}
></TextField>
{!props.notebook.isLocal && (
<ExpansionPanel
<Accordion
elevation={2}
expanded={expanded}
onChange={() => setExpanded(!expanded)}
>
<ExpansionPanelSummary expandIcon={<ChevronDown></ChevronDown>}>
<AccordionSummary expandIcon={<ChevronDown></ChevronDown>}>
<Typography>{`${t("general/git-repository")} (${t(
"general/optional",
)})`}</Typography>
</ExpansionPanelSummary>
<ExpansionPanelDetails>
</AccordionSummary>
<AccordionDetails>
<Box>
<TextField
label={t("general/url")}
Expand Down Expand Up @@ -220,8 +234,8 @@ export default function ConfigureNotebookDialog(props: Props) {
</Box>
) : null}
</Box>
</ExpansionPanelDetails>
</ExpansionPanel>
</AccordionDetails>
</Accordion>
)}
</DialogContent>
<DialogActions>
Expand Down
14 changes: 12 additions & 2 deletions src/components/DeleteNoteDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -21,9 +21,17 @@ interface Props {

export function DeleteNoteDialog(props: Props) {
const { t } = useTranslation();
const isMounted = useRef<boolean>(false);
const note = props.note;
const crossnoteContainer = CrossnoteContainer.useContainer();

useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);

return (
<Dialog open={props.open} onClose={props.onClose}>
<DialogTitle>{t("delete-note-dialog/title")}</DialogTitle>
Expand All @@ -41,7 +49,9 @@ export function DeleteNoteDialog(props: Props) {
note.notebookPath,
note.filePath,
);
props.onClose();
if (isMounted.current) {
props.onClose();
}
}}
>
{t("general/Delete")}
Expand Down
8 changes: 5 additions & 3 deletions src/components/GraphView.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { debounce } from "@0xgg/echomd";
import {
createStyles,
makeStyles,
Expand Down Expand Up @@ -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]);
Expand Down
2 changes: 1 addition & 1 deletion src/components/NoteCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
Expand Down
12 changes: 11 additions & 1 deletion src/components/NotePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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]);

Expand Down
4 changes: 3 additions & 1 deletion src/containers/crossnote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
4 changes: 3 additions & 1 deletion src/lib/crossnote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/notebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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?:\/\//) ||
Expand Down