Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
286b2b39be | ||
|
|
6eb383c75a | ||
|
|
f6a93061fd | ||
|
|
96246a1e33 | ||
|
|
1f38f67871 | ||
|
|
203d7ad881 | ||
|
|
725fe41db2 |
1
.github/workflows/vericrypt-deploy.yml
vendored
@@ -29,6 +29,7 @@ jobs:
|
||||
- run: |
|
||||
cd apps/vericrypt
|
||||
npm i
|
||||
npm run build
|
||||
mv ./build/ ./public_html/
|
||||
|
||||
- uses: blbecker/rsync-deploy@v1.0
|
||||
|
||||
72
README.md
@@ -1,50 +1,15 @@
|
||||
<p align="center">
|
||||
|
||||
<img style="align:center;" src="https://app.notesnook.com/apple-touch-icon.png" alt="Notesnook Logo" width="100" />
|
||||
</p>
|
||||
|
||||
<h1 align="center">Notesnook</h1>
|
||||
<h2 align="center">Take private notes, capture ideas, make lists & sync them anywhere</h2>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/5davZnhw3V"><img alt="Chat with us on Discord" src="https://img.shields.io/discord/796015620436787241?label=Chat%20with%20us&logo=discord&logoColor=white"/></a>
|
||||
<a href="https://GitHub.com/streetwriters/notesnook/issues/"><img src="https://img.shields.io/github/issues/streetwriters/notesnook.svg"/></a>
|
||||
<a href="https://twitter.com/notesnook"><img alt="Follow us on Twitter @notesnook" src="https://img.shields.io/twitter/follow/notesnook?label=Follow%20us%20%40notesnook&logo=twitter&style=social"></a>
|
||||
<a href="https://notesnook.com/">Website</a> | <a href="https://notesnook.com/roadmap">Roadmap</a> | <a href="https://notesnook.com/downloads">Downloads</a> | <a href="https://twitter.com/@notesnook">Twitter</a> | <a href="https://discord.gg/5davZnhw3V">Discord</a>
|
||||
</p>
|
||||
|
||||
<p align="center"><img src="https://github.com/streetwriters/notesnook/raw/main/banners/crossplatform.jpg" alt="Notesnook - Take private notes" width="75%"/></p>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://play.google.com/store/apps/details?id=com.streetwriters.notesnook">
|
||||
<img alt="Get it on Google Play" src="https://github.com/streetwriters/notesnook/raw/main/badges/google.png" height="50px">
|
||||
</a>
|
||||
<a href="https://apps.apple.com/pk/app/notesnook-take-private-notes/id1544027013">
|
||||
<img alt="Download on the App Store" src="https://raw.githubusercontent.com/irshad/notesnook/main/badges/app-store-badge.png" height="50px">
|
||||
</a>
|
||||
<a href="https://app.notesnook.com/">
|
||||
<img alt="Try Notesnook on the Web" src="https://github.com/streetwriters/notesnook/raw/main/badges/web.png" height="50px" style="margin-left: 15px">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 😎 Features
|
||||
|
||||
Privacy isn't the only thing we have:
|
||||
|
||||
1. Cross platform - Notesnook has apps on all platforms
|
||||
2. End to end encrypted sync to unlimted devices
|
||||
3. Organize your notes using:
|
||||
1. Notebooks
|
||||
2. Topics
|
||||
3. Tags
|
||||
4. Colors
|
||||
4. Encrypt/lock your notes locally
|
||||
5. Full rich text editor with markdown support
|
||||
6. Focus mode (distraction-free mode)
|
||||
7. Export notes as HTML, MD, PDF & TXT
|
||||
8. Automatic backups
|
||||
9. Dark mode and custom accents
|
||||
|
||||
**_Note: You can checkout a preview of all these features on [the website](https://notesnook.com/)._**
|
||||
> ## Announcement:
|
||||
>
|
||||
> ### We will be open sourcing Notesnook in July-August, 2022. Follow our [Twitter](https://twitter.com/@notesnook) for updates.
|
||||
|
||||
## Support
|
||||
|
||||
@@ -55,11 +20,11 @@ You can reach out to us via:
|
||||
3. [Twitter](https://twitter.com/notesnook)
|
||||
4. [Create an issue](https://github.com/streetwriters/notesnook/issues/new)
|
||||
|
||||
We take all queries, issues, bug reports that you might have. Feel free to ask.
|
||||
We take all queries, issues and bug reports that you might have. Feel free to ask.
|
||||
|
||||
## 🛣️ Roadmap
|
||||
|
||||
This is just the beginning; we are not stopping here. **Read what we have planned for Notesnook in [our roadmap](https://github.com/streetwriters/notesnook/blob/main/ROADMAP.md).**
|
||||
This is just the beginning; we are not stopping here. **Read what we have planned for Notesnook in [our roadmap](https://notesnook.com/roadmap).**
|
||||
|
||||
## ❓ FAQs
|
||||
|
||||
@@ -69,8 +34,8 @@ There are [many](https://en.wikipedia.org/wiki/Comparison_of_note-taking_softwar
|
||||
|
||||
These are the 4 problems that Notesnook solves:
|
||||
|
||||
1. No compromise on security and user privacy
|
||||
2. No sacrifice on important note taking features (e.g. note locking, PDF exports, organize via notebooks, topics & tags)
|
||||
1. No compromise on security and user privacy.
|
||||
2. No sacrifice on important note taking features (e.g. note locking, PDF exports, organize via notebooks, topics & tags).
|
||||
3. Provides a simple, easy to use user interface.
|
||||
4. Works exactly the same on all platforms.
|
||||
|
||||
@@ -78,13 +43,11 @@ At Notesnook we believe in `simple privacy`. Simple privacy means giving you ful
|
||||
|
||||
### If you are so privacy focused, why did you not make Notesnook open source?
|
||||
|
||||
Notesnook is developed & maintained by a small team (only 3 people). The effort required to make it "open source-able" (writing good docs, managing pull requests etc) is currently out of our scope. We want to make a good product and ship it to you as fast as possible.
|
||||
|
||||
However, we have plans to open source the core parts of Notesnook (like the auth, encryption, storage etc.) that'll be reusable and auditable by the public.
|
||||
Notesnook is going open source in July-August 2022 (subject to change).
|
||||
|
||||
### Can I self host Notesnook?
|
||||
|
||||
Nope. Not right now. We might make the sync server available for self-hosting in the future (after certain procedures) but as of now, no.
|
||||
Nope. Not right now. We have plans to make the sync server available for self-hosting in the future (after certain procedures) after the client apps are open sourced.
|
||||
|
||||
### What happens to my notes if Notesnook is abandoned?
|
||||
|
||||
@@ -116,10 +79,10 @@ Anyone offering privacy for free is scamming you to sell your data. Why? Because
|
||||
`$4.49/mo` is worth it because:
|
||||
|
||||
1. It is cheaper than all other premium note taking apps (like Evernote, Standard Notes).
|
||||
2. It is the minimum viable price you can spend to ensure your notes' privacy. (If you self host, the cheapest VPS will cost you around $5).
|
||||
2. It is the minimum viable price you can spend to ensure your notes' privacy. (If you self host, the cheapest VPS will cost you around \$5).
|
||||
3. Your subscription is evidence that privacy is a global issue and should be addressed. That you care.
|
||||
|
||||
If you still think $4.49/mo is too much, you are welcome to spend >$4.49/mo on some other privacy invasive note taking app. :)
|
||||
If you still think $4.49/mo is too much, you are welcome to spend >$4.49/mo on some other privacy invasive note taking app :)
|
||||
|
||||
## Contribute
|
||||
|
||||
@@ -135,18 +98,13 @@ Bug reports are given utmost priority. Report it and we'll fix it ASAP.
|
||||
|
||||
### Join our Discord server & help out in the community
|
||||
|
||||
You can join [our Discord server](https://discord.gg/5davZnhw3V) and help other Notesnook users. We also post announcements, host polls, ask for early feedback there.
|
||||
You can join [our Discord server](https://discord.gg/5davZnhw3V) and help other Notesnook users. We also post announcements, host polls and ask for early feedback there.
|
||||
|
||||
### Help us out by giving social proof
|
||||
|
||||
Social proof helps other people know what they are getting. If you have tried out Notesnook and loved it, you can give social proof:
|
||||
|
||||
1. By tweeting about @notesnook on Twitter
|
||||
1. By tweeting about @notesnook on Twitter.
|
||||
2. Posting on Facebook, Reddit or any other social media.
|
||||
|
||||
We take all social proofs and publish them on the website for the public to see.
|
||||
|
||||
---
|
||||
|
||||
<sup>1</sup>Google Play and the Google Play logo are trademarks of Google LLC.<br/>
|
||||
<sup>2</sup>Apple logo® is a trademark of Apple Inc.
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
- [ ] **Two-Factor-Authentication** via Auth app & SMS.
|
||||
- [ ] **Stylus & Drawing Support** to take notes by drawing on the screen. We will be adding a dedicated editor where you can draw and take notes.
|
||||
- [ ] **Note Publishing** on a public url that is viewable by anyone with a shareable link. The note can be encrypted if required before publishing so only people with the password can view it.
|
||||
- [ ] **Links:** A dedicated links screen where user can list all links and import browser bookmarks
|
||||
- [ ] **Links** - A dedicated links screen where user can list all links and import browser bookmarks.
|
||||
- [ ] **Widgets on Android & iOS** - Initially we are working on adding a Quick Note widget to add notes without opening app.
|
||||
|
||||
1832
apps/vericrypt/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/vericrypt",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
@@ -20,6 +20,7 @@
|
||||
"typescript": "^4.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/signalr-protocol-msgpack": "^6.0.7",
|
||||
"@notesnook/crypto": "^1.0.0",
|
||||
"clipboard-polyfill": "^3.0.3",
|
||||
"colord": "^2.9.2",
|
||||
|
||||
BIN
apps/vericrypt/src/assets/screenshots/devtools_requests_ws.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 27 KiB |
@@ -26,7 +26,8 @@ export function ErrorsList(props: ErrorsListProps) {
|
||||
onClick={() =>
|
||||
window.open(
|
||||
"https://github.com/streetwriters/notesnook/issues/new",
|
||||
"_blank"
|
||||
"_blank",
|
||||
"noopener"
|
||||
)
|
||||
}
|
||||
>
|
||||
|
||||
@@ -84,8 +84,8 @@ const steps = {
|
||||
<>
|
||||
On the right panel, you'll see an input with the placeholder "Start from
|
||||
key" at the top. Type <Code text="user" /> in that input. If you don't see
|
||||
the 'user' object, scroll down in key-value pair list and the search
|
||||
again.
|
||||
the 'user' object, scroll to end using <Code text="Page down" /> key in
|
||||
key-value pair list and then search again.
|
||||
</>,
|
||||
`At the top of the list, you'll see an entry with key "user". Expand the value.`,
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import { Flex, Text, Image, Textarea } from "@theme-ui/components";
|
||||
import { StepContainer } from "./StepContainer";
|
||||
import DevtoolsRequestsFilter from "../assets/screenshots/devtools_requests_filter.png";
|
||||
import DevtoolsRequestsCopy from "../assets/screenshots/devtools_requests_copy.png";
|
||||
import DevtoolsRequestsWS from "../assets/screenshots/devtools_requests_ws.png";
|
||||
import DevtoolsRequestsWSMessages from "../assets/screenshots/devtools_requests_ws_messages.png";
|
||||
import DevtoolsRequestsWSMessagesSelect from "../assets/screenshots/devtools_requests_ws_messages_select.png";
|
||||
import DevtoolsRequestsWSMessagesCopy from "../assets/screenshots/devtools_requests_ws_messages_copy.png";
|
||||
|
||||
import DevtoolsRequestsFilterFirefox from "../assets/screenshots/firefox/network_tab_firefox.png";
|
||||
import DevtoolsRequestsCopyFirefox from "../assets/screenshots/firefox/copy_curl_request.png";
|
||||
// Firefox does not support extracting raw WebSocket response data yet.
|
||||
// Once it does we can start using these.
|
||||
// import FirefoxDevtoolsRequestsWS from "../assets/screenshots/firefox/devtools_requests_ws.png";
|
||||
// import FirefoxDevtoolsRequestsFilter from "../assets/screenshots/firefox/devtools_requests_filter.png";
|
||||
// import FirefoxDevtoolsRequestsWSResponse from "../assets/screenshots/firefox/devtools_requests_ws_response.png";
|
||||
// import FirefoxDevtoolsRequestsWSResponseSizeColumn from "../assets/screenshots/firefox/devtools_requests_ws_response_sizecolumn.png";
|
||||
// import FirefoxDevtoolsRequestsWSMessagesSelect from "../assets/screenshots/firefox/devtools_requests_ws_messages_select.png";
|
||||
// import FirefoxDevtoolsRequestsWSMessagesCopy from "../assets/screenshots/firefox/devtools_requests_ws_messages_copy.png";
|
||||
|
||||
import { Accordion } from "./Accordion";
|
||||
import { getCombo } from "../utils/keycombos";
|
||||
@@ -14,7 +23,7 @@ import { Code } from "./Code";
|
||||
import { useState, useEffect } from "react";
|
||||
import { ErrorsList } from "./ErrorsList";
|
||||
import { getSourceUrl } from "../utils/links";
|
||||
import { parseCURL } from "../utils/curlparser";
|
||||
import { MessagePackHubProtocol } from "@microsoft/signalr-protocol-msgpack";
|
||||
|
||||
type PasteEncryptedDataProps = {
|
||||
onEncryptedDataPasted: (data?: SyncRequestBody) => void;
|
||||
@@ -37,16 +46,7 @@ export type SyncRequestBody = {
|
||||
attachments: EncryptedSyncItem[];
|
||||
};
|
||||
|
||||
const SAMPLE_CURL = `Paste your cURL request here.
|
||||
For example:
|
||||
curl 'https://api.notesnook.com/sync'
|
||||
-H 'authority: api.notesnook.com'
|
||||
-H 'authorization: Bearer 84374D98...'
|
||||
-H ...
|
||||
-H ...
|
||||
-H 'content-type: application/json'
|
||||
--data-raw '{"notes":[{...}], "notebooks": [{...}], "content": [{...}], "lastSynced":1443215713231}'
|
||||
--compressed`;
|
||||
const SAMPLE_CURL = `Paste raw base64 encoded data here.`;
|
||||
|
||||
const steps = {
|
||||
chromium: [
|
||||
@@ -58,6 +58,13 @@ const steps = {
|
||||
<>
|
||||
Switch to the <Code text="Network" /> tab.
|
||||
</>,
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">
|
||||
Make sure you have <Code text="WS" /> toggled instead of{" "}
|
||||
<Code text="Fetch/XHR" />
|
||||
</Text>
|
||||
<Image src={DevtoolsRequestsWS} width={400} sx={{ mt: 1 }} />
|
||||
</Flex>,
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">
|
||||
In the filter input, type <Code text="sync" /> to filter out sync
|
||||
@@ -66,63 +73,134 @@ const steps = {
|
||||
<Image src={DevtoolsRequestsFilter} width={400} sx={{ mt: 1 }} />
|
||||
</Flex>,
|
||||
<>
|
||||
At this point, you probably won't see anything useful. Try editing one of
|
||||
your notes and syncing. Make sure to keep the <Code text="Network" /> tab
|
||||
open.
|
||||
<b>Refresh the page by pressing F5</b> (this is done so we can capture the
|
||||
websocket request that happens on startup).
|
||||
</>,
|
||||
<>
|
||||
In the requests table in <Code text="Network" /> tab, you'll now see 3 or
|
||||
more new requests popup.
|
||||
Wait until a request starting with <Code text="sync?access_token=" /> pops
|
||||
up. It'll probably be the only one popping up and might take a bit so
|
||||
don't panic if you don't see anything.
|
||||
</>,
|
||||
<>Left-click on this request to open its details.</>,
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">
|
||||
Switch to the <Code text="Messages" /> tab.
|
||||
</Text>
|
||||
<Image src={DevtoolsRequestsWSMessages} width={400} sx={{ mt: 1 }} />
|
||||
</Flex>,
|
||||
<>
|
||||
At this point, you will a list of Binary messages. None of these will
|
||||
appear really useful. This is normal.
|
||||
</>,
|
||||
<>
|
||||
We are interested in only the <Code text="sync" /> request. Right click on
|
||||
this request to open the context menu.
|
||||
Now try editing one of your notes and syncing. (Make sure to keep the{" "}
|
||||
<Code text="Network" /> tab open.)
|
||||
</>,
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">
|
||||
From the context menu, go to <Code text="Copy" /> & click on{" "}
|
||||
<Code text="Copy as cURL" />.
|
||||
You will see a bunch of new <Code text="Binary Messages" /> appear in
|
||||
the list. Find the one with the largest Length (in KBs). Also make sure
|
||||
the output type is set to <Code text="Base64" /> as in the screenshot
|
||||
below.
|
||||
</Text>
|
||||
<Image src={DevtoolsRequestsCopy} width={400} sx={{ mt: 1 }} />
|
||||
</Flex>,
|
||||
],
|
||||
firefox: [
|
||||
"Focus the Notesnook tab in your browser.",
|
||||
<>
|
||||
Press <KeyCombo combo={getCombo("chromium", "developerTools")} /> to open
|
||||
Developer Tools.
|
||||
</>,
|
||||
<>
|
||||
Switch to the <Code text="Network" /> tab.
|
||||
</>,
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">
|
||||
In the filter input, type <Code text="sync" /> to filter out sync
|
||||
requests.
|
||||
</Text>
|
||||
<Image src={DevtoolsRequestsFilterFirefox} width={400} sx={{ mt: 1 }} />
|
||||
</Flex>,
|
||||
<>
|
||||
At this point, you probably won't see anything useful. Try editing one of
|
||||
your notes and syncing. Make sure to keep the <Code text="Network" /> tab
|
||||
open.
|
||||
</>,
|
||||
<>
|
||||
In the requests table in <Code text="Network" /> tab, you'll now see 3 or
|
||||
more new requests popup.
|
||||
</>,
|
||||
<>
|
||||
We are interested in only the <Code text="sync" /> request. Right click on
|
||||
this request to open the context menu.
|
||||
</>,
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">
|
||||
From the context menu, go to <Code text="Copy" /> & click on{" "}
|
||||
<Code text="Copy as cURL" />.
|
||||
</Text>
|
||||
<Image src={DevtoolsRequestsCopyFirefox} width={400} sx={{ mt: 1 }} />
|
||||
<Image
|
||||
src={DevtoolsRequestsWSMessagesSelect}
|
||||
width={700}
|
||||
sx={{ mt: 1, maxWidth: "95%" }}
|
||||
/>
|
||||
</Flex>,
|
||||
<Flex sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">Click on the copy button to copy the payload.</Text>
|
||||
<Image src={DevtoolsRequestsWSMessagesCopy} width={200} sx={{ mt: 1 }} />
|
||||
</Flex>,
|
||||
<> Paste it below to see the decrypted data.</>,
|
||||
],
|
||||
firefox: [],
|
||||
// firefox: [
|
||||
// "Focus the Notesnook tab in your browser.",
|
||||
// <>
|
||||
// Press <KeyCombo combo={getCombo("firefox", "developerTools")} /> to open
|
||||
// Developer Tools.
|
||||
// </>,
|
||||
// <>
|
||||
// Switch to the <Code text="Network" /> tab.
|
||||
// </>,
|
||||
// <Flex sx={{ flexDirection: "column" }}>
|
||||
// <Text as="p">
|
||||
// Make sure you have <Code text="WS" /> toggled instead of{" "}
|
||||
// <Code text="Fetch/XHR" />
|
||||
// </Text>
|
||||
// <Image src={FirefoxDevtoolsRequestsWS} width={400} sx={{ mt: 1 }} />
|
||||
// </Flex>,
|
||||
// <Flex sx={{ flexDirection: "column" }}>
|
||||
// <Text as="p">
|
||||
// In the filter input, type <Code text="sync" /> to filter out sync
|
||||
// requests.
|
||||
// </Text>
|
||||
// <Image src={FirefoxDevtoolsRequestsFilter} width={400} sx={{ mt: 1 }} />
|
||||
// </Flex>,
|
||||
// <>
|
||||
// <b>Refresh the page by pressing F5</b> (this is done so we can capture the
|
||||
// websocket request that happens on startup).
|
||||
// </>,
|
||||
// <>
|
||||
// Wait until a request starting with <Code text="sync?access_token=" /> pops
|
||||
// up. It'll probably be the only one popping up and might take a bit so
|
||||
// don't panic if you don't see anything.
|
||||
// </>,
|
||||
// <>Left-click on this request to open its details.</>,
|
||||
// <Flex sx={{ flexDirection: "column" }}>
|
||||
// <Text as="p">
|
||||
// Switch to the <Code text="Response" /> tab.
|
||||
// </Text>
|
||||
// <Image
|
||||
// src={FirefoxDevtoolsRequestsWSResponse}
|
||||
// width={400}
|
||||
// sx={{ mt: 1 }}
|
||||
// />
|
||||
// </Flex>,
|
||||
// <>
|
||||
// At this point, you will a list of Binary messages. None of these will
|
||||
// appear really useful. This is normal.
|
||||
// </>,
|
||||
// <Flex sx={{ flexDirection: "column" }}>
|
||||
// <Text as="p">
|
||||
// To help in finding the right request, <Code text="Right click" /> on the
|
||||
// table header & enable the <Code text="Size" /> column.
|
||||
// </Text>
|
||||
// <Image
|
||||
// src={FirefoxDevtoolsRequestsWSResponseSizeColumn}
|
||||
// width={300}
|
||||
// sx={{ mt: 1 }}
|
||||
// />
|
||||
// </Flex>,
|
||||
// <>
|
||||
// Now try editing one of your notes and syncing. (Make sure to keep the{" "}
|
||||
// <Code text="Network" /> tab open.)
|
||||
// </>,
|
||||
// <Flex sx={{ flexDirection: "column" }}>
|
||||
// <Text as="p">
|
||||
// You will see a bunch of new items appear in the table. Find the one with
|
||||
// the largest Length (in KBs).
|
||||
// </Text>
|
||||
// <Image
|
||||
// src={FirefoxDevtoolsRequestsWSMessagesSelect}
|
||||
// width={700}
|
||||
// sx={{ mt: 1, maxWidth: "95%" }}
|
||||
// />
|
||||
// </Flex>,
|
||||
// <Flex sx={{ flexDirection: "column" }}>
|
||||
// <Text as="p">
|
||||
// Right-click on the item & click on <Code text="Copy Message" />
|
||||
// </Text>
|
||||
// <Image
|
||||
// src={FirefoxDevtoolsRequestsWSMessagesCopy}
|
||||
// width={400}
|
||||
// sx={{ mt: 1 }}
|
||||
// />
|
||||
// </Flex>,
|
||||
// <> Paste it below to see the decrypted data.</>,
|
||||
// ],
|
||||
};
|
||||
|
||||
const isChromium = Platform.name === "Chrome";
|
||||
@@ -161,23 +239,37 @@ export function PasteEncryptedData(props: PasteEncryptedDataProps) {
|
||||
borderRadius: "default",
|
||||
}}
|
||||
>
|
||||
<Text variant="body" sx={{ mx: 2 }}>
|
||||
To make this whole process verifiable & trustworthy, we need to
|
||||
extract the raw data that Notesnook sends to its servers during sync.
|
||||
That way you can be sure that the data leaving your device is actually
|
||||
encrypted or not.
|
||||
</Text>
|
||||
<Text as="ol" variant="body" sx={{ mb: 2 }}>
|
||||
{instructions?.map((item) => (
|
||||
<Text as="li" sx={{ mt: 1 }}>
|
||||
{item}
|
||||
{isChromium ? (
|
||||
<>
|
||||
<Text variant="body" sx={{ mx: 2 }}>
|
||||
To make this whole process verifiable & trustworthy, we need
|
||||
to extract the raw data that Notesnook sends to its servers during
|
||||
sync. That way you can be sure that the data leaving your device
|
||||
is actually encrypted or not.
|
||||
</Text>
|
||||
))}
|
||||
</Text>
|
||||
<Text as="ol" variant="body" sx={{ mb: 2 }}>
|
||||
{instructions?.map((item) => (
|
||||
<Text as="li" sx={{ mt: 1 }}>
|
||||
{item}
|
||||
</Text>
|
||||
))}
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<Flex sx={{ bg: "errorBg", p: 1 }}>
|
||||
<Text as="p" variant="body" sx={{ color: "error" }}>
|
||||
Currently Firefox does not support pasting raw data from the
|
||||
WebSocket response view.{" "}
|
||||
<b>Please use a Chromium-based browser</b> for grabbing the
|
||||
necessary data.
|
||||
</Text>
|
||||
</Flex>
|
||||
)}
|
||||
</Accordion>
|
||||
<Textarea
|
||||
variant="forms.clean"
|
||||
placeholder={SAMPLE_CURL}
|
||||
spellCheck={false}
|
||||
sx={{
|
||||
mt: 2,
|
||||
fontSize: "body",
|
||||
@@ -188,28 +280,67 @@ export function PasteEncryptedData(props: PasteEncryptedDataProps) {
|
||||
onChange={(e) => {
|
||||
try {
|
||||
setError(undefined);
|
||||
const curlRequest = e.target.value;
|
||||
if (!curlRequest) return setEncryptedData(undefined);
|
||||
const parsed = parseCURL(curlRequest);
|
||||
const base64Data = e.target.value;
|
||||
|
||||
if (parsed.url !== "https://api.notesnook.com/sync") {
|
||||
throw new Error(
|
||||
"Invalid cURL request. URL must be https://api.notesnook.com/sync."
|
||||
);
|
||||
const protocol = new MessagePackHubProtocol();
|
||||
const messages = protocol
|
||||
.parseMessages(toArrayBuffer(base64Data), {
|
||||
log: console.log,
|
||||
})
|
||||
.filter((m) => m.type === 1);
|
||||
|
||||
if (!messages.length) {
|
||||
setError("Invalid message.");
|
||||
return setEncryptedData(undefined);
|
||||
}
|
||||
|
||||
if (!parsed.data)
|
||||
throw new Error("Invalid cURL request. No data found.");
|
||||
const syncData: SyncRequestBody = {
|
||||
attachments: [],
|
||||
content: [],
|
||||
notebooks: [],
|
||||
notes: [],
|
||||
};
|
||||
for (const message of messages) {
|
||||
if (message.type === 1) {
|
||||
const { items, types } = message.arguments[0] as {
|
||||
items?: string[];
|
||||
types?: string[];
|
||||
};
|
||||
if (!items || !types) continue;
|
||||
|
||||
for (let i = 0; i < types.length; ++i) {
|
||||
const itemType = types[i];
|
||||
const item = JSON.parse(items[i]) as EncryptedSyncItem;
|
||||
|
||||
switch (itemType) {
|
||||
case "note":
|
||||
syncData.notes.push(item);
|
||||
break;
|
||||
case "notebook":
|
||||
syncData.notebooks.push(item);
|
||||
break;
|
||||
case "content":
|
||||
syncData.content.push(item);
|
||||
break;
|
||||
case "attachment":
|
||||
syncData.attachments.push(item);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const syncData: SyncRequestBody = JSON.parse(parsed.data);
|
||||
if (syncData.notes.length <= 0 && syncData.content.length <= 0) {
|
||||
throw new Error(
|
||||
"Empty cURL request. Make sure the request body contains at least 1 note or 1 content."
|
||||
"The pasted data does not contain any notes. Please select another payload."
|
||||
);
|
||||
}
|
||||
|
||||
setEncryptedData(syncData);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
const error = e as Error;
|
||||
setError(error.message);
|
||||
}
|
||||
@@ -239,3 +370,13 @@ export function PasteEncryptedData(props: PasteEncryptedDataProps) {
|
||||
</StepContainer>
|
||||
);
|
||||
}
|
||||
|
||||
function toArrayBuffer(payload: string) {
|
||||
var binary_string = window.atob(payload);
|
||||
var len = binary_string.length;
|
||||
var bytes = new Uint8Array(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
bytes[i] = binary_string.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
const LITERAL_NAMES = {
|
||||
CURL: "curl",
|
||||
INCLUDE_HEADERS: "include-headers",
|
||||
SILENT: "run-silent",
|
||||
USE_GET: "use-get",
|
||||
COMPRESSED: "compressed",
|
||||
STATES: {
|
||||
HEADER: "header-state",
|
||||
CUSTOM_METHOD: "custom-method-state",
|
||||
DATA: "data-state",
|
||||
USER: "user-state",
|
||||
},
|
||||
STRING: "string",
|
||||
OTHERS: "others",
|
||||
};
|
||||
|
||||
const literals = [
|
||||
{
|
||||
regex: /^\bcurl\b/,
|
||||
name: LITERAL_NAMES.CURL,
|
||||
},
|
||||
{
|
||||
regex: /^(-H|--header)/,
|
||||
name: LITERAL_NAMES.STATES.HEADER,
|
||||
},
|
||||
{
|
||||
regex: /^-X/,
|
||||
name: LITERAL_NAMES.STATES.CUSTOM_METHOD,
|
||||
},
|
||||
{
|
||||
regex: /^(-u|--user)/,
|
||||
name: LITERAL_NAMES.STATES.USER,
|
||||
},
|
||||
{
|
||||
regex: /^(-d|--data-raw|--data-ascii|--data)/,
|
||||
name: LITERAL_NAMES.STATES.DATA,
|
||||
},
|
||||
{
|
||||
regex: /^--compressed/,
|
||||
name: LITERAL_NAMES.COMPRESSED,
|
||||
},
|
||||
{
|
||||
regex: /^(-i|--include)/,
|
||||
name: LITERAL_NAMES.INCLUDE_HEADERS,
|
||||
},
|
||||
{
|
||||
regex: /^(-s|--silent)/,
|
||||
name: LITERAL_NAMES.SILENT,
|
||||
},
|
||||
{
|
||||
regex: /^(-G|--get)/,
|
||||
name: LITERAL_NAMES.USE_GET,
|
||||
},
|
||||
{
|
||||
regex: /^'[^']*'/,
|
||||
name: LITERAL_NAMES.STRING,
|
||||
},
|
||||
{
|
||||
regex: /^"[^"]*"/,
|
||||
name: LITERAL_NAMES.STRING,
|
||||
},
|
||||
{
|
||||
regex: /^[^\n\r\s]*/,
|
||||
name: LITERAL_NAMES.STRING,
|
||||
},
|
||||
{
|
||||
regex: /^.*/,
|
||||
name: LITERAL_NAMES.OTHERS,
|
||||
},
|
||||
];
|
||||
|
||||
const trimValue = (val: string) =>
|
||||
val
|
||||
.trim()
|
||||
.replace(/^('|")\s*/, "")
|
||||
.replace(/\s*('|")$/, "");
|
||||
|
||||
const isURL = (val: string) =>
|
||||
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w\-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/\\\w]*))?)/.test(
|
||||
val
|
||||
);
|
||||
|
||||
type Token = { name: string; value: RegExpMatchArray | null };
|
||||
type ParsedCurlRequest = {
|
||||
url: string;
|
||||
method: string;
|
||||
headers: Record<string, string>;
|
||||
data?: string;
|
||||
};
|
||||
|
||||
export function parseCURL(curlCmd: string) {
|
||||
let cmd = curlCmd.trim();
|
||||
const tokens: Token[] = [];
|
||||
const result: ParsedCurlRequest = {
|
||||
url: "",
|
||||
method: "GET",
|
||||
headers: {} as Record<string, string>,
|
||||
data: "",
|
||||
};
|
||||
while (cmd) {
|
||||
for (const literal of literals) {
|
||||
if (literal.regex.test(cmd)) {
|
||||
tokens.push({
|
||||
name: literal.name,
|
||||
value: cmd.match(literal.regex),
|
||||
});
|
||||
|
||||
cmd = cmd.replace(literal.regex, "").trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens.length) {
|
||||
if (tokens.shift()?.name !== "curl") {
|
||||
throw new Error("Not a curl command.");
|
||||
}
|
||||
|
||||
let state = "";
|
||||
tokens.forEach((token) => {
|
||||
if (!token.value) return;
|
||||
|
||||
if (!state) {
|
||||
switch (token.name) {
|
||||
case LITERAL_NAMES.STATES.HEADER:
|
||||
state = LITERAL_NAMES.STATES.HEADER;
|
||||
break;
|
||||
case LITERAL_NAMES.STATES.DATA:
|
||||
state = LITERAL_NAMES.STATES.DATA;
|
||||
break;
|
||||
case LITERAL_NAMES.STATES.CUSTOM_METHOD:
|
||||
state = LITERAL_NAMES.STATES.CUSTOM_METHOD;
|
||||
break;
|
||||
case LITERAL_NAMES.STATES.USER:
|
||||
state = LITERAL_NAMES.STATES.USER;
|
||||
break;
|
||||
case LITERAL_NAMES.STRING: {
|
||||
const val = trimValue(token.value[0]);
|
||||
if (isURL(val)) {
|
||||
result.url = val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (state) {
|
||||
case LITERAL_NAMES.STATES.HEADER: {
|
||||
const pair = trimValue(token.value[0]).split(/\s*:\s*/);
|
||||
result.headers[pair[0]] = pair[1];
|
||||
break;
|
||||
}
|
||||
case LITERAL_NAMES.STATES.DATA: {
|
||||
console.log(token);
|
||||
const pair = token.value[0];
|
||||
result.data = trimValue(pair).trim();
|
||||
break;
|
||||
}
|
||||
case LITERAL_NAMES.STATES.CUSTOM_METHOD: {
|
||||
const pair = token.value[0];
|
||||
result.method = trimValue(pair).trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
state = "";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"downlevelIteration": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
---
|
||||
icon: pencil
|
||||
order: 990
|
||||
label: Creating a note
|
||||
label: Create a note
|
||||
---
|
||||
|
||||
# Creating a note
|
||||
You are in a notes app, the first thing you want to do is make a note.
|
||||
# Create a note
|
||||
Once you have successfully installed [Notesnook](https://notesnook.com/downloads/), the first thing you may want to do is create a note.
|
||||
|
||||
To create a note on
|
||||
|
||||
+++ Desktop/Web
|
||||
1. Click on the `+` button on top right corner or click anywhere inside the editor to focus it.
|
||||
2. Start writing and your note will be created.
|
||||
3. As you write, note will be saved automatically whenever you stop for a second.
|
||||
1. Click on the green colored `+` button in the top right corner of the `Notes` section.
|
||||
2. Start writing in the editor and your note will be created automatically with your current date and time as note title. Alternatively, you can name your note title yourself.
|
||||
3. Notes will be saved automatically whenever you stop writing for a time interval of more than one second.
|
||||
+++ Mobile/Tablet
|
||||
1. On mobile, just like desktop, regardless of what screen you have opened, you can always swipe from right to left and open the editor.
|
||||
2. You can also press the `+` button on bottom right corner to open the editor when you are in `Notes`, a `Notebook` or `Tag`.
|
||||
3. Start writing in editor and your note will be created.
|
||||
4. As you write, note will be saved automatically whenever you stop for a second.
|
||||
1. On mobile, regardless of what section of the app you have opened, you can always swipe from right to left and open the editor.
|
||||
2. Alternatively, you can also press the `+` button in the bottom right corner to open the editor when you are in `Notes`, a `Notebook`, or `Tag` section.
|
||||
3. Start writing in the editor and your note will be created automatically with your current date and time as note title. Alternatively, you can name your note title yourself.
|
||||
4. Notes will be saved automatically whenever you stop writing for a time interval of more than one second.
|
||||
+++
|
||||
|
||||
And that is how you create your first private note on Notesnook!
|
||||
Congratulations, You have successfully created your first private note on Notesnook!
|
||||
|
||||
@@ -11,28 +11,28 @@ We are currently working on writing detailed docs for our app. The current versi
|
||||
!!!
|
||||
|
||||
|
||||
Notesnook is a simple and cross-platform **private notes app** that keeps all your notes organized and synced on your phone, tablet and computer.
|
||||
Notesnook is a simple and cross-platform **private notes app** that keeps all your notes organized and synced between your phone, tablet and computer.
|
||||
|
||||
<img src="https://github.com/streetwriters/notesnook/raw/main/banners/crossplatform.jpg" alt="Notesnook - Take private notes"/>
|
||||
|
||||
We use best-in-class encryption algorithms **XChaCha20-Poly1305 & Argon2** that are stronger & safer than AES256, impenetrable & future-proof. Your notes are encrypted on your device. All your notes are 100% private. **No one but you can read your notes (not even us).**
|
||||
We use best-in-class encryption algorithms **XChaCha20-Poly1305 & Argon2** that are stronger & safer than AES256, impenetrable & future-proof. Your notes are always encrypted on your device first and then stored on servers. All your notes are 100% private. **No one but only you can read your notes (not even us).**
|
||||
|
||||
Take notes, capture ideas, create to-do lists, keep a journal, write your assignments and manage projects, we have got you covered everywhere.
|
||||
|
||||
## Features
|
||||
|
||||
Privacy isn't the only thing that Notesnook has to offer:
|
||||
Privacy isn't the only thing that Notesnook offers:
|
||||
|
||||
1. Cross platform - Notesnook has apps on all platforms and works even on your browser.
|
||||
2. End to end encrypted private note syncing to unlimted devices
|
||||
3. Organize your notes with notebooks, tags and colors
|
||||
4. Encrypt/lock your notes in a private vault locally
|
||||
5. Full rich text editor with markdown support
|
||||
6. Focus mode (distraction-free mode)
|
||||
7. Export notes in HTML, Markdown, PDF & Text formats
|
||||
8. Automatic backups
|
||||
9. Dark mode and custom accents
|
||||
10. Notesnook Monograph - Share your notes on public url with one click in a safe and secure way
|
||||
1. Cross platform - Notesnook supports apps on all platforms and works even on your browser.
|
||||
2. End to end encrypted private note syncing between unlimited devices.
|
||||
3. Organize your notes with notebooks, tags and colors.
|
||||
4. Encrypt/lock your notes in a private vault locally.
|
||||
5. Full rich text editor with markdown support.
|
||||
6. Focus mode (distraction-free mode).
|
||||
7. Export notes in HTML, Markdown, PDF & other Text formats.
|
||||
8. Automatic backups.
|
||||
9. Dark mode and custom accents.
|
||||
10. Notesnook Monograph - Share your notes on public url with just one click in a safe and secure way.
|
||||
|
||||
Notesnook is specifically designed for each platform to give you the best private note taking experience.
|
||||
|
||||
@@ -42,8 +42,8 @@ Notesnook is available to download on Android, iOS, Windows, MacOS, and Linux. P
|
||||
|
||||
## Support
|
||||
|
||||
Technical support questions are best asked on our [Discord](https://discord.com/invite/5davZnhw3V). We are available there 24/7 to respond to your queries. You can also chat with us there and other members who are using notesnook and share your experience.
|
||||
For technical questions, doubts or support, join our [Discord](https://discord.com/invite/5davZnhw3V). We are available 24/7 to respond to your queries. You can also join to communicate our ever growing community members and share your experiences on Discord.
|
||||
|
||||
If you find a bug or would like to submit a feature request, please create an [Issue](https://github.com/streetwriters/notesnook/issues) and we will investigate right away.
|
||||
If you found any bug or like to submit a feature request, please create an [Issue](https://github.com/streetwriters/notesnook/issues) and we will review right away.
|
||||
|
||||
Do you have a general inquiry? Please feel free to contact us at support@notesnook.com.
|
||||
If you have any other general inquiry, feel free to contact us at support@notesnook.com.
|
||||
|
||||