diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f3a738b08..d307764497 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,111 @@ +Changes in [0.12.6](https://github.com/vector-im/riot-web/releases/tag/v0.12.6) (2017-09-21) +============================================================================================ +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.5...v0.12.6) + + * Use matrix-js-sdk v0.8.4 to fix build + +Changes in [0.12.5](https://github.com/vector-im/riot-web/releases/tag/v0.12.5) (2017-09-21) +============================================================================================ +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.4...v0.12.5) + + * Use react-sdk v0.10.5 to fix build + +Changes in [0.12.4](https://github.com/vector-im/riot-web/releases/tag/v0.12.4) (2017-09-20) +============================================================================================ +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.4-rc.1...v0.12.4) + + * No changes + +Changes in [0.12.4-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.12.4-rc.1) (2017-09-19) +====================================================================================================== +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.3...v0.12.4-rc.1) + + * Fix test for new behaviour of 'joining' flag + [\#5053](https://github.com/vector-im/riot-web/pull/5053) + * fix really dumb blunder/typo preventing system from going to sleep. + [\#5080](https://github.com/vector-im/riot-web/pull/5080) + * T3chguy/devtools + [\#4735](https://github.com/vector-im/riot-web/pull/4735) + * CSS for unignore button in UserSettings + [\#5042](https://github.com/vector-im/riot-web/pull/5042) + * Fix alias on home page for identity room + [\#5044](https://github.com/vector-im/riot-web/pull/5044) + * generic contextual menu for tooltip/responses + [\#4989](https://github.com/vector-im/riot-web/pull/4989) + * Update from Weblate. + [\#5018](https://github.com/vector-im/riot-web/pull/5018) + * Avoid re-rendering RoomList on room switch + [\#5015](https://github.com/vector-im/riot-web/pull/5015) + * Fix menu on change keyboard language issue #4345 + [\#4623](https://github.com/vector-im/riot-web/pull/4623) + * Make isInvite default to false + [\#4999](https://github.com/vector-im/riot-web/pull/4999) + * Revert "Implement sticky date separators" + [\#4991](https://github.com/vector-im/riot-web/pull/4991) + * Implement sticky date separators + [\#4939](https://github.com/vector-im/riot-web/pull/4939) + +Changes in [0.12.3](https://github.com/vector-im/riot-web/releases/tag/v0.12.3) (2017-09-06) +============================================================================================ +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.3-rc.3...v0.12.3) + + * No changes + +Changes in [0.12.3-rc.3](https://github.com/vector-im/riot-web/releases/tag/v0.12.3-rc.3) (2017-09-05) +====================================================================================================== +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.3-rc.2...v0.12.3-rc.3) + + * Fix plurals in translations + [\#4971](https://github.com/vector-im/riot-web/pull/4971) + * Update from Weblate. + [\#4968](https://github.com/vector-im/riot-web/pull/4968) + +Changes in [0.12.3-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.12.3-rc.2) (2017-09-05) +====================================================================================================== +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.3-rc.1...v0.12.3-rc.2) + + * New react-sdk version to pull in new translations and fix some translation bugs. + + +Changes in [0.12.3-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.12.3-rc.1) (2017-09-01) +====================================================================================================== +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.2...v0.12.3-rc.1) + + * Fix overflowing login/register buttons on some languages issue #4804 + [\#4858](https://github.com/vector-im/riot-web/pull/4858) + * Update vector-im to riot-im on Login + [\#4943](https://github.com/vector-im/riot-web/pull/4943) + * lets let people know that the bug report actually sent properly :) + [\#4910](https://github.com/vector-im/riot-web/pull/4910) + * another s/vector/riot/ in README + [\#4934](https://github.com/vector-im/riot-web/pull/4934) + * fix two room list regressions + [\#4907](https://github.com/vector-im/riot-web/pull/4907) + +Changes in [0.12.2](https://github.com/vector-im/riot-web/releases/tag/v0.12.2) (2017-08-24) +============================================================================================ +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.1...v0.12.2) + + * Update react-sdk and js-sdk to fix bugs with incoming calls, messages and notifications + in encrypted rooms. + +Changes in [0.12.1](https://github.com/vector-im/riot-web/releases/tag/v0.12.1) (2017-08-23) +============================================================================================ +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.1-rc.1...v0.12.1) + + * [No changes] + +Changes in [0.12.1-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.12.1-rc.1) (2017-08-22) +====================================================================================================== +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.12.0-rc.2...v0.12.1-rc.1) + + * Update from Weblate. + [\#4832](https://github.com/vector-im/riot-web/pull/4832) + * Misc styling fixes. + [\#4826](https://github.com/vector-im/riot-web/pull/4826) + * Show / Hide apps icons + [\#4774](https://github.com/vector-im/riot-web/pull/4774) + Changes in [0.12.0-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.12.0-rc.1) (2017-08-16) ====================================================================================================== [Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.4...v0.12.0-rc.1) diff --git a/README.md b/README.md index 271382030e..72b2df1846 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ released version of Riot: 1. Download the latest version from https://github.com/vector-im/riot-web/releases 1. Untar the tarball on your web server -1. Move (or symlink) the vector-x.x.x directory to an appropriate name +1. Move (or symlink) the riot-x.x.x directory to an appropriate name 1. If desired, copy `config.sample.json` to `config.json` and edit it as desired. See below for details. 1. Enter the URL into your browser and log into Riot! diff --git a/docs/translating-dev.md b/docs/translating-dev.md index 55ba34be10..3bd9ddcc7d 100644 --- a/docs/translating-dev.md +++ b/docs/translating-dev.md @@ -6,10 +6,30 @@ - Be able to understand English - Be able to understand the language you want to translate riot-web into +## Translating strings vs. marking strings for translation + +Translating strings are done with the `_t()` function found in matrix-react-sdk/lib/languageHandler.js. It is recommended to call this function wherever you introduce a string constant which should be translated. However, translating can not be performed until after the translation system has been initialized. Thus, sometimes translation must be performed at a different location in the source code than where the string is introduced. This breaks some tooling and makes it difficult to find translatable strings. Therefore, there is the alternative `_td()` function which is used to mark strings for translation, without actually performing the translation (which must still be performed separately, and after the translation system has been initialized). + +Basically, whenever a translatable string is introduced, you should call either `_t()` immediately OR `_td()` and later `_t()`. + +Example: +``` +// Module-level constant +const COLORS = { + '#f8481c': _td('reddish orange'), // Can't call _t() here yet + '#fc2647': _td('pinky red') // Use _td() instead so the text is picked up for translation anyway +} + +// Function that is called some time after i18n has been loaded +function getColorName(hex) { + return _t(COLORS[hex]); // Perform actual translation here +} +``` + ## Adding new strings -1. Check if the import ``import { _t } from 'matrix-react-sdk/lib/languageHandler';`` is present. If not add it to the other import statements. -2. Add ``_t()`` to your string. (Don't forget curly braces when you assign an expression to JSX attributes in the render method) +1. Check if the import ``import { _t } from 'matrix-react-sdk/lib/languageHandler';`` is present. If not add it to the other import statements. Also import `_td` if needed. +2. Add ``_t()`` to your string. (Don't forget curly braces when you assign an expression to JSX attributes in the render method). If the string is introduced at a point before the translation system has not yet been initialized, use `_td()` instead, and call `_t()` at the appropriate time. 3. Add the String to the ``en_EN.json`` file in ``src/i18n/strings`` (respect which repository you are on). ## Adding variables inside a string. @@ -21,6 +41,8 @@ ## Things to know/Style Guides -- Do not use it inside ``getDefaultProps`` at the point where ``getDefaultProps`` is initialized the translations aren't loaded yet and it causes missing translations. -- If using translated strings as constants, translated strings can't be in constants loaded at class-load time since the translations won't be loaded. +- Do not use `_t()` inside ``getDefaultProps``: the translations aren't loaded when `getDefaultProps` is called, leading to missing translations. Use `_td()` to indicate that `_t()` will be called on the string later. +- If using translated strings as constants, translated strings can't be in constants loaded at class-load time since the translations won't be loaded. Mark the strings using `_td()` instead and perform the actual translation later. - If a string is presented in the UI with punctuation like a full stop, include this in the translation strings, since punctuation varies between languages too. +- Avoid "translation in parts", i.e. concatenating translated strings or using translated strings in variable substitutions. Context is important for translations, and translating partial strings this way is simply not always possible. +- Concatenating strings often also introduces an implicit assumption about word order (e.g. that the subject of the sentence comes first), which is incorrect for many languages. diff --git a/electron_app/package.json b/electron_app/package.json index 2eed90d5d7..4d1776903a 100644 --- a/electron_app/package.json +++ b/electron_app/package.json @@ -2,7 +2,7 @@ "name": "riot-web", "productName": "Riot", "main": "src/electron-main.js", - "version": "0.12.0-rc.1", + "version": "0.12.6", "description": "A feature-rich client for Matrix.org", "author": "Vector Creations Ltd.", "dependencies": { diff --git a/electron_app/riot.im/New Vector Ltd.pem b/electron_app/riot.im/New Vector Ltd.pem new file mode 100644 index 0000000000..1a34127210 --- /dev/null +++ b/electron_app/riot.im/New Vector Ltd.pem @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF0jCCBLqgAwIBAgIRAISYBqZi3VvCUeSfHXF+cbwwDQYJKoZIhvcNAQELBQAw +gZExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTcwNQYD +VQQDEy5DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gQ29kZSBTaWduaW5n +IENBMB4XDTE3MDgyMzAwMDAwMFoXDTIwMDgyMjIzNTk1OVowgdgxETAPBgNVBAUT +CDEwODczNjYxMRMwEQYLKwYBBAGCNzwCAQMTAkdCMR0wGwYDVQQPExRQcml2YXRl +IE9yZ2FuaXphdGlvbjELMAkGA1UEBhMCR0IxETAPBgNVBBEMCFdDMVIgNEFHMQ8w +DQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEbMBkGA1UECQwSMjYgUmVk +IExpb24gU3F1YXJlMRcwFQYDVQQKDA5OZXcgVmVjdG9yIEx0ZDEXMBUGA1UEAwwO +TmV3IFZlY3RvciBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7 +X0HP3oM/SVr6PboD03ndtYTONZDcJ/GJ3EyYi6UNrcbKjuDHwPktx9hjAhNjcVkG +lmuTEPluPj9DbvjaTrers0cQsAS1vJ0RHjLfA93Flg1ys9Q6OThUMw77FtFPtiJU +z5cSYzfFAhn/4dv7BcgGptn+Mv/8CaTu+RUZJUgoSlRWcT1TREmxkzWotbblqsHO +zjDmUg20tL5/qpt6BSWsNespf5udKQFXMtqkczBcLvBLmql0vurVcQy8BibB+Q89 +QKwRzwLgaIa7O8WEssFcW8uJe9s0SNtUy8ehbuoSxpA/DbHFwsiDbNA78vp7HrqM +qY6t6OIgLtDYBFCfe/btAgMBAAGjggHaMIIB1jAfBgNVHSMEGDAWgBTfj/MgDOnK +pgTYW1g3Kj2rRtyDSTAdBgNVHQ4EFgQUH+mDOdRkF3bYDxCWEaGB4lxiCxcwDgYD +VR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMw +EQYJYIZIAYb4QgEBBAQDAgQQMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQYBMCsw +KQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMFUGA1Ud +HwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JTQUV4 +dGVuZGVkVmFsaWRhdGlvbkNvZGVTaWduaW5nQ0EuY3JsMIGGBggrBgEFBQcBAQR6 +MHgwUAYIKwYBBQUHMAKGRGh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JT +QUV4dGVuZGVkVmFsaWRhdGlvbkNvZGVTaWduaW5nQ0EuY3J0MCQGCCsGAQUFBzAB +hhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wJgYDVR0RBB8wHaAbBggrBgEFBQcI +A6APMA0MC0dCLTEwODczNjYxMA0GCSqGSIb3DQEBCwUAA4IBAQBJ2aH4aixh0aiz +4WKlK+LMVLHpQ2POE3FZYNpAW7o1q2YDGEADXdGrygPE9NCGNBXKo0CAemCYNWfX +Ov/jdoiMfeqW3vrZ66oEy8OqbvJSwK1xmomWuYw3wYPWcPVG+YbWYD2CGdQu8jTz +fzAJCpvAuY3Wji3fQjiecAC7JCSB4fBHa0ALJOmiSqKQUUpkXs5kW7O0lPBnHzNF +2tQGltXMSIrq1QfFtcreMyKlwDOxPIh360dv5aHhaeSRDRKxq7uq5ikQF2gjKx4k +ieg2HRbAW6fVPpFr4zRS5umpeZV3i06i11VQQPS/mA/OBEXyaqzx4mr6B7U6ptrp +jMqiUv2w +-----END CERTIFICATE----- diff --git a/electron_app/src/electron-main.js b/electron_app/src/electron-main.js index ce5ac38413..4ffe211044 100644 --- a/electron_app/src/electron-main.js +++ b/electron_app/src/electron-main.js @@ -84,7 +84,7 @@ let powerSaveBlockerId; electron.ipcMain.on('app_onAction', function(ev, payload) { switch (payload.action) { case 'call_state': - if (powerSaveBlockerId && powerSaveBlockerId.isStarted(powerSaveBlockerId)) { + if (powerSaveBlockerId && electron.powerSaveBlocker.isStarted(powerSaveBlockerId)) { if (payload.state === 'ended') { electron.powerSaveBlocker.stop(powerSaveBlockerId); } diff --git a/electron_app/src/vectormenu.js b/electron_app/src/vectormenu.js index ab30b376b3..14f91a5268 100644 --- a/electron_app/src/vectormenu.js +++ b/electron_app/src/vectormenu.js @@ -19,7 +19,7 @@ const {app, shell, Menu} = require('electron'); // Menu template from http://electron.atom.io/docs/api/menu/, edited const template = [ { - label: 'Edit', + label: '&Edit', submenu: [ { role: 'undo' }, { role: 'redo' }, @@ -33,7 +33,7 @@ const template = [ ], }, { - label: 'View', + label: '&View', submenu: [ { type: 'separator' }, { role: 'resetzoom' }, @@ -45,6 +45,7 @@ const template = [ ], }, { + label: '&Window', role: 'window', submenu: [ { role: 'minimize' }, @@ -52,6 +53,7 @@ const template = [ ], }, { + label: '&Help', role: 'help', submenu: [ { @@ -122,7 +124,7 @@ if (process.platform === 'darwin') { ]; } else { template.unshift({ - label: 'File', + label: '&File', submenu: [ // For some reason, 'about' does not seem to work on windows. /*{ diff --git a/package.json b/package.json index 5b75232510..455692d15e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "riot-web", "productName": "Riot", "main": "electron_app/src/electron-main.js", - "version": "0.12.0-rc.1", + "version": "0.12.6", "description": "A feature-rich client for Matrix.org", "author": "Vector Creations Ltd.", "repository": { @@ -47,7 +47,7 @@ "lint": "eslint src/", "lintall": "eslint src/ test/", "clean": "rimraf lib webapp electron_app/dist", - "prepublish": "npm run build:compile", + "prepublish": "npm run clean && npm run build:compile", "test": "karma start --single-run=true --autoWatch=false --browsers ChromeHeadless", "test-multi": "karma start" }, @@ -66,10 +66,11 @@ "gfm.css": "^1.1.1", "highlight.js": "^9.0.0", "linkifyjs": "^2.1.3", - "matrix-js-sdk": "0.8.0", - "matrix-react-sdk": "0.10.0-rc.1", + "matrix-js-sdk": "0.8.4", + "matrix-react-sdk": "0.10.6", "modernizr": "^3.1.0", "pako": "^1.0.5", + "prop-types": "^15.5.10", "react": "^15.6.0", "react-dnd": "^2.1.4", "react-dnd-html5-backend": "^2.1.2", @@ -151,7 +152,7 @@ "build": { "appId": "im.riot.app", "category": "Network", - "electronVersion": "1.6.8", + "electronVersion": "1.7.5", "//asar=false": "https://github.com/electron-userland/electron-builder/issues/675", "asar": false, "dereference": true, diff --git a/res/home.html b/res/home.html index 3ba2e96419..4b8da3daaf 100644 --- a/res/home.html +++ b/res/home.html @@ -249,7 +249,7 @@ _t("Implementing VoIP services with Matrix")
- + Matrix Identity diff --git a/scripts/copy-res.js b/scripts/copy-res.js index fa52492e00..59f716929f 100755 --- a/scripts/copy-res.js +++ b/scripts/copy-res.js @@ -17,6 +17,7 @@ const INCLUDE_LANGS = [ {'value': 'eo', 'label': 'Esperanto'}, {'value': 'es', 'label': 'Español'}, {'value': 'eu', 'label': 'Euskal'}, + {'value': 'fi', 'label': 'Suomi'}, {'value': 'fr', 'label': 'Français'}, {'value': 'hu', 'label': 'Magyar'}, {'value': 'ko', 'label': '한국어'}, @@ -156,7 +157,7 @@ function genLangFile(lang, dest) { const reactSdkFile = 'node_modules/matrix-react-sdk/src/i18n/strings/' + lang + '.json'; const riotWebFile = 'src/i18n/strings/' + lang + '.json'; - const translations = {}; + let translations = {}; [reactSdkFile, riotWebFile].forEach(function(f) { if (fs.existsSync(f)) { Object.assign( @@ -165,6 +166,9 @@ function genLangFile(lang, dest) { ); } }); + + translations = weblateToCounterpart(translations) + fs.writeFileSync(dest + lang + '.json', JSON.stringify(translations, null, 4)); if (verbose) { console.log("Generated language file: " + lang); @@ -193,5 +197,39 @@ function genLangList() { } } +/** + * Convert translation key from weblate format + * (which only supports a single level) to counterpart + * which requires object values for 'count' translations. + * + * eg. + * "there are %(count)s badgers|one": "a badger", + * "there are %(count)s badgers|other": "%(count)s badgers" + * becomes + * "there are %(count)s badgers": { + * "one": "a badger", + * "other": "%(count)s badgers" + * } + */ +function weblateToCounterpart(inTrs) { + const outTrs = {}; + + for (const key of Object.keys(inTrs)) { + const keyParts = key.split('|', 2); + if (keyParts.length === 2) { + let obj = outTrs[keyParts[0]]; + if (obj === undefined) { + obj = {}; + outTrs[keyParts[0]] = obj; + } + obj[keyParts[1]] = inTrs[key]; + } else { + outTrs[key] = inTrs[key]; + } + } + + return outTrs; +} + genLangList(); next(0); diff --git a/scripts/deploy.py b/scripts/deploy.py index cc350e4c9a..e8fd9aa455 100755 --- a/scripts/deploy.py +++ b/scripts/deploy.py @@ -13,6 +13,8 @@ import os.path import subprocess import sys import tarfile +import shutil +import glob try: # python3 @@ -48,11 +50,12 @@ def move_bundles(source, dest): for f in os.listdir(source): dst = os.path.join(dest, f) if os.path.exists(dst): - raise DeployException( - "Not deploying. The bundle includes '%s' which we have previously deployed." + print ( + "Skipping bundle. The bundle includes '%s' which we have previously deployed." % f ) - renames[os.path.join(source, f)] = dst + else: + renames[os.path.join(source, f)] = dst for (src, dst) in renames.iteritems(): print ("Move %s -> %s" % (src, dst)) @@ -64,7 +67,7 @@ class Deployer: self.bundles_path = None self.should_clean = False # filename -> symlink path e.g 'config.localhost.json' => '../localhost/config.json' - self.config_locations = {} + self.symlink_paths = {} self.verify_signature = True def deploy(self, tarball, extract_path): @@ -96,20 +99,20 @@ class Deployer: print ("Extracted into: %s" % extracted_dir) - if self.config_locations: - for config_filename, config_loc in self.config_locations.iteritems(): + if self.symlink_paths: + for link_path, file_path in self.symlink_paths.iteritems(): create_relative_symlink( - target=config_loc, - linkname=os.path.join(extracted_dir, config_filename) + target=file_path, + linkname=os.path.join(extracted_dir, link_path) ) if self.bundles_path: extracted_bundles = os.path.join(extracted_dir, 'bundles') move_bundles(source=extracted_bundles, dest=self.bundles_path) - # replace the (hopefully now empty) extracted_bundles dir with a - # symlink to the common dir. - os.rmdir(extracted_bundles) + # replace the extracted_bundles dir (which may not be empty if some + # bundles were skipped) with a symlink to the common dir. + shutil.rmtree(extracted_bundles) create_relative_symlink( target=self.bundles_path, linkname=extracted_bundles, @@ -163,9 +166,10 @@ if __name__ == "__main__": ) ) parser.add_argument( - "--config", nargs='?', default='./config.json', help=( - "Write a symlink at config.json in the extracted tarball to this \ - location. (Default: '%(default)s')" + "--include", nargs='*', default='./config*.json', help=( + "Symlink these files into the root of the deployed tarball. \ + Useful for config files and home pages. Supports glob syntax. \ + (Default: '%(default)s')" ) ) parser.add_argument( @@ -180,8 +184,8 @@ if __name__ == "__main__": deployer.packages_path = args.packages_dir deployer.bundles_path = args.bundles_dir deployer.should_clean = args.clean - deployer.config_locations = { - "config.json": args.config, - } + + for include in args.include: + deployer.symlink_paths.update({ os.path.basename(pth): pth for pth in glob.iglob(include) }) deployer.deploy(args.tarball, args.extract_path) diff --git a/scripts/electron-package.sh b/scripts/electron-package.sh index 973ea45e82..f0ba941478 100755 --- a/scripts/electron-package.sh +++ b/scripts/electron-package.sh @@ -94,17 +94,20 @@ distdir="$builddir/electron_app/dist" pubdir="$projdir/electron_app/pub" rm -r "$pubdir" || true mkdir -p "$pubdir" +rm -r "$projdir/electron_app/dist" || true +mkdir -p "$projdir/electron_app/dist/unsigned/" # Install packages: what the user downloads the first time, # (DMGs for mac, exe installer for windows) mkdir -p "$pubdir/install/macos" cp $distdir/mac/*.dmg "$pubdir/install/macos/" +# Windows installers go to the dist dir because they need signing mkdir -p "$pubdir/install/win32/ia32/" -cp $distdir/win-ia32/*.exe "$pubdir/install/win32/ia32/" +cp $distdir/win-ia32/*.exe "$projdir/electron_app/dist/unsigned/" mkdir -p "$pubdir/install/win32/x64/" -cp $distdir/win/*.exe "$pubdir/install/win32/x64/" +cp $distdir/win/*.exe "$projdir/electron_app/dist/unsigned/" # Packages for auto-update mkdir -p "$pubdir/update/macos" @@ -120,11 +123,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_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 "Unsigned Windows installers have been placed in electron_app/dist/unsigned/ - sign them," +echo "or just copy them to "$pubdir/install/win32/\/"" +echo "Once you've done this, $pubdir can be hosted on your web server." echo "deb archives are in electron_app/dist/ - these should be added into your debian repository" diff --git a/scripts/redeploy.py b/scripts/redeploy.py index e10a48c008..2dac2931fa 100755 --- a/scripts/redeploy.py +++ b/scripts/redeploy.py @@ -15,6 +15,7 @@ import json, requests, tarfile, argparse, os, errno import time import traceback from urlparse import urljoin +import glob from flask import Flask, jsonify, request, abort @@ -188,15 +189,12 @@ if __name__ == "__main__": ) ) - def _raise(ex): - raise ex - - # --config config.json=../../config.json --config config.localhost.json=./localhost.json + # --include ../../config.json ./localhost.json homepages/* parser.add_argument( - "--config", action="append", dest="configs", - type=lambda kv: kv.split("=", 1) if "=" in kv else _raise(Exception("Missing =")), help=( - "A list of configs to symlink into the extracted tarball. \ - For example, --config config.json=../config.json config2.json=../test/config.json" + "--include", nargs='*', default='./config*.json', help=( + "Symlink these files into the root of the deployed tarball. \ + Useful for config files and home pages. Supports glob syntax. \ + (Default: '%(default)s')" ) ) parser.add_argument( @@ -220,7 +218,9 @@ if __name__ == "__main__": deployer = Deployer() deployer.bundles_path = args.bundles_dir deployer.should_clean = args.clean - deployer.config_locations = dict(args.configs) if args.configs else {} + + for include in args.include: + deployer.symlink_paths.update({ os.path.basename(pth): pth for pth in glob.iglob(include) }) # we don't pgp-sign jenkins artifacts; instead we rely on HTTPS access to @@ -234,13 +234,13 @@ if __name__ == "__main__": deploy_tarball(args.tarball_uri, build_dir) else: print( - "Listening on port %s. Extracting to %s%s. Symlinking to %s. Jenkins URL: %s. Config locations: %s" % + "Listening on port %s. Extracting to %s%s. Symlinking to %s. Jenkins URL: %s. Include files: %s" % (args.port, arg_extract_path, " (clean after)" if deployer.should_clean else "", arg_symlink, arg_jenkins_url, - deployer.config_locations, + deployer.symlink_paths, ) ) app.run(host="0.0.0.0", port=args.port, debug=True) diff --git a/src/components/structures/BottomLeftMenu.js b/src/components/structures/BottomLeftMenu.js index eacc500ae2..4014261caa 100644 --- a/src/components/structures/BottomLeftMenu.js +++ b/src/components/structures/BottomLeftMenu.js @@ -19,9 +19,9 @@ import React from 'react'; import ReactDOM from 'react-dom'; import sdk from 'matrix-react-sdk'; import dis from 'matrix-react-sdk/lib/dispatcher'; -import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton'; import Velocity from 'velocity-vector'; import 'velocity-vector/velocity.ui'; +import UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore'; const CALLOUT_ANIM_DURATION = 1000; @@ -167,8 +167,12 @@ module.exports = React.createClass({ const StartChatButton = sdk.getComponent('elements.StartChatButton'); const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); + const GroupsButton = sdk.getComponent('elements.GroupsButton'); const SettingsButton = sdk.getComponent('elements.SettingsButton'); + const groupsButton = UserSettingsStore.isFeatureEnabled('feature_groups') ? + : null; + return (
@@ -182,6 +186,7 @@ module.exports = React.createClass({
+ { groupsButton } diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 4539df1ffa..1988dc5ef9 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -30,13 +30,14 @@ import VectorConferenceHandler from '../../VectorConferenceHandler'; var LeftPanel = React.createClass({ displayName: 'LeftPanel', + // NB. If you add props, don't forget to update + // shouldComponentUpdate! propTypes: { collapsed: React.PropTypes.bool.isRequired, }, getInitialState: function() { return { - showCallElement: null, searchFilter: '', }; }, @@ -45,26 +46,25 @@ var LeftPanel = React.createClass({ this.focusedElement = null; }, - componentDidMount: function() { - this.dispatcherRef = dis.register(this.onAction); - }, - - componentWillReceiveProps: function(newProps) { - this._recheckCallElement(newProps.selectedRoom); - }, - - componentWillUnmount: function() { - dis.unregister(this.dispatcherRef); - }, - - onAction: function(payload) { - switch (payload.action) { - // listen for call state changes to prod the render method, which - // may hide the global CallView if the call it is tracking is dead - case 'call_state': - this._recheckCallElement(this.props.selectedRoom); - break; + shouldComponentUpdate: function(nextProps, nextState) { + // MatrixChat will update whenever the user switches + // rooms, but propagating this change all the way down + // the react tree is quite slow, so we cut this off + // here. The RoomTiles listen for the room change + // events themselves to know when to update. + // We just need to update if any of these things change. + if ( + this.props.collapsed !== nextProps.collapsed || + this.props.opacity !== nextProps.opacity + ) { + return true; } + + if (this.state.searchFilter !== nextState.searchFilter) { + return true; + } + + return false; }, _onFocus: function(ev) { @@ -152,74 +152,41 @@ var LeftPanel = React.createClass({ } }, - _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 - // audio/video not crap out - var activeCall = CallHandler.getAnyActiveCall(); - var callForRoom = CallHandler.getCallForRoom(selectedRoomId); - var showCall = (activeCall && activeCall.call_state === 'connected' && !callForRoom); - this.setState({ - showCallElement: showCall - }); - }, - onHideClick: function() { dis.dispatch({ action: 'hide_left_panel', }); }, - onCallViewClick: function() { - var call = CallHandler.getAnyActiveCall(); - if (call) { - dis.dispatch({ - action: 'view_room', - room_id: call.groupRoomId || call.roomId, - }); - } - }, - onSearch: function(term) { this.setState({ searchFilter: term }); }, render: function() { - var RoomList = sdk.getComponent('rooms.RoomList'); - var BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu'); + const RoomList = sdk.getComponent('rooms.RoomList'); + const BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu'); + const CallPreview = sdk.getComponent('voip.CallPreview'); - var topBox; + let topBox; if (MatrixClientPeg.get().isGuest()) { - var LoginBox = sdk.getComponent('structures.LoginBox'); + const LoginBox = sdk.getComponent('structures.LoginBox'); topBox = ; - } - else { - var SearchBox = sdk.getComponent('structures.SearchBox'); + } else { + const SearchBox = sdk.getComponent('structures.SearchBox'); topBox = ; } - var classes = "mx_LeftPanel mx_fadable"; + let classes = "mx_LeftPanel mx_fadable"; if (this.props.collapsed) { classes += " collapsed"; } - var callPreview; - if (this.state.showCallElement && !this.props.collapsed) { - var CallView = sdk.getComponent('voip.CallView'); - callPreview = ( - - ); - } - return (