diff --git a/CHANGELOG.md b/CHANGELOG.md index c7272d56..f2541d19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,40 @@ +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) diff --git a/electron_app/package.json b/electron_app/package.json index 730baaca..ea0932b6 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.2", + "version": "0.12.3", "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 00000000..1a341272 --- /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/vectormenu.js b/electron_app/src/vectormenu.js index ab30b376..14f91a52 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 08172833..61fb440c 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.2", + "version": "0.12.3", "description": "A feature-rich client for Matrix.org", "author": "Vector Creations Ltd.", "repository": { @@ -67,7 +67,7 @@ "highlight.js": "^9.0.0", "linkifyjs": "^2.1.3", "matrix-js-sdk": "0.8.2", - "matrix-react-sdk": "0.10.2", + "matrix-react-sdk": "0.10.3", "modernizr": "^3.1.0", "pako": "^1.0.5", "react": "^15.6.0", diff --git a/scripts/copy-res.js b/scripts/copy-res.js index fa52492e..ac3daf60 100755 --- a/scripts/copy-res.js +++ b/scripts/copy-res.js @@ -156,7 +156,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 +165,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 +196,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 cc350e4c..e7ad3f78 100755 --- a/scripts/deploy.py +++ b/scripts/deploy.py @@ -13,6 +13,7 @@ import os.path import subprocess import sys import tarfile +import shutil try: # python3 @@ -48,11 +49,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)) @@ -107,9 +109,9 @@ class Deployer: 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, diff --git a/scripts/electron-package.sh b/scripts/electron-package.sh index 973ea45e..f0ba9414 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/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 4539df1f..1988dc5e 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 (