From 665f507537602878bff2373490ede4a7366ae482 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 21 Apr 2017 18:18:35 +0100 Subject: [PATCH 001/127] Update js-sdk dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a0a51fc0b..67dfa165af 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "isomorphic-fetch": "^2.2.1", "linkifyjs": "^2.1.3", "lodash": "^4.13.1", - "matrix-js-sdk": "0.7.6", + "matrix-js-sdk": "0.7.7-rc.1", "optimist": "^0.6.1", "q": "^1.4.1", "react": "^15.4.0", From 2f08340ff0ee2bf767998fbe6d8e2bfee7187752 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 21 Apr 2017 18:22:39 +0100 Subject: [PATCH 002/127] Prepare changelog for v0.8.8-rc.1 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 292e60607d..7d4a69fb5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [0.8.8-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.8.8-rc.1) (2017-04-21) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.8.7...v0.8.8-rc.1) + + * Update js-sdk to fix registration without a captcha (https://github.com/vector-im/riot-web/issues/3621) + + Changes in [0.8.7](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.8.7) (2017-04-12) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.8.7-rc.4...v0.8.7) From a55eb00dad61e6485ace58737d44a898c08a41f2 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 21 Apr 2017 18:22:39 +0100 Subject: [PATCH 003/127] v0.8.8-rc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 67dfa165af..38d08344e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.8.7", + "version": "0.8.8-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From bb6dd363d70d9ebeaa650a8349c233251c0b00be Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 10 Apr 2017 12:07:39 +0100 Subject: [PATCH 004/127] unbreak in-app permalinks correctly --- src/linkify-matrix.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js index e085b1a27a..c8e20316a9 100644 --- a/src/linkify-matrix.js +++ b/src/linkify-matrix.js @@ -122,7 +122,7 @@ var escapeRegExp = function(string) { // anyone else really should be using matrix.to. matrixLinkify.VECTOR_URL_PATTERN = "^(?:https?:\/\/)?(?:" + escapeRegExp(window.location.host + window.location.pathname) + "|" - + "(?:www\\.)?(riot|vector)\\.im/(?:beta|staging|develop)/" + + "(?:www\\.)?(?:riot|vector)\\.im/(?:beta|staging|develop)/" + ")(#.*)"; matrixLinkify.MATRIXTO_URL_PATTERN = "^(?:https?:\/\/)?(?:www\\.)?matrix\\.to/#/((#|@|!).*)"; From cf2cf66caebea125912b1ff228935d2fc2497213 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 22 Apr 2017 21:06:38 +0100 Subject: [PATCH 005/127] fix deep-linking to riot.im/app --- src/linkify-matrix.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js index c8e20316a9..d9b0b78982 100644 --- a/src/linkify-matrix.js +++ b/src/linkify-matrix.js @@ -122,7 +122,7 @@ var escapeRegExp = function(string) { // anyone else really should be using matrix.to. matrixLinkify.VECTOR_URL_PATTERN = "^(?:https?:\/\/)?(?:" + escapeRegExp(window.location.host + window.location.pathname) + "|" - + "(?:www\\.)?(?:riot|vector)\\.im/(?:beta|staging|develop)/" + + "(?:www\\.)?(?:riot|vector)\\.im/(?:app|beta|staging|develop)/" + ")(#.*)"; matrixLinkify.MATRIXTO_URL_PATTERN = "^(?:https?:\/\/)?(?:www\\.)?matrix\\.to/#/((#|@|!).*)"; From 8e6981db44c7a765cc26f21c3fde76d5a723debe Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 24 Apr 2017 18:24:28 +0100 Subject: [PATCH 006/127] Prepare changelog for v0.8.8-rc.2 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d4a69fb5b..32f16c46ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [0.8.8-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.8.8-rc.2) (2017-04-24) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.8.8-rc.1...v0.8.8-rc.2) + + * Fix bug where links to Riot would fail to open. + + Changes in [0.8.8-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.8.8-rc.1) (2017-04-21) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.8.7...v0.8.8-rc.1) From e569144d6f700cf05e52f67b66aa92237ee7546f Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 24 Apr 2017 18:24:29 +0100 Subject: [PATCH 007/127] v0.8.8-rc.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38d08344e0..5fc8bc2750 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.8.8-rc.1", + "version": "0.8.8-rc.2", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 74dabb20873cb4650041710085d2ed06b3476218 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 25 Apr 2017 10:52:44 +0100 Subject: [PATCH 008/127] Released js-sdk --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5fc8bc2750..d14bc2b766 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "isomorphic-fetch": "^2.2.1", "linkifyjs": "^2.1.3", "lodash": "^4.13.1", - "matrix-js-sdk": "0.7.7-rc.1", + "matrix-js-sdk": "0.7.7", "optimist": "^0.6.1", "q": "^1.4.1", "react": "^15.4.0", From f6fd7b04ac01d7a7e3ef83ca186d9c462b047cb1 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 25 Apr 2017 10:53:58 +0100 Subject: [PATCH 009/127] Prepare changelog for v0.8.8 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32f16c46ae..97dda666de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [0.8.8](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.8.8) (2017-04-25) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.8.8-rc.2...v0.8.8) + + * No changes + + Changes in [0.8.8-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.8.8-rc.2) (2017-04-24) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.8.8-rc.1...v0.8.8-rc.2) From d81adb234a7581169a2ddbf2f0ee6375e5c340ce Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 25 Apr 2017 10:53:59 +0100 Subject: [PATCH 010/127] v0.8.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d14bc2b766..00dc902cc9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.8.8-rc.2", + "version": "0.8.8", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From f5f35e32946a6690615eaecffe77c723f8567950 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 26 Apr 2017 18:59:16 +0100 Subject: [PATCH 011/127] Make the left panel more friendly to new users https://github.com/vector-im/riot-web/issues/3609 --- src/components/views/rooms/RoomList.js | 118 +++++++++++++++++++------ 1 file changed, 89 insertions(+), 29 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 96ff65498f..39d3406b73 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -29,7 +29,14 @@ import DMRoomMap from '../../../utils/DMRoomMap'; var Receipt = require('../../../utils/Receipt'); var constantTimeDispatcher = require('../../../ConstantTimeDispatcher'); -var HIDE_CONFERENCE_CHANS = true; +const HIDE_CONFERENCE_CHANS = true; + +const VERBS = { + 'm.favourite': 'favourite', + 'im.vector.fake.direct': 'tag direct chat', + 'im.vector.fake.recent': 'restore', + 'm.lowpriority': 'demote', +}; module.exports = React.createClass({ displayName: 'RoomList', @@ -53,6 +60,7 @@ module.exports = React.createClass({ getInitialState: function() { return { isLoadingLeftRooms: false, + totalRoomCount: null, lists: {}, incomingCall: null, }; @@ -73,8 +81,7 @@ module.exports = React.createClass({ // lookup for which lists a given roomId is currently in. this.listsForRoomId = {}; - var s = this.getRoomLists(); - this.setState(s); + this.refreshRoomList(); // order of the sublists //this.listOrder = []; @@ -317,21 +324,29 @@ module.exports = React.createClass({ // any changes to it incrementally, updating the appropriate sublists // as needed. // Alternatively we'd do something magical with Immutable.js or similar. - this.setState(this.getRoomLists()); + const lists = this.getRoomLists(); + let totalRooms = 0; + for (const l of Object.values(lists)) { + totalRooms += l.length; + } + this.setState({ + lists: this.getRoomLists(), + totalRoomCount: totalRooms, + }); // this._lastRefreshRoomListTs = Date.now(); }, getRoomLists: function() { var self = this; - var s = { lists: {} }; + const lists = {}; - s.lists["im.vector.fake.invite"] = []; - s.lists["m.favourite"] = []; - s.lists["im.vector.fake.recent"] = []; - s.lists["im.vector.fake.direct"] = []; - s.lists["m.lowpriority"] = []; - s.lists["im.vector.fake.archived"] = []; + lists["im.vector.fake.invite"] = []; + lists["m.favourite"] = []; + lists["im.vector.fake.recent"] = []; + lists["im.vector.fake.direct"] = []; + lists["m.lowpriority"] = []; + lists["im.vector.fake.archived"] = []; this.listsForRoomId = {}; var otherTagNames = {}; @@ -353,7 +368,7 @@ module.exports = React.createClass({ if (me.membership == "invite") { self.listsForRoomId[room.roomId].push("im.vector.fake.invite"); - s.lists["im.vector.fake.invite"].push(room); + lists["im.vector.fake.invite"].push(room); } else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) { // skip past this room & don't put it in any lists @@ -366,8 +381,8 @@ module.exports = React.createClass({ if (tagNames.length) { for (var i = 0; i < tagNames.length; i++) { var tagName = tagNames[i]; - s.lists[tagName] = s.lists[tagName] || []; - s.lists[tagName].push(room); + lists[tagName] = lists[tagName] || []; + lists[tagName].push(room); self.listsForRoomId[room.roomId].push(tagName); otherTagNames[tagName] = 1; } @@ -375,46 +390,46 @@ module.exports = React.createClass({ else if (dmRoomMap.getUserIdForRoomId(room.roomId)) { // "Direct Message" rooms (that we're still in and that aren't otherwise tagged) self.listsForRoomId[room.roomId].push("im.vector.fake.direct"); - s.lists["im.vector.fake.direct"].push(room); + lists["im.vector.fake.direct"].push(room); } else { self.listsForRoomId[room.roomId].push("im.vector.fake.recent"); - s.lists["im.vector.fake.recent"].push(room); + lists["im.vector.fake.recent"].push(room); } } else if (me.membership === "leave") { self.listsForRoomId[room.roomId].push("im.vector.fake.archived"); - s.lists["im.vector.fake.archived"].push(room); + lists["im.vector.fake.archived"].push(room); } else { console.error("unrecognised membership: " + me.membership + " - this should never happen"); } }); - if (s.lists["im.vector.fake.direct"].length == 0 && + if (lists["im.vector.fake.direct"].length == 0 && MatrixClientPeg.get().getAccountData('m.direct') === undefined && !MatrixClientPeg.get().isGuest()) { // scan through the 'recents' list for any rooms which look like DM rooms // and make them DM rooms - const oldRecents = s.lists["im.vector.fake.recent"]; - s.lists["im.vector.fake.recent"] = []; + const oldRecents = lists["im.vector.fake.recent"]; + lists["im.vector.fake.recent"] = []; for (const room of oldRecents) { const me = room.getMember(MatrixClientPeg.get().credentials.userId); if (me && Rooms.looksLikeDirectMessageRoom(room, me)) { self.listsForRoomId[room.roomId].push("im.vector.fake.direct"); - s.lists["im.vector.fake.direct"].push(room); + lists["im.vector.fake.direct"].push(room); } else { self.listsForRoomId[room.roomId].push("im.vector.fake.recent"); - s.lists["im.vector.fake.recent"].push(room); + lists["im.vector.fake.recent"].push(room); } } // save these new guessed DM rooms into the account data const newMDirectEvent = {}; - for (const room of s.lists["im.vector.fake.direct"]) { + for (const room of lists["im.vector.fake.direct"]) { const me = room.getMember(MatrixClientPeg.get().credentials.userId); const otherPerson = Rooms.getOnlyOtherMember(room, me); if (!otherPerson) continue; @@ -449,7 +464,7 @@ module.exports = React.createClass({ ]; */ - return s; + return lists; }, _getScrollNode: function() { @@ -479,6 +494,7 @@ module.exports = React.createClass({ var incomingCallBox = document.getElementById("incomingCallBox"); if (incomingCallBox && incomingCallBox.parentElement) { var scrollArea = this._getScrollNode(); + if (!scrollArea) return; // Use the offset of the top of the scroll area from the window // as this is used to calculate the CSS fixed top position for the stickies var scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset; @@ -502,6 +518,7 @@ module.exports = React.createClass({ // properly through React _initAndPositionStickyHeaders: function(initialise, scrollToPosition) { var scrollArea = this._getScrollNode(); + if (!scrollArea) return; // Use the offset of the top of the scroll area from the window // as this is used to calculate the CSS fixed top position for the stickies var scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset; @@ -599,6 +616,49 @@ module.exports = React.createClass({ this.refs.gemscroll.forceUpdate(); }, + _getEmptyContent: function(section) { + let greyed = false; + if (this.state.totalRoomCount === 0) { + const TintableSvg = sdk.getComponent('elements.TintableSvg'); + switch (section) { + case 'm.favourite': + case 'm.lowpriority': + greyed = true; + break; + case 'im.vector.fake.direct': + return
+
+ +
+ Use the button below to chat with someone! +
; + case 'im.vector.fake.recent': + return
+
+ +
+ Use the button below to browse the room directory +

+
+ +
+ or this button to start a new one! +
; + } + } + const RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget'); + + const labelText = 'Drop here to ' + (VERBS[section] || 'tag ' + section); + + let label; + if (greyed) { + label = {labelText}; + } else { + label = labelText; + } + return ; + }, + render: function() { var RoomSubList = sdk.getComponent('structures.RoomSubList'); var self = this; @@ -622,7 +682,7 @@ module.exports = React.createClass({ Date: Fri, 28 Apr 2017 11:20:29 +0100 Subject: [PATCH 012/127] Other empty sections no longer need to be greyed --- src/components/views/rooms/RoomList.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 39d3406b73..963f5ad425 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -617,14 +617,9 @@ module.exports = React.createClass({ }, _getEmptyContent: function(section) { - let greyed = false; if (this.state.totalRoomCount === 0) { const TintableSvg = sdk.getComponent('elements.TintableSvg'); switch (section) { - case 'm.favourite': - case 'm.lowpriority': - greyed = true; - break; case 'im.vector.fake.direct': return
@@ -650,13 +645,7 @@ module.exports = React.createClass({ const labelText = 'Drop here to ' + (VERBS[section] || 'tag ' + section); - let label; - if (greyed) { - label = {labelText}; - } else { - label = labelText; - } - return ; + return ; }, render: function() { From 6685cbcb25e76abd9304319e6f2f16dfc53e58f8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 29 Apr 2017 06:13:03 +0100 Subject: [PATCH 013/127] make MessageComposerInput (new and old) warn on unload new needs binding due to class this ref being softer couldn't do this nicely in MessageComposer/Input as isTyping wasn't propagated. Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/MessageComposerInput.js | 10 ++++++++++ src/components/views/rooms/MessageComposerInputOld.js | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 8efd2fa579..672279ef54 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -93,6 +93,7 @@ export default class MessageComposerInput extends React.Component { this.onEscape = this.onEscape.bind(this); this.setDisplayedCompletion = this.setDisplayedCompletion.bind(this); this.onMarkdownToggleClicked = this.onMarkdownToggleClicked.bind(this); + this.onPageUnload = this.onPageUnload.bind(this); const isRichtextEnabled = UserSettingsStore.getSyncedSetting('MessageComposerInput.isRichTextEnabled', false); @@ -233,11 +234,13 @@ export default class MessageComposerInput extends React.Component { this.refs.editor, this.props.room.roomId ); + window.addEventListener('beforeunload', this.onPageUnload); } componentWillUnmount() { dis.unregister(this.dispatcherRef); this.sentHistory.saveLastTextEntry(); + window.removeEventListener('beforeunload', this.onPageUnload); } componentWillUpdate(nextProps, nextState) { @@ -249,6 +252,13 @@ export default class MessageComposerInput extends React.Component { } } + onPageUnload(event) { + if (this.isTyping) { + return event.returnValue = + 'You seem to be typing a message, are you sure you want to quit?'; + } + } + onAction(payload) { let editor = this.refs.editor; let contentState = this.state.editorState.getCurrentContent(); diff --git a/src/components/views/rooms/MessageComposerInputOld.js b/src/components/views/rooms/MessageComposerInputOld.js index 378644478c..2a992cdf5f 100644 --- a/src/components/views/rooms/MessageComposerInputOld.js +++ b/src/components/views/rooms/MessageComposerInputOld.js @@ -177,11 +177,20 @@ export default React.createClass({ if (this.props.tabComplete) { this.props.tabComplete.setTextArea(this.refs.textarea); } + window.addEventListener('beforeunload', this.onPageUnload); }, componentWillUnmount: function() { dis.unregister(this.dispatcherRef); this.sentHistory.saveLastTextEntry(); + window.removeEventListener('beforeunload', this.onPageUnload); + }, + + onPageUnload(event) { + if (this.isTyping) { + return event.returnValue = + 'You seem to be typing a message, are you sure you want to quit?'; + } }, onAction: function(payload) { From daae3bd1ecfae565ff1ed7958c564ff73fb0eae0 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 29 Apr 2017 06:25:30 +0100 Subject: [PATCH 014/127] warn on unload when uploading file(s) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomView.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index a0c36374b6..9414a59e01 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -271,6 +271,7 @@ module.exports = React.createClass({ this._updateConfCallNotification(); + window.addEventListener('beforeunload', this.onPageUnload); window.addEventListener('resize', this.onResize); this.onResize(); @@ -353,6 +354,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().removeListener("accountData", this.onAccountData); } + window.removeEventListener('beforeunload', this.onPageUnload); window.removeEventListener('resize', this.onResize); document.removeEventListener("keydown", this.onKeyDown); @@ -365,6 +367,14 @@ module.exports = React.createClass({ // Tinter.tint(); // reset colourscheme }, + onPageUnload(event) { + if (ContentMessages.getCurrentUploads().length > 0) { + return event.returnValue = + 'You seem to be uploading files, are you sure you want to quit?'; + } + }, + + onKeyDown: function(ev) { let handled = false; const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; From b6fd771b9aaba669ef1b567c6d937f026533c2b4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 3 May 2017 16:21:35 +0100 Subject: [PATCH 015/127] move implementation to MessageComposer to it applies to any future composers Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/MessageComposer.js | 11 +++++++++++ src/components/views/rooms/MessageComposerInput.js | 10 ---------- src/components/views/rooms/MessageComposerInputOld.js | 9 --------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 88230062fe..2161198142 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -43,6 +43,7 @@ export default class MessageComposer extends React.Component { this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this); this.onInputStateChanged = this.onInputStateChanged.bind(this); this.onEvent = this.onEvent.bind(this); + this.onPageUnload = this.onPageUnload.bind(this); this.state = { autocompleteQuery: '', @@ -64,12 +65,22 @@ export default class MessageComposer extends React.Component { // marked as encrypted. // XXX: fragile as all hell - fixme somehow, perhaps with a dedicated Room.encryption event or something. MatrixClientPeg.get().on("event", this.onEvent); + + window.addEventListener('beforeunload', this.onPageUnload); } componentWillUnmount() { if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("event", this.onEvent); } + window.removeEventListener('beforeunload', this.onPageUnload); + } + + onPageUnload(event) { + if (this.messageComposerInput && this.messageComposerInput.isTyping) { + return event.returnValue = + 'You seem to be typing a message, are you sure you want to quit?'; + } } onEvent(event) { diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 672279ef54..8efd2fa579 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -93,7 +93,6 @@ export default class MessageComposerInput extends React.Component { this.onEscape = this.onEscape.bind(this); this.setDisplayedCompletion = this.setDisplayedCompletion.bind(this); this.onMarkdownToggleClicked = this.onMarkdownToggleClicked.bind(this); - this.onPageUnload = this.onPageUnload.bind(this); const isRichtextEnabled = UserSettingsStore.getSyncedSetting('MessageComposerInput.isRichTextEnabled', false); @@ -234,13 +233,11 @@ export default class MessageComposerInput extends React.Component { this.refs.editor, this.props.room.roomId ); - window.addEventListener('beforeunload', this.onPageUnload); } componentWillUnmount() { dis.unregister(this.dispatcherRef); this.sentHistory.saveLastTextEntry(); - window.removeEventListener('beforeunload', this.onPageUnload); } componentWillUpdate(nextProps, nextState) { @@ -252,13 +249,6 @@ export default class MessageComposerInput extends React.Component { } } - onPageUnload(event) { - if (this.isTyping) { - return event.returnValue = - 'You seem to be typing a message, are you sure you want to quit?'; - } - } - onAction(payload) { let editor = this.refs.editor; let contentState = this.state.editorState.getCurrentContent(); diff --git a/src/components/views/rooms/MessageComposerInputOld.js b/src/components/views/rooms/MessageComposerInputOld.js index 2a992cdf5f..378644478c 100644 --- a/src/components/views/rooms/MessageComposerInputOld.js +++ b/src/components/views/rooms/MessageComposerInputOld.js @@ -177,20 +177,11 @@ export default React.createClass({ if (this.props.tabComplete) { this.props.tabComplete.setTextArea(this.refs.textarea); } - window.addEventListener('beforeunload', this.onPageUnload); }, componentWillUnmount: function() { dis.unregister(this.dispatcherRef); this.sentHistory.saveLastTextEntry(); - window.removeEventListener('beforeunload', this.onPageUnload); - }, - - onPageUnload(event) { - if (this.isTyping) { - return event.returnValue = - 'You seem to be typing a message, are you sure you want to quit?'; - } }, onAction: function(payload) { From 356d29939c1deb2ce07694e653e0ee3c6d581d09 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 3 May 2017 16:25:27 +0100 Subject: [PATCH 016/127] also warn when quitting mid-call Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomStatusBar.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index 0389b606aa..0cb246973b 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -100,6 +100,10 @@ module.exports = React.createClass({ this._checkSize(); }, + componentDidMount: function() { + window.addEventListener('beforeunload', this.onPageUnload); + }, + componentDidUpdate: function() { this._checkSize(); }, @@ -111,6 +115,7 @@ module.exports = React.createClass({ client.removeListener("sync", this.onSyncStateChange); client.removeListener("RoomMember.typing", this.onRoomMemberTyping); } + window.removeEventListener('beforeunload', this.onPageUnload); }, onSyncStateChange: function(state, prevState) { @@ -128,6 +133,13 @@ module.exports = React.createClass({ }); }, + onPageUnload(event) { + if (this.props.hasActiveCall) { + return event.returnValue = + 'You seem to be in a call, are you sure you want to quit?'; + } + }, + // Check whether current size is greater than 0, if yes call props.onVisible _checkSize: function () { if (this.props.onVisible && this._getSize()) { From 9d92f93fcbf7208bc2ee37f3bf2fcb8e15629e07 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 3 May 2017 16:36:57 +0100 Subject: [PATCH 017/127] consolidate call onPageUnload handler into RoomView Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomStatusBar.js | 12 ------------ src/components/structures/RoomView.js | 3 +++ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index 0cb246973b..0389b606aa 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -100,10 +100,6 @@ module.exports = React.createClass({ this._checkSize(); }, - componentDidMount: function() { - window.addEventListener('beforeunload', this.onPageUnload); - }, - componentDidUpdate: function() { this._checkSize(); }, @@ -115,7 +111,6 @@ module.exports = React.createClass({ client.removeListener("sync", this.onSyncStateChange); client.removeListener("RoomMember.typing", this.onRoomMemberTyping); } - window.removeEventListener('beforeunload', this.onPageUnload); }, onSyncStateChange: function(state, prevState) { @@ -133,13 +128,6 @@ module.exports = React.createClass({ }); }, - onPageUnload(event) { - if (this.props.hasActiveCall) { - return event.returnValue = - 'You seem to be in a call, are you sure you want to quit?'; - } - }, - // Check whether current size is greater than 0, if yes call props.onVisible _checkSize: function () { if (this.props.onVisible && this._getSize()) { diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 9414a59e01..1b3ed6e80d 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -371,6 +371,9 @@ module.exports = React.createClass({ if (ContentMessages.getCurrentUploads().length > 0) { return event.returnValue = 'You seem to be uploading files, are you sure you want to quit?'; + } else if (this._getCallForRoom() && this.state.callState !== 'ended') { + return event.returnValue = + 'You seem to be in a call, are you sure you want to quit?'; } }, From ce119a63643309a22f31e004fe59c69ed37ab9a7 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 13:55:52 +0100 Subject: [PATCH 018/127] Add buttons to room sub list headers --- src/component-index.js | 2 + src/components/views/elements/RoleButton.js | 75 +++++++++++++++++++++ src/components/views/rooms/RoomList.js | 41 +++++++---- 3 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 src/components/views/elements/RoleButton.js diff --git a/src/component-index.js b/src/component-index.js index d6873c6dfd..68a734cbf6 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -125,6 +125,8 @@ import views$elements$PowerSelector from './components/views/elements/PowerSelec views$elements$PowerSelector && (module.exports.components['views.elements.PowerSelector'] = views$elements$PowerSelector); import views$elements$ProgressBar from './components/views/elements/ProgressBar'; views$elements$ProgressBar && (module.exports.components['views.elements.ProgressBar'] = views$elements$ProgressBar); +import views$elements$RoleButton from './components/views/elements/RoleButton'; +views$elements$RoleButton && (module.exports.components['views.elements.RoleButton'] = views$elements$RoleButton); import views$elements$TintableSvg from './components/views/elements/TintableSvg'; views$elements$TintableSvg && (module.exports.components['views.elements.TintableSvg'] = views$elements$TintableSvg); import views$elements$TruncatedList from './components/views/elements/TruncatedList'; diff --git a/src/components/views/elements/RoleButton.js b/src/components/views/elements/RoleButton.js new file mode 100644 index 0000000000..06006a5779 --- /dev/null +++ b/src/components/views/elements/RoleButton.js @@ -0,0 +1,75 @@ +/* +Copyright Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import PropTypes from 'prop-types'; +import AccessibleButton from './AccessibleButton'; +import dis from '../../../dispatcher'; +import sdk from '../../../index'; + +export default React.createClass({ + displayName: 'RoleButton', + + propTypes: { + role: PropTypes.string.isRequired, + size: PropTypes.string, + }, + + getDefaultProps: function() { + return { + size: 25, + }; + }, + + _onClick: function(ev) { + ev.stopPropagation(); + + let action; + switch(this.props.role) { + case 'start_chat': + action = 'view_create_chat'; + break; + case 'room_directory': + action = 'view_room_directory'; + break; + case 'create_room': + action = 'view_create_room'; + break; + } + if (action) dis.dispatch({action: action}); + }, + + _getIconPath() { + switch(this.props.role) { + case 'start_chat': + return 'img/icons-people.svg'; + case 'room_directory': + return 'img/icons-directory.svg'; + case 'create_room': + return 'img/icons-create-room.svg'; + } + }, + + render: function() { + const TintableSvg = sdk.getComponent("elements.TintableSvg"); + + return ( + + + + ); + } +}); diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 963f5ad425..fe75271a25 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -28,6 +29,7 @@ var Rooms = require('../../../Rooms'); import DMRoomMap from '../../../utils/DMRoomMap'; var Receipt = require('../../../utils/Receipt'); var constantTimeDispatcher = require('../../../ConstantTimeDispatcher'); +import AccessibleButton from '../elements/AccessibleButton'; const HIDE_CONFERENCE_CHANS = true; @@ -617,27 +619,23 @@ module.exports = React.createClass({ }, _getEmptyContent: function(section) { + const RoleButton = sdk.getComponent('elements.RoleButton'); if (this.state.totalRoomCount === 0) { const TintableSvg = sdk.getComponent('elements.TintableSvg'); switch (section) { case 'im.vector.fake.direct': return
-
- -
- Use the button below to chat with someone! + Press + + to start a chat with someone
; case 'im.vector.fake.recent': return
-
- -
- Use the button below to browse the room directory -

-
- -
- or this button to start a new one! + You're not in any rooms yet! Press + + to make a room or + + to browse the directory
; } } @@ -648,6 +646,21 @@ module.exports = React.createClass({ return ; }, + _getHeaderItems: function(section) { + const RoleButton = sdk.getComponent('elements.RoleButton'); + switch (section) { + case 'im.vector.fake.direct': + return + + ; + case 'im.vector.fake.recent': + return + + + ; + } + }, + render: function() { var RoomSubList = sdk.getComponent('structures.RoomSubList'); var self = this; @@ -685,6 +698,7 @@ module.exports = React.createClass({ label="People" tagName="im.vector.fake.direct" emptyContent={this._getEmptyContent('im.vector.fake.direct')} + headerItems={this._getHeaderItems('im.vector.fake.direct')} editable={ true } order="recent" incomingCall={ self.state.incomingCall } @@ -700,6 +714,7 @@ module.exports = React.createClass({ tagName="im.vector.fake.recent" editable={ true } emptyContent={this._getEmptyContent('im.vector.fake.recent')} + headerItems={this._getHeaderItems('im.vector.fake.recent')} order="recent" incomingCall={ self.state.incomingCall } collapsed={ self.props.collapsed } From 0998adb36693ed5dd445b360b2b86792b3c6912f Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 15:02:21 +0100 Subject: [PATCH 019/127] What year is it? Who's the president? --- src/components/views/elements/RoleButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/RoleButton.js b/src/components/views/elements/RoleButton.js index 06006a5779..f20b4c6b88 100644 --- a/src/components/views/elements/RoleButton.js +++ b/src/components/views/elements/RoleButton.js @@ -1,5 +1,5 @@ /* -Copyright Vector Creations Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 6a1d0fbab54d10d6c06d5172f2e7d4d20e138b0f Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 15:38:09 +0100 Subject: [PATCH 020/127] Make bottom left menu buttons use RoleButton too --- src/components/views/elements/RoleButton.js | 53 ++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/RoleButton.js b/src/components/views/elements/RoleButton.js index f20b4c6b88..60f227a067 100644 --- a/src/components/views/elements/RoleButton.js +++ b/src/components/views/elements/RoleButton.js @@ -31,6 +31,13 @@ export default React.createClass({ getDefaultProps: function() { return { size: 25, + tooltip: false, + }; + }, + + getInitialState: function() { + return { + showTooltip: false, }; }, @@ -48,10 +55,39 @@ export default React.createClass({ case 'create_room': action = 'view_create_room'; break; + case 'home_page': + action = 'view_home_page'; + break; + case 'settings': + action = 'view_user_settings'; + break; } if (action) dis.dispatch({action: action}); }, + _onMouseEnter: function() { + if (this.props.tooltip) this.setState({showTooltip: true}); + }, + + _onMouseLeave: function() { + this.setState({showTooltip: false}); + }, + + _getLabel() { + switch(this.props.role) { + case 'start_chat': + return 'Start chat'; + case 'room_directory': + return 'Room directory'; + case 'create_room': + return 'Create new room'; + case 'home_page': + return 'Welcome page'; + case 'settings': + return 'Settings'; + } + }, + _getIconPath() { switch(this.props.role) { case 'start_chat': @@ -60,15 +96,30 @@ export default React.createClass({ return 'img/icons-directory.svg'; case 'create_room': return 'img/icons-create-room.svg'; + case 'home_page': + return 'img/icons-home.svg'; + case 'settings': + return 'img/icons-settings.svg'; } }, render: function() { const TintableSvg = sdk.getComponent("elements.TintableSvg"); + let tooltip; + if (this.state.showTooltip) { + const RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); + tooltip = ; + } + return ( - + + {tooltip} ); } From 72df43d22b40884faed5155f289fae467235d205 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 15:46:24 +0100 Subject: [PATCH 021/127] Year --- src/components/views/rooms/RoomList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 0b56b87c72..33f6890a2a 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -1,6 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd -Copyright Vector Creations Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 909cdb6e9aadfb115f38d859a82e0583daa9b114 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 16:22:06 +0100 Subject: [PATCH 022/127] Depend on prop-types module So we can start writing code compatible with new React --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 95a82bbb73..37903252c4 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "lodash": "^4.13.1", "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "optimist": "^0.6.1", + "prop-types": "^15.5.8", "q": "^1.4.1", "react": "^15.4.0", "react-addons-css-transition-group": "15.3.2", From f86ca5bc97e915ae097f5e4eba459aba9e0973b8 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 18:08:04 +0100 Subject: [PATCH 023/127] Hide empty tips if collapsed --- src/components/views/rooms/RoomList.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 33f6890a2a..6f5097840f 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -578,6 +578,12 @@ module.exports = React.createClass({ }, _getEmptyContent: function(section) { + const RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget'); + + if (this.props.collapsed) { + return ; + } + const RoleButton = sdk.getComponent('elements.RoleButton'); if (this.state.totalRoomCount === 0) { const TintableSvg = sdk.getComponent('elements.TintableSvg'); @@ -598,7 +604,6 @@ module.exports = React.createClass({
; } } - const RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget'); const labelText = 'Drop here to ' + (VERBS[section] || 'tag ' + section); From 4a5821e1999748a9fae288a08f0def9e4a72f897 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 5 May 2017 14:25:18 +0100 Subject: [PATCH 024/127] Separate classes for the different buttons Also rename RoleButton to ActionButton because it's not being given a Role any more. --- src/component-index.js | 14 ++++- .../{RoleButton.js => ActionButton.js} | 60 +++---------------- .../views/elements/CreateRoomButton.js | 37 ++++++++++++ src/components/views/elements/HomeButton.js | 37 ++++++++++++ .../views/elements/RoomDirectoryButton.js | 37 ++++++++++++ .../views/elements/SettingsButton.js | 37 ++++++++++++ .../views/elements/StartChatButton.js | 37 ++++++++++++ src/components/views/rooms/RoomList.js | 20 ++++--- 8 files changed, 216 insertions(+), 63 deletions(-) rename src/components/views/elements/{RoleButton.js => ActionButton.js} (54%) create mode 100644 src/components/views/elements/CreateRoomButton.js create mode 100644 src/components/views/elements/HomeButton.js create mode 100644 src/components/views/elements/RoomDirectoryButton.js create mode 100644 src/components/views/elements/SettingsButton.js create mode 100644 src/components/views/elements/StartChatButton.js diff --git a/src/component-index.js b/src/component-index.js index 68a734cbf6..090a27d5ed 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -103,10 +103,14 @@ import views$dialogs$UnknownDeviceDialog from './components/views/dialogs/Unknow views$dialogs$UnknownDeviceDialog && (module.exports.components['views.dialogs.UnknownDeviceDialog'] = views$dialogs$UnknownDeviceDialog); import views$elements$AccessibleButton from './components/views/elements/AccessibleButton'; views$elements$AccessibleButton && (module.exports.components['views.elements.AccessibleButton'] = views$elements$AccessibleButton); +import views$elements$ActionButton from './components/views/elements/ActionButton'; +views$elements$ActionButton && (module.exports.components['views.elements.ActionButton'] = views$elements$ActionButton); import views$elements$AddressSelector from './components/views/elements/AddressSelector'; views$elements$AddressSelector && (module.exports.components['views.elements.AddressSelector'] = views$elements$AddressSelector); import views$elements$AddressTile from './components/views/elements/AddressTile'; views$elements$AddressTile && (module.exports.components['views.elements.AddressTile'] = views$elements$AddressTile); +import views$elements$CreateRoomButton from './components/views/elements/CreateRoomButton'; +views$elements$CreateRoomButton && (module.exports.components['views.elements.CreateRoomButton'] = views$elements$CreateRoomButton); import views$elements$DeviceVerifyButtons from './components/views/elements/DeviceVerifyButtons'; views$elements$DeviceVerifyButtons && (module.exports.components['views.elements.DeviceVerifyButtons'] = views$elements$DeviceVerifyButtons); import views$elements$DirectorySearchBox from './components/views/elements/DirectorySearchBox'; @@ -119,14 +123,20 @@ import views$elements$EditableTextContainer from './components/views/elements/Ed views$elements$EditableTextContainer && (module.exports.components['views.elements.EditableTextContainer'] = views$elements$EditableTextContainer); import views$elements$EmojiText from './components/views/elements/EmojiText'; views$elements$EmojiText && (module.exports.components['views.elements.EmojiText'] = views$elements$EmojiText); +import views$elements$HomeButton from './components/views/elements/HomeButton'; +views$elements$HomeButton && (module.exports.components['views.elements.HomeButton'] = views$elements$HomeButton); import views$elements$MemberEventListSummary from './components/views/elements/MemberEventListSummary'; views$elements$MemberEventListSummary && (module.exports.components['views.elements.MemberEventListSummary'] = views$elements$MemberEventListSummary); import views$elements$PowerSelector from './components/views/elements/PowerSelector'; views$elements$PowerSelector && (module.exports.components['views.elements.PowerSelector'] = views$elements$PowerSelector); import views$elements$ProgressBar from './components/views/elements/ProgressBar'; views$elements$ProgressBar && (module.exports.components['views.elements.ProgressBar'] = views$elements$ProgressBar); -import views$elements$RoleButton from './components/views/elements/RoleButton'; -views$elements$RoleButton && (module.exports.components['views.elements.RoleButton'] = views$elements$RoleButton); +import views$elements$RoomDirectoryButton from './components/views/elements/RoomDirectoryButton'; +views$elements$RoomDirectoryButton && (module.exports.components['views.elements.RoomDirectoryButton'] = views$elements$RoomDirectoryButton); +import views$elements$SettingsButton from './components/views/elements/SettingsButton'; +views$elements$SettingsButton && (module.exports.components['views.elements.SettingsButton'] = views$elements$SettingsButton); +import views$elements$StartChatButton from './components/views/elements/StartChatButton'; +views$elements$StartChatButton && (module.exports.components['views.elements.StartChatButton'] = views$elements$StartChatButton); import views$elements$TintableSvg from './components/views/elements/TintableSvg'; views$elements$TintableSvg && (module.exports.components['views.elements.TintableSvg'] = views$elements$TintableSvg); import views$elements$TruncatedList from './components/views/elements/TruncatedList'; diff --git a/src/components/views/elements/RoleButton.js b/src/components/views/elements/ActionButton.js similarity index 54% rename from src/components/views/elements/RoleButton.js rename to src/components/views/elements/ActionButton.js index 60f227a067..6d6289ddab 100644 --- a/src/components/views/elements/RoleButton.js +++ b/src/components/views/elements/ActionButton.js @@ -24,8 +24,11 @@ export default React.createClass({ displayName: 'RoleButton', propTypes: { - role: PropTypes.string.isRequired, size: PropTypes.string, + tooltip: PropTypes.bool, + action: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + iconPath: PropTypes.string.isRequired, }, getDefaultProps: function() { @@ -43,26 +46,7 @@ export default React.createClass({ _onClick: function(ev) { ev.stopPropagation(); - - let action; - switch(this.props.role) { - case 'start_chat': - action = 'view_create_chat'; - break; - case 'room_directory': - action = 'view_room_directory'; - break; - case 'create_room': - action = 'view_create_room'; - break; - case 'home_page': - action = 'view_home_page'; - break; - case 'settings': - action = 'view_user_settings'; - break; - } - if (action) dis.dispatch({action: action}); + dis.dispatch({action: this.props.action}); }, _onMouseEnter: function() { @@ -73,43 +57,13 @@ export default React.createClass({ this.setState({showTooltip: false}); }, - _getLabel() { - switch(this.props.role) { - case 'start_chat': - return 'Start chat'; - case 'room_directory': - return 'Room directory'; - case 'create_room': - return 'Create new room'; - case 'home_page': - return 'Welcome page'; - case 'settings': - return 'Settings'; - } - }, - - _getIconPath() { - switch(this.props.role) { - case 'start_chat': - return 'img/icons-people.svg'; - case 'room_directory': - return 'img/icons-directory.svg'; - case 'create_room': - return 'img/icons-create-room.svg'; - case 'home_page': - return 'img/icons-home.svg'; - case 'settings': - return 'img/icons-settings.svg'; - } - }, - render: function() { const TintableSvg = sdk.getComponent("elements.TintableSvg"); let tooltip; if (this.state.showTooltip) { const RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); - tooltip = ; + tooltip = ; } return ( @@ -118,7 +72,7 @@ export default React.createClass({ onMouseEnter={this._onMouseEnter} onMouseLeave={this._onMouseLeave} > - + {tooltip} ); diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js new file mode 100644 index 0000000000..d6b6526d6c --- /dev/null +++ b/src/components/views/elements/CreateRoomButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const CreateRoomButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +CreateRoomButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default CreateRoomButton; diff --git a/src/components/views/elements/HomeButton.js b/src/components/views/elements/HomeButton.js new file mode 100644 index 0000000000..4c7f295c87 --- /dev/null +++ b/src/components/views/elements/HomeButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const HomeButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +HomeButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default HomeButton; diff --git a/src/components/views/elements/RoomDirectoryButton.js b/src/components/views/elements/RoomDirectoryButton.js new file mode 100644 index 0000000000..651dd8edd0 --- /dev/null +++ b/src/components/views/elements/RoomDirectoryButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const RoomDirectoryButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +RoomDirectoryButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default RoomDirectoryButton; diff --git a/src/components/views/elements/SettingsButton.js b/src/components/views/elements/SettingsButton.js new file mode 100644 index 0000000000..51da6e3fd1 --- /dev/null +++ b/src/components/views/elements/SettingsButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const SettingsButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +SettingsButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default SettingsButton; diff --git a/src/components/views/elements/StartChatButton.js b/src/components/views/elements/StartChatButton.js new file mode 100644 index 0000000000..66cd911754 --- /dev/null +++ b/src/components/views/elements/StartChatButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const StartChatButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +StartChatButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default StartChatButton; diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 6f5097840f..5917af5eb1 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -584,22 +584,24 @@ module.exports = React.createClass({ return ; } - const RoleButton = sdk.getComponent('elements.RoleButton'); + const StartChatButton = sdk.getComponent('elements.StartChatButton'); + const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); + const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); if (this.state.totalRoomCount === 0) { const TintableSvg = sdk.getComponent('elements.TintableSvg'); switch (section) { case 'im.vector.fake.direct': return
Press - + to start a chat with someone
; case 'im.vector.fake.recent': return
You're not in any rooms yet! Press - + to make a room or - + to browse the directory
; } @@ -611,16 +613,18 @@ module.exports = React.createClass({ }, _getHeaderItems: function(section) { - const RoleButton = sdk.getComponent('elements.RoleButton'); + const StartChatButton = sdk.getComponent('elements.StartChatButton'); + const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); + const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); switch (section) { case 'im.vector.fake.direct': return - + ; case 'im.vector.fake.recent': return - - + + ; } }, From 4fc4ae1e9907267d97d96ac9c5ac31b6140aac6b Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 5 May 2017 14:56:26 +0100 Subject: [PATCH 025/127] Size is a string, import react React gets put in by the JSX transpile --- src/components/views/elements/ActionButton.js | 2 +- src/components/views/elements/CreateRoomButton.js | 1 + src/components/views/elements/HomeButton.js | 1 + src/components/views/elements/RoomDirectoryButton.js | 1 + src/components/views/elements/SettingsButton.js | 1 + src/components/views/elements/StartChatButton.js | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js index 6d6289ddab..267388daf6 100644 --- a/src/components/views/elements/ActionButton.js +++ b/src/components/views/elements/ActionButton.js @@ -33,7 +33,7 @@ export default React.createClass({ getDefaultProps: function() { return { - size: 25, + size: "25", tooltip: false, }; }, diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js index d6b6526d6c..e7e526d36b 100644 --- a/src/components/views/elements/CreateRoomButton.js +++ b/src/components/views/elements/CreateRoomButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; diff --git a/src/components/views/elements/HomeButton.js b/src/components/views/elements/HomeButton.js index 4c7f295c87..5c446f24c9 100644 --- a/src/components/views/elements/HomeButton.js +++ b/src/components/views/elements/HomeButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; diff --git a/src/components/views/elements/RoomDirectoryButton.js b/src/components/views/elements/RoomDirectoryButton.js index 651dd8edd0..5e68776a15 100644 --- a/src/components/views/elements/RoomDirectoryButton.js +++ b/src/components/views/elements/RoomDirectoryButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; diff --git a/src/components/views/elements/SettingsButton.js b/src/components/views/elements/SettingsButton.js index 51da6e3fd1..c6438da277 100644 --- a/src/components/views/elements/SettingsButton.js +++ b/src/components/views/elements/SettingsButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; diff --git a/src/components/views/elements/StartChatButton.js b/src/components/views/elements/StartChatButton.js index 66cd911754..02d5677a7c 100644 --- a/src/components/views/elements/StartChatButton.js +++ b/src/components/views/elements/StartChatButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; From 1a0ea29995d38b5ef824b11aa299b98cea12ebd3 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 5 May 2017 17:51:14 +0100 Subject: [PATCH 026/127] Remove redundant role elements --- src/components/views/rooms/RoomList.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 5917af5eb1..8d396b5536 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -619,12 +619,12 @@ module.exports = React.createClass({ switch (section) { case 'im.vector.fake.direct': return - + ; case 'im.vector.fake.recent': return - - + + ; } }, From 2b71123ddcacb103d2338d8d525fd4922d24ff68 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 6 May 2017 01:45:28 +0100 Subject: [PATCH 027/127] suppress null member rejoins again reverts https://github.com/matrix-org/matrix-react-sdk/commit/f5fe4b24336a8245b5a08050fefe13b9999d92fb should fix https://github.com/vector-im/riot-web/issues/3788 --- src/TextForEvent.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TextForEvent.js b/src/TextForEvent.js index 40d6a49998..3f200a089d 100644 --- a/src/TextForEvent.js +++ b/src/TextForEvent.js @@ -65,8 +65,8 @@ function textForMemberEvent(ev) { } else if (!ev.getPrevContent().avatar_url && ev.getContent().avatar_url) { return senderName + " set a profile picture"; } else { - // hacky hack for https://github.com/vector-im/vector-web/issues/2020 - return senderName + " rejoined the room."; + // suppress null rejoins + return ''; } } else { if (!ev.target) console.warn("Join message has no target! -- " + ev.getContent().state_key); From 2b2b43a7f3d57dcbf53a70817b31d6287974e517 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 7 May 2017 18:15:37 +0100 Subject: [PATCH 028/127] Content in Composer is not lost on unload so it should be fine to scare the user thinking they have lost all of their content even though when they come back they can cry with joy :D Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/MessageComposer.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 2161198142..88230062fe 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -43,7 +43,6 @@ export default class MessageComposer extends React.Component { this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this); this.onInputStateChanged = this.onInputStateChanged.bind(this); this.onEvent = this.onEvent.bind(this); - this.onPageUnload = this.onPageUnload.bind(this); this.state = { autocompleteQuery: '', @@ -65,22 +64,12 @@ export default class MessageComposer extends React.Component { // marked as encrypted. // XXX: fragile as all hell - fixme somehow, perhaps with a dedicated Room.encryption event or something. MatrixClientPeg.get().on("event", this.onEvent); - - window.addEventListener('beforeunload', this.onPageUnload); } componentWillUnmount() { if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("event", this.onEvent); } - window.removeEventListener('beforeunload', this.onPageUnload); - } - - onPageUnload(event) { - if (this.messageComposerInput && this.messageComposerInput.isTyping) { - return event.returnValue = - 'You seem to be typing a message, are you sure you want to quit?'; - } } onEvent(event) { From a14135067005f7d0e07121dcefb29f548c6754da Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 7 May 2017 20:01:55 +0100 Subject: [PATCH 029/127] Explicitly save composer content onUnload small oversight, caught by Matthew Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/MessageComposer.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 88230062fe..0ee3c2082d 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -43,6 +43,7 @@ export default class MessageComposer extends React.Component { this.onToggleMarkdownClicked = this.onToggleMarkdownClicked.bind(this); this.onInputStateChanged = this.onInputStateChanged.bind(this); this.onEvent = this.onEvent.bind(this); + this.onPageUnload = this.onPageUnload.bind(this); this.state = { autocompleteQuery: '', @@ -64,12 +65,21 @@ export default class MessageComposer extends React.Component { // marked as encrypted. // XXX: fragile as all hell - fixme somehow, perhaps with a dedicated Room.encryption event or something. MatrixClientPeg.get().on("event", this.onEvent); + + window.addEventListener('beforeunload', this.onPageUnload); } componentWillUnmount() { if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("event", this.onEvent); } + window.removeEventListener('beforeunload', this.onPageUnload); + } + + onPageUnload(event) { + if (this.messageComposerInput) { + this.messageComposerInput.sentHistory.saveLastTextEntry(); + } } onEvent(event) { From 78e72723440780814fced82cc8a2406c47992464 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Sun, 7 May 2017 20:43:42 +0100 Subject: [PATCH 030/127] Fixes 2 issues with Dialog closing + Upload Confirmation dialog would just change focus on ESC and not close + Keywords Dialog in UserSettings would also close UserSettings because event bubbled up --- src/components/views/dialogs/BaseDialog.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index 279dedbd43..d567a0ba9a 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -57,6 +57,12 @@ export default React.createClass({ } }, + // Don't let key down events get any further, so they only trigger this and nothing more + _onKeyDown: function(e) { + e.stopPropagation(); + e.preventDefault(); + }, + // Must be when the key is released (and not pressed) otherwise componentWillUnmount // will focus another element which will receive future key events _onKeyUp: function(e) { @@ -81,7 +87,7 @@ export default React.createClass({ const TintableSvg = sdk.getComponent("elements.TintableSvg"); return ( -
+
From 360f1cd250378a54d0305464111b2af57fb79731 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Sun, 7 May 2017 20:57:54 +0100 Subject: [PATCH 031/127] completely missed the ESC check I need sleep --- src/components/views/dialogs/BaseDialog.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index d567a0ba9a..e7b8a687f5 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -59,8 +59,10 @@ export default React.createClass({ // Don't let key down events get any further, so they only trigger this and nothing more _onKeyDown: function(e) { - e.stopPropagation(); - e.preventDefault(); + if (e.keyCode === KeyCode.ESCAPE) { + e.stopPropagation(); + e.preventDefault(); + } }, // Must be when the key is released (and not pressed) otherwise componentWillUnmount From bd32df4ef6dbf66f1ba5d9b23117fefbe2132c72 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Sun, 7 May 2017 20:58:30 +0100 Subject: [PATCH 032/127] comment wording --- src/components/views/dialogs/BaseDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index e7b8a687f5..ac36dfd056 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -57,7 +57,7 @@ export default React.createClass({ } }, - // Don't let key down events get any further, so they only trigger this and nothing more + // Don't let esc keydown events get any further, so they only trigger this and nothing more _onKeyDown: function(e) { if (e.keyCode === KeyCode.ESCAPE) { e.stopPropagation(); From c841eb641b85995bddb235d3db2c779daffe97a1 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 8 May 2017 11:26:25 +0100 Subject: [PATCH 033/127] Fix 'start chat' button --- src/components/views/elements/StartChatButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/StartChatButton.js b/src/components/views/elements/StartChatButton.js index 02d5677a7c..747f75d1b3 100644 --- a/src/components/views/elements/StartChatButton.js +++ b/src/components/views/elements/StartChatButton.js @@ -21,7 +21,7 @@ import PropTypes from 'prop-types'; const StartChatButton = function(props) { const ActionButton = sdk.getComponent('elements.ActionButton'); return ( - Date: Mon, 8 May 2017 11:59:06 +0100 Subject: [PATCH 034/127] Fix keys for AddressSelector Was using a property which just did not exist. --- src/components/views/elements/AddressSelector.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/AddressSelector.js b/src/components/views/elements/AddressSelector.js index 6bad15f7d0..5329994037 100644 --- a/src/components/views/elements/AddressSelector.js +++ b/src/components/views/elements/AddressSelector.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -138,7 +139,7 @@ export default React.createClass({ onClick={this.onClick.bind(this, i)} onMouseEnter={this.onMouseEnter.bind(this, i)} onMouseLeave={this.onMouseLeave} - key={this.props.addressList[i].userId} + key={this.props.addressList[i].addressType + "/" + this.props.addressList[i].address} ref={(ref) => { this.addressListElement = ref; }} > From 39323647d13532993872ed870e1f68760e73bf73 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 8 May 2017 14:01:44 +0100 Subject: [PATCH 035/127] Don't show null URL previews These are URLs that were spidered by the server without error but yielded an empty response from the server. There's nothing to display, so return an empty div. --- src/components/views/rooms/LinkPreviewWidget.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js index ef8fb29cbc..35e6d28b1f 100644 --- a/src/components/views/rooms/LinkPreviewWidget.js +++ b/src/components/views/rooms/LinkPreviewWidget.js @@ -100,7 +100,9 @@ module.exports = React.createClass({ render: function() { var p = this.state.preview; - if (!p) return
; + if (!p || Object.keys(p).length === 0) { + return
; + } // FIXME: do we want to factor out all image displaying between this and MImageBody - especially for lightboxing? var image = p["og:image"]; From d1f467ee914423e4ea640e8116cb8625c9ba70c8 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 8 May 2017 14:53:00 +0100 Subject: [PATCH 036/127] Remove auto-generated component-index This will now be generated as part of the build process (`npm run build`) and whilst developing (`npm run start`). --- src/component-index.js | 265 ----------------------------------------- 1 file changed, 265 deletions(-) delete mode 100644 src/component-index.js diff --git a/src/component-index.js b/src/component-index.js deleted file mode 100644 index 090a27d5ed..0000000000 --- a/src/component-index.js +++ /dev/null @@ -1,265 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/* - * THIS FILE IS AUTO-GENERATED - * You can edit it you like, but your changes will be overwritten, - * so you'd just be trying to swim upstream like a salmon. - * You are not a salmon. - * - * To update it, run: - * ./reskindex.js -h header - */ - -module.exports.components = {}; -import structures$ContextualMenu from './components/structures/ContextualMenu'; -structures$ContextualMenu && (module.exports.components['structures.ContextualMenu'] = structures$ContextualMenu); -import structures$CreateRoom from './components/structures/CreateRoom'; -structures$CreateRoom && (module.exports.components['structures.CreateRoom'] = structures$CreateRoom); -import structures$FilePanel from './components/structures/FilePanel'; -structures$FilePanel && (module.exports.components['structures.FilePanel'] = structures$FilePanel); -import structures$InteractiveAuth from './components/structures/InteractiveAuth'; -structures$InteractiveAuth && (module.exports.components['structures.InteractiveAuth'] = structures$InteractiveAuth); -import structures$LoggedInView from './components/structures/LoggedInView'; -structures$LoggedInView && (module.exports.components['structures.LoggedInView'] = structures$LoggedInView); -import structures$MatrixChat from './components/structures/MatrixChat'; -structures$MatrixChat && (module.exports.components['structures.MatrixChat'] = structures$MatrixChat); -import structures$MessagePanel from './components/structures/MessagePanel'; -structures$MessagePanel && (module.exports.components['structures.MessagePanel'] = structures$MessagePanel); -import structures$NotificationPanel from './components/structures/NotificationPanel'; -structures$NotificationPanel && (module.exports.components['structures.NotificationPanel'] = structures$NotificationPanel); -import structures$RoomStatusBar from './components/structures/RoomStatusBar'; -structures$RoomStatusBar && (module.exports.components['structures.RoomStatusBar'] = structures$RoomStatusBar); -import structures$RoomView from './components/structures/RoomView'; -structures$RoomView && (module.exports.components['structures.RoomView'] = structures$RoomView); -import structures$ScrollPanel from './components/structures/ScrollPanel'; -structures$ScrollPanel && (module.exports.components['structures.ScrollPanel'] = structures$ScrollPanel); -import structures$TimelinePanel from './components/structures/TimelinePanel'; -structures$TimelinePanel && (module.exports.components['structures.TimelinePanel'] = structures$TimelinePanel); -import structures$UploadBar from './components/structures/UploadBar'; -structures$UploadBar && (module.exports.components['structures.UploadBar'] = structures$UploadBar); -import structures$UserSettings from './components/structures/UserSettings'; -structures$UserSettings && (module.exports.components['structures.UserSettings'] = structures$UserSettings); -import structures$login$ForgotPassword from './components/structures/login/ForgotPassword'; -structures$login$ForgotPassword && (module.exports.components['structures.login.ForgotPassword'] = structures$login$ForgotPassword); -import structures$login$Login from './components/structures/login/Login'; -structures$login$Login && (module.exports.components['structures.login.Login'] = structures$login$Login); -import structures$login$PostRegistration from './components/structures/login/PostRegistration'; -structures$login$PostRegistration && (module.exports.components['structures.login.PostRegistration'] = structures$login$PostRegistration); -import structures$login$Registration from './components/structures/login/Registration'; -structures$login$Registration && (module.exports.components['structures.login.Registration'] = structures$login$Registration); -import views$avatars$BaseAvatar from './components/views/avatars/BaseAvatar'; -views$avatars$BaseAvatar && (module.exports.components['views.avatars.BaseAvatar'] = views$avatars$BaseAvatar); -import views$avatars$MemberAvatar from './components/views/avatars/MemberAvatar'; -views$avatars$MemberAvatar && (module.exports.components['views.avatars.MemberAvatar'] = views$avatars$MemberAvatar); -import views$avatars$RoomAvatar from './components/views/avatars/RoomAvatar'; -views$avatars$RoomAvatar && (module.exports.components['views.avatars.RoomAvatar'] = views$avatars$RoomAvatar); -import views$create_room$CreateRoomButton from './components/views/create_room/CreateRoomButton'; -views$create_room$CreateRoomButton && (module.exports.components['views.create_room.CreateRoomButton'] = views$create_room$CreateRoomButton); -import views$create_room$Presets from './components/views/create_room/Presets'; -views$create_room$Presets && (module.exports.components['views.create_room.Presets'] = views$create_room$Presets); -import views$create_room$RoomAlias from './components/views/create_room/RoomAlias'; -views$create_room$RoomAlias && (module.exports.components['views.create_room.RoomAlias'] = views$create_room$RoomAlias); -import views$dialogs$BaseDialog from './components/views/dialogs/BaseDialog'; -views$dialogs$BaseDialog && (module.exports.components['views.dialogs.BaseDialog'] = views$dialogs$BaseDialog); -import views$dialogs$ChatCreateOrReuseDialog from './components/views/dialogs/ChatCreateOrReuseDialog'; -views$dialogs$ChatCreateOrReuseDialog && (module.exports.components['views.dialogs.ChatCreateOrReuseDialog'] = views$dialogs$ChatCreateOrReuseDialog); -import views$dialogs$ChatInviteDialog from './components/views/dialogs/ChatInviteDialog'; -views$dialogs$ChatInviteDialog && (module.exports.components['views.dialogs.ChatInviteDialog'] = views$dialogs$ChatInviteDialog); -import views$dialogs$ConfirmRedactDialog from './components/views/dialogs/ConfirmRedactDialog'; -views$dialogs$ConfirmRedactDialog && (module.exports.components['views.dialogs.ConfirmRedactDialog'] = views$dialogs$ConfirmRedactDialog); -import views$dialogs$ConfirmUserActionDialog from './components/views/dialogs/ConfirmUserActionDialog'; -views$dialogs$ConfirmUserActionDialog && (module.exports.components['views.dialogs.ConfirmUserActionDialog'] = views$dialogs$ConfirmUserActionDialog); -import views$dialogs$DeactivateAccountDialog from './components/views/dialogs/DeactivateAccountDialog'; -views$dialogs$DeactivateAccountDialog && (module.exports.components['views.dialogs.DeactivateAccountDialog'] = views$dialogs$DeactivateAccountDialog); -import views$dialogs$ErrorDialog from './components/views/dialogs/ErrorDialog'; -views$dialogs$ErrorDialog && (module.exports.components['views.dialogs.ErrorDialog'] = views$dialogs$ErrorDialog); -import views$dialogs$InteractiveAuthDialog from './components/views/dialogs/InteractiveAuthDialog'; -views$dialogs$InteractiveAuthDialog && (module.exports.components['views.dialogs.InteractiveAuthDialog'] = views$dialogs$InteractiveAuthDialog); -import views$dialogs$NeedToRegisterDialog from './components/views/dialogs/NeedToRegisterDialog'; -views$dialogs$NeedToRegisterDialog && (module.exports.components['views.dialogs.NeedToRegisterDialog'] = views$dialogs$NeedToRegisterDialog); -import views$dialogs$QuestionDialog from './components/views/dialogs/QuestionDialog'; -views$dialogs$QuestionDialog && (module.exports.components['views.dialogs.QuestionDialog'] = views$dialogs$QuestionDialog); -import views$dialogs$SessionRestoreErrorDialog from './components/views/dialogs/SessionRestoreErrorDialog'; -views$dialogs$SessionRestoreErrorDialog && (module.exports.components['views.dialogs.SessionRestoreErrorDialog'] = views$dialogs$SessionRestoreErrorDialog); -import views$dialogs$SetDisplayNameDialog from './components/views/dialogs/SetDisplayNameDialog'; -views$dialogs$SetDisplayNameDialog && (module.exports.components['views.dialogs.SetDisplayNameDialog'] = views$dialogs$SetDisplayNameDialog); -import views$dialogs$TextInputDialog from './components/views/dialogs/TextInputDialog'; -views$dialogs$TextInputDialog && (module.exports.components['views.dialogs.TextInputDialog'] = views$dialogs$TextInputDialog); -import views$dialogs$UnknownDeviceDialog from './components/views/dialogs/UnknownDeviceDialog'; -views$dialogs$UnknownDeviceDialog && (module.exports.components['views.dialogs.UnknownDeviceDialog'] = views$dialogs$UnknownDeviceDialog); -import views$elements$AccessibleButton from './components/views/elements/AccessibleButton'; -views$elements$AccessibleButton && (module.exports.components['views.elements.AccessibleButton'] = views$elements$AccessibleButton); -import views$elements$ActionButton from './components/views/elements/ActionButton'; -views$elements$ActionButton && (module.exports.components['views.elements.ActionButton'] = views$elements$ActionButton); -import views$elements$AddressSelector from './components/views/elements/AddressSelector'; -views$elements$AddressSelector && (module.exports.components['views.elements.AddressSelector'] = views$elements$AddressSelector); -import views$elements$AddressTile from './components/views/elements/AddressTile'; -views$elements$AddressTile && (module.exports.components['views.elements.AddressTile'] = views$elements$AddressTile); -import views$elements$CreateRoomButton from './components/views/elements/CreateRoomButton'; -views$elements$CreateRoomButton && (module.exports.components['views.elements.CreateRoomButton'] = views$elements$CreateRoomButton); -import views$elements$DeviceVerifyButtons from './components/views/elements/DeviceVerifyButtons'; -views$elements$DeviceVerifyButtons && (module.exports.components['views.elements.DeviceVerifyButtons'] = views$elements$DeviceVerifyButtons); -import views$elements$DirectorySearchBox from './components/views/elements/DirectorySearchBox'; -views$elements$DirectorySearchBox && (module.exports.components['views.elements.DirectorySearchBox'] = views$elements$DirectorySearchBox); -import views$elements$Dropdown from './components/views/elements/Dropdown'; -views$elements$Dropdown && (module.exports.components['views.elements.Dropdown'] = views$elements$Dropdown); -import views$elements$EditableText from './components/views/elements/EditableText'; -views$elements$EditableText && (module.exports.components['views.elements.EditableText'] = views$elements$EditableText); -import views$elements$EditableTextContainer from './components/views/elements/EditableTextContainer'; -views$elements$EditableTextContainer && (module.exports.components['views.elements.EditableTextContainer'] = views$elements$EditableTextContainer); -import views$elements$EmojiText from './components/views/elements/EmojiText'; -views$elements$EmojiText && (module.exports.components['views.elements.EmojiText'] = views$elements$EmojiText); -import views$elements$HomeButton from './components/views/elements/HomeButton'; -views$elements$HomeButton && (module.exports.components['views.elements.HomeButton'] = views$elements$HomeButton); -import views$elements$MemberEventListSummary from './components/views/elements/MemberEventListSummary'; -views$elements$MemberEventListSummary && (module.exports.components['views.elements.MemberEventListSummary'] = views$elements$MemberEventListSummary); -import views$elements$PowerSelector from './components/views/elements/PowerSelector'; -views$elements$PowerSelector && (module.exports.components['views.elements.PowerSelector'] = views$elements$PowerSelector); -import views$elements$ProgressBar from './components/views/elements/ProgressBar'; -views$elements$ProgressBar && (module.exports.components['views.elements.ProgressBar'] = views$elements$ProgressBar); -import views$elements$RoomDirectoryButton from './components/views/elements/RoomDirectoryButton'; -views$elements$RoomDirectoryButton && (module.exports.components['views.elements.RoomDirectoryButton'] = views$elements$RoomDirectoryButton); -import views$elements$SettingsButton from './components/views/elements/SettingsButton'; -views$elements$SettingsButton && (module.exports.components['views.elements.SettingsButton'] = views$elements$SettingsButton); -import views$elements$StartChatButton from './components/views/elements/StartChatButton'; -views$elements$StartChatButton && (module.exports.components['views.elements.StartChatButton'] = views$elements$StartChatButton); -import views$elements$TintableSvg from './components/views/elements/TintableSvg'; -views$elements$TintableSvg && (module.exports.components['views.elements.TintableSvg'] = views$elements$TintableSvg); -import views$elements$TruncatedList from './components/views/elements/TruncatedList'; -views$elements$TruncatedList && (module.exports.components['views.elements.TruncatedList'] = views$elements$TruncatedList); -import views$elements$UserSelector from './components/views/elements/UserSelector'; -views$elements$UserSelector && (module.exports.components['views.elements.UserSelector'] = views$elements$UserSelector); -import views$login$CaptchaForm from './components/views/login/CaptchaForm'; -views$login$CaptchaForm && (module.exports.components['views.login.CaptchaForm'] = views$login$CaptchaForm); -import views$login$CasLogin from './components/views/login/CasLogin'; -views$login$CasLogin && (module.exports.components['views.login.CasLogin'] = views$login$CasLogin); -import views$login$CountryDropdown from './components/views/login/CountryDropdown'; -views$login$CountryDropdown && (module.exports.components['views.login.CountryDropdown'] = views$login$CountryDropdown); -import views$login$CustomServerDialog from './components/views/login/CustomServerDialog'; -views$login$CustomServerDialog && (module.exports.components['views.login.CustomServerDialog'] = views$login$CustomServerDialog); -import views$login$InteractiveAuthEntryComponents from './components/views/login/InteractiveAuthEntryComponents'; -views$login$InteractiveAuthEntryComponents && (module.exports.components['views.login.InteractiveAuthEntryComponents'] = views$login$InteractiveAuthEntryComponents); -import views$login$LoginFooter from './components/views/login/LoginFooter'; -views$login$LoginFooter && (module.exports.components['views.login.LoginFooter'] = views$login$LoginFooter); -import views$login$LoginHeader from './components/views/login/LoginHeader'; -views$login$LoginHeader && (module.exports.components['views.login.LoginHeader'] = views$login$LoginHeader); -import views$login$PasswordLogin from './components/views/login/PasswordLogin'; -views$login$PasswordLogin && (module.exports.components['views.login.PasswordLogin'] = views$login$PasswordLogin); -import views$login$RegistrationForm from './components/views/login/RegistrationForm'; -views$login$RegistrationForm && (module.exports.components['views.login.RegistrationForm'] = views$login$RegistrationForm); -import views$login$ServerConfig from './components/views/login/ServerConfig'; -views$login$ServerConfig && (module.exports.components['views.login.ServerConfig'] = views$login$ServerConfig); -import views$messages$MAudioBody from './components/views/messages/MAudioBody'; -views$messages$MAudioBody && (module.exports.components['views.messages.MAudioBody'] = views$messages$MAudioBody); -import views$messages$MFileBody from './components/views/messages/MFileBody'; -views$messages$MFileBody && (module.exports.components['views.messages.MFileBody'] = views$messages$MFileBody); -import views$messages$MImageBody from './components/views/messages/MImageBody'; -views$messages$MImageBody && (module.exports.components['views.messages.MImageBody'] = views$messages$MImageBody); -import views$messages$MVideoBody from './components/views/messages/MVideoBody'; -views$messages$MVideoBody && (module.exports.components['views.messages.MVideoBody'] = views$messages$MVideoBody); -import views$messages$MessageEvent from './components/views/messages/MessageEvent'; -views$messages$MessageEvent && (module.exports.components['views.messages.MessageEvent'] = views$messages$MessageEvent); -import views$messages$SenderProfile from './components/views/messages/SenderProfile'; -views$messages$SenderProfile && (module.exports.components['views.messages.SenderProfile'] = views$messages$SenderProfile); -import views$messages$TextualBody from './components/views/messages/TextualBody'; -views$messages$TextualBody && (module.exports.components['views.messages.TextualBody'] = views$messages$TextualBody); -import views$messages$TextualEvent from './components/views/messages/TextualEvent'; -views$messages$TextualEvent && (module.exports.components['views.messages.TextualEvent'] = views$messages$TextualEvent); -import views$messages$UnknownBody from './components/views/messages/UnknownBody'; -views$messages$UnknownBody && (module.exports.components['views.messages.UnknownBody'] = views$messages$UnknownBody); -import views$room_settings$AliasSettings from './components/views/room_settings/AliasSettings'; -views$room_settings$AliasSettings && (module.exports.components['views.room_settings.AliasSettings'] = views$room_settings$AliasSettings); -import views$room_settings$ColorSettings from './components/views/room_settings/ColorSettings'; -views$room_settings$ColorSettings && (module.exports.components['views.room_settings.ColorSettings'] = views$room_settings$ColorSettings); -import views$room_settings$UrlPreviewSettings from './components/views/room_settings/UrlPreviewSettings'; -views$room_settings$UrlPreviewSettings && (module.exports.components['views.room_settings.UrlPreviewSettings'] = views$room_settings$UrlPreviewSettings); -import views$rooms$Autocomplete from './components/views/rooms/Autocomplete'; -views$rooms$Autocomplete && (module.exports.components['views.rooms.Autocomplete'] = views$rooms$Autocomplete); -import views$rooms$AuxPanel from './components/views/rooms/AuxPanel'; -views$rooms$AuxPanel && (module.exports.components['views.rooms.AuxPanel'] = views$rooms$AuxPanel); -import views$rooms$EntityTile from './components/views/rooms/EntityTile'; -views$rooms$EntityTile && (module.exports.components['views.rooms.EntityTile'] = views$rooms$EntityTile); -import views$rooms$EventTile from './components/views/rooms/EventTile'; -views$rooms$EventTile && (module.exports.components['views.rooms.EventTile'] = views$rooms$EventTile); -import views$rooms$LinkPreviewWidget from './components/views/rooms/LinkPreviewWidget'; -views$rooms$LinkPreviewWidget && (module.exports.components['views.rooms.LinkPreviewWidget'] = views$rooms$LinkPreviewWidget); -import views$rooms$MemberDeviceInfo from './components/views/rooms/MemberDeviceInfo'; -views$rooms$MemberDeviceInfo && (module.exports.components['views.rooms.MemberDeviceInfo'] = views$rooms$MemberDeviceInfo); -import views$rooms$MemberInfo from './components/views/rooms/MemberInfo'; -views$rooms$MemberInfo && (module.exports.components['views.rooms.MemberInfo'] = views$rooms$MemberInfo); -import views$rooms$MemberList from './components/views/rooms/MemberList'; -views$rooms$MemberList && (module.exports.components['views.rooms.MemberList'] = views$rooms$MemberList); -import views$rooms$MemberTile from './components/views/rooms/MemberTile'; -views$rooms$MemberTile && (module.exports.components['views.rooms.MemberTile'] = views$rooms$MemberTile); -import views$rooms$MessageComposer from './components/views/rooms/MessageComposer'; -views$rooms$MessageComposer && (module.exports.components['views.rooms.MessageComposer'] = views$rooms$MessageComposer); -import views$rooms$MessageComposerInput from './components/views/rooms/MessageComposerInput'; -views$rooms$MessageComposerInput && (module.exports.components['views.rooms.MessageComposerInput'] = views$rooms$MessageComposerInput); -import views$rooms$MessageComposerInputOld from './components/views/rooms/MessageComposerInputOld'; -views$rooms$MessageComposerInputOld && (module.exports.components['views.rooms.MessageComposerInputOld'] = views$rooms$MessageComposerInputOld); -import views$rooms$PresenceLabel from './components/views/rooms/PresenceLabel'; -views$rooms$PresenceLabel && (module.exports.components['views.rooms.PresenceLabel'] = views$rooms$PresenceLabel); -import views$rooms$ReadReceiptMarker from './components/views/rooms/ReadReceiptMarker'; -views$rooms$ReadReceiptMarker && (module.exports.components['views.rooms.ReadReceiptMarker'] = views$rooms$ReadReceiptMarker); -import views$rooms$RoomHeader from './components/views/rooms/RoomHeader'; -views$rooms$RoomHeader && (module.exports.components['views.rooms.RoomHeader'] = views$rooms$RoomHeader); -import views$rooms$RoomList from './components/views/rooms/RoomList'; -views$rooms$RoomList && (module.exports.components['views.rooms.RoomList'] = views$rooms$RoomList); -import views$rooms$RoomNameEditor from './components/views/rooms/RoomNameEditor'; -views$rooms$RoomNameEditor && (module.exports.components['views.rooms.RoomNameEditor'] = views$rooms$RoomNameEditor); -import views$rooms$RoomPreviewBar from './components/views/rooms/RoomPreviewBar'; -views$rooms$RoomPreviewBar && (module.exports.components['views.rooms.RoomPreviewBar'] = views$rooms$RoomPreviewBar); -import views$rooms$RoomSettings from './components/views/rooms/RoomSettings'; -views$rooms$RoomSettings && (module.exports.components['views.rooms.RoomSettings'] = views$rooms$RoomSettings); -import views$rooms$RoomTile from './components/views/rooms/RoomTile'; -views$rooms$RoomTile && (module.exports.components['views.rooms.RoomTile'] = views$rooms$RoomTile); -import views$rooms$RoomTopicEditor from './components/views/rooms/RoomTopicEditor'; -views$rooms$RoomTopicEditor && (module.exports.components['views.rooms.RoomTopicEditor'] = views$rooms$RoomTopicEditor); -import views$rooms$SearchResultTile from './components/views/rooms/SearchResultTile'; -views$rooms$SearchResultTile && (module.exports.components['views.rooms.SearchResultTile'] = views$rooms$SearchResultTile); -import views$rooms$SearchableEntityList from './components/views/rooms/SearchableEntityList'; -views$rooms$SearchableEntityList && (module.exports.components['views.rooms.SearchableEntityList'] = views$rooms$SearchableEntityList); -import views$rooms$SimpleRoomHeader from './components/views/rooms/SimpleRoomHeader'; -views$rooms$SimpleRoomHeader && (module.exports.components['views.rooms.SimpleRoomHeader'] = views$rooms$SimpleRoomHeader); -import views$rooms$TabCompleteBar from './components/views/rooms/TabCompleteBar'; -views$rooms$TabCompleteBar && (module.exports.components['views.rooms.TabCompleteBar'] = views$rooms$TabCompleteBar); -import views$rooms$TopUnreadMessagesBar from './components/views/rooms/TopUnreadMessagesBar'; -views$rooms$TopUnreadMessagesBar && (module.exports.components['views.rooms.TopUnreadMessagesBar'] = views$rooms$TopUnreadMessagesBar); -import views$rooms$UserTile from './components/views/rooms/UserTile'; -views$rooms$UserTile && (module.exports.components['views.rooms.UserTile'] = views$rooms$UserTile); -import views$settings$AddPhoneNumber from './components/views/settings/AddPhoneNumber'; -views$settings$AddPhoneNumber && (module.exports.components['views.settings.AddPhoneNumber'] = views$settings$AddPhoneNumber); -import views$settings$ChangeAvatar from './components/views/settings/ChangeAvatar'; -views$settings$ChangeAvatar && (module.exports.components['views.settings.ChangeAvatar'] = views$settings$ChangeAvatar); -import views$settings$ChangeDisplayName from './components/views/settings/ChangeDisplayName'; -views$settings$ChangeDisplayName && (module.exports.components['views.settings.ChangeDisplayName'] = views$settings$ChangeDisplayName); -import views$settings$ChangePassword from './components/views/settings/ChangePassword'; -views$settings$ChangePassword && (module.exports.components['views.settings.ChangePassword'] = views$settings$ChangePassword); -import views$settings$DevicesPanel from './components/views/settings/DevicesPanel'; -views$settings$DevicesPanel && (module.exports.components['views.settings.DevicesPanel'] = views$settings$DevicesPanel); -import views$settings$DevicesPanelEntry from './components/views/settings/DevicesPanelEntry'; -views$settings$DevicesPanelEntry && (module.exports.components['views.settings.DevicesPanelEntry'] = views$settings$DevicesPanelEntry); -import views$settings$EnableNotificationsButton from './components/views/settings/EnableNotificationsButton'; -views$settings$EnableNotificationsButton && (module.exports.components['views.settings.EnableNotificationsButton'] = views$settings$EnableNotificationsButton); -import views$voip$CallView from './components/views/voip/CallView'; -views$voip$CallView && (module.exports.components['views.voip.CallView'] = views$voip$CallView); -import views$voip$IncomingCallBox from './components/views/voip/IncomingCallBox'; -views$voip$IncomingCallBox && (module.exports.components['views.voip.IncomingCallBox'] = views$voip$IncomingCallBox); -import views$voip$VideoFeed from './components/views/voip/VideoFeed'; -views$voip$VideoFeed && (module.exports.components['views.voip.VideoFeed'] = views$voip$VideoFeed); -import views$voip$VideoView from './components/views/voip/VideoView'; -views$voip$VideoView && (module.exports.components['views.voip.VideoView'] = views$voip$VideoView); From ca7989a1fdd0d9b69f29bcad06ebf7580d68bd65 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 8 May 2017 14:55:55 +0100 Subject: [PATCH 037/127] .gitignore auto-generated component-index --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 5139d614ad..dcfe1c355d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ npm-debug.log # test reports created by karma /karma-reports + +# ignore auto-generated component index +/src/component-index.js From 1addc7e2c573394696a0a1e1cda675cb3a2c0b62 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 8 May 2017 14:56:38 +0100 Subject: [PATCH 038/127] Update header copyright --- header | 1 + 1 file changed, 1 insertion(+) diff --git a/header b/header index 060709b82e..beee1ebe89 100644 --- a/header +++ b/header @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 2eaaa974516ce224602b0295f937549de1bb1b8e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 8 May 2017 14:57:04 +0100 Subject: [PATCH 039/127] Give `reskindex.js` a watch mode (-w) `scripts/reskindex.js -w` will run reskindex in watch mode whereby FS events will cause a reskindex to occur. This depends on `chokidar` --- package.json | 1 + scripts/reskindex.js | 92 +++++++++++++++++++++++++------------------- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index 2001f0d4ad..b019c63da5 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "blueimp-canvas-to-blob": "^3.5.0", "browser-encrypt-attachment": "^0.3.0", "browser-request": "^0.3.3", + "chokidar": "^1.6.1", "classnames": "^2.1.2", "commonmark": "^0.27.0", "draft-js": "^0.8.1", diff --git a/scripts/reskindex.js b/scripts/reskindex.js index f9cbc2a711..e82104f35c 100755 --- a/scripts/reskindex.js +++ b/scripts/reskindex.js @@ -1,53 +1,67 @@ #!/usr/bin/env node - var fs = require('fs'); var path = require('path'); var glob = require('glob'); - var args = require('optimist').argv; - -var header = args.h || args.header; - -var componentsDir = path.join('src', 'components'); +var chokidar = require('chokidar'); var componentIndex = path.join('src', 'component-index.js'); +var componentsDir = path.join('src', 'components'); -var packageJson = JSON.parse(fs.readFileSync('./package.json')); +function reskindex() { + var header = args.h || args.header; + var packageJson = JSON.parse(fs.readFileSync('./package.json')); -var strm = fs.createWriteStream(componentIndex); + var strm = fs.createWriteStream(componentIndex); -if (header) { - strm.write(fs.readFileSync(header)); - strm.write('\n'); + if (header) { + strm.write(fs.readFileSync(header)); + strm.write('\n'); + } + + strm.write("/*\n"); + strm.write(" * THIS FILE IS AUTO-GENERATED\n"); + strm.write(" * You can edit it you like, but your changes will be overwritten,\n"); + strm.write(" * so you'd just be trying to swim upstream like a salmon.\n"); + strm.write(" * You are not a salmon.\n"); + strm.write(" */\n\n"); + + if (packageJson['matrix-react-parent']) { + strm.write( + "module.exports.components = require('"+ + packageJson['matrix-react-parent']+ + "/lib/component-index').components;\n\n" + ); + } else { + strm.write("module.exports.components = {};\n"); + } + + var files = glob.sync('**/*.js', {cwd: componentsDir}).sort(); + for (var i = 0; i < files.length; ++i) { + var file = files[i].replace('.js', ''); + + var moduleName = (file.replace(/\//g, '.')); + var importName = moduleName.replace(/\./g, "$"); + + strm.write("import " + importName + " from './components/" + file + "';\n"); + strm.write(importName + " && (module.exports.components['"+moduleName+"'] = " + importName + ");"); + strm.write('\n'); + strm.uncork(); + } + + strm.end(); + console.log('Reskindex: completed'); } -strm.write("/*\n"); -strm.write(" * THIS FILE IS AUTO-GENERATED\n"); -strm.write(" * You can edit it you like, but your changes will be overwritten,\n"); -strm.write(" * so you'd just be trying to swim upstream like a salmon.\n"); -strm.write(" * You are not a salmon.\n"); -strm.write(" *\n"); -strm.write(" * To update it, run:\n"); -strm.write(" * ./reskindex.js -h header\n"); -strm.write(" */\n\n"); - -if (packageJson['matrix-react-parent']) { - strm.write("module.exports.components = require('"+packageJson['matrix-react-parent']+"/lib/component-index').components;\n\n"); -} else { - strm.write("module.exports.components = {};\n"); +// -w indicates watch mode where any FS events will trigger reskindex +if (!args.w) { + reskindex(); + return; } -var files = glob.sync('**/*.js', {cwd: componentsDir}).sort(); -for (var i = 0; i < files.length; ++i) { - var file = files[i].replace('.js', ''); - - var moduleName = (file.replace(/\//g, '.')); - var importName = moduleName.replace(/\./g, "$"); - - strm.write("import " + importName + " from './components/" + file + "';\n"); - strm.write(importName + " && (module.exports.components['"+moduleName+"'] = " + importName + ");"); - strm.write('\n'); - strm.uncork(); -} - -strm.end(); +var watchDebouncer = null; +chokidar.watch('./src').on('all', (event, path) => { + if (path === componentIndex) return; + if (watchDebouncer) clearTimeout(watchDebouncer); + watchDebouncer = setTimeout(reskindex, 1000); +}); From 7d1940620db557203887b710292c23cfff2a910e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 8 May 2017 15:07:58 +0100 Subject: [PATCH 040/127] Add (watching) reskindex to `npm start` also add reskindex in non-watching mode to `npm run build` --- package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b019c63da5..28f77f9460 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,10 @@ }, "scripts": { "reskindex": "scripts/reskindex.js -h header", - "build": "babel src -d lib --source-maps", - "start": "babel src -w -d lib --source-maps", + "reskindex:watch": "scripts/reskindex.js -h header -w", + "build": "npm run reskindex && babel src -d lib --source-maps", + "build:watch": "babel src -w -d lib --source-maps", + "start": "parallelshell \"npm run build:watch\" \"npm run reskindex:watch\"", "lint": "eslint src/", "lintall": "eslint src/ test/", "clean": "rimraf lib", @@ -106,6 +108,7 @@ "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^1.7.0", "mocha": "^2.4.5", + "parallelshell": "^1.2.0", "phantomjs-prebuilt": "^2.1.7", "react-addons-test-utils": "^15.4.0", "require-json": "0.0.1", From 534f9277d436e66725a7f8875d88d78f7cf59f02 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 8 May 2017 15:37:40 +0100 Subject: [PATCH 041/127] Fix this/self fail in LeftPanel --- src/components/views/dialogs/ChatInviteDialog.js | 5 +++++ src/components/views/rooms/RoomList.js | 14 +++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/components/views/dialogs/ChatInviteDialog.js b/src/components/views/dialogs/ChatInviteDialog.js index 7ba503099a..b349b94e5d 100644 --- a/src/components/views/dialogs/ChatInviteDialog.js +++ b/src/components/views/dialogs/ChatInviteDialog.js @@ -191,6 +191,7 @@ module.exports = React.createClass({ this.queryChangedDebouncer = setTimeout(() => { // Only do search if there is something to search if (query.length > 0 && query != '@') { + performance.mark('start'); // Weighted keys prefer to match userIds when first char is @ this._fuse.options.keys = [{ name: 'displayName', @@ -199,6 +200,7 @@ module.exports = React.createClass({ name: 'userId', weight: query[0] === '@' ? 0.9 : 0.1, }]; + performance.mark('middle'); queryList = this._fuse.search(query).map((user) => { // Return objects, structure of which is defined // by InviteAddressType @@ -210,6 +212,9 @@ module.exports = React.createClass({ isKnown: true, } }); + performance.mark('end'); + performance.measure('setopts', 'start', 'middle'); + performance.measure('search', 'middle', 'end'); // If the query is a valid address, add an entry for that // This is important, otherwise there's no way to invite diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 8d396b5536..a595a91ba9 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -652,7 +652,7 @@ module.exports = React.createClass({ Date: Mon, 8 May 2017 16:03:52 +0100 Subject: [PATCH 042/127] Fix Create Room button Opened the DM dialog rather than the new room dialog --- src/components/views/elements/CreateRoomButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js index e7e526d36b..73c984a860 100644 --- a/src/components/views/elements/CreateRoomButton.js +++ b/src/components/views/elements/CreateRoomButton.js @@ -21,7 +21,7 @@ import PropTypes from 'prop-types'; const CreateRoomButton = function(props) { const ActionButton = sdk.getComponent('elements.ActionButton'); return ( - Date: Mon, 8 May 2017 16:24:13 +0100 Subject: [PATCH 043/127] Move chokidar to devDeps --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28f77f9460..4b0e8de5cd 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "blueimp-canvas-to-blob": "^3.5.0", "browser-encrypt-attachment": "^0.3.0", "browser-request": "^0.3.3", - "chokidar": "^1.6.1", "classnames": "^2.1.2", "commonmark": "^0.27.0", "draft-js": "^0.8.1", @@ -92,6 +91,7 @@ "babel-preset-es2016": "^6.11.3", "babel-preset-es2017": "^6.14.0", "babel-preset-react": "^6.11.1", + "chokidar": "^1.6.1", "eslint": "^3.13.1", "eslint-config-google": "^0.7.1", "eslint-plugin-babel": "^4.0.1", From 9af9603373ea9a3459170fc02413ae74200a04da Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 8 May 2017 16:29:53 +0100 Subject: [PATCH 044/127] Only watch indexed files --- scripts/reskindex.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/reskindex.js b/scripts/reskindex.js index e82104f35c..1db22f9e10 100755 --- a/scripts/reskindex.js +++ b/scripts/reskindex.js @@ -7,6 +7,7 @@ var chokidar = require('chokidar'); var componentIndex = path.join('src', 'component-index.js'); var componentsDir = path.join('src', 'components'); +var componentGlob = '**/*.js'; function reskindex() { var header = args.h || args.header; @@ -36,7 +37,7 @@ function reskindex() { strm.write("module.exports.components = {};\n"); } - var files = glob.sync('**/*.js', {cwd: componentsDir}).sort(); + var files = glob.sync(componentGlob, {cwd: componentsDir}).sort(); for (var i = 0; i < files.length; ++i) { var file = files[i].replace('.js', ''); @@ -60,7 +61,7 @@ if (!args.w) { } var watchDebouncer = null; -chokidar.watch('./src').on('all', (event, path) => { +chokidar.watch(path.join(componentsDir, componentGlob)).on('all', (event, path) => { if (path === componentIndex) return; if (watchDebouncer) clearTimeout(watchDebouncer); watchDebouncer = setTimeout(reskindex, 1000); From 805354bd2c3d2e6233c55833f561d489d8b40445 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 8 May 2017 16:39:11 +0100 Subject: [PATCH 045/127] Revert unintentional change --- src/components/views/dialogs/ChatInviteDialog.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/components/views/dialogs/ChatInviteDialog.js b/src/components/views/dialogs/ChatInviteDialog.js index b349b94e5d..7ba503099a 100644 --- a/src/components/views/dialogs/ChatInviteDialog.js +++ b/src/components/views/dialogs/ChatInviteDialog.js @@ -191,7 +191,6 @@ module.exports = React.createClass({ this.queryChangedDebouncer = setTimeout(() => { // Only do search if there is something to search if (query.length > 0 && query != '@') { - performance.mark('start'); // Weighted keys prefer to match userIds when first char is @ this._fuse.options.keys = [{ name: 'displayName', @@ -200,7 +199,6 @@ module.exports = React.createClass({ name: 'userId', weight: query[0] === '@' ? 0.9 : 0.1, }]; - performance.mark('middle'); queryList = this._fuse.search(query).map((user) => { // Return objects, structure of which is defined // by InviteAddressType @@ -212,9 +210,6 @@ module.exports = React.createClass({ isKnown: true, } }); - performance.mark('end'); - performance.measure('setopts', 'start', 'middle'); - performance.measure('search', 'middle', 'end'); // If the query is a valid address, add an entry for that // This is important, otherwise there's no way to invite From 85ed39b9d87214a069af6c6ab2b642b6ff8b3386 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 8 May 2017 16:49:40 +0100 Subject: [PATCH 046/127] Put room name in 'leave room' confirmation dialog https://github.com/vector-im/riot-web/issues/3850 --- src/components/structures/MatrixChat.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 9b8aa3426a..8865d77d51 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -392,9 +392,10 @@ module.exports = React.createClass({ this.notifyNewScreen('forgot_password'); break; case 'leave_room': + const roomToLeave = MatrixClientPeg.get().getRoom(payload.room_id); Modal.createDialog(QuestionDialog, { title: "Leave room", - description: "Are you sure you want to leave the room?", + description: Are you sure you want to leave the room {roomToLeave.name}?, onFinished: (should_leave) => { if (should_leave) { const d = MatrixClientPeg.get().leave(payload.room_id); From 488fa3745b567cdff57041b1f81352c484aef0ec Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 9 May 2017 10:03:40 +0100 Subject: [PATCH 047/127] Fix RM not updating if RR event unpaginated If the RR event has been unpaginated, the logic in `sendReadReceipt` will now fallback on the event ID of the RM which in theory is always =< RR event ID stream-wise. --- src/components/structures/ScrollPanel.js | 2 +- src/components/structures/TimelinePanel.js | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index a652bcc827..22eb2240ed 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -575,7 +575,7 @@ module.exports = React.createClass({ var boundingRect = node.getBoundingClientRect(); var scrollDelta = boundingRect.bottom + pixelOffset - wrapperRect.bottom; - debuglog("ScrollPanel: scrolling to token '" + scrollToken + "'+" + + console.log("ScrollPanel: scrolling to token '" + scrollToken + "'+" + pixelOffset + " (delta: "+scrollDelta+")"); if(scrollDelta != 0) { diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 7c89694a29..d85282b5dc 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -510,8 +510,10 @@ var TimelinePanel = React.createClass({ var currentReadUpToEventId = this._getCurrentReadReceipt(true); var currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId); + currentReadUpToEventIndex = currentReadUpToEventIndex || + this._indexForEventId(this.state.readMarkerEventId); // We want to avoid sending out read receipts when we are looking at - // events in the past which are before the latest RR. + // events in the past which are before the latest RR/RM. // // For now, let's apply a heuristic: if (a) the event corresponding to // the latest RR (either from the server, or sent by ourselves) doesn't @@ -523,6 +525,7 @@ var TimelinePanel = React.createClass({ // RRs) - but that is a bit of a niche case. It will sort itself out when // the user eventually hits the live timeline. // + console.log(currentReadUpToEventId, currentReadUpToEventIndex, this._timelineWindow.canPaginate(EventTimeline.FORWARDS)); if (currentReadUpToEventId && currentReadUpToEventIndex === null && this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) { return; @@ -544,6 +547,11 @@ var TimelinePanel = React.createClass({ this.last_rr_sent_event_id = lastReadEvent.getId(); this.last_rm_sent_event_id = this.state.readMarkerEventId; + console.log('TimelinePanel: Sending Read Markers for ', + this.props.timelineSet.room.roomId, + 'rm', this.state.readMarkerEventId, + 'rr', lastReadEvent.getId(), + ); MatrixClientPeg.get().setRoomReadMarkers( this.props.timelineSet.room.roomId, this.state.readMarkerEventId, From ac25fd6d87214e962897667d7abdd8b766cef2b9 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 9 May 2017 10:16:37 +0100 Subject: [PATCH 048/127] Remove log --- src/components/structures/TimelinePanel.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index d85282b5dc..ba233780ec 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -525,7 +525,6 @@ var TimelinePanel = React.createClass({ // RRs) - but that is a bit of a niche case. It will sort itself out when // the user eventually hits the live timeline. // - console.log(currentReadUpToEventId, currentReadUpToEventIndex, this._timelineWindow.canPaginate(EventTimeline.FORWARDS)); if (currentReadUpToEventId && currentReadUpToEventIndex === null && this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) { return; From f02e659fb7502ebb524651494e9c9bd1098fcc9b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Tue, 9 May 2017 11:27:06 +0100 Subject: [PATCH 049/127] Consume key{up,down,pressed} events so they don't trigger other things bubbling up until Modal is closed --- src/components/views/dialogs/BaseDialog.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index ac36dfd056..02460148b3 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -57,28 +57,25 @@ export default React.createClass({ } }, - // Don't let esc keydown events get any further, so they only trigger this and nothing more - _onKeyDown: function(e) { - if (e.keyCode === KeyCode.ESCAPE) { - e.stopPropagation(); - e.preventDefault(); - } + // Don't let key{down,press} events escape the modal. Consume them all. + _eatKeyEvent: function(e) { + e.stopPropagation(); }, // Must be when the key is released (and not pressed) otherwise componentWillUnmount // will focus another element which will receive future key events _onKeyUp: function(e) { if (e.keyCode === KeyCode.ESCAPE) { - e.stopPropagation(); e.preventDefault(); this.props.onFinished(); } else if (e.keyCode === KeyCode.ENTER) { if (this.props.onEnterPressed) { - e.stopPropagation(); e.preventDefault(); this.props.onEnterPressed(e); } } + // Consume all keyup events while Modal is open + e.stopPropagation(); }, _onCancelClick: function(e) { @@ -89,7 +86,11 @@ export default React.createClass({ const TintableSvg = sdk.getComponent("elements.TintableSvg"); return ( -
+
From fdf48def00d336dd55ee189d21ea854cc72fd1d8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Tue, 9 May 2017 17:13:27 +0100 Subject: [PATCH 050/127] make reskindex windows friendly makes #871 windows friendly --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4b0e8de5cd..21add8ccb7 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,8 @@ "reskindex": "scripts/reskindex.js" }, "scripts": { - "reskindex": "scripts/reskindex.js -h header", - "reskindex:watch": "scripts/reskindex.js -h header -w", + "reskindex": "node scripts/reskindex.js -h header", + "reskindex:watch": "node scripts/reskindex.js -h header -w", "build": "npm run reskindex && babel src -d lib --source-maps", "build:watch": "babel src -w -d lib --source-maps", "start": "parallelshell \"npm run build:watch\" \"npm run reskindex:watch\"", From ca79d9bb6eed092b7b6ca7c7f89ae345624f4047 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 9 May 2017 17:36:19 +0100 Subject: [PATCH 051/127] Separate predicates for RM/RR Instead of modifying the condition for updating the RR, separate the RM and RR conditions and use an OR to decide when to set both. Make some logs only log when DEBUG. --- src/components/structures/ScrollPanel.js | 2 +- src/components/structures/TimelinePanel.js | 27 ++++++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 22eb2240ed..a652bcc827 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -575,7 +575,7 @@ module.exports = React.createClass({ var boundingRect = node.getBoundingClientRect(); var scrollDelta = boundingRect.bottom + pixelOffset - wrapperRect.bottom; - console.log("ScrollPanel: scrolling to token '" + scrollToken + "'+" + + debuglog("ScrollPanel: scrolling to token '" + scrollToken + "'+" + pixelOffset + " (delta: "+scrollDelta+")"); if(scrollDelta != 0) { diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index ba233780ec..973c619904 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -504,16 +504,15 @@ var TimelinePanel = React.createClass({ // very possible have logged out within that timeframe, so check // we still have a client. const cli = MatrixClientPeg.get(); - // if no client or client is guest don't send RR + // if no client or client is guest don't send RR or RM if (!cli || cli.isGuest()) return; + let shouldSendRR = true; + var currentReadUpToEventId = this._getCurrentReadReceipt(true); var currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId); - - currentReadUpToEventIndex = currentReadUpToEventIndex || - this._indexForEventId(this.state.readMarkerEventId); // We want to avoid sending out read receipts when we are looking at - // events in the past which are before the latest RR/RM. + // events in the past which are before the latest RR. // // For now, let's apply a heuristic: if (a) the event corresponding to // the latest RR (either from the server, or sent by ourselves) doesn't @@ -527,26 +526,30 @@ var TimelinePanel = React.createClass({ // if (currentReadUpToEventId && currentReadUpToEventIndex === null && this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) { - return; + shouldSendRR = false; } var lastReadEventIndex = this._getLastDisplayedEventIndex({ ignoreOwn: true }); - if (lastReadEventIndex === null) return; + if (lastReadEventIndex === null) { + shouldSendRR = false; + } var lastReadEvent = this.state.events[lastReadEventIndex]; + shouldSendRR = shouldSendRR && + (lastReadEventIndex > currentReadUpToEventIndex && + this.last_rr_sent_event_id != lastReadEvent.getId()); + + const shouldSendRM = this.last_rm_sent_event_id != this.state.readMarkerEventId; // we also remember the last read receipt we sent to avoid spamming the // same one at the server repeatedly - if ((lastReadEventIndex > currentReadUpToEventIndex && - this.last_rr_sent_event_id != lastReadEvent.getId()) || - this.last_rm_sent_event_id != this.state.readMarkerEventId) { - + if (shouldSendRR || shouldSendRM) { this.last_rr_sent_event_id = lastReadEvent.getId(); this.last_rm_sent_event_id = this.state.readMarkerEventId; - console.log('TimelinePanel: Sending Read Markers for ', + debuglog('TimelinePanel: Sending Read Markers for ', this.props.timelineSet.room.roomId, 'rm', this.state.readMarkerEventId, 'rr', lastReadEvent.getId(), From 7f766d89c32feba745c3d3000c64e94be5431226 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 10 May 2017 14:42:06 +0100 Subject: [PATCH 052/127] Rename variables, more comments --- src/components/structures/TimelinePanel.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 973c619904..874c6b1ac0 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -507,7 +507,7 @@ var TimelinePanel = React.createClass({ // if no client or client is guest don't send RR or RM if (!cli || cli.isGuest()) return; - let shouldSendRR = true; + let shouldSendReadReceipt = true; var currentReadUpToEventId = this._getCurrentReadReceipt(true); var currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId); @@ -526,26 +526,30 @@ var TimelinePanel = React.createClass({ // if (currentReadUpToEventId && currentReadUpToEventIndex === null && this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) { - shouldSendRR = false; + shouldSendReadReceipt = false; } var lastReadEventIndex = this._getLastDisplayedEventIndex({ ignoreOwn: true }); if (lastReadEventIndex === null) { - shouldSendRR = false; + shouldSendReadReceipt = false; } var lastReadEvent = this.state.events[lastReadEventIndex]; - shouldSendRR = shouldSendRR && - (lastReadEventIndex > currentReadUpToEventIndex && - this.last_rr_sent_event_id != lastReadEvent.getId()); + shouldSendReadReceipt = shouldSendReadReceipt && + // Only send a RR if the last read Event is ahead in the timeline relative to + // the current RR event. + lastReadEventIndex > currentReadUpToEventIndex && + // Only send a RR if the last RR set != the one we would send + this.last_rr_sent_event_id != lastReadEvent.getId(); - const shouldSendRM = this.last_rm_sent_event_id != this.state.readMarkerEventId; + // Only send a RM if the last RM sent != the one we would send + const shouldSendReadMarker = this.last_rm_sent_event_id != this.state.readMarkerEventId; // we also remember the last read receipt we sent to avoid spamming the // same one at the server repeatedly - if (shouldSendRR || shouldSendRM) { + if (shouldSendReadReceipt || shouldSendReadMarker) { this.last_rr_sent_event_id = lastReadEvent.getId(); this.last_rm_sent_event_id = this.state.readMarkerEventId; From 30e183a7f1e0c5378d837f3ab45dfc8abbe6ade0 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 10 May 2017 14:48:01 +0100 Subject: [PATCH 053/127] Only send RR if we should --- src/components/structures/TimelinePanel.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 874c6b1ac0..26bf9dd400 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -550,23 +550,27 @@ var TimelinePanel = React.createClass({ // we also remember the last read receipt we sent to avoid spamming the // same one at the server repeatedly if (shouldSendReadReceipt || shouldSendReadMarker) { - this.last_rr_sent_event_id = lastReadEvent.getId(); + if (shouldSendReadReceipt) { + this.last_rr_sent_event_id = lastReadEvent.getId(); + } else { + lastReadEvent = null; + } this.last_rm_sent_event_id = this.state.readMarkerEventId; debuglog('TimelinePanel: Sending Read Markers for ', this.props.timelineSet.room.roomId, 'rm', this.state.readMarkerEventId, - 'rr', lastReadEvent.getId(), + lastReadEvent ? 'rr ' + lastReadEvent.getId() : '', ); MatrixClientPeg.get().setRoomReadMarkers( this.props.timelineSet.room.roomId, this.state.readMarkerEventId, - lastReadEvent + lastReadEvent, // Could be null, in which case no RR is sent ).catch((e) => { // /read_markers API is not implemented on this HS, fallback to just RR - if (e.errcode === 'M_UNRECOGNIZED') { + if (e.errcode === 'M_UNRECOGNIZED' && lastReadEvent) { return MatrixClientPeg.get().sendReadReceipt( - lastReadEvent + lastReadEvent, ).catch(() => { this.last_rr_sent_event_id = undefined; }); From fe8ea4ffe7dcc5844c52a3baf96563838cac8a90 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 10 May 2017 14:51:47 +0100 Subject: [PATCH 054/127] Rename vars, linting --- src/components/structures/TimelinePanel.js | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 26bf9dd400..8a6c80980e 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -177,8 +177,8 @@ var TimelinePanel = React.createClass({ componentWillMount: function() { debuglog("TimelinePanel: mounting"); - this.last_rr_sent_event_id = undefined; - this.last_rm_sent_event_id = undefined; + this.lastRRSentSentId = undefined; + this.lastRMSentEventId = undefined; this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on("Room.timeline", this.onRoomTimeline); @@ -509,8 +509,8 @@ var TimelinePanel = React.createClass({ let shouldSendReadReceipt = true; - var currentReadUpToEventId = this._getCurrentReadReceipt(true); - var currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId); + const currentReadUpToEventId = this._getCurrentReadReceipt(true); + const currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId); // We want to avoid sending out read receipts when we are looking at // events in the past which are before the latest RR. // @@ -529,33 +529,33 @@ var TimelinePanel = React.createClass({ shouldSendReadReceipt = false; } - var lastReadEventIndex = this._getLastDisplayedEventIndex({ - ignoreOwn: true + const lastReadEventIndex = this._getLastDisplayedEventIndex({ + ignoreOwn: true, }); if (lastReadEventIndex === null) { shouldSendReadReceipt = false; } - - var lastReadEvent = this.state.events[lastReadEventIndex]; + let lastReadEvent = this.state.events[lastReadEventIndex]; shouldSendReadReceipt = shouldSendReadReceipt && // Only send a RR if the last read Event is ahead in the timeline relative to // the current RR event. lastReadEventIndex > currentReadUpToEventIndex && // Only send a RR if the last RR set != the one we would send - this.last_rr_sent_event_id != lastReadEvent.getId(); + this.lastRRSentSentId != lastReadEvent.getId(); // Only send a RM if the last RM sent != the one we would send - const shouldSendReadMarker = this.last_rm_sent_event_id != this.state.readMarkerEventId; + const shouldSendReadMarker = + this.lastRMSentEventId != this.state.readMarkerEventId; // we also remember the last read receipt we sent to avoid spamming the // same one at the server repeatedly if (shouldSendReadReceipt || shouldSendReadMarker) { if (shouldSendReadReceipt) { - this.last_rr_sent_event_id = lastReadEvent.getId(); + this.lastRRSentSentId = lastReadEvent.getId(); } else { lastReadEvent = null; } - this.last_rm_sent_event_id = this.state.readMarkerEventId; + this.lastRMSentEventId = this.state.readMarkerEventId; debuglog('TimelinePanel: Sending Read Markers for ', this.props.timelineSet.room.roomId, @@ -572,12 +572,12 @@ var TimelinePanel = React.createClass({ return MatrixClientPeg.get().sendReadReceipt( lastReadEvent, ).catch(() => { - this.last_rr_sent_event_id = undefined; + this.lastRRSentSentId = undefined; }); } // it failed, so allow retries next time the user is active - this.last_rr_sent_event_id = undefined; - this.last_rm_sent_event_id = undefined; + this.lastRRSentSentId = undefined; + this.lastRMSentEventId = undefined; }); // do a quick-reset of our unreadNotificationCount to avoid having From 856ef58d4678e4b243f4df94bdc20bb3b6e70efb Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 10 May 2017 14:55:58 +0100 Subject: [PATCH 055/127] fix commen --- src/components/structures/TimelinePanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 8a6c80980e..08b94fbdbf 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -537,7 +537,7 @@ var TimelinePanel = React.createClass({ } let lastReadEvent = this.state.events[lastReadEventIndex]; shouldSendReadReceipt = shouldSendReadReceipt && - // Only send a RR if the last read Event is ahead in the timeline relative to + // Only send a RR if the last read event is ahead in the timeline relative to // the current RR event. lastReadEventIndex > currentReadUpToEventIndex && // Only send a RR if the last RR set != the one we would send From 50092a0f1f432ad8b7aed33120765b264e32e7cb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 10 May 2017 15:16:49 +0100 Subject: [PATCH 056/127] fixes vector-im/riot-web#3881 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/RoomSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index 2c29dd433c..798aacfa8e 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -926,7 +926,7 @@ module.exports = React.createClass({
- To redact messages, you must be a + To redact other users' messages, you must be a
From 3815ad6cd031a9cd14081a18ba6c6c0448fcbc6c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 11 May 2017 09:20:34 +0100 Subject: [PATCH 057/127] Sent -> Event --- src/components/structures/TimelinePanel.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 08b94fbdbf..5a5abc6257 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -177,7 +177,7 @@ var TimelinePanel = React.createClass({ componentWillMount: function() { debuglog("TimelinePanel: mounting"); - this.lastRRSentSentId = undefined; + this.lastRRSentEventId = undefined; this.lastRMSentEventId = undefined; this.dispatcherRef = dis.register(this.onAction); @@ -541,7 +541,7 @@ var TimelinePanel = React.createClass({ // the current RR event. lastReadEventIndex > currentReadUpToEventIndex && // Only send a RR if the last RR set != the one we would send - this.lastRRSentSentId != lastReadEvent.getId(); + this.lastRRSentEventId != lastReadEvent.getId(); // Only send a RM if the last RM sent != the one we would send const shouldSendReadMarker = @@ -551,7 +551,7 @@ var TimelinePanel = React.createClass({ // same one at the server repeatedly if (shouldSendReadReceipt || shouldSendReadMarker) { if (shouldSendReadReceipt) { - this.lastRRSentSentId = lastReadEvent.getId(); + this.lastRRSentEventId = lastReadEvent.getId(); } else { lastReadEvent = null; } @@ -572,11 +572,11 @@ var TimelinePanel = React.createClass({ return MatrixClientPeg.get().sendReadReceipt( lastReadEvent, ).catch(() => { - this.lastRRSentSentId = undefined; + this.lastRRSentEventId = undefined; }); } // it failed, so allow retries next time the user is active - this.lastRRSentSentId = undefined; + this.lastRRSentEventId = undefined; this.lastRMSentEventId = undefined; }); From 852e1eb72016d71c22b817515547c1d448bdc67a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 11 May 2017 09:31:59 +0100 Subject: [PATCH 058/127] Rename some variables `ReadUpTo` -> `RR` `ReadReceipt` -> `RR` `ReadMarker` -> `RM` --- src/components/structures/TimelinePanel.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 5a5abc6257..de43bd1c19 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -507,10 +507,10 @@ var TimelinePanel = React.createClass({ // if no client or client is guest don't send RR or RM if (!cli || cli.isGuest()) return; - let shouldSendReadReceipt = true; + let shouldSendRR = true; - const currentReadUpToEventId = this._getCurrentReadReceipt(true); - const currentReadUpToEventIndex = this._indexForEventId(currentReadUpToEventId); + const currentRREventId = this._getCurrentReadReceipt(true); + const currentRREventIndex = this._indexForEventId(currentRREventId); // We want to avoid sending out read receipts when we are looking at // events in the past which are before the latest RR. // @@ -524,33 +524,33 @@ var TimelinePanel = React.createClass({ // RRs) - but that is a bit of a niche case. It will sort itself out when // the user eventually hits the live timeline. // - if (currentReadUpToEventId && currentReadUpToEventIndex === null && + if (currentRREventId && currentRREventIndex === null && this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) { - shouldSendReadReceipt = false; + shouldSendRR = false; } const lastReadEventIndex = this._getLastDisplayedEventIndex({ ignoreOwn: true, }); if (lastReadEventIndex === null) { - shouldSendReadReceipt = false; + shouldSendRR = false; } let lastReadEvent = this.state.events[lastReadEventIndex]; - shouldSendReadReceipt = shouldSendReadReceipt && + shouldSendRR = shouldSendRR && // Only send a RR if the last read event is ahead in the timeline relative to // the current RR event. - lastReadEventIndex > currentReadUpToEventIndex && + lastReadEventIndex > currentRREventIndex && // Only send a RR if the last RR set != the one we would send this.lastRRSentEventId != lastReadEvent.getId(); // Only send a RM if the last RM sent != the one we would send - const shouldSendReadMarker = + const shouldSendRM = this.lastRMSentEventId != this.state.readMarkerEventId; // we also remember the last read receipt we sent to avoid spamming the // same one at the server repeatedly - if (shouldSendReadReceipt || shouldSendReadMarker) { - if (shouldSendReadReceipt) { + if (shouldSendRR || shouldSendRM) { + if (shouldSendRR) { this.lastRRSentEventId = lastReadEvent.getId(); } else { lastReadEvent = null; From f55b27f43281e860ca92b37635a8207907b9134d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 11 May 2017 17:32:23 +0100 Subject: [PATCH 059/127] looks like it is passed and accessed like a string so unless I'm going insane, it should be a string. fixes ``` rageshake.js:61 Warning: Failed prop type: The prop `onClick` is marked as required in `AccessibleButton`, but its value is `undefined`. in AccessibleButton (created by RoomHeader) in RoomHeader (created by RoomView) in div (created by RoomView) in RoomView (created by LoggedInView) in main (created by LoggedInView) in div (created by LoggedInView) in div (created by LoggedInView) in LoggedInView (created by MatrixChat) in MatrixChat ``` Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/RoomPreviewBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 43c3b05295..5b7ec9347b 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -47,7 +47,7 @@ module.exports = React.createClass({ // The alias that was used to access this room, if appropriate // If given, this will be how the room is referred to (eg. // in error messages). - roomAlias: React.PropTypes.object, + roomAlias: React.PropTypes.string, }, getDefaultProps: function() { From 5e4467adced6ac7cd7eb8b20464efbeb0d8830db Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 11 May 2017 17:35:06 +0100 Subject: [PATCH 060/127] hide settings/search appropriately pass inRoom prop to RoomHeader (defaults to false) remove default onSettingsClick, handle if it is passed EVERYWHERE if onSettingsClick is passes, show that button show search button only if we are in the room, seems to fail otherwise this seems to handle all cases I could throw at it. Give it your best Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/RoomView.js | 1 + src/components/views/rooms/RoomHeader.js | 30 +++++++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 1b3ed6e80d..af0c595ea9 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -1772,6 +1772,7 @@ module.exports = React.createClass({ oobData={this.props.oobData} editing={this.state.editingRoomSettings} saving={this.state.uploadingRoomSettings} + inRoom={myMember && myMember.membership === 'join'} collapsedRhs={ this.props.collapsedRhs } onSearchClick={this.onSearchClick} onSettingsClick={this.onSettingsClick} diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index 94f2691f2c..5a7da47cbf 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -39,6 +39,7 @@ module.exports = React.createClass({ oobData: React.PropTypes.object, editing: React.PropTypes.bool, saving: React.PropTypes.bool, + inRoom: React.PropTypes.bool, collapsedRhs: React.PropTypes.bool, onSettingsClick: React.PropTypes.func, onSaveClick: React.PropTypes.func, @@ -49,7 +50,7 @@ module.exports = React.createClass({ getDefaultProps: function() { return { editing: false, - onSettingsClick: function() {}, + inRoom: false, onSaveClick: function() {}, }; }, @@ -225,12 +226,17 @@ module.exports = React.createClass({ roomName = this.props.room.name; } + const innerName = + {roomName}; + + if (this.props.onSettingsClick) { + name =
{ innerName }{ searchStatus }
; + } else { + name =
{ innerName }{ searchStatus }
; + } - name = -
- {roomName} - { searchStatus } -
; } if (can_set_room_topic) { @@ -299,6 +305,14 @@ module.exports = React.createClass({ ; } + let search_button; + if (this.props.onSearchClick && this.props.inRoom) { + search_button = + + + ; + } + var rightPanel_buttons; if (this.props.collapsedRhs) { rightPanel_buttons = @@ -313,9 +327,7 @@ module.exports = React.createClass({
{ settings_button } { forget_button } - - - + { search_button } { rightPanel_buttons }
; } From 69d860e98207df27eaaefdb1a53f9e82918f94bc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 12 May 2017 21:06:36 +0100 Subject: [PATCH 061/127] revert name overengineering, undefined onClick should be fine on div Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/RoomHeader.js | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index 5a7da47cbf..c10228c334 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -226,17 +226,11 @@ module.exports = React.createClass({ roomName = this.props.room.name; } - const innerName = - {roomName}; - - if (this.props.onSettingsClick) { - name =
{ innerName }{ searchStatus }
; - } else { - name =
{ innerName }{ searchStatus }
; - } - + name = +
+ {roomName} + { searchStatus } +
; } if (can_set_room_topic) { From 822f2f10f28a724654d3cc574ecc4672d7f243fa Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 12 May 2017 21:16:55 +0100 Subject: [PATCH 062/127] conform to Luke's comment https://github.com/matrix-org/matrix-react-sdk/pull/880#discussion_r116257726 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/RoomHeader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index c10228c334..e9bb10c60c 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -228,7 +228,7 @@ module.exports = React.createClass({ name =
- {roomName} + { roomName } { searchStatus }
; } From 60b13d76a505fbc99940e72f425f21d7984bef1b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 12 May 2017 21:20:56 +0100 Subject: [PATCH 063/127] conform to Luke's other comment Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/RoomHeader.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index e9bb10c60c..4cf20454a0 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -17,6 +17,7 @@ limitations under the License. 'use strict'; var React = require('react'); +var classNames = require('classnames'); var sdk = require('../../../index'); var MatrixClientPeg = require('../../../MatrixClientPeg'); var Modal = require("../../../Modal"); @@ -226,9 +227,10 @@ module.exports = React.createClass({ roomName = this.props.room.name; } + const emojiTextClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint }); name =
- { roomName } + { roomName } { searchStatus }
; } From 29568feb9519c2068e852037894451573aee645a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 12 May 2017 22:38:57 +0100 Subject: [PATCH 064/127] show error if we can't set a filter this way it still works for a room we've been in before Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/FilePanel.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index fc4cbd9423..778a0cd6f3 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -59,6 +59,8 @@ var FilePanel = React.createClass({ var client = MatrixClientPeg.get(); var room = client.getRoom(roomId); + this.noRoom = !room; + if (room) { var filter = new Matrix.Filter(client.credentials.userId); filter.setDefinition( @@ -82,13 +84,18 @@ var FilePanel = React.createClass({ console.error("Failed to get or create file panel filter", error); } ); - } - else { + } else { console.error("Failed to add filtered timelineSet for FilePanel as no room!"); } }, render: function() { + if (this.noRoom) { + return
+
You must join the room to see its files
+
; + } + // wrap a TimelinePanel with the jump-to-event bits turned off. var TimelinePanel = sdk.getComponent("structures.TimelinePanel"); var Loader = sdk.getComponent("elements.Spinner"); From 6ec799a028dfff7af27e471df9c13f438ae4e7d0 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 13 May 2017 15:04:20 +0100 Subject: [PATCH 065/127] I broke UserSettings for webpack-dev-server where version file doesn't exist, version starts as null then gets set to undefined by the promise this wasn't handled and now undefined is understood to be unknown rather than null also picked up on a small casing error threePids vs threepids, most things using the latter apart from the init Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/UserSettings.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 46dce8bd2e..1740f066d6 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -36,7 +36,7 @@ const REACT_SDK_VERSION = 'dist' in packageJson ? packageJson.version : packageJ // Simple method to help prettify GH Release Tags and Commit Hashes. const semVerRegex = /^v?(\d+\.\d+\.\d+(?:-rc.+)?)(?:-(?:\d+-g)?([0-9a-fA-F]+))?(?:-dirty)?$/i; -const gHVersionLabel = function(repo, token) { +const gHVersionLabel = function(repo, token='') { const match = token.match(semVerRegex); let url; if (match && match[1]) { // basic semVer string possibly with commit hash @@ -151,10 +151,10 @@ module.exports = React.createClass({ getInitialState: function() { return { avatarUrl: null, - threePids: [], + threepids: [], phase: "UserSettings.LOADING", // LOADING, DISPLAY email_add_pending: false, - vectorVersion: null, + vectorVersion: undefined, rejectingInvites: false, }; }, @@ -1004,7 +1004,7 @@ module.exports = React.createClass({ ? gHVersionLabel('matrix-org/matrix-react-sdk', REACT_SDK_VERSION) : REACT_SDK_VERSION }
- riot-web version: {(this.state.vectorVersion !== null) + riot-web version: {(this.state.vectorVersion !== undefined) ? gHVersionLabel('vector-im/riot-web', this.state.vectorVersion) : 'unknown' }
From d7c88a9813087db5df9360eac1c9f57eafa67246 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 13 May 2017 15:20:31 +0100 Subject: [PATCH 066/127] only removed `/me `, remove anyway to fix vector-im/riot-web#3733 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/rooms/MessageComposerInput.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 8efd2fa579..e2fcc19f67 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -542,9 +542,9 @@ export default class MessageComposerInput extends React.Component { let sendTextFn = this.client.sendTextMessage; if (contentText.startsWith('/me')) { - contentText = contentText.replace('/me ', ''); + contentText = contentText.substring(4); // bit of a hack, but the alternative would be quite complicated - if (contentHTML) contentHTML = contentHTML.replace('/me ', ''); + if (contentHTML) contentHTML = contentHTML.replace(/\/me ?/, ''); sendHtmlFn = this.client.sendHtmlEmote; sendTextFn = this.client.sendEmoteMessage; } From f3274426db369814b5c819aee6b46141fedb5584 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 00:25:12 +0100 Subject: [PATCH 067/127] revert f999aa9 and support full date formats when desired --- src/DateUtils.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/DateUtils.js b/src/DateUtils.js index 07bab4ae7b..c58c09d4de 100644 --- a/src/DateUtils.js +++ b/src/DateUtils.js @@ -19,13 +19,14 @@ limitations under the License. var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; +function pad(n) { + return (n < 10 ? '0' : '') + n; +} + module.exports = { formatDate: function(date) { // date.toLocaleTimeString is completely system dependent. // just go 24h for now - function pad(n) { - return (n < 10 ? '0' : '') + n; - } var now = new Date(); if (date.toDateString() === now.toDateString()) { @@ -34,19 +35,20 @@ module.exports = { else if (now.getTime() - date.getTime() < 6 * 24 * 60 * 60 * 1000) { return days[date.getDay()] + " " + pad(date.getHours()) + ':' + pad(date.getMinutes()); } - else /* if (now.getFullYear() === date.getFullYear()) */ { + else if (now.getFullYear() === date.getFullYear()) { return days[date.getDay()] + ", " + months[date.getMonth()] + " " + date.getDate() + " " + pad(date.getHours()) + ':' + pad(date.getMinutes()); } - /* else { - return days[date.getDay()] + ", " + months[date.getMonth()] + " " + date.getDate() + " " + date.getFullYear() + " " + pad(date.getHours()) + ':' + pad(date.getMinutes()); + return this.formatFullDate(date); } - */ + }, + + formatFullDate: function(date) { + return days[date.getDay()] + ", " + months[date.getMonth()] + " " + date.getDate() + " " + date.getFullYear() + " " + pad(date.getHours()) + ':' + pad(date.getMinutes()); }, formatTime: function(date) { - //return pad(date.getHours()) + ':' + pad(date.getMinutes()); - return ('00' + date.getHours()).slice(-2) + ':' + ('00' + date.getMinutes()).slice(-2); + return pad(date.getHours()) + ':' + pad(date.getMinutes()); } }; From c0cead15465ee6c7bf0091d58b4c131491c240f1 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 01:32:37 +0100 Subject: [PATCH 068/127] workaround for https://github.com/vector-im/riot-web/issues/3633. unsure our vector url match could ever return undefined, but apparently it is... --- src/HtmlUtils.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index a31601790f..4acb314c2f 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -148,17 +148,18 @@ var sanitizeHtmlParams = { attribs.href = m[1]; delete attribs.target; } - - m = attribs.href.match(linkifyMatrix.MATRIXTO_URL_PATTERN); - if (m) { - var entity = m[1]; - if (entity[0] === '@') { - attribs.href = '#/user/' + entity; + else { + m = attribs.href.match(linkifyMatrix.MATRIXTO_URL_PATTERN); + if (m) { + var entity = m[1]; + if (entity[0] === '@') { + attribs.href = '#/user/' + entity; + } + else if (entity[0] === '#' || entity[0] === '!') { + attribs.href = '#/room/' + entity; + } + delete attribs.target; } - else if (entity[0] === '#' || entity[0] === '!') { - attribs.href = '#/room/' + entity; - } - delete attribs.target; } } attribs.rel = 'noopener'; // https://mathiasbynens.github.io/rel-noopener/ From c5f2b69e48de2606ba1d420ee40086fb4445f3d6 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 01:37:24 +0100 Subject: [PATCH 069/127] add alt attributes to e2e icons on msgs; fixes https://github.com/vector-im/riot-web/issues/3786 --- src/components/views/rooms/EventTile.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index d1486d22c9..e2e203f680 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -492,22 +492,22 @@ module.exports = WithMatrixClient(React.createClass({ var e2e; // cosmetic padlocks: if ((e2eEnabled && this.props.eventSendStatus) || this.props.mxEvent.getType() === 'm.room.encryption') { - e2e = ; + e2e = Encrypted by verified device; } // real padlocks else if (this.props.mxEvent.isEncrypted() || (e2eEnabled && this.props.eventSendStatus)) { if (this.props.mxEvent.getContent().msgtype === 'm.bad.encrypted') { - e2e = ; + e2e = Undecryptable; } else if (this.state.verified == true || (e2eEnabled && this.props.eventSendStatus)) { - e2e = ; + e2e = Encrypted by verified device; } else { - e2e = ; + e2e = Encrypted by unverified device; } } else if (e2eEnabled) { - e2e = ; + e2e = Unencrypted message; } const timestamp = this.props.mxEvent.getTs() ? : null; From 48864b0880f5c98dc46b043902833b5295d19b78 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 01:39:57 +0100 Subject: [PATCH 070/127] fix visibility of topbar close on dark theme, fixing https://github.com/vector-im/riot-web/issues/3783 --- src/components/views/rooms/TopUnreadMessagesBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/TopUnreadMessagesBar.js b/src/components/views/rooms/TopUnreadMessagesBar.js index 72b489a406..74c689c395 100644 --- a/src/components/views/rooms/TopUnreadMessagesBar.js +++ b/src/components/views/rooms/TopUnreadMessagesBar.js @@ -38,7 +38,7 @@ module.exports = React.createClass({ title="Scroll to unread messages"/> Jump to first unread message.
- Close From 82092dc2d81401b24af4dc60dd0b1bcec5f05a27 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 02:14:50 +0100 Subject: [PATCH 071/127] onClick MELS avatars = expand MELS; fixes https://github.com/vector-im/riot-web/issues/3899 --- src/components/views/elements/MemberEventListSummary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index ae8678894d..dcf1810468 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -269,7 +269,7 @@ module.exports = React.createClass({ ); }); return ( - + {avatars} ); From 5c0c49e1f60a45f0f866ab19474d94cb1a446b0d Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 02:18:18 +0100 Subject: [PATCH 072/127] ignore voip answer/hangup in unread events - fixes https://github.com/vector-im/riot-web/issues/3827 --- src/Unread.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Unread.js b/src/Unread.js index d7490c8632..67166dc24f 100644 --- a/src/Unread.js +++ b/src/Unread.js @@ -25,7 +25,9 @@ module.exports = { eventTriggersUnreadCount: function(ev) { if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) { return false; - } else if (ev.getType() == "m.room.member") { + } else if (ev.getType() == 'm.room.member') { + return false; + } else if (ev.getType() == 'm.call.answer' || ev.getType() == 'm.call.hangup') { return false; } else if (ev.getType == 'm.room.message' && ev.getContent().msgtype == 'm.notify') { return false; From 6879f7ee6f8f2f1e943b1609dee12800b735d4e0 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 02:43:23 +0100 Subject: [PATCH 073/127] add presence to MemberInfo, fixes https://github.com/vector-im/riot-web/issues/3720 --- src/components/views/rooms/MemberInfo.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 1a9a8d5e0f..839405c922 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -717,8 +717,16 @@ module.exports = WithMatrixClient(React.createClass({ const memberName = this.props.member.name; + if (this.props.member.user) { + var presenceState = this.props.member.user.presence; + var presenceLastActiveAgo = this.props.member.user.lastActiveAgo; + var presenceLastTs = this.props.member.user.lastPresenceTs; + var presenceCurrentlyActive = this.props.member.user.currentlyActive; + } + var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); var PowerSelector = sdk.getComponent('elements.PowerSelector'); + var PresenceLabel = sdk.getComponent('rooms.PresenceLabel'); const EmojiText = sdk.getComponent('elements.EmojiText'); return (
@@ -736,6 +744,11 @@ module.exports = WithMatrixClient(React.createClass({
Level:
+
+ +
{ adminTools } From 486301cffb55aee0a7cfb3df1df3ff5a8ad3c228 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 02:55:07 +0100 Subject: [PATCH 074/127] remove dodgy heuristics for hiding dates on RRs and use DateUtils instead. reverts https://github.com/matrix-org/matrix-react-sdk/pull/586/commits/5d99d68a64ec0c81b42c5a8e6959376dab798feb fixes https://github.com/vector-im/riot-web/issues/3523 --- src/components/views/rooms/EventTile.js | 11 ----------- src/components/views/rooms/ReadReceiptMarker.js | 17 ++++------------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index e2e203f680..44c4051995 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -295,16 +295,6 @@ module.exports = WithMatrixClient(React.createClass({ const receiptOffset = 15; let left = 0; - // It's possible that the receipt was sent several days AFTER the event. - // If it is, we want to display the complete date along with the HH:MM:SS, - // rather than just HH:MM:SS. - let dayAfterEvent = new Date(this.props.mxEvent.getTs()); - dayAfterEvent.setDate(dayAfterEvent.getDate() + 1); - dayAfterEvent.setHours(0); - dayAfterEvent.setMinutes(0); - dayAfterEvent.setSeconds(0); - let dayAfterEventTime = dayAfterEvent.getTime(); - var receipts = this.props.readReceipts || []; for (var i = 0; i < receipts.length; ++i) { var receipt = receipts[i]; @@ -340,7 +330,6 @@ module.exports = WithMatrixClient(React.createClass({ suppressAnimation={this._suppressReadReceiptAnimation} onClick={this.toggleAllReadAvatars} timestamp={receipt.ts} - showFullTimestamp={receipt.ts >= dayAfterEventTime} /> ); } diff --git a/src/components/views/rooms/ReadReceiptMarker.js b/src/components/views/rooms/ReadReceiptMarker.js index 230efbd1ea..0911d50c3e 100644 --- a/src/components/views/rooms/ReadReceiptMarker.js +++ b/src/components/views/rooms/ReadReceiptMarker.js @@ -24,6 +24,8 @@ var sdk = require('../../../index'); var Velociraptor = require('../../../Velociraptor'); require('../../../VelocityBounce'); +import DateUtils from '../../../DateUtils'; + var bounce = false; try { if (global.localStorage) { @@ -63,9 +65,6 @@ module.exports = React.createClass({ // Timestamp when the receipt was read timestamp: React.PropTypes.number, - - // True to show the full date/time rather than just the time - showFullTimestamp: React.PropTypes.bool, }, getDefaultProps: function() { @@ -170,16 +169,8 @@ module.exports = React.createClass({ let title; if (this.props.timestamp) { - const prefix = "Seen by " + this.props.member.userId + " at "; - let ts = new Date(this.props.timestamp); - if (this.props.showFullTimestamp) { - // "15/12/2016, 7:05:45 PM (@alice:matrix.org)" - title = prefix + ts.toLocaleString(); - } - else { - // "7:05:45 PM (@alice:matrix.org)" - title = prefix + ts.toLocaleTimeString(); - } + title = "Seen by " + this.props.member.userId + " at " + + DateUtils.formatDate(new Date(this.props.timestamp)); } return ( From 317e24852dc7eaed7cc2a9a055a1139bab934801 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 03:03:17 +0100 Subject: [PATCH 075/127] explicitly label email & phone add sections; fixes https://github.com/vector-im/riot-web/issues/3531 --- src/components/structures/UserSettings.js | 1 + src/components/views/settings/AddPhoneNumber.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 1740f066d6..2c1f17ee3e 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -855,6 +855,7 @@ module.exports = React.createClass({ addEmailSection = (
+
+
From 83cb1e6e29a639dc65e45254fdbd706d2d06c347 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 15 May 2017 10:15:35 +0100 Subject: [PATCH 076/127] tell guests they can't use filepanel until they register Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/FilePanel.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index 778a0cd6f3..e7438afc4d 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -90,7 +90,11 @@ var FilePanel = React.createClass({ }, render: function() { - if (this.noRoom) { + if (MatrixClientPeg.get().isGuest()) { + return
+
You must register to use this functionality
+
; + } else if (this.noRoom) { return
You must join the room to see its files
; From 15201d86aa3b5246242293f0fd4bd9346073aad0 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 15 May 2017 10:16:47 +0100 Subject: [PATCH 077/127] Prevent reskindex -w from running when file names have not changed --- scripts/reskindex.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/scripts/reskindex.js b/scripts/reskindex.js index 1db22f9e10..9516614fa5 100755 --- a/scripts/reskindex.js +++ b/scripts/reskindex.js @@ -8,8 +8,15 @@ var chokidar = require('chokidar'); var componentIndex = path.join('src', 'component-index.js'); var componentsDir = path.join('src', 'components'); var componentGlob = '**/*.js'; +var prevFiles = []; function reskindex() { + var files = glob.sync(componentGlob, {cwd: componentsDir}).sort(); + if (!filesHaveChanged(files, prevFiles)) { + return; + } + prevFiles = files; + var header = args.h || args.header; var packageJson = JSON.parse(fs.readFileSync('./package.json')); @@ -37,7 +44,6 @@ function reskindex() { strm.write("module.exports.components = {};\n"); } - var files = glob.sync(componentGlob, {cwd: componentsDir}).sort(); for (var i = 0; i < files.length; ++i) { var file = files[i].replace('.js', ''); @@ -54,6 +60,20 @@ function reskindex() { console.log('Reskindex: completed'); } +// Expects both arrays of file names to be sorted +function filesHaveChanged(files, prevFiles) { + if (files.length !== prevFiles.length) { + return true; + } + // Check for name changes + for (var i = 0; i < files.length; i++) { + if (prevFiles[i] !== files[i]) { + return true; + } + } + return false; +} + // -w indicates watch mode where any FS events will trigger reskindex if (!args.w) { reskindex(); From 8715b5233c63f9bedfc92f81dea2e4c36d90f715 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 15 May 2017 10:31:17 +0100 Subject: [PATCH 078/127] link to #/register Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/FilePanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index e7438afc4d..d83b6b5564 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -92,7 +92,7 @@ var FilePanel = React.createClass({ render: function() { if (MatrixClientPeg.get().isGuest()) { return
-
You must register to use this functionality
+
You must register to use this functionality
; } else if (this.noRoom) { return
From 6bd7af29176d952f171591b1be147f4711802b69 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 14:00:09 +0100 Subject: [PATCH 079/127] Revert "Merge pull request #867 from matrix-org/t3chguy/BaseDialog-patch1" This reverts commit 3549ff254325cdba689b425307218e678c89a2c8, reversing changes made to 1db677141ea281ac2fba361006597768110f77a5. --- src/components/views/dialogs/BaseDialog.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index 02460148b3..279dedbd43 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -57,25 +57,20 @@ export default React.createClass({ } }, - // Don't let key{down,press} events escape the modal. Consume them all. - _eatKeyEvent: function(e) { - e.stopPropagation(); - }, - // Must be when the key is released (and not pressed) otherwise componentWillUnmount // will focus another element which will receive future key events _onKeyUp: function(e) { if (e.keyCode === KeyCode.ESCAPE) { + e.stopPropagation(); e.preventDefault(); this.props.onFinished(); } else if (e.keyCode === KeyCode.ENTER) { if (this.props.onEnterPressed) { + e.stopPropagation(); e.preventDefault(); this.props.onEnterPressed(e); } } - // Consume all keyup events while Modal is open - e.stopPropagation(); }, _onCancelClick: function(e) { @@ -86,11 +81,7 @@ export default React.createClass({ const TintableSvg = sdk.getComponent("elements.TintableSvg"); return ( -
+
From f8d1a6d24042925692827f6ee100416a34fa516f Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 14:26:46 +0100 Subject: [PATCH 080/127] Revert "Fix 'start chat' button" This reverts commit c841eb641b85995bddb235d3db2c779daffe97a1. --- src/components/views/elements/StartChatButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/StartChatButton.js b/src/components/views/elements/StartChatButton.js index 747f75d1b3..02d5677a7c 100644 --- a/src/components/views/elements/StartChatButton.js +++ b/src/components/views/elements/StartChatButton.js @@ -21,7 +21,7 @@ import PropTypes from 'prop-types'; const StartChatButton = function(props) { const ActionButton = sdk.getComponent('elements.ActionButton'); return ( - Date: Tue, 16 May 2017 14:30:02 +0100 Subject: [PATCH 081/127] Revert "Fix Create Room button" This reverts commit 9cae667c063e67b32e60b89e7256d714a056559b. --- src/components/views/elements/CreateRoomButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js index 73c984a860..e7e526d36b 100644 --- a/src/components/views/elements/CreateRoomButton.js +++ b/src/components/views/elements/CreateRoomButton.js @@ -21,7 +21,7 @@ import PropTypes from 'prop-types'; const CreateRoomButton = function(props) { const ActionButton = sdk.getComponent('elements.ActionButton'); return ( - Date: Tue, 16 May 2017 14:49:55 +0100 Subject: [PATCH 082/127] Revert "Merge pull request #859 from matrix-org/dbkr/left_panel_for_newbies_2" This reverts commit 3366d3bbae203ce28ff85f8d7b80a6e3077a02a6, reversing changes made to ceb71a4ef65607cfcf5c50452839edb1aef40593. --- package.json | 1 - src/components/views/elements/ActionButton.js | 80 ------------ .../views/elements/CreateRoomButton.js | 38 ------ src/components/views/elements/HomeButton.js | 38 ------ .../views/elements/RoomDirectoryButton.js | 38 ------ .../views/elements/SettingsButton.js | 38 ------ .../views/elements/StartChatButton.js | 38 ------ src/components/views/rooms/RoomList.js | 121 ++++-------------- 8 files changed, 24 insertions(+), 368 deletions(-) delete mode 100644 src/components/views/elements/ActionButton.js delete mode 100644 src/components/views/elements/CreateRoomButton.js delete mode 100644 src/components/views/elements/HomeButton.js delete mode 100644 src/components/views/elements/RoomDirectoryButton.js delete mode 100644 src/components/views/elements/SettingsButton.js delete mode 100644 src/components/views/elements/StartChatButton.js diff --git a/package.json b/package.json index 21add8ccb7..3e1fa2d8f3 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,6 @@ "lodash": "^4.13.1", "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "optimist": "^0.6.1", - "prop-types": "^15.5.8", "q": "^1.4.1", "react": "^15.4.0", "react-addons-css-transition-group": "15.3.2", diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js deleted file mode 100644 index 267388daf6..0000000000 --- a/src/components/views/elements/ActionButton.js +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import PropTypes from 'prop-types'; -import AccessibleButton from './AccessibleButton'; -import dis from '../../../dispatcher'; -import sdk from '../../../index'; - -export default React.createClass({ - displayName: 'RoleButton', - - propTypes: { - size: PropTypes.string, - tooltip: PropTypes.bool, - action: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - iconPath: PropTypes.string.isRequired, - }, - - getDefaultProps: function() { - return { - size: "25", - tooltip: false, - }; - }, - - getInitialState: function() { - return { - showTooltip: false, - }; - }, - - _onClick: function(ev) { - ev.stopPropagation(); - dis.dispatch({action: this.props.action}); - }, - - _onMouseEnter: function() { - if (this.props.tooltip) this.setState({showTooltip: true}); - }, - - _onMouseLeave: function() { - this.setState({showTooltip: false}); - }, - - render: function() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); - - let tooltip; - if (this.state.showTooltip) { - const RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); - tooltip = ; - } - - return ( - - - {tooltip} - - ); - } -}); diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js deleted file mode 100644 index e7e526d36b..0000000000 --- a/src/components/views/elements/CreateRoomButton.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import sdk from '../../../index'; -import PropTypes from 'prop-types'; - -const CreateRoomButton = function(props) { - const ActionButton = sdk.getComponent('elements.ActionButton'); - return ( - - ); -}; - -CreateRoomButton.propTypes = { - size: PropTypes.string, - tooltip: PropTypes.bool, -}; - -export default CreateRoomButton; diff --git a/src/components/views/elements/HomeButton.js b/src/components/views/elements/HomeButton.js deleted file mode 100644 index 5c446f24c9..0000000000 --- a/src/components/views/elements/HomeButton.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import sdk from '../../../index'; -import PropTypes from 'prop-types'; - -const HomeButton = function(props) { - const ActionButton = sdk.getComponent('elements.ActionButton'); - return ( - - ); -}; - -HomeButton.propTypes = { - size: PropTypes.string, - tooltip: PropTypes.bool, -}; - -export default HomeButton; diff --git a/src/components/views/elements/RoomDirectoryButton.js b/src/components/views/elements/RoomDirectoryButton.js deleted file mode 100644 index 5e68776a15..0000000000 --- a/src/components/views/elements/RoomDirectoryButton.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import sdk from '../../../index'; -import PropTypes from 'prop-types'; - -const RoomDirectoryButton = function(props) { - const ActionButton = sdk.getComponent('elements.ActionButton'); - return ( - - ); -}; - -RoomDirectoryButton.propTypes = { - size: PropTypes.string, - tooltip: PropTypes.bool, -}; - -export default RoomDirectoryButton; diff --git a/src/components/views/elements/SettingsButton.js b/src/components/views/elements/SettingsButton.js deleted file mode 100644 index c6438da277..0000000000 --- a/src/components/views/elements/SettingsButton.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import sdk from '../../../index'; -import PropTypes from 'prop-types'; - -const SettingsButton = function(props) { - const ActionButton = sdk.getComponent('elements.ActionButton'); - return ( - - ); -}; - -SettingsButton.propTypes = { - size: PropTypes.string, - tooltip: PropTypes.bool, -}; - -export default SettingsButton; diff --git a/src/components/views/elements/StartChatButton.js b/src/components/views/elements/StartChatButton.js deleted file mode 100644 index 02d5677a7c..0000000000 --- a/src/components/views/elements/StartChatButton.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import sdk from '../../../index'; -import PropTypes from 'prop-types'; - -const StartChatButton = function(props) { - const ActionButton = sdk.getComponent('elements.ActionButton'); - return ( - - ); -}; - -StartChatButton.propTypes = { - size: PropTypes.string, - tooltip: PropTypes.bool, -}; - -export default StartChatButton; diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index a595a91ba9..49af1560f1 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -1,6 +1,5 @@ /* Copyright 2015, 2016 OpenMarket Ltd -Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -29,16 +28,8 @@ var Rooms = require('../../../Rooms'); import DMRoomMap from '../../../utils/DMRoomMap'; var Receipt = require('../../../utils/Receipt'); var constantTimeDispatcher = require('../../../ConstantTimeDispatcher'); -import AccessibleButton from '../elements/AccessibleButton'; -const HIDE_CONFERENCE_CHANS = true; - -const VERBS = { - 'm.favourite': 'favourite', - 'im.vector.fake.direct': 'tag direct chat', - 'im.vector.fake.recent': 'restore', - 'm.lowpriority': 'demote', -}; +var HIDE_CONFERENCE_CHANS = true; module.exports = React.createClass({ displayName: 'RoomList', @@ -62,7 +53,6 @@ module.exports = React.createClass({ getInitialState: function() { return { isLoadingLeftRooms: false, - totalRoomCount: null, lists: {}, incomingCall: null, }; @@ -83,7 +73,8 @@ module.exports = React.createClass({ // lookup for which lists a given roomId is currently in. this.listsForRoomId = {}; - this.refreshRoomList(); + var s = this.getRoomLists(); + this.setState(s); // order of the sublists //this.listOrder = []; @@ -326,29 +317,21 @@ module.exports = React.createClass({ // any changes to it incrementally, updating the appropriate sublists // as needed. // Alternatively we'd do something magical with Immutable.js or similar. - const lists = this.getRoomLists(); - let totalRooms = 0; - for (const l of Object.values(lists)) { - totalRooms += l.length; - } - this.setState({ - lists: this.getRoomLists(), - totalRoomCount: totalRooms, - }); - + this.setState(this.getRoomLists()); + // this._lastRefreshRoomListTs = Date.now(); }, getRoomLists: function() { var self = this; - const lists = {}; + var s = { lists: {} }; - lists["im.vector.fake.invite"] = []; - lists["m.favourite"] = []; - lists["im.vector.fake.recent"] = []; - lists["im.vector.fake.direct"] = []; - lists["m.lowpriority"] = []; - lists["im.vector.fake.archived"] = []; + s.lists["im.vector.fake.invite"] = []; + s.lists["m.favourite"] = []; + s.lists["im.vector.fake.recent"] = []; + s.lists["im.vector.fake.direct"] = []; + s.lists["m.lowpriority"] = []; + s.lists["im.vector.fake.archived"] = []; this.listsForRoomId = {}; var otherTagNames = {}; @@ -370,7 +353,7 @@ module.exports = React.createClass({ if (me.membership == "invite") { self.listsForRoomId[room.roomId].push("im.vector.fake.invite"); - lists["im.vector.fake.invite"].push(room); + s.lists["im.vector.fake.invite"].push(room); } else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) { // skip past this room & don't put it in any lists @@ -383,8 +366,8 @@ module.exports = React.createClass({ if (tagNames.length) { for (var i = 0; i < tagNames.length; i++) { var tagName = tagNames[i]; - lists[tagName] = lists[tagName] || []; - lists[tagName].push(room); + s.lists[tagName] = s.lists[tagName] || []; + s.lists[tagName].push(room); self.listsForRoomId[room.roomId].push(tagName); otherTagNames[tagName] = 1; } @@ -392,16 +375,16 @@ module.exports = React.createClass({ else if (dmRoomMap.getUserIdForRoomId(room.roomId)) { // "Direct Message" rooms (that we're still in and that aren't otherwise tagged) self.listsForRoomId[room.roomId].push("im.vector.fake.direct"); - lists["im.vector.fake.direct"].push(room); + s.lists["im.vector.fake.direct"].push(room); } else { self.listsForRoomId[room.roomId].push("im.vector.fake.recent"); - lists["im.vector.fake.recent"].push(room); + s.lists["im.vector.fake.recent"].push(room); } } else if (me.membership === "leave") { self.listsForRoomId[room.roomId].push("im.vector.fake.archived"); - lists["im.vector.fake.archived"].push(room); + s.lists["im.vector.fake.archived"].push(room); } else { console.error("unrecognised membership: " + me.membership + " - this should never happen"); @@ -425,7 +408,7 @@ module.exports = React.createClass({ ]; */ - return lists; + return s; }, _getScrollNode: function() { @@ -455,7 +438,6 @@ module.exports = React.createClass({ var incomingCallBox = document.getElementById("incomingCallBox"); if (incomingCallBox && incomingCallBox.parentElement) { var scrollArea = this._getScrollNode(); - if (!scrollArea) return; // Use the offset of the top of the scroll area from the window // as this is used to calculate the CSS fixed top position for the stickies var scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset; @@ -479,7 +461,6 @@ module.exports = React.createClass({ // properly through React _initAndPositionStickyHeaders: function(initialise, scrollToPosition) { var scrollArea = this._getScrollNode(); - if (!scrollArea) return; // Use the offset of the top of the scroll area from the window // as this is used to calculate the CSS fixed top position for the stickies var scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset; @@ -577,58 +558,6 @@ module.exports = React.createClass({ this.refs.gemscroll.forceUpdate(); }, - _getEmptyContent: function(section) { - const RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget'); - - if (this.props.collapsed) { - return ; - } - - const StartChatButton = sdk.getComponent('elements.StartChatButton'); - const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); - const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); - if (this.state.totalRoomCount === 0) { - const TintableSvg = sdk.getComponent('elements.TintableSvg'); - switch (section) { - case 'im.vector.fake.direct': - return
- Press - - to start a chat with someone -
; - case 'im.vector.fake.recent': - return
- You're not in any rooms yet! Press - - to make a room or - - to browse the directory -
; - } - } - - const labelText = 'Drop here to ' + (VERBS[section] || 'tag ' + section); - - return ; - }, - - _getHeaderItems: function(section) { - const StartChatButton = sdk.getComponent('elements.StartChatButton'); - const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); - const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); - switch (section) { - case 'im.vector.fake.direct': - return - - ; - case 'im.vector.fake.recent': - return - - - ; - } - }, - render: function() { var RoomSubList = sdk.getComponent('structures.RoomSubList'); var self = this; @@ -652,7 +581,7 @@ module.exports = React.createClass({ Date: Tue, 16 May 2017 14:50:19 +0100 Subject: [PATCH 083/127] Revert "Merge pull request #841 from matrix-org/luke/fix-double-dialogs" This reverts commit 1913a32fbd0c303080645f2661cacff25ccff232, reversing changes made to 0c16298c452089188bcc156cf213358988ce7341. --- src/components/views/dialogs/BaseDialog.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index 279dedbd43..d0f34c5fbd 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -57,9 +57,7 @@ export default React.createClass({ } }, - // Must be when the key is released (and not pressed) otherwise componentWillUnmount - // will focus another element which will receive future key events - _onKeyUp: function(e) { + _onKeyDown: function(e) { if (e.keyCode === KeyCode.ESCAPE) { e.stopPropagation(); e.preventDefault(); @@ -81,7 +79,7 @@ export default React.createClass({ const TintableSvg = sdk.getComponent("elements.TintableSvg"); return ( -
+
From ff9c40472a5b1f52450347a890ea720c78e1aa39 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 14:50:29 +0100 Subject: [PATCH 084/127] Revert "Merge pull request #822 from t3chguy/BaseDialog_restore_focus" This reverts commit 0ac836919d54cd04705002d8e53d3514dcce8dde, reversing changes made to 7e07ffd55fe1475ce30e172fa5b0b37061e7375f. --- src/components/views/dialogs/BaseDialog.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index d0f34c5fbd..0b2ca5225d 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -47,16 +47,6 @@ export default React.createClass({ children: React.PropTypes.node, }, - componentWillMount: function() { - this.priorActiveElement = document.activeElement; - }, - - componentWillUnmount: function() { - if (this.priorActiveElement !== null) { - this.priorActiveElement.focus(); - } - }, - _onKeyDown: function(e) { if (e.keyCode === KeyCode.ESCAPE) { e.stopPropagation(); @@ -77,7 +67,7 @@ export default React.createClass({ render: function() { const TintableSvg = sdk.getComponent("elements.TintableSvg"); - + return (
Date: Tue, 16 May 2017 15:35:22 +0100 Subject: [PATCH 085/127] Revert "comment out spammy CTD logging" This reverts commit 19482d751d82c162321d99c5bf95ac8fe950768b. --- src/ConstantTimeDispatcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ConstantTimeDispatcher.js b/src/ConstantTimeDispatcher.js index 6c2c3266aa..265ee11fd4 100644 --- a/src/ConstantTimeDispatcher.js +++ b/src/ConstantTimeDispatcher.js @@ -47,7 +47,7 @@ class ConstantTimeDispatcher { dispatch(type, arg, params) { if (!this.listeners[type] || !this.listeners[type][arg]) { - //console.warn("No registered listeners for dispatch (type=" + type + ", arg=" + arg + ")"); + console.warn("No registered listeners for dispatch (type=" + type + ", arg=" + arg + ")"); return; } this.listeners[type][arg].forEach(listener=>{ From 714cd6a10fd49df86caa9df4406e7a31cc7bfea1 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:00:34 +0100 Subject: [PATCH 086/127] Revert "recalculate roomlist when your invites change" This reverts commit ec6a1c4c750f959017cdf823402a6c9d86b16fe2. --- src/components/views/rooms/RoomList.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 49af1560f1..101f0838a9 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -265,16 +265,9 @@ module.exports = React.createClass({ }, onRoomStateMember: function(ev, state, member) { - if (ev.getStateKey() === MatrixClientPeg.get().credentials.userId && - ev.getPrevContent() && ev.getPrevContent().membership === "invite") - { - this._delayedRefreshRoomList(); - } - else { - constantTimeDispatcher.dispatch( - "RoomTile.refresh", member.roomId, {} - ); - } + constantTimeDispatcher.dispatch( + "RoomTile.refresh", member.roomId, {} + ); }, onRoomMemberName: function(ev, member) { From b063c605a86bdd9f216506e09bd93f54e42a29df Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:01:14 +0100 Subject: [PATCH 087/127] Revert "fix stupid typos in RoomList's shouldComponentUpdate" This reverts commit b0288ebd89841ad362a6804b41839ef9d3bdca7f. --- src/components/views/rooms/RoomList.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 101f0838a9..b99d26376f 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -44,9 +44,9 @@ module.exports = React.createClass({ shouldComponentUpdate: function(nextProps, nextState) { if (nextProps.collapsed !== this.props.collapsed) return true; if (nextProps.searchFilter !== this.props.searchFilter) return true; - if (nextState.lists !== this.state.lists || - nextState.isLoadingLeftRooms !== this.state.isLoadingLeftRooms || - nextState.incomingCall !== this.state.incomingCall) return true; + if (nextState.lists !== this.props.lists || + nextState.isLoadingLeftRooms !== this.isLoadingLeftRooms || + nextState.incomingCall !== this.incomingCall) return true; return false; }, From 7a949b6a4591cdb7c5fe93b8aef610388ef8eba4 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:01:32 +0100 Subject: [PATCH 088/127] Revert "oops, actually refresh roomlist when its state changes!" This reverts commit 35a16edcccd07fdd4209783ce1efaee8115eb4b4. --- src/components/views/rooms/RoomList.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index b99d26376f..b4ab25a0f2 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -44,9 +44,6 @@ module.exports = React.createClass({ shouldComponentUpdate: function(nextProps, nextState) { if (nextProps.collapsed !== this.props.collapsed) return true; if (nextProps.searchFilter !== this.props.searchFilter) return true; - if (nextState.lists !== this.props.lists || - nextState.isLoadingLeftRooms !== this.isLoadingLeftRooms || - nextState.incomingCall !== this.incomingCall) return true; return false; }, From eddc2af92d7a465f755c472f3ea3da3cca3a185f Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:01:54 +0100 Subject: [PATCH 089/127] Revert "HOW DID THIS EVER WORK?" This reverts commit 0d8d3c67106a3e84fd30de4016b9c852870f99b3. --- src/components/views/rooms/RoomList.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index b4ab25a0f2..b86d17d290 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -558,7 +558,6 @@ module.exports = React.createClass({
Date: Tue, 16 May 2017 16:02:13 +0100 Subject: [PATCH 090/127] Revert "unbreak stack overflow which fires on tests due to mocked timers" This reverts commit e69ea68133bb01dfd2093ffc5644edef24fbed70. --- src/components/views/rooms/RoomList.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index b86d17d290..d6e2ab633d 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -74,11 +74,7 @@ module.exports = React.createClass({ this.setState(s); // order of the sublists - //this.listOrder = []; - - // loop count to stop a stack overflow if the user keeps waggling the - // mouse for >30s in a row, or if running under mocha - this._delayedRefreshRoomListLoopCount = 0 + this.listOrder = []; }, componentDidMount: function() { @@ -288,12 +284,10 @@ module.exports = React.createClass({ // if the mouse has been moving over the RoomList in the last 500ms // then delay the refresh further to avoid bouncing around under the // cursor - if (Date.now() - this._lastMouseOverTs > 500 || this._delayedRefreshRoomListLoopCount > 60) { + if (Date.now() - this._lastMouseOverTs > 500) { this.refreshRoomList(); - this._delayedRefreshRoomListLoopCount = 0; } else { - this._delayedRefreshRoomListLoopCount++; this._delayedRefreshRoomList(); } }, 500), From ebfafb363972e77ef02f0e518573bf68ebc0ed15 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:11:01 +0100 Subject: [PATCH 091/127] Revert "Merge pull request #807 from matrix-org/matthew/quick-search" This reverts commit 0ad1d8caf3f83aca517d1afff492f1c3d01e9ad5, reversing changes made to 1189368aab8cfb22c1895f8ce6c0d8a8fbe7ca0b. --- package.json | 2 +- src/ConstantTimeDispatcher.js | 62 ----- src/KeyCode.js | 1 - src/components/structures/TimelinePanel.js | 1 - .../views/dialogs/QuestionDialog.js | 8 +- src/components/views/rooms/RoomList.js | 233 ++++++------------ src/components/views/rooms/RoomTile.js | 57 ++--- 7 files changed, 99 insertions(+), 265 deletions(-) delete mode 100644 src/ConstantTimeDispatcher.js diff --git a/package.json b/package.json index 3e1fa2d8f3..444d1c5369 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "react": "^15.4.0", "react-addons-css-transition-group": "15.3.2", "react-dom": "^15.4.0", - "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#39d858c", + "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", "sanitize-html": "^1.11.1", "text-encoding-utf-8": "^1.0.1", "velocity-vector": "vector-im/velocity#059e3b2", diff --git a/src/ConstantTimeDispatcher.js b/src/ConstantTimeDispatcher.js deleted file mode 100644 index 265ee11fd4..0000000000 --- a/src/ConstantTimeDispatcher.js +++ /dev/null @@ -1,62 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// singleton which dispatches invocations of a given type & argument -// rather than just a type (as per EventEmitter and Flux's dispatcher etc) -// -// This means you can have a single point which listens for an EventEmitter event -// and then dispatches out to one of thousands of RoomTiles (for instance) rather than -// having each RoomTile register for the EventEmitter event and having to -// iterate over all of them. -class ConstantTimeDispatcher { - constructor() { - // type -> arg -> [ listener(arg, params) ] - this.listeners = {}; - } - - register(type, arg, listener) { - if (!this.listeners[type]) this.listeners[type] = {}; - if (!this.listeners[type][arg]) this.listeners[type][arg] = []; - this.listeners[type][arg].push(listener); - } - - unregister(type, arg, listener) { - if (this.listeners[type] && this.listeners[type][arg]) { - var i = this.listeners[type][arg].indexOf(listener); - if (i > -1) { - this.listeners[type][arg].splice(i, 1); - } - } - else { - console.warn("Unregistering unrecognised listener (type=" + type + ", arg=" + arg + ")"); - } - } - - dispatch(type, arg, params) { - if (!this.listeners[type] || !this.listeners[type][arg]) { - console.warn("No registered listeners for dispatch (type=" + type + ", arg=" + arg + ")"); - return; - } - this.listeners[type][arg].forEach(listener=>{ - listener.call(arg, params); - }); - } -} - -if (!global.constantTimeDispatcher) { - global.constantTimeDispatcher = new ConstantTimeDispatcher(); -} -module.exports = global.constantTimeDispatcher; diff --git a/src/KeyCode.js b/src/KeyCode.js index f164dbc15c..c9cac01239 100644 --- a/src/KeyCode.js +++ b/src/KeyCode.js @@ -32,5 +32,4 @@ module.exports = { DELETE: 46, KEY_D: 68, KEY_E: 69, - KEY_K: 75, }; diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index de43bd1c19..8794713501 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -590,7 +590,6 @@ var TimelinePanel = React.createClass({ this.props.timelineSet.room.setUnreadNotificationCount('highlight', 0); dis.dispatch({ action: 'on_room_read', - room: this.props.timelineSet.room, }); } } diff --git a/src/components/views/dialogs/QuestionDialog.js b/src/components/views/dialogs/QuestionDialog.js index 8e20b0d2bc..6012541b94 100644 --- a/src/components/views/dialogs/QuestionDialog.js +++ b/src/components/views/dialogs/QuestionDialog.js @@ -47,12 +47,6 @@ export default React.createClass({ this.props.onFinished(false); }, - componentDidMount: function() { - if (this.props.focus) { - this.refs.button.focus(); - } - }, - render: function() { const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); const cancelButton = this.props.hasCancelButton ? ( @@ -69,7 +63,7 @@ export default React.createClass({ {this.props.description}
- {this.props.extraButtons} diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index d6e2ab633d..611dd10780 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -21,13 +21,13 @@ var GeminiScrollbar = require('react-gemini-scrollbar'); var MatrixClientPeg = require("../../../MatrixClientPeg"); var CallHandler = require('../../../CallHandler'); var RoomListSorter = require("../../../RoomListSorter"); +var Unread = require('../../../Unread'); var dis = require("../../../dispatcher"); var sdk = require('../../../index'); var rate_limited_func = require('../../../ratelimitedfunc'); var Rooms = require('../../../Rooms'); import DMRoomMap from '../../../utils/DMRoomMap'; var Receipt = require('../../../utils/Receipt'); -var constantTimeDispatcher = require('../../../ConstantTimeDispatcher'); var HIDE_CONFERENCE_CHANS = true; @@ -37,16 +37,10 @@ module.exports = React.createClass({ propTypes: { ConferenceHandler: React.PropTypes.any, collapsed: React.PropTypes.bool.isRequired, - selectedRoom: React.PropTypes.string, + currentRoom: React.PropTypes.string, searchFilter: React.PropTypes.string, }, - shouldComponentUpdate: function(nextProps, nextState) { - if (nextProps.collapsed !== this.props.collapsed) return true; - if (nextProps.searchFilter !== this.props.searchFilter) return true; - return false; - }, - getInitialState: function() { return { isLoadingLeftRooms: false, @@ -63,18 +57,12 @@ module.exports = React.createClass({ cli.on("Room.name", this.onRoomName); cli.on("Room.tags", this.onRoomTags); cli.on("Room.receipt", this.onRoomReceipt); - cli.on("RoomState.members", this.onRoomStateMember); + cli.on("RoomState.events", this.onRoomStateEvents); cli.on("RoomMember.name", this.onRoomMemberName); cli.on("accountData", this.onAccountData); - // lookup for which lists a given roomId is currently in. - this.listsForRoomId = {}; - var s = this.getRoomLists(); this.setState(s); - - // order of the sublists - this.listOrder = []; }, componentDidMount: function() { @@ -83,22 +71,7 @@ module.exports = React.createClass({ this._updateStickyHeaders(true); }, - componentWillReceiveProps: function(nextProps) { - // short-circuit react when the room changes - // to avoid rerendering all the sublists everywhere - if (nextProps.selectedRoom !== this.props.selectedRoom) { - if (this.props.selectedRoom) { - constantTimeDispatcher.dispatch( - "RoomTile.select", this.props.selectedRoom, {} - ); - } - constantTimeDispatcher.dispatch( - "RoomTile.select", nextProps.selectedRoom, { selected: true } - ); - } - }, - - componentDidUpdate: function(prevProps, prevState) { + componentDidUpdate: function() { // Reinitialise the stickyHeaders when the component is updated this._updateStickyHeaders(true); this._repositionIncomingCallBox(undefined, false); @@ -124,24 +97,10 @@ module.exports = React.createClass({ } break; case 'on_room_read': - // poke the right RoomTile to refresh, using the constantTimeDispatcher - // to avoid each and every RoomTile registering to the 'on_room_read' event - // XXX: if we like the constantTimeDispatcher we might want to dispatch - // directly from TimelinePanel rather than needlessly bouncing via here. - constantTimeDispatcher.dispatch( - "RoomTile.refresh", payload.room.roomId, {} - ); - - // also have to poke the right list(s) - var lists = this.listsForRoomId[payload.room.roomId]; - if (lists) { - lists.forEach(list=>{ - constantTimeDispatcher.dispatch( - "RoomSubList.refreshHeader", list, { room: payload.room } - ); - }); - } - + // Force an update because the notif count state is too deep to cause + // an update. This forces the local echo of reading notifs to be + // reflected by the RoomTiles. + this.forceUpdate(); break; } }, @@ -155,7 +114,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().removeListener("Room.name", this.onRoomName); MatrixClientPeg.get().removeListener("Room.tags", this.onRoomTags); MatrixClientPeg.get().removeListener("Room.receipt", this.onRoomReceipt); - MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember); + MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents); MatrixClientPeg.get().removeListener("RoomMember.name", this.onRoomMemberName); MatrixClientPeg.get().removeListener("accountData", this.onAccountData); } @@ -164,14 +123,10 @@ module.exports = React.createClass({ }, onRoom: function(room) { - // XXX: this happens rarely; ideally we should only update the correct - // sublists when it does (e.g. via a constantTimeDispatch to the right sublist) this._delayedRefreshRoomList(); }, onDeleteRoom: function(roomId) { - // XXX: this happens rarely; ideally we should only update the correct - // sublists when it does (e.g. via a constantTimeDispatch to the right sublist) this._delayedRefreshRoomList(); }, @@ -194,10 +149,6 @@ module.exports = React.createClass({ } }, - _onMouseOver: function(ev) { - this._lastMouseOverTs = Date.now(); - }, - onSubListHeaderClick: function(isHidden, scrollToPosition) { // The scroll area has expanded or contracted, so re-calculate sticky headers positions this._updateStickyHeaders(true, scrollToPosition); @@ -207,89 +158,41 @@ module.exports = React.createClass({ if (toStartOfTimeline) return; if (!room) return; if (data.timeline.getTimelineSet() !== room.getUnfilteredTimelineSet()) return; - - // rather than regenerate our full roomlists, which is very heavy, we poke the - // correct sublists to just re-sort themselves. This isn't enormously reacty, - // but is much faster than the default react reconciler, or having to do voodoo - // with shouldComponentUpdate and a pleaseRefresh property or similar. - var lists = this.listsForRoomId[room.roomId]; - if (lists) { - lists.forEach(list=>{ - constantTimeDispatcher.dispatch("RoomSubList.sort", list, { room: room }); - }); - } - - // we have to explicitly hit the roomtile which just changed - constantTimeDispatcher.dispatch( - "RoomTile.refresh", room.roomId, {} - ); + this._delayedRefreshRoomList(); }, onRoomReceipt: function(receiptEvent, room) { // because if we read a notification, it will affect notification count // only bother updating if there's a receipt from us if (Receipt.findReadReceiptFromUserId(receiptEvent, MatrixClientPeg.get().credentials.userId)) { - var lists = this.listsForRoomId[room.roomId]; - if (lists) { - lists.forEach(list=>{ - constantTimeDispatcher.dispatch( - "RoomSubList.refreshHeader", list, { room: room } - ); - }); - } - - // we have to explicitly hit the roomtile which just changed - constantTimeDispatcher.dispatch( - "RoomTile.refresh", room.roomId, {} - ); + this._delayedRefreshRoomList(); } }, onRoomName: function(room) { - constantTimeDispatcher.dispatch( - "RoomTile.refresh", room.roomId, {} - ); - }, - - onRoomTags: function(event, room) { - // XXX: this happens rarely; ideally we should only update the correct - // sublists when it does (e.g. via a constantTimeDispatch to the right sublist) this._delayedRefreshRoomList(); }, - onRoomStateMember: function(ev, state, member) { - constantTimeDispatcher.dispatch( - "RoomTile.refresh", member.roomId, {} - ); + onRoomTags: function(event, room) { + this._delayedRefreshRoomList(); + }, + + onRoomStateEvents: function(ev, state) { + this._delayedRefreshRoomList(); }, onRoomMemberName: function(ev, member) { - constantTimeDispatcher.dispatch( - "RoomTile.refresh", member.roomId, {} - ); + this._delayedRefreshRoomList(); }, onAccountData: function(ev) { if (ev.getType() == 'm.direct') { - // XXX: this happens rarely; ideally we should only update the correct - // sublists when it does (e.g. via a constantTimeDispatch to the right sublist) - this._delayedRefreshRoomList(); - } - else if (ev.getType() == 'm.push_rules') { this._delayedRefreshRoomList(); } }, _delayedRefreshRoomList: new rate_limited_func(function() { - // if the mouse has been moving over the RoomList in the last 500ms - // then delay the refresh further to avoid bouncing around under the - // cursor - if (Date.now() - this._lastMouseOverTs > 500) { - this.refreshRoomList(); - } - else { - this._delayedRefreshRoomList(); - } + this.refreshRoomList(); }, 500), refreshRoomList: function() { @@ -297,10 +200,12 @@ module.exports = React.createClass({ // (!this._lastRefreshRoomListTs ? "-" : (Date.now() - this._lastRefreshRoomListTs)) // ); - // TODO: ideally we'd calculate this once at start, and then maintain - // any changes to it incrementally, updating the appropriate sublists - // as needed. - // Alternatively we'd do something magical with Immutable.js or similar. + // TODO: rather than bluntly regenerating and re-sorting everything + // every time we see any kind of room change from the JS SDK + // we could do incremental updates on our copy of the state + // based on the room which has actually changed. This would stop + // us re-rendering all the sublists every time anything changes anywhere + // in the state of the client. this.setState(this.getRoomLists()); // this._lastRefreshRoomListTs = Date.now(); @@ -317,9 +222,6 @@ module.exports = React.createClass({ s.lists["m.lowpriority"] = []; s.lists["im.vector.fake.archived"] = []; - this.listsForRoomId = {}; - var otherTagNames = {}; - const dmRoomMap = new DMRoomMap(MatrixClientPeg.get()); MatrixClientPeg.get().getRooms().forEach(function(room) { @@ -331,12 +233,7 @@ module.exports = React.createClass({ // ", target = " + me.events.member.getStateKey() + // ", prevMembership = " + me.events.member.getPrevContent().membership); - if (!self.listsForRoomId[room.roomId]) { - self.listsForRoomId[room.roomId] = []; - } - if (me.membership == "invite") { - self.listsForRoomId[room.roomId].push("im.vector.fake.invite"); s.lists["im.vector.fake.invite"].push(room); } else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) { @@ -347,27 +244,23 @@ module.exports = React.createClass({ { // Used to split rooms via tags var tagNames = Object.keys(room.tags); + if (tagNames.length) { for (var i = 0; i < tagNames.length; i++) { var tagName = tagNames[i]; s.lists[tagName] = s.lists[tagName] || []; - s.lists[tagName].push(room); - self.listsForRoomId[room.roomId].push(tagName); - otherTagNames[tagName] = 1; + s.lists[tagNames[i]].push(room); } } else if (dmRoomMap.getUserIdForRoomId(room.roomId)) { // "Direct Message" rooms (that we're still in and that aren't otherwise tagged) - self.listsForRoomId[room.roomId].push("im.vector.fake.direct"); s.lists["im.vector.fake.direct"].push(room); } else { - self.listsForRoomId[room.roomId].push("im.vector.fake.recent"); s.lists["im.vector.fake.recent"].push(room); } } else if (me.membership === "leave") { - self.listsForRoomId[room.roomId].push("im.vector.fake.archived"); s.lists["im.vector.fake.archived"].push(room); } else { @@ -375,22 +268,44 @@ module.exports = React.createClass({ } }); - // we actually apply the sorting to this when receiving the prop in RoomSubLists. + if (s.lists["im.vector.fake.direct"].length == 0 && + MatrixClientPeg.get().getAccountData('m.direct') === undefined && + !MatrixClientPeg.get().isGuest()) + { + // scan through the 'recents' list for any rooms which look like DM rooms + // and make them DM rooms + const oldRecents = s.lists["im.vector.fake.recent"]; + s.lists["im.vector.fake.recent"] = []; - // we'll need this when we get to iterating through lists programatically - e.g. ctrl-shift-up/down -/* - this.listOrder = [ - "im.vector.fake.invite", - "m.favourite", - "im.vector.fake.recent", - "im.vector.fake.direct", - Object.keys(otherTagNames).filter(tagName=>{ - return (!tagName.match(/^m\.(favourite|lowpriority)$/)); - }).sort(), - "m.lowpriority", - "im.vector.fake.archived" - ]; -*/ + for (const room of oldRecents) { + const me = room.getMember(MatrixClientPeg.get().credentials.userId); + + if (me && Rooms.looksLikeDirectMessageRoom(room, me)) { + s.lists["im.vector.fake.direct"].push(room); + } else { + s.lists["im.vector.fake.recent"].push(room); + } + } + + // save these new guessed DM rooms into the account data + const newMDirectEvent = {}; + for (const room of s.lists["im.vector.fake.direct"]) { + const me = room.getMember(MatrixClientPeg.get().credentials.userId); + const otherPerson = Rooms.getOnlyOtherMember(room, me); + if (!otherPerson) continue; + + const roomList = newMDirectEvent[otherPerson.userId] || []; + roomList.push(room.roomId); + newMDirectEvent[otherPerson.userId] = roomList; + } + + // if this fails, fine, we'll just do the same thing next time we get the room lists + MatrixClientPeg.get().setAccountData('m.direct', newMDirectEvent).done(); + } + + //console.log("calculated new roomLists; im.vector.fake.recent = " + s.lists["im.vector.fake.recent"]); + + // we actually apply the sorting to this when receiving the prop in RoomSubLists. return s; }, @@ -548,15 +463,15 @@ module.exports = React.createClass({ return ( -
+ autoshow={true} onScroll={ self._whenScrolling } ref="gemscroll"> +
@@ -567,9 +482,9 @@ module.exports = React.createClass({ verb="favourite" editable={ true } order="manual" + selectedRoom={ self.props.selectedRoom } incomingCall={ self.state.incomingCall } collapsed={ self.props.collapsed } - selectedRoom={ self.props.selectedRoom } searchFilter={ self.props.searchFilter } onHeaderClick={ self.onSubListHeaderClick } onShowMoreRooms={ self.onShowMoreRooms } /> @@ -580,9 +495,9 @@ module.exports = React.createClass({ verb="tag direct chat" editable={ true } order="recent" + selectedRoom={ self.props.selectedRoom } incomingCall={ self.state.incomingCall } collapsed={ self.props.collapsed } - selectedRoom={ self.props.selectedRoom } alwaysShowHeader={ true } searchFilter={ self.props.searchFilter } onHeaderClick={ self.onSubListHeaderClick } @@ -593,14 +508,14 @@ module.exports = React.createClass({ editable={ true } verb="restore" order="recent" + selectedRoom={ self.props.selectedRoom } incomingCall={ self.state.incomingCall } collapsed={ self.props.collapsed } - selectedRoom={ self.props.selectedRoom } searchFilter={ self.props.searchFilter } onHeaderClick={ self.onSubListHeaderClick } onShowMoreRooms={ self.onShowMoreRooms } /> - { Object.keys(self.state.lists).sort().map(function(tagName) { + { Object.keys(self.state.lists).map(function(tagName) { if (!tagName.match(/^(m\.(favourite|lowpriority)|im\.vector\.fake\.(invite|recent|direct|archived))$/)) { return ; @@ -625,9 +540,9 @@ module.exports = React.createClass({ verb="demote" editable={ true } order="recent" + selectedRoom={ self.props.selectedRoom } incomingCall={ self.state.incomingCall } collapsed={ self.props.collapsed } - selectedRoom={ self.props.selectedRoom } searchFilter={ self.props.searchFilter } onHeaderClick={ self.onSubListHeaderClick } onShowMoreRooms={ self.onShowMoreRooms } /> @@ -636,8 +551,8 @@ module.exports = React.createClass({ label="Historical" editable={ false } order="recent" - collapsed={ self.props.collapsed } selectedRoom={ self.props.selectedRoom } + collapsed={ self.props.collapsed } alwaysShowHeader={ true } startAsHidden={ true } showSpinner={ self.state.isLoadingLeftRooms } diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 3b37d4608f..c123f31d19 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -27,8 +27,6 @@ var RoomNotifs = require('../../../RoomNotifs'); var FormattingUtils = require('../../../utils/FormattingUtils'); import AccessibleButton from '../elements/AccessibleButton'; var UserSettingsStore = require('../../../UserSettingsStore'); -var constantTimeDispatcher = require('../../../ConstantTimeDispatcher'); -var Unread = require('../../../Unread'); module.exports = React.createClass({ displayName: 'RoomTile', @@ -38,10 +36,12 @@ module.exports = React.createClass({ connectDropTarget: React.PropTypes.func, onClick: React.PropTypes.func, isDragging: React.PropTypes.bool, - selectedRoom: React.PropTypes.string, room: React.PropTypes.object.isRequired, collapsed: React.PropTypes.bool.isRequired, + selected: React.PropTypes.bool.isRequired, + unread: React.PropTypes.bool.isRequired, + highlight: React.PropTypes.bool.isRequired, isInvite: React.PropTypes.bool.isRequired, incomingCall: React.PropTypes.object, }, @@ -54,11 +54,10 @@ module.exports = React.createClass({ getInitialState: function() { return({ - hover: false, - badgeHover: false, + hover : false, + badgeHover : false, menuDisplayed: false, notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId), - selected: this.props.room ? (this.props.selectedRoom === this.props.room.roomId) : false, }); }, @@ -80,32 +79,23 @@ module.exports = React.createClass({ } }, + onAccountData: function(accountDataEvent) { + if (accountDataEvent.getType() == 'm.push_rules') { + this.setState({ + notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId), + }); + } + }, + componentWillMount: function() { - constantTimeDispatcher.register("RoomTile.refresh", this.props.room.roomId, this.onRefresh); - constantTimeDispatcher.register("RoomTile.select", this.props.room.roomId, this.onSelect); - this.onRefresh(); + MatrixClientPeg.get().on("accountData", this.onAccountData); }, componentWillUnmount: function() { - constantTimeDispatcher.unregister("RoomTile.refresh", this.props.room.roomId, this.onRefresh); - constantTimeDispatcher.unregister("RoomTile.select", this.props.room.roomId, this.onSelect); - }, - - componentWillReceiveProps: function(nextProps) { - this.onRefresh(); - }, - - onRefresh: function(params) { - this.setState({ - unread: Unread.doesRoomHaveUnreadMessages(this.props.room), - highlight: this.props.room.getUnreadNotificationCount('highlight') > 0 || this.props.isInvite, - }); - }, - - onSelect: function(params) { - this.setState({ - selected: params.selected, - }); + var cli = MatrixClientPeg.get(); + if (cli) { + MatrixClientPeg.get().removeListener("accountData", this.onAccountData); + } }, onClick: function(ev) { @@ -179,13 +169,13 @@ module.exports = React.createClass({ // var highlightCount = this.props.room.getUnreadNotificationCount("highlight"); const notifBadges = notificationCount > 0 && this._shouldShowNotifBadge(); - const mentionBadges = this.state.highlight && this._shouldShowMentionBadge(); + const mentionBadges = this.props.highlight && this._shouldShowMentionBadge(); const badges = notifBadges || mentionBadges; var classes = classNames({ 'mx_RoomTile': true, - 'mx_RoomTile_selected': this.state.selected, - 'mx_RoomTile_unread': this.state.unread, + 'mx_RoomTile_selected': this.props.selected, + 'mx_RoomTile_unread': this.props.unread, 'mx_RoomTile_unreadNotify': notifBadges, 'mx_RoomTile_highlight': mentionBadges, 'mx_RoomTile_invited': (me && me.membership == 'invite'), @@ -231,7 +221,7 @@ module.exports = React.createClass({ 'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.menuDisplayed, }); - if (this.state.selected) { + if (this.props.selected) { let nameSelected = {name}; label =
{ nameSelected }
; @@ -265,8 +255,7 @@ module.exports = React.createClass({ let ret = (
{ /* Only native elements can be wrapped in a DnD object. */} - +
From 75eea89c08354caf2f65e9bbeb60a572830c21c2 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:12:57 +0100 Subject: [PATCH 092/127] Revert "Merge pull request #765 from t3chguy/t3chguy/escape-closes-user-settings" This reverts commit a29d8c2af200af9bd5f55da60a10d1fc9c473764, reversing changes made to 1d836c7d02a6935313bfb05d94fc38ae05439480. --- src/components/structures/LoggedInView.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index c4eeb03d5f..25ca025a23 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -107,18 +107,6 @@ export default React.createClass({ var handled = false; switch (ev.keyCode) { - case KeyCode.ESCAPE: - - // Implemented this way so possible handling for other pages is neater - switch (this.props.page_type) { - case PageTypes.UserSettings: - this.props.onUserSettingsClose(); - handled = true; - break; - } - - break; - case KeyCode.UP: case KeyCode.DOWN: if (ev.altKey && !ev.shiftKey && !ev.ctrlKey && !ev.metaKey) { From 8695397abbe00d8a3d938580539929ff5f889a0c Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 17 May 2017 01:41:42 +0100 Subject: [PATCH 093/127] Support for pasting files into normal composer We don't seem to be in any danger of getting a working RTE any time soon, so implement file pasting in the normal composer too. --- src/components/views/rooms/MessageComposer.js | 10 +++++---- .../views/rooms/MessageComposerInput.js | 9 ++------ .../views/rooms/MessageComposerInputOld.js | 22 ++++++++++++++++++- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 0ee3c2082d..830d3f38ff 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -33,6 +33,7 @@ export default class MessageComposer extends React.Component { this.onHangupClick = this.onHangupClick.bind(this); this.onUploadClick = this.onUploadClick.bind(this); this.onUploadFileSelected = this.onUploadFileSelected.bind(this); + this.uploadFiles = this.uploadFiles.bind(this); this.onVoiceCallClick = this.onVoiceCallClick.bind(this); this.onInputContentChanged = this.onInputContentChanged.bind(this); this.onUpArrow = this.onUpArrow.bind(this); @@ -101,10 +102,11 @@ export default class MessageComposer extends React.Component { this.refs.uploadInput.click(); } - onUploadFileSelected(files, isPasted) { - if (!isPasted) - files = files.target.files; + onUploadFileSelected(files) { + this.uploadFiles(files.target.files); + } + uploadFiles(files) { let QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); let TintableSvg = sdk.getComponent("elements.TintableSvg"); @@ -310,7 +312,7 @@ export default class MessageComposer extends React.Component { tryComplete={this._tryComplete} onUpArrow={this.onUpArrow} onDownArrow={this.onDownArrow} - onUploadFileSelected={this.onUploadFileSelected} + onFilesPasted={this.uploadFiles} tabComplete={this.props.tabComplete} // used for old messagecomposerinput/tabcomplete onContentChanged={this.onInputContentChanged} onInputStateChanged={this.onInputStateChanged} />, diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index e2fcc19f67..af361db235 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -84,7 +84,6 @@ export default class MessageComposerInput extends React.Component { this.onAction = this.onAction.bind(this); this.handleReturn = this.handleReturn.bind(this); this.handleKeyCommand = this.handleKeyCommand.bind(this); - this.handlePastedFiles = this.handlePastedFiles.bind(this); this.onEditorContentChanged = this.onEditorContentChanged.bind(this); this.setEditorState = this.setEditorState.bind(this); this.onUpArrow = this.onUpArrow.bind(this); @@ -477,10 +476,6 @@ export default class MessageComposerInput extends React.Component { return false; } - handlePastedFiles(files) { - this.props.onUploadFileSelected(files, true); - } - handleReturn(ev) { if (ev.shiftKey) { this.onEditorContentChanged(RichUtils.insertSoftNewline(this.state.editorState)); @@ -734,7 +729,7 @@ export default class MessageComposerInput extends React.Component { keyBindingFn={MessageComposerInput.getKeyBinding} handleKeyCommand={this.handleKeyCommand} handleReturn={this.handleReturn} - handlePastedFiles={this.handlePastedFiles} + handlePastedFiles={this.props.onFilesPasted} stripPastedStyles={!this.state.isRichtextEnabled} onTab={this.onTab} onUpArrow={this.onUpArrow} @@ -764,7 +759,7 @@ MessageComposerInput.propTypes = { onDownArrow: React.PropTypes.func, - onUploadFileSelected: React.PropTypes.func, + onFilesPasted: React.PropTypes.func, // attempts to confirm currently selected completion, returns whether actually confirmed tryComplete: React.PropTypes.func, diff --git a/src/components/views/rooms/MessageComposerInputOld.js b/src/components/views/rooms/MessageComposerInputOld.js index 378644478c..adc6bc2c91 100644 --- a/src/components/views/rooms/MessageComposerInputOld.js +++ b/src/components/views/rooms/MessageComposerInputOld.js @@ -69,6 +69,9 @@ export default React.createClass({ // The text to use a placeholder in the input box placeholder: React.PropTypes.string.isRequired, + + // callback to handle files pasted into the composer + onFilesPasted: React.PropTypes.func, }, componentWillMount: function() { @@ -439,10 +442,27 @@ export default React.createClass({ this.refs.textarea.focus(); }, + _onPaste: function(ev) { + const items = ev.clipboardData.items; + const files = []; + for (const item of items) { + if (item.kind === 'file') { + files.push(item.getAsFile()); + } + } + if (files.length && this.props.onFilesPasted) { + this.props.onFilesPasted(files); + return true; + } + return false; + }, + render: function() { return (
-