Skip to content

Commit

Permalink
feat: menu with copy text, copy HTMl, uncheck boxes
Browse files Browse the repository at this point in the history
  • Loading branch information
TheodoreChu committed Dec 7, 2020
1 parent 13c72e7 commit f1d7142
Show file tree
Hide file tree
Showing 21 changed files with 243 additions and 45 deletions.
20 changes: 10 additions & 10 deletions build/asset-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"static/js/0.96650d91.chunk.js.map": "./static/js/0.96650d91.chunk.js.map",
"static/js/1.78ca9d6c.chunk.js": "./static/js/1.78ca9d6c.chunk.js",
"static/js/1.78ca9d6c.chunk.js.map": "./static/js/1.78ca9d6c.chunk.js.map",
"main.css": "./static/css/main.52f19b8d.chunk.css",
"main.js": "./static/js/main.a922e0bb.chunk.js",
"main.js.map": "./static/js/main.a922e0bb.chunk.js.map",
"main.css": "./static/css/main.1852c0ce.chunk.css",
"main.js": "./static/js/main.02a84f27.chunk.js",
"main.js.map": "./static/js/main.02a84f27.chunk.js.map",
"runtime-main.js": "./static/js/runtime-main.25e89614.js",
"runtime-main.js.map": "./static/js/runtime-main.25e89614.js.map",
"static/css/4.7c0a8645.chunk.css": "./static/css/4.7c0a8645.chunk.css",
"static/js/4.b613b891.chunk.js": "./static/js/4.b613b891.chunk.js",
"static/js/4.b613b891.chunk.js.map": "./static/js/4.b613b891.chunk.js.map",
"static/js/4.ea980b31.chunk.js": "./static/js/4.ea980b31.chunk.js",
"static/js/4.ea980b31.chunk.js.map": "./static/js/4.ea980b31.chunk.js.map",
"static/js/5.09338a01.chunk.js": "./static/js/5.09338a01.chunk.js",
"static/js/5.09338a01.chunk.js.map": "./static/js/5.09338a01.chunk.js.map",
"static/js/6.ca7d77f3.chunk.js": "./static/js/6.ca7d77f3.chunk.js",
Expand Down Expand Up @@ -152,16 +152,16 @@
"static/js/73.cbdec997.chunk.js.map": "./static/js/73.cbdec997.chunk.js.map",
"index.html": "./index.html",
"static/css/4.7c0a8645.chunk.css.map": "./static/css/4.7c0a8645.chunk.css.map",
"static/css/main.52f19b8d.chunk.css.map": "./static/css/main.52f19b8d.chunk.css.map",
"static/js/4.b613b891.chunk.js.LICENSE.txt": "./static/js/4.b613b891.chunk.js.LICENSE.txt",
"static/css/main.1852c0ce.chunk.css.map": "./static/css/main.1852c0ce.chunk.css.map",
"static/js/4.ea980b31.chunk.js.LICENSE.txt": "./static/js/4.ea980b31.chunk.js.LICENSE.txt",
"static/js/65.393e0ac1.chunk.js.LICENSE.txt": "./static/js/65.393e0ac1.chunk.js.LICENSE.txt",
"static/media/codicon.css": "./static/media/codicon.b3726f01.ttf"
},
"entrypoints": [
"static/js/runtime-main.25e89614.js",
"static/css/4.7c0a8645.chunk.css",
"static/js/4.b613b891.chunk.js",
"static/css/main.52f19b8d.chunk.css",
"static/js/main.a922e0bb.chunk.js"
"static/js/4.ea980b31.chunk.js",
"static/css/main.1852c0ce.chunk.css",
"static/js/main.02a84f27.chunk.js"
]
}
3 changes: 3 additions & 0 deletions build/icons/ic-menu-variant.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion build/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" type="image/png" href="./icon.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="The Append Editor is an unofficial editor for Standard Notes, a free, open-source, and end-to-end encrypted notes app. Try the demo at beta.appendeditor.com or learn more at appendeditor.com."/><link rel="apple-touch-icon" href="./icon192.png"/><link rel="manifest" href="./manifest.json"/><link rel="stylesheet" href="./katex/v0.12.0/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous"/><title>Append Editor</title><link href="./static/css/4.7c0a8645.chunk.css" rel="stylesheet"><link href="./static/css/main.52f19b8d.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="editor.worker.bundle.js"></script><script src="json.worker.bundle.js"></script><script src="css.worker.bundle.js"></script><script src="html.worker.bundle.js"></script><script src="ts.worker.bundle.js"></script><script>!function(e){function r(r){for(var n,o,a=r[0],u=r[1],i=r[2],b=0,l=[];b<a.length;b++)o=a[b],Object.prototype.hasOwnProperty.call(c,o)&&c[o]&&l.push(c[o][0]),c[o]=0;for(n in u)Object.prototype.hasOwnProperty.call(u,n)&&(e[n]=u[n]);for(d&&d(r);l.length;)l.shift()();return f.push.apply(f,i||[]),t()}function t(){for(var e,r=0;r<f.length;r++){for(var t=f[r],n=!0,a=1;a<t.length;a++){var u=t[a];0!==c[u]&&(n=!1)}n&&(f.splice(r--,1),e=o(o.s=t[0]))}return e}var n={},c={3:0},f=[];function o(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var r=[],t=c[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=c[e]=[r,n]}));r.push(t[2]=n);var f,a=document.createElement("script");a.charset="utf-8",a.timeout=120,o.nc&&a.setAttribute("nonce",o.nc),a.src=function(e){return o.p+"static/js/"+({}[e]||e)+"."+{0:"96650d91",1:"78ca9d6c",5:"09338a01",6:"ca7d77f3",7:"717544c1",8:"7623f70a",9:"e17d9463",10:"a1368cf2",11:"71b71c55",12:"2cc25895",13:"1fb74336",14:"70097320",15:"ebd33ea1",16:"b5d70f16",17:"15bd2337",18:"fddb6358",19:"443b54fb",20:"4a7b005c",21:"cb435385",22:"1803dcd5",23:"6efdbfce",24:"39737423",25:"39dac257",26:"18e00863",27:"29f35b73",28:"398d30c0",29:"59ce2c24",30:"986c71be",31:"7887f40e",32:"857a3f6b",33:"27135546",34:"8eff15cf",35:"e6a51cf9",36:"96b77479",37:"e7e64e90",38:"ff558f50",39:"75d696a7",40:"ea8d1f64",41:"09d45323",42:"5b924b1e",43:"8f8f8c91",44:"a4504e7e",45:"54a25c70",46:"08b8b641",47:"51f1484f",48:"dbe97939",49:"b213c8bf",50:"fd853f67",51:"7dfa9470",52:"bc98cf52",53:"b9fccd87",54:"43cccae9",55:"62a8bf5c",56:"ff82f7d1",57:"3ea0f273",58:"8305f91a",59:"21713170",60:"5dcb04b6",61:"8ff54cb0",62:"f560fa1e",63:"f145f631",64:"f406beef",65:"393e0ac1",66:"8c910e5c",67:"f95fa00e",68:"6ae39414",69:"c94b8637",70:"50aabebd",71:"a2964ae5",72:"a5d59cdc",73:"cbdec997"}[e]+".chunk.js"}(e);var u=new Error;f=function(r){a.onerror=a.onload=null,clearTimeout(i);var t=c[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),f=r&&r.target&&r.target.src;u.message="Loading chunk "+e+" failed.\n("+n+": "+f+")",u.name="ChunkLoadError",u.type=n,u.request=f,t[1](u)}c[e]=void 0}};var i=setTimeout((function(){f({type:"timeout",target:a})}),12e4);a.onerror=a.onload=f,document.head.appendChild(a)}return Promise.all(r)},o.m=e,o.c=n,o.d=function(e,r,t){o.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,r){if(1&r&&(e=o(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(o.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)o.d(t,n,function(r){return e[r]}.bind(null,n));return t},o.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(r,"a",r),r},o.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},o.p="./",o.oe=function(e){throw console.error(e),e};var a=this["webpackJsonpappend-editor"]=this["webpackJsonpappend-editor"]||[],u=a.push.bind(a);a.push=r,a=a.slice();for(var i=0;i<a.length;i++)r(a[i]);var d=u;t()}([])</script><script src="./static/js/4.b613b891.chunk.js"></script><script src="./static/js/main.a922e0bb.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" type="image/png" href="./icon.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="The Append Editor is an unofficial editor for Standard Notes, a free, open-source, and end-to-end encrypted notes app. Try the demo at beta.appendeditor.com or learn more at appendeditor.com."/><link rel="apple-touch-icon" href="./icon192.png"/><link rel="manifest" href="./manifest.json"/><link rel="stylesheet" href="./katex/v0.12.0/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous"/><title>Append Editor</title><link href="./static/css/4.7c0a8645.chunk.css" rel="stylesheet"><link href="./static/css/main.1852c0ce.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="editor.worker.bundle.js"></script><script src="json.worker.bundle.js"></script><script src="css.worker.bundle.js"></script><script src="html.worker.bundle.js"></script><script src="ts.worker.bundle.js"></script><script>!function(e){function r(r){for(var n,o,a=r[0],u=r[1],i=r[2],b=0,l=[];b<a.length;b++)o=a[b],Object.prototype.hasOwnProperty.call(c,o)&&c[o]&&l.push(c[o][0]),c[o]=0;for(n in u)Object.prototype.hasOwnProperty.call(u,n)&&(e[n]=u[n]);for(d&&d(r);l.length;)l.shift()();return f.push.apply(f,i||[]),t()}function t(){for(var e,r=0;r<f.length;r++){for(var t=f[r],n=!0,a=1;a<t.length;a++){var u=t[a];0!==c[u]&&(n=!1)}n&&(f.splice(r--,1),e=o(o.s=t[0]))}return e}var n={},c={3:0},f=[];function o(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var r=[],t=c[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=c[e]=[r,n]}));r.push(t[2]=n);var f,a=document.createElement("script");a.charset="utf-8",a.timeout=120,o.nc&&a.setAttribute("nonce",o.nc),a.src=function(e){return o.p+"static/js/"+({}[e]||e)+"."+{0:"96650d91",1:"78ca9d6c",5:"09338a01",6:"ca7d77f3",7:"717544c1",8:"7623f70a",9:"e17d9463",10:"a1368cf2",11:"71b71c55",12:"2cc25895",13:"1fb74336",14:"70097320",15:"ebd33ea1",16:"b5d70f16",17:"15bd2337",18:"fddb6358",19:"443b54fb",20:"4a7b005c",21:"cb435385",22:"1803dcd5",23:"6efdbfce",24:"39737423",25:"39dac257",26:"18e00863",27:"29f35b73",28:"398d30c0",29:"59ce2c24",30:"986c71be",31:"7887f40e",32:"857a3f6b",33:"27135546",34:"8eff15cf",35:"e6a51cf9",36:"96b77479",37:"e7e64e90",38:"ff558f50",39:"75d696a7",40:"ea8d1f64",41:"09d45323",42:"5b924b1e",43:"8f8f8c91",44:"a4504e7e",45:"54a25c70",46:"08b8b641",47:"51f1484f",48:"dbe97939",49:"b213c8bf",50:"fd853f67",51:"7dfa9470",52:"bc98cf52",53:"b9fccd87",54:"43cccae9",55:"62a8bf5c",56:"ff82f7d1",57:"3ea0f273",58:"8305f91a",59:"21713170",60:"5dcb04b6",61:"8ff54cb0",62:"f560fa1e",63:"f145f631",64:"f406beef",65:"393e0ac1",66:"8c910e5c",67:"f95fa00e",68:"6ae39414",69:"c94b8637",70:"50aabebd",71:"a2964ae5",72:"a5d59cdc",73:"cbdec997"}[e]+".chunk.js"}(e);var u=new Error;f=function(r){a.onerror=a.onload=null,clearTimeout(i);var t=c[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),f=r&&r.target&&r.target.src;u.message="Loading chunk "+e+" failed.\n("+n+": "+f+")",u.name="ChunkLoadError",u.type=n,u.request=f,t[1](u)}c[e]=void 0}};var i=setTimeout((function(){f({type:"timeout",target:a})}),12e4);a.onerror=a.onload=f,document.head.appendChild(a)}return Promise.all(r)},o.m=e,o.c=n,o.d=function(e,r,t){o.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,r){if(1&r&&(e=o(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(o.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)o.d(t,n,function(r){return e[r]}.bind(null,n));return t},o.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(r,"a",r),r},o.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},o.p="./",o.oe=function(e){throw console.error(e),e};var a=this["webpackJsonpappend-editor"]=this["webpackJsonpappend-editor"]||[],u=a.push.bind(a);a.push=r,a=a.slice();for(var i=0;i<a.length;i++)r(a[i]);var d=u;t()}([])</script><script src="./static/js/4.ea980b31.chunk.js"></script><script src="./static/js/main.02a84f27.chunk.js"></script></body></html>
2 changes: 2 additions & 0 deletions build/static/css/main.1852c0ce.chunk.css

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions build/static/css/main.1852c0ce.chunk.css.map

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions build/static/css/main.52f19b8d.chunk.css

