From 76008e8abd3e89eda16d39260e93e570d44cff7f Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 12 Apr 2017 18:13:25 +0100
Subject: [PATCH 001/220] Remember and Recall window layout so that
position+size persist
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
electron/src/electron-main.js | 16 +++++++++++++++-
package.json | 1 +
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/electron/src/electron-main.js b/electron/src/electron-main.js
index 33b44ce9d1..8dd5e81333 100644
--- a/electron/src/electron-main.js
+++ b/electron/src/electron-main.js
@@ -30,6 +30,8 @@ const tray = require('./tray');
const VectorMenu = require('./vectormenu');
+const windowStateKeeper = require('electron-window-state');
+
let vectorConfig = {};
try {
vectorConfig = require('../../webapp/config.json');
@@ -186,11 +188,21 @@ electron.app.on('ready', () => {
process.platform == 'win32' ? 'ico' : 'png'
);
+ // Load the previous window state with fallback to defaults
+ let mainWindowState = windowStateKeeper({
+ defaultWidth: 1024,
+ defaultHeight: 768,
+ });
+
mainWindow = new electron.BrowserWindow({
icon: icon_path,
- width: 1024, height: 768,
show: false,
autoHideMenuBar: true,
+
+ x: mainWindowState.x,
+ y: mainWindowState.y,
+ width: mainWindowState.width,
+ height: mainWindowState.height,
});
mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`);
electron.Menu.setApplicationMenu(VectorMenu);
@@ -226,6 +238,8 @@ electron.app.on('ready', () => {
onLinkContextMenu(ev, params);
}
});
+
+ mainWindowState.manage(mainWindow);
});
electron.app.on('window-all-closed', () => {
diff --git a/package.json b/package.json
index 28cde3895a..35ffb87b78 100644
--- a/package.json
+++ b/package.json
@@ -96,6 +96,7 @@
"css-raw-loader": "^0.1.1",
"electron-builder": "^11.2.4",
"electron-builder-squirrel-windows": "^11.2.1",
+ "electron-window-state": "^4.1.0",
"emojione": "^2.2.7",
"eslint": "^3.14.0",
"eslint-config-google": "^0.7.1",
From 3fb54029d7dff8b66f48d6a50ce4ac92ed268373 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Thu, 13 Apr 2017 13:39:15 +0100
Subject: [PATCH 002/220] Fix packaged functionality Improve dependency
management for Electron main process deps
Dependencies in /electron/package.json will be installed through a script in /package.json and will be bundled via electron-builder
Does not affect standard webapp whatsoever
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
.gitignore | 1 +
electron/package.json | 6 ++++++
package.json | 11 ++++++-----
3 files changed, 13 insertions(+), 5 deletions(-)
create mode 100644 electron/package.json
diff --git a/.gitignore b/.gitignore
index c28df64c65..86baa127f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
/key.pem
/lib
/node_modules
+/electron/node_modules
/packages/
/webapp
/.npmrc
diff --git a/electron/package.json b/electron/package.json
new file mode 100644
index 0000000000..e6e7e2a42d
--- /dev/null
+++ b/electron/package.json
@@ -0,0 +1,6 @@
+{
+ "description": "Electron main process dependencies",
+ "dependencies": {
+ "electron-window-state": "^4.1.0"
+ }
+}
diff --git a/package.json b/package.json
index 35ffb87b78..dc1e3bea96 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"build": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle",
"build:dev": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle:dev",
"dist": "scripts/package.sh",
+ "postinstall": "cd electron && npm i",
"start:res": "node scripts/copy-res.js -w",
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress",
"start:js:prod": "NODE_ENV=production webpack-dev-server -w --progress",
@@ -96,7 +97,6 @@
"css-raw-loader": "^0.1.1",
"electron-builder": "^11.2.4",
"electron-builder-squirrel-windows": "^11.2.1",
- "electron-window-state": "^4.1.0",
"emojione": "^2.2.7",
"eslint": "^3.14.0",
"eslint-config-google": "^0.7.1",
@@ -145,6 +145,7 @@
"dereference": true,
"//files": "We bundle everything, so we only need to include webapp/",
"files": [
+ "electron/node_modules/**",
"electron/src/**",
"electron/img/**",
"webapp/**",
@@ -159,10 +160,10 @@
},
"win": {
"target": "squirrel"
+ },
+ "directories": {
+ "buildResources": "electron/build",
+ "output": "electron/dist"
}
- },
- "directories": {
- "buildResources": "electron/build",
- "output": "electron/dist"
}
}
From 20abb2c2dfd15eb339d9730589cf65fada4299cb Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 21 Apr 2017 13:01:10 +0100
Subject: [PATCH 003/220] Add Forward Message button to m.room.message events
Conform this file to eslint
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
.../views/context_menus/MessageContextMenu.js | 64 ++++++++++++-------
1 file changed, 41 insertions(+), 23 deletions(-)
diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js
index db416b8a06..4a6c978892 100644
--- a/src/components/views/context_menus/MessageContextMenu.js
+++ b/src/components/views/context_menus/MessageContextMenu.js
@@ -16,13 +16,13 @@ limitations under the License.
'use strict';
-var React = require('react');
+const React = require('react');
-var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
-var dis = require('matrix-react-sdk/lib/dispatcher');
-var sdk = require('matrix-react-sdk');
-var Modal = require('matrix-react-sdk/lib/Modal');
-var Resend = require("matrix-react-sdk/lib/Resend");
+const MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
+const dis = require('matrix-react-sdk/lib/dispatcher');
+const sdk = require('matrix-react-sdk');
+const Modal = require('matrix-react-sdk/lib/Modal');
+const Resend = require("matrix-react-sdk/lib/Resend");
import * as UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore';
module.exports = React.createClass({
@@ -45,7 +45,7 @@ module.exports = React.createClass({
},
onViewSourceClick: function() {
- var ViewSource = sdk.getComponent('structures.ViewSource');
+ const ViewSource = sdk.getComponent('structures.ViewSource');
Modal.createDialog(ViewSource, {
content: this.props.mxEvent.event,
}, 'mx_Dialog_viewsource');
@@ -70,12 +70,12 @@ module.exports = React.createClass({
MatrixClientPeg.get().redactEvent(
this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()
).catch(function(e) {
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
// display error message stating you couldn't delete this.
- var code = e.errcode || e.statusCode;
+ const code = e.errcode || e.statusCode;
Modal.createDialog(ErrorDialog, {
title: "Error",
- description: "You cannot delete this message. (" + code + ")"
+ description: "You cannot delete this message. (" + code + ")",
});
}).done();
},
@@ -88,6 +88,14 @@ module.exports = React.createClass({
if (this.props.onFinished) this.props.onFinished();
},
+ onForwardClick: function() {
+ dis.dispatch({
+ action: 'forward_message',
+ content: this.props.mxEvent.getContent(),
+ });
+ this.closeMenu();
+ },
+
closeMenu: function() {
if (this.props.onFinished) this.props.onFinished();
},
@@ -99,7 +107,7 @@ module.exports = React.createClass({
if (this.props.onFinished) this.props.onFinished();
},
- onQuoteClick: function () {
+ onQuoteClick: function() {
console.log(this.props.mxEvent);
dis.dispatch({
action: 'quote',
@@ -108,15 +116,16 @@ module.exports = React.createClass({
},
render: function() {
- var eventStatus = this.props.mxEvent.status;
- var resendButton;
- var viewSourceButton;
- var viewClearSourceButton;
- var redactButton;
- var cancelButton;
- var permalinkButton;
- var unhidePreviewButton;
- var externalURLButton;
+ const eventStatus = this.props.mxEvent.status;
+ let resendButton;
+ let redactButton;
+ let cancelButton;
+ let forwardButton;
+ let viewSourceButton;
+ let viewClearSourceButton;
+ let unhidePreviewButton;
+ let permalinkButton;
+ let externalURLButton;
if (eventStatus === 'not_sent') {
resendButton = (
@@ -142,6 +151,14 @@ module.exports = React.createClass({
);
}
+ if (this.props.mxEvent.getType() === 'm.room.message') {
+ forwardButton = (
+
+ Forward Message
+
+ );
+ }
+
viewSourceButton = (
View Source
@@ -162,7 +179,7 @@ module.exports = React.createClass({
Unhide Preview
- )
+ );
}
}
@@ -185,7 +202,7 @@ module.exports = React.createClass({
externalURLButton = (
Source URL
+ rel="noopener" target="_blank" onClick={ this.closeMenu }>Source URL
);
}
@@ -196,6 +213,7 @@ module.exports = React.createClass({
{resendButton}
{redactButton}
{cancelButton}
+ {forwardButton}
{viewSourceButton}
{viewClearSourceButton}
{unhidePreviewButton}
@@ -204,5 +222,5 @@ module.exports = React.createClass({
{externalURLButton}
);
- }
+ },
});
From 77ce58b59d8e382568cf436f5eeaef56d6a495f6 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 21 Apr 2017 12:58:43 +0100
Subject: [PATCH 004/220] add .idea to .gitignore so I don't accidentally push
my IDE config
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index c28df64c65..c9e9b250be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@
npm-debug.log
electron/dist
electron/pub
+/.idea
From 9747836a4dccf6d913ad9ae3e15eb9e5c7951a6a Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:24:29 +0100
Subject: [PATCH 005/220] Update react-sdk and js-sdk dependencies
---
package.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/package.json b/package.json
index 8bdb2ba0f4..2341734587 100644
--- a/package.json
+++ b/package.json
@@ -62,8 +62,8 @@
"gfm.css": "^1.1.1",
"highlight.js": "^9.0.0",
"linkifyjs": "^2.1.3",
- "matrix-js-sdk": "0.7.6",
- "matrix-react-sdk": "0.8.7",
+ "matrix-js-sdk": "0.7.7-rc.1",
+ "matrix-react-sdk": "0.8.8-rc.1",
"modernizr": "^3.1.0",
"q": "^1.4.1",
"react": "^15.4.0",
From b5a5b472c482754b38a98f63c323ce637d2d0d9f Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:26:29 +0100
Subject: [PATCH 006/220] Prepare changelog for v0.9.9-rc.1
---
CHANGELOG.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a2ed314978..bde4dbd168 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
+====================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
+
+ * Update js-sdk and matrix-react-sdk to fix registration without a captcha (https://github.com/vector-im/riot-web/issues/3621)
+
+
Changes in [0.9.8](https://github.com/vector-im/riot-web/releases/tag/v0.9.8) (2017-04-12)
==========================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8-rc.3...v0.9.8)
From eec0c274d260f1f4e067558f980bb4c89fc9875f Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:26:29 +0100
Subject: [PATCH 007/220] v0.9.9-rc.1
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 2341734587..d58b7f22ad 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
- "version": "0.9.8",
+ "version": "0.9.9-rc.1",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
From ca6d9063fdef52022e53ff6e3c2d314abc742e22 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:32:55 +0100
Subject: [PATCH 008/220] Back up release version to try again
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index d58b7f22ad..7ec84667b9 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
- "version": "0.9.9-rc.1",
+ "version": "0.9.9",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
From f25612198efb930348e2bf077a86a0ca1fb446f5 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:33:53 +0100
Subject: [PATCH 009/220] 0.9.8, not 0.9.9
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 7ec84667b9..2341734587 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
- "version": "0.9.9",
+ "version": "0.9.8",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
From d0c0eeac0aac27a7ccaba978a52b6cd924cb191b Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:35:14 +0100
Subject: [PATCH 010/220] Prepare changelog for v0.9.9-rc.1
---
CHANGELOG.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bde4dbd168..4be99030f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
+====================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
+
+
Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
From 95647fb7a1c18533271668d95dc6376e0a1c3445 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:35:15 +0100
Subject: [PATCH 011/220] v0.9.9-rc.1
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 2341734587..d58b7f22ad 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
- "version": "0.9.8",
+ "version": "0.9.9-rc.1",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
From ce5a7ba48aac244225604c1a8e007d03a1e67750 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:39:11 +0100
Subject: [PATCH 012/220] Rewind version to try again, again
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index d58b7f22ad..2341734587 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
- "version": "0.9.9-rc.1",
+ "version": "0.9.8",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
From 8aed52ece990254efc000712638a7d2f895ff1a9 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:40:24 +0100
Subject: [PATCH 013/220] Prepare changelog for v0.9.9-rc.1
---
CHANGELOG.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4be99030f1..0145dec622 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,11 @@ Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
+Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
+====================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
+
+
Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
From 141aafd18e0962fc791bf6413124a5e6f5bfc12f Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 21 Apr 2017 18:40:25 +0100
Subject: [PATCH 014/220] v0.9.9-rc.1
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 2341734587..d58b7f22ad 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
- "version": "0.9.8",
+ "version": "0.9.9-rc.1",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
From 2139fb74bbbd3c7f1865efd49342029939393584 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Sun, 23 Apr 2017 09:56:43 +0100
Subject: [PATCH 015/220] change show logic to same as that of the tray icon
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
src/vector/platform/ElectronPlatform.js | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/vector/platform/ElectronPlatform.js b/src/vector/platform/ElectronPlatform.js
index b0928a8f41..21d324a49b 100644
--- a/src/vector/platform/ElectronPlatform.js
+++ b/src/vector/platform/ElectronPlatform.js
@@ -106,13 +106,14 @@ export default class ElectronPlatform extends VectorBasePlatform {
notification.onclick = function() {
dis.dispatch({
action: 'view_room',
- room_id: room.roomId
+ room_id: room.roomId,
});
global.focus();
- const currentWin = electron.remote.getCurrentWindow();
- currentWin.show();
- currentWin.restore();
- currentWin.focus();
+ const win = electron.remote.getCurrentWindow();
+
+ if (win.isMinimized()) win.restore();
+ else if (!win.isVisible()) win.show();
+ else win.focus();
};
return notification;
From b3c9229aeeae48620a1a8164dc1f1eb1cdef8cfb Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Sun, 23 Apr 2017 09:59:00 +0100
Subject: [PATCH 016/220] DRY code and change double quotes to single
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
src/vector/platform/ElectronPlatform.js | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/vector/platform/ElectronPlatform.js b/src/vector/platform/ElectronPlatform.js
index 21d324a49b..9c857e3524 100644
--- a/src/vector/platform/ElectronPlatform.js
+++ b/src/vector/platform/ElectronPlatform.js
@@ -24,12 +24,12 @@ import q from 'q';
const electron = require('electron');
const remote = electron.remote;
-electron.remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
+remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
function onUpdateDownloaded(ev, releaseNotes, ver, date, updateURL) {
dis.dispatch({
action: 'new_version',
- currentVersion: electron.remote.app.getVersion(),
+ currentVersion: remote.app.getVersion(),
newVersion: ver,
releaseNotes: releaseNotes,
});
@@ -68,7 +68,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
try {
remote.app.setBadgeCount(count);
} catch (e) {
- console.error("Failed to set notification count", e);
+ console.error('Failed to set notification count', e);
}
}
@@ -89,7 +89,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
// we only have to strip out < and > as the spec doesn't include anything about things like &
// so we shouldn't assume that all implementations will treat those properly. Very basic tag parsing is done.
if (window.process.platform === 'linux') {
- msg = msg.replace(//g, ">");
+ msg = msg.replace(//g, '>');
}
// Notifications in Electron use the HTML5 notification API
@@ -98,7 +98,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
{
body: msg,
icon: avatarUrl,
- tag: "vector",
+ tag: 'vector',
silent: true, // we play our own sounds
}
);
@@ -109,7 +109,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
room_id: room.roomId,
});
global.focus();
- const win = electron.remote.getCurrentWindow();
+ const win = remote.getCurrentWindow();
if (win.isMinimized()) win.restore();
else if (!win.isVisible()) win.show();
@@ -124,7 +124,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
getAppVersion() {
- return q(electron.remote.app.getVersion());
+ return q(remote.app.getVersion());
}
pollForUpdate() {
@@ -141,7 +141,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
getDefaultDeviceDisplayName() {
- return "Riot Desktop on " + platformFriendlyName();
+ return 'Riot Desktop on ' + platformFriendlyName();
}
screenCaptureErrorString() {
@@ -153,6 +153,6 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
reload() {
- electron.remote.getCurrentWebContents().reload();
+ remote.getCurrentWebContents().reload();
}
}
From 9e2324fb69342897d3a95fa4bf8a9d95dae66be0 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Sun, 23 Apr 2017 22:50:58 +0100
Subject: [PATCH 017/220] don't hook on postinstall, current dev cycle uses
(abuses) npm i to build so no point making it take longer than it has to for
the devs only testing webapp
build:electron - hook npm run install:electron
install:electron - run npm i for the electron deps
electron - start the app locally for testing
add to README
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
README.md | 1 +
package.json | 5 +++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 2d7ab81b8a..7bef64783d 100644
--- a/README.md
+++ b/README.md
@@ -135,6 +135,7 @@ To run as a desktop app:
```
npm install electron
+ npm run install:electron
node_modules/.bin/electron .
```
diff --git a/package.json b/package.json
index dc1e3bea96..a64d0d9ea3 100644
--- a/package.json
+++ b/package.json
@@ -32,11 +32,12 @@
"build:compile": "babel --source-maps -d lib src",
"build:bundle": "NODE_ENV=production webpack -p --progress",
"build:bundle:dev": "webpack --optimize-occurence-order --progress",
- "build:electron": "npm run clean && npm run build && build -wml --ia32 --x64",
+ "build:electron": "npm run clean && npm run build && npm run install:electron && build -wml --ia32 --x64",
"build": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle",
"build:dev": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle:dev",
"dist": "scripts/package.sh",
- "postinstall": "cd electron && npm i",
+ "install:electron": "cd electron && npm i",
+ "electron": "npm run install:electron && electron .",
"start:res": "node scripts/copy-res.js -w",
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress",
"start:js:prod": "NODE_ENV=production webpack-dev-server -w --progress",
From c067800a4fa4a32d809e685a0df72c69c345505a Mon Sep 17 00:00:00 2001
From: Luke Barnard
Date: Mon, 24 Apr 2017 10:00:39 +0100
Subject: [PATCH 018/220] Disable dropdown highlight on focus
---
.../css/matrix-react-sdk/views/elements/_Dropdown.scss | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_Dropdown.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_Dropdown.scss
index 1f9cbb63dd..26fe3792e8 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/elements/_Dropdown.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_Dropdown.scss
@@ -31,6 +31,11 @@ limitations under the License.
border-color: $accent-color;
}
+/* Disable dropdown highlight on focus */
+.mx_Dropdown_input.mx_AccessibleButton:focus {
+ filter: none;
+}
+
.mx_Dropdown_arrow {
border-color: $primary-fg-color transparent transparent;
border-style: solid;
From 61bba6c31f060df4e78ff314bb1b614494530d3c Mon Sep 17 00:00:00 2001
From: turt2live
Date: Mon, 24 Apr 2017 08:44:53 -0600
Subject: [PATCH 019/220] CSS to make h1 and h2 the same size as h1.
Addresses #1772
Signed-off-by: Travis Ralston
---
.../css/matrix-react-sdk/views/rooms/_EventTile.scss | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
index 4f01aeeee7..5adf016f05 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
@@ -331,6 +331,14 @@ limitations under the License.
font-family: inherit ! important;
}
+
+/* Make h1 and h2 the same size as h3. */
+.mx_EventTile_content .markdown-body h1,
+.mx_EventTile_content .markdown-body h2
+{
+ font-size: 1.5em;
+}
+
.mx_EventTile_content .markdown-body a {
color: $accent-color;
}
From 69f5833c9f648ea1a9497336b4124974e23847b7 Mon Sep 17 00:00:00 2001
From: Luke Barnard
Date: Mon, 24 Apr 2017 16:05:10 +0100
Subject: [PATCH 020/220] Prevent long room names/topics from pushing UI of the
screen
This was causing the "save" button in RoomSettings to be obscured when room names were set to long strings without spaces
Fixes https://github.com/vector-im/riot-web/issues/1729
---
.../vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss
index 4affc99490..5150d8cfdd 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss
@@ -31,6 +31,7 @@ limitations under the License.
margin-left: -2px;
order: 1;
flex: 1;
+ overflow: hidden;
}
.mx_RoomHeader_spinner {
From 1701ea43a4109efcad0d9381bbeda6248abd486e Mon Sep 17 00:00:00 2001
From: David Baker
Date: Mon, 24 Apr 2017 18:22:23 +0100
Subject: [PATCH 021/220] Remove spurious changelog entries
---
CHANGELOG.md | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0145dec622..bde4dbd168 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,13 +1,3 @@
-Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
-====================================================================================================
-[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
-
-
-Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
-====================================================================================================
-[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
-
-
Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
From b6435502fc6c84f84c82e9355815670dfdb03ad8 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Mon, 24 Apr 2017 18:25:13 +0100
Subject: [PATCH 022/220] New version of react-sdk
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index d58b7f22ad..2584954eda 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
"highlight.js": "^9.0.0",
"linkifyjs": "^2.1.3",
"matrix-js-sdk": "0.7.7-rc.1",
- "matrix-react-sdk": "0.8.8-rc.1",
+ "matrix-react-sdk": "0.8.8-rc.2",
"modernizr": "^3.1.0",
"q": "^1.4.1",
"react": "^15.4.0",
From 7f2fa09d4c7df9c375cbeab60c4627f85236921b Mon Sep 17 00:00:00 2001
From: David Baker
Date: Mon, 24 Apr 2017 18:26:19 +0100
Subject: [PATCH 023/220] Prepare changelog for v0.9.9-rc.2
---
CHANGELOG.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bde4dbd168..71210db3a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+Changes in [0.9.9-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.2) (2017-04-24)
+====================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.9-rc.1...v0.9.9-rc.2)
+
+ * Fix bug where links to Riot would fail to open.
+
+
Changes in [0.9.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.1) (2017-04-21)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8...v0.9.9-rc.1)
From 5326faa0b805c536be19cafc9c134a4b154891a8 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Mon, 24 Apr 2017 18:26:20 +0100
Subject: [PATCH 024/220] v0.9.9-rc.2
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 2584954eda..835a27f136 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
- "version": "0.9.9-rc.1",
+ "version": "0.9.9-rc.2",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
From 92b52a61e71f808a65afc0e4d93aa9a08f5a022b Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Mon, 24 Apr 2017 18:33:25 +0100
Subject: [PATCH 025/220] don't show forward option for things we cannot
decrypt
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
src/components/views/context_menus/MessageContextMenu.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js
index 4a6c978892..5de8d18d72 100644
--- a/src/components/views/context_menus/MessageContextMenu.js
+++ b/src/components/views/context_menus/MessageContextMenu.js
@@ -151,7 +151,8 @@ module.exports = React.createClass({
);
}
- if (this.props.mxEvent.getType() === 'm.room.message') {
+ if (this.props.mxEvent.getType() === 'm.room.message'
+ && this.props.mxEvent.getContent().msgtype !== 'm.bad.encrypted') {
forwardButton = (
Forward Message
From 0a1ebc2487cf3f85f017b93f21088215136342a2 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Mon, 24 Apr 2017 22:43:02 +0100
Subject: [PATCH 026/220] Don't show for anything that doesn't have a msgtype
and body otherwise the server will just reject it anyway
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
.../views/context_menus/MessageContextMenu.js | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js
index 5de8d18d72..002ec5bccc 100644
--- a/src/components/views/context_menus/MessageContextMenu.js
+++ b/src/components/views/context_menus/MessageContextMenu.js
@@ -151,13 +151,17 @@ module.exports = React.createClass({
);
}
- if (this.props.mxEvent.getType() === 'm.room.message'
- && this.props.mxEvent.getContent().msgtype !== 'm.bad.encrypted') {
- forwardButton = (
-
- Forward Message
-
- );
+ if (this.props.mxEvent.getType() === 'm.room.message') {
+ const content = this.props.mxEvent.getContent();
+ if (content.msgtype // truthy check msgtype
+ && content.msgtype !== 'm.bad.encrypted'
+ && content.hasOwnProperty('body')) {
+ forwardButton = (
+
+ Forward Message
+
+ );
+ }
}
viewSourceButton = (
From 4dd6ee681d3032f7d7a3d58e8a88ea07017e420f Mon Sep 17 00:00:00 2001
From: Matthew Hodgson
Date: Tue, 25 Apr 2017 00:14:18 +0100
Subject: [PATCH 027/220] fix /config.json in .gitignore
---
.gitignore | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 0978bc5676..c5826b78d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,4 @@
npm-debug.log
electron/dist
electron/pub
-config.json
+/config.json
From e24ef2bb5cbbcaa8a4541465b98a7f0793200979 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Tue, 25 Apr 2017 10:18:17 +0100
Subject: [PATCH 028/220] Warn when exiting due to single-instance
This lost me a fair bit of time trying to figure out why Riot was
starting and then immediately quitting.
---
electron/src/electron-main.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/electron/src/electron-main.js b/electron/src/electron-main.js
index e6ffffac9b..a1fc9c1a6d 100644
--- a/electron/src/electron-main.js
+++ b/electron/src/electron-main.js
@@ -171,6 +171,7 @@ const shouldQuit = electron.app.makeSingleInstance((commandLine, workingDirector
});
if (shouldQuit) {
+ console.log("Other instance detected: exiting");
electron.app.quit()
}
From 2d311ddbf4ea1848a0374e6ba288897652dcc746 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Tue, 25 Apr 2017 11:04:03 +0100
Subject: [PATCH 029/220] Released js-sdk & react-sdk
---
package.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/package.json b/package.json
index 835a27f136..ba875972c1 100644
--- a/package.json
+++ b/package.json
@@ -62,8 +62,8 @@
"gfm.css": "^1.1.1",
"highlight.js": "^9.0.0",
"linkifyjs": "^2.1.3",
- "matrix-js-sdk": "0.7.7-rc.1",
- "matrix-react-sdk": "0.8.8-rc.2",
+ "matrix-js-sdk": "0.7.7",
+ "matrix-react-sdk": "0.8.8",
"modernizr": "^3.1.0",
"q": "^1.4.1",
"react": "^15.4.0",
From 6fd64d19f0f95e9c009056ea8a3212015bf38b1c Mon Sep 17 00:00:00 2001
From: David Baker
Date: Tue, 25 Apr 2017 11:08:07 +0100
Subject: [PATCH 030/220] Prepare changelog for v0.9.9
---
CHANGELOG.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71210db3a9..ea63ee66a0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+Changes in [0.9.9](https://github.com/vector-im/riot-web/releases/tag/v0.9.9) (2017-04-25)
+==========================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.9-rc.2...v0.9.9)
+
+ * No changes
+
+
Changes in [0.9.9-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.9.9-rc.2) (2017-04-24)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.9-rc.1...v0.9.9-rc.2)
From aa482bae2857215619094c698f497b4c05de3127 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Tue, 25 Apr 2017 11:08:08 +0100
Subject: [PATCH 031/220] v0.9.9
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index ba875972c1..340ee80560 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron/src/electron-main.js",
- "version": "0.9.9-rc.2",
+ "version": "0.9.9",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
From 78cabed0bfb9d9815dce54707bf615cd7ae5f50a Mon Sep 17 00:00:00 2001
From: Luke Barnard
Date: Tue, 25 Apr 2017 16:24:00 +0100
Subject: [PATCH 032/220] Modify CSS for matrix-org/matrix-react-sdk#833
---
.../structures/_UserSettings.scss | 9 ++++++++
.../structures/login/_Login.scss | 22 ++++++-------------
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
index 9f33e1bcc2..739ac88ab9 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
@@ -176,6 +176,15 @@ limitations under the License.
cursor: pointer;
}
+.mx_UserSettings_phoneSection {
+ display:table;
+}
+
+.mx_UserSettings_phoneCountry {
+ width: 70px;
+ display: table-cell;
+}
+
input.mx_UserSettings_phoneNumberField {
margin-left: 3px;
width: 172px;
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss b/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss
index 124304802a..93173ed336 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss
@@ -179,11 +179,11 @@ limitations under the License.
align-self: flex-end;
}
-.mx_Login_username_group {
+.mx_Login_field_group {
display: flex;
}
-.mx_Login_username_prefix {
+.mx_Login_field_prefix {
height: 33px;
padding: 0px 5px;
line-height: 33px;
@@ -196,7 +196,7 @@ limitations under the License.
text-align: center;
}
-.mx_Login_username_suffix {
+.mx_Login_field_suffix {
height: 33px;
padding: 0px 5px;
line-height: 33px;
@@ -214,7 +214,9 @@ limitations under the License.
flex-shrink: 1;
min-width: 0px;
border-radius: 3px;
- /* The "@" is always prefixed, so no rounded corners */
+}
+
+.mx_Login_field_has_prefix {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
@@ -224,13 +226,8 @@ limitations under the License.
border-bottom-right-radius: 0px;
}
-.mx_Login_phoneSection {
- display: table;
-}
-
.mx_Login_phoneCountry {
- display: table-cell;
- width: 70px;
+ margin-bottom: 14px;
}
.mx_Login_phoneCountry .mx_Dropdown_option {
@@ -246,8 +243,3 @@ limitations under the License.
margin: 4px;
vertical-align: top;
}
-
-.mx_Login_phoneNumberField {
- width: 210px;
- margin-left: 3px;
-}
From 7b3719bc3c8056660144ef61c180e9f4373c3ae6 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Wed, 26 Apr 2017 16:27:25 +0100
Subject: [PATCH 033/220] Remove unused `placeholder` prop on RoomDropTarget
---
src/components/views/rooms/RoomDropTarget.js | 20 ++++++-------------
.../views/rooms/_RoomDropTarget.scss | 5 -----
2 files changed, 6 insertions(+), 19 deletions(-)
diff --git a/src/components/views/rooms/RoomDropTarget.js b/src/components/views/rooms/RoomDropTarget.js
index 1c5eb3c115..f5ca4f015d 100644
--- a/src/components/views/rooms/RoomDropTarget.js
+++ b/src/components/views/rooms/RoomDropTarget.js
@@ -22,20 +22,12 @@ module.exports = React.createClass({
displayName: 'RoomDropTarget',
render: function() {
- if (this.props.placeholder) {
- return (
-
+ return (
+
+
+ { this.props.label }
- );
- }
- else {
- return (
-
-
- { this.props.label }
-
-
- );
- }
+
+ );
}
});
diff --git a/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss b/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss
index e0a50a95c7..08229e377b 100644
--- a/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss
+++ b/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss
@@ -33,11 +33,6 @@ limitations under the License.
margin-left: 10px;
}
-.mx_RoomDropTarget_placeholder {
- padding-top: 1px;
- padding-bottom: 1px;
-}
-
.mx_RoomDropTarget_label {
position: relative;
margin-top: 3px;
From 44d0e7dcba2c2261be9b3730f0000b49b357d4a6 Mon Sep 17 00:00:00 2001
From: Luke Barnard
Date: Wed, 26 Apr 2017 18:00:51 +0100
Subject: [PATCH 034/220] Fix emote RRs alignment
---
.../vector/css/matrix-react-sdk/views/rooms/_EventTile.scss | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
index 5adf016f05..cbd7142285 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
@@ -218,8 +218,8 @@ limitations under the License.
}
.mx_EventTile_continuation .mx_EventTile_readAvatars,
-.mx_EventTile_info .mx_EventTile_readAvatars
-{
+.mx_EventTile_info .mx_EventTile_readAvatars,
+.mx_EventTile_emote .mx_EventTile_readAvatars {
top: 7px;
}
From e6f694307d7ee176fdda81722766cabe234fa3a9 Mon Sep 17 00:00:00 2001
From: Luke Barnard
Date: Thu, 27 Apr 2017 16:46:14 +0100
Subject: [PATCH 035/220] add word-break to RoomDirectory
---
src/skins/vector/css/vector-web/structures/_RoomDirectory.scss | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss b/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss
index 6e508ec78f..4acdd244c6 100644
--- a/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss
+++ b/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss
@@ -21,6 +21,7 @@ limitations under the License.
margin-right: auto;
margin-bottom: 12px;
color: $primary-fg-color;
+ word-break: break-word;
display: flex;
From afb4b79d81e3159c4d9507874a64acc1629cb560 Mon Sep 17 00:00:00 2001
From: Luke Barnard
Date: Thu, 27 Apr 2017 18:04:41 +0100
Subject: [PATCH 036/220] Improve Room Directory Look & Feel
By adding an icon next to the title.
Requires https://github.com/matrix-org/matrix-react-sdk/pull/848
---
src/components/structures/RoomDirectory.js | 2 +-
.../css/matrix-react-sdk/views/rooms/_RoomHeader.scss | 6 ++++++
.../vector/css/vector-web/structures/_RoomDirectory.scss | 4 ++++
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index f8a3d9e981..cdf8d19e55 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -548,7 +548,7 @@ module.exports = React.createClass({
const DirectorySearchBox = sdk.getComponent('elements.DirectorySearchBox');
return (
-
+
Date: Wed, 26 Apr 2017 19:00:07 +0100
Subject: [PATCH 037/220] Make left panel more friendly to new users
https://github.com/vector-im/riot-web/issues/3609
---
src/components/structures/RoomSubList.js | 14 +++++++-----
.../views/rooms/_RoomList.scss | 22 +++++++++++++++++++
2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index 577dac9c8f..fde35b129f 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -82,6 +82,7 @@ var RoomSubList = React.createClass({
incomingCall: React.PropTypes.object,
onShowMoreRooms: React.PropTypes.func,
searchFilter: React.PropTypes.string,
+ emptyContent: React.PropTypes.node, // content shown if the list is empty
},
getInitialState: function() {
@@ -468,16 +469,18 @@ var RoomSubList = React.createClass({
render: function() {
var connectDropTarget = this.props.connectDropTarget;
- var RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget');
var TruncatedList = sdk.getComponent('elements.TruncatedList');
var label = this.props.collapsed ? null : this.props.label;
//console.log("render: " + JSON.stringify(this.state.sortedList));
- var target;
- if (this.state.sortedList.length == 0 && this.props.editable) {
- target = ;
+ let content;
+ if (this.state.sortedList.length == 0) {
+ //content = ;
+ content = this.props.emptyContent;
+ } else {
+ content = this.makeRoomTiles();
}
var roomCount = this.props.list.length > 0 ? this.props.list.length : '';
@@ -497,8 +500,7 @@ var RoomSubList = React.createClass({
if (!this.state.hidden) {
subList =
- { target }
- { this.makeRoomTiles() }
+ { content }
;
}
else {
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
index 110dcd5b6b..bc699ae792 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2107 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.
@@ -37,3 +38,24 @@ limitations under the License.
.mx_RoomList_scrollbar .gm-scrollbar.-vertical {
z-index: 6;
}
+
+.mx_RoomList_greyedSubListLabel {
+ color: #a2a2a2;
+}
+
+.mx_RoomList_emptySubListTip {
+ font-size: 13px;
+ margin-left: 18px;
+ margin-right: 18px;
+ margin-top: 8px;
+ margin-bottom: 7px;
+ padding: 5px;
+ border: 1px solid $accent-color;
+ color: $primary-fg-color;
+ background-color: $droptarget-bg-color;
+ border-radius: 4px;
+}
+
+.mx_RoomList_butonPreview {
+ float: right;
+}
From 73fb2c859e2c60d843eb9107fd0d200b06520ee3 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 28 Apr 2017 11:20:55 +0100
Subject: [PATCH 038/220] Remove now-redundant grey CSS
---
.../vector/css/matrix-react-sdk/views/rooms/_RoomList.scss | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
index bc699ae792..e51b64f0c4 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
@@ -39,10 +39,6 @@ limitations under the License.
z-index: 6;
}
-.mx_RoomList_greyedSubListLabel {
- color: #a2a2a2;
-}
-
.mx_RoomList_emptySubListTip {
font-size: 13px;
margin-left: 18px;
From 4eb0ca63a9e4cc12fb3131a57edccb7dc580fdc4 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 28 Apr 2017 11:22:05 +0100
Subject: [PATCH 039/220] Revert commits acciderntally put on develop
---
src/components/structures/RoomSubList.js | 14 ++++++--------
.../views/rooms/_RoomList.scss | 18 ------------------
2 files changed, 6 insertions(+), 26 deletions(-)
diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index fde35b129f..577dac9c8f 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -82,7 +82,6 @@ var RoomSubList = React.createClass({
incomingCall: React.PropTypes.object,
onShowMoreRooms: React.PropTypes.func,
searchFilter: React.PropTypes.string,
- emptyContent: React.PropTypes.node, // content shown if the list is empty
},
getInitialState: function() {
@@ -469,18 +468,16 @@ var RoomSubList = React.createClass({
render: function() {
var connectDropTarget = this.props.connectDropTarget;
+ var RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget');
var TruncatedList = sdk.getComponent('elements.TruncatedList');
var label = this.props.collapsed ? null : this.props.label;
//console.log("render: " + JSON.stringify(this.state.sortedList));
- let content;
- if (this.state.sortedList.length == 0) {
- //content = ;
- content = this.props.emptyContent;
- } else {
- content = this.makeRoomTiles();
+ var target;
+ if (this.state.sortedList.length == 0 && this.props.editable) {
+ target = ;
}
var roomCount = this.props.list.length > 0 ? this.props.list.length : '';
@@ -500,7 +497,8 @@ var RoomSubList = React.createClass({
if (!this.state.hidden) {
subList =
- { content }
+ { target }
+ { this.makeRoomTiles() }
;
}
else {
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
index e51b64f0c4..110dcd5b6b 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
@@ -1,6 +1,5 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
-Copyright 2107 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.
@@ -38,20 +37,3 @@ limitations under the License.
.mx_RoomList_scrollbar .gm-scrollbar.-vertical {
z-index: 6;
}
-
-.mx_RoomList_emptySubListTip {
- font-size: 13px;
- margin-left: 18px;
- margin-right: 18px;
- margin-top: 8px;
- margin-bottom: 7px;
- padding: 5px;
- border: 1px solid $accent-color;
- color: $primary-fg-color;
- background-color: $droptarget-bg-color;
- border-radius: 4px;
-}
-
-.mx_RoomList_butonPreview {
- float: right;
-}
From 96c867b34bbee417620ffbdb38a14585528198d4 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Wed, 26 Apr 2017 19:00:07 +0100
Subject: [PATCH 040/220] Make left panel more friendly to new users
https://github.com/vector-im/riot-web/issues/3609
---
src/components/structures/RoomSubList.js | 14 +++++++-----
.../views/rooms/_RoomList.scss | 22 +++++++++++++++++++
2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index 577dac9c8f..fde35b129f 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -82,6 +82,7 @@ var RoomSubList = React.createClass({
incomingCall: React.PropTypes.object,
onShowMoreRooms: React.PropTypes.func,
searchFilter: React.PropTypes.string,
+ emptyContent: React.PropTypes.node, // content shown if the list is empty
},
getInitialState: function() {
@@ -468,16 +469,18 @@ var RoomSubList = React.createClass({
render: function() {
var connectDropTarget = this.props.connectDropTarget;
- var RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget');
var TruncatedList = sdk.getComponent('elements.TruncatedList');
var label = this.props.collapsed ? null : this.props.label;
//console.log("render: " + JSON.stringify(this.state.sortedList));
- var target;
- if (this.state.sortedList.length == 0 && this.props.editable) {
- target = ;
+ let content;
+ if (this.state.sortedList.length == 0) {
+ //content = ;
+ content = this.props.emptyContent;
+ } else {
+ content = this.makeRoomTiles();
}
var roomCount = this.props.list.length > 0 ? this.props.list.length : '';
@@ -497,8 +500,7 @@ var RoomSubList = React.createClass({
if (!this.state.hidden) {
subList =
- { target }
- { this.makeRoomTiles() }
+ { content }
;
}
else {
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
index 110dcd5b6b..bc699ae792 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2107 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.
@@ -37,3 +38,24 @@ limitations under the License.
.mx_RoomList_scrollbar .gm-scrollbar.-vertical {
z-index: 6;
}
+
+.mx_RoomList_greyedSubListLabel {
+ color: #a2a2a2;
+}
+
+.mx_RoomList_emptySubListTip {
+ font-size: 13px;
+ margin-left: 18px;
+ margin-right: 18px;
+ margin-top: 8px;
+ margin-bottom: 7px;
+ padding: 5px;
+ border: 1px solid $accent-color;
+ color: $primary-fg-color;
+ background-color: $droptarget-bg-color;
+ border-radius: 4px;
+}
+
+.mx_RoomList_butonPreview {
+ float: right;
+}
From 67efb8bde264e3ea0823e40558d29dd89120c0c9 Mon Sep 17 00:00:00 2001
From: Matthew Hodgson
Date: Sat, 29 Apr 2017 00:00:29 +0100
Subject: [PATCH 041/220] Add date tooltip to timestamps
---
src/components/views/messages/MessageTimestamp.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/views/messages/MessageTimestamp.js b/src/components/views/messages/MessageTimestamp.js
index dda87767a6..ab910b05ab 100644
--- a/src/components/views/messages/MessageTimestamp.js
+++ b/src/components/views/messages/MessageTimestamp.js
@@ -25,7 +25,7 @@ module.exports = React.createClass({
render: function() {
var date = new Date(this.props.ts);
return (
-
+
{ DateUtils.formatTime(date) }
);
From 4a8ad53bd956866dbd413b24f5d820d352a34186 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@googlemail.com>
Date: Sun, 30 Apr 2017 13:11:01 +0100
Subject: [PATCH 042/220] Pin filesize ver to fix break upstream
https://travis-ci.org/vector-im/riot-web/builds/227340622
avoidwork/filesize.js#87
3.5.7 and 3.5.8 ver released <24h ago and broke stuff for us
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 843b69dc19..a25e17955f 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,7 @@
"draft-js": "^0.8.1",
"extract-text-webpack-plugin": "^0.9.1",
"favico.js": "^0.3.10",
- "filesize": "^3.1.2",
+ "filesize": "3.5.6",
"flux": "~2.0.3",
"gfm.css": "^1.1.1",
"highlight.js": "^9.0.0",
From 61c338a23358f340008f63a2b193d18e59529b87 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 2 May 2017 21:24:02 +0100
Subject: [PATCH 043/220] remove leading v in /version file so its semver and
also then consistent with electron versioning
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
scripts/package.sh | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/scripts/package.sh b/scripts/package.sh
index 5c1fdd5e36..b3bc00bf03 100755
--- a/scripts/package.sh
+++ b/scripts/package.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
set -e
@@ -22,7 +22,14 @@ cp config.sample.json webapp/
mkdir -p dist
cp -r webapp vector-$version
-echo $version > vector-$version/version
+
+# if $version looks like semver with leading v, strip it before writing to file
+if [[ ${version} =~ ^v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+(-.+)?$ ]]; then
+ echo ${version:1} > vector-$version/version
+else
+ echo ${version} > vector-$version/version
+fi
+
tar chvzf dist/vector-$version.tar.gz vector-$version
rm -r vector-$version
From 6367344181d4312fb0d18b89a3c022ee5da9ae94 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 2 May 2017 21:29:19 +0100
Subject: [PATCH 044/220] tidy and fix flow notation
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
src/vector/platform/ElectronPlatform.js | 22 ++++++-------
src/vector/platform/VectorBasePlatform.js | 2 +-
src/vector/platform/WebPlatform.js | 39 +++++++++++------------
3 files changed, 30 insertions(+), 33 deletions(-)
diff --git a/src/vector/platform/ElectronPlatform.js b/src/vector/platform/ElectronPlatform.js
index 9c857e3524..82ef0b5168 100644
--- a/src/vector/platform/ElectronPlatform.js
+++ b/src/vector/platform/ElectronPlatform.js
@@ -20,13 +20,11 @@ limitations under the License.
import VectorBasePlatform from './VectorBasePlatform';
import dis from 'matrix-react-sdk/lib/dispatcher';
import q from 'q';
-
-const electron = require('electron');
-const remote = electron.remote;
+import electron, {remote} from 'electron';
remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
-function onUpdateDownloaded(ev, releaseNotes, ver, date, updateURL) {
+function onUpdateDownloaded(ev: Event, releaseNotes: string, ver: string, date: Date, updateURL: string) {
dis.dispatch({
action: 'new_version',
currentVersion: remote.app.getVersion(),
@@ -35,7 +33,7 @@ function onUpdateDownloaded(ev, releaseNotes, ver, date, updateURL) {
});
}
-function platformFriendlyName() {
+function platformFriendlyName(): string {
console.log(window.process);
switch (window.process.platform) {
case 'darwin':
@@ -72,11 +70,11 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
}
- supportsNotifications() : boolean {
+ supportsNotifications(): boolean {
return true;
}
- maySendNotifications() : boolean {
+ maySendNotifications(): boolean {
return true;
}
@@ -100,7 +98,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
icon: avatarUrl,
tag: 'vector',
silent: true, // we play our own sounds
- }
+ },
);
notification.onclick = function() {
@@ -123,7 +121,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
notif.close();
}
- getAppVersion() {
+ getAppVersion(): Promise {
return q(remote.app.getVersion());
}
@@ -140,15 +138,15 @@ export default class ElectronPlatform extends VectorBasePlatform {
electron.ipcRenderer.send('install_update');
}
- getDefaultDeviceDisplayName() {
+ getDefaultDeviceDisplayName(): string {
return 'Riot Desktop on ' + platformFriendlyName();
}
- screenCaptureErrorString() {
+ screenCaptureErrorString(): ?string {
return null;
}
- requestNotificationPermission() : Promise {
+ requestNotificationPermission(): Promise {
return q('granted');
}
diff --git a/src/vector/platform/VectorBasePlatform.js b/src/vector/platform/VectorBasePlatform.js
index 5240f3f583..1466b76ae3 100644
--- a/src/vector/platform/VectorBasePlatform.js
+++ b/src/vector/platform/VectorBasePlatform.js
@@ -44,7 +44,7 @@ export default class VectorBasePlatform extends BasePlatform {
* Get a sensible default display name for the
* device Vector is running on
*/
- getDefaultDeviceDisplayName() {
+ getDefaultDeviceDisplayName(): string {
return "Unknown device";
}
}
diff --git a/src/vector/platform/WebPlatform.js b/src/vector/platform/WebPlatform.js
index 5dc5505297..72ca19f06c 100644
--- a/src/vector/platform/WebPlatform.js
+++ b/src/vector/platform/WebPlatform.js
@@ -52,7 +52,7 @@ export default class WebPlatform extends VectorBasePlatform {
}
this.favicon.badge(notif, {
- bgColor: bgColor
+ bgColor: bgColor,
});
} catch (e) {
console.warn(`Failed to set badge count: ${e.message}`);
@@ -75,7 +75,7 @@ export default class WebPlatform extends VectorBasePlatform {
* Returns true if the platform supports displaying
* notifications, otherwise false.
*/
- supportsNotifications() : boolean {
+ supportsNotifications(): boolean {
return Boolean(global.Notification);
}
@@ -83,8 +83,8 @@ export default class WebPlatform extends VectorBasePlatform {
* Returns true if the application currently has permission
* to display notifications. Otherwise false.
*/
- maySendNotifications() : boolean {
- return global.Notification.permission == 'granted';
+ maySendNotifications(): boolean {
+ return global.Notification.permission === 'granted';
}
/**
@@ -94,7 +94,7 @@ export default class WebPlatform extends VectorBasePlatform {
* that is 'granted' if the user allowed the request or
* 'denied' otherwise.
*/
- requestNotificationPermission() : Promise {
+ requestNotificationPermission(): Promise {
// annoyingly, the latest spec says this returns a
// promise, but this is only supported in Chrome 46
// and Firefox 47, so adapt the callback API.
@@ -113,13 +113,13 @@ export default class WebPlatform extends VectorBasePlatform {
icon: avatarUrl,
tag: "vector",
silent: true, // we play our own sounds
- }
+ },
);
notification.onclick = function() {
dis.dispatch({
action: 'view_room',
- room_id: room.roomId
+ room_id: room.roomId,
});
global.focus();
notification.close();
@@ -132,7 +132,7 @@ export default class WebPlatform extends VectorBasePlatform {
}, 5 * 1000);
}
- _getVersion() {
+ _getVersion(): Promise {
const deferred = q.defer();
// We add a cachebuster to the request to make sure that we know about
@@ -148,19 +148,19 @@ export default class WebPlatform extends VectorBasePlatform {
},
(err, response, body) => {
if (err || response.status < 200 || response.status >= 300) {
- if (err == null) err = { status: response.status };
+ if (err === null) err = { status: response.status };
deferred.reject(err);
return;
}
const ver = body.trim();
deferred.resolve(ver);
- }
+ },
);
return deferred.promise;
}
- getAppVersion() {
+ getAppVersion(): Promise {
if (this.runningVersion !== null) {
return q(this.runningVersion);
}
@@ -169,9 +169,9 @@ export default class WebPlatform extends VectorBasePlatform {
pollForUpdate() {
this._getVersion().done((ver) => {
- if (this.runningVersion == null) {
+ if (this.runningVersion === null) {
this.runningVersion = ver;
- } else if (this.runningVersion != ver) {
+ } else if (this.runningVersion !== ver) {
dis.dispatch({
action: 'new_version',
currentVersion: this.runningVersion,
@@ -187,19 +187,18 @@ export default class WebPlatform extends VectorBasePlatform {
window.location.reload();
}
- getDefaultDeviceDisplayName() {
+ getDefaultDeviceDisplayName(): string {
// strip query-string and fragment from uri
- let u = url.parse(window.location.href);
+ const u = url.parse(window.location.href);
u.search = "";
u.hash = "";
- let app_name = u.format();
+ const appName = u.format();
- let ua = new UAParser();
- return app_name + " via " + ua.getBrowser().name +
- " on " + ua.getOS().name;
+ const ua = new UAParser();
+ return `${appName} via ${ua.getBrowser().name} on ${ua.getOS().name}`;
}
- screenCaptureErrorString() {
+ screenCaptureErrorString(): ?string {
// it won't work at all if you're not on HTTPS so whine whine whine
if (!global.window || global.window.location.protocol !== "https:") {
return "You need to be using HTTPS to place a screen-sharing call.";
From d5009962cda4f38d423f4fdae0280772a5918469 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@googlemail.com>
Date: Tue, 2 May 2017 22:19:32 +0100
Subject: [PATCH 045/220] Fix scope of callback
This may have led to the room list not refreshing on error of deleting alias
---
src/components/structures/RoomDirectory.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index cdf8d19e55..9104695938 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -204,7 +204,7 @@ module.exports = React.createClass({
}).done(() => {
modal.close();
this.refreshRoomList();
- }, function(err) {
+ }, (err) => {
modal.close();
this.refreshRoomList();
console.error("Failed to " + step + ": " + err);
From 9997cc989186f535e10bde4c85c69c71c1d73e24 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@googlemail.com>
Date: Tue, 2 May 2017 22:27:30 +0100
Subject: [PATCH 046/220] import Modal
class seems to be referring to Modal but does not import it
---
src/components/structures/RoomSubList.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index 577dac9c8f..c315ae46e9 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -29,6 +29,7 @@ var FormattingUtils = require('matrix-react-sdk/lib/utils/FormattingUtils');
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
var ConstantTimeDispatcher = require('matrix-react-sdk/lib/ConstantTimeDispatcher');
var RoomSubListHeader = require('./RoomSubListHeader.js');
+import Modal from 'matrix-react-sdk/lib/Modal';
// turn this on for drag & drop console debugging galore
var debug = false;
From c5d37ab2fbec70fab03e7fac9c48b61fece17989 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 3 May 2017 22:56:39 +0100
Subject: [PATCH 047/220] add to manifest for #334
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
res/vector-icons/manifest.json | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/res/vector-icons/manifest.json b/res/vector-icons/manifest.json
index feab1753cb..2cf10bed44 100644
--- a/res/vector-icons/manifest.json
+++ b/res/vector-icons/manifest.json
@@ -1,5 +1,9 @@
{
- "name": "Riot",
+ "name": "Riot - Matrix Client",
+ "short_name": "Riot",
+ "display": "standalone",
+ "theme_color": "#76CFA6",
+ "start_url": "../",
"icons": [
{
"src": "android-chrome-36x36.png",
@@ -37,5 +41,13 @@
"type": "image\/png",
"density": "4.0"
}
- ]
+ ],
+ "related_applications": [{
+ "platform": "play",
+ "url": "https://play.google.com/store/apps/details?id=im.vector.alpha",
+ "id": "im.vector.alpha"
+ }, {
+ "platform": "itunes",
+ "url": "https://itunes.apple.com/gb/app/riot-open-source-team-collaboration-via-matrix/id1083446067"
+ }]
}
From 095da68aace2e59355346fc2f8e620e04e181e53 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Thu, 4 May 2017 13:58:17 +0100
Subject: [PATCH 048/220] Add buttons to room sub list headers
---
src/components/structures/RoomSubList.js | 4 ++
.../structures/RoomSubListHeader.js | 42 +++++++++----------
src/skins/vector/css/_components.scss | 1 +
.../views/elements/_RoleButton.scss | 26 ++++++++++++
.../views/rooms/_RoomList.scss | 11 ++---
5 files changed, 54 insertions(+), 30 deletions(-)
create mode 100644 src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss
diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index fde35b129f..4d2a3927a4 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -1,4 +1,5 @@
/*
+Copyright 2017 Vector Creations Ltd
Copyright 2015, 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
@@ -83,6 +84,7 @@ var RoomSubList = React.createClass({
onShowMoreRooms: React.PropTypes.func,
searchFilter: React.PropTypes.string,
emptyContent: React.PropTypes.node, // content shown if the list is empty
+ headerItems: React.PropTypes.node, // content shown in the sublist header
},
getInitialState: function() {
@@ -522,6 +524,7 @@ var RoomSubList = React.createClass({
roomNotificationCount={ this.roomNotificationCount() }
onClick={ this.onClick }
onHeaderClick={ this.props.onHeaderClick }
+ headerItems={this.props.headerItems}
/>
{ subList }
@@ -543,6 +546,7 @@ var RoomSubList = React.createClass({
roomNotificationCount={ this.roomNotificationCount() }
onClick={ this.onClick }
onHeaderClick={ this.props.onHeaderClick }
+ headerItems={this.props.headerItems}
/>
: undefined }
{ (this.props.showSpinner && !this.state.hidden) ?
: undefined }
diff --git a/src/components/structures/RoomSubListHeader.js b/src/components/structures/RoomSubListHeader.js
index ad9aff5f70..3ad7547ccb 100644
--- a/src/components/structures/RoomSubListHeader.js
+++ b/src/components/structures/RoomSubListHeader.js
@@ -14,16 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-'use strict';
-
-var React = require('react');
-var ReactDOM = require('react-dom');
-var classNames = require('classnames');
-var sdk = require('matrix-react-sdk')
-var FormattingUtils = require('matrix-react-sdk/lib/utils/FormattingUtils');
-var RoomNotifs = require('matrix-react-sdk/lib/RoomNotifs');
-var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
-var ConstantTimeDispatcher = require('matrix-react-sdk/lib/ConstantTimeDispatcher');
+import React from 'react';
+import classNames from 'classnames';
+import sdk from 'matrix-react-sdk';
+import FormattingUtils from 'matrix-react-sdk/lib/utils/FormattingUtils';
+import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
module.exports = React.createClass({
displayName: 'RoomSubListHeader',
@@ -42,6 +37,7 @@ module.exports = React.createClass({
hidden: React.PropTypes.bool,
onClick: React.PropTypes.func,
onHeaderClick: React.PropTypes.func,
+ headerItems: React.PropTypes.node, // content shown in the sublist header
},
getDefaultProps: function() {
@@ -63,35 +59,34 @@ module.exports = React.createClass({
// },
render: function() {
- var TintableSvg = sdk.getComponent("elements.TintableSvg");
+ const TintableSvg = sdk.getComponent("elements.TintableSvg");
- var subListNotifications = this.props.roomNotificationCount;
- var subListNotifCount = subListNotifications[0];
- var subListNotifHighlight = subListNotifications[1];
+ const subListNotifications = this.props.roomNotificationCount;
+ const subListNotifCount = subListNotifications[0];
+ const subListNotifHighlight = subListNotifications[1];
- var chevronClasses = classNames({
+ const chevronClasses = classNames({
'mx_RoomSubList_chevron': true,
'mx_RoomSubList_chevronRight': this.props.hidden,
'mx_RoomSubList_chevronDown': !this.props.hidden,
});
- var badgeClasses = classNames({
+ const badgeClasses = classNames({
'mx_RoomSubList_badge': true,
'mx_RoomSubList_badgeHighlight': subListNotifHighlight,
});
- var badge;
+ let badge;
if (subListNotifCount > 0) {
badge =
{ FormattingUtils.formatCount(subListNotifCount) }
;
- }
- else if (subListNotifHighlight) {
+ } else if (subListNotifHighlight) {
badge =
!
;
}
// When collapsed, allow a long hover on the header to show user
// the full tag name and room count
- var title;
- var roomCount = this.props.roomCount;
+ let title;
+ const roomCount = this.props.roomCount;
if (this.props.collapsed) {
title = this.props.label;
if (roomCount !== '') {
@@ -99,9 +94,9 @@ module.exports = React.createClass({
}
}
- var incomingCall;
+ let incomingCall;
if (this.props.isIncomingCallRoom) {
- var IncomingCallBox = sdk.getComponent("voip.IncomingCallBox");
+ const IncomingCallBox = sdk.getComponent("voip.IncomingCallBox");
incomingCall =
;
}
@@ -109,6 +104,7 @@ module.exports = React.createClass({
{ this.props.collapsed ? '' : this.props.label }
+ {this.props.headerItems}
{ roomCount }
{ badge }
diff --git a/src/skins/vector/css/_components.scss b/src/skins/vector/css/_components.scss
index df3c4600eb..5b23bb82f8 100644
--- a/src/skins/vector/css/_components.scss
+++ b/src/skins/vector/css/_components.scss
@@ -27,6 +27,7 @@
@import "./matrix-react-sdk/views/elements/_MemberEventListSummary.scss";
@import "./matrix-react-sdk/views/elements/_ProgressBar.scss";
@import "./matrix-react-sdk/views/elements/_RichText.scss";
+@import "./matrix-react-sdk/views/elements/_RoleButton.scss";
@import "./matrix-react-sdk/views/login/_InteractiveAuthEntryComponents.scss";
@import "./matrix-react-sdk/views/login/_ServerConfig.scss";
@import "./matrix-react-sdk/views/messages/_MEmoteBody.scss";
diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss
new file mode 100644
index 0000000000..04503346ff
--- /dev/null
+++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss
@@ -0,0 +1,26 @@
+/*
+Copyright 2107 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.
+*/
+
+.mx_RoleButton {
+ margin-left: 4px;
+ margin-right: 4px;
+ cursor: pointer;
+ display: inline-block;
+}
+
+.mx_RoleButton object {
+ pointer-events: none;
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
index bc699ae792..77df1f8fda 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
@@ -39,10 +39,6 @@ limitations under the License.
z-index: 6;
}
-.mx_RoomList_greyedSubListLabel {
- color: #a2a2a2;
-}
-
.mx_RoomList_emptySubListTip {
font-size: 13px;
margin-left: 18px;
@@ -50,12 +46,13 @@ limitations under the License.
margin-top: 8px;
margin-bottom: 7px;
padding: 5px;
- border: 1px solid $accent-color;
+ border: 1px dashed $accent-color;
color: $primary-fg-color;
background-color: $droptarget-bg-color;
border-radius: 4px;
}
-.mx_RoomList_butonPreview {
- float: right;
+.mx_RoomList_headerButtons {
+ position: absolute;
+ right: 60px;
}
From ff709ed8b126c3f9c96ebebb815730b12a62e31d Mon Sep 17 00:00:00 2001
From: David Baker
Date: Thu, 4 May 2017 14:53:13 +0100
Subject: [PATCH 049/220] Fix import
---
src/components/structures/RoomSubListHeader.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/structures/RoomSubListHeader.js b/src/components/structures/RoomSubListHeader.js
index 3ad7547ccb..74094ae0ba 100644
--- a/src/components/structures/RoomSubListHeader.js
+++ b/src/components/structures/RoomSubListHeader.js
@@ -17,7 +17,7 @@ limitations under the License.
import React from 'react';
import classNames from 'classnames';
import sdk from 'matrix-react-sdk';
-import FormattingUtils from 'matrix-react-sdk/lib/utils/FormattingUtils';
+import { formatCount } from 'matrix-react-sdk/lib/utils/FormattingUtils';
import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
module.exports = React.createClass({
@@ -78,7 +78,7 @@ module.exports = React.createClass({
let badge;
if (subListNotifCount > 0) {
- badge = { FormattingUtils.formatCount(subListNotifCount) }
;
+ badge = { formatCount(subListNotifCount) }
;
} else if (subListNotifHighlight) {
badge = !
;
}
From 2bf007495331542c49ff6a9fc98002cee947dac6 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Thu, 4 May 2017 15:38:53 +0100
Subject: [PATCH 050/220] Make bottom left menu buttons use RoleButton too
---
src/components/structures/BottomLeftMenu.js | 122 ++----------------
.../views/elements/_RoleButton.scss | 7 +
.../css/vector-web/structures/_LeftPanel.scss | 34 ++---
3 files changed, 25 insertions(+), 138 deletions(-)
diff --git a/src/components/structures/BottomLeftMenu.js b/src/components/structures/BottomLeftMenu.js
index f378cac628..1195a6f347 100644
--- a/src/components/structures/BottomLeftMenu.js
+++ b/src/components/structures/BottomLeftMenu.js
@@ -14,13 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-'use strict';
-
-var React = require('react');
-var ReactDOM = require('react-dom');
-var sdk = require('matrix-react-sdk')
-var dis = require('matrix-react-sdk/lib/dispatcher');
-var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
+import React from 'react';
+import sdk from 'matrix-react-sdk';
module.exports = React.createClass({
displayName: 'BottomLeftMenu',
@@ -30,121 +25,24 @@ module.exports = React.createClass({
teamToken: React.PropTypes.string,
},
- getInitialState: function() {
- return({
- directoryHover : false,
- roomsHover : false,
- homeHover: false,
- peopleHover : false,
- settingsHover : false,
- });
- },
-
- // Room events
- onDirectoryClick: function() {
- dis.dispatch({ action: 'view_room_directory' });
- },
-
- onDirectoryMouseEnter: function() {
- this.setState({ directoryHover: true });
- },
-
- onDirectoryMouseLeave: function() {
- this.setState({ directoryHover: false });
- },
-
- onRoomsClick: function() {
- dis.dispatch({ action: 'view_create_room' });
- },
-
- onRoomsMouseEnter: function() {
- this.setState({ roomsHover: true });
- },
-
- onRoomsMouseLeave: function() {
- this.setState({ roomsHover: false });
- },
-
- // Home button events
- onHomeClick: function() {
- dis.dispatch({ action: 'view_home_page' });
- },
-
- onHomeMouseEnter: function() {
- this.setState({ homeHover: true });
- },
-
- onHomeMouseLeave: function() {
- this.setState({ homeHover: false });
- },
-
- // People events
- onPeopleClick: function() {
- dis.dispatch({ action: 'view_create_chat' });
- },
-
- onPeopleMouseEnter: function() {
- this.setState({ peopleHover: true });
- },
-
- onPeopleMouseLeave: function() {
- this.setState({ peopleHover: false });
- },
-
- // Settings events
- onSettingsClick: function() {
- dis.dispatch({ action: 'view_user_settings' });
- },
-
- onSettingsMouseEnter: function() {
- this.setState({ settingsHover: true });
- },
-
- onSettingsMouseLeave: function() {
- this.setState({ settingsHover: false });
- },
-
- // Get the label/tooltip to show
- getLabel: function(label, show) {
- if (show) {
- var RoomTooltip = sdk.getComponent("rooms.RoomTooltip");
- return ;
- }
- },
-
render: function() {
- var TintableSvg = sdk.getComponent('elements.TintableSvg');
+ const RoleButton = sdk.getComponent('elements.RoleButton');
var homeButton;
if (this.props.teamToken) {
- homeButton = (
-
-
- { this.getLabel("Welcome page", this.state.homeHover) }
-
- );
+ homeButton = ;
}
return (
{ homeButton }
-
-
- { this.getLabel("Start chat", this.state.peopleHover) }
-
-
-
- { this.getLabel("Room directory", this.state.directoryHover) }
-
-
-
- { this.getLabel("Create new room", this.state.roomsHover) }
-
-
-
- { this.getLabel("Settings", this.state.settingsHover) }
-
+
+
+
+
+
+
);
diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss
index 04503346ff..094e0b9b1b 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss
@@ -24,3 +24,10 @@ limitations under the License.
.mx_RoleButton object {
pointer-events: none;
}
+
+.mx_RoleButton_tooltip {
+ display: inline-block;
+ position: relative;
+ top: -25px;
+ left: 6px;
+}
diff --git a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss
index d3bbce1b19..f171591cd6 100644
--- a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss
+++ b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss
@@ -64,43 +64,25 @@ limitations under the License.
pointer-events: none;
}
-.mx_LeftPanel .mx_BottomLeftMenu_homePage,
-.mx_LeftPanel .mx_BottomLeftMenu_directory,
-.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
-.mx_LeftPanel .mx_BottomLeftMenu_people,
-.mx_LeftPanel .mx_BottomLeftMenu_settings {
- display: inline-block;
- cursor: pointer;
-}
-
-.collapsed .mx_BottomLeftMenu_homePage,
-.collapsed .mx_BottomLeftMenu_directory,
-.collapsed .mx_BottomLeftMenu_createRoom,
-.collapsed .mx_BottomLeftMenu_people,
-.collapsed .mx_BottomLeftMenu_settings {
+.collapsed .mx_RoleButton {
margin-right: 0px ! important;
padding-top: 3px ! important;
padding-bottom: 3px ! important;
}
-.mx_LeftPanel .mx_BottomLeftMenu_homePage,
-.mx_LeftPanel .mx_BottomLeftMenu_directory,
-.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
-.mx_LeftPanel .mx_BottomLeftMenu_people {
+.mx_BottomLeftMenu_options .mx_RoleButton {
+ margin-left: 0px;
margin-right: 10px;
}
-.mx_LeftPanel .mx_BottomLeftMenu_settings {
+.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings {
float: right;
}
+.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings .mx_RoleButton {
+ margin-right: 0px;
+}
+
.mx_LeftPanel.collapsed .mx_BottomLeftMenu_settings {
float: none;
}
-
-.mx_LeftPanel .mx_BottomLeftMenu_tooltip {
- display: inline-block;
- position: relative;
- top: -25px;
- left: 6px;
-}
From 7b320f8fbbf85c10d8212af5bc2eb6689879f04b Mon Sep 17 00:00:00 2001
From: David Baker
Date: Thu, 4 May 2017 16:51:36 +0100
Subject: [PATCH 051/220] Remove babelcheck
Nobody is likley to be upgrading from babel 5 any more, so this
can go away now.
---
package.json | 6 +++---
scripts/babelcheck.js | 26 --------------------------
2 files changed, 3 insertions(+), 29 deletions(-)
delete mode 100644 scripts/babelcheck.js
diff --git a/package.json b/package.json
index a25e17955f..6554f2f733 100644
--- a/package.json
+++ b/package.json
@@ -33,13 +33,13 @@
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress",
"build:bundle:dev": "webpack --optimize-occurence-order --progress",
"build:electron": "npm run clean && npm run build && build -wml --ia32 --x64",
- "build": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle",
- "build:dev": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle:dev",
+ "build": "npm run build:res && npm run build:bundle",
+ "build:dev": "npm run build:res && npm run build:bundle:dev",
"dist": "scripts/package.sh",
"start:res": "node scripts/copy-res.js -w",
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress",
"start:js:prod": "cross-env NODE_ENV=production webpack-dev-server -w --progress",
- "start": "node scripts/babelcheck.js && parallelshell \"npm run start:res\" \"npm run start:js\"",
+ "start": "parallelshell \"npm run start:res\" \"npm run start:js\"",
"start:prod": "parallelshell \"npm run start:res\" \"npm run start:js:prod\"",
"lint": "eslint src/",
"lintall": "eslint src/ test/",
diff --git a/scripts/babelcheck.js b/scripts/babelcheck.js
deleted file mode 100644
index 89f5cac554..0000000000
--- a/scripts/babelcheck.js
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env node
-
-var exec = require('child_process').exec;
-
-// Makes sure the babel executable in the path is babel 6 (or greater), not
-// babel 5, which it is if you upgrade from an older version of react-sdk and
-// run 'npm install' since the package has changed to babel-cli, so 'babel'
-// remains installed and the executable in node_modules/.bin remains as babel
-// 5.
-
-// This script is duplicated from matrix-react-sdk because it can't reliably
-// be pulled in from react-sdk while npm install is failing, as it will do
-// if the environment is in the erroneous state this script checks for.
-
-exec("babel -V", function (error, stdout, stderr) {
- if ((error && error.code) || parseInt(stdout.substr(0,1), 10) < 6) {
- console.log("\033[31m\033[1m"+
- '*****************************************\n'+
- '* vector-web has moved to babel 6 *\n'+
- '* Please "rm -rf node_modules && npm i" *\n'+
- '* then restore links as appropriate *\n'+
- '*****************************************\n'+
- "\033[91m");
- process.exit(1);
- }
-});
From 45efdbdd43ac29cca27f8f9c3eb3e1bd947c0e66 Mon Sep 17 00:00:00 2001
From: Richard van der Hoff
Date: Thu, 4 May 2017 17:21:16 +0100
Subject: [PATCH 052/220] Include MXID and device id in rageshakes
- to make for easier triage
---
src/vector/submit-rageshake.js | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/vector/submit-rageshake.js b/src/vector/submit-rageshake.js
index ef6fbabe29..45b427e899 100644
--- a/src/vector/submit-rageshake.js
+++ b/src/vector/submit-rageshake.js
@@ -17,6 +17,7 @@ limitations under the License.
import pako from 'pako';
import q from "q";
+import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
import rageshake from './rageshake'
@@ -64,6 +65,8 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
userAgent = window.navigator.userAgent;
}
+ const client = MatrixClientPeg.get();
+
console.log("Sending bug report.");
const body = new FormData();
@@ -72,6 +75,11 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
body.append('version', version);
body.append('user_agent', userAgent);
+ if (client) {
+ body.append('user_id', client.credentials.userId);
+ body.append('device_id', client.deviceId);
+ }
+
if (opts.sendLogs) {
progressCallback("Collecting logs");
const logs = await rageshake.getLogsForReport();
From da960e776dde215aaf20885fbc7faf22ae905f7a Mon Sep 17 00:00:00 2001
From: David Baker
Date: Thu, 4 May 2017 17:45:11 +0100
Subject: [PATCH 053/220] Remove commented code
---
src/components/structures/RoomSubList.js | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index 4d2a3927a4..bac87bc489 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -475,8 +475,6 @@ var RoomSubList = React.createClass({
var label = this.props.collapsed ? null : this.props.label;
- //console.log("render: " + JSON.stringify(this.state.sortedList));
-
let content;
if (this.state.sortedList.length == 0) {
//content = ;
From 23a141c5ad390cb8d6cf4aede5fd32c9f2463949 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Thu, 4 May 2017 17:46:44 +0100
Subject: [PATCH 054/220] Remove slightly misleading commented code
---
src/components/structures/RoomSubList.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js
index bac87bc489..adeb365148 100644
--- a/src/components/structures/RoomSubList.js
+++ b/src/components/structures/RoomSubList.js
@@ -477,7 +477,6 @@ var RoomSubList = React.createClass({
let content;
if (this.state.sortedList.length == 0) {
- //content = ;
content = this.props.emptyContent;
} else {
content = this.makeRoomTiles();
From 1001c98a3c8fca82d264a54d5a433845a2e36fe9 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Thu, 4 May 2017 18:23:04 +0100
Subject: [PATCH 055/220] Align buttons better with the text
---
.../vector/css/matrix-react-sdk/views/rooms/_RoomList.scss | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
index 77df1f8fda..35787ca0c4 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
@@ -52,6 +52,10 @@ limitations under the License.
border-radius: 4px;
}
+.mx_RoomList_emptySubListTip .mx_RoleButton {
+ vertical-align: -3px;
+}
+
.mx_RoomList_headerButtons {
position: absolute;
right: 60px;
From ae76c76558a9c38100c51a9c7019cb50bfdc388e Mon Sep 17 00:00:00 2001
From: Luke Barnard
Date: Thu, 4 May 2017 21:27:33 +0100
Subject: [PATCH 056/220] Fix #3450 - RM hidden by things
---
.../vector/css/matrix-react-sdk/structures/_RoomView.scss | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss b/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss
index 1286193974..e251ecd14c 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss
@@ -160,7 +160,8 @@ hr.mx_RoomView_myReadMarker {
border-bottom: solid 1px $accent-color;
margin-top: 0px;
position: relative;
- top: 5px;
+ top: -1px;
+ z-index: 1;
}
.mx_RoomView_statusArea {
From e1cd046c1a4ff92992c1477ddf975b80195af50c Mon Sep 17 00:00:00 2001
From: Luke Barnard
Date: Fri, 5 May 2017 09:54:00 +0100
Subject: [PATCH 057/220] Prevent zalgo-like text overflowing MELS summary
---
.../matrix-react-sdk/views/elements/_MemberEventListSummary.scss | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss
index 1858865980..1969bc2db0 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss
@@ -20,6 +20,7 @@ limitations under the License.
.mx_TextualEvent.mx_MemberEventListSummary_summary {
font-size: 14px;
+ display: inline-flex;
}
.mx_MemberEventListSummary_avatars {
From c27f39714a66bbcb0fb6bee95638f7bb67e20637 Mon Sep 17 00:00:00 2001
From: David Baker
Date: Fri, 5 May 2017 14:26:13 +0100
Subject: [PATCH 058/220] Dedicated classes for the buttons
---
src/components/structures/BottomLeftMenu.js | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/components/structures/BottomLeftMenu.js b/src/components/structures/BottomLeftMenu.js
index 1195a6f347..63dfac60d8 100644
--- a/src/components/structures/BottomLeftMenu.js
+++ b/src/components/structures/BottomLeftMenu.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.
@@ -26,22 +27,26 @@ module.exports = React.createClass({
},
render: function() {
- const RoleButton = sdk.getComponent('elements.RoleButton');
+ const HomeButton = sdk.getComponent('elements.HomeButton');
+ const StartChatButton = sdk.getComponent('elements.StartChatButton');
+ const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton');
+ const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton');
+ const SettingsButton = sdk.getComponent('elements.SettingsButton');
var homeButton;
if (this.props.teamToken) {
- homeButton = ;
+ homeButton = ;
}
return (
{ homeButton }
-
-
-
+
+
+
-
+
From f54708227e0eb624dc178992c134519e42c43dfa Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 5 May 2017 16:54:55 +0100
Subject: [PATCH 059/220] Proper two package.json format, release.sh bumps 2nd
json ver too
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
electron/package.json | 6 +++++-
package.json | 14 ++++++++------
release.sh | 13 +++++++++++++
3 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/electron/package.json b/electron/package.json
index e6e7e2a42d..0fff99f522 100644
--- a/electron/package.json
+++ b/electron/package.json
@@ -1,5 +1,9 @@
{
- "description": "Electron main process dependencies",
+ "name": "riot-web",
+ "main": "src/electron-main.js",
+ "version": "0.0.0",
+ "description": "A feature-rich client for Matrix.org",
+ "author": "Vector Creations Ltd.",
"dependencies": {
"electron-window-state": "^4.1.0"
}
diff --git a/package.json b/package.json
index a64d0d9ea3..e801ed5d07 100644
--- a/package.json
+++ b/package.json
@@ -146,11 +146,12 @@
"dereference": true,
"//files": "We bundle everything, so we only need to include webapp/",
"files": [
- "electron/node_modules/**",
- "electron/src/**",
- "electron/img/**",
- "webapp/**",
- "package.json"
+ "node_modules/**",
+ "src/**",
+ "img/**"
+ ],
+ "extraResources": [
+ "webapp/**/*"
],
"linux": {
"target": "deb",
@@ -164,7 +165,8 @@
},
"directories": {
"buildResources": "electron/build",
- "output": "electron/dist"
+ "output": "electron/dist",
+ "app": "electron"
}
}
}
diff --git a/release.sh b/release.sh
index e8c68b9024..a3225150b6 100755
--- a/release.sh
+++ b/release.sh
@@ -9,4 +9,17 @@ set -e
cd `dirname $0`
+
+# bump Electron's package.json first
+release="${1#v}"
+tag="v${release}"
+echo "electron npm version"
+
+cd electron
+npm version --no-git-tag-version "$release"
+git commit package.json -m "$tag"
+
+
+cd ..
+
exec ./node_modules/matrix-js-sdk/release.sh -z "$@"
From 8a5020718936368d556c438a1f1b1691414c884c Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 5 May 2017 16:57:18 +0100
Subject: [PATCH 060/220] Change shebang to bash for string manipulations
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
release.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/release.sh b/release.sh
index a3225150b6..9d02e98e93 100755
--- a/release.sh
+++ b/release.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
#
# Script to perform a release of vector-web.
#
From 499b04c25467fd4f6550568232a6d89797dcbe47 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 5 May 2017 17:01:32 +0100
Subject: [PATCH 061/220] Only install electron deps when we're
bundling/running electron
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index e801ed5d07..548c95d2fc 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
"build": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle",
"build:dev": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle:dev",
"dist": "scripts/package.sh",
- "install:electron": "cd electron && npm i",
+ "install:electron": "install-app-deps",
"electron": "npm run install:electron && electron .",
"start:res": "node scripts/copy-res.js -w",
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress",
From 1ed1080bf3fa8be1ef2325ad854b68893330bb90 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 5 May 2017 17:05:03 +0100
Subject: [PATCH 062/220] Update README with npm run electron
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
README.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 7bef64783d..55463a376e 100644
--- a/README.md
+++ b/README.md
@@ -135,8 +135,7 @@ To run as a desktop app:
```
npm install electron
- npm run install:electron
- node_modules/.bin/electron .
+ npm run electron
```
To build packages, use electron-builder. This is configured to output:
From 309afdb813e1413a95de1ed248cdc5f78e7a7fd1 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Fri, 5 May 2017 17:08:50 +0100
Subject: [PATCH 063/220] no point installing deps here, builder will do it for
us
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index d0161610d8..b01c1aa0c0 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
"build:compile": "babel --source-maps -d lib src",
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress",
"build:bundle:dev": "webpack --optimize-occurence-order --progress",
- "build:electron": "npm run clean && npm run build && npm run install:electron && build -wml --ia32 --x64",
+ "build:electron": "npm run clean && npm run build && build -wml --ia32 --x64",
"build": "npm run build:res && npm run build:bundle",
"build:dev": "npm run build:res && npm run build:bundle:dev",
"dist": "scripts/package.sh",
From 9c6b3819a5797ac4490ec74e6295e0ae8708cf01 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@googlemail.com>
Date: Sat, 6 May 2017 10:24:13 +0100
Subject: [PATCH 064/220] Re-add productName
so that electron-builder packages is as Riot rather than riot-web
---
electron/package.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/electron/package.json b/electron/package.json
index 69ea9a2899..cf5b4efd5d 100644
--- a/electron/package.json
+++ b/electron/package.json
@@ -1,5 +1,6 @@
{
"name": "riot-web",
+ "productName": "Riot",
"main": "src/electron-main.js",
"version": "0.9.8",
"description": "A feature-rich client for Matrix.org",
From 1e5908a31e15e88567bd231f20078d48bf2754cb Mon Sep 17 00:00:00 2001
From: Matthew Hodgson
Date: Sun, 7 May 2017 19:34:05 +0100
Subject: [PATCH 065/220] speed up burndown generation by ~250x
---
scripts/issues-burndown.pl | 40 +++++++++++++++++++++++++-------------
scripts/issues-no-state.pl | 12 ++++++++++--
2 files changed, 36 insertions(+), 16 deletions(-)
mode change 100644 => 100755 scripts/issues-burndown.pl
diff --git a/scripts/issues-burndown.pl b/scripts/issues-burndown.pl
old mode 100644
new mode 100755
index 7d0f3409c0..67c05673df
--- a/scripts/issues-burndown.pl
+++ b/scripts/issues-burndown.pl
@@ -4,16 +4,24 @@ use warnings;
use strict;
use Net::GitHub;
-use DateTime;
-use DateTime::Format::ISO8601;
+use Time::Moment;
+use Term::ReadPassword;
+
+# This version of the script emits the cumulative number of bugs, split into open & closed
+# suitable for drawing the 'top' and 'bottom' of a burndown graph.
+#
+# N.B. this doesn't take into account issues changing priority over time, but only their most recent priority.
+#
+# If you want instead the number of open issues on a given day, then look at issues-no-state.pl
my $gh = Net::GitHub->new(
- login => 'ara4n', pass => 'secret'
+ login => 'ara4n', pass => read_password("github password: "),
);
$gh->set_default_user_repo('vector-im', 'vector-web');
-my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 });
+#my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 });
+my @issues = $gh->issue->repos_issues({ state => 'all' });
while ($gh->issue->has_next_page) {
push @issues, $gh->issue->next_page;
}
@@ -30,11 +38,11 @@ while ($gh->issue->has_next_page) {
my $days = {};
my $schema = {};
-my $now = DateTime->now();
+my $now = Time::Moment->now;
foreach my $issue (@issues) {
next if ($issue->{pull_request});
-
+
# use Data::Dumper;
# print STDERR Dumper($issue);
@@ -56,10 +64,10 @@ foreach my $issue (@issues) {
my $priority = &$extract_labels(qw(p1 p2 p3 p4 p5)) || "unprioritised";
my $severity = &$extract_labels(qw(minor major critical cosmetic network)) || "no-severity";
- my $start = DateTime::Format::ISO8601->parse_datetime($issue->{created_at});
+ my $start = Time::Moment->from_string($issue->{created_at});
do {
- my $ymd = $start->ymd();
+ my $ymd = $start->strftime('%F');
$days->{ $ymd }->{ 'created' }->{ $type }->{ $priority }->{ $severity }->{ total }++;
$schema->{ 'created' }->{ $type }->{ $priority }->{ $severity }->{ total }++;
@@ -68,13 +76,14 @@ foreach my $issue (@issues) {
$schema->{ 'created' }->{ $type }->{ $priority }->{ $severity }->{ $_ }++;
}
- $start = $start->add(days => 1);
- } while (DateTime->compare($start, $now) < 0);
+ $start = $start->plus_days(1);
+ # print STDERR "^";
+ } while ($start->compare($now) < 0);
if ($state eq 'closed') {
- my $end = DateTime::Format::ISO8601->parse_datetime($issue->{closed_at});
+ my $end = Time::Moment->from_string($issue->{closed_at});
do {
- my $ymd = $end->ymd();
+ my $ymd = $end->strftime('%F');
$days->{ $ymd }->{ 'resolved' }->{ $type }->{ $priority }->{ $severity }->{ total }++;
$schema->{ 'resolved' }->{ $type }->{ $priority }->{ $severity }->{ total }++;
@@ -83,9 +92,12 @@ foreach my $issue (@issues) {
$schema->{ 'resolved' }->{ $type }->{ $priority }->{ $severity }->{ $_ }++;
}
- $end = $end->add(days => 1);
- } while (DateTime->compare($end, $now) < 0);
+ $end = $end->plus_days(1);
+ } while ($end->compare($now) < 0);
+ # print STDERR "v";
}
+
+ # print STDERR "\n";
}
print "day,";
diff --git a/scripts/issues-no-state.pl b/scripts/issues-no-state.pl
index da12fb225a..9b07ed271f 100755
--- a/scripts/issues-no-state.pl
+++ b/scripts/issues-no-state.pl
@@ -6,14 +6,22 @@ use strict;
use Net::GitHub;
use DateTime;
use DateTime::Format::ISO8601;
+use Term::ReadPassword;
+
+# This version of the script emits the total number of bugs open on a given day,
+# split by various tags.
+#
+# If you want instead the cumulative number of open & closed issues on a given day,
+# then look at issues-burndown.pl
my $gh = Net::GitHub->new(
- login => 'ara4n', pass => 'secret'
+ login => 'ara4n', pass => read_password("github password: "),
);
$gh->set_default_user_repo('vector-im', 'vector-web');
-my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 });
+#my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 });
+my @issues = $gh->issue->repos_issues({ state => 'all' });
while ($gh->issue->has_next_page) {
push @issues, $gh->issue->next_page;
}
From ea72e9c7a0f0ef77583cc4875a610509c8396ee6 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@googlemail.com>
Date: Sun, 7 May 2017 20:33:13 +0100
Subject: [PATCH 066/220] match primary package.json
got mismatched after a release -> develop merge
---
electron/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/electron/package.json b/electron/package.json
index cf5b4efd5d..99651cc1c5 100644
--- a/electron/package.json
+++ b/electron/package.json
@@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "src/electron-main.js",
- "version": "0.9.8",
+ "version": "0.9.9",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"dependencies": {
From 640aa98cf4adfdfcd97db5b837ada3d5e722443f Mon Sep 17 00:00:00 2001
From: David Baker
Date: Mon, 8 May 2017 13:05:17 +0100
Subject: [PATCH 067/220] Update 2 missed icons to the new icon
Electron icons for windows & Linux. Also add them to the script
that makes all the icon versions.
---
electron/img/riot.ico | Bin 21650 -> 104772 bytes
electron/img/riot.png | Bin 14677 -> 10430 bytes
scripts/make-icons.sh | 2 ++
3 files changed, 2 insertions(+)
diff --git a/electron/img/riot.ico b/electron/img/riot.ico
index 8b681ffba3c1fbc6af4ad68fc41449ce017d9b53..8f8ff94eea677e966568bc2a264d1c0fe708dcf4 100644
GIT binary patch
literal 104772
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≈@&
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
literal 21650
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