Skip to content
This repository has been archived by the owner on Jan 6, 2023. It is now read-only.

Refactor events workflow #865

Merged
merged 7 commits into from
Apr 3, 2018
18 changes: 11 additions & 7 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ let editorConnectedDeferred;
let isEditorConnected = new Promise(resolve => { editorConnectedDeferred = {resolve}; });

// Kinto sync and encryption

const client = new Kinto({remote: KINTO_SERVER, bucket: 'default'});

// Analytics
Expand Down Expand Up @@ -167,9 +166,6 @@ browser.runtime.onMessage.addListener(function(eventData) {
case 'kinto-sync':
loadFromKinto(client, credentials);
break;
case 'kinto-save':
saveToKinto(client, credentials, eventData.note);
break;
case 'metrics-changed':
sendMetrics('changed', eventData.context);
break;
Expand Down Expand Up @@ -198,14 +194,22 @@ browser.runtime.onMessage.addListener(function(eventData) {
browser.runtime.sendMessage({
action: 'create-note',
id: result.data.id,
content: result.data.content
content: result.data.content,
lastModified: result.data.lastModified
});
});
break;
case 'update-note':
saveToKinto(client, credentials, eventData.note, eventData.from);
break;
case 'delete-note':
// We create a note, and send id with note-created nessage
deleteNote(client, eventData.id).then((note) => {
loadFromKinto(client, credentials);
deleteNote(client, eventData.id).then(() => {
// loadFromKinto(client, credentials);
browser.runtime.sendMessage({
action: 'delete-note',
id: eventData.id
});
});
break;
case 'theme-changed':
Expand Down
40 changes: 25 additions & 15 deletions src/sidebar/app/actions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SYNC_AUTHENTICATED,
KINTO_LOADED,
TEXT_SAVED,
TEXT_SYNCED,
RECONNECT_SYNC,
DISCONNECTED,
Expand All @@ -21,20 +22,23 @@ import * as FileSaver from 'file-saver';
/*
* action creators
*/
export function updatedNote(id, content, lastModified) {
return { type: UPDATE_NOTE, id, content, lastModified };
}
export function updateNote(id, content) {
let isInitialContent = false;
const lastModified = new Date();
if (content.replace(/ /g, '\xa0') !== INITIAL_CONTENT.replace(/\s\s+/g, ' ')) {
chrome.runtime.sendMessage({
action: 'kinto-save',
note: {
id, content, lastModified
}
browser.windows.getCurrent({populate: true}).then((windowInfo) => {
chrome.runtime.sendMessage({
action: UPDATE_NOTE,
from: windowInfo.id,
note: {
id, content, lastModified
}
});
});
} else {
isInitialContent = true;
}
return { type: UPDATE_NOTE, id, content, lastModified, isInitialContent };
return { type: UPDATE_NOTE, id, content, lastModified };
}

export function authenticate(email) {
Expand All @@ -45,6 +49,10 @@ export function authenticate(email) {
return { type: SYNC_AUTHENTICATED, email };
}

export function saved(id, content, lastModified) {
return { type: TEXT_SAVED, id, content, lastModified };
}

export function synced(notes) {
return { type: TEXT_SYNCED, notes };
}
Expand Down Expand Up @@ -80,6 +88,9 @@ export function reconnectSync() {
return { type: RECONNECT_SYNC };
}

export function createdNote(id, content, lastModified) {
return { type: CREATE_NOTE, id, content, lastModified };
}
export function createNote(content = '') {

const id = uuid4();
Expand All @@ -103,17 +114,16 @@ export function createNote(content = '') {
return fct;
}

export function deletedNote(id) {
return { type: DELETE_NOTE, id };
}
export function deleteNote(id) {

id ? chrome.runtime.sendMessage({ action: 'delete-note', id }) : null;

browser.runtime.sendMessage({
action: 'kinto-sync'
});

chrome.runtime.sendMessage({ action: 'delete-note', id });
return { type: DELETE_NOTE, id };
}


// EXPORT HTML
export function exportHTML(content) {

Expand Down
21 changes: 16 additions & 5 deletions src/sidebar/app/components/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getPadStats, customizeEditor } from '../utils/editor';

import INITIAL_CONFIG from '../data/editorConfig';

import { updateNote } from '../actions';
import { updateNote, createNote, deleteNote, setFocusedNote } from '../actions';

const styles = {
container: {
Expand Down Expand Up @@ -47,7 +47,15 @@ class Editor extends React.Component {
const content = editor.getData();

if (!this.ignoreChange) {
this.props.dispatch(updateNote(this.props.note.id, content));
if (!this.props.note.id) {
this.props.dispatch(createNote(content)).then(id => {
this.props.dispatch(setFocusedNote(id));
});
} else if (this.props.note.id && (content === '' || content === '<p>&nbsp;</p>')) {
this.props.dispatch(deleteNote(this.props.note.id));
} else {
this.props.dispatch(updateNote(this.props.note.id, content));
}
}
this.ignoreChange = false;

Expand Down Expand Up @@ -80,7 +88,9 @@ class Editor extends React.Component {
}

componentWillUnmount() {
this.editor.destroy();
if (this.editor) {
this.editor.destroy();
}
}

render() {
Expand All @@ -92,7 +102,7 @@ class Editor extends React.Component {
ref={node => {
this.node = node;
}}
dangerouslySetInnerHTML={{ __html: this.props.note.content || '' }}>
dangerouslySetInnerHTML={{ __html: this.props.note ? this.props.note.content : '' }}>
</div>
</div>

Expand All @@ -115,7 +125,8 @@ function mapStateToProps(state) {

Editor.propTypes = {
state: PropTypes.object.isRequired,
note: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
note: PropTypes.object,
dispatch: PropTypes.func.isRequired
};

Expand Down
30 changes: 15 additions & 15 deletions src/sidebar/app/components/EditorPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
import Header from './Header';
import Editor from './Editor';

import { createNote, setFocusedNote } from '../actions';
import { setFocusedNote } from '../actions';

class EditorPanel extends React.Component {

Expand All @@ -15,16 +15,16 @@ class EditorPanel extends React.Component {
this.props = props;

this.note = {}; // Note should be reference to state.
this.note = props.state.notes.find((note) => {
return note.id === props.match.params.id;
});
this.props.dispatch(setFocusedNote(props.match.params.id));
if (props.match.params.id) {
this.note = props.state.notes.find((note) => {
return note.id === props.match.params.id;
});
this.props.dispatch(setFocusedNote(props.match.params.id));
}

this.onNewNoteEvent = () => {
// Request new id and redirec to new note
this.props.dispatch(createNote()).then(id => {
props.history.push(`/note/${id}`);
});
this.props.dispatch(setFocusedNote());
props.history.push('/note');
};
}

Expand All @@ -36,27 +36,27 @@ class EditorPanel extends React.Component {

// This is triggered when redux update state.
componentWillReceiveProps(nextProps) {
if (nextProps.match.params.id !== this.props.match.params.id) {
if (this.props.state.sync.focusedNoteId !== nextProps.state.sync.focusedNoteId) {
this.note = nextProps.state.notes.find((note) => {
return note.id === nextProps.match.params.id;
return note.id === nextProps.state.sync.focusedNoteId;
});
this.props.dispatch(setFocusedNote(nextProps.match.params.id));
this.props.dispatch(setFocusedNote(nextProps.state.sync.focusedNoteId));
} else if (!this.props.state.sync.isSyncing) {
this.note = nextProps.state.notes.find((note) => {
return note.id === nextProps.match.params.id;
return note.id === nextProps.state.sync.focusedNoteId;
});
}

if (!this.note) {
this.note = {};
this.props.history.push('/');
// this.props.history.push('/');
}
}

render() {
return [
<Header key="header" history={this.props.history} note={this.note} onNewNoteEvent={this.onNewNoteEvent} />,
<Editor key="editor" note={this.note} />
<Editor key="editor" history={this.props.history} note={this.note} />
];
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/sidebar/app/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ function mapStateToProps(state) {
Header.propTypes = {
state: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
note: PropTypes.object.isRequired,
note: PropTypes.object,
onNewNoteEvent: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired
};
Expand Down
27 changes: 15 additions & 12 deletions src/sidebar/app/components/ListPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
import INITIAL_CONTENT from '../data/initialContent';

import NewIcon from './icons/NewIcon';
import { deleteNote, setFocusedNote, createNote } from '../actions';
import { setFocusedNote, createNote } from '../actions';
import { formatLastModified } from '../utils/utils';


Expand All @@ -16,10 +16,8 @@ class ListPanel extends React.Component {
this.props = props;

this.requestNewNote = () => {
// Request not id from background.
this.props.dispatch(createNote()).then(id => {
props.history.push(`/note/${id}`);
});
props.dispatch(setFocusedNote());
props.history.push('/note');
};
}

Expand All @@ -32,10 +30,6 @@ class ListPanel extends React.Component {
this.props.history.push(`/note/${id}`);
});
} else {
// We delete notes with no content
const listOfEmptyNote = this.props.state.notes.filter((n) => !n.firstLine ).map((n) => n.id);
listOfEmptyNote.forEach((id) => this.props.dispatch(deleteNote(id)));

// Set no focused Note to create new note on send note event.
this.props.dispatch(setFocusedNote());
}
Expand Down Expand Up @@ -69,7 +63,7 @@ class ListPanel extends React.Component {
<NewIcon /> <span>{ browser.i18n.getMessage('newNote') }</span>
</button>
<ul>
{ this.props.state.notes.filter((note) => note.firstLine ).sort((a, b) => {
{ this.props.state.notes.sort((a, b) => {
if (a.lastModified.getTime() !== b.lastModified.getTime()) {
return a.lastModified.getTime() < b.lastModified.getTime() ? 1 : -1;
}
Expand All @@ -80,8 +74,17 @@ class ListPanel extends React.Component {
<button
onClick={ () => this.props.history.push(`/note/${note.id}`) }
className="btn fullWidth borderBottom">
<p><strong>{ note.firstLine }</strong></p>
<p><span>{ formatLastModified(note.lastModified) }</span> { note.secondLine }</p>
{ note.firstLine ?
<div>
<p><strong>{ note.firstLine }</strong></p>
<p><span>{ formatLastModified(note.lastModified) }</span> { note.secondLine }</p>
</div>
:
<div style={{ opacity: '0.4' }}>
<p><strong>{ browser.i18n.getMessage('emptyPlaceHolder') }</strong></p>
<p><span>{ formatLastModified(note.lastModified) }</span></p>
</div>
}
</button>
</li>
);
Expand Down
Loading