This file was deleted.

1 change: 0 additions & 1 deletion build/static/css/main.52f19b8d.chunk.css.map

This file was deleted.

3 changes: 0 additions & 3 deletions build/static/js/4.b613b891.chunk.js

This file was deleted.

3 changes: 3 additions & 0 deletions build/static/js/4.ea980b31.chunk.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions build/static/js/main.02a84f27.chunk.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions build/static/js/main.02a84f27.chunk.js.map

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions build/static/js/main.a922e0bb.chunk.js

This file was deleted.

1 change: 0 additions & 1 deletion build/static/js/main.a922e0bb.chunk.js.map

This file was deleted.

3 changes: 3 additions & 0 deletions public/icons/ic-menu-variant.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 47 additions & 10 deletions src/components/AppendEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import AppendText from './AppendText';
import Settings from './Settings';
import { MonacoDiffEditor } from './Monaco';
import ErrorBoundary from './ErrorBoundary';
import Menu from './Menu';

import CodeMirror, { Editor } from 'codemirror';
import 'codemirror/lib/codemirror';
Expand Down Expand Up @@ -769,19 +770,20 @@ export default class AppendEditor extends React.Component<{}, AppendInterface> {
onPrintMode = () => {
this.setState(
{
showHeader: false,
showAppendix: false,
editMode: false,
printMode: true,
viewMode: false,
showAppendix: false,
showHeader: false,
showMenu: false,
refreshView: !this.state.refreshView,
viewMode: false,
},
() => {
window.print();
this.setState(
{
showHeader: true,
showAppendix: true,
showHeader: true,
},
() => {
const printButton = document.getElementById(printButtonID);
Expand Down Expand Up @@ -828,7 +830,7 @@ export default class AppendEditor extends React.Component<{}, AppendInterface> {
}
};

onToggleShowHelp = () => {
toggleShowHelp = () => {
this.setState(
{
showHelp: !this.state.showHelp,
Expand All @@ -843,7 +845,7 @@ export default class AppendEditor extends React.Component<{}, AppendInterface> {
);
};

onToggleShowMenu = () => {
toggleShowMenu = () => {
this.setState({
showMenu: !this.state.showMenu,
});
Expand All @@ -859,13 +861,14 @@ export default class AppendEditor extends React.Component<{}, AppendInterface> {
() => {
this.setState(
{
showAppendix: false, // Hides the scroll up/down buttons
showHeader: false,
appendMode: false,
editMode: false,
printMode: false,
viewMode: false,
settingsMode: true,
showAppendix: false, // Hides the scroll up/down buttons
showHeader: false,
showMenu: false,
viewMode: false,
},
() => {
const undoDialog = document.getElementById('undoDialog');
Expand Down Expand Up @@ -1602,7 +1605,7 @@ export default class AppendEditor extends React.Component<{}, AppendInterface> {
<button
type="button"
id={helpButtonID}
onClick={this.onToggleShowHelp}
onClick={this.toggleShowHelp}
title="Help"
className={'sk-button ' + (this.state.showHelp ? 'on' : 'off')}
>
Expand Down Expand Up @@ -1740,6 +1743,32 @@ export default class AppendEditor extends React.Component<{}, AppendInterface> {
/>
</svg>
</button>
<button
type="button"
id="showMenubotton"
onClick={this.toggleShowMenu}
title="Toggle Menu"
className={'sk-button ' + (this.state.showMenu ? 'on' : 'off')}
>
<svg
role="button"
aria-label="Dots button to show menu"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17 5V6.66667H3V5H17ZM3 15H17V13.3333H3V15ZM3 10.8333H17V9.16667H3V10.8333Z"
fill={
this.state.showMenu
? 'var(--sn-stylekit-info-color)'
: 'var(--sn-stylekit-foreground-color)'
}
/>
</svg>
</button>
</div>
</div>,
]}
Expand All @@ -1749,6 +1778,14 @@ export default class AppendEditor extends React.Component<{}, AppendInterface> {
'content ' + (this.state.printMode ? 'printModeOn' : 'printModeOff')
}
>
{this.state.showMenu && (
<Menu
refreshEdit={this.refreshEdit}
refreshView={this.refreshView}
saveText={this.saveText}
text={this.state.text}
/>
)}
{this.state.settingsMode && (
<Settings
cancelText="Cancel"
Expand Down
116 changes: 116 additions & 0 deletions src/components/Menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React from 'react';

interface MenuProps {
refreshEdit: () => void;
refreshView: () => void;
saveText: (text: string) => void;
text: string;
}

interface MenuState {
message?: string;
displayMessage: boolean;
}

const initialState = {
message: '',
displayMessage: false,
};

export default class Menu extends React.Component<MenuProps, MenuState> {
clearTooltipTimer: NodeJS.Timeout | undefined;
constructor(props: MenuProps) {
super(props);
this.state = initialState;
}

showMessage = () => {
this.setState(
{
displayMessage: true,
},
() => {
if (this.clearTooltipTimer) {
clearTimeout(this.clearTooltipTimer);
}
this.clearTooltipTimer = setTimeout(() => {
this.setState({
displayMessage: false,
});
}, 1000);
}
);
};

copyToClipboard = (text: string) => {
const textField = document.createElement('textarea');
textField.innerText = text;
document.body.appendChild(textField);
textField.select();
document.execCommand('copy');
this.showMessage();
textField.remove();
};

copyText = () => {
if (this.props.text) {
this.setState({ message: 'Copied Text to clipboard.' }, () => {
this.copyToClipboard(this.props.text);
});
} else {
this.setState({ message: 'No text to copy.' }, () => {
this.showMessage();
});
}
};

copyHtml = () => {
const renderedNote = document.getElementById('renderedNote');
if (renderedNote?.firstElementChild?.innerHTML) {
this.setState({ message: 'Copied HTML to clipboard.' });
this.copyToClipboard(renderedNote?.firstElementChild.innerHTML);
} else {
this.setState({ message: 'No HTML to copy.' }, () => {
this.showMessage();
});
}
};

uncheckBoxes = () => {
const { text } = this.props;
const checkedBoxes = new RegExp(/- \[x\]/gm);
if (checkedBoxes.test(text)) {
const newText = text.replace(checkedBoxes, '- [ ]');
this.props.saveText(newText);
this.props.refreshEdit();
this.props.refreshView();
this.setState({ message: 'Unchecked all checkboxes.' }, () => {
this.showMessage();
});
} else {
this.setState({ message: 'No checked boxes found.' }, () => {
this.showMessage();
});
}
};

render() {
// You can render any custom fallback UI
return (
<div id={'menu'}>
<button onClick={this.copyText}>Copy note text</button>
<button onClick={this.copyHtml}>Copy rendered HTML</button>
<button onClick={this.uncheckBoxes}>Uncheck all Checkboxes</button>
<div
className={`notification ${
this.state.displayMessage ? 'visible' : 'hidden'
}`}
>
<p>
<b>{this.state.message}</b>
</p>
</div>
</div>
);
}
}
1 change: 1 addition & 0 deletions src/components/ViewNote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export default class ViewNote extends React.Component<ViewProps, ViewState> {
(this.props.printMode ? 'printModeOn' : 'printModeOff') +
(this.props.printURL ? ' printURL' : ' printURLOff')
}
id="view"
>
<div className="sk-panel-content view">
<div>
Expand Down
Loading

0 comments on commit f1d7142

Please sign in to comment.