diff --git a/app/package.json b/app/package.json index 2e1bb853..9c7d8a31 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "micropad", - "version": "3.29.1", + "version": "3.30.0", "private": true, "scripts": { "preinstall": "python3 ../libs/build-libs.py; ./get_precache_files.py > src/extraPrecacheFiles.ts", diff --git a/app/src/app/ReadOnly.ts b/app/src/app/ReadOnly.ts new file mode 100644 index 00000000..0dfe8d46 --- /dev/null +++ b/app/src/app/ReadOnly.ts @@ -0,0 +1,10 @@ +import { isDev } from './util'; + +export function isReadOnlyNotebook(title: string) { + // All notebooks are editable in dev mode + if (isDev()) { + return false; + } + + return title === 'Help'; +} diff --git a/app/src/app/actions.ts b/app/src/app/actions.ts index fb96e219..4b254033 100644 --- a/app/src/app/actions.ts +++ b/app/src/app/actions.ts @@ -62,12 +62,11 @@ export const actions = { imagePasted: actionCreator.async('IMAGE_PASTED'), exportAll: actionCreator.async('EXPORT_ALL_NOTEPADS'), exportToMarkdown: actionCreator.async('EXPORT_ALL_NOTEPADS_TO_MD'), - clearOldData: actionCreator.async('CLEAR_OLD_DATA'), + clearOldData: actionCreator.async<{ silent: boolean }, void, Error>('CLEAR_OLD_DATA'), getHelp: actionCreator.async('GET_HELP'), getDueDates: actionCreator.async('GET_DUE_DATES'), moveObjAcrossNotepads: actionCreator.async('CROSS_NOTEPAD_MOVE'), - started: actionCreator('APP_STARTED'), restoreJsonNotepad: actionCreator('PARSE_JSON_NOTEPAD'), restoreJsonNotepadAndLoadNote: actionCreator('PARSE_JSON_NOTEPAD_AND_LOAD_NOTE'), newNotepad: actionCreator('NEW_NOTEPAD'), @@ -120,3 +119,25 @@ export const actions = { closeNotepad: actionCreator('CLOSE_NOTEPAD'), importMarkdown: actionCreator('IMPORT_FROM_MARKDOWN') }; + +export const READ_ONLY_ACTIONS: ReadonlySet = new Set([ + actions.quickNote.started.type, + actions.quickNote.done.type, + actions.quickNote.failed.type, + + actions.imagePasted.started.type, + actions.imagePasted.done.type, + actions.imagePasted.failed.type, + + actions.updateElement.type, + actions.quickMarkdownInsert.type, + actions.insertElement.type, + actions.toggleInsertMenu.type, + actions.openEditor.type, + actions.renameNotepadObject.type, + actions.newSection.type, + actions.newNote.type, + actions.moveNotepadObject.type, + actions.deleteElement.type, + actions.deleteNotepadObject.type +]); diff --git a/app/src/app/assets/Help.npx b/app/src/app/assets/Help.npx index bb29a4d5..47494ca6 100644 --- a/app/src/app/assets/Help.npx +++ b/app/src/app/assets/Help.npx @@ -1,4 +1,4 @@ -data:image/png;base64,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RECCrj4gAiIgAiIgAj4gIEH3QSOqCiIgAiIgAiIgQVcfEAEREAEREAEfEJCg+6ARVQUREAEREAERkKCrD4iACIiACIiADwhI0H3QiKqCCIiACIiACEjQ1QdEQAREQAREwAcEJOg+aERVQQREQAREQAQk6OoDIiACIiACIuADAhJ0HzSiqiACIiACIiACEnT1AREQAREQARHwAQEJug8aUVUQAREQAREQAQm6+oAIiIAIiIAI+ICABN0HjagqiIAIiIAIiIAEXX1ABERABERABHxAQILug0ZUFURABERABERAgq4+IAIiIAIiIAI+ICBB90EjqgoiIAIiIAIiIEFXHxABERABERABHxCQoPugEVUFERABERABEZCgqw+IgAiIgAiIgA8ISNB90IiqggiIgAiIgAhI0NUHREAEREAERMAHBCToPmhEVUEEREAEREAEJOjqAyIgAiIgAiLgAwISdB80oqogAiIgAiIgAhJ09QEREAEREAER8AEBCboPGlFVEAEREAEREAEJuvqACIiACIiACPiAgATdB42oKoiACIiACIiABF19QAREQAREQAR8QECC7oNGVBVEQAREQAREQIKuPiACIiACIiACPiAgQfdBI6oKIiACIiACIiBBVx8QAREQAREQAR8QkKD7oBFVBREQAREQARGQoKsPiIAIiIAIiIAPCEjQfdCIqoIIiIAIiIAISNDVB0RABERABETABwQk6D5oRFVBBERABERABCTo6gMiIAIiIAIi4AMCEnQfNKKqIAIiIAIiIAISdPUBERABERABEfABAQm6DxpRVRABERABERABCbr6gAiIgAiIgAj4gIAE3QeNqCqIgAiIgAiIgARdfUAEREAEREAEfEBAgu6DRlQVREAEREAERECCrj4gAiIgAiIgAj4gIEH3QSOqCiIgAiIgAiIgQVcfEAEREAEREAEfEJCg+6ARVQUREAEREAERkKCrD4iACIiACIiADwhI0H3QiKqCCIiACIiACEjQ1QdEQAREQAREwAcEJOg+aERVQQREQAREQAQk6OoDIiACIiACIuADAhJ0HzSiqiACIiACIiACEnT1AREQAREQARHwAQEJug8aUVUQAREQAREQAQm6+oAIiIAIiIAI+ICABN0HjagqiIAIiIAIiIAEXX1ABERABERABHxAQILug0ZUFURABERABERAgq4+IAIiIAIiIAI+ICBB90EjqgoiIAIiIAIiIEFXHxABERABERABHxCQoPugEVUFERABERABEZCgqw+IgAiIgAiIgA8ISNB90IiqggiIgAiIgAhI0NUHREAEREAERMAHBCToPmhEVUEEREAEREAEJOjqAyIgAiIgAiLgAwISdB80oqogAiIgAiIgAhJ09QEREAEREAER8AEBCboPGlFVEAEREAEREAEJuvqACIiACIiACPiAgATdB42oKoiACIiACIiABF19QAREQAREQAR8QECC7oNGVBVEQAREQAREQIKuPiACIiACIiACPiAgQfdBI6oKIiACIiACIiBBVx8QAREQAREQAR8QkKD7oBFVBREQAREQARGQoKsPiIAIiIAIiIAPCEjQfdCIqoIIiIAIiIAISNDVB0RABERABETABwQk6D5oRFVBBERABERABCTo6gMiIAIiIAIi4AMCEnQfNKKqIAIiIAIiIAISdPUBERABERABEfABAQm6DxpRVRABERABERABCbr6gAiIgAiIgAj4gIAE3QeNqCqIgAiIgAiIgARdfUAEREAEREAEfEBAgu6DRlQVREAEREAERECCrj4gAiIgAiIgAj4gIEH3QSOqCiIgAiIgAiIgQVcfEAEREAEREAEfEJCg+6ARVQUREAEREAERkKCrD4iACIiACIiADwhI0H3QiKqCCIiACIiACEjQ1QdEQAREQAREwAcEJOg+aERVQQREQAREQAQk6OoDIiACIiACIuADAhJ0HzSiqiACIiACIiACEnT1AREQAREQARHwAQEJug8aUVUQAREQAREQAQm6+oAIiIAIiIAI+ICABN0HjagqiIAIiIAIiIAEXX1ABERABERABHxAQILug0ZUFURABERABERAgq4+IAIiIAIiIAI+ICBB90EjqgoiIAIiIAIiIEFXHxABERABERABHxCQoPugEVUFERABERABEZCgqw+IgAiIgAiIgA8ISNB90IiqggiIgAiIgAhI0NUHREAEREAERMAHBCToPmhEVUEEREAEREAEJOjqAyIgAiIgAiLgAwISdB80oqogAiIgAiIgAhJ09QEREAEREAER8AEBCboPGlFVEAEREAEREAEJuvqACIiACIiACPiAgATdB42oKoiACIiACIiABF19QAREQAREQAR8QECC7oNGVBVEQAREQAREQIKuPiACIiACIiACPiAgQfdBI6oKIiACIiACIiBBVx8QAREQAREQAR8QkKD7oBFVBREQAREQARGQoKsPiIAIiIAIiIAPCEjQfdCIqoIIiIAIiIAISNDVB0RABERABETABwQk6D5oRFVBBERABERABCTo6gMiIAIiIAIi4AMCEnQfNKKqIAIiIAIiIAISdPUBERABERABEfABAQm6DxpRVRABERABERABCbr6gAiIgAiIgAj4gIAE3QeNqCqIgAiIgAiIgARdfUAEREAEREAEfEBAgu6DRlQVREAEREAERECCrj4gAiIgAiIgAj4gIEH3QSOqCiIgAiIgAiIgQVcfEAEREAEREAEfEJCg+6ARVQUREAEREAERkKCrD4iACIiACIiADwhI0H3QiKqCCIiACIiACEjQ1QdEQAREQAREwAcEJOg+aERVQQREQAREQAQk6OoDIiACIiACIuADAhJ0HzSiqiCMwsAMAAADU0lEQVQCIiACIiACEnT1AREQAREQARHwAQEJug8aUVUQAREQAREQAQm6+oAIiIAIiIAI+ICABN0HjagqiIAIiIAIiIAEXX1ABERABERABHxAQILug0ZUFURABERABERAgq4+IAIiIAIiIAI+ICBB90EjqgoiIAIiIAIiIEFXHxABERABERABHxCQoPugEVUFERABERABEZCgqw+IgAiIgAiIgA8ISNB90IiqggiIgAiIgAhI0NUHREAEREAERMAHBCToPmhEVUEEREAEREAEJOjqAyIgAiIgAiLgAwISdB80oqogAiIgAiIgAhJ09QEREAEREAER8AEBCboPGlFVEAEREAEREAEJuvqACIiACIiACPiAgATdB42oKoiACIiACIiABF19QAREQAREQAR8QECC7oNGVBVEQAREQAREQIKuPiACIiACIiACPiAgQfdBI6oKIiACIiACIiBBVx8QAREQAREQAR8QkKD7oBFVBREQAREQARGQoKsPiIAIiIAIiIAPCEjQfdCIqoIIiIAIiIAISNDVB0RABERABETABwQk6D5oRFVBBERABERABCTo6gMiIAIiIAIi4AMCEnQfNKKqIAIiIAIiIAISdPUBERABERABEfABAQm6DxpRVRABERABERABCbr6gAiIgAiIgAj4gIAE3QeNqCqIgAiIgAiIgARdfeD/26sDEgAAAIRh/Vu/x1kEpyABAgQIEBgIOPRBiSIQIECAAAGHbgMECBAgQGAg4NAHJYpAgAABAgQcug0QIECAAIGBgEMflCgCAQIECBBw6DZAgAABAgQGAg59UKIIBAgQIEDAodsAAQIECBAYCDj0QYkiECBAgAABh24DBAgQIEBgIODQByWKQIAAAQIEHLoNECBAgACBgYBDH5QoAgECBAgQcOg2QIAAAQIEBgIOfVCiCAQIECBAwKHbAAECBAgQGAg49EGJIhAgQIAAAYduAwQIECBAYCDg0AclikCAAAECBBy6DRAgQIAAgYGAQx+UKAIBAgQIEHDoNkCAAAECBAYCDn1QoggECBAgQMCh2wABAgQIEBgIOPRBiSIQIECAAAGHbgMECBAgQGAg4NAHJYpAgAABAgQcug0QIECAAIGBgEMflCgCAQIECBAInli+4MiP65oAAAAASUVORK5CYII=
https://getmicropad.com/# What is µPad? +data:image/png;base64,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RECCrj4gAiIgAiIgAj4gIEH3QSOqCiIgAiIgAiIgQVcfEAEREAEREAEfEJCg+6ARVQUREAEREAERkKCrD4iACIiACIiADwhI0H3QiKqCCIiACIiACEjQ1QdEQAREQAREwAcEJOg+aERVQQREQAREQAQk6OoDIiACIiACIuADAhJ0HzSiqiACIiACIiACEnT1AREQAREQARHwAQEJug8aUVUQAREQAREQAQm6+oAIiIAIiIAI+ICABN0HjagqiIAIiIAIiIAEXX1ABERABERABHxAQILug0ZUFURABERABERAgq4+IAIiIAIiIAI+ICBB90EjqgoiIAIiIAIiIEFXHxABERABERABHxCQoPugEVUFERABERABEZCgqw+IgAiIgAiIgA8ISNB90IiqggiIgAiIgAhI0NUHREAEREAERMAHBCToPmhEVUEEREAEREAEJOjqAyIgAiIgAiLgAwISdB80oqogAiIgAiIgAhJ09QEREAEREAER8AEBCboPGlFVEAEREAEREAEJuvqACIiACIiACPiAgATdB42oKoiACIiACIiABF19QAREQAREQAR8QECC7oNGVBVEQAREQAREQIKuPiACIiACIiACPiAgQfdBI6oKIiACIiACIiBBVx8QAREQAREQAR8QkKD7oBFVBREQAREQARGQoKsPiIAIiIAIiIAPCEjQfdCIqoIIiIAIiIAISNDVB0RABERABETABwQk6D5oRFVBBERABERABCTo6gMiIAIiIAIi4AMCEnQfNKKqIAIiIAIiIAISdPUBERABERABEfABAQm6DxpRVRABERABERABCbr6gAiIgAiIgAj4gIAE3QeNqCqIgAiIgAiIgARdfUAEREAEREAEfEBAgu6DRlQVREAEREAERECCrj4gAiIgAiIgAj4gIEH3QSOqCiIgAiIgAiIgQVcfEAEREAEREAEfEJCg+6ARVQUREAEREAERkKCrD4iACIiACIiADwhI0H3QiKqCCIiACIiACEjQ1QdEQAREQAREwAcEJOg+aERVQQREQAREQAQk6OoDIiACIiACIuADAhJ0HzSiqiACIiACIiACEnT1AREQAREQARHwAQEJug8aUVUQAREQAREQAQm6+oAIiIAIiIAI+ICABN0HjagqiIAIiIAIiIAEXX1ABERABERABHxAQILug0ZUFURABERABERAgq4+IAIiIAIiIAI+ICBB90EjqgoiIAIiIAIiIEFXHxABERABERABHxCQoPugEVUFERABERABEZCgqw+IgAiIgAiIgA8ISNB90IiqggiIgAiIgAhI0NUHREAEREAERMAHBCToPmhEVUEEREAEREAEJOjqAyIgAiIgAiLgAwISdB80oqogAiIgAiIgAhJ09QEREAEREAER8AEBCboPGlFVEAEREAEREAEJuvqACIiACIiACPiAgATdB42oKoiACIiACIiABF19QAREQAREQAR8QECC7oNGVBVEQAREQAREQIKuPiACIiACIiACPiAgQfdBI6oKIiACIiACIiBBVx8QAREQAREQAR8QkKD7oBFVBREQAREQARGQoKsPiIAIiIAIiIAPCEjQfdCIqoIIiIAIiIAISNDVB0RABERABETABwQk6D5oRFVBBERABERABCTo6gMiIAIiIAIi4AMCEnQfNKKqIAIiIAIiIAISdPUBERABERABEfABAQm6DxpRVRABERABERABCbr6gAiIgAiIgAj4gIAE3QeNqCqIgAiIgAiIgARdfUAEREAEREAEfEBAgu6DRlQVREAEREAERECCrj4gAiIgAiIgAj4gIEH3QSOqCiIgAiIgAiIgQVcfEAEREAEREAEfEJCg+6ARVQUREAEREAERkKCrD4iACIiACIiADwhI0H3QiKqCCIiACIiACEjQ1QdEQAREQAREwAcEJOg+aERVQQREQAREQAQk6OoDIiACIiACIuADAhJ0HzSiqiACIiACIiACEnT1AREQAREQARHwAQEJug8aUVUQAREQAREQAQm6+oAIiIAIiIAI+ICABN0HjagqiIAIiIAIiIAEXX1ABERABERABHxAQILug0ZUFURABERABERAgq4+IAIiIAIiIAI+ICBB90EjqgoiIAIiIAIiIEFXHxABERABERABHxCQoPugEVUFERABERABEZCgqw+IgAiIgAiIgA8ISNB90IiqggiIgAiIgAhI0NUHREAEREAERMAHBCToPmhEVUEEREAEREAEJOjqAyIgAiIgAiLgAwISdB80oqogAiIgAiIgAhJ09QEREAEREAER8AEBCboPGlFVEAEREAEREAEJuvqACIiACIiACPiAgATdB42oKoiACIiACIiABF19QAREQAREQAR8QECC7oNGVBVEQAREQAREQIKuPiACIiACIiACPiAgQfdBI6oKIiACIiACIiBBVx8QAREQAREQAR8QkKD7oBFVBREQAREQARGQoKsPiIAIiIAIiIAPCEjQfdCIqoIIiIAIiIAISNDVB0RABERABETABwQk6D5oRFVBBERABERABCTo6gMiIAIiIAIi4AMCEnQfNKKqIAIiIAIiIAISdPUBERABERABEfABAQm6DxpRVRABERABERABCbr6gAiIgAiIgAj4gIAE3QeNqCqIgAiIgAiIgARdfUAEREAEREAEfEBAgu6DRlQVREAEREAERECCrj4gAiIgAiIgAj4gIEH3QSOqCiIgAiIgAiIgQVcfEAEREAEREAEfEJCg+6ARVQUREAEREAERkKCrD4iACIiACIiADwhI0H3QiKqCCIiACIiACEjQ1QdEQAREQAREwAcEJOg+aERVQQREQAREQAQk6OoDIiACIiACIuADAhJ0HzSiqiCMwsAMAAADU0lEQVQCIiACIiACEnT1AREQAREQARHwAQEJug8aUVUQAREQAREQAQm6+oAIiIAIiIAI+ICABN0HjagqiIAIiIAIiIAEXX1ABERABERABHxAQILug0ZUFURABERABERAgq4+IAIiIAIiIAI+ICBB90EjqgoiIAIiIAIiIEFXHxABERABERABHxCQoPugEVUFERABERABEZCgqw+IgAiIgAiIgA8ISNB90IiqggiIgAiIgAhI0NUHREAEREAERMAHBCToPmhEVUEEREAEREAEJOjqAyIgAiIgAiLgAwISdB80oqogAiIgAiIgAhJ09QEREAEREAER8AEBCboPGlFVEAEREAEREAEJuvqACIiACIiACPiAgATdB42oKoiACIiACIiABF19QAREQAREQAR8QECC7oNGVBVEQAREQAREQIKuPiACIiACIiACPiAgQfdBI6oKIiACIiACIiBBVx8QAREQAREQAR8QkKD7oBFVBREQAREQARGQoKsPiIAIiIAIiIAPCEjQfdCIqoIIiIAIiIAISNDVB0RABERABETABwQk6D5oRFVBBERABERABCTo6gMiIAIiIAIi4AMCEnQfNKKqIAIiIAIiIAISdPUBERABERABEfABAQm6DxpRVRABERABERABCbr6gAiIgAiIgAj4gIAE3QeNqCqIgAiIgAiIgARdfeD/26sDEgAAAIRh/Vu/x1kEpyABAgQIEBgIOPRBiSIQIECAAAGHbgMECBAgQGAg4NAHJYpAgAABAgQcug0QIECAAIGBgEMflCgCAQIECBBw6DZAgAABAgQGAg59UKIIBAgQIEDAodsAAQIECBAYCDj0QYkiECBAgAABh24DBAgQIEBgIODQByWKQIAAAQIEHLoNECBAgACBgYBDH5QoAgECBAgQcOg2QIAAAQIEBgIOfVCiCAQIECBAwKHbAAECBAgQGAg49EGJIhAgQIAAAYduAwQIECBAYCDg0AclikCAAAECBBy6DRAgQIAAgYGAQx+UKAIBAgQIEHDoNkCAAAECBAYCDn1QoggECBAgQMCh2wABAgQIEBgIOPRBiSIQIECAAAGHbgMECBAgQGAg4NAHJYpAgAABAgQcug0QIECAAIGBgEMflCgCAQIECBAInli+4MiP65oAAAAASUVORK5CYII=
https://getmicropad.com/# What is µPad? µPad, also known as *MicroPad*, is a note taking application that is built upon the principles of power and openness. @@ -14,6 +14,16 @@ of power and openness. - This may be bundled with Electron. The licence for Electron can be found [here](https://github.com/electron/electron/blob/master/LICENSE).
.]]>
\ No newline at end of file +*N.B. Binary asset handling changed as of µPad v2. More information coming soon.*.]]> diff --git a/app/src/app/components/explorer/NotepadExplorerComponent.tsx b/app/src/app/components/explorer/NotepadExplorerComponent.tsx index 0c263558..10c46165 100644 --- a/app/src/app/components/explorer/NotepadExplorerComponent.tsx +++ b/app/src/app/components/explorer/NotepadExplorerComponent.tsx @@ -54,7 +54,10 @@ export default class NotepadExplorerComponent extends React.Component - {notepad.title} + + {notepad.title} + {this.props.isReadOnly && (Read-Only)} + diff --git a/app/src/app/components/explorer/NotepadExplorerContainer.ts b/app/src/app/components/explorer/NotepadExplorerContainer.ts index eec82cc6..856b9b0b 100644 --- a/app/src/app/components/explorer/NotepadExplorerContainer.ts +++ b/app/src/app/components/explorer/NotepadExplorerContainer.ts @@ -21,7 +21,8 @@ export function mapStateToProps({ notepads, explorer, app, currentNote }: IStore openSections: explorer.openSections, isFullScreen: app.isFullScreen, openNote: note, - theme: ThemeValues[app.theme] + theme: ThemeValues[app.theme], + isReadOnly: !!notepads?.notepad?.isReadOnly }; } diff --git a/app/src/app/components/explorer/app-settings/AppSettingsContainer.ts b/app/src/app/components/explorer/app-settings/AppSettingsContainer.ts index ef97d2a4..af133964 100644 --- a/app/src/app/components/explorer/app-settings/AppSettingsContainer.ts +++ b/app/src/app/components/explorer/app-settings/AppSettingsContainer.ts @@ -3,7 +3,7 @@ import { actions } from '../../../actions'; import AppSettingsComponent from './AppSettingsComponent'; export const appSettingsContainer = connect(() => ({}), dispatch => ({ - clearOldData: () => dispatch(actions.clearOldData.started()) + clearOldData: () => dispatch(actions.clearOldData.started({ silent: false })) })); export default appSettingsContainer(AppSettingsComponent); diff --git a/app/src/app/components/explorer/explorer-options/ExplorerOptionsComponent.tsx b/app/src/app/components/explorer/explorer-options/ExplorerOptionsComponent.tsx index 4e7f5e64..72165c5d 100644 --- a/app/src/app/components/explorer/explorer-options/ExplorerOptionsComponent.tsx +++ b/app/src/app/components/explorer/explorer-options/ExplorerOptionsComponent.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { FormEvent } from 'react'; import { Button, Col, Icon, Input, Modal, Row } from 'react-materialize'; import { Notepad } from 'upad-parse/dist'; import { NPXObject } from 'upad-parse/dist/NPXObject'; @@ -88,7 +89,8 @@ export default class ExplorerOptionsComponent extends React.Component { ); } - private rename = () => { + private rename = (e: FormEvent) => { + e.preventDefault(); const { objToEdit, type, renameNotepad, renameNotepadObject } = this.props; const value = this.titleInput.state.value; @@ -107,6 +109,8 @@ export default class ExplorerOptionsComponent extends React.Component { default: break; } + + return false; } private delete = async () => { diff --git a/app/src/app/components/header/NotepadDropdownComponent.tsx b/app/src/app/components/header/NotepadDropdownComponent.tsx index 81463179..0d0fba68 100644 --- a/app/src/app/components/header/NotepadDropdownComponent.tsx +++ b/app/src/app/components/header/NotepadDropdownComponent.tsx @@ -97,6 +97,7 @@ export default class NotepadDropdownComponent extends React.Component { const title = await Dialog.prompt('Notebook/Notepad Title:'); + if (!title) return; let notepad = new FlatNotepad(title); let section = FlatNotepad.makeFlatSection('Unorganised Notes'); diff --git a/app/src/app/components/note-viewer/NoteViewerComponent.tsx b/app/src/app/components/note-viewer/NoteViewerComponent.tsx index 4171bf19..644e6946 100644 --- a/app/src/app/components/note-viewer/NoteViewerComponent.tsx +++ b/app/src/app/components/note-viewer/NoteViewerComponent.tsx @@ -29,6 +29,7 @@ export interface INoteViewerComponentProps { downloadAsset?: (filename: string, uuid: string) => void; updateElement?: (id: string, changes: NoteElement, newAsset?: Blob) => void; toggleInsertMenu?: (opts: Partial) => void; + hideInsert?: () => void; insert?: (element: NoteElement) => void; deleteElement?: (id: string) => void; deleteNotepad?: () => void; @@ -141,14 +142,14 @@ export default class NoteViewerComponent extends React.Component edit!('')); setInterval(() => { if (this.scrolling) { this.scrolling = false; - toggleInsertMenu!({ enabled: false }); + hideInsert?.(); } }, 250); } diff --git a/app/src/app/containers/NoteViewerContainer.ts b/app/src/app/containers/NoteViewerContainer.ts index 68b1dcc5..a5dbf9a2 100644 --- a/app/src/app/containers/NoteViewerContainer.ts +++ b/app/src/app/containers/NoteViewerContainer.ts @@ -12,9 +12,11 @@ import { Note } from 'upad-parse/dist'; let noteRef: string = ''; let note: Note | null; let notepadTitle: string = ''; +let isInsertMenuOpen: boolean = false; export function mapStateToProps({ notepads, currentNote, app }: IStoreState) { noteRef = currentNote.ref; + isInsertMenuOpen = currentNote.insertElement.enabled; if (currentNote.ref.length !== 0) { note = notepads.notepad!.item!.notes[currentNote.ref]; @@ -62,7 +64,11 @@ export function mapDispatchToProps(dispatch: Dispatch): Partial dispatch(actions.quickNotepad(undefined)), makeQuickNote: () => dispatch(actions.quickNote.started(undefined)), - deleteNotepad: () => dispatch(actions.deleteNotepad(notepadTitle)) + deleteNotepad: () => dispatch(actions.deleteNotepad(notepadTitle)), + hideInsert: () => { + if (!isInsertMenuOpen) return; + return dispatch(actions.toggleInsertMenu({ enabled: false })); + } }; } diff --git a/app/src/app/epics/HelpEpics.ts b/app/src/app/epics/HelpEpics.ts index e71fd340..72f682d0 100644 --- a/app/src/app/epics/HelpEpics.ts +++ b/app/src/app/epics/HelpEpics.ts @@ -7,7 +7,9 @@ import { filterTruthy } from '../util'; import { actions, MicroPadAction } from '../actions'; import { Dialog } from '../services/dialogs'; -export const getHelp$ = (action$: Observable, store: EpicStore) => +const HELP_READONLY_DATE = new Date('2021-06-18T14:34:30.958+12:00'); + +export const getHelp$ = (action$: Observable, store: EpicStore, { getStorage }: EpicDeps) => action$.pipe( ofType(actions.getHelp.started.type), concatMap(() => @@ -15,7 +17,15 @@ export const getHelp$ = (action$: Observable, store: EpicStore) const notepadList = store.getState().notepads.savedNotepadTitles; if (!notepadList || !notepadList.includes('Help')) return true; - return Dialog.confirm(`You have already imported the Help notebook. It can be accessed from the notebooks dropdown. If you continue you will lose any changes made to the notebook.`); + const helpLastModified: string | null = await getStorage().notepadStorage.getItem('Help') + .then(np => np ? JSON.parse(np).lastModified : null) + .catch(err => { console.error(err); return null; }); + + if (!helpLastModified || new Date(helpLastModified).getTime() < HELP_READONLY_DATE.getTime()) { + return Dialog.confirm(`You have already imported the Help notebook. It can be accessed from the notebooks dropdown. If you continue you will lose any changes made to the notebook.`); + } + + return true; })()) ), filterTruthy(), diff --git a/app/src/app/epics/NoteEpics.ts b/app/src/app/epics/NoteEpics.ts index 14f1711c..e80d1353 100644 --- a/app/src/app/epics/NoteEpics.ts +++ b/app/src/app/epics/NoteEpics.ts @@ -31,8 +31,8 @@ const loadNote$ = (action$: Observable, store: EpicStore) => ]; } - const error = new Error(`MicroPad couldn't load the current note`); - console.warn(error); + const error = new Error(`MicroPad couldn't load the current note (handled in loadNote$)`); + console.error(error); return [actions.loadNote.failed({ params: ref, error })]; }) ); diff --git a/app/src/app/epics/NotepadEpics.ts b/app/src/app/epics/NotepadEpics.ts index 81a0ed76..6058c839 100644 --- a/app/src/app/epics/NotepadEpics.ts +++ b/app/src/app/epics/NotepadEpics.ts @@ -1,4 +1,4 @@ -import { actions, MicroPadAction } from '../actions'; +import { actions, MicroPadAction, READ_ONLY_ACTIONS } from '../actions'; import { catchError, combineLatest, @@ -43,8 +43,9 @@ import { Dispatch } from 'redux'; import { format } from 'date-fns'; import { NotepadShell } from 'upad-parse/dist/interfaces'; import { fromShell } from '../services/CryptoService'; -import { ASSET_STORAGE, NOTEPAD_STORAGE } from '../root'; +import { ASSET_STORAGE, NOTEPAD_STORAGE, store as STORE } from '../root'; import { EpicDeps, EpicStore } from './index'; +import * as Materialize from 'materialize-css/dist/js/materialize'; const parseQueue: string[] = []; @@ -519,6 +520,27 @@ const moveObjAcrossNotepadsFailure$ = (actions$: Observable) => noEmit() ); +const warnOnReadOnlyEdit$ = (actions$: Observable, store: EpicStore, { getToastEventHandler }: EpicDeps) => + actions$.pipe( + filter(() => !!store.getState().notepads.notepad?.isReadOnly), + filter(action => READ_ONLY_ACTIONS.has(action.type)), + tap(() => { + Materialize.Toast.removeAll(); + const guid = getToastEventHandler().register(async () => { + const newTitle = await Dialog.prompt('New Title:'); + if (!newTitle) return; + + STORE.dispatch(actions.renameNotepad.started(newTitle)); + }) + + Materialize.toast(`This notepad is read-only. Changes will not be saved.
` + + `Please create a notebook or open another one using the notebooks dropdown if you want to edit a notebook.
` + + `If you have made changes to this notebook, you can make it editable by renaming it.
` + + `RENAME`, 10_000); + }), + noEmit() + ) + export const notepadEpics$ = combineEpics( parseNpx$, syncOnNotepadParsed$ as any, @@ -543,7 +565,8 @@ export const notepadEpics$ = combineEpics( quickNotepad$, autoFillNewNotepads$, moveObjAcrossNotepads$, - moveObjAcrossNotepadsFailure$ + moveObjAcrossNotepadsFailure$, + warnOnReadOnlyEdit$ ); interface IExportedNotepad { diff --git a/app/src/app/epics/StorageEpics.ts b/app/src/app/epics/StorageEpics.ts index c76115f3..73b27eff 100644 --- a/app/src/app/epics/StorageEpics.ts +++ b/app/src/app/epics/StorageEpics.ts @@ -4,6 +4,7 @@ import { concatMap, debounceTime, distinctUntilChanged, + distinctUntilKeyChanged, filter, map, mergeMap, @@ -27,6 +28,7 @@ import { NotepadShell } from 'upad-parse/dist/interfaces'; import { ASSET_STORAGE, NOTEPAD_STORAGE } from '../root'; import { ICurrentNoteState } from '../reducers/NoteReducer'; import { EpicDeps, EpicStore } from './index'; +import { isReadOnlyNotebook } from '../ReadOnly'; let currentNotepadTitle = ''; @@ -55,13 +57,14 @@ const saveOnChanges$ = (action$: Observable, store: EpicStore) = map((notepadState: INotepadStoreState) => notepadState.item), filterTruthy(), debounceTime(1000), - distinctUntilChanged(), + distinctUntilKeyChanged('lastModified'), filter((notepad: FlatNotepad) => { const condition = notepad.title === currentNotepadTitle; currentNotepadTitle = notepad.title; return condition; }), + filter(notepad => !isReadOnlyNotebook(notepad.title)), map((notepad: FlatNotepad) => notepad.toNotepad()), mergeMap((notepad: Notepad) => { const actionsToReturn: Action[] = []; @@ -157,7 +160,7 @@ const deleteNotepad$ = (action$: Observable) => ofType>(actions.deleteNotepad.type), map((action: Action) => action.payload), tap((notepadTitle: string) => from(NOTEPAD_STORAGE.removeItem(notepadTitle))), - noEmit() + map(() => actions.clearOldData.started({ silent: true })) ); export type LastOpenedNotepad = { notepadTitle: string, noteRef?: string }; @@ -229,17 +232,17 @@ const clearLastOpenedNotepad$ = (action$: Observable) => const clearOldData$ = (action$: Observable, store: EpicStore) => action$.pipe( - ofType(actions.clearOldData.started.type), - concatMap(() => - from(cleanHangingAssets(NOTEPAD_STORAGE, ASSET_STORAGE, store.getState())).pipe( + ofType>(actions.clearOldData.started.type), + concatMap(action => + from(cleanHangingAssets(NOTEPAD_STORAGE, ASSET_STORAGE, store.getState(), action.payload.silent)).pipe( mergeMap((addPasskeyActions: Action[]) => [ - actions.clearOldData.done({ params: undefined, result: undefined }), + actions.clearOldData.done({ params: action.payload, result: undefined }), ...addPasskeyActions ]), catchError(error => { Dialog.alert('There was an error clearing old data'); console.error(error); - return of(actions.clearOldData.failed({ params: undefined, error })); + return of(actions.clearOldData.failed({ params: action.payload, error })); }) ) ) @@ -247,8 +250,8 @@ const clearOldData$ = (action$: Observable, store: EpicStore) => const notifyOnClearOldDataSuccess$ = (action$: Observable>>) => action$.pipe( - ofType(actions.clearOldData.done.type), - tap(() => Dialog.alert('The spring cleaning has been done!')), + ofType>>(actions.clearOldData.done.type), + tap(action => !action.payload.params.silent && Dialog.alert('The spring cleaning has been done!')), noEmit() ); @@ -271,13 +274,18 @@ export const storageEpics$ = combineEpics( /** * Clean up all the assets that aren't in any notepads yet */ -async function cleanHangingAssets(notepadStorage: LocalForage, assetStorage: LocalForage, state: IStoreState): Promise[]> { +async function cleanHangingAssets(notepadStorage: LocalForage, assetStorage: LocalForage, state: IStoreState, silent): Promise[]> { const cryptoPasskeys: Action[] = []; - const notepads: Promise[] = []; + const notepads: Promise[] = []; await notepadStorage.iterate((json: string) => { const shell: NotepadShell = JSON.parse(json); - notepads.push(fromShell(shell, state.notepadPasskeys[shell.title])); + let passkey = state.notepadPasskeys[shell.title]; + if (!passkey && silent) { + passkey = ''; + } + + notepads.push(fromShell(shell, passkey).catch(err => err)); return; }); @@ -290,7 +298,7 @@ async function cleanHangingAssets(notepadStorage: LocalForage, assetStorage: Loc const areNotepadsStillEncrypted = !!resolvedNotepadsOrErrors.find(res => res instanceof Error); - const resolvedNotepads = resolvedNotepadsOrErrors.filter(res => !(res instanceof Error)).map((cryptoInfo: EncryptNotepadAction) => { + const resolvedNotepads = resolvedNotepadsOrErrors.filter((res): res is EncryptNotepadAction => !(res instanceof Error)).map((cryptoInfo: EncryptNotepadAction) => { cryptoPasskeys.push(actions.addCryptoPasskey({ notepadTitle: cryptoInfo.notepad.title, passkey: cryptoInfo.passkey })); return cryptoInfo.notepad; }); diff --git a/app/src/app/epics/SyncEpics.ts b/app/src/app/epics/SyncEpics.ts index faa80a02..669462ad 100644 --- a/app/src/app/epics/SyncEpics.ts +++ b/app/src/app/epics/SyncEpics.ts @@ -15,7 +15,7 @@ import { } from 'rxjs/operators'; import { Action, Success } from 'redux-typescript-actions'; import { AssetList, ISyncedNotepad, SyncLoginRequest, SyncUser } from '../types/SyncTypes'; -import { ASSET_STORAGE, store as STORE, SYNC_STORAGE, TOAST_HANDLER } from '../root'; +import { ASSET_STORAGE, store as STORE, SYNC_STORAGE } from '../root'; import * as DifferenceEngine from '../services/DifferenceEngine'; import { Dialog } from '../services/dialogs'; import { IStoreState, SYNC_NAME } from '../types'; @@ -103,11 +103,11 @@ export const sync$ = (action$: Observable) => filterTruthy() ); -export const requestDownload$ = (action$: Observable) => +export const requestDownload$ = (action$: Observable, _, { getToastEventHandler }: EpicDeps) => action$.pipe( ofType>(actions.requestSyncDownload.type), tap((action: Action) => { - const guid = TOAST_HANDLER.register(() => STORE.dispatch(actions.syncDownload.started(action.payload))); + const guid = getToastEventHandler().register(() => STORE.dispatch(actions.syncDownload.started(action.payload))); Materialize.toast(`A newer copy of your notepad is online DOWNLOAD`); }), noEmit() diff --git a/app/src/app/epics/index.ts b/app/src/app/epics/index.ts index b6db00ff..86e1b21c 100644 --- a/app/src/app/epics/index.ts +++ b/app/src/app/epics/index.ts @@ -9,7 +9,7 @@ import { noteEpics$ } from './NoteEpics'; import { appEpics$ } from './AppEpics'; import { Action } from 'redux-typescript-actions'; import { cryptoEpics$ } from './CryptoEpics'; -import { getStorage, StorageMap } from '../root'; +import { getStorage, StorageMap, TOAST_HANDLER } from '../root'; import { printEpics$ } from './PrintEpics'; import { helpEpics$ } from './HelpEpics'; import { searchEpics$ } from './SearchEpics'; @@ -18,6 +18,7 @@ import { explorerEpics$ } from './ExplorerEpics'; import { dueDatesEpics$ } from './DueDatesEpics'; import { Dispatch, MiddlewareAPI } from 'redux'; import { IStoreState } from '../types'; +import ToastEventHandler from '../services/ToastEventHandler'; const baseEpic$ = combineEpics( notepadEpics$, @@ -35,13 +36,17 @@ const baseEpic$ = combineEpics( export type EpicDeps = { helpNpx: string, - getStorage: () => StorageMap + getStorage: () => StorageMap, + now: () => Date, + getToastEventHandler: () => ToastEventHandler }; export const epicMiddleware = createEpicMiddleware, any, EpicDeps>(baseEpic$, { dependencies: { helpNpx, - getStorage: getStorage + getStorage: getStorage, + now: () => new Date(), + getToastEventHandler: () => TOAST_HANDLER } }); diff --git a/app/src/app/reducers/BaseReducer.ts b/app/src/app/reducers/BaseReducer.ts index 9d8f0992..38f5ed0a 100644 --- a/app/src/app/reducers/BaseReducer.ts +++ b/app/src/app/reducers/BaseReducer.ts @@ -11,8 +11,9 @@ import { SyncReducer } from './SyncReducer'; import { AppReducer } from './AppReducer'; import { IsExportingReducer } from './IsExportingReducer'; import { NotepadPasskeysReducer } from './NotepadPasskeysReducer'; -import { MicroPadAction } from '../actions'; +import { MicroPadAction, READ_ONLY_ACTIONS } from '../actions'; import { Action, Reducer } from 'redux'; +import { isReadOnlyNotebook } from '../ReadOnly'; export const REDUCERS: Array> = [ new AppReducer(), @@ -42,14 +43,27 @@ export class BaseReducer implements ReduxReducer { public reducer(state: IStoreState | undefined, action: MicroPadAction): IStoreState { if (!state) { - return this.initialState; + state = this.initialState; + } + + if (BaseReducer.isReadonlyViolation(state, action)) { + // Skip any state updates if we're in a readonly notebook + return state; } let newState = { ...state }; - REDUCERS.forEach(reducer => newState[reducer.key] = reducer.reducer(state[reducer.key], action)); + REDUCERS.forEach(reducer => newState[reducer.key] = reducer.reducer(state![reducer.key], action)); return isDev() ? deepFreeze(newState) : newState; } + + private static isReadonlyViolation(state: IStoreState, action: MicroPadAction): boolean { + if (!isReadOnlyNotebook(state.notepads?.notepad?.item?.title ?? '')) { + return false; + } + + return READ_ONLY_ACTIONS.has(action.type); + } } diff --git a/app/src/app/reducers/NotepadsReducer.ts b/app/src/app/reducers/NotepadsReducer.ts index e083044e..389105b4 100644 --- a/app/src/app/reducers/NotepadsReducer.ts +++ b/app/src/app/reducers/NotepadsReducer.ts @@ -8,6 +8,7 @@ import { FlatSection } from 'upad-parse/dist/FlatNotepad'; import { FlatNotepad, Note } from 'upad-parse/dist'; import { format } from 'date-fns'; import { DueItem } from '../services/DueDates'; +import { isReadOnlyNotebook } from '../ReadOnly'; export class NotepadsReducer extends MicroPadReducer { public readonly key = 'notepads'; @@ -17,6 +18,15 @@ export class NotepadsReducer extends MicroPadReducer { }; public reducer(state: INotepadsStoreState, action: Action): INotepadsStoreState { + const newState = this.reducerImpl(state, action); + if (newState.notepad && newState.notepad.item) { + newState.notepad.isReadOnly = isReadOnlyNotebook(newState.notepad?.item?.title ?? ''); + } + + return newState; + } + + private reducerImpl(state: INotepadsStoreState, action: Action): INotepadsStoreState { if (isType(action, actions.parseNpx.done)) { const result = action.payload.result; @@ -29,6 +39,7 @@ export class NotepadsReducer extends MicroPadReducer { notepad: { isLoading: false, saving: false, + isReadOnly: isReadOnlyNotebook(result.title), item: result } }; @@ -83,6 +94,7 @@ export class NotepadsReducer extends MicroPadReducer { notepad: { isLoading: false, saving: false, + isReadOnly: isReadOnlyNotebook(notepad.title), item: notepad } }; diff --git a/app/src/app/root.tsx b/app/src/app/root.tsx index 0b4365bf..f1b4296d 100644 --- a/app/src/app/root.tsx +++ b/app/src/app/root.tsx @@ -32,13 +32,13 @@ import * as PasteImage from 'paste-image'; import PrintViewOrAppContainerComponent from './containers/PrintViewContainer'; import WhatsNewModalComponent from './components/WhatsNewModalComponent'; import { SyncUser } from './types/SyncTypes'; -import { INotepadStoreState } from './types/NotepadTypes'; import { SyncProErrorComponent } from './components/sync/SyncProErrorComponent'; import InsertElementComponent from './containers/InsertElementContainer'; import { ThemeName } from './types/Themes'; import AppBodyComponent from './containers/AppBodyContainer'; import ToastEventHandler from './services/ToastEventHandler'; import { LastOpenedNotepad } from './epics/StorageEpics'; +import { noop } from './util'; try { document.domain = MICROPAD_URL.split('//')[1]; @@ -115,8 +115,8 @@ export function getStorage(): StorageMap { document.getElementById('app') as HTMLElement ); - if (!await localforage.getItem('hasRunBefore')) store.dispatch(actions.getHelp.started()); - await localforage.setItem('hasRunBefore', true); + // Some clean up of an old storage item, this line can be deleted at some point in the future + localforage.removeItem('hasRunBefore').then(noop); await displayWhatsNew(); @@ -124,14 +124,14 @@ export function getStorage(): StorageMap { pasteWatcher(); + store.dispatch(actions.clearOldData.started({ silent: true })); + // Show a warning when closing before notepad save or sync is complete store.subscribe(() => { - const isSaving = store.getState().notepads.isLoading || (store.getState().notepads.notepad || {} as INotepadStoreState).isLoading; + const isSaving = store.getState().notepads.isLoading || store.getState().notepads.notepad?.isLoading; const isSyncing = store.getState().sync.isLoading; window.onbeforeunload = (isSyncing || isSaving) ? () => true : null; }); - - store.dispatch(actions.started()); })(); async function hydrateStoreFromLocalforage() { diff --git a/app/src/app/services/CryptoService.ts b/app/src/app/services/CryptoService.ts index 8705f515..8d4eeb1b 100644 --- a/app/src/app/services/CryptoService.ts +++ b/app/src/app/services/CryptoService.ts @@ -9,7 +9,7 @@ export async function fromShell(shell: NotepadShell, key?: string): Promise { delete this.handlers[guid]; }, 5 * 60 * 1000) + return guid; } } diff --git a/app/src/app/services/dialogs.ts b/app/src/app/services/dialogs.ts index a99f7184..2b8b6012 100644 --- a/app/src/app/services/dialogs.ts +++ b/app/src/app/services/dialogs.ts @@ -23,7 +23,7 @@ export class Dialog { }) ) - public static prompt = (message: string, placeholder?: string): Promise => + public static prompt = (message: string, placeholder?: string): Promise => new Promise(resolve => { setTimeout(() => { Vex.dialog.prompt({ @@ -34,7 +34,7 @@ export class Dialog { }, 0); }) - public static promptSecure = (message: string): Promise => + public static promptSecure = (message: string): Promise => new Promise(resolve => { setTimeout(() => { Vex.dialog.open({ diff --git a/app/src/app/types/NotepadTypes.ts b/app/src/app/types/NotepadTypes.ts index e307da5d..0748795e 100644 --- a/app/src/app/types/NotepadTypes.ts +++ b/app/src/app/types/NotepadTypes.ts @@ -16,6 +16,7 @@ export interface INotepadStoreState { saving: boolean; activeSyncId?: string; scribe?: string; + isReadOnly?: boolean; item?: FlatNotepad; } diff --git a/app/src/app/util.ts b/app/src/app/util.ts index 55f193b2..a7325306 100644 --- a/app/src/app/util.ts +++ b/app/src/app/util.ts @@ -137,3 +137,5 @@ export function debounce(callback: (...args: any[]) => void, time: number) { export function unreachable() { return new Error('Unreachable Error!'); } + +export function noop() {}