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 01/83] 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 02/83] 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 9747836a4dccf6d913ad9ae3e15eb9e5c7951a6a Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 21 Apr 2017 18:24:29 +0100 Subject: [PATCH 03/83] 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 04/83] 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 05/83] 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 06/83] 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 07/83] 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 08/83] 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 09/83] 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 10/83] 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 11/83] 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 12/83] 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 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 13/83] 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 1701ea43a4109efcad0d9381bbeda6248abd486e Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 24 Apr 2017 18:22:23 +0100 Subject: [PATCH 14/83] 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 15/83] 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 16/83] 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 17/83] 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 2d311ddbf4ea1848a0374e6ba288897652dcc746 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 25 Apr 2017 11:04:03 +0100 Subject: [PATCH 18/83] 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 19/83] 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 20/83] 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 96c867b34bbee417620ffbdb38a14585528198d4 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 26 Apr 2017 19:00:07 +0100 Subject: [PATCH 21/83] 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 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 22/83] 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 23/83] 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 24/83] 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 25/83] 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 26/83] 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 27/83] 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 28/83] 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 29/83] 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 30/83] 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 31/83] 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 32/83] 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 33/83] 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 34/83] 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 35/83] 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 36/83] 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 37/83] 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 38/83] 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 39/83] 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 40/83] 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 41/83] 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 42/83] 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 43/83] 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 44/83] 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 45/83] 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 46/83] 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 47/83] 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 zcmaI7WmH>T7cCq-xEBrD;##D^U5dLDx1vRg1b26e7KauHPLa|A#kDvDiUlw3Ui1sk z``!EV!eAtWoUF6g+-uLJ2LM1q{67C60q6k!Ism{6#QPWxH3eKON-V@%+_#FdTF;+8 z{}G@gUU1euUI73)GH+$2bi5Z1;Sdj9-R1t%WAWy{r5HrM7`t?03|_Kny|HMo=Hw4> z<)n%YR^I`nvSUekU({*pb}sW=EQ=HoPYrW!A6zHB+!$#~3{wKLc8tHP`HTiWU&!^~dq^Dg;hASH)mtY7ssX1zSqohPGBQiB4D)-fC@6 z{`iZu{55lLzAn;Nzxk_ef?!)0k5^ysX+&aCRApvM-hf?K(k-vJE#um3dg9})W*wK? zND(n=l=oQka!9A61$K46hKKql{wzp?{KZ40Ar;of7t=S4g>zKj26EAh{wxvt3fc|- zi1^p(erx$I#8>et?7bw3As8v4{_YnEa|$v)mD_6nlvo|m@-wYf@nq5dMDU*#Qf9T# zK0l>EvEx_9cA`RVsNaC^YhFb&-4Bk-t}@@PW_q(S`5$X0ZZKuJQDqy5QsiN713~zP z2AiJ(L>I4B)&*F_unX$%J`fbYPKk3xyIk@y`(7|Fb?BJ#V=wdMGJ(cz7K=;&&@b_| zV3x^eSJNMqHa}q#N9-`JU*V>z&f4QCvaMN0KXf|eKMb71tf*+{VmH7@DA;J>n$buk zgfWx!kwpm+aJVN{J99)*>rvN&46-k>jCEoGY> zx2col(0f%D717Uu`~*u+401mvL}XZESr+`M)GT=fOV&EaCqXibopPxtaDV()UP?a& zpQKyO(g;XHj6K++uQQW6EXTxBn!R<_biN#amMY_hY4%;vI^H`Z>Z)I~%g@YmyZfXH zSA^ExBgWbmL#1|c(BPCc|kIU+4wOr7W z0(&Hhg}tZ~i2u|qpweprE-+oqT$YPQY0-qwEX?CAS|4bd$oOalBXRfnM2k%7HJnyg<3E5ddy1 zH8go58jP)ki)Z0(F(wkWkU=3H?!rjUu}TBz75#S%Y+Rr=Qdi5vU%>#2tPW?U0)j-j z1eRX9qq4}ayb-HMYT|ru@05Zn^WiBGH+-86@5aRK_ZRt(kFG$uO<~QI?zHm`qEx<8 zoIf2t|DL9uep8R47RpkXY^TyXoiA-8bALH6PYzZ0z-3$WHajpr_bf!Kj0TLs8p@Fjz}D81xvwcZm6%Y$S0g=zS;e%0^s<0~Hjg&DC5gW` z@~=$OK0d739wf5&(xxE0e)=W0J>yfLdgf1fca`#@rVPDQI1}|xWoc4^o;Z6HAtzVS ztKn$Wk1@>FkOi!-PSG8V5(Kz=0`L&L)gZC9lqS@xpaq7GADq-f&K_#3;yivLL9ntg zU$yHJTrJe_U;HmnGm3fZ1V>AP{j2^}x)Q06j?4Ntq3DucU409XOc zqfsdvfw^Dym#DntyU+*t)PI0#Q5~W8Mn^gd7t*)h>WopS(t`q^ar|U&Bhky)DM)d>yKMD_ay5< zPx3@3=MUH8H#DjTd1vp&lv;aY_ug`)2ThM0S}ly_EpgFT$yn5{feNeyV znakC=KPuAML4GTZu;sDYjcPGS!mDWuSvT9?oo^*a!dDtyv_1GXO^Dv`c%VbwZjBc- z&eB3rlE;5Q75OP+&s+;xRa~$Q!pB*PvrwqBp9)=^5KJkPByIsw(G(l(JLS&yaaD=? z`DNUI^h&wQq~C@+=y(uQt^$-tTS%A#M2U@oPE=m97knD8XtnM@zD$plWqHl0UG-S! z=sA#sy)Sun_6`*GA%sLM7G07f%I#segIiXv7yw#`jd^PqL7WhE&`g=E3K%%ZXxAt9 zD_sh*PJ;8w&AcS*ldyk(%-b<`7>pr zMthP}xvhh+b~55xbsw;@9)3)!G*&0(t?TU^{?<-!-}3aCzVNI{!QLR2kB*(xbba?5`u(YeoUq{Ruj60ER$tN;_-fj-aEz=b zp-zAUbCq~aMN?a*GZuQe?#CdumcP=(`_2y&S=pF>l04!c2Z^+g=MH_Kj4DX=i|kQp zofqQX(co+my&SK0ANE=&zG7oXrrk$vk(%U8>3E0VeYM}x$Q~WGH16nu?ISrllj5Nu z_<|@sRa&Y`1{GMe-6*H2augm%J_zu%`-k727^8rmXqk+_^e-LSYKOP&A&gIaxJKZ$ zuvkOf{u0Eu_3VKR%FHDm<;6jd3?yK3zbDn$Eta|r<0@v}6sY2zcEVW9Kk)T=RAO16 zn4HMQaR?R9@fy^oDE`QHHzNFP0)vuRUc7Jmh&i9(sw3m5RqV7rtqd=~8eu`--Xh)L zYajbQ)g;lnZ^MMXSB5cr9mtNK6|3V0nBkW0Pw!M6(I-)!-3Pu}Wuw^BuieGV#TyWJ ztmChv_3}92Z{WdIspWh32E}*(T4|gnxdXfSOv}J7F9rq0eF#UIgvj@bX8i`;-GY5( zqF0j@67IDK($?YlxcWONx8+u@Y8UyiU(k4_%f}+sPFPa-E~=8OyW(Et;h=Qy9&)pdFn#6zTl-B z_BXoqS~5xcE_EnN0kO0ii-nJQMgtK|7~5aXiFHwKG%uN_kLsk;h*K>uD9qLwl0vW7 zF9O1UILN-+gI;{FFX$clCX!#L(8LXB%DZdaUPZ%&Tg63D(3*+lGw-S^cP8n-_@_&c z{sQY_W{+i<{`-j{@t;2$4Oby1M-he0C+Mw*c&xHQ(|}XY!2!Ch-7(Z5<|kGCy}ApK zy|xhqAsgIOaY)iR{HIOia^osx+Cid$dGh?Esy#nJ&Ws#0lb1e*lE!tr7FLl6u|JC;osJI7s?6N}aKWC+aUE`aKqM7g_le8|O zefDN;{I|2R5G8z~gGAQf3QZuSXrDuaiJ6_^zM8y{#RS+n_m@}fmox}NOfKa;@r8FwaZ#&=foMp=j$^nvbbnz0rv z0m%DJ=Ja?tj;VP_ZqZ>$#NedJiAN+in(0?6o)!4=um}A$gNB?=4l<85tc8%zSxcm6 zmdw}zr)AG@0JJ6DL?;|u?ZLcqSFiRF#T3Y)o;!S`rsmEfhT(TQFANPP zL%;JE#^(SnyMwu-SLwEl@V|Lc}Lj-N${*8`<2{9m0#sP)l+J}4B6-! z3Ou;x-o1xhQ#C!HhqgG-oKf~re0k+3cALo=I#ow-pbDpDDx5x|&SYM2cAL@oGmrb5NbZeeg(_0CLC$&h7u%#e>M-e^wD|*z#3_Ofc)6@xk;JxFV(_`f zs^DzKH(X?IvFF#`gDLMM44^+2A`0Kwx@2YPr4#*@D!?4=c>E$JHOR#uZygclN9W zWb}_=G18FS5GlNn=KQw-bPr{X%)SEOL^8mtrSIZfK7ZBhv*>)=2cv2oMZ9!yP(2-ikX6q(%lpZ%}PSqO8e z%KvqU_v+Cgof|Ouh3|{WLw1rUSQ>3lqk*S;sLKMvrm4AWxJQT=x^EfO!b{WE{I^L! z52?1?O$!iyLrV>I`)(+0(*4aeP8F2*=(*5rV)NM(P4_Q$uwT`a{N?+*@pyq*J_nU0 zo2UAL4uYo@3(7T&FP&|%Lj-P~M^XwL6FRj$ju0?C8zxz{#$6I?cTbnSiB?o;P`+R* zoXTr}=&9y68DRTQh+Bn1RPvsK$#6mq3*NNsi>DX~je6SNruZT*Z;>td_6?DayIA;s zuypa}jXC{e)JmzoiGfKoft+Yjxrz4l6r?m@UUrNcN>|~J#PdG;8j4o!1U@X^cQi|E0%dO$!H07;LZ49ui9%NL3+l^p^Mt-C42(79Bt92AQ z2eBhyToaW-W>~=lK`F=@R=h0T4@uwcyrwrFLt%{p(BOdx(ygTfK5fcgqFPEUBe7;HJO8fbp7iji-(gsaxcNTaR+R8 z`uc0Y)L)}kD_t_(4nWnGbm-VWFs33B0do~O_Y0`VCBY0ejKd@|Uy?B8j3k(V`Ewi{ ze@Cz&HDl0-cKMrG=q@$>*EBJh z>IkRsmQly}-btcQUtJcld{SIVp?xps;tT zOgv=@Nvadkv(df8?wlADn$-Z#p8D4mV0fnID}q|JW3bqBMX3ujD&Dg?9V7=gXe!=FTR2@{yvL<`+rbp|7C~?Z8c2R zd+)M+-NLsCe*yXIgLH!O=OgvaAL7agmXgSQl6R7mH__W8YZ{`0ZI$VG4!|(`_Yh(F z-VWYV^W2%#joyzJk&=5DyAj81EprH*pl4{oX0UW?DbtQ@$I!bjj*s7GnnDD>4qI}a zKBXOzf4+7a^^-y3!T2$O5nSV&QuRny96AX|^e0*SafDZoUFKW9OM}qx1wupU?k&Gs zRA^AI=zHgoZvEo#25`xQ8M2AlBah;4yP=N^o$(N1J1n6NChKr5sgA+L17zwFBNS|U zHkyc-Nnu$U3C)cRx$+OwjMIYUnh1N^LD*AaL15lH0^feP@p$-wYSSLN2y&~PI(N-8J3LTh4!@D1Okg0xp!u=u%wDeFd^<6G*mt@p<7Iip*HCctuk1PX&~YUOng^heNDw8XB{xKxi$6D zV-@*<=F}^SL^_usfp}&x3Wa-?6GRK)P6)b&PWB??J~Lkl>}3G@VbN+>*0hWQ-CYA} z(22Nt{E@1W(wl68nFPuz+7iMW?O#z<24Lq|AMP7L4Mh@q>u|;B-(`pk2>*=EyxH~H z`!egY0D=}*h`;%T;82u|>6=iI)t!xmBg{6uE$|;QVSvYmvf-vK?xiiV=bCp|i%b|_ zk*fvFzkwM_=0UqK2T}u`X4>&5M#e?c=MJWomS30PD;ia!BhEx|xj33+CJq0;kQ#OU z!O?0TXFFDFvRO8)SE1QOIn$VRJex>e73%OR+A?}nte&wyd8>*8@=?f1A&Huq^#svO z+KEXoia)U#*5!moA?N<-U)@5g&k;v>kl4~&lHk|X21=+|5TX8EzO~iF()@KB0_vT1 zQ*{ikbO9vY>@OZ;9cYy?!B+cJD){6Yb$nY@6Vw{D`&S;D1reG+&2pj1QBwuN;jYI_ z@%PnEXKSte-$iufG#{`eca1x44VWiz&lY9}aSlVQ-U#f_%%N8_t1;%UIFl4R)F}lW zX?rjn7TFoXboQyi{B=XPj~o-fboe^}yws^KkJ366l+}@h@<>Jd?fm{-X!Huw?yWMq zBr~;uwDLZhCG$f8Q}Y+pIQ$)7Z|qsT-w02N0`@@gVh^QGdTnG~$zAtHJ=%eU_+S)$ zeiy?f+E{eC8lGbmfp^T)SpT-TWp%ABiiJ&;(0`Jc@^l@6N#!m%0XB?CUp$Gb3++CJ zkNZ+ynJs?wJgqgKg}j(R21gmfWSw!+b$8hU1>~=b1gHzNuH!ph!M8eLH=Rft`n)ME z!6B>?7W5S?XsZj7AY|_vKSod8+pNawd<(CE`Wzgu3@z>*YluacXihP-2> z8h?KB?eN}wumfjihaaf1KQa?DQ^E#>6P-1F@cJehqTbzpZz=XB&l1R0YQ~t+9)E>b zmpn}$4&5W+f(g-{;N}_3wHI!Z>Cff;7My{gu1YkSldcsO2r^LM-`VC0R(ZeLT*`6{ z+QHIj@Z^94UNy&HReSuF7lR%bvZ5OKnf~GK$}d~sViU%RxK^0qUkuK!Xq`g(yiQmw zjJYoPhq{l@^4lkE`H{!V9!Ttup(6t?L?BS=kwT8Y(`ttmB5pxd9atyw?IAT{T)In$ z_k5(JaBGL9h4D>dZ0W%^gx5t2d!!_hrzR>MrdLy}ncVdCs&O@OiZf`DK~61tPsxqh zLQ-}rhfSu*wT=AGz>y+C{z<{_$i$WDgdJqGOxcbPH4!F!!YbVHQR~IPj>{KN!xll4 z6bAF=da5Twe|hSi(LGY}aFjSB>le*oGQ`>Z7e<|Io`gb@s(7p4MH&gZ^_X7dd)3y5 z^}zP7!r*QP42Y@$>q8{;{mu)I$lU9V?eMMcv1#E_lB1AyvK|pbWhDhvUpgvao`X$a zCH^rHev2Z!&(_sd>Aa~A((^dOInK6>;oI^pr(DwZL4bGAQjH$ffJNuVT%{Y>;XP;- zH}$67Hu(djN?R4H^J%?^00qV)7QK}$P<*xDg*xZsT(*rZ5ne2wGEmi3*#4(4cgQ7b zIQmRe5Mkkg;qry86!_;X)IU}m-}X(`)p}N9#6BU-Iw>dz2qk|l)1+dxla5|VGx_oh z)(H+uIice<8lZ#Tztl77xICEr7uf=@%4&c+Jekmwdzu*oEr+ntBko+=kl$vR74gAl= zgwppA=TL*{*Y+c(XX-B2kX&t5XSEZI5X;O7?yQ9`V)*|JtslRApmqrSr4 z*gW~o^GJIy@|0vY|O20HHDB{oj-+CB$qK9 zf-a$lJt9E{Jix0aC$ah+T7tF-J{5K3CRy7_>}XpFXKSw84t7Jo)3o-`j80Vt49B$} z4M#a$pX>gn9Ib3gpbTumTHm<7sEf`K0$xm*5yUOsL=Z679K1_WCGfnGn|+n&d0P_g z+G>@@rUiJcsRyB%&BAv8TM0GN0l?Rk%}(z`$-X-u&z7&M4t~znc;ms&qc!@T3aam6 zD-3XsRSv?MX&^`om_8m}d>Ncw#<+{rcO3PnakevG?1LFsHvVGG-c$)45msWq#~a(Q z?5}>4G|*9JQN3h#?9_bGaZlA9=3db<|}qbxPdhtJHfVr_f4elH&1CNOhGiG}P2!z=iVCX;lGz{Fhaoqa9&Z}+ z^cdss;JSiqhvp>R=kAp)W!tgw_#NELPG6ZXZwMDAg(yuY>>`tgSKNra3ud+-ucjxJ-f7+*U z;{|i5WUfofAPH9b^EnsI!-AJrr#->(_j1(K_R);;EyqI0t#Rwy@Z@n5^&oTw370wW z38qtEg@Q_;`W(f)n?V;I3z&J!{hS#QRirO;_T8!yCDRAe_YRc-;)i~)$TOSfv{>3Z zEoA<-fmEF_p%u2Jiv@ap&Q}6yl=}k8LOM)(8TN?>742u5b~NWMoW={zmcvbs@C2}P zB-N^Ka-@knmySghnD4*ONkQwmKdO?Ci#(U19Y zk_yn_8)Pinm@|Xw)y^Ew>>Kqk)j!Pb866nk&EP(|U4TI$zIH#m*LK?Q-^Lm)`x&{3 zDk(sEHC(jtqDd3sdMR#;k2+uBDZg{5(LE~C;XH_5!~`;MO*$;-E!T?vmhu5bFj!Zd&7G0oY77g1|Oo3q87X%pm z)33BqXks^8TM3GlczI98MGFjn{PS8RUm5G2)}9)nLHMQluK*x@IKdNJINA8wFt}pu z<+tOg_GaJBGJati3rJO}YI`f@^98?Eft5#ZJYatFX3X#-FaqCT0%_oBEk9GyTe?FWSmfUfe-lyhNg)IvM68?HOH$+@ML3(B0%5 z?}JQ3!KeH*Hjre5JxU^0awDe3VOKYGME-wn;Kvcm<4F5mMBXRme_x@IK-V))hhrK1 zZvlQd!O**dM9ms*_5T#<3JKBEz2ZT%(h%#A6?pldRA}V?)SO8sd0t5|<){B->Bt~z zRRq$}4vPQD(!_m>gwTn;g8u*Y<@IZpR+KdE|1Rl0=AFoTkKbyQwlYlotoIWcAXkWc z9`vORQR+baBQOb@IKV##&igy=zdNsA-ynGo+Ct+0uexh2bJyX|pHCkFq@%GqyF<{g z+$sAy^&JQXB*!%n@Uio_x6nbO3 z!q28M;EBv#7_ujYb~&!cOk6ZlF_=sLm8KNOS76+UN#-KxYulii0DT2Y1o|qS>S<-iJPhj13Wt1yJcTcExP0 zt&?O#37GNvwGG%8Mxw*wJY0=LFh7DThc4#G(CAVj=K);;A@Mu00drsn6QuSW6G)}Q z(-)1tts3%WkJI&l-$g?rEZbIKTTEkof4&jz_Jk5}Ip3ezS$R_zEH5g}wKEP2qegvK zDcA^bOiq!-=D}~}nq)%dy8dcNTx2J=*}Ch@j)2tV4b zSwYY1rqK)YO;_^(j7^+JH{7X`=_W=He{rRegO!ZcaI|iuks)kE=RFp7@I&KQ@{11+ zD2`Iqlk7rN-S0>ac$~v_9Fu%ZdgzY&dfv2tqC4w3;09fX?k}#F_Gg;6*<8{QWl3Sj zhNxsT(0bTI=zKyzdjBI-*h_EQD(9*n!Rd({(35#U0Om?Z+c-M zjPgu-V+=13lm77Io|%-%u)!X3^L`OOGL8xbD?!k^dE5TpnBUanZn{)W5Xs$IXGCGq z=hqS&yMTb07^kXZt2@w5D-C{jy{Q^DiE&MBJReuJQ1rbN;>N zXl%GjVUT5ifjXm+v?^?l!#9T~tSUAXNSA{e>eT@bY;|k4!AvR4hdtP1^1l}|<#{7i zJ2ROq!Rv(}?biX95_ldF8)P$xN(1lBoo}llrH+;0I-2uzkDc{(98r2=1lf6+5VeM_ z)yse#zcK~2--S!~hl!r`L)wVFKre~AxRBXX5DdQ6`11ur*6($uh=^2NrXFr|7HYN2 zz2{r&m$1==pX28&;WHeA0yN0CJYnw&sVZdKk;UXxE#8oB_dn6rre5aC(d;2QJgsY-d=|r<<$e?)pxXh8sRB;vIG!uHj(a ziZ?=ogTY{4)B11Ue?i-4H#~CMQoIIOxe;sxjsESdQ#tc*GdNH&U|jy>#TK`#Kb|U= z$&>Pp--Pev6om0wvb*UnqvaTNyQxcqHJ8nbaX^Q)`>6+wlTBt(lR1b@u|A_+1lai>}`bIh@#f%l?w<0G{rU8EFiRqX5a#=73 zDr-X!bhqiNH?Jj3IVK)vc=aUbcDh{>+>3VOo8-N5_(fX0-g%3iEydyHBG<&*e{PQNjW@V>&A`f|jtdd}NH30m?yYbd;)@xLV z@UUntdep^NKh!Gl1nK}3)(seY{}rgCPs3kSJpjfS?GF2On5eysK;Mlm9ex9uPGq3V zM3vS^Mfv?8o;&N&w@cVW=kRp;n0Q#IP%-a>HtUY(leRRs*?*C_+d6|a8^Sy5pI=b; zD6+VWGaT~XXm$kC1vOt>4xjQ)a;0YW8@eIC0UXtJ?cHOpXKCzgKrG(k|4?4nVQD=* zE=G~-{5(RB?hsIS?5obkFXE_LdD1|4(ASM0FJ8#4gWiFR)UDJp{QLSLwdf$SJ&Q^R z{lb=^iQYmn@{b8hcB}qC)C#_ZeFQh<+d>x|5yOahppGZHIob++Bmvs4Re>Yy%W~mk ziJzg41;Y4Q%wD}Yl6hrxqLp;$T{sI1=n=b?O1-(n{ly(zIk#e%06>@!!-}YSNWJv; z%vqAK{G$B#+`T?{LF=(m?@?yS34hTa^mkK#5!q>lvCY!U6;@!GuZrIA?#I0J8WnHd z$VFs{;VkNMvKB}M&?qoafQou<>yeuB$x7zywVtaW&Qiq~@xCZ#8N0kcXO+b z#!BtfJYf0y+(?K?I@M;M7MB)1|3|lDf^XrmuCk5dPieNFudKC_=;{hy+|bj1IEEjs zX-ggZ!0M~xDtzCT6oLlrIecagDjCN#Rjl~%&-0=zAd~fXUJfX86-8Ce{+{`@sc)vcJ>!eu}$Q7fBst5 zSO8V2+3C^LWPn$3r>S$NOKei-Ku~EA~SpFy6pxQSTJ8`*aI~~(g z@2GuxnuPiqjay&M95eHi4Mb7X`FH-+4|Pr(G4IiPwEnV*)dbG{Hmfcl6T9g8uHPZrXUl-fHYhsqZ`L1A+@1ZIKs|cDD}BD( z$4}D~jxZtbkbOPqWq-cnIR3rhqqZb}DV!Az?;|Ehl|r!4$ckqsq7e9OfD%>`Wtuqh zpvs@wc$l770_PVfQ4(pRH0ENqLkx8ecIrcGYVzFsO3vZ80pArOs>7g*ueZUR6Z%l< z3`T8auSxPOG+ZGy>iGuB+tQcfDQ6A;D&gP$Ct6CPFwg=e95RyN8ZI?rG;lwL)G4!v zAxIbZP*GVgK+j##Jco2-6nk5NGEw*EeFud1N9_ssYg2S3TIRIzA=a&4xt&aQs5%DT zqwp}IMje3&@YQ7J-Qfvy;biNv_|+bAA(fFGrDq}e19>|CdSv>ZbiNC&vZeQZjGhlX z;6sF^*KMFAZ&N@Z4DA9LZyL1&Zc&MrfY($OP4|95uAML@KP~eNvH+?mPDUK`7=vOi zM(kY8E{h70-j*cTM=p$(Z_x%y%_OA7I)a$tk|tv$dy;v-TDi~pBY)UOr5gJbYQt#s z7~@ce3y7PTFcRXbxUEV1gOcMi2$&_4R+Ya?-fS-63@`zM#9SJzsCFzI+;%qtrSD6f zzU|nGc1pQ=VHsDAg+%smSs$wa?@C?k++OYITngo+$bDhX>6bLT)>Z*e@;P55C?BM~ zKG;b|beQa(eH8;%3=^s*rr~8?YnRX~1N9kzo-3h{R}?X+9%2HfX^()N?xU2~U<%e{ zE&Nu`fSue&!J<_e>B890ra^UK0B z{(5qu%ezrjCxcdcV_3!5rMb1y59h7hq1`eyh0P3Zga+vXiMJQ9g%TM8x2oGIY!ljiMD`C8 zbv1|VgQf409`MGKk@B(QTBz4^{E>x~OQtYyVjjJ0Nf5l2*7@LoN!2OBEV1B? zLdms!pMLE>*Z!rUdG#X?pGnLu%X5b0EvXE;k-@5yo(5VHWnIM{|Leup{)A8R+bTO+U@V(1 zXrRio?~9{L{(8U2jbntYS!=Vr9?uGwa;13v>SV=^q~b)#*sj~O;?NKLE#PA%6ixA z1xE^wuFK@nd|YUh^}0TXc+3^K^-W0n6;2s47a{{H+mcYf#l-x4{a{>Q=53@XJ0=kz zG82}kxsWq;xar8*p}Nzjsb6-P@NaBX&upG=$xtWxtJ-K1iTXI)c>{wkSYep!sJLyD zKphD4@mExZ@(Yp)_B;^!7oh0)`HB-D0KDHC+9v*Ik;L3U)lEpk)b$pJbMCl8? zVG!yAYF%JpT2pwm?}wR&QQ}ms>>ccbL|wyYuDwn-*88=&ftpf@6)iUgJ#3GNu`S7k$l@(O=KQxp z;~ULR1~L^ZFJIt#0&`efpTL`c?K>u zfm|1w^#fCNe+Wb}wNEv_aQ!kx`7=RB*@b-Vu~wx4{?>M4|1D*wa{EU_6IF-tRrBQ( zA2aozoZ&2N+>8%mG+wN-{-51T7zr=vnsRh?@&?d`O~X*IxA8Y_FjWsT$4)(!+Fq74 ze0G4eRY)TO?~VaP=|B`3Xo(UYYy9N`YnA-cv-8Ncc!4#Ch~+`lcV*<*CO#}u`Fq=T z9?lpmA~&KjfI9yLrU#`I#`KH2#_85#2aH zSbJ9|+;hBfBz7f+%c=g#B9<9sUFM)pf5VOC@*e3O1&SdcJS9m54cL0{MWC;csA~Hs z(H`lCApQf#=;dUJLnlp42myyrh6M+r0=*26EE%&NHrfc#vph~4Y8gE8)=fval}AO} z2VCCOl^v7!hp6t28+ZZY6Q4+BpJ6pZn30+mcLVkkVPD+LYdi0?t>9~A*YOi(s)i8# z8E>zrt8Mlwx;1cMzP#`#^bSU|vPn~v){JF~V33MbgkPc6U=>wGIl(^>Y{UV|duQxz zOPZ9M6(_=XWt;R74ht*2=VLUD|AD0~5e(Gav-=s(dZ)w~NL?rwu_QIo8S!)9GgsC^ zY-#vf+0t66Al@CpfF{r3OOkPEnHH6Fo>=Y9TMbcB%aDHruI!9Vtmqq*fuEv60oq3J^cI#U}b%73gT-3j2Y7 z@nw%)&|+l)kbv?RLfjicbBS{82J#d)b+}&CH+eo#Nok{bkKKQ*WtJTUYJfsr2m86| z%!NXZz-E!J1SP*qQET+?3^7y4Y}7yEgri%1H(eJaruH0}hIyD*3m>N)(Ls?uBzDJ9 z3H+mK*9+LaI8!vs>lI+tH}X6TT&!S65KAsVAlv$#R9Ey4#^?u)HvV-dcOq!Yt;4&8 zJhkX2g6;(Lhi{a>r4+q6t$wv)_7it0ohD?ogW^#YgFo6 z7IGf9N;pGsBaJK0DgvyS3d*%xD!8WqBpQ$5e1)rY@cH9m%B5EaXno}w{$3WqCFS8R z@E_Ze*E#**F&QLj9tGwB|1_O4jVvdp`*GyNyeYp)W1~yvgK=JwR~h`5SX6MoFKA7Y z#x2MmqpKd_qq4ByXhj#V!A%12nXXjd&eOVF$B}iYKO2s`!UKw?IhU(=iI{7nW)JV< zU-P^VI83C_9xhSDD9U=roVs$X6veE^r=sNr5MPgY)DGom32^IU1PFEbQ3dD4Uff0& zswPByohm0QYs!7xyVb1b#_BnY;8W^YtJE}BVjuLayBaZnxp|!EC*;8nz4l}jMtS$> z9D@aQ!sudkz-sOK)d5xyz`*tU@V%`d%Z1zo*2rxs1l%qE+M(7&p-KVJQ z#N^|W-Uco7!^fqgOjfmcr;Zsek2RJwrS^4g%wDRX=93oHitgOuEZ1lApCUAiIE2dHv&cQ~J8nDo_`M>UUBPVmsd^hF`=C7K!eli{efjSuYiD6D4 zM3zz9&Av!cCt^l~Ldf?qQe@%UyYy(IHN$(k_5JL&M2YD|iS|`{72AJ;(r{0oWF+Jn zfjH+Xjp$wNW=0rsx6-SM20?Ii*u$+_HoZD#bnK`)_{GjP?9K^$We9&sN`6n&kydq7 zT|H>($a{S=IWC!iSsM{PI)RiSgNKIh`a3MtgD$6frxb?FQd>Bc|1RF+Ub+ zjJAQHAshC`_s3c;rYABZo`}KO|DgIU^Ku>>ya8iGjoP5Xzbe2RxSQFf$i>|wg?~Z3z7XMkrS21rle+96o4vo- zdO~D#Amv>0pD;u@t?7>h5n9F~ul@=OMXHgwejCMELG;5sHHJfJjWU_FlB5oU12tYZ zkF&Z30Vg=iKLj4r8}nRnDc2Evb&}hjHLJ12anHPOHD}xSShph#1i5t-2cdhSrIyDX z(6O*#FiTz-1!M2;Qk*lFEjO5Jo|isDuYv&2i$z4)JknW>c~H2)%Yp|7@09?>o&>5d zZx|S-*Hy)ffFwNx!tvrBiw*o$b%HCYphJhj|JtJP&RLq@NWyF@Op0ph1;KjFo; zNa$J@m?lqYY$P@Uo0pmeK?Ifb(9}-Y7s&g@~>@8L( zgnqCN^#noR-r_7UI-&P{iT7NS3-4p!~MCbczVbj}Z825+a`UNE3ghapHY3 zx+Ojs?d)SZ$-y%Kc3JmVO8k(3W{psvf`z1FHdU4&j@RMxo?F|+q^@pE0U@B~SwKqq zA>9oCGKrITSwRbOLRCl-oZBhD-D40ldEUH4jEEyo@quzF*B!|Dv=#=3!4cv?7d=nL zOdNW)Ft1y(;!cNytglhskG1biP1^9!xT6#JqQbIE_6PAoi?uZOG#O3{(N|(J-%+8qtI~Ucp zCwdwbxS_Ia5J*^;)?SGijwiL6=51tRlf-0^=ks-nz)V?L95 z*?n}|DN5>?D_(yv^U*hAr@^wP$gMFyXy2815>l;7=IQEzf&bok&pQ)jt<4;H1OV@v-u zUfCVt7E_Fpz;o=t8|3S7jfPKkd5EX4``iG>qfHXr z^2rtFVl{=M6lCmGj!3DWBVQfHA=`ib%(%-&nLtqkMs(pmF3WSXSd71ZwlmMt=P_(_M;Dp1giao zHtq!=-iPxb*9OFmgr8SuHI(Py{*@{b7vPX`Ez5?-KO3TaF!rjqpcwG?-wU!7a>ixe zg>urCpiFDTQSd+Yxz6Va>3dcplx-Q>Cat%=5b4xM$0b_qN>zokvA-r$^=i+URbj6L+`UKb;j zd3LSQPt5-)SKx2)KeS;b$ZhdG)VUI{9oR#-5WtaP5w&dezjcNAoezA)Gp(yLWkl#h z@~qDjT+`VCK443To^_0aBI#ZW|AyGjTrjUMUZGGEQ2c)CezIJKtnKK288Kyw$Q#3N z{=XKkJ09x)kDom=FT}}qqKv-A89B$9XM{qMU5>K9_B!L@WJ}gbM#v~cGUBWbWs}I> zWRFC~?{odWe|{d1_vi5*ulM`)e!pJN=kxV0#r>BYihCQb#lc!0a&E2uQOweMujG}A zw3zraz!^2pQ^$pUbS9Hs3;OW?q$}+%T*PLD=f%Ou^qIdHf0!fS)6UCv8olXui^bH4 z!mOIY%P|f6>90d8Z5`U`0AenQHPM0llNBcIWqdVs5^R(SLf802lLnWnZs7z@>VA|k zBkLLttsUbW4rtxFU7SVwgAR3d<#A3;|7q3&MBwpIBzU1{HTx);j?6d{Ej!UAgp7%3 z9a}fjso|E(M*pRPVp!&lP|fWMifdaASpS{*V8P4m2Iz}Bf5%2;)QC}0f$+kDL(v_H z459N9jY1^CVH8W)6euK8^=M20%!-)Hut9~&aJd3|)G)(DCTfll5^{gqY-aaCq_wZM z62Qy@3|hSy;lv|4#?L54^lW~84ViqgCPlim^{p^vqrI{P8NO$azVoh-pq;4SKT@QQ z;!zEv7q_mv*sE+J99SoA_HS9KplvJPc}q#)s5)M@n<7{v zCnptC4Ul?B=7z1Mu!oF6b1tLXJ-NLXkBiWF*o#q(J`V8ZY;rdZ zR>ZmDOkbGnVHy>4U|6m4oxgM)F@^5PkUHqpCwKZxbhUP9B93AI_j}(Jws~eOJAe6^ z51z>V)~$N*KR!|ZsfY((83$iyB>UKN=0UNVyRKL3*wW&(>_!`6t=5wR0`sRl|1xQi z^(ez%ozQqW=ITVtCz;Qqur&K+%%p>{ZGzdW5$1lD^66p)k*GFB-^l@wkFGs!36 zqD3bk`{7F^kM(9yx<{0vEV?(E`om&ynjUW`l5SCAVcn&nWYQoZ*^w=-{FIwy2V_k1 zgv;x0e)x64`ghxJ3k&1Q09CEiqMlmb%`;%o`QmR*s0avJ^I4fjhZsFnUave_5N7@T z>z4GWA>aIJqrWnhm=`qc88-akXsz-Kmb(Z*#nB0)U7WJ@V>EWYXVGe$;h2*CCv(cK zG<(sqIXY$CqLywTVZQqo2y1;Bp-&TIs-8FSO$At&^ims;ev?J!m(2tL@oU)6cRw;q z9oKYaIRnEJ4@h!X8@fS!>;-}bX-SGkMcQgXf%Ou9%f*mp`j9iv?2McxUTgcY1JJE5 zmbN|fp$7(OdDY#{5APzC8|@#s#!E?Sd~hn4A@&t>eed#;5F<8VC-A>+tE(zM$V>9x zyk4!GP~s>n@bzr-yCGAjB8h*{fV#T=Oke5q_{QSD-}Dv8px>Z>lAS1#0n!5{n@#}j z>(ttM)XDxW15j~53GK&a+%2ZQ==v%0brUi*zuA|_Dw4vt{~-M!xHT2>I)=i?NEDMz zC}Mo&c;PE>&U6VaDa4uDCI?`<#Z7>CjYUg#@aHm!UfWlraUn)e-PlXipAr#KW^}Y9 zY^bmMssIp^wxF7OkJN{z?yuX5N?h(NH>y!?JuKTu5E7@Oz)q;9!Sd;5PHLt+JNQtcLE7yu?u*nX*hGbA$g zgwo|lPD#_9WAYuNdfCn@M_LXhNaI7O%yt7@RuI+GR^CDeh_2C z>R%Km zKm)6DF$D#W39G&|`O$Dmf$T%*yoMcHS2`+OEDuzJ3+Fk!_h=PCOe?+E4cbT$Ie)q6 zII~k|P2?=VwZiwfW;^QLlcwsC*n+{lEJsu1pth6fy=GnAg|meXrn}RCGWmD$rBmc* zHa^4H0r(dkjF_FB-KIAyLVyUbzra3gXHG@ymzX1ldXds z%crUg(*X7Q`5LWce#M==njJ!ZBUcX$cdDj8cpNxM`K(@2BiBFj@bZ#R>{l8Wv`Z$K|rtXF#j)QrQ0n7Dm0 zXctsN58V)x6~8b6oPsHm!t#iphq+b3(lniWebC@&0!RUHcVBCcPIa5`g21i)PdN1% zzn*demxm#1{L@)+dTH8bFNZyiX3iAqtE(iXNW}yPCTv14Nb)`-f>BU4i@fWbz-V|j zC~t|=zLMea^Kf%C`~6FdYjZ$^Tx>yBTy^?>*b`*u?kb+cMo$WQo#<2Z-S=^h3eiqm z!1;Sn8bY=cl49|XNY4dpz5j09C+>LmPp-*;nH2}QECP;9V$z$Ooc@T4TBmt^LEK|B zGZ2|sY!r8PtfUU=7IOGXtv{L3;!C~wOzp0teO`iFQIggC%LmE9Y1=u4%GC^;2@lg< zY(PCxeQ`~LkQQeNNvjd=5N;-Lg1X|J!u87AfvN!(QPwTb>(F06Q<+cj>fK@N_WNV4 z*Wh#EMTq~2^BzE#J0wozpzy-fm}9Wa;(V@3M&?H0ZsKTYp*FqR8&2xl`#!_=UTdgJ z>wS0~%Gu!IyL*i%8jbt7mXasfx^#8OjN$8B`>V1=soNIz>OEzxPMZl(aSoq~tAtkf z1baI+nXQu)8%8V;1)Lg$60+biVlFK50Z;az%~;(V<>HOR3tS5M4qvd7sJzbFY_5)s z99?`Lu?^>K+|6WvQ`q9z0w(jJndm7vpaI{RN`@)D{xavXkAL^uJB7So9@Q`!m>t-` zs!%IKuh4oFre1(~=)1xmmV(39e~_S}gvkeod700Y6r!qwCIBooiG0WA_e=dJFTKu^ zpQ6EX(Hl@k2JfXSz{LmEA%k$M3(MWsnBI#wQW07@x$6lSI!(jN4>+iX$8zH+gKF(X z6AWU|Tme+=uJ(|n4L5C012q)n+jxlw^2PstStg+(gF0lt`GWhQzPfAgouP*MR(|ec ziVvQcc3WVqXaULQ=bm7QCI=Ps%KM1K(SiQ5jezO=V3C=nMuoMavz3Cb;??O~V~dZ& z+FfW{s)zFg&qC2oi=El|MPXnb49z)@0O6n>P*!H|)(d~Lp2M|ch+yJrYdtt$THfrB zVj+DyGB2SP${e{9EmeuNr`-J;XXSqbr?sju<8_}kiQ(k~SPoEUN%hbTFJ?6bJbuh; z3o374@u6kG9?f|lYJN3iSM3S=)z(3zIWK|NDZebqT9!hE__y|NeoMwZ`})R}ZjJz} zTVzPHx@#mtQL7Nma*SlGM;RFNm0rm;)ID)IXbp8Y8Q$`^oD+QKqG%*~sKp?tAWfH& zNswrRq-D-SaXgQ!5KEjoE`>Ze$&~Y8v%LR|oL>6r*CPWR73HPR?rgx`D@{LsW*U7x zW4eZnp7Rn>Ul_x1ao4pHe1%tge00;2Y|$)FM=(QzSBXx(A2 zPJ`Vr(O0_+0FLpFZ~hr}DgufyIPl!?w7QjJA1iGlbxqN&+O=ltSezHi5#D}dmqie^ z>m)b;30bn7p}?&as=PeQ0qVE>Hs3cdI^oFZ3x~YQ;Cp8oj@8^^SLDJBo`d+!r`U~u zU8RztyBa`A%c{7<$z2tnW%@zXZ?{)>9q;pXDxc2 z0=EYvRg`^m3Y6}g56cwynuYmW{-_v}#}0OT)GE|*s{ifa5B6Mx0Hf^>q$HmGdDF-o zgSG1*9W%$_(hr)i&*(FCob?L%`FCR-NCc^g=n{K&3)dls%Y>i7h6R!>czCjk?3JU@)<_=rZAsX`?39yVpJ^X~{5=So zMTjl#Y74(uYV0yw@i-l>XkNQ@dhJa>`gdN_m==fgZzDW#qGCdh>|m~qG~cDDtuLQD z+E#Bt2E?{~d{?rY`Hq$QOacW32PIqOw>%|5M*)=e^UwD!9 z3y1*m8U{*7_328Bwo~|c3g~h`Mdd(A23GCvpKF<77l$ImUCEZG(x;Tuy#*9Bu!DR5 z%%tHcOtm12#H}PC_k9d6O1QUU-ysEAfEh@hTw!N6uEU4(7_3f8NmmXGs+LZ;3DHx9 z=hDu7wv=Q09w~9-8D;*pbK#8OB6szn%QOn#dEYmbSk}GJyY6FoGFh``SHDrf8Zb4s zAeh)Ckv&huuH?fA1f|X86yo$G-|gxpgU*Mxc@kTQFQ9^*Uu zUU?fgIG%xyqkzx70v(!4sf=`-b)!By6L#Ig%b7j=a z4RB=y)v*x5>%ExgAVL?7+OVAXoiFVj1IZ4JY#}QmFLQ5BKx~ixNFX)kkI?I*xw)>^L26j)GOqaW9-BB^ zTk0+qq6z%Y1%qJS+I~7)OdA>)$rpg_;(Z5g*^tm#zhdPC^rELjR#Ip(qm%pMm-@!z zjY4*_;o;k0wqZL7dQR5OTNY8QWu-kIr8NvrL&2r?|+OrI6Zjyn8_Ye#%;C;$&7;VXW2-}!WqB*gdI zdZWrcX{@L2PY4i&9Xs|{wm!3dl?UzB9WdQj;%3!qAMO(l&+70|$p&#m8}Y@dv;Xjt zjb-W6Y9~|Z+)ZQ=#<14Xa#DZn;Sl(6wsH~PMzE7ZIu3yP2!&Km z31(T9`?O<}R%^4ng^_gz*P43IHWd9W_tb5A3$HHU@NKb~PdwwR$&YK%!Nm&!RYgI% Mnuf@?>b4R81I3T|A^-pY diff --git a/electron/img/riot.png b/electron/img/riot.png index fe13aa99c3aac79efe1ce0e4dd549656f7e0451f..85e9f8ca74a6cd79a8a1fed0ea06be3d11ffc46c 100644 GIT binary patch literal 10430 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 Date: Tue, 9 May 2017 12:27:41 +0100 Subject: [PATCH 48/83] Fix bug report endpoint in config.sample.json. Not sure why this was like this - has vector.im/bugs *ever* worked? --- config.sample.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.sample.json b/config.sample.json index a65646ac77..3c513f7ab2 100644 --- a/config.sample.json +++ b/config.sample.json @@ -4,7 +4,7 @@ "brand": "Riot", "integrations_ui_url": "https://scalar.vector.im/", "integrations_rest_url": "https://scalar.vector.im/api", - "bug_report_endpoint_url": "https://vector.im/bugs", + "bug_report_endpoint_url": "https://riot.im/bugreports/submit", "enableLabs": true, "roomDirectory": { "servers": [ From c607b1bc8913ab84a3ae169d7cf950dc0d26404f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 10 May 2017 13:36:27 +0100 Subject: [PATCH 49/83] npm is "smart" enough to try and install our electron wrapper as a module instead of the actual electron package. With no way to ignore directories. I'd like to think of this as temporary, until I get to rip apart riot-web and riot-electron Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- {electron => electron_app}/build/icon.icns | Bin {electron => electron_app}/build/icon.ico | Bin {electron => electron_app}/build/icons/128x128.png | Bin {electron => electron_app}/build/icons/16x16.png | Bin {electron => electron_app}/build/icons/24x24.png | Bin {electron => electron_app}/build/icons/256x256.png | Bin {electron => electron_app}/build/icons/48x48.png | Bin {electron => electron_app}/build/icons/512x512.png | Bin {electron => electron_app}/build/icons/64x64.png | Bin {electron => electron_app}/build/icons/96x96.png | Bin .../build/install-spinner.gif | Bin {electron => electron_app}/img/riot.ico | Bin {electron => electron_app}/img/riot.png | Bin {electron => electron_app}/package.json | 0 {electron => electron_app}/riot.im/README | 0 {electron => electron_app}/riot.im/config.json | 0 {electron => electron_app}/src/electron-main.js | 0 {electron => electron_app}/src/squirrelhooks.js | 0 {electron => electron_app}/src/tray.js | 0 {electron => electron_app}/src/vectormenu.js | 0 package.json | 8 ++++---- release.sh | 4 ++-- scripts/electron-package.sh | 12 ++++++------ scripts/make-icons.sh | 10 +++++----- 24 files changed, 17 insertions(+), 17 deletions(-) rename {electron => electron_app}/build/icon.icns (100%) rename {electron => electron_app}/build/icon.ico (100%) rename {electron => electron_app}/build/icons/128x128.png (100%) rename {electron => electron_app}/build/icons/16x16.png (100%) rename {electron => electron_app}/build/icons/24x24.png (100%) rename {electron => electron_app}/build/icons/256x256.png (100%) rename {electron => electron_app}/build/icons/48x48.png (100%) rename {electron => electron_app}/build/icons/512x512.png (100%) rename {electron => electron_app}/build/icons/64x64.png (100%) rename {electron => electron_app}/build/icons/96x96.png (100%) rename {electron => electron_app}/build/install-spinner.gif (100%) rename {electron => electron_app}/img/riot.ico (100%) rename {electron => electron_app}/img/riot.png (100%) rename {electron => electron_app}/package.json (100%) rename {electron => electron_app}/riot.im/README (100%) rename {electron => electron_app}/riot.im/config.json (100%) rename {electron => electron_app}/src/electron-main.js (100%) rename {electron => electron_app}/src/squirrelhooks.js (100%) rename {electron => electron_app}/src/tray.js (100%) rename {electron => electron_app}/src/vectormenu.js (100%) diff --git a/electron/build/icon.icns b/electron_app/build/icon.icns similarity index 100% rename from electron/build/icon.icns rename to electron_app/build/icon.icns diff --git a/electron/build/icon.ico b/electron_app/build/icon.ico similarity index 100% rename from electron/build/icon.ico rename to electron_app/build/icon.ico diff --git a/electron/build/icons/128x128.png b/electron_app/build/icons/128x128.png similarity index 100% rename from electron/build/icons/128x128.png rename to electron_app/build/icons/128x128.png diff --git a/electron/build/icons/16x16.png b/electron_app/build/icons/16x16.png similarity index 100% rename from electron/build/icons/16x16.png rename to electron_app/build/icons/16x16.png diff --git a/electron/build/icons/24x24.png b/electron_app/build/icons/24x24.png similarity index 100% rename from electron/build/icons/24x24.png rename to electron_app/build/icons/24x24.png diff --git a/electron/build/icons/256x256.png b/electron_app/build/icons/256x256.png similarity index 100% rename from electron/build/icons/256x256.png rename to electron_app/build/icons/256x256.png diff --git a/electron/build/icons/48x48.png b/electron_app/build/icons/48x48.png similarity index 100% rename from electron/build/icons/48x48.png rename to electron_app/build/icons/48x48.png diff --git a/electron/build/icons/512x512.png b/electron_app/build/icons/512x512.png similarity index 100% rename from electron/build/icons/512x512.png rename to electron_app/build/icons/512x512.png diff --git a/electron/build/icons/64x64.png b/electron_app/build/icons/64x64.png similarity index 100% rename from electron/build/icons/64x64.png rename to electron_app/build/icons/64x64.png diff --git a/electron/build/icons/96x96.png b/electron_app/build/icons/96x96.png similarity index 100% rename from electron/build/icons/96x96.png rename to electron_app/build/icons/96x96.png diff --git a/electron/build/install-spinner.gif b/electron_app/build/install-spinner.gif similarity index 100% rename from electron/build/install-spinner.gif rename to electron_app/build/install-spinner.gif diff --git a/electron/img/riot.ico b/electron_app/img/riot.ico similarity index 100% rename from electron/img/riot.ico rename to electron_app/img/riot.ico diff --git a/electron/img/riot.png b/electron_app/img/riot.png similarity index 100% rename from electron/img/riot.png rename to electron_app/img/riot.png diff --git a/electron/package.json b/electron_app/package.json similarity index 100% rename from electron/package.json rename to electron_app/package.json diff --git a/electron/riot.im/README b/electron_app/riot.im/README similarity index 100% rename from electron/riot.im/README rename to electron_app/riot.im/README diff --git a/electron/riot.im/config.json b/electron_app/riot.im/config.json similarity index 100% rename from electron/riot.im/config.json rename to electron_app/riot.im/config.json diff --git a/electron/src/electron-main.js b/electron_app/src/electron-main.js similarity index 100% rename from electron/src/electron-main.js rename to electron_app/src/electron-main.js diff --git a/electron/src/squirrelhooks.js b/electron_app/src/squirrelhooks.js similarity index 100% rename from electron/src/squirrelhooks.js rename to electron_app/src/squirrelhooks.js diff --git a/electron/src/tray.js b/electron_app/src/tray.js similarity index 100% rename from electron/src/tray.js rename to electron_app/src/tray.js diff --git a/electron/src/vectormenu.js b/electron_app/src/vectormenu.js similarity index 100% rename from electron/src/vectormenu.js rename to electron_app/src/vectormenu.js diff --git a/package.json b/package.json index b8a4accc82..884811af93 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "riot-web", "productName": "Riot", - "main": "electron/src/electron-main.js", + "main": "electron_app/src/electron-main.js", "version": "0.9.9", "description": "A feature-rich client for Matrix.org", "author": "Vector Creations Ltd.", @@ -165,9 +165,9 @@ "target": "squirrel" }, "directories": { - "buildResources": "electron/build", - "output": "electron/dist", - "app": "electron" + "buildResources": "electron_app/build", + "output": "electron_app/dist", + "app": "electron_app" } } } diff --git a/release.sh b/release.sh index 9d02e98e93..c245456051 100755 --- a/release.sh +++ b/release.sh @@ -2,7 +2,7 @@ # # Script to perform a release of vector-web. # -# Requires github-changelog-generator; to install, do +# Requires github-changelog-generator; to install, do # pip install git+https://github.com/matrix-org/github-changelog-generator.git set -e @@ -15,7 +15,7 @@ release="${1#v}" tag="v${release}" echo "electron npm version" -cd electron +cd electron_app npm version --no-git-tag-version "$release" git commit package.json -m "$tag" diff --git a/scripts/electron-package.sh b/scripts/electron-package.sh index 87e353f746..a5718df832 100755 --- a/scripts/electron-package.sh +++ b/scripts/electron-package.sh @@ -90,8 +90,8 @@ npm run build:electron popd -distdir="$builddir/electron/dist" -pubdir="$projdir/electron/pub" +distdir="$builddir/electron_app/dist" +pubdir="$projdir/electron_app/pub" rm -r "$pubdir" || true mkdir -p "$pubdir" @@ -120,11 +120,11 @@ cp $distdir/win/*.nupkg "$pubdir/update/win32/x64/" cp $distdir/win/RELEASES "$pubdir/update/win32/x64/" # Move the debs to the main project dir's dist folder -rm -r "$projdir/electron/dist" || true -mkdir -p "$projdir/electron/dist" -cp $distdir/*.deb "$projdir/electron/dist/" +rm -r "$projdir/electron_app/dist" || true +mkdir -p "$projdir/electron_app/dist" +cp $distdir/*.deb "$projdir/electron_app/dist/" rm -rf "$builddir" echo "Riot Desktop is ready to go in $pubdir: this directory can be hosted on your web server." -echo "deb archives are in electron/dist/ - these should be added into your debian repository" +echo "deb archives are in electron_app/dist/ - these should be added into your debian repository" diff --git a/scripts/make-icons.sh b/scripts/make-icons.sh index ebb15852c1..19e48895df 100755 --- a/scripts/make-icons.sh +++ b/scripts/make-icons.sh @@ -52,7 +52,7 @@ cp "$tmpdir/256.png" "$tmpdir/Riot.iconset/icon_256x256.png" cp "$tmpdir/512.png" "$tmpdir/Riot.iconset/icon_256x256@2x.png" cp "$tmpdir/512.png" "$tmpdir/Riot.iconset/icon_512x512.png" cp "$tmpdir/1024.png" "$tmpdir/Riot.iconset/icon_512x512@2x.png" -iconutil -c icns -o electron/build/icon.icns "$tmpdir/Riot.iconset" +iconutil -c icns -o electron_app/build/icon.icns "$tmpdir/Riot.iconset" cp "$tmpdir/36.png" "res/vector-icons/android-chrome-36x36.png" cp "$tmpdir/48.png" "res/vector-icons/android-chrome-48x48.png" @@ -79,17 +79,17 @@ cp "$tmpdir/144.png" "res/vector-icons/mstile-144x144.png" cp "$tmpdir/150.png" "res/vector-icons/mstile-150x150.png" cp "$tmpdir/310.png" "res/vector-icons/mstile-310x310.png" cp "$tmpdir/310x150.png" "res/vector-icons/mstile-310x150.png" -cp "$tmpdir/180.png" "electron/img/riot.png" +cp "$tmpdir/180.png" "electron_app/img/riot.png" convert "$tmpdir/16.png" "$tmpdir/32.png" "$tmpdir/64.png" "$tmpdir/128.png" "$tmpdir/256.png" "res/vector-icons/favicon.ico" -cp "res/vector-icons/favicon.ico" "electron/build/icon.ico" -cp "res/vector-icons/favicon.ico" "electron/img/riot.ico" +cp "res/vector-icons/favicon.ico" "electron_app/build/icon.ico" +cp "res/vector-icons/favicon.ico" "electron_app/img/riot.ico" # https://github.com/electron-userland/electron-builder/blob/3f97b86993d4ea5172e562b182230a194de0f621/src/targets/LinuxTargetHelper.ts#L127 for i in 24 96 16 48 64 128 256 512 do - cp "$tmpdir/$i.png" "electron/build/icons/${i}x${i}.png" + cp "$tmpdir/$i.png" "electron_app/build/icons/${i}x${i}.png" done rm -r "$tmpdir" From 6d94f35c33a226d126b9773c9484b9842377b83d Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 11 May 2017 10:35:56 +0100 Subject: [PATCH 50/83] Automatically update component-index Following changes to the react-sdk, reskindex can now be updated using the "-w" (watch) equivalent of the reskindex script. -Alter npm scripts so that reskindex is run when building once and so that reskindex:start is runwhen developing -Remove and stop tracking component-index, this will now only be created at build-time --- .gitignore | 1 + package.json | 11 +++--- src/component-index.js | 90 ------------------------------------------ 3 files changed, 7 insertions(+), 95 deletions(-) delete mode 100644 src/component-index.js diff --git a/.gitignore b/.gitignore index cba50a69e7..6dd2b988c3 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ npm-debug.log electron/dist electron/pub /config.json +/src/component-index.js diff --git a/package.json b/package.json index 884811af93..a1f06b00b1 100644 --- a/package.json +++ b/package.json @@ -27,22 +27,23 @@ "matrix-react-parent": "matrix-react-sdk", "scripts": { "reskindex": "reskindex -h src/header", + "reskindex:watch": "reskindex -h src/header -w", "build:res": "node scripts/copy-res.js", "build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js", - "build:compile": "babel --source-maps -d lib src", + "build:compile": "npm run reskindex && 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 && build -wml --ia32 --x64", - "build": "npm run build:res && npm run build:bundle", - "build:dev": "npm run build:res && npm run build:bundle:dev", + "build": "npm run reskindex && npm run build:res && npm run build:bundle", + "build:dev": "npm run reskindex && npm run build:res && npm run build:bundle:dev", "dist": "scripts/package.sh", "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", "start:js:prod": "cross-env NODE_ENV=production webpack-dev-server -w --progress", - "start": "parallelshell \"npm run start:res\" \"npm run start:js\"", - "start:prod": "parallelshell \"npm run start:res\" \"npm run start:js:prod\"", + "start": "parallelshell \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js\"", + "start:prod": "parallelshell \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js:prod\"", "lint": "eslint src/", "lintall": "eslint src/ test/", "clean": "rimraf lib webapp electron/dist", diff --git a/src/component-index.js b/src/component-index.js deleted file mode 100644 index 4bf0b0f984..0000000000 --- a/src/component-index.js +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/* - * THIS FILE IS AUTO-GENERATED - * You can edit it you like, but your changes will be overwritten, - * so you'd just be trying to swim upstream like a salmon. - * You are not a salmon. - * - * To update it, run: - * ./reskindex.js -h header - */ - -module.exports.components = require('matrix-react-sdk/lib/component-index').components; - -import structures$BottomLeftMenu from './components/structures/BottomLeftMenu'; -structures$BottomLeftMenu && (module.exports.components['structures.BottomLeftMenu'] = structures$BottomLeftMenu); -import structures$CompatibilityPage from './components/structures/CompatibilityPage'; -structures$CompatibilityPage && (module.exports.components['structures.CompatibilityPage'] = structures$CompatibilityPage); -import structures$HomePage from './components/structures/HomePage'; -structures$HomePage && (module.exports.components['structures.HomePage'] = structures$HomePage); -import structures$LeftPanel from './components/structures/LeftPanel'; -structures$LeftPanel && (module.exports.components['structures.LeftPanel'] = structures$LeftPanel); -import structures$RightPanel from './components/structures/RightPanel'; -structures$RightPanel && (module.exports.components['structures.RightPanel'] = structures$RightPanel); -import structures$RoomDirectory from './components/structures/RoomDirectory'; -structures$RoomDirectory && (module.exports.components['structures.RoomDirectory'] = structures$RoomDirectory); -import structures$RoomSubList from './components/structures/RoomSubList'; -structures$RoomSubList && (module.exports.components['structures.RoomSubList'] = structures$RoomSubList); -import structures$RoomSubListHeader from './components/structures/RoomSubListHeader'; -structures$RoomSubListHeader && (module.exports.components['structures.RoomSubListHeader'] = structures$RoomSubListHeader); -import structures$SearchBox from './components/structures/SearchBox'; -structures$SearchBox && (module.exports.components['structures.SearchBox'] = structures$SearchBox); -import structures$ViewSource from './components/structures/ViewSource'; -structures$ViewSource && (module.exports.components['structures.ViewSource'] = structures$ViewSource); -import views$context_menus$MessageContextMenu from './components/views/context_menus/MessageContextMenu'; -views$context_menus$MessageContextMenu && (module.exports.components['views.context_menus.MessageContextMenu'] = views$context_menus$MessageContextMenu); -import views$context_menus$RoomTileContextMenu from './components/views/context_menus/RoomTileContextMenu'; -views$context_menus$RoomTileContextMenu && (module.exports.components['views.context_menus.RoomTileContextMenu'] = views$context_menus$RoomTileContextMenu); -import views$dialogs$BugReportDialog from './components/views/dialogs/BugReportDialog'; -views$dialogs$BugReportDialog && (module.exports.components['views.dialogs.BugReportDialog'] = views$dialogs$BugReportDialog); -import views$dialogs$ChangelogDialog from './components/views/dialogs/ChangelogDialog'; -views$dialogs$ChangelogDialog && (module.exports.components['views.dialogs.ChangelogDialog'] = views$dialogs$ChangelogDialog); -import views$directory$NetworkDropdown from './components/views/directory/NetworkDropdown'; -views$directory$NetworkDropdown && (module.exports.components['views.directory.NetworkDropdown'] = views$directory$NetworkDropdown); -import views$elements$ImageView from './components/views/elements/ImageView'; -views$elements$ImageView && (module.exports.components['views.elements.ImageView'] = views$elements$ImageView); -import views$elements$Spinner from './components/views/elements/Spinner'; -views$elements$Spinner && (module.exports.components['views.elements.Spinner'] = views$elements$Spinner); -import views$globals$GuestWarningBar from './components/views/globals/GuestWarningBar'; -views$globals$GuestWarningBar && (module.exports.components['views.globals.GuestWarningBar'] = views$globals$GuestWarningBar); -import views$globals$MatrixToolbar from './components/views/globals/MatrixToolbar'; -views$globals$MatrixToolbar && (module.exports.components['views.globals.MatrixToolbar'] = views$globals$MatrixToolbar); -import views$globals$NewVersionBar from './components/views/globals/NewVersionBar'; -views$globals$NewVersionBar && (module.exports.components['views.globals.NewVersionBar'] = views$globals$NewVersionBar); -import views$login$VectorCustomServerDialog from './components/views/login/VectorCustomServerDialog'; -views$login$VectorCustomServerDialog && (module.exports.components['views.login.VectorCustomServerDialog'] = views$login$VectorCustomServerDialog); -import views$login$VectorLoginFooter from './components/views/login/VectorLoginFooter'; -views$login$VectorLoginFooter && (module.exports.components['views.login.VectorLoginFooter'] = views$login$VectorLoginFooter); -import views$login$VectorLoginHeader from './components/views/login/VectorLoginHeader'; -views$login$VectorLoginHeader && (module.exports.components['views.login.VectorLoginHeader'] = views$login$VectorLoginHeader); -import views$messages$DateSeparator from './components/views/messages/DateSeparator'; -views$messages$DateSeparator && (module.exports.components['views.messages.DateSeparator'] = views$messages$DateSeparator); -import views$messages$MessageTimestamp from './components/views/messages/MessageTimestamp'; -views$messages$MessageTimestamp && (module.exports.components['views.messages.MessageTimestamp'] = views$messages$MessageTimestamp); -import views$rooms$DNDRoomTile from './components/views/rooms/DNDRoomTile'; -views$rooms$DNDRoomTile && (module.exports.components['views.rooms.DNDRoomTile'] = views$rooms$DNDRoomTile); -import views$rooms$RoomDropTarget from './components/views/rooms/RoomDropTarget'; -views$rooms$RoomDropTarget && (module.exports.components['views.rooms.RoomDropTarget'] = views$rooms$RoomDropTarget); -import views$rooms$RoomTooltip from './components/views/rooms/RoomTooltip'; -views$rooms$RoomTooltip && (module.exports.components['views.rooms.RoomTooltip'] = views$rooms$RoomTooltip); -import views$rooms$SearchBar from './components/views/rooms/SearchBar'; -views$rooms$SearchBar && (module.exports.components['views.rooms.SearchBar'] = views$rooms$SearchBar); -import views$settings$IntegrationsManager from './components/views/settings/IntegrationsManager'; -views$settings$IntegrationsManager && (module.exports.components['views.settings.IntegrationsManager'] = views$settings$IntegrationsManager); -import views$settings$Notifications from './components/views/settings/Notifications'; -views$settings$Notifications && (module.exports.components['views.settings.Notifications'] = views$settings$Notifications); From ffa53ca2053d6e30d4a834a3eb3dd22ce65c3b12 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Thu, 11 May 2017 11:17:55 +0100 Subject: [PATCH 51/83] Update manifest.json --- res/vector-icons/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/vector-icons/manifest.json b/res/vector-icons/manifest.json index 2cf10bed44..7536efebc5 100644 --- a/res/vector-icons/manifest.json +++ b/res/vector-icons/manifest.json @@ -1,5 +1,5 @@ { - "name": "Riot - Matrix Client", + "name": "Riot - open team collaboration", "short_name": "Riot", "display": "standalone", "theme_color": "#76CFA6", From 3c5594e03464cf8e9145837cecafa01444aa86bf Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 11 May 2017 13:12:26 +0100 Subject: [PATCH 52/83] move manifest.json outward so it is scoped properly this will matter more when we add a service worker Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/manifest.json | 56 ++++++++++++++++++++++++++++++++++ res/vector-icons/manifest.json | 53 -------------------------------- scripts/copy-res.js | 1 + src/vector/index.html | 2 +- 4 files changed, 58 insertions(+), 54 deletions(-) create mode 100644 res/manifest.json delete mode 100644 res/vector-icons/manifest.json diff --git a/res/manifest.json b/res/manifest.json new file mode 100644 index 0000000000..75b182122d --- /dev/null +++ b/res/manifest.json @@ -0,0 +1,56 @@ +{ + "name": "Riot - open team collaboration", + "short_name": "Riot", + "display": "standalone", + "theme_color": "#76CFA6", + "start_url": "index.html", + "icons": [ + { + "src": "vector-icons/android-chrome-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "vector-icons/android-chrome-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "vector-icons/android-chrome-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "vector-icons/android-chrome-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "vector-icons/android-chrome-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "vector-icons/android-chrome-192x192.png", + "sizes": "192x192", + "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" + } + ] +} diff --git a/res/vector-icons/manifest.json b/res/vector-icons/manifest.json deleted file mode 100644 index 7536efebc5..0000000000 --- a/res/vector-icons/manifest.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "Riot - open team collaboration", - "short_name": "Riot", - "display": "standalone", - "theme_color": "#76CFA6", - "start_url": "../", - "icons": [ - { - "src": "android-chrome-36x36.png", - "sizes": "36x36", - "type": "image\/png", - "density": "0.75" - }, - { - "src": "android-chrome-48x48.png", - "sizes": "48x48", - "type": "image\/png", - "density": "1.0" - }, - { - "src": "android-chrome-72x72.png", - "sizes": "72x72", - "type": "image\/png", - "density": "1.5" - }, - { - "src": "android-chrome-96x96.png", - "sizes": "96x96", - "type": "image\/png", - "density": "2.0" - }, - { - "src": "android-chrome-144x144.png", - "sizes": "144x144", - "type": "image\/png", - "density": "3.0" - }, - { - "src": "android-chrome-192x192.png", - "sizes": "192x192", - "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" - }] -} diff --git a/scripts/copy-res.js b/scripts/copy-res.js index 4702d5cf1b..5a43c4e6e5 100755 --- a/scripts/copy-res.js +++ b/scripts/copy-res.js @@ -7,6 +7,7 @@ // common parents. Hence, "res/{a,b}/**": the output will be "dest/a/..." and // "dest/b/...". const COPY_LIST = [ + ["res/manifest.json", "webapp"], ["res/{media,vector-icons}/**", "webapp"], ["src/skins/vector/{fonts,img}/**", "webapp"], ["node_modules/emojione/assets/svg/*", "webapp/emojione/svg/"], diff --git a/src/vector/index.html b/src/vector/index.html index 331bf68448..38810f62c1 100644 --- a/src/vector/index.html +++ b/src/vector/index.html @@ -12,7 +12,7 @@ - + From f248477f82da6af6ec3c0f6f18ca03c497e2946e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 11 May 2017 17:46:08 +0100 Subject: [PATCH 53/83] stage 0.5 rebrand (rename dist release) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- scripts/jenkins.sh | 2 +- scripts/package.sh | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/jenkins.sh b/scripts/jenkins.sh index 0d441cdd76..312eea4543 100755 --- a/scripts/jenkins.sh +++ b/scripts/jenkins.sh @@ -34,7 +34,7 @@ npm run test # run eslint npm run lintall -- -f checkstyle -o eslint.xml || true -rm dist/vector-*.tar.gz || true # rm previous artifacts without failing if it doesn't exist +rm dist/riot-*.tar.gz || true # rm previous artifacts without failing if it doesn't exist # node_modules deps from 'npm install' don't have a .git dir so can't # rev-parse; but they do set the commit in package.json under 'gitHead' which diff --git a/scripts/package.sh b/scripts/package.sh index b3bc00bf03..cffb6d288b 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -25,13 +25,13 @@ cp -r webapp vector-$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 + echo ${version:1} > riot-$version/version else - echo ${version} > vector-$version/version + echo ${version} > riot-$version/version fi -tar chvzf dist/vector-$version.tar.gz vector-$version -rm -r vector-$version +tar chvzf dist/riot-$version.tar.gz riot-$version +rm -r riot-$version echo -echo "Packaged dist/vector-$version.tar.gz" +echo "Packaged dist/riot-$version.tar.gz" From ea0b166da7f3bb6b5591dbee0f1aa5eeab388210 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 11 May 2017 17:49:31 +0100 Subject: [PATCH 54/83] change wording to not confuse users building repo change default repos to match their current naming Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- scripts/electron-package.sh | 2 +- scripts/issues-burndown.pl | 2 +- scripts/issues-no-state.pl | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/electron-package.sh b/scripts/electron-package.sh index a5718df832..973ea45e82 100755 --- a/scripts/electron-package.sh +++ b/scripts/electron-package.sh @@ -63,7 +63,7 @@ fi if [ ! -f package.json ]; then echo "No package.json found. This script must be run from" - echo "the vector-web directory." + echo "the riot-web directory." exit fi diff --git a/scripts/issues-burndown.pl b/scripts/issues-burndown.pl index 67c05673df..03af5ed7cc 100755 --- a/scripts/issues-burndown.pl +++ b/scripts/issues-burndown.pl @@ -18,7 +18,7 @@ my $gh = Net::GitHub->new( login => 'ara4n', pass => read_password("github password: "), ); -$gh->set_default_user_repo('vector-im', 'vector-web'); +$gh->set_default_user_repo('vector-im', 'riot-web'); #my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 }); my @issues = $gh->issue->repos_issues({ state => 'all' }); diff --git a/scripts/issues-no-state.pl b/scripts/issues-no-state.pl index 9b07ed271f..748809c59a 100755 --- a/scripts/issues-no-state.pl +++ b/scripts/issues-no-state.pl @@ -18,7 +18,7 @@ my $gh = Net::GitHub->new( login => 'ara4n', pass => read_password("github password: "), ); -$gh->set_default_user_repo('vector-im', 'vector-web'); +$gh->set_default_user_repo('vector-im', 'riot-web'); #my @issues = $gh->issue->repos_issues({ state => 'all', milestone => 3 }); my @issues = $gh->issue->repos_issues({ state => 'all' }); @@ -42,7 +42,7 @@ my $now = DateTime->now(); foreach my $issue (@issues) { next if ($issue->{pull_request}); - + use Data::Dumper; print STDERR Dumper($issue); From 25a727b8d8bb7b658da0ff1628d431b615fd346d Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 00:26:02 +0100 Subject: [PATCH 55/83] use full date formats on timestamps - fixes https://github.com/vector-im/riot-web/issues/3874 --- 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 ab910b05ab..a97f54b173 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 8e2e6cee35845f256cfe2f9981a1efa7978d2f0a Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 01:07:25 +0100 Subject: [PATCH 56/83] require indexeddb & webworkers in modernizr --- src/vector/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vector/index.js b/src/vector/index.js index 0d704d995d..02713afca7 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -103,7 +103,7 @@ function checkBrowserFeatures(featureList) { var validBrowser = checkBrowserFeatures([ "displaytable", "flexbox", "es5object", "es5function", "localstorage", - "objectfit" + "objectfit", "indexeddb", "webworkers", ]); // Parse the given window.location and return parameters that can be used when calling From c3477a30a7de80ade690dca05db1f7c1176a5d06 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 01:22:32 +0100 Subject: [PATCH 57/83] oops, rebuild modernizr to pull in new tests --- .modernizr.json | 6 ++++-- src/vector/modernizr.js | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.modernizr.json b/.modernizr.json index 29e620a5ba..06be8b4fa1 100644 --- a/.modernizr.json +++ b/.modernizr.json @@ -9,6 +9,8 @@ "test/css/flexbox", "test/es5/specification", "test/css/objectfit", - "test/storage/localstorage" + "test/storage/localstorage", + "test/workers/webworkers", + "test/indexeddb" ] -} \ No newline at end of file +} diff --git a/src/vector/modernizr.js b/src/vector/modernizr.js index 5ef7778aeb..07bd2fd37c 100644 --- a/src/vector/modernizr.js +++ b/src/vector/modernizr.js @@ -1,3 +1,3 @@ -/*! modernizr 3.1.0 (Custom Build) | MIT * - * http://modernizr.com/download/?-displaytable-es5-flexbox-localstorage-objectfit-cssclassprefix:modernizr_ !*/ -!function(window,document,undefined){function is(e,t){return typeof e===t}function testRunner(){var e,t,r,n,o,s,i;for(var d in tests){if(e=[],t=tests[d],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(r=0;rd;d++)if(l=e[d],c=mStyle.style[l],contains(l,"-")&&(l=cssToDOM(l)),mStyle.style[l]!==undefined){if(n||is(r,"undefined"))return o(),"pfx"==t?l:!0;try{mStyle.style[l]=r}catch(u){}if(mStyle.style[l]!=c)return o(),"pfx"==t?l:!0}return o(),!1}function fnBind(e,t){return function(){return e.apply(t,arguments)}}function testDOMProps(e,t,r){var n;for(var o in e)if(e[o]in t)return r===!1?e[o]:(n=t[e[o]],is(n,"function")?fnBind(n,r||t):n);return!1}function testPropsAll(e,t,r,n,o){var s=e.charAt(0).toUpperCase()+e.slice(1),i=(e+" "+cssomPrefixes.join(s+" ")+s).split(" ");return is(t,"string")||is(t,"undefined")?testProps(i,t,n,o):(i=(e+" "+domPrefixes.join(s+" ")+s).split(" "),testDOMProps(i,t,r))}function testAllProps(e,t,r){return testPropsAll(e,undefined,undefined,t,r)}var tests=[],ModernizrProto={_version:"3.1.0",_config:{classPrefix:"modernizr_",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var r=this;setTimeout(function(){t(r[e])},0)},addTest:function(e,t,r){tests.push({name:e,fn:t,options:r})},addAsyncTest:function(e){tests.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=ModernizrProto,Modernizr=new Modernizr;var classes=[],docElement=document.documentElement,isSVG="svg"===docElement.nodeName.toLowerCase(),testStyles=ModernizrProto.testStyles=injectElementWithStyles;testStyles("#modernizr{display: table; direction: ltr}#modernizr div{display: table-cell; padding: 10px}",function(e){var t,r=e.childNodes;t=r[0].offsetLefto;o++){var s=prefixes[o],i=s.toUpperCase()+"_"+t;if(i in n)return"@-"+s.toLowerCase()+"-"+e}return!1};ModernizrProto.atRule=atRule;var prefixed=ModernizrProto.prefixed=function(e,t,r){return 0===e.indexOf("@")?atRule(e):(-1!=e.indexOf("-")&&(e=cssToDOM(e)),t?testPropsAll(e,t,r):testPropsAll(e,"pfx"))};Modernizr.addTest("objectfit",!!prefixed("objectFit"),{aliases:["object-fit"]}),Modernizr.addTest("localstorage",function(){var e="modernizr";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(t){return!1}}),testRunner(),setClasses(classes),delete ModernizrProto.addTest,delete ModernizrProto.addAsyncTest;for(var i=0;id;d++)if(l=e[d],c=mStyle.style[l],contains(l,"-")&&(l=cssToDOM(l)),mStyle.style[l]!==undefined){if(n||is(r,"undefined"))return o(),"pfx"==t?l:!0;try{mStyle.style[l]=r}catch(u){}if(mStyle.style[l]!=c)return o(),"pfx"==t?l:!0}return o(),!1}function fnBind(e,t){return function(){return e.apply(t,arguments)}}function testDOMProps(e,t,r){var n;for(var o in e)if(e[o]in t)return r===!1?e[o]:(n=t[e[o]],is(n,"function")?fnBind(n,r||t):n);return!1}function testPropsAll(e,t,r,n,o){var i=e.charAt(0).toUpperCase()+e.slice(1),s=(e+" "+cssomPrefixes.join(i+" ")+i).split(" ");return is(t,"string")||is(t,"undefined")?testProps(s,t,n,o):(s=(e+" "+domPrefixes.join(i+" ")+i).split(" "),testDOMProps(s,t,r))}function testAllProps(e,t,r){return testPropsAll(e,undefined,undefined,t,r)}var tests=[],ModernizrProto={_version:"3.3.1",_config:{classPrefix:"modernizr_",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var r=this;setTimeout(function(){t(r[e])},0)},addTest:function(e,t,r){tests.push({name:e,fn:t,options:r})},addAsyncTest:function(e){tests.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=ModernizrProto,Modernizr=new Modernizr;var classes=[],docElement=document.documentElement,isSVG="svg"===docElement.nodeName.toLowerCase(),testStyles=ModernizrProto.testStyles=injectElementWithStyles;testStyles("#modernizr{display: table; direction: ltr}#modernizr div{display: table-cell; padding: 10px}",function(e){var t,r=e.childNodes;t=r[0].offsetLefto;o++){var i=prefixes[o],s=i.toUpperCase()+"_"+t;if(s in n)return"@-"+i.toLowerCase()+"-"+e}return!1};ModernizrProto.atRule=atRule;var prefixed=ModernizrProto.prefixed=function(e,t,r){return 0===e.indexOf("@")?atRule(e):(-1!=e.indexOf("-")&&(e=cssToDOM(e)),t?testPropsAll(e,t,r):testPropsAll(e,"pfx"))};Modernizr.addTest("objectfit",!!prefixed("objectFit"),{aliases:["object-fit"]}),Modernizr.addTest("localstorage",function(){var e="modernizr";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(t){return!1}}),Modernizr.addTest("webworkers","Worker"in window);var indexeddb;try{indexeddb=prefixed("indexedDB",window)}catch(e){}Modernizr.addTest("indexeddb",!!indexeddb),indexeddb&&Modernizr.addTest("indexeddb.deletedatabase","deleteDatabase"in indexeddb),testRunner(),setClasses(classes),delete ModernizrProto.addTest,delete ModernizrProto.addAsyncTest;for(var i=0;i Date: Mon, 15 May 2017 02:24:34 +0100 Subject: [PATCH 58/83] cursor pointer for avatar upload in user settings --- .../vector/css/matrix-react-sdk/structures/_UserSettings.scss | 4 ++++ 1 file changed, 4 insertions(+) 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 739ac88ab9..fe60aacb9f 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss +++ b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss @@ -219,6 +219,10 @@ input.mx_UserSettings_phoneNumberField { margin-top: 10px; } +.mx_UserSettings_avatarPicker_edit img { + cursor: pointer; +} + .mx_UserSettings_avatarPicker_edit > input { display: none; } From fe61a7eefd83af9bc4d33a25235dfe0fe4b45d5b Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 15 May 2017 02:32:25 +0100 Subject: [PATCH 59/83] fix off-by-one pixel errors in login field heights - fixes https://github.com/vector-im/riot-web/issues/3738 --- .../css/matrix-react-sdk/structures/login/_Login.scss | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 93173ed336..3537046464 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 @@ -184,7 +184,7 @@ limitations under the License. } .mx_Login_field_prefix { - height: 33px; + height: 34px; padding: 0px 5px; line-height: 33px; @@ -197,7 +197,7 @@ limitations under the License. } .mx_Login_field_suffix { - height: 33px; + height: 34px; padding: 0px 5px; line-height: 33px; @@ -211,11 +211,16 @@ limitations under the License. } .mx_Login_username { + height: 16px; flex-shrink: 1; min-width: 0px; border-radius: 3px; } +.mx_Login_phoneNumberField { + height: 16px; +} + .mx_Login_field_has_prefix { border-top-left-radius: 0px; border-bottom-left-radius: 0px; From cef26a5b20601904ae104cf1688f9721edfb83c8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Mon, 15 May 2017 21:14:01 +0100 Subject: [PATCH 60/83] fix #3894 --- scripts/package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/package.sh b/scripts/package.sh index cffb6d288b..23d0925b05 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -21,7 +21,7 @@ npm run build$dev cp config.sample.json webapp/ mkdir -p dist -cp -r webapp vector-$version +cp -r webapp riot-$version # if $version looks like semver with leading v, strip it before writing to file if [[ ${version} =~ ^v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+(-.+)?$ ]]; then From 3cead032c2fe1a0b0034c2a3b2c06248ebc2c564 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:27:58 +0100 Subject: [PATCH 61/83] Revert "Merge pull request #3804 from vector-im/dbkr/left_panel_for_newbies_2" This reverts commit e6133820a2f70f94e693f6352da71c03ef5a079a, reversing changes made to d1db602b3a3e735430016af2fc837841feafdb43. --- src/components/structures/BottomLeftMenu.js | 127 +++++++++++++++--- src/components/structures/RoomSubList.js | 19 ++- .../structures/RoomSubListHeader.js | 44 +++--- src/skins/vector/css/_components.scss | 1 - .../views/elements/_RoleButton.scss | 33 ----- .../views/rooms/_RoomList.scss | 23 ---- .../css/vector-web/structures/_LeftPanel.scss | 34 +++-- 7 files changed, 170 insertions(+), 111 deletions(-) delete mode 100644 src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss diff --git a/src/components/structures/BottomLeftMenu.js b/src/components/structures/BottomLeftMenu.js index 63dfac60d8..f378cac628 100644 --- a/src/components/structures/BottomLeftMenu.js +++ b/src/components/structures/BottomLeftMenu.js @@ -1,6 +1,5 @@ /* Copyright 2015, 2016 OpenMarket Ltd -Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,8 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import sdk from 'matrix-react-sdk'; +'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'); module.exports = React.createClass({ displayName: 'BottomLeftMenu', @@ -26,28 +30,121 @@ 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() { - 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 TintableSvg = sdk.getComponent('elements.TintableSvg'); var homeButton; if (this.props.teamToken) { - homeButton = ; + homeButton = ( + + + { this.getLabel("Welcome page", this.state.homeHover) } + + ); } 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/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index ab6c4422d1..c315ae46e9 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -1,5 +1,4 @@ /* -Copyright 2017 Vector Creations Ltd Copyright 2015, 2016 OpenMarket Ltd Licensed under the Apache License, Version 2.0 (the "License"); @@ -84,8 +83,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 - headerItems: React.PropTypes.node, // content shown in the sublist header }, getInitialState: function() { @@ -472,15 +469,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; - let content; - if (this.state.sortedList.length == 0) { - content = this.props.emptyContent; - } else { - content = this.makeRoomTiles(); + //console.log("render: " + JSON.stringify(this.state.sortedList)); + + 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 +498,8 @@ var RoomSubList = React.createClass({ if (!this.state.hidden) { subList = - { content } + { target } + { this.makeRoomTiles() } ; } else { @@ -522,7 +521,6 @@ var RoomSubList = React.createClass({ roomNotificationCount={ this.roomNotificationCount() } onClick={ this.onClick } onHeaderClick={ this.props.onHeaderClick } - headerItems={this.props.headerItems} /> { subList }
@@ -544,7 +542,6 @@ 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 74094ae0ba..ad9aff5f70 100644 --- a/src/components/structures/RoomSubListHeader.js +++ b/src/components/structures/RoomSubListHeader.js @@ -14,11 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import classNames from 'classnames'; -import sdk from 'matrix-react-sdk'; -import { formatCount } from 'matrix-react-sdk/lib/utils/FormattingUtils'; -import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton'; +'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'); module.exports = React.createClass({ displayName: 'RoomSubListHeader', @@ -37,7 +42,6 @@ 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() { @@ -59,34 +63,35 @@ module.exports = React.createClass({ // }, render: function() { - const TintableSvg = sdk.getComponent("elements.TintableSvg"); + var TintableSvg = sdk.getComponent("elements.TintableSvg"); - const subListNotifications = this.props.roomNotificationCount; - const subListNotifCount = subListNotifications[0]; - const subListNotifHighlight = subListNotifications[1]; + var subListNotifications = this.props.roomNotificationCount; + var subListNotifCount = subListNotifications[0]; + var subListNotifHighlight = subListNotifications[1]; - const chevronClasses = classNames({ + var chevronClasses = classNames({ 'mx_RoomSubList_chevron': true, 'mx_RoomSubList_chevronRight': this.props.hidden, 'mx_RoomSubList_chevronDown': !this.props.hidden, }); - const badgeClasses = classNames({ + var badgeClasses = classNames({ 'mx_RoomSubList_badge': true, 'mx_RoomSubList_badgeHighlight': subListNotifHighlight, }); - let badge; + var badge; if (subListNotifCount > 0) { - badge =
{ formatCount(subListNotifCount) }
; - } else if (subListNotifHighlight) { + badge =
{ FormattingUtils.formatCount(subListNotifCount) }
; + } + else if (subListNotifHighlight) { badge =
!
; } // When collapsed, allow a long hover on the header to show user // the full tag name and room count - let title; - const roomCount = this.props.roomCount; + var title; + var roomCount = this.props.roomCount; if (this.props.collapsed) { title = this.props.label; if (roomCount !== '') { @@ -94,9 +99,9 @@ module.exports = React.createClass({ } } - let incomingCall; + var incomingCall; if (this.props.isIncomingCallRoom) { - const IncomingCallBox = sdk.getComponent("voip.IncomingCallBox"); + var IncomingCallBox = sdk.getComponent("voip.IncomingCallBox"); incomingCall = ; } @@ -104,7 +109,6 @@ 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 5b23bb82f8..df3c4600eb 100644 --- a/src/skins/vector/css/_components.scss +++ b/src/skins/vector/css/_components.scss @@ -27,7 +27,6 @@ @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 deleted file mode 100644 index 094e0b9b1b..0000000000 --- a/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss +++ /dev/null @@ -1,33 +0,0 @@ -/* -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; -} - -.mx_RoleButton_tooltip { - display: inline-block; - position: relative; - top: -25px; - left: 6px; -} 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 35787ca0c4..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,25 +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 dashed $accent-color; - color: $primary-fg-color; - background-color: $droptarget-bg-color; - border-radius: 4px; -} - -.mx_RoomList_emptySubListTip .mx_RoleButton { - vertical-align: -3px; -} - -.mx_RoomList_headerButtons { - position: absolute; - right: 60px; -} diff --git a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss index f171591cd6..d3bbce1b19 100644 --- a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss +++ b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss @@ -64,25 +64,43 @@ limitations under the License. pointer-events: none; } -.collapsed .mx_RoleButton { +.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 { margin-right: 0px ! important; padding-top: 3px ! important; padding-bottom: 3px ! important; } -.mx_BottomLeftMenu_options .mx_RoleButton { - margin-left: 0px; +.mx_LeftPanel .mx_BottomLeftMenu_homePage, +.mx_LeftPanel .mx_BottomLeftMenu_directory, +.mx_LeftPanel .mx_BottomLeftMenu_createRoom, +.mx_LeftPanel .mx_BottomLeftMenu_people { margin-right: 10px; } -.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings { +.mx_LeftPanel .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 03476705b1cccf03070bdc55af5139450dd1c1cc Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:35:06 +0100 Subject: [PATCH 62/83] Revert "better solution to incomingcallbox weirdness" This reverts commit be527874730d959fa980e81c897a658a03952aad. --- src/components/structures/RoomSubListHeader.js | 2 +- .../css/matrix-react-sdk/views/voip/_IncomingCallbox.scss | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/structures/RoomSubListHeader.js b/src/components/structures/RoomSubListHeader.js index ad9aff5f70..eb73f72162 100644 --- a/src/components/structures/RoomSubListHeader.js +++ b/src/components/structures/RoomSubListHeader.js @@ -112,8 +112,8 @@ module.exports = React.createClass({
{ roomCount }
{ badge } + { incomingCall }
- { incomingCall }
); }, diff --git a/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss b/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss index 64eac25d01..e63814f545 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss +++ b/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss @@ -25,6 +25,8 @@ limitations under the License. margin-top: -3px; margin-left: -20px; width: 200px; + font-weight: initial; + text-transform: initial; } .mx_IncomingCallBox_chevron { From 9399b7ddf0cf7b272e527b9086fc6fe68db2e66d Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 16:35:17 +0100 Subject: [PATCH 63/83] Revert "fix incoming call box" This reverts commit b3431bb75008b068a2a1805803b91d0ff2616571. --- src/components/structures/RoomSubList.js | 1 - src/components/structures/RoomSubListHeader.js | 1 - .../vector/css/matrix-react-sdk/structures/_RoomView.scss | 4 ++-- .../css/matrix-react-sdk/views/voip/_IncomingCallbox.scss | 2 -- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index c315ae46e9..f741a30f03 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -516,7 +516,6 @@ var RoomSubList = React.createClass({ roomCount={ roomCount } collapsed={ this.props.collapsed } hidden={ this.state.hidden } - incomingCall={ this.props.incomingCall } isIncomingCallRoom={ isIncomingCallRoom } roomNotificationCount={ this.roomNotificationCount() } onClick={ this.onClick } diff --git a/src/components/structures/RoomSubListHeader.js b/src/components/structures/RoomSubListHeader.js index eb73f72162..5618b39b85 100644 --- a/src/components/structures/RoomSubListHeader.js +++ b/src/components/structures/RoomSubListHeader.js @@ -36,7 +36,6 @@ module.exports = React.createClass({ React.PropTypes.number ]), collapsed: React.PropTypes.bool.isRequired, // is LeftPanel collapsed? - incomingCall: React.PropTypes.object, isIncomingCallRoom: React.PropTypes.bool, roomNotificationCount: React.PropTypes.array, hidden: React.PropTypes.bool, 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 e251ecd14c..3d5fe02963 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss +++ b/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss @@ -172,7 +172,7 @@ hr.mx_RoomView_myReadMarker { max-height: 0px; background-color: $primary-bg-color; - z-index: 5; + z-index: 1000; overflow: hidden; -webkit-transition: all .2s ease-out; @@ -260,4 +260,4 @@ hr.mx_RoomView_myReadMarker { .mx_RoomView_ongoingConfCallNotification a { color: $accent-fg-color ! important; -} +} \ No newline at end of file diff --git a/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss b/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss index e63814f545..64eac25d01 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss +++ b/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss @@ -25,8 +25,6 @@ limitations under the License. margin-top: -3px; margin-left: -20px; width: 200px; - font-weight: initial; - text-transform: initial; } .mx_IncomingCallBox_chevron { From fdf326c9f0651c9766d55bc5aeddd60d5e0372d1 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 17:13:39 +0100 Subject: [PATCH 64/83] Revert "Cancel quick-search on Escape, clearing it and returning focus to composer." This reverts commit 52a119244b2ff221c32c082166e77f9913833573. --- src/components/structures/SearchBox.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index d0868b690d..d79617c046 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -100,10 +100,6 @@ module.exports = React.createClass({ } switch (ev.keyCode) { - case KeyCode.ESCAPE: - this._clearSearch(); - dis.dispatch({action: 'focus_composer'}); - break; case KeyCode.KEY_K: if (ctrlCmdOnly) { if (this.refs.search) { From 844ea390c87eab83c9f287313d32e727c958a6fb Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 17:13:55 +0100 Subject: [PATCH 65/83] Revert "clear the searchbox after quick-search" This reverts commit ddd12edc064bdd81fffbad941e199eaa065e3ae0. --- src/components/structures/RoomSubList.js | 3 +-- src/components/structures/SearchBox.js | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index f741a30f03..a1291eebd7 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -165,11 +165,10 @@ var RoomSubList = React.createClass({ } }, - onRoomTileClick(roomId, ev) { + onRoomTileClick(roomId) { dis.dispatch({ action: 'view_room', room_id: roomId, - clear_search: (ev && (ev.keyCode == 13 || ev.keyCode == 32)), }); }, diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index d79617c046..a3848dcc44 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -48,14 +48,18 @@ module.exports = React.createClass({ }, onAction: function(payload) { + // Disabling this as I find it really really annoying, and was used to the + // previous behaviour - see https://github.com/vector-im/riot-web/issues/3348 +/* switch (payload.action) { // Clear up the text field when a room is selected. case 'view_room': - if (payload.clear_search && this.refs.search) { + if (this.refs.search) { this._clearSearch(); } break; } +*/ }, onChange: function() { From 9fc9de3af53e6457a6f83e1305c1f2247ab95421 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 May 2017 17:21:49 +0100 Subject: [PATCH 66/83] Revert "Merge pull request #3654 from vector-im/matthew/quick-search" This reverts commit 8f20fcfa6b6828421d1278b169df663e80d2a743, reversing changes made to 751f715e77a73fa704298dd1dbad0035eb7a75e8. --- package.json | 3 +- src/components/structures/LeftPanel.js | 94 +---------- src/components/structures/RoomSubList.js | 147 ++++++++++-------- .../structures/RoomSubListHeader.js | 120 -------------- src/components/structures/SearchBox.js | 31 ---- 5 files changed, 86 insertions(+), 309 deletions(-) delete mode 100644 src/components/structures/RoomSubListHeader.js diff --git a/package.json b/package.json index a1f06b00b1..644e9309dc 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "favico.js": "^0.3.10", "filesize": "3.5.6", "flux": "~2.0.3", + "gemini-scrollbar": "matrix-org/gemini-scrollbar#b302279", "gfm.css": "^1.1.1", "highlight.js": "^9.0.0", "linkifyjs": "^2.1.3", @@ -73,7 +74,7 @@ "react-dnd": "^2.1.4", "react-dnd-html5-backend": "^2.1.2", "react-dom": "^15.4.0", - "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#39d858c", + "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", "sanitize-html": "^1.11.1", "ua-parser-js": "^0.7.10", "url": "^0.11.0" diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 2d97313a07..a9df37a8b8 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -19,11 +19,9 @@ limitations under the License. var React = require('react'); var DragDropContext = require('react-dnd').DragDropContext; var HTML5Backend = require('react-dnd-html5-backend'); -var KeyCode = require('matrix-react-sdk/lib/KeyCode'); var sdk = require('matrix-react-sdk') var dis = require('matrix-react-sdk/lib/dispatcher'); - var VectorConferenceHandler = require('../../VectorConferenceHandler'); var CallHandler = require("matrix-react-sdk/lib/CallHandler"); @@ -42,10 +40,6 @@ var LeftPanel = React.createClass({ }; }, - componentWillMount: function() { - this.focusedElement = null; - }, - componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); }, @@ -68,91 +62,6 @@ var LeftPanel = React.createClass({ } }, - _onFocus: function(ev) { - this.focusedElement = ev.target; - }, - - _onBlur: function(ev) { - this.focusedElement = null; - }, - - _onKeyDown: function(ev) { - if (!this.focusedElement) return; - let handled = false; - - switch (ev.keyCode) { - case KeyCode.UP: - this._onMoveFocus(true); - handled = true; - break; - case KeyCode.DOWN: - this._onMoveFocus(false); - handled = true; - break; - } - - if (handled) { - ev.stopPropagation(); - ev.preventDefault(); - } - }, - - _onMoveFocus: function(up) { - var element = this.focusedElement; - - // unclear why this isn't needed - // var descending = (up == this.focusDirection) ? this.focusDescending : !this.focusDescending; - // this.focusDirection = up; - - var descending = false; // are we currently descending or ascending through the DOM tree? - var classes; - - do { - var child = up ? element.lastElementChild : element.firstElementChild; - var sibling = up ? element.previousElementSibling : element.nextElementSibling; - - if (descending) { - if (child) { - element = child; - } - else if (sibling) { - element = sibling; - } - else { - descending = false; - element = element.parentElement; - } - } - else { - if (sibling) { - element = sibling; - descending = true; - } - else { - element = element.parentElement; - } - } - - if (element) { - classes = element.classList; - if (classes.contains("mx_LeftPanel")) { // we hit the top - element = up ? element.lastElementChild : element.firstElementChild; - descending = true; - } - } - - } while(element && !( - classes.contains("mx_RoomTile") || - classes.contains("mx_SearchBox_search") || - classes.contains("mx_RoomSubList_ellipsis"))); - - if (element) { - element.focus(); - this.focusedElement = element; - this.focusedDescending = descending; - } - }, - _recheckCallElement: function(selectedRoomId) { // if we aren't viewing a room with an ongoing call, but there is an // active call, show the call element - we need to do this to make @@ -211,8 +120,7 @@ var LeftPanel = React.createClass({ } return ( -