diff --git a/app/components/SocketProvider.js b/app/components/SocketProvider.js index 43d179fd..4cc857df 100644 --- a/app/components/SocketProvider.js +++ b/app/components/SocketProvider.js @@ -128,22 +128,6 @@ class SocketProvider extends React.Component { }); } } - - // TODO: Move this to the document scene once data loading - // has been refactored to be friendlier there. - if ( - auth.user && - documentId === ui.activeDocumentId && - document.updatedBy.id !== auth.user.id - ) { - ui.showToast(`Document updated by ${document.updatedBy.name}`, { - timeout: 30 * 1000, - action: { - text: 'Refresh', - onClick: () => window.location.reload(), - }, - }); - } } } diff --git a/app/models/Document.js b/app/models/Document.js index 96946c86..d3968357 100644 --- a/app/models/Document.js +++ b/app/models/Document.js @@ -10,7 +10,12 @@ import Revision from 'models/Revision'; import User from 'models/User'; import DocumentsStore from 'stores/DocumentsStore'; -type SaveOptions = { publish?: boolean, done?: boolean, autosave?: boolean }; +type SaveOptions = { + publish?: boolean, + done?: boolean, + autosave?: boolean, + lastRevision?: number, +}; export default class Document extends BaseModel { @observable isSaving: boolean = false; @@ -185,7 +190,7 @@ export default class Document extends BaseModel { id: this.id, title: this.title, text: this.text, - lastRevision: this.revision, + lastRevision: options.lastRevision, ...options, }); } finally { diff --git a/app/scenes/Document/components/Document.js b/app/scenes/Document/components/Document.js index 78593ecd..c91aca20 100644 --- a/app/scenes/Document/components/Document.js +++ b/app/scenes/Document/components/Document.js @@ -14,6 +14,7 @@ import { documentMoveUrl, documentHistoryUrl, documentEditUrl, + documentUrl, } from 'utils/routeHelpers'; import { emojiToUrl } from 'utils/emoji'; @@ -74,11 +75,13 @@ class DocumentScene extends React.Component { @observable isDirty: boolean = false; @observable isEmpty: boolean = true; @observable moveModalOpen: boolean = false; + @observable lastRevision: number; @observable title: string; constructor(props) { super(); this.title = props.document.title; + this.lastRevision = props.document.revision; this.loadEditor(); } @@ -86,6 +89,29 @@ class DocumentScene extends React.Component { this.updateIsDirty(); } + componentDidUpdate(prevProps) { + const { auth, document } = this.props; + + if (this.props.readOnly) { + this.lastRevision = document.revision; + } else if (prevProps.document.revision !== this.lastRevision) { + if (auth.user && document.updatedBy.id !== auth.user.id) { + this.props.ui.showToast( + `Document updated by ${document.updatedBy.name}`, + { + timeout: 30 * 1000, + action: { + text: 'Reload', + onClick: () => { + window.location.href = documentUrl(document); + }, + }, + } + ); + } + } + } + @keydown('m') goToMove(ev) { if (!this.props.readOnly) return; @@ -174,7 +200,11 @@ class DocumentScene extends React.Component { handleOpenMoveModal = () => (this.moveModalOpen = true); onSave = async ( - options: { done?: boolean, publish?: boolean, autosave?: boolean } = {} + options: { + done?: boolean, + publish?: boolean, + autosave?: boolean, + } = {} ) => { const { document } = this.props; @@ -202,17 +232,27 @@ class DocumentScene extends React.Component { let isNew = !document.id; this.isSaving = true; this.isPublishing = !!options.publish; - const savedDocument = await document.save(options); - this.isDirty = false; - this.isSaving = false; - this.isPublishing = false; - if (options.done) { - this.props.history.push(savedDocument.url); - this.props.ui.setActiveDocument(savedDocument); - } else if (isNew) { - this.props.history.push(documentEditUrl(savedDocument)); - this.props.ui.setActiveDocument(savedDocument); + try { + const savedDocument = await document.save({ + ...options, + lastRevision: this.lastRevision, + }); + this.isDirty = false; + this.lastRevision = savedDocument.revision; + + if (options.done) { + this.props.history.push(savedDocument.url); + this.props.ui.setActiveDocument(savedDocument); + } else if (isNew) { + this.props.history.push(documentEditUrl(savedDocument)); + this.props.ui.setActiveDocument(savedDocument); + } + } catch (err) { + this.props.ui.showToast(err.message); + } finally { + this.isSaving = false; + this.isPublishing = false; } };