mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 06:59:31 +01:00
feat: allow locking from everywhere
This commit is contained in:
@@ -10,9 +10,12 @@ const CheckBox = props => {
|
|||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setChecked(!checked);
|
|
||||||
if (props.onChecked) {
|
if (props.onChecked) {
|
||||||
props.onChecked(!checked);
|
props.onChecked(!checked);
|
||||||
|
setChecked(!checked);
|
||||||
|
}
|
||||||
|
if (props.onClick) {
|
||||||
|
props.onClick();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
width="full"
|
width="full"
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ import Dialog, { showDialog } from "./dialog";
|
|||||||
import * as Icon from "react-feather";
|
import * as Icon from "react-feather";
|
||||||
|
|
||||||
function PasswordDialog(props) {
|
function PasswordDialog(props) {
|
||||||
let password = "";
|
|
||||||
const [isWrong, setIsWrong] = useState(false);
|
const [isWrong, setIsWrong] = useState(false);
|
||||||
const passwordRef = useRef();
|
const passwordRef = useRef();
|
||||||
const submit = useCallback(async () => {
|
const submit = useCallback(async () => {
|
||||||
|
const password = passwordRef.current.value;
|
||||||
if (await props.validate(password)) {
|
if (await props.validate(password)) {
|
||||||
props.onDone();
|
props.onDone();
|
||||||
} else {
|
} else {
|
||||||
setIsWrong(true);
|
setIsWrong(true);
|
||||||
passwordRef.current.focus();
|
passwordRef.current.focus();
|
||||||
}
|
}
|
||||||
}, [setIsWrong, password, props]);
|
}, [setIsWrong, props]);
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
isOpen={true}
|
isOpen={true}
|
||||||
@@ -28,7 +28,6 @@ function PasswordDialog(props) {
|
|||||||
autoFocus
|
autoFocus
|
||||||
variant={isWrong ? "error" : "default"}
|
variant={isWrong ? "error" : "default"}
|
||||||
type="password"
|
type="password"
|
||||||
onChange={e => (password = e.target.value)}
|
|
||||||
placeholder="Enter vault password"
|
placeholder="Enter vault password"
|
||||||
onKeyUp={async e => {
|
onKeyUp={async e => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const menuItems = (note, index) => [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: note.favorite ? "Unfavorite" : "Favorite",
|
title: note.favorite ? "Unfavorite" : "Favorite",
|
||||||
onClick: () => store.getState().favorite(note, index)
|
onClick: () => store.getState().favorite(note)
|
||||||
},
|
},
|
||||||
{ title: "Edit", onClick: () => editorStore.getState().openSession(note) },
|
{ title: "Edit", onClick: () => editorStore.getState().openSession(note) },
|
||||||
{
|
{
|
||||||
@@ -33,9 +33,9 @@ const menuItems = (note, index) => [
|
|||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
const { unlock, lock } = store.getState();
|
const { unlock, lock } = store.getState();
|
||||||
if (!note.locked) {
|
if (!note.locked) {
|
||||||
lock(note, index);
|
lock(note.id);
|
||||||
} else {
|
} else {
|
||||||
unlock(note, index);
|
unlock(note.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -80,7 +80,7 @@ function Note(props) {
|
|||||||
{note.favorite && <Icon.Star size={13} style={{ marginLeft: 5 }} />}
|
{note.favorite && <Icon.Star size={13} style={{ marginLeft: 5 }} />}
|
||||||
</Flex>
|
</Flex>
|
||||||
}
|
}
|
||||||
pinned={note.pinned}
|
pinned={props.pinnable && note.pinned}
|
||||||
menuData={note}
|
menuData={note}
|
||||||
menuItems={menuItems(note, index)}
|
menuItems={menuItems(note, index)}
|
||||||
dropdownRefs={dropdownRefs}
|
dropdownRefs={dropdownRefs}
|
||||||
|
|||||||
@@ -12,12 +12,15 @@ import { useStore as useAppStore } from "../../stores/app-store";
|
|||||||
const Properties = props => {
|
const Properties = props => {
|
||||||
const pinned = useStore(store => store.session.pinned);
|
const pinned = useStore(store => store.session.pinned);
|
||||||
const favorite = useStore(store => store.session.favorite);
|
const favorite = useStore(store => store.session.favorite);
|
||||||
|
const locked = useStore(store => store.session.locked);
|
||||||
const colors = useStore(store => store.session.colors);
|
const colors = useStore(store => store.session.colors);
|
||||||
const tags = useStore(store => store.session.tags);
|
const tags = useStore(store => store.session.tags);
|
||||||
|
|
||||||
const setSession = useStore(store => store.setSession);
|
const setSession = useStore(store => store.setSession);
|
||||||
const setColor = useStore(store => store.setColor);
|
const setColor = useStore(store => store.setColor);
|
||||||
const setTag = useStore(store => store.setTag);
|
const setTag = useStore(store => store.setTag);
|
||||||
|
const toggleLocked = useStore(store => store.toggleLocked);
|
||||||
|
|
||||||
function changeState(prop, value) {
|
function changeState(prop, value) {
|
||||||
setSession(state => {
|
setSession(state => {
|
||||||
state.session[prop] = value;
|
state.session[prop] = value;
|
||||||
@@ -92,13 +95,13 @@ const Properties = props => {
|
|||||||
label="Pin"
|
label="Pin"
|
||||||
onChecked={state => changeState("pinned", state)}
|
onChecked={state => changeState("pinned", state)}
|
||||||
/>
|
/>
|
||||||
|
<CheckBox icon={Icon.Star} checked={favorite} label="Favorite" />
|
||||||
<CheckBox
|
<CheckBox
|
||||||
icon={Icon.Star}
|
icon={Icon.Lock}
|
||||||
checked={favorite}
|
label="Lock"
|
||||||
label="Favorite"
|
checked={locked}
|
||||||
onChecked={state => changeState("favorite", state)}
|
onClick={toggleLocked}
|
||||||
/>
|
/>
|
||||||
<CheckBox icon={Icon.Lock} label="Lock" onChecked={props.onLocked} />
|
|
||||||
<Flex fontSize="body" sx={{ marginBottom: 3 }} alignItems="center">
|
<Flex fontSize="body" sx={{ marginBottom: 3 }} alignItems="center">
|
||||||
<Icon.Book size={18} />
|
<Icon.Book size={18} />
|
||||||
<Text sx={{ marginLeft: 1 }}>Move to notebook</Text>
|
<Text sx={{ marginLeft: 1 }}>Move to notebook</Text>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const DEFAULT_SESSION = {
|
|||||||
id: "",
|
id: "",
|
||||||
pinned: false,
|
pinned: false,
|
||||||
favorite: false,
|
favorite: false,
|
||||||
|
locked: false,
|
||||||
tags: [],
|
tags: [],
|
||||||
colors: [],
|
colors: [],
|
||||||
dateEdited: 0,
|
dateEdited: 0,
|
||||||
@@ -58,8 +59,8 @@ function editorStore(set, get) {
|
|||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
console.log(e);
|
if (e.message === "ERR_WRNG_PwD") return false;
|
||||||
return false;
|
else console.error(e);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
@@ -73,6 +74,7 @@ function editorStore(set, get) {
|
|||||||
pinned: note.pinned,
|
pinned: note.pinned,
|
||||||
favorite: note.favorite,
|
favorite: note.favorite,
|
||||||
colors: note.colors,
|
colors: note.colors,
|
||||||
|
locked: note.locked,
|
||||||
tags: note.tags,
|
tags: note.tags,
|
||||||
dateEdited: note.dateEdited,
|
dateEdited: note.dateEdited,
|
||||||
content,
|
content,
|
||||||
@@ -86,7 +88,17 @@ function editorStore(set, get) {
|
|||||||
state.session.isSaving = true;
|
state.session.isSaving = true;
|
||||||
});
|
});
|
||||||
const { session } = get();
|
const { session } = get();
|
||||||
const { title, id, content, pinned, favorite, tags, colors } = session;
|
const {
|
||||||
|
title,
|
||||||
|
id,
|
||||||
|
content,
|
||||||
|
pinned,
|
||||||
|
favorite,
|
||||||
|
locked,
|
||||||
|
tags,
|
||||||
|
colors
|
||||||
|
} = session;
|
||||||
|
|
||||||
let note = {
|
let note = {
|
||||||
content,
|
content,
|
||||||
title,
|
title,
|
||||||
@@ -96,6 +108,7 @@ function editorStore(set, get) {
|
|||||||
tags,
|
tags,
|
||||||
colors
|
colors
|
||||||
};
|
};
|
||||||
|
|
||||||
db.notes.add(note).then(id => {
|
db.notes.add(note).then(id => {
|
||||||
if (tags.length > 0) updateContext("tags", tags);
|
if (tags.length > 0) updateContext("tags", tags);
|
||||||
if (colors.length > 0) {
|
if (colors.length > 0) {
|
||||||
@@ -113,7 +126,7 @@ function editorStore(set, get) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
notesState.refresh();
|
notesState.refresh();
|
||||||
saveLastOpenedNote(id);
|
saveLastOpenedNote(locked ? undefined : id);
|
||||||
|
|
||||||
// we update favorites only if favorite has changed
|
// we update favorites only if favorite has changed
|
||||||
if (!oldSession || oldSession.favorite !== session.favorite) {
|
if (!oldSession || oldSession.favorite !== session.favorite) {
|
||||||
@@ -144,6 +157,14 @@ function editorStore(set, get) {
|
|||||||
saveLastOpenedNote();
|
saveLastOpenedNote();
|
||||||
noteStore.getState().setSelectedNote(0);
|
noteStore.getState().setSelectedNote(0);
|
||||||
},
|
},
|
||||||
|
toggleLocked: function() {
|
||||||
|
const { session } = get();
|
||||||
|
if (session.locked) {
|
||||||
|
noteStore.getState().unlock(session.id);
|
||||||
|
} else {
|
||||||
|
noteStore.getState().lock(session.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
setColor: function(color) {
|
setColor: function(color) {
|
||||||
setTagOrColor(get().session, "colors", color, "color", get().setSession);
|
setTagOrColor(get().session, "colors", color, "color", get().setSession);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ function noteStore(set, get) {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
setSelectedContext: function(context) {
|
setSelectedContext: function(context) {
|
||||||
|
console.log("setting context");
|
||||||
let notes = [];
|
let notes = [];
|
||||||
switch (context.type) {
|
switch (context.type) {
|
||||||
case "tag":
|
case "tag":
|
||||||
@@ -77,44 +78,34 @@ function noteStore(set, get) {
|
|||||||
await db.notes.note(note).pin();
|
await db.notes.note(note).pin();
|
||||||
set(state => {
|
set(state => {
|
||||||
state.notes = db.notes.group(undefined, true);
|
state.notes = db.notes.group(undefined, true);
|
||||||
syncEditor(note, "pinned");
|
|
||||||
});
|
});
|
||||||
|
syncEditor(note.id, "pinned");
|
||||||
},
|
},
|
||||||
favorite: async function(note, index) {
|
favorite: async function(note) {
|
||||||
await db.notes.note(note).favorite();
|
await db.notes.note(note).favorite();
|
||||||
set(state => {
|
setValue(set, note.id, "favorite", !note.favorite);
|
||||||
if (index < 0 || !index) {
|
|
||||||
index = state.notes.items.findIndex(n => n.id === note.id);
|
|
||||||
if (index < 0) return;
|
|
||||||
}
|
|
||||||
state.notes.items[index].favorite = !note.favorite;
|
|
||||||
});
|
|
||||||
syncEditor(note, "favorite");
|
|
||||||
get().refreshList(LIST_TYPES.fav);
|
get().refreshList(LIST_TYPES.fav);
|
||||||
},
|
},
|
||||||
unlock: function(note, index) {
|
unlock: function(noteId) {
|
||||||
showPasswordDialog("unlock_note", password => {
|
showPasswordDialog("unlock_note", password => {
|
||||||
return db.vault
|
return db.vault
|
||||||
.remove(note.id, password)
|
.remove(noteId, password)
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch(() => false);
|
.catch(e => {
|
||||||
|
if (e.message === "ERR_WRNG_PWD") return false;
|
||||||
|
else console.error(e);
|
||||||
|
});
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res) {
|
if (res) {
|
||||||
set(state => {
|
setValue(set, noteId, "locked", false);
|
||||||
state.notes.items[index].locked = false;
|
|
||||||
});
|
|
||||||
syncEditor(note, "locked");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
lock: function lock(note, index) {
|
lock: function lock(noteId) {
|
||||||
db.vault
|
db.vault
|
||||||
.add(note.id)
|
.add(noteId)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
set(state => {
|
setValue(set, noteId, "locked", true);
|
||||||
state.notes.items[index].locked = true;
|
|
||||||
});
|
|
||||||
syncEditor(note, "locked");
|
|
||||||
})
|
})
|
||||||
.catch(async ({ message }) => {
|
.catch(async ({ message }) => {
|
||||||
switch (message) {
|
switch (message) {
|
||||||
@@ -128,22 +119,34 @@ function noteStore(set, get) {
|
|||||||
})
|
})
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result === true) {
|
if (result === true) {
|
||||||
lock(note, index);
|
lock(noteId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncEditor(note, action) {
|
function syncEditor(noteId, action) {
|
||||||
const editorState = editorStore.getState();
|
const editorState = editorStore.getState();
|
||||||
if (editorState.session.id === note.id) {
|
if (editorState.session.id === noteId) {
|
||||||
editorState.setSession(
|
editorState.setSession(
|
||||||
state => (state.session[action] = !state.session[action])
|
state => (state.session[action] = !state.session[action])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setValue(set, noteId, prop, value) {
|
||||||
|
set(state => {
|
||||||
|
const arr = !state.selectedNotes.length
|
||||||
|
? state.notes.items
|
||||||
|
: state.selectedNotes;
|
||||||
|
let index = arr.findIndex(n => n.id === noteId);
|
||||||
|
if (index < 0) return;
|
||||||
|
arr[index][prop] = value;
|
||||||
|
});
|
||||||
|
syncEditor(noteId, prop);
|
||||||
|
}
|
||||||
|
|
||||||
const [useStore, store] = createStore(noteStore);
|
const [useStore, store] = createStore(noteStore);
|
||||||
|
|
||||||
export { useStore, store, LIST_TYPES };
|
export { useStore, store, LIST_TYPES };
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ function Home() {
|
|||||||
notes.groupCounts[groupIndex] && (
|
notes.groupCounts[groupIndex] && (
|
||||||
<Note
|
<Note
|
||||||
index={index}
|
index={index}
|
||||||
|
pinnable={true}
|
||||||
groupIndex={groupIndex}
|
groupIndex={groupIndex}
|
||||||
item={notes.items[index]}
|
item={notes.items[index]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,9 +16,12 @@ const Notes = props => {
|
|||||||
clearSelectedContext();
|
clearSelectedContext();
|
||||||
};
|
};
|
||||||
}, [clearSelectedContext]);
|
}, [clearSelectedContext]);
|
||||||
|
console.log("refreshing notesssss", selectedNotes);
|
||||||
return (
|
return (
|
||||||
<ListContainer
|
<ListContainer
|
||||||
item={index => <Note index={index} item={selectedNotes[index]} />}
|
item={index => (
|
||||||
|
<Note index={index} pinnable={false} item={selectedNotes[index]} />
|
||||||
|
)}
|
||||||
itemsLength={selectedNotes.length}
|
itemsLength={selectedNotes.length}
|
||||||
button={{
|
button={{
|
||||||
content: "Make a new note",
|
content: "Make a new note",
|
||||||
|
|||||||
Reference in New Issue
Block a user