diff --git a/.gitignore b/.gitignore index c28df64c650..0978bc5676f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ npm-debug.log electron/dist electron/pub +config.json diff --git a/electron/src/electron-main.js b/electron/src/electron-main.js index 33b44ce9d14..e6ffffac9b7 100644 --- a/electron/src/electron-main.js +++ b/electron/src/electron-main.js @@ -201,9 +201,12 @@ electron.app.on('ready', () => { brand: vectorConfig.brand || 'Riot' }); - mainWindow.once('ready-to-show', () => { - mainWindow.show(); - }); + if (!process.argv.includes('--hidden')) { + mainWindow.once('ready-to-show', () => { + mainWindow.show(); + }); + } + mainWindow.on('closed', () => { mainWindow = null; }); diff --git a/package.json b/package.json index 6cca7a31c56..55c918e2f16 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "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:bundle": "NODE_ENV=production webpack -p --progress", + "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", @@ -38,7 +38,7 @@ "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": "NODE_ENV=production webpack-dev-server -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:prod": "parallelshell \"npm run start:res\" \"npm run start:js:prod\"", "lint": "eslint src/", @@ -59,19 +59,19 @@ "favico.js": "^0.3.10", "filesize": "^3.1.2", "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", "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "matrix-react-sdk": "matrix-org/matrix-react-sdk#develop", "modernizr": "^3.1.0", + "pako": "^1.0.5", "q": "^1.4.1", "react": "^15.4.0", "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#5e97aef", + "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#39d858c", "sanitize-html": "^1.11.1", "ua-parser-js": "^0.7.10", "url": "^0.11.0" @@ -94,6 +94,7 @@ "babel-preset-stage-2": "^6.17.0", "chokidar": "^1.6.1", "cpx": "^1.3.2", + "cross-env": "^4.0.0", "css-raw-loader": "^0.1.1", "electron-builder": "^11.2.4", "electron-builder-squirrel-windows": "^11.2.1", diff --git a/scripts/copy-res.js b/scripts/copy-res.js index 826d9a96b3c..4702d5cf1b4 100755 --- a/scripts/copy-res.js +++ b/scripts/copy-res.js @@ -10,6 +10,7 @@ const COPY_LIST = [ ["res/{media,vector-icons}/**", "webapp"], ["src/skins/vector/{fonts,img}/**", "webapp"], ["node_modules/emojione/assets/svg/*", "webapp/emojione/svg/"], + ["node_modules/emojione/assets/png/*", "webapp/emojione/png/"], ["./config.json", "webapp", {directwatch: 1}], ]; diff --git a/src/component-index.js b/src/component-index.js index 2b67aa15e5f..4bf0b0f9847 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -40,6 +40,8 @@ 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'; diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js index 508eb46f453..ea6f5e4a88c 100644 --- a/src/components/structures/LeftPanel.js +++ b/src/components/structures/LeftPanel.js @@ -19,9 +19,11 @@ 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"); @@ -40,6 +42,10 @@ var LeftPanel = React.createClass({ }; }, + componentWillMount: function() { + this.focusedElement = null; + }, + componentDidMount: function() { this.dispatcherRef = dis.register(this.onAction); }, @@ -62,6 +68,91 @@ 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 @@ -121,7 +212,8 @@ var LeftPanel = React.createClass({ } return ( -