mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 15:09:33 +01:00
feat: impl note locking and unlocking
This commit is contained in:
69
apps/web/src/components/dialogs/password-dialog.js
Normal file
69
apps/web/src/components/dialogs/password-dialog.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Box } from "rebass";
|
||||||
|
import { Input } from "@rebass/forms";
|
||||||
|
import Dialog, { showDialog } from "./dialog";
|
||||||
|
import * as Icon from "react-feather";
|
||||||
|
|
||||||
|
function PasswordDialog(props) {
|
||||||
|
let password = "";
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
isOpen={true}
|
||||||
|
title={props.title}
|
||||||
|
icon={props.icon}
|
||||||
|
content={
|
||||||
|
<Box my={1}>
|
||||||
|
<Input
|
||||||
|
variant="default"
|
||||||
|
type="password"
|
||||||
|
onChange={e => (password = e.target.value)}
|
||||||
|
placeholder="Enter vault password"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
positiveButton={{
|
||||||
|
text: props.positiveButtonText,
|
||||||
|
onClick: () => props.onDone(password)
|
||||||
|
}}
|
||||||
|
negativeButton={{ text: "Cancel", onClick: props.onCancel }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDialogData(type) {
|
||||||
|
switch (type) {
|
||||||
|
case "create_vault":
|
||||||
|
return {
|
||||||
|
title: "Set Up Your Vault",
|
||||||
|
icon: Icon.Shield,
|
||||||
|
positiveButtonText: "Done"
|
||||||
|
};
|
||||||
|
case "unlock_vault":
|
||||||
|
return {
|
||||||
|
title: "Unlock Vault",
|
||||||
|
icon: Icon.Unlock,
|
||||||
|
positiveButtonText: "Unlock"
|
||||||
|
};
|
||||||
|
case "unlock_note":
|
||||||
|
return {
|
||||||
|
title: "Unlock Note",
|
||||||
|
icon: Icon.Unlock,
|
||||||
|
positiveButtonText: "Unlock"
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showPasswordDialog = type => {
|
||||||
|
const { title, icon, positiveButtonText } = getDialogData(type);
|
||||||
|
return showDialog(perform => (
|
||||||
|
<PasswordDialog
|
||||||
|
title={title}
|
||||||
|
icon={icon}
|
||||||
|
positiveButtonText={positiveButtonText}
|
||||||
|
onCancel={() => perform()}
|
||||||
|
onDone={password => perform(password)}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
};
|
||||||
@@ -28,7 +28,17 @@ const menuItems = (note, index) => [
|
|||||||
onClick: () => store.getState().favorite(note, index)
|
onClick: () => store.getState().favorite(note, index)
|
||||||
},
|
},
|
||||||
{ title: "Edit", onClick: () => editorStore.getState().openSession(note) },
|
{ title: "Edit", onClick: () => editorStore.getState().openSession(note) },
|
||||||
{ title: note.locked ? "Remove lock" : "Lock" }, //TODO
|
{
|
||||||
|
title: note.locked ? "Unlock" : "Lock",
|
||||||
|
onClick: async () => {
|
||||||
|
const { unlock, lock } = store.getState();
|
||||||
|
if (!note.locked) {
|
||||||
|
lock(note, index);
|
||||||
|
} else {
|
||||||
|
unlock(note, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Move to Trash",
|
title: "Move to Trash",
|
||||||
color: "red",
|
color: "red",
|
||||||
@@ -85,6 +95,7 @@ export default React.memo(Note, function(prevProps, nextProps) {
|
|||||||
prevItem.pinned === nextItem.pinned &&
|
prevItem.pinned === nextItem.pinned &&
|
||||||
prevItem.favorite === nextItem.favorite &&
|
prevItem.favorite === nextItem.favorite &&
|
||||||
prevItem.headline === nextItem.headline &&
|
prevItem.headline === nextItem.headline &&
|
||||||
prevItem.title === nextItem.title
|
prevItem.title === nextItem.title &&
|
||||||
|
prevItem.locked === nextItem.locked
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import createStore from "../common/store";
|
import createStore from "../common/store";
|
||||||
import { db } from "../common";
|
import { db } from "../common";
|
||||||
|
import { showPasswordDialog } from "../components/dialogs/passworddialog";
|
||||||
|
|
||||||
function appStore(set, get) {
|
function appStore(set, get) {
|
||||||
return {
|
return {
|
||||||
@@ -52,6 +53,23 @@ function appStore(set, get) {
|
|||||||
if (get().selectedItems.length <= 0) {
|
if (get().selectedItems.length <= 0) {
|
||||||
get().exitSelectionMode();
|
get().exitSelectionMode();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
createVault: function() {
|
||||||
|
return showPasswordDialog("create_vault").then(password => {
|
||||||
|
if (!password) return false;
|
||||||
|
return db.vault.create(password);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
unlockVault: function unlockVault() {
|
||||||
|
return showPasswordDialog("unlock_vault")
|
||||||
|
.then(password => {
|
||||||
|
if (!password) return false;
|
||||||
|
return db.vault.unlock(password);
|
||||||
|
})
|
||||||
|
.catch(({ message }) => {
|
||||||
|
if (message === "ERR_WRNG_PWD") return unlockVault();
|
||||||
|
else return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { db } from "../common/index";
|
import { db } from "../common/index";
|
||||||
import createStore from "../common/store";
|
import createStore from "../common/store";
|
||||||
import { store as editorStore } from "./editor-store";
|
import { store as editorStore } from "./editor-store";
|
||||||
|
import { store as appStore } from "./app-store";
|
||||||
|
import { showPasswordDialog } from "../components/dialogs/passworddialog";
|
||||||
|
|
||||||
const LIST_TYPES = {
|
const LIST_TYPES = {
|
||||||
fav: "favorites"
|
fav: "favorites"
|
||||||
@@ -89,6 +91,46 @@ function noteStore(set, get) {
|
|||||||
syncEditor(note, "favorite");
|
syncEditor(note, "favorite");
|
||||||
});
|
});
|
||||||
get().refreshList(LIST_TYPES.fav);
|
get().refreshList(LIST_TYPES.fav);
|
||||||
|
},
|
||||||
|
unlock: function unlock(note, index) {
|
||||||
|
showPasswordDialog("unlock_note")
|
||||||
|
.then(password => {
|
||||||
|
if (!password) return;
|
||||||
|
return db.vault.remove(note.id, password);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
set(state => {
|
||||||
|
state.notes.items[index].locked = false;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(({ message }) => {
|
||||||
|
if (message === "ERR_WRNG_PWD") unlock(note, index);
|
||||||
|
else console.log(message);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
lock: function lock(note, index) {
|
||||||
|
db.vault
|
||||||
|
.add(note.id)
|
||||||
|
.then(() => {
|
||||||
|
set(state => {
|
||||||
|
state.notes.items[index].locked = true;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(async ({ message }) => {
|
||||||
|
switch (message) {
|
||||||
|
case "ERR_NO_VAULT":
|
||||||
|
return appStore.getState().createVault();
|
||||||
|
case "ERR_VAULT_LOCKED":
|
||||||
|
return appStore.getState().unlockVault();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
if (result === true) {
|
||||||
|
lock(note, index);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6823,9 +6823,8 @@ normalize-url@^3.0.0, normalize-url@^3.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
|
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
|
||||||
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
|
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
|
||||||
|
|
||||||
"notes-core@https://github.com/thecodrr/notes-core.git":
|
notes-core@../notes-core:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://github.com/thecodrr/notes-core.git#5ee5dfbd5df2abb748cc1a6b8eae6bdad234dba3"
|
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-sort "^2.0.1"
|
fast-sort "^2.0.1"
|
||||||
fuzzysearch "^1.0.3"
|
fuzzysearch "^1.0.3"
|
||||||
@@ -8275,18 +8274,7 @@ quill-markdown-shortcuts@^0.0.10:
|
|||||||
dependencies:
|
dependencies:
|
||||||
quill "^1.3.1"
|
quill "^1.3.1"
|
||||||
|
|
||||||
quill@^1.3.1:
|
quill@^1.3.1, "quill@https://github.com/thecodrr/quill.git#1.3.7":
|
||||||
version "1.3.7"
|
|
||||||
resolved "https://github.com/thecodrr/quill.git#a88a62366eeb52a3b4aa6c4f140426055d7b0bc9"
|
|
||||||
dependencies:
|
|
||||||
clone "^2.1.1"
|
|
||||||
deep-equal "^1.0.1"
|
|
||||||
eventemitter3 "^2.0.3"
|
|
||||||
extend "^3.0.2"
|
|
||||||
parchment "^1.1.4"
|
|
||||||
quill-delta "^3.6.2"
|
|
||||||
|
|
||||||
"quill@https://github.com/thecodrr/quill.git#1.3.7":
|
|
||||||
version "1.3.7"
|
version "1.3.7"
|
||||||
resolved "https://github.com/thecodrr/quill.git#4ff9cee6f27efb2a7bad5aef50b6af140b4629fb"
|
resolved "https://github.com/thecodrr/quill.git#4ff9cee6f27efb2a7bad5aef50b6af140b4629fb"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user