From f981d7b7293c0eb2ad869091cabbb836b0c86a23 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 20 May 2018 22:39:40 +0100 Subject: [PATCH] unify buttons on the node type names, and make them work --- ...o-n.svg => button-text-block-quote-on.svg} | 0 ...-quote.svg => button-text-block-quote.svg} | 0 ...t-bold-o-n.svg => button-text-bold-on.svg} | 0 ...n.svg => button-text-bulleted-list-on.svg} | 0 ...llet.svg => button-text-bulleted-list.svg} | 0 ...t-code-o-n.svg => button-text-code-on.svg} | 0 ...ike-o-n.svg => button-text-deleted-on.svg} | 0 ...ext-strike.svg => button-text-deleted.svg} | 0 ...alic-o-n.svg => button-text-italic-on.svg} | 0 ...n.svg => button-text-numbered-list-on.svg} | 0 ...llet.svg => button-text-numbered-list.svg} | 0 ...-o-n.svg => button-text-underlined-on.svg} | 0 ...derline.svg => button-text-underlined.svg} | 0 src/components/views/rooms/MessageComposer.js | 58 ++++++++------- .../views/rooms/MessageComposerInput.js | 70 ++++++++++--------- 15 files changed, 68 insertions(+), 60 deletions(-) rename res/img/{button-text-quote-o-n.svg => button-text-block-quote-on.svg} (100%) rename res/img/{button-text-quote.svg => button-text-block-quote.svg} (100%) rename res/img/{button-text-bold-o-n.svg => button-text-bold-on.svg} (100%) rename res/img/{button-text-bullet-o-n.svg => button-text-bulleted-list-on.svg} (100%) rename res/img/{button-text-bullet.svg => button-text-bulleted-list.svg} (100%) rename res/img/{button-text-code-o-n.svg => button-text-code-on.svg} (100%) rename res/img/{button-text-strike-o-n.svg => button-text-deleted-on.svg} (100%) rename res/img/{button-text-strike.svg => button-text-deleted.svg} (100%) rename res/img/{button-text-italic-o-n.svg => button-text-italic-on.svg} (100%) rename res/img/{button-text-numbullet-o-n.svg => button-text-numbered-list-on.svg} (100%) rename res/img/{button-text-numbullet.svg => button-text-numbered-list.svg} (100%) rename res/img/{button-text-underline-o-n.svg => button-text-underlined-on.svg} (100%) rename res/img/{button-text-underline.svg => button-text-underlined.svg} (100%) diff --git a/res/img/button-text-quote-o-n.svg b/res/img/button-text-block-quote-on.svg similarity index 100% rename from res/img/button-text-quote-o-n.svg rename to res/img/button-text-block-quote-on.svg diff --git a/res/img/button-text-quote.svg b/res/img/button-text-block-quote.svg similarity index 100% rename from res/img/button-text-quote.svg rename to res/img/button-text-block-quote.svg diff --git a/res/img/button-text-bold-o-n.svg b/res/img/button-text-bold-on.svg similarity index 100% rename from res/img/button-text-bold-o-n.svg rename to res/img/button-text-bold-on.svg diff --git a/res/img/button-text-bullet-o-n.svg b/res/img/button-text-bulleted-list-on.svg similarity index 100% rename from res/img/button-text-bullet-o-n.svg rename to res/img/button-text-bulleted-list-on.svg diff --git a/res/img/button-text-bullet.svg b/res/img/button-text-bulleted-list.svg similarity index 100% rename from res/img/button-text-bullet.svg rename to res/img/button-text-bulleted-list.svg diff --git a/res/img/button-text-code-o-n.svg b/res/img/button-text-code-on.svg similarity index 100% rename from res/img/button-text-code-o-n.svg rename to res/img/button-text-code-on.svg diff --git a/res/img/button-text-strike-o-n.svg b/res/img/button-text-deleted-on.svg similarity index 100% rename from res/img/button-text-strike-o-n.svg rename to res/img/button-text-deleted-on.svg diff --git a/res/img/button-text-strike.svg b/res/img/button-text-deleted.svg similarity index 100% rename from res/img/button-text-strike.svg rename to res/img/button-text-deleted.svg diff --git a/res/img/button-text-italic-o-n.svg b/res/img/button-text-italic-on.svg similarity index 100% rename from res/img/button-text-italic-o-n.svg rename to res/img/button-text-italic-on.svg diff --git a/res/img/button-text-numbullet-o-n.svg b/res/img/button-text-numbered-list-on.svg similarity index 100% rename from res/img/button-text-numbullet-o-n.svg rename to res/img/button-text-numbered-list-on.svg diff --git a/res/img/button-text-numbullet.svg b/res/img/button-text-numbered-list.svg similarity index 100% rename from res/img/button-text-numbullet.svg rename to res/img/button-text-numbered-list.svg diff --git a/res/img/button-text-underline-o-n.svg b/res/img/button-text-underlined-on.svg similarity index 100% rename from res/img/button-text-underline-o-n.svg rename to res/img/button-text-underlined-on.svg diff --git a/res/img/button-text-underline.svg b/res/img/button-text-underlined.svg similarity index 100% rename from res/img/button-text-underline.svg rename to res/img/button-text-underlined.svg diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 157dc9e704..4d00927767 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -215,7 +215,7 @@ export default class MessageComposer extends React.Component { } } - onFormatButtonClicked(name: "bold" | "italic" | "strike" | "code" | "underline" | "quote" | "bullet" | "numbullet", event) { + onFormatButtonClicked(name, event) { event.preventDefault(); this.messageComposerInput.onFormatButtonClicked(name, event); } @@ -303,14 +303,14 @@ export default class MessageComposer extends React.Component { ); - const formattingButton = ( + const formattingButton = this.state.inputState.isRichTextEnabled ? ( - ); + ) : null; let placeholderText; if (this.state.isQuoting) { @@ -353,31 +353,27 @@ export default class MessageComposer extends React.Component { ); } - const {marks, blockType} = this.state.inputState; - const formatButtons = ["bold", "italic", "strike", "underline", "code", "quote", "bullet", "numbullet"].map( - (name) => { - const active = marks.includes(name) || blockType === name; - const suffix = active ? '-o-n' : ''; - const onFormatButtonClicked = this.onFormatButtonClicked.bind(this, name); - const className = 'mx_MessageComposer_format_button mx_filterFlipColor'; - return ; - }, - ); + let formatBar; + if (this.state.showFormatting) { + const {marks, blockType} = this.state.inputState; + const formatButtons = ["bold", "italic", "deleted", "underlined", "code", "block-quote", "bulleted-list", "numbered-list"].map( + (name) => { + const active = marks.some(mark => mark.type === name) || blockType === name; + const suffix = active ? '-on' : ''; + const onFormatButtonClicked = this.onFormatButtonClicked.bind(this, name); + const className = 'mx_MessageComposer_format_button mx_filterFlipColor'; + return ; + }, + ); - return ( -
-
-
- { controls } -
-
+ formatBar =
-
+
{ formatButtons }
+ } + + return ( +
+
+
+ { controls } +
+
+ { formatBar }
); } diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index aac7c7ddbb..2d5e6d050d 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -132,9 +132,6 @@ export default class MessageComposerInput extends React.Component { // js-sdk Room object room: PropTypes.object.isRequired, - // called with current plaintext content (as a string) whenever it changes - onContentChanged: PropTypes.func, - onFilesPasted: PropTypes.func, onInputStateChanged: PropTypes.func, @@ -319,15 +316,6 @@ export default class MessageComposerInput extends React.Component { dis.unregister(this.dispatcherRef); } - componentWillUpdate(nextProps, nextState) { - // this is dirty, but moving all this state to MessageComposer is dirtier - if (this.props.onInputStateChanged && nextState !== this.state) { - const state = this.getSelectionInfo(nextState.editorState); - state.isRichTextEnabled = nextState.isRichTextEnabled; - this.props.onInputStateChanged(state); - } - } - onAction = (payload) => { const editor = this.refs.editor; let editorState = this.state.editorState; @@ -567,6 +555,27 @@ export default class MessageComposerInput extends React.Component { } } + if (this.props.onInputStateChanged) { + let blockType = editorState.blocks.first().type; + console.log("onInputStateChanged; current block type is " + blockType + " and marks are " + editorState.activeMarks); + + if (blockType === 'list-item') { + const parent = editorState.document.getParent(editorState.blocks.first().key); + if (parent.type === 'numbered-list') { + blockType = 'numbered-list'; + } + else if (parent.type === 'bulleted-list') { + blockType = 'bulleted-list'; + } + } + const inputState = { + marks: editorState.activeMarks, + isRichTextEnabled: this.state.isRichTextEnabled, + blockType + }; + this.props.onInputStateChanged(inputState); + } + // Record the editor state for this room so that it can be retrieved after // switching to another room and back dis.dispatch({ @@ -1239,17 +1248,6 @@ export default class MessageComposerInput extends React.Component { await this.setDisplayedCompletion(null); // restore originalEditorState }; - /* returns inline style and block type of current SelectionState so MessageComposer can render formatting - buttons. */ - getSelectionInfo(editorState: Value) { - return { - marks: editorState.activeMarks, - // XXX: shouldn't we return all the types of blocks in the current selection, - // not just the anchor? - blockType: editorState.anchorBlock ? editorState.anchorBlock.type : null, - }; - } - /* If passed null, restores the original editor content from state.originalEditorState. * If passed a non-null displayedCompletion, modifies state.originalEditorState to compute new state.editorState. */ @@ -1406,18 +1404,22 @@ export default class MessageComposerInput extends React.Component { } }; - onFormatButtonClicked = (name: "bold" | "italic" | "strike" | "code" | "underline" | "quote" | "bullet" | "numbullet", e) => { - e.preventDefault(); // don't steal focus from the editor! + onFormatButtonClicked = (name, e) => { + if (e) { + e.preventDefault(); // don't steal focus from the editor! + } - const command = { - // code: 'code-block', // let's have the button do inline code for now - quote: 'block-quote', - bullet: 'bulleted-list', - numbullet: 'numbered-list', - underline: 'underlined', - strike: 'deleted', - }[name] || name; - this.handleKeyCommand(command); + // XXX: horrible evil hack to ensure the editor is focused so the act + // of focusing it doesn't then cancel the format button being pressed + if (document.activeElement && document.activeElement.className !== 'mx_MessageComposer_editor') { + this.refs.editor.focus(); + setTimeout(()=>{ + this.handleKeyCommand(name); + }, 500); // can't find any callback to hook this to. onFocus and onChange and willComponentUpdate fire too early. + return; + } + + this.handleKeyCommand(name); }; getAutocompleteQuery(editorState: Value) {