diff --git a/apps/web/src/common/selectionoptions.js b/apps/web/src/common/selectionoptions.js index 30204401e..ec5c2e564 100644 --- a/apps/web/src/common/selectionoptions.js +++ b/apps/web/src/common/selectionoptions.js @@ -68,7 +68,7 @@ const UnfavoriteOption = createOption(Icon.Star, function(state) { if (!item.favorite) return; await db.notes.note(item.id).favorite(); }); - notesStore.getState().setSelectedContext({ type: "favorites" }); + notesStore.getState().setContext({ type: "favorites" }); }); const AddToNotebookOption = createOption(Icon.Plus, async function(state) { diff --git a/apps/web/src/common/vault.js b/apps/web/src/common/vault.js index d090633fc..a209e5ee0 100644 --- a/apps/web/src/common/vault.js +++ b/apps/web/src/common/vault.js @@ -16,5 +16,34 @@ class Vault { .catch(() => false); }); } + + static unlockNote(id, done) { + showPasswordDialog("unlock_note", password => { + return db.vault + .remove(id, password) + .then(() => true) + .catch(e => { + if (e.message === "ERR_WRNG_PWD") return false; + else console.error(e); + }); + }).then(res => res && done()); + } + + static lockNote(id, done) { + db.vault + .add(id) + .then(done) + .catch(({ message }) => { + switch (message) { + case "ERR_NO_VAULT": + return Vault.createVault(); + case "ERR_VAULT_LOCKED": + return Vault.unlockVault(); + default: + return false; + } + }) + .then(result => result && this.lock(id)); + } } export default Vault; diff --git a/apps/web/src/components/note/index.js b/apps/web/src/components/note/index.js index 3db3ce810..d186da8ea 100644 --- a/apps/web/src/components/note/index.js +++ b/apps/web/src/components/note/index.js @@ -56,7 +56,7 @@ function menuItems(note, context) { .notebook(context.notebook.id) .topics.topic(context.value) .delete(note.id); - await store.getState().setSelectedContext(context); + await store.getState().setContext(context); } }); } diff --git a/apps/web/src/stores/app-store.js b/apps/web/src/stores/app-store.js index 8467ce760..73822e573 100644 --- a/apps/web/src/stores/app-store.js +++ b/apps/web/src/stores/app-store.js @@ -14,7 +14,7 @@ class AppStore extends BaseStore { refresh = () => { noteStore.getState().refresh(); notebookStore.getState().refresh(); - noteStore.getState().refreshSelectedContext(); + noteStore.getState().refreshContext(); trashStore.getState().refresh(); this.refreshColors(); }; diff --git a/apps/web/src/stores/editor-store.js b/apps/web/src/stores/editor-store.js index da8c2cf24..3109eb9b7 100644 --- a/apps/web/src/stores/editor-store.js +++ b/apps/web/src/stores/editor-store.js @@ -138,7 +138,7 @@ function editorStore(set, get) { // we update favorites only if favorite has changed if (!oldSession || oldSession.favorite !== session.favorite) { - notesState.setSelectedContext({ type: "favorites" }); + notesState.setContext({ type: "favorites" }); } }); }, @@ -206,10 +206,10 @@ function updateContext(key, array) { let type = key === "colors" ? "color" : "tag"; // update notes if the selected context (the current view in the navigator) is a tag or color const notesState = noteStore.getState(); - const context = notesState.selectedContext; + const context = notesState.context; if (context.type === type) { const isValue = array.some(value => value === context.value); - if (isValue) noteStore.getState().setSelectedContext(context); + if (isValue) noteStore.getState().setContext(context); } if (type === "tag") { tagStore.getState().refreshTags(); diff --git a/apps/web/src/stores/note-store.js b/apps/web/src/stores/note-store.js index 6218b70e0..767c237c6 100644 --- a/apps/web/src/stores/note-store.js +++ b/apps/web/src/stores/note-store.js @@ -1,149 +1,108 @@ import { db } from "../common/index"; import createStore from "../common/store"; import { store as editorStore } from "./editor-store"; -import { store as appStore } from "./app-store"; -import { showPasswordDialog } from "../components/dialogs/passworddialog"; import Vault from "../common/vault"; +import BaseStore from "."; -function noteStore(set, get) { - return { - notes: { - items: [], - groupCounts: [], - groups: [] - }, - selectedNotes: [], - selectedContext: {}, - selectedNote: 0, - setSelectedNote: function(id) { - set(state => { - state.selectedNote = id; - }); - }, - refresh: function() { - set(state => { - //TODO save group type - state.notes = db.notes.group(undefined, true); - }); - }, - refreshSelectedContext: function() { - const { setSelectedContext, selectedContext } = get(); - if (!selectedContext.type) return; - setSelectedContext(selectedContext); - }, - setSelectedContext: function(context) { - let notes = []; - switch (context.type) { - case "tag": - notes = db.notes.tagged(context.value); - break; - case "color": - notes = db.notes.colored(context.value); - break; - case "topic": - notes = db.notebooks - .notebook(context.notebook.id) - .topics.topic(context.value).all; - break; - case "favorites": - notes = db.notes.favorites; - break; - default: - return; - } - set(state => { - state.selectedContext = context; - state.selectedNotes = notes; - }); - }, - clearSelectedContext: function() { - set(state => { - state.selectedContext = {}; - state.selectedNotes = []; - }); - }, - delete: async function(id) { - await db.notes.delete(id); - const state = get(); - state.setSelectedContext(state.selectedContext); - state.refresh(); - const editorState = editorStore.getState(); - if (editorState.session.id === id) { - editorState.newSession(); - } - }, - pin: async function(note) { - await db.notes.note(note).pin(); - set(state => { - state.notes = db.notes.group(undefined, true); - }); - syncEditor(note.id, "pinned"); - }, - favorite: async function(note) { - await db.notes.note(note).favorite(); - setValue(set, note.id, "favorite", !note.favorite); - }, - unlock: function(noteId) { - showPasswordDialog("unlock_note", password => { - return db.vault - .remove(noteId, password) - .then(() => true) - .catch(e => { - if (e.message === "ERR_WRNG_PWD") return false; - else console.error(e); - }); - }).then(res => { - if (res) { - setValue(set, noteId, "locked", false); - } - }); - }, - lock: function lock(noteId) { - db.vault - .add(noteId) - .then(() => { - setValue(set, noteId, "locked", true); - }) - .catch(async ({ message }) => { - switch (message) { - case "ERR_NO_VAULT": - return Vault.createVault(); - case "ERR_VAULT_LOCKED": - return Vault.unlockVault(); - default: - return false; - } - }) - .then(result => { - if (result === true) { - lock(noteId); - } - }); +class NoteStore extends BaseStore { + notes = { + items: [], + groupCounts: [], + groups: [] + }; + context = undefined; + selectedNote = 0; + + setSelectedNote = id => { + this.set(state => (state.selectedNote = id)); + }; + + refresh = () => { + this.set(state => (state.notes = db.notes.group(undefined, true))); + }; + + refreshContext = () => { + if (!this.context) return; + this.setContext(this.context); + }; + + setContext = context => { + let notes = []; + switch (context.type) { + case "tag": + notes = db.notes.tagged(context.value); + break; + case "color": + notes = db.notes.colored(context.value); + break; + case "topic": + notes = db.notebooks + .notebook(context.notebook.id) + .topics.topic(context.value).all; + break; + case "favorites": + notes = db.notes.favorites; + break; + default: + return; + } + this.set(state => (state.context = { ...context, notes })); + }; + + delete = async id => { + await db.notes.delete(id); + this.refreshContext(); + this.refresh(); + const { session, newSession } = editorStore.getState(); + if (session.id === id) { + newSession(); + } + }; + + pin = async note => { + await db.notes.note(note).pin(); + this.refresh(); + this._syncEditor(note.id, "pinned"); + }; + + favorite = async note => { + await db.notes.note(note).favorite(); + this._setValue(note.id, "favorite", !note.favorite); + }; + + unlock = id => { + Vault.unlockNote(id, () => this._setValue(id, "locked", false)); + }; + + lock = id => { + Vault.lockNote(id, () => this._setValue(id, "locked", true)); + }; + + /** + * @private + */ + _setValue = (noteId, prop, value) => { + this.set(state => { + const { context, notes } = state; + const arr = !context ? notes.items : context.notes; + let index = arr.findIndex(note => note.id === noteId); + if (index < 0) return; + + arr[index][prop] = value; + this._syncEditor(noteId, prop); + }); + }; + + /** + * @private + */ + _syncEditor = (noteId, action) => { + const { session, setSession } = editorStore.getState(); + if (session.id === noteId) { + setSession(state => (state.session[action] = !state.session[action])); } }; } -function syncEditor(noteId, action) { - const editorState = editorStore.getState(); - if (editorState.session.id === noteId) { - editorState.setSession( - 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 }; diff --git a/apps/web/src/views/Notes.js b/apps/web/src/views/Notes.js index 75053d630..616b3e262 100644 --- a/apps/web/src/views/Notes.js +++ b/apps/web/src/views/Notes.js @@ -7,19 +7,14 @@ import { DEFAULT_CONTEXT } from "../common"; function Notes(props) { const newSession = useStore(store => store.newSession); - const selectedNotes = useNotesStore(store => store.selectedNotes); - const selectedContext = useNotesStore(store => store.selectedContext); + const context = useNotesStore(store => store.context); + return ( ( - + )} button={{ content: "Make a new note", diff --git a/apps/web/src/views/Tags.js b/apps/web/src/views/Tags.js index ca8fb241c..994c00537 100644 --- a/apps/web/src/views/Tags.js +++ b/apps/web/src/views/Tags.js @@ -18,7 +18,7 @@ function TagNode({ title }) { } function Tags(props) { - const setSelectedContext = useNotesStore(store => store.setSelectedContext); + const setContext = useNotesStore(store => store.setContext); const tags = useStore(store => store.tags); useEffect(() => { store.getState().refreshTags(); @@ -37,7 +37,7 @@ function Tags(props) { title={} info={`${noteIds.length} notes`} onClick={() => { - setSelectedContext({ type: "tag", value: title }); + setContext({ type: "tag", value: title }); props.navigator.navigate("notes", { title: "#" + title, context: { tags: [title] } diff --git a/apps/web/src/views/Topics.js b/apps/web/src/views/Topics.js index 5f4c181d8..e2df01e77 100644 --- a/apps/web/src/views/Topics.js +++ b/apps/web/src/views/Topics.js @@ -7,7 +7,7 @@ import { useStore as useNbStore } from "../stores/notebook-store"; import { showTopicDialog } from "../components/dialogs/topicdialog"; function Topics(props) { - const setSelectedContext = useNoteStore(store => store.setSelectedContext); + const setContext = useNoteStore(store => store.setContext); const setSelectedNotebookTopics = useNbStore( store => store.setSelectedNotebookTopics ); @@ -34,7 +34,7 @@ function Topics(props) { item={item} onClick={() => { let topic = item; - setSelectedContext({ + setContext({ type: "topic", value: topic.title, notebook: props.notebook