diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..fabbe10497 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +src/vector/modernizr.js +src/component-index.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..c181384fd5 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ["./node_modules/matrix-react-sdk/.eslintrc.js"], +} diff --git a/.travis.yml b/.travis.yml index af738bb429..9720d8872f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ node_js: install: - npm install - (cd node_modules/matrix-js-sdk && npm install) - - (cd node_modules/matrix-react-sdk && npm run build) + - (cd node_modules/matrix-react-sdk && npm install) diff --git a/CHANGELOG.md b/CHANGELOG.md index 265cbe80fd..ee745baa1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,32 @@ +Changes in [0.9.6](https://github.com/vector-im/riot-web/releases/tag/v0.9.6) (2017-01-16) +========================================================================================== +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.6-rc.1...v0.9.6) + + * Update to matrix-js-sdk 0.9.6 for video calling fix + +Changes in [0.9.6-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.6-rc.1) (2017-01-13) +==================================================================================================== +[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.5...v0.9.6-rc.1) + + * Build the js-sdk in the CI script + [\#2920](https://github.com/vector-im/riot-web/pull/2920) + * Hopefully fix Windows shortcuts + [\#2917](https://github.com/vector-im/riot-web/pull/2917) + * Update README now the js-sdk has a transpile step + [\#2921](https://github.com/vector-im/riot-web/pull/2921) + * Use the role for 'toggle dev tools' + [\#2915](https://github.com/vector-im/riot-web/pull/2915) + * Enable screen sharing easter-egg in desktop app + [\#2909](https://github.com/vector-im/riot-web/pull/2909) + * make electron send email validation URLs with a nextlink of riot.im + [\#2808](https://github.com/vector-im/riot-web/pull/2808) + * add Debian Stretch install steps to readme + [\#2809](https://github.com/vector-im/riot-web/pull/2809) + * Update desktop build instructions fixes #2792 + [\#2793](https://github.com/vector-im/riot-web/pull/2793) + * CSS for the delete threepid button + [\#2784](https://github.com/vector-im/riot-web/pull/2784) + Changes in [0.9.5](https://github.com/vector-im/riot-web/releases/tag/v0.9.5) (2016-12-24) ========================================================================================== [Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.4...v0.9.5) diff --git a/README.md b/README.md index ba59ea2690..fd6acfd778 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://riot.im/develop for those who like living dangerously. To host your own copy of Riot, the quickest bet is to use a pre-built released version of Riot: -1. Download the latest version from https://github.com/vector-im/vector-web/releases +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. If desired, copy `config.sample.json` to `config.json` and edit it @@ -44,7 +44,7 @@ access to Riot (or other apps) due to sharing the same domain. We have put some coarse mitigations into place to try to protect against this situation, but it's still not good practice to do it in the first place. See -https://github.com/vector-im/vector-web/issues/1977 for more details. +https://github.com/vector-im/riot-web/issues/1977 for more details. Building From Source ==================== @@ -53,8 +53,8 @@ Riot is a modular webapp built with modern ES6 and requires a npm build system to build. 1. Install or update `node.js` so that your `npm` is at least at version `2.0.0` -1. Clone the repo: `git clone https://github.com/vector-im/vector-web.git` -1. Switch to the vector-web directory: `cd vector-web` +1. Clone the repo: `git clone https://github.com/vector-im/riot-web.git` +1. Switch to the riot-web directory: `cd riot-web` 1. Install the prerequisites: `npm install` 1. If you are using the `develop` branch of vector-web, you will probably need to rebuild some of the dependencies, due to @@ -109,16 +109,18 @@ Running as a Desktop app ======================== Riot can also be run as a desktop app, wrapped in electron. You can download a -pre-built version from https://riot.im/download/desktop/ or, if you prefer, +pre-built version from https://riot.im/desktop.html or, if you prefer, built it yourself. To run as a desktop app: -``` -npm install -npm install electron -npm run build -node_modules/.bin/electron . -``` + +1. Follow the instructions in 'Building From Source' above +2. Install electron and run it: + + ``` + npm install electron + node_modules/.bin/electron . + ``` To build packages, use electron-builder. This is configured to output: * dmg + zip for macOS @@ -141,11 +143,9 @@ npm run build:electron For other packages, use electron-builder manually. For example, to build a package for 64 bit Linux: -``` -npm install -npm run build -node_modules/.bin/build -l --x64 -``` + + 1. Follow the instructions in 'Building From Source' above + 2. `node_modules/.bin/build -l --x64` All electron packages go into `electron/dist/` @@ -179,13 +179,13 @@ the `component-index.js` for the app (used in future for skinning) development on Riot forcing `matrix-react-sdk` to move fast at the expense of maintaining a clear abstraction between the two.** Hacking on Riot inevitably means hacking equally on `matrix-react-sdk`, and there are bits of -`matrix-react-sdk` behaviour incorrectly residing in the `vector-web` project +`matrix-react-sdk` behaviour incorrectly residing in the `riot-web` project (e.g. matrix-react-sdk specific CSS), and a bunch of Riot specific behaviour in the `matrix-react-sdk` (grep for `vector` / `riot`). This separation problem will be solved asap once development on Riot (and thus matrix-react-sdk) has stabilised. Until then, the two projects should basically be considered as a single unit. In particular, `matrix-react-sdk` issues are currently filed -against `vector-web` in github. +against `riot-web` in github. Please note that Riot is intended to run correctly without access to the public internet. So please don't depend on resources (JS libs, CSS, images, fonts) @@ -220,8 +220,8 @@ Then similarly with `matrix-react-sdk`: Finally, build and start Riot itself: -1. `git clone git@github.com:vector-im/vector-web.git` -1. `cd vector-web` +1. `git clone git@github.com:vector-im/riot-web.git` +1. `cd riot-web` 1. `git checkout develop` 1. `npm install` 1. `rm -r node_modules/matrix-js-sdk; ln -s ../../matrix-js-sdk node_modules/` diff --git a/config.sample.json b/config.sample.json index e6384221c1..a65646ac77 100644 --- a/config.sample.json +++ b/config.sample.json @@ -4,6 +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", "enableLabs": true, "roomDirectory": { "servers": [ diff --git a/docs/theming.md b/docs/theming.md new file mode 100644 index 0000000000..c6373e52b6 --- /dev/null +++ b/docs/theming.md @@ -0,0 +1,25 @@ +Theming Riot +============ + +Themes are a very basic way of providing simple alternative look & feels to the +riot-web app via CSS & custom imagery. + +They are *NOT* co be confused with 'skins', which describe apps which sit on top +of matrix-react-sdk - e.g. in theory Riot itself is a react-sdk skin. +As of Jan 2017, skins are not fully supported; riot is the only available skin. + +To define a theme for Riot: + + 1. Pick a name, e.g. `teal`. at time of writing we have `light` and `dark`. + 2. Fork `src/skins/vector/css/themes/dark.scss` to be teal.scss + 3. Fork `src/skins/vector/css/themes/_base.scss` to be _teal.scss + 4. Override variables in _teal.scss as desired. You may wish to delete ones + which don't differ from _base.scss, to make it clear which are being + overridden. If every single colour is being changed (as per _dark.scss) + then you might as well keep them all. + 5. Add the theme to the list of entrypoints in webpack.config.js + 6. Add the theme to the list of themes in matrix-react-sdk's UserSettings.js + 7. Sit back and admire your handywork. + +In future, the assets for a theme will probably be gathered together into a +single directory tree. diff --git a/electron/src/electron-main.js b/electron/src/electron-main.js index 675640a520..33b44ce9d1 100644 --- a/electron/src/electron-main.js +++ b/electron/src/electron-main.js @@ -26,6 +26,8 @@ if (check_squirrel_hooks()) return; const electron = require('electron'); const url = require('url'); +const tray = require('./tray'); + const VectorMenu = require('./vectormenu'); let vectorConfig = {}; @@ -112,7 +114,16 @@ function startAutoUpdate(update_base_url) { // 204 No Content. On windows it takes a base path and looks for // files under that path. if (process.platform == 'darwin') { - electron.autoUpdater.setFeedURL(update_base_url + 'macos/'); + // include the current version in the URL we hit. Electron doesn't add + // it anywhere (apart from the User-Agent) so it's up to us. We could + // (and previously did) just use the User-Agent, but this doesn't + // rely on NSURLConnection setting the User-Agent to what we expect, + // and also acts as a convenient cache-buster to ensure that when the + // app updates it always gets a fresh value to avoid update-looping. + electron.autoUpdater.setFeedURL( + update_base_url + + 'macos/?localVersion=' + encodeURIComponent(electron.app.getVersion()) + ); } else if (process.platform == 'win32') { electron.autoUpdater.setFeedURL(update_base_url + 'win32/' + process.arch + '/'); } else { @@ -150,6 +161,19 @@ electron.ipcMain.on('install_update', installUpdate); electron.app.commandLine.appendSwitch('--enable-usermedia-screen-capturing'); +const shouldQuit = electron.app.makeSingleInstance((commandLine, workingDirectory) => { + // Someone tried to run a second instance, we should focus our window. + if (mainWindow) { + if (!mainWindow.isVisible()) mainWindow.show(); + if (mainWindow.isMinimized()) mainWindow.restore(); + mainWindow.focus(); + } +}); + +if (shouldQuit) { + electron.app.quit() +} + electron.app.on('ready', () => { if (vectorConfig.update_base_url) { console.log("Starting auto update with base URL: " + vectorConfig.update_base_url); @@ -166,10 +190,17 @@ electron.app.on('ready', () => { icon: icon_path, width: 1024, height: 768, show: false, + autoHideMenuBar: true, }); mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`); electron.Menu.setApplicationMenu(VectorMenu); + // Create trayIcon icon + tray.create(mainWindow, { + icon_path: icon_path, + brand: vectorConfig.brand || 'Riot' + }); + mainWindow.once('ready-to-show', () => { mainWindow.show(); }); @@ -177,7 +208,7 @@ electron.app.on('ready', () => { mainWindow = null; }); mainWindow.on('close', (e) => { - if (process.platform == 'darwin' && !appQuitting) { + if (!appQuitting && (tray.hasTray() || process.platform == 'darwin')) { // On Mac, closing the window just hides it // (this is generally how single-window Mac apps // behave, eg. Mail.app) diff --git a/electron/src/squirrelhooks.js b/electron/src/squirrelhooks.js index ca0983b66e..15ed670f0c 100644 --- a/electron/src/squirrelhooks.js +++ b/electron/src/squirrelhooks.js @@ -1,3 +1,19 @@ +/* +Copyright 2017 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. +*/ + const path = require('path'); const spawn = require('child_process').spawn; const app = require('electron').app; diff --git a/electron/src/tray.js b/electron/src/tray.js new file mode 100644 index 0000000000..2ccdf40ccc --- /dev/null +++ b/electron/src/tray.js @@ -0,0 +1,67 @@ +/* +Copyright 2017 Karl Glatz <karl@glatz.biz> +Copyright 2017 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. +*/ + +const path = require('path'); +const electron = require('electron'); + +const app = electron.app; +const Tray = electron.Tray; +const MenuItem = electron.MenuItem; + +let trayIcon = null; + +exports.hasTray = function hasTray() { + return (trayIcon !== null); +} + +exports.create = function (win, config) { + // no trays on darwin + if (process.platform === 'darwin' || trayIcon) { + return; + } + + const toggleWin = function () { + if (win.isVisible() && !win.isMinimized()) { + win.hide(); + } else { + if (win.isMinimized()) win.restore(); + if (!win.isVisible()) win.show(); + win.focus(); + } + }; + + const contextMenu = electron.Menu.buildFromTemplate([ + { + label: 'Show/Hide ' + config.brand, + click: toggleWin + }, + { + type: 'separator' + }, + { + label: 'Quit', + click: function () { + app.quit(); + } + } + ]); + + trayIcon = new Tray(config.icon_path); + trayIcon.setToolTip(config.brand); + trayIcon.setContextMenu(contextMenu); + trayIcon.on('click', toggleWin); +}; diff --git a/karma.conf.js b/karma.conf.js index 2474216916..b0a48c92ba 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -2,13 +2,14 @@ var path = require('path'); var webpack = require('webpack'); +var webpack_config = require('./webpack.config'); /* * We use webpack to build our tests. It's a pain to have to wait for webpack * to build everything; however it's the easiest way to load our dependencies * from node_modules. * - * If you run karma in multi-run mode (with `npm run test:multi`), it will watch + * If you run karma in multi-run mode (with `npm run test-multi`), it will watch * the tests for changes, and webpack will rebuild using a cache. This is much quicker * than a clean rebuild. */ @@ -19,8 +20,41 @@ var testFile = process.env.KARMA_TEST_FILE || 'test/all-tests.js'; process.env.PHANTOMJS_BIN = 'node_modules/.bin/phantomjs'; process.env.Q_DEBUG = 1; +/* the webpack config is based on the real one, to (a) try to simulate the + * deployed environment as closely as possible, and (b) to avoid a shedload of + * cut-and-paste. + */ + +// find out if we're shipping olm, and where it is, if so. +const olm_entry = webpack_config.entry['olm']; + +// remove the default entries - karma provides its own (via the 'files' and +// 'preprocessors' config below) +delete webpack_config['entry']; + +// add ./test as a search path for js +webpack_config.module.loaders.unshift({ + test: /\.js$/, loader: "babel", + include: [path.resolve('./src'), path.resolve('./test')], +}); + +// disable parsing for sinon, because it +// tries to do voodoo with 'require' which upsets +// webpack (https://github.com/webpack/webpack/issues/304) +webpack_config.module.noParse.push(/sinon\/pkg\/sinon\.js$/); + +// ? +webpack_config.resolve.alias['sinon'] = 'sinon/pkg/sinon.js'; + +webpack_config.resolve.root = [ + path.resolve('./src'), + path.resolve('./test'), +]; + +webpack_config.devtool = 'inline-source-map'; + module.exports = function (config) { - config.set({ + const myconfig = { // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['mocha'], @@ -29,19 +63,29 @@ module.exports = function (config) { files: [ 'node_modules/babel-polyfill/browser.js', testFile, - {pattern: 'vector/img/*', watched: false, included: false, served: true, nocache: false}, + + // make the images available via our httpd. They will be avaliable + // below http://localhost:[PORT]/base/. See also `proxies` which + // defines alternative URLs for them. + // + // This isn't required by any of the tests, but it stops karma + // logging warnings when it serves a 404 for them. + { + pattern: 'src/skins/vector/img/*', + watched: false, included: false, served: true, nocache: false, + }, ], - // redirect img links to the karma server proxies: { - "/img/": "/base/vector/img/", + // redirect img links to the karma server. See above. + "/img/": "/base/src/skins/vector/img/", }, // preprocess matching files before serving them to the browser // available preprocessors: // https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { - 'test/**/*.js': ['webpack', 'sourcemap'] + '{src,test}/**/*.js': ['webpack'], }, // test results reporter to use @@ -84,53 +128,20 @@ module.exports = function (config) { outputDir: 'karma-reports', }, - webpack: { - module: { - loaders: [ - { test: /\.json$/, loader: "json" }, - { - test: /\.js$/, loader: "babel", - include: [path.resolve('./src'), - path.resolve('./test'), - ] - }, - ], - noParse: [ - // don't parse the languages within highlight.js. They - // cause stack overflows - // (https://github.com/webpack/webpack/issues/1721), and - // there is no need for webpack to parse them - they can - // just be included as-is. - /highlight\.js\/lib\/languages/, + webpack: webpack_config, - // also disable parsing for sinon, because it - // tries to do voodoo with 'require' which upsets - // webpack (https://github.com/webpack/webpack/issues/304) - /sinon\/pkg\/sinon\.js$/, - ], + webpackMiddleware: { + stats: { + // don't fill the console up with a mahoosive list of modules + chunks: false, }, - resolve: { - alias: { - // alias any requires to the react module to the one in our path, otherwise - // we tend to get the react source included twice when using npm link. - react: path.resolve('./node_modules/react'), - - // same goes for js-sdk - "matrix-js-sdk": path.resolve('./node_modules/matrix-js-sdk'), - - sinon: 'sinon/pkg/sinon.js', - }, - root: [ - path.resolve('./src'), - path.resolve('./test'), - ], - }, - plugins: [ - // olm may not be installed, so avoid webpack warnings by - // ignoring it. - new webpack.IgnorePlugin(/^olm$/), - ], - devtool: 'inline-source-map', }, - }); + }; + + // include the olm loader if we have it. + if (olm_entry) { + myconfig.files.unshift(olm_entry); + } + + config.set(myconfig); }; diff --git a/package.json b/package.json index fd7c3b12ee..d48eaffe62 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.5", + "version": "0.9.6", "description": "A feature-rich client for Matrix.org", "author": "Vector Creations Ltd.", "repository": { @@ -29,24 +29,24 @@ "reskindex": "reskindex -h src/header", "build:res": "node scripts/copy-res.js", "build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js", - "build:css": "mkdirp build && catw \"src/skins/vector/css/**/*.css\" -o build/components.css --no-watch", "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": "node scripts/babelcheck.js && npm run build:res && npm run build:css && npm run build:bundle", - "build:dev": "node scripts/babelcheck.js && npm run build:res && npm run build:css && npm run build:bundle:dev", + "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", "start:res": "node scripts/copy-res.js -w", - "start:js": "webpack-dev-server -w --progress", + "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:css": "mkdirp build && catw \"src/skins/vector/css/**/*.css\" -o build/components.css", - "start": "node scripts/babelcheck.js && parallelshell \"npm run start:res\" \"npm run start:js\" \"npm run start:css\"", - "start:prod": "parallelshell \"npm run start:res\" \"npm run start:js:prod\" \"npm run start:css\"", - "clean": "rimraf build lib webapp electron/dist", + "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/", + "lintall": "eslint src/ test/", + "clean": "rimraf lib webapp electron/dist", "prepublish": "npm run build:compile", "test": "karma start --single-run=true --autoWatch=false --browsers PhantomJS --colors=false", - "test:multi": "karma start" + "test-multi": "karma start" }, "dependencies": { "babel-polyfill": "^6.5.0", @@ -76,6 +76,7 @@ "url": "^0.11.0" }, "devDependencies": { + "autoprefixer": "^6.6.0", "babel-cli": "^6.5.2", "babel-core": "^6.14.0", "babel-eslint": "^6.1.0", @@ -90,13 +91,16 @@ "babel-preset-es2017": "^6.16.0", "babel-preset-react": "^6.16.0", "babel-preset-stage-2": "^6.17.0", - "catw": "^1.0.1", "chokidar": "^1.6.1", "cpx": "^1.3.2", "css-raw-loader": "^0.1.1", "electron-builder": "^11.2.4", "electron-builder-squirrel-windows": "^11.2.1", "emojione": "^2.2.3", + "eslint": "^3.14.0", + "eslint-config-google": "^0.7.1", + "eslint-plugin-flowtype": "^2.30.0", + "eslint-plugin-react": "^6.9.0", "expect": "^1.16.0", "fs-extra": "^0.30.0", "html-webpack-plugin": "^2.24.0", @@ -107,13 +111,20 @@ "karma-junit-reporter": "^0.4.1", "karma-mocha": "^0.2.2", "karma-phantomjs-launcher": "^1.0.0", - "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^1.7.0", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "mocha": "^2.4.5", "parallelshell": "^1.2.0", "phantomjs-prebuilt": "^2.1.7", + "postcss-extend": "^1.0.5", + "postcss-import": "^9.0.0", + "postcss-loader": "^1.2.2", + "postcss-mixins": "^5.4.1", + "postcss-nested": "^1.0.0", + "postcss-scss": "^0.4.0", + "postcss-simple-vars": "^3.0.0", + "postcss-strip-inline-comments": "^0.1.5", "react-addons-perf": "^15.4.0", "react-addons-test-utils": "^15.4.0", "rimraf": "^2.4.3", @@ -140,7 +151,10 @@ ], "linux": { "target": "deb", - "maintainer": "support@riot.im" + "maintainer": "support@riot.im", + "desktop": { + "StartupWMClass": "riot-web" + } }, "win": { "target": "squirrel" diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000000..5305d9ed9e --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,13 @@ +module.exports = { + plugins: [ + require("postcss-import")(), + require("autoprefixer")(), + require("postcss-simple-vars")(), + require("postcss-extend")(), + require("postcss-nested")(), + require("postcss-mixins")(), + require("postcss-strip-inline-comments")(), + ], + "parser": "postcss-scss", + "local-plugins": true, +}; diff --git a/scripts/deploy.py b/scripts/deploy.py new file mode 100755 index 0000000000..c96b46e81f --- /dev/null +++ b/scripts/deploy.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python +# +# download and unpack a riot-web tarball. +# +# Allows `bundles` to be extracted to a common directory, and a link to +# config.json to be added. + +from __future__ import print_function + +import argparse +import os +import os.path +import subprocess +import sys +import tarfile + +try: + # python3 + from urllib.request import urlretrieve +except ImportError: + # python2 + from urllib import urlretrieve + +class DeployException(Exception): + pass + +def create_relative_symlink(linkname, target): + relpath = os.path.relpath(target, os.path.dirname(linkname)) + print ("Symlink %s -> %s" % (linkname, relpath)) + os.symlink(relpath, linkname) + + +def move_bundles(source, dest): + """Move the contents of the 'bundles' directory to a common dir + + We check that we will not be overwriting anything before we proceed. + + Args: + source (str): path to 'bundles' within the extracted tarball + dest (str): target common directory + """ + + if not os.path.isdir(dest): + os.mkdir(dest) + + # build a map from source to destination, checking for non-existence as we go. + renames = {} + 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." + % f + ) + renames[os.path.join(source, f)] = dst + + for (src, dst) in renames.iteritems(): + print ("Move %s -> %s" % (src, dst)) + os.rename(src, dst) + +class Deployer: + def __init__(self): + self.packages_path = "." + self.bundles_path = None + self.should_clean = False + self.config_location = None + self.verify_signature = True + + def deploy(self, tarball, extract_path): + """Download a tarball if necessary, and unpack it + + Returns: + (str) the path to the unpacked deployment + """ + print("Deploying %s to %s" % (tarball, extract_path)) + + name_str = os.path.basename(tarball).replace(".tar.gz", "") + extracted_dir = os.path.join(extract_path, name_str) + if os.path.exists(extracted_dir): + raise DeployException('Cannot unpack %s: %s already exists' % ( + tarball, extracted_dir)) + + downloaded = False + if tarball.startswith("http://") or tarball.startswith("https://"): + tarball = self.download_and_verify(tarball) + print("Downloaded file: %s" % tarball) + downloaded = True + + try: + with tarfile.open(tarball) as tar: + tar.extractall(extract_path) + finally: + if self.should_clean and downloaded: + os.remove(tarball) + + print ("Extracted into: %s" % extracted_dir) + + if self.config_location: + create_relative_symlink( + target=self.config_location, + linkname=os.path.join(extracted_dir, 'config.json') + ) + + 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) + create_relative_symlink( + target=self.bundles_path, + linkname=extracted_bundles, + ) + return extracted_dir + + def download_and_verify(self, url): + tarball = self.download_file(url) + + if self.verify_signature: + sigfile = self.download_file(url + ".asc") + subprocess.check_call(["gpg", "--verify", sigfile, tarball]) + + return tarball + + def download_file(self, url): + if not os.path.isdir(self.packages_path): + os.mkdir(self.packages_path) + local_filename = os.path.join(self.packages_path, + url.split('/')[-1]) + sys.stdout.write("Downloading %s -> %s..." % (url, local_filename)) + sys.stdout.flush() + urlretrieve(url, local_filename) + print ("Done") + return local_filename + +if __name__ == "__main__": + parser = argparse.ArgumentParser("Deploy a Riot build on a web server.") + parser.add_argument( + "-p", "--packages-dir", default="./packages", help=( + "The directory to download the tarball into. (Default: '%(default)s')" + ) + ) + parser.add_argument( + "-e", "--extract-path", default="./deploys", help=( + "The location to extract .tar.gz files to. (Default: '%(default)s')" + ) + ) + parser.add_argument( + "-b", "--bundles-dir", nargs='?', default="./bundles", help=( + "A directory to move the contents of the 'bundles' directory to. A \ + symlink to the bundles directory will also be written inside the \ + extracted tarball. Example: './bundles'. \ + (Default: '%(default)s')" + ) + ) + parser.add_argument( + "-c", "--clean", action="store_true", default=False, help=( + "Remove .tar.gz files after they have been downloaded and extracted. \ + (Default: %(default)s)" + ) + ) + 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')" + ) + ) + parser.add_argument( + "tarball", help=( + "filename of tarball, or URL to download." + ), + ) + + args = parser.parse_args() + + deployer = Deployer() + deployer.packages_path = args.packages_dir + deployer.bundles_path = args.bundles_dir + deployer.should_clean = args.clean + deployer.config_location = args.config + + deployer.deploy(args.tarball, args.extract_path) diff --git a/scripts/jenkins.sh b/scripts/jenkins.sh index bd27d6e3b1..0f4fac2513 100755 --- a/scripts/jenkins.sh +++ b/scripts/jenkins.sh @@ -20,12 +20,15 @@ rm -r node_modules/olm cp -r olm/package node_modules/olm # we may be using dev branches of js-sdk and react-sdk, in which case we need to build them -(cd node_modules/matrix-js-sdk && npm run build) -(cd node_modules/matrix-react-sdk && npm run build) +(cd node_modules/matrix-js-sdk && npm install) +(cd node_modules/matrix-react-sdk && npm install) # run the mocha tests 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 # node_modules deps from 'npm install' don't have a .git dir so can't diff --git a/scripts/redeploy.py b/scripts/redeploy.py index 36585f53a0..598f6c5265 100755 --- a/scripts/redeploy.py +++ b/scripts/redeploy.py @@ -1,26 +1,30 @@ #!/usr/bin/env python +# +# auto-deploy script for https://riot.im/develop +# +# Listens for HTTP hits. When it gets one, downloads the artifact from jenkins +# and deploys it as the new version. +# +# Requires the following python packages: +# +# - requests +# - flask +# from __future__ import print_function import json, requests, tarfile, argparse, os, errno +import time from urlparse import urljoin + from flask import Flask, jsonify, request, abort + +from deploy import Deployer, DeployException + app = Flask(__name__) -arg_jenkins_url, arg_extract_path, arg_should_clean, arg_symlink, arg_config_location = ( - None, None, None, None, None -) - -def download_file(url): - local_filename = url.split('/')[-1] - r = requests.get(url, stream=True) - with open(local_filename, 'wb') as f: - for chunk in r.iter_content(chunk_size=1024): - if chunk: # filter out keep-alive new chunks - f.write(chunk) - return local_filename - -def untar_to(tarball, dest): - with tarfile.open(tarball) as tar: - tar.extractall(dest) +arg_jenkins_url = None +deployer = None +arg_extract_path = None +arg_symlink = None def create_symlink(source, linkname): try: @@ -57,6 +61,9 @@ def on_receive_jenkins_poke(): abort(400, "Missing or bad build number") return + return fetch_jenkins_build(job_name, build_num) + +def fetch_jenkins_build(job_name, build_num): artifact_url = urljoin( arg_jenkins_url, "job/%s/%s/api/json" % (job_name, build_num) ) @@ -106,43 +113,41 @@ def on_receive_jenkins_poke(): arg_jenkins_url, "job/%s/%s/artifact/%s" % (job_name, build_num, tar_gz_path) ) - print("Retrieving .tar.gz file: %s" % tar_gz_url) - - # we rely on the fact that flask only serves one request at a time to - # ensure that we do not overwrite a tarball from a concurrent request. - filename = download_file(tar_gz_url) - print("Downloaded file: %s" % filename) - + # we extract into a directory based on the build number. This avoids the + # problem of multiple builds building the same git version and thus having + # the same tarball name. That would lead to two potential problems: + # (a) sometimes jenkins serves corrupted artifacts; we would replace + # a good deploy with a bad one + # (b) we'll be overwriting the live deployment, which means people might + # see half-written files. + build_dir = os.path.join(arg_extract_path, "%s-#%s" % (job_name, build_num)) try: - # we extract into a directory based on the build number. This avoids the - # problem of multiple builds building the same git version and thus having - # the same tarball name. That would lead to two potential problems: - # (a) sometimes jenkins serves corrupted artifacts; we would replace - # a good deploy with a bad one - # (b) we'll be overwriting the live deployment, which means people might - # see half-written files. - build_dir = os.path.join(arg_extract_path, "%s-#%s" % (job_name, build_num)) - if os.path.exists(build_dir): - abort(400, "Not deploying. We have previously deployed this build.") - return - os.mkdir(build_dir) - - untar_to(filename, build_dir) - print("Extracted to: %s" % build_dir) - finally: - if arg_should_clean: - os.remove(filename) - - name_str = filename.replace(".tar.gz", "") - extracted_dir = os.path.join(build_dir, name_str) - - if arg_config_location: - create_symlink(source=arg_config_location, linkname=os.path.join(extracted_dir, 'config.json')) + extracted_dir = deploy_tarball(tar_gz_url, build_dir) + except DeployException as e: + abort(400, e.message) create_symlink(source=extracted_dir, linkname=arg_symlink) return jsonify({}) +def deploy_tarball(tar_gz_url, build_dir): + """Download a tarball from jenkins and unpack it + + Returns: + (str) the path to the unpacked deployment + """ + if os.path.exists(build_dir): + raise DeployException( + "Not deploying. We have previously deployed this build." + ) + os.mkdir(build_dir) + + # we rely on the fact that flask only serves one request at a time to + # ensure that we do not overwrite a tarball from a concurrent request. + + return deployer.deploy(tar_gz_url, build_dir) + + if __name__ == "__main__": parser = argparse.ArgumentParser("Runs a Vector redeployment server.") parser.add_argument( @@ -161,6 +166,13 @@ if __name__ == "__main__": "The location to extract .tar.gz files to." ) ) + parser.add_argument( + "-b", "--bundles-dir", dest="bundles_dir", help=( + "A directory to move the contents of the 'bundles' directory to. A \ + symlink to the bundles directory will also be written inside the \ + extracted tarball. Example: './bundles'." + ) + ) parser.add_argument( "-c", "--clean", dest="clean", action="store_true", default=False, help=( "Remove .tar.gz files after they have been downloaded and extracted." @@ -179,18 +191,47 @@ if __name__ == "__main__": To this location." ) ) + parser.add_argument( + "--test", dest="tarball_uri", help=( + "Don't start an HTTP listener. Instead download a build from Jenkins \ + immediately." + ), + ) + args = parser.parse_args() if args.jenkins.endswith("/"): # important for urljoin arg_jenkins_url = args.jenkins else: arg_jenkins_url = args.jenkins + "/" arg_extract_path = args.extract - arg_should_clean = args.clean arg_symlink = args.symlink - arg_config_location = args.config - print( - "Listening on port %s. Extracting to %s%s. Symlinking to %s. Jenkins URL: %s. Config location: %s" % - (args.port, arg_extract_path, - " (clean after)" if arg_should_clean else "", arg_symlink, arg_jenkins_url, arg_config_location) - ) - app.run(host="0.0.0.0", port=args.port, debug=True) + + if not os.path.isdir(arg_extract_path): + os.mkdir(arg_extract_path) + + deployer = Deployer() + deployer.bundles_path = args.bundles_dir + deployer.should_clean = args.clean + deployer.config_location = args.config + + # we don't pgp-sign jenkins artifacts; instead we rely on HTTPS access to + # the jenkins server (and the jenkins server not being compromised and/or + # github not serving it compromised source). If that's not good enough for + # you, don't use riot.im/develop. + deployer.verify_signature = False + + if args.tarball_uri is not None: + build_dir = os.path.join(arg_extract_path, "test-%i" % (time.time())) + deploy_tarball(args.tarball_uri, build_dir) + else: + print( + "Listening on port %s. Extracting to %s%s. Symlinking to %s. Jenkins URL: %s. Config location: %s" % + (args.port, + arg_extract_path, + " (clean after)" if deployer.should_clean else "", + arg_symlink, + arg_jenkins_url, + deployer.config_location, + ) + ) + app.run(host="0.0.0.0", port=args.port, debug=True) diff --git a/src/component-index.js b/src/component-index.js index 3141087ce6..456f8176fc 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -27,60 +27,62 @@ limitations under the License. module.exports.components = require('matrix-react-sdk/lib/component-index').components; import structures$BottomLeftMenu from './components/structures/BottomLeftMenu'; -module.exports.components['structures.BottomLeftMenu'] = structures$BottomLeftMenu; +structures$BottomLeftMenu && (module.exports.components['structures.BottomLeftMenu'] = structures$BottomLeftMenu); import structures$CompatibilityPage from './components/structures/CompatibilityPage'; -module.exports.components['structures.CompatibilityPage'] = structures$CompatibilityPage; +structures$CompatibilityPage && (module.exports.components['structures.CompatibilityPage'] = structures$CompatibilityPage); import structures$LeftPanel from './components/structures/LeftPanel'; -module.exports.components['structures.LeftPanel'] = structures$LeftPanel; +structures$LeftPanel && (module.exports.components['structures.LeftPanel'] = structures$LeftPanel); import structures$RightPanel from './components/structures/RightPanel'; -module.exports.components['structures.RightPanel'] = structures$RightPanel; +structures$RightPanel && (module.exports.components['structures.RightPanel'] = structures$RightPanel); import structures$RoomDirectory from './components/structures/RoomDirectory'; -module.exports.components['structures.RoomDirectory'] = structures$RoomDirectory; +structures$RoomDirectory && (module.exports.components['structures.RoomDirectory'] = structures$RoomDirectory); import structures$RoomSubList from './components/structures/RoomSubList'; -module.exports.components['structures.RoomSubList'] = structures$RoomSubList; +structures$RoomSubList && (module.exports.components['structures.RoomSubList'] = structures$RoomSubList); import structures$SearchBox from './components/structures/SearchBox'; -module.exports.components['structures.SearchBox'] = structures$SearchBox; +structures$SearchBox && (module.exports.components['structures.SearchBox'] = structures$SearchBox); import structures$ViewSource from './components/structures/ViewSource'; -module.exports.components['structures.ViewSource'] = structures$ViewSource; +structures$ViewSource && (module.exports.components['structures.ViewSource'] = structures$ViewSource); import views$context_menus$MessageContextMenu from './components/views/context_menus/MessageContextMenu'; -module.exports.components['views.context_menus.MessageContextMenu'] = views$context_menus$MessageContextMenu; +views$context_menus$MessageContextMenu && (module.exports.components['views.context_menus.MessageContextMenu'] = views$context_menus$MessageContextMenu); import views$context_menus$NotificationStateContextMenu from './components/views/context_menus/NotificationStateContextMenu'; -module.exports.components['views.context_menus.NotificationStateContextMenu'] = views$context_menus$NotificationStateContextMenu; +views$context_menus$NotificationStateContextMenu && (module.exports.components['views.context_menus.NotificationStateContextMenu'] = views$context_menus$NotificationStateContextMenu); import views$context_menus$RoomTagContextMenu from './components/views/context_menus/RoomTagContextMenu'; -module.exports.components['views.context_menus.RoomTagContextMenu'] = views$context_menus$RoomTagContextMenu; +views$context_menus$RoomTagContextMenu && (module.exports.components['views.context_menus.RoomTagContextMenu'] = views$context_menus$RoomTagContextMenu); +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'; -module.exports.components['views.dialogs.ChangelogDialog'] = views$dialogs$ChangelogDialog; +views$dialogs$ChangelogDialog && (module.exports.components['views.dialogs.ChangelogDialog'] = views$dialogs$ChangelogDialog); import views$directory$NetworkDropdown from './components/views/directory/NetworkDropdown'; -module.exports.components['views.directory.NetworkDropdown'] = views$directory$NetworkDropdown; +views$directory$NetworkDropdown && (module.exports.components['views.directory.NetworkDropdown'] = views$directory$NetworkDropdown); import views$elements$ImageView from './components/views/elements/ImageView'; -module.exports.components['views.elements.ImageView'] = views$elements$ImageView; +views$elements$ImageView && (module.exports.components['views.elements.ImageView'] = views$elements$ImageView); import views$elements$Spinner from './components/views/elements/Spinner'; -module.exports.components['views.elements.Spinner'] = views$elements$Spinner; +views$elements$Spinner && (module.exports.components['views.elements.Spinner'] = views$elements$Spinner); import views$globals$GuestWarningBar from './components/views/globals/GuestWarningBar'; -module.exports.components['views.globals.GuestWarningBar'] = views$globals$GuestWarningBar; +views$globals$GuestWarningBar && (module.exports.components['views.globals.GuestWarningBar'] = views$globals$GuestWarningBar); import views$globals$MatrixToolbar from './components/views/globals/MatrixToolbar'; -module.exports.components['views.globals.MatrixToolbar'] = views$globals$MatrixToolbar; +views$globals$MatrixToolbar && (module.exports.components['views.globals.MatrixToolbar'] = views$globals$MatrixToolbar); import views$globals$NewVersionBar from './components/views/globals/NewVersionBar'; -module.exports.components['views.globals.NewVersionBar'] = views$globals$NewVersionBar; +views$globals$NewVersionBar && (module.exports.components['views.globals.NewVersionBar'] = views$globals$NewVersionBar); import views$login$VectorCustomServerDialog from './components/views/login/VectorCustomServerDialog'; -module.exports.components['views.login.VectorCustomServerDialog'] = views$login$VectorCustomServerDialog; +views$login$VectorCustomServerDialog && (module.exports.components['views.login.VectorCustomServerDialog'] = views$login$VectorCustomServerDialog); import views$login$VectorLoginFooter from './components/views/login/VectorLoginFooter'; -module.exports.components['views.login.VectorLoginFooter'] = views$login$VectorLoginFooter; +views$login$VectorLoginFooter && (module.exports.components['views.login.VectorLoginFooter'] = views$login$VectorLoginFooter); import views$login$VectorLoginHeader from './components/views/login/VectorLoginHeader'; -module.exports.components['views.login.VectorLoginHeader'] = views$login$VectorLoginHeader; +views$login$VectorLoginHeader && (module.exports.components['views.login.VectorLoginHeader'] = views$login$VectorLoginHeader); import views$messages$DateSeparator from './components/views/messages/DateSeparator'; -module.exports.components['views.messages.DateSeparator'] = views$messages$DateSeparator; +views$messages$DateSeparator && (module.exports.components['views.messages.DateSeparator'] = views$messages$DateSeparator); import views$messages$MessageTimestamp from './components/views/messages/MessageTimestamp'; -module.exports.components['views.messages.MessageTimestamp'] = views$messages$MessageTimestamp; +views$messages$MessageTimestamp && (module.exports.components['views.messages.MessageTimestamp'] = views$messages$MessageTimestamp); import views$rooms$DNDRoomTile from './components/views/rooms/DNDRoomTile'; -module.exports.components['views.rooms.DNDRoomTile'] = views$rooms$DNDRoomTile; +views$rooms$DNDRoomTile && (module.exports.components['views.rooms.DNDRoomTile'] = views$rooms$DNDRoomTile); import views$rooms$RoomDropTarget from './components/views/rooms/RoomDropTarget'; -module.exports.components['views.rooms.RoomDropTarget'] = views$rooms$RoomDropTarget; +views$rooms$RoomDropTarget && (module.exports.components['views.rooms.RoomDropTarget'] = views$rooms$RoomDropTarget); import views$rooms$RoomTooltip from './components/views/rooms/RoomTooltip'; -module.exports.components['views.rooms.RoomTooltip'] = views$rooms$RoomTooltip; +views$rooms$RoomTooltip && (module.exports.components['views.rooms.RoomTooltip'] = views$rooms$RoomTooltip); import views$rooms$SearchBar from './components/views/rooms/SearchBar'; -module.exports.components['views.rooms.SearchBar'] = views$rooms$SearchBar; +views$rooms$SearchBar && (module.exports.components['views.rooms.SearchBar'] = views$rooms$SearchBar); import views$settings$IntegrationsManager from './components/views/settings/IntegrationsManager'; -module.exports.components['views.settings.IntegrationsManager'] = views$settings$IntegrationsManager; +views$settings$IntegrationsManager && (module.exports.components['views.settings.IntegrationsManager'] = views$settings$IntegrationsManager); import views$settings$Notifications from './components/views/settings/Notifications'; -module.exports.components['views.settings.Notifications'] = views$settings$Notifications; +views$settings$Notifications && (module.exports.components['views.settings.Notifications'] = views$settings$Notifications); diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 7bd5d3b9ed..f609a4cd46 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -70,45 +70,21 @@ module.exports = React.createClass({ }, onMemberListButtonClick: function() { - if (this.props.collapsed || this.state.phase !== this.Phase.MemberList) { - this.setState({ phase: this.Phase.MemberList }); - dis.dispatch({ - action: 'show_right_panel', - }); - } - else { - dis.dispatch({ - action: 'hide_right_panel', - }); - } + this.setState({ phase: this.Phase.MemberList }); }, onFileListButtonClick: function() { - if (this.props.collapsed || this.state.phase !== this.Phase.FilePanel) { - this.setState({ phase: this.Phase.FilePanel }); - dis.dispatch({ - action: 'show_right_panel', - }); - } - else { - dis.dispatch({ - action: 'hide_right_panel', - }); - } + this.setState({ phase: this.Phase.FilePanel }); }, onNotificationListButtonClick: function() { - if (this.props.collapsed || this.state.phase !== this.Phase.NotificationPanel) { - this.setState({ phase: this.Phase.NotificationPanel }); - dis.dispatch({ - action: 'show_right_panel', - }); - } - else { - dis.dispatch({ - action: 'hide_right_panel', - }); - } + this.setState({ phase: this.Phase.NotificationPanel }); + }, + + onCollapseClick: function() { + dis.dispatch({ + action: 'hide_right_panel', + }); }, onInviteButtonClick: function() { @@ -242,6 +218,9 @@ module.exports = React.createClass({ { notificationsHighlight } </AccessibleButton> </div> + <div className="mx_RightPanel_headerButton mx_RightPanel_collapsebutton" title="Hide panel" onClick={ this.onCollapseClick }> + <TintableSvg src="img/minimise.svg" width="10" height="16"/> + </div> </div>; } diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js index 036ff3f15c..12bfc6dd6f 100644 --- a/src/components/structures/SearchBox.js +++ b/src/components/structures/SearchBox.js @@ -95,13 +95,13 @@ module.exports = React.createClass({ if (this.props.collapsed) { toggleCollapse = <AccessibleButton className="mx_SearchBox_maximise" tabIndex={collapseTabIndex} onClick={ this.onToggleCollapse.bind(this, true) }> - <TintableSvg src="img/maximise.svg" width="10" height="16" alt="<"/> + <TintableSvg src="img/maximise.svg" width="10" height="16" alt="Expand panel"/> </AccessibleButton> } else { toggleCollapse = <AccessibleButton className="mx_SearchBox_minimise" tabIndex={collapseTabIndex} onClick={ this.onToggleCollapse.bind(this, false) }> - <TintableSvg src="img/minimise.svg" width="10" height="16" alt="<"/> + <TintableSvg src="img/minimise.svg" width="10" height="16" alt="Collapse panel"/> </AccessibleButton> } diff --git a/src/components/views/context_menus/NotificationStateContextMenu.js b/src/components/views/context_menus/NotificationStateContextMenu.js index 243275db27..d4b40d1732 100644 --- a/src/components/views/context_menus/NotificationStateContextMenu.js +++ b/src/components/views/context_menus/NotificationStateContextMenu.js @@ -120,22 +120,22 @@ module.exports = React.createClass({ </div> <div className={ alertMeClasses } onClick={this._onClickAlertMe} > <img className="mx_NotificationStateContextMenu_activeIcon" src="img/notif-active.svg" width="12" height="12" /> - <img className="mx_NotificationStateContextMenu_icon" src="img/icon-context-mute-off-copy.svg" width="16" height="12" /> + <img className="mx_NotificationStateContextMenu_icon mx_filterFlipColor" src="img/icon-context-mute-off-copy.svg" width="16" height="12" /> All messages (loud) </div> <div className={ allNotifsClasses } onClick={this._onClickAllNotifs} > <img className="mx_NotificationStateContextMenu_activeIcon" src="img/notif-active.svg" width="12" height="12" /> - <img className="mx_NotificationStateContextMenu_icon" src="img/icon-context-mute-off.svg" width="16" height="12" /> + <img className="mx_NotificationStateContextMenu_icon mx_filterFlipColor" src="img/icon-context-mute-off.svg" width="16" height="12" /> All messages </div> <div className={ mentionsClasses } onClick={this._onClickMentions} > <img className="mx_NotificationStateContextMenu_activeIcon" src="img/notif-active.svg" width="12" height="12" /> - <img className="mx_NotificationStateContextMenu_icon" src="img/icon-context-mute-mentions.svg" width="16" height="12" /> + <img className="mx_NotificationStateContextMenu_icon mx_filterFlipColor" src="img/icon-context-mute-mentions.svg" width="16" height="12" /> Mentions only </div> <div className={ muteNotifsClasses } onClick={this._onClickMute} > <img className="mx_NotificationStateContextMenu_activeIcon" src="img/notif-active.svg" width="12" height="12" /> - <img className="mx_NotificationStateContextMenu_icon" src="img/icon-context-mute.svg" width="16" height="12" /> + <img className="mx_NotificationStateContextMenu_icon mx_filterFlipColor" src="img/icon-context-mute.svg" width="16" height="12" /> Mute </div> </div> diff --git a/src/components/views/dialogs/BugReportDialog.js b/src/components/views/dialogs/BugReportDialog.js new file mode 100644 index 0000000000..dcc0850ef7 --- /dev/null +++ b/src/components/views/dialogs/BugReportDialog.js @@ -0,0 +1,127 @@ +/* +Copyright 2017 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. +*/ + +import React from 'react'; +import sdk from 'matrix-react-sdk'; +import rageshake from '../../../vector/rageshake'; + +export default class BugReportDialog extends React.Component { + constructor(props, context) { + super(props, context); + this.state = { + sendLogs: true, + busy: false, + err: null, + text: "", + }; + this._onSubmit = this._onSubmit.bind(this); + this._onCancel = this._onCancel.bind(this); + this._onTextChange = this._onTextChange.bind(this); + this._onSendLogsChange = this._onSendLogsChange.bind(this); + } + + _onCancel(ev) { + this.props.onFinished(false); + } + + _onSubmit(ev) { + const sendLogs = this.state.sendLogs; + const userText = this.state.text; + if (!sendLogs && userText.trim().length === 0) { + this.setState({ + err: "Please describe the bug and/or send logs.", + }); + return; + } + this.setState({ busy: true, err: null }); + rageshake.sendBugReport(userText, sendLogs).then(() => { + this.setState({ busy: false }); + this.props.onFinished(false); + }, (err) => { + this.setState({ busy: false, err: `Failed: ${err.message}` }); + }); + } + + _onTextChange(ev) { + this.setState({ text: ev.target.value }); + } + + _onSendLogsChange(ev) { + this.setState({ sendLogs: ev.target.checked }); + } + + render() { + const Loader = sdk.getComponent("elements.Spinner"); + + let error = null; + if (this.state.err) { + error = <div className="error"> + {this.state.err} + </div>; + } + + const okLabel = this.state.busy ? <Loader /> : 'Send'; + + let cancelButton = null; + if (!this.state.busy) { + cancelButton = <button onClick={this._onCancel}> + Cancel + </button>; + } + + return ( + <div className="mx_BugReportDialog"> + <div className="mx_Dialog_title"> + Report a bug + </div> + <div className="mx_Dialog_content"> + <p>Please describe the bug. What did you do? + What did you expect to happen? + What actually happened?</p> + <textarea + className="mx_BugReportDialog_input" + rows={5} + onChange={this._onTextChange} + value={this.state.text} + placeholder="Describe your problem here." + /> + <p>In order to diagnose problems, logs from this client will be sent with + this bug report. + If you would prefer to only send the text above, please untick:</p> + <input type="checkbox" checked={this.state.sendLogs} + onChange={this._onSendLogsChange} id="mx_BugReportDialog_logs"/> + <label htmlFor="mx_BugReportDialog_logs">Send logs</label> + {error} + </div> + <div className="mx_Dialog_buttons"> + <button + className="mx_Dialog_primary danger" + onClick={this._onSubmit} + autoFocus={true} + > + {okLabel} + </button> + + {cancelButton} + </div> + </div> + ); + } +} + +BugReportDialog.propTypes = { + onFinished: React.PropTypes.func.isRequired, +}; diff --git a/src/components/views/directory/NetworkDropdown.js b/src/components/views/directory/NetworkDropdown.js index 4ce094bc37..c891ee5b29 100644 --- a/src/components/views/directory/NetworkDropdown.js +++ b/src/components/views/directory/NetworkDropdown.js @@ -181,7 +181,10 @@ export default class NetworkDropdown extends React.Component { span_class = 'mx_NetworkDropdown_menu_network'; } else { key = server + '_inst_' + instance.instance_id; - icon = <img src={instance.icon || DEFAULT_ICON_URL} />; + const imgUrl = instance.icon ? + MatrixClientPeg.get().mxcUrlToHttp(instance.icon, 25, 25, 'crop', true) : + DEFAULT_ICON_URL; + icon = <img src={imgUrl} />; name = instance.desc; span_class = 'mx_NetworkDropdown_menu_network'; } diff --git a/src/components/views/login/VectorLoginHeader.js b/src/components/views/login/VectorLoginHeader.js index 328672300d..daa2b09c67 100644 --- a/src/components/views/login/VectorLoginHeader.js +++ b/src/components/views/login/VectorLoginHeader.js @@ -23,11 +23,14 @@ module.exports = React.createClass({ statics: { replaces: 'LoginHeader', }, + propTypes: { + icon: React.PropTypes.string, + }, render: function() { return ( <div className="mx_Login_logo"> - <img src="img/logo.png" width="195" height="195" alt="Riot"/> + <img src={this.props.icon || "img/logo.png"} alt="Riot"/> </div> ); } diff --git a/src/skins/vector/css/common.css b/src/skins/vector/css/_common.scss similarity index 81% rename from src/skins/vector/css/common.css rename to src/skins/vector/css/_common.scss index bb00bbd8c0..bf31bea6cb 100644 --- a/src/skins/vector/css/common.css +++ b/src/skins/vector/css/_common.scss @@ -29,7 +29,8 @@ body { Arial here. */ font-family: 'Open Sans', Arial, Helvetica, Sans-Serif; font-size: 15px; - color: #454545; + background-color: $primary-bg-color; + color: $primary-fg-color; border: 0px; margin: 0px; /* This should render the fonts the same accross browsers */ @@ -41,7 +42,7 @@ div.error { } h2 { - color: #454545; + color: $primary-fg-color; font-weight: 400; font-size: 18px; margin-top: 16px; @@ -51,15 +52,20 @@ h2 { a:hover, a:link, a:visited { - color: #76cfa6; + color: $accent-color; +} + +input[type=text], input[type=password], textarea { + background-color: transparent; + color: $primary-fg-color; } input[type=text].error, input[type=password].error { - border: 1px solid red; + border: 1px solid $warning-color; } input[type=text]:focus, textarea:focus { - border: 1px solid #76CFA6; + border: 1px solid $accent-color; outline: none; box-shadow: none; } @@ -77,10 +83,7 @@ textarea { /* applied to side-panels and messagepanel when in RoomSettings */ .mx_fadable { opacity: 1; - -webkit-transition: opacity 0.2s ease-in-out; - -moz-transition: opacity 0.2s ease-in-out; - -ms-transition: opacity 0.2s ease-in-out; - -o-transition: opacity 0.2s ease-in-out; + transition: opacity 0.2s ease-in-out; } /* XXX: critical hack to GeminiScrollbar to allow them to work in FF 42 and Chrome 48. @@ -122,14 +125,8 @@ textarea { width: 100%; height: 100%; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; - -webkit-align-items: center; align-items: center; - -webkit-justify-content: center; justify-content: center; } @@ -148,8 +145,8 @@ textarea { } .mx_Dialog { - background-color: #fff; - color: #747474; + background-color: $primary-bg-color; + color: $light-fg-color; z-index: 4010; font-weight: 300; font-size: 15px; @@ -168,13 +165,13 @@ textarea { left: 0; width: 100%; height: 100%; - background-color: #e9e9e9; + background-color: $dialog-background-bg-color; opacity: 0.8; } .mx_Dialog_lightbox .mx_Dialog_background { opacity: 0.85; - background-color: #000; + background-color: $lightbox-background-bg-color; } .mx_Dialog_lightbox .mx_Dialog { @@ -190,7 +187,7 @@ textarea { .mx_Dialog_content { margin: 24px 58px 68px 0; font-size: 14px; - color: #4a4a4a; + color: $primary-fg-color; word-wrap: break-word; } @@ -202,7 +199,7 @@ textarea { border: 0px; height: 36px; border-radius: 40px; - border: solid 1px #76cfa6; + border: solid 1px $accent-color; font-weight: 600; font-size: 14px; font-family: 'Open Sans', Arial, Helvetica, Sans-Serif; @@ -212,26 +209,26 @@ textarea { padding-right: 1.5em; outline: none; cursor: pointer; - color: #76cfa6; - background-color: #fff; + color: $accent-color; + background-color: $primary-bg-color; /* align images in buttons (eg spinners) */ vertical-align: middle; } .mx_Dialog button.mx_Dialog_primary, .mx_Dialog input[type="submit"].mx_Dialog_primary { - color: #fff; - background-color: #76cfa6; + color: $accent-fg-color; + background-color: $accent-color; } .mx_Dialog button.danger, .mx_Dialog input[type="submit"].danger { - background-color: #ff0064; - border: solid 1px #ff0064; + background-color: $warning-color; + border: solid 1px $warning-color; } .mx_Dialog button:disabled, .mx_Dialog input[type="submit"]:disabled { - background-color: #777777; - border: solid 1px #777777; + background-color: $light-fg-color; + border: solid 1px $light-fg-color; opacity: 0.7; } @@ -241,11 +238,11 @@ textarea { font-weight: bold; font-size: 22px; line-height: 1.4; - color: #454545; + color: $primary-fg-color; } .mx_Dialog_title.danger { - color: #ff0064; + color: $warning-color; } .mx_TextInputDialog_label { @@ -256,10 +253,10 @@ textarea { .mx_TextInputDialog_input { font-size: 15px; border-radius: 3px; - border: 1px solid #f0f0f0; + border: 1px solid $input-border-color; padding: 9px; - color: #454545; - background-color: #fff; + color: $primary-fg-color; + background-color: $primary-bg-color; } .mx_emojione { @@ -268,19 +265,19 @@ textarea { } ::-moz-selection { - background-color: #76CFA6; - color: white; + background-color: $accent-color; + color: $selection-fg-color; } ::selection { - background-color: #76CFA6; - color: white; + background-color: $accent-color; + color: $selection-fg-color; } /** green button with rounded corners */ .mx_textButton { - color: #fff; - background-color: #76cfa6; + color: $accent-fg-color; + background-color: $accent-color; border-radius: 17px; text-align: center; padding-left: 1em; diff --git a/src/skins/vector/css/_components.scss b/src/skins/vector/css/_components.scss new file mode 100644 index 0000000000..323c22e0b0 --- /dev/null +++ b/src/skins/vector/css/_components.scss @@ -0,0 +1,75 @@ +// autogenerated by rethemendex.sh +@import "./_common.scss"; +@import "./matrix-react-sdk/structures/_ContextualMenu.scss"; +@import "./matrix-react-sdk/structures/_CreateRoom.scss"; +@import "./matrix-react-sdk/structures/_FilePanel.scss"; +@import "./matrix-react-sdk/structures/_MatrixChat.scss"; +@import "./matrix-react-sdk/structures/_NotificationPanel.scss"; +@import "./matrix-react-sdk/structures/_RoomStatusBar.scss"; +@import "./matrix-react-sdk/structures/_RoomView.scss"; +@import "./matrix-react-sdk/structures/_SearchBox.scss"; +@import "./matrix-react-sdk/structures/_UploadBar.scss"; +@import "./matrix-react-sdk/structures/_UserSettings.scss"; +@import "./matrix-react-sdk/structures/login/_Login.scss"; +@import "./matrix-react-sdk/views/avatars/_BaseAvatar.scss"; +@import "./matrix-react-sdk/views/dialogs/_BugReportDialog.scss"; +@import "./matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss"; +@import "./matrix-react-sdk/views/dialogs/_EncryptedEventDialog.scss"; +@import "./matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss"; +@import "./matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss"; +@import "./matrix-react-sdk/views/elements/_AddressSelector.scss"; +@import "./matrix-react-sdk/views/elements/_AddressTile.scss"; +@import "./matrix-react-sdk/views/elements/_DirectorySearchBox.scss"; +@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/login/_ServerConfig.scss"; +@import "./matrix-react-sdk/views/messages/_MImageBody.scss"; +@import "./matrix-react-sdk/views/messages/_MNoticeBody.scss"; +@import "./matrix-react-sdk/views/messages/_MTextBody.scss"; +@import "./matrix-react-sdk/views/messages/_TextualEvent.scss"; +@import "./matrix-react-sdk/views/messages/_UnknownBody.scss"; +@import "./matrix-react-sdk/views/rooms/_Autocomplete.scss"; +@import "./matrix-react-sdk/views/rooms/_EntityTile.scss"; +@import "./matrix-react-sdk/views/rooms/_EventTile.scss"; +@import "./matrix-react-sdk/views/rooms/_LinkPreviewWidget.scss"; +@import "./matrix-react-sdk/views/rooms/_MemberDeviceInfo.scss"; +@import "./matrix-react-sdk/views/rooms/_MemberInfo.scss"; +@import "./matrix-react-sdk/views/rooms/_MemberList.scss"; +@import "./matrix-react-sdk/views/rooms/_MessageComposer.scss"; +@import "./matrix-react-sdk/views/rooms/_PresenceLabel.scss"; +@import "./matrix-react-sdk/views/rooms/_RoomHeader.scss"; +@import "./matrix-react-sdk/views/rooms/_RoomList.scss"; +@import "./matrix-react-sdk/views/rooms/_RoomPreviewBar.scss"; +@import "./matrix-react-sdk/views/rooms/_RoomSettings.scss"; +@import "./matrix-react-sdk/views/rooms/_RoomTile.scss"; +@import "./matrix-react-sdk/views/rooms/_SearchableEntityList.scss"; +@import "./matrix-react-sdk/views/rooms/_TabCompleteBar.scss"; +@import "./matrix-react-sdk/views/rooms/_TopUnreadMessagesBar.scss"; +@import "./matrix-react-sdk/views/settings/_DevicesPanel.scss"; +@import "./matrix-react-sdk/views/settings/_IntegrationsManager.scss"; +@import "./matrix-react-sdk/views/voip/_CallView.scss"; +@import "./matrix-react-sdk/views/voip/_IncomingCallbox.scss"; +@import "./matrix-react-sdk/views/voip/_VideoView.scss"; +@import "./vector-web/_fonts.scss"; +@import "./vector-web/structures/_CompatibilityPage.scss"; +@import "./vector-web/structures/_LeftPanel.scss"; +@import "./vector-web/structures/_RightPanel.scss"; +@import "./vector-web/structures/_RoomDirectory.scss"; +@import "./vector-web/structures/_RoomSubList.scss"; +@import "./vector-web/structures/_ViewSource.scss"; +@import "./vector-web/views/context_menus/_MessageContextMenu.scss"; +@import "./vector-web/views/context_menus/_NotificationStateContextMenu.scss"; +@import "./vector-web/views/context_menus/_RoomTagContextMenu.scss"; +@import "./vector-web/views/dialogs/_ChangelogDialog.scss"; +@import "./vector-web/views/directory/_NetworkDropdown.scss"; +@import "./vector-web/views/elements/_ImageView.scss"; +@import "./vector-web/views/elements/_Spinner.scss"; +@import "./vector-web/views/globals/_GuestWarningBar.scss"; +@import "./vector-web/views/globals/_MatrixToolbar.scss"; +@import "./vector-web/views/messages/_MessageTimestamp.scss"; +@import "./vector-web/views/messages/_SenderProfile.scss"; +@import "./vector-web/views/rooms/_RoomDropTarget.scss"; +@import "./vector-web/views/rooms/_RoomTooltip.scss"; +@import "./vector-web/views/rooms/_SearchBar.scss"; +@import "./vector-web/views/settings/_Notifications.scss"; diff --git a/src/skins/vector/css/matrix-react-sdk/structures/ContextualMenu.css b/src/skins/vector/css/matrix-react-sdk/structures/_ContextualMenu.scss similarity index 87% rename from src/skins/vector/css/matrix-react-sdk/structures/ContextualMenu.css rename to src/skins/vector/css/matrix-react-sdk/structures/_ContextualMenu.scss index d317363dd5..d3e73a9a15 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/ContextualMenu.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_ContextualMenu.scss @@ -30,10 +30,10 @@ limitations under the License. } .mx_ContextualMenu { - border: solid 1px rgba(187, 187, 187, 0.5); + border: solid 1px $menu-border-color; border-radius: 4px; - background-color: #f6f6f6; - color: #4a4a4a; + background-color: $menu-bg-color; + color: $primary-fg-color; position: absolute; padding: 6px; font-size: 14px; @@ -51,7 +51,7 @@ limitations under the License. width: 0; height: 0; border-top: 8px solid transparent; - border-left: 8px solid rgba(187, 187, 187, 0.5); + border-left: 8px solid $menu-border-color; border-bottom: 8px solid transparent; } @@ -60,7 +60,7 @@ limitations under the License. width: 0; height: 0; border-top: 7px solid transparent; - border-left: 7px solid #f6f6f6; + border-left: 7px solid $menu-bg-color; border-bottom: 7px solid transparent; position:absolute; top: -7px; @@ -78,7 +78,7 @@ limitations under the License. width: 0; height: 0; border-top: 8px solid transparent; - border-right: 8px solid rgba(187, 187, 187, 0.5); + border-right: 8px solid $menu-border-color; border-bottom: 8px solid transparent; } @@ -87,7 +87,7 @@ limitations under the License. width: 0; height: 0; border-top: 7px solid transparent; - border-right: 7px solid #f6f6f6; + border-right: 7px solid $menu-bg-color; border-bottom: 7px solid transparent; position:absolute; top: -7px; diff --git a/src/skins/vector/css/matrix-react-sdk/structures/CreateRoom.css b/src/skins/vector/css/matrix-react-sdk/structures/_CreateRoom.scss similarity index 91% rename from src/skins/vector/css/matrix-react-sdk/structures/CreateRoom.css rename to src/skins/vector/css/matrix-react-sdk/structures/_CreateRoom.scss index 88804409e2..2be193525e 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/CreateRoom.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_CreateRoom.scss @@ -18,13 +18,13 @@ limitations under the License. width: 960px; margin-left: auto; margin-right: auto; - color: #4a4a4a; + color: $primary-fg-color; } .mx_CreateRoom input, .mx_CreateRoom textarea { border-radius: 3px; - border: 1px solid #c7c7c7; + border: 1px solid $strong-input-border-color; font-weight: 300; font-size: 13px; padding: 9px; diff --git a/src/skins/vector/css/matrix-react-sdk/structures/FilePanel.css b/src/skins/vector/css/matrix-react-sdk/structures/_FilePanel.scss similarity index 90% rename from src/skins/vector/css/matrix-react-sdk/structures/FilePanel.css rename to src/skins/vector/css/matrix-react-sdk/structures/_FilePanel.scss index fca53b1d2a..872085b66b 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/FilePanel.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_FilePanel.scss @@ -15,13 +15,8 @@ limitations under the License. */ .mx_FilePanel { - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; - -webkit-flex: 1 1 0; flex: 1 1 0; width: 100%; @@ -58,12 +53,12 @@ limitations under the License. .mx_FilePanel .mx_EventTile .mx_MImageBody_download { display: flex; font-size: 14px; - color: #acacac; + color: $event-timestamp-color; } .mx_FilePanel .mx_EventTile .mx_MImageBody_downloadLink { flex: 1 1 auto; - color: #747474; + color: $light-fg-color; } .mx_FilePanel .mx_EventTile .mx_MImageBody_size { @@ -90,7 +85,7 @@ limitations under the License. padding: 0px; font-size: 11px; opacity: 1.0; - color: #acacac; + color: $event-timestamp-color; } .mx_FilePanel .mx_EventTile .mx_MessageTimestamp { @@ -100,7 +95,7 @@ limitations under the License. position: initial; font-size: 11px; opacity: 1.0; - color: #acacac; + color: $event-timestamp-color; } /* Overrides for the wrappers around the body tile */ @@ -111,7 +106,7 @@ limitations under the License. } .mx_FilePanel .mx_EventTile:hover .mx_EventTile_line { - background-color: #fff; + background-color: $primary-bg-color; } .mx_FilePanel .mx_EventTile_selected .mx_EventTile_line { diff --git a/src/skins/vector/css/matrix-react-sdk/structures/MatrixChat.css b/src/skins/vector/css/matrix-react-sdk/structures/_MatrixChat.scss similarity index 65% rename from src/skins/vector/css/matrix-react-sdk/structures/MatrixChat.css rename to src/skins/vector/css/matrix-react-sdk/structures/_MatrixChat.scss index f1cc7d4a1a..05a39ea727 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/MatrixChat.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_MatrixChat.scss @@ -27,34 +27,21 @@ limitations under the License. } .mx_MatrixChat_wrapper { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; flex-direction: column; - -webkit-flex-direction: column; width: 100%; height: 100%; } .mx_MatrixToolbar { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; order: 1; height: 40px; } .mx_GuestWarningBar { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; order: 1; height: 40px; @@ -68,52 +55,32 @@ limitations under the License. width: 100%; height: 100%; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; - -webkit-flex: 1; flex: 1; } .mx_MatrixChat .mx_LeftPanel { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; order: 1; - background-color: #eaf5f0; + background-color: $secondary-accent-color; - -webkit-flex: 0 0 235px; flex: 0 0 235px; } .mx_MatrixChat .mx_LeftPanel.collapsed { - -webkit-flex: 0 0 60px; flex: 0 0 60px; } .mx_MatrixChat .mx_MatrixChat_middlePanel { - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; padding-left: 20px; padding-right: 22px; - background-color: #fff; + background-color: $primary-bg-color; - -webkit-flex: 1; flex: 1; /* Experimental fix for https://github.com/vector-im/vector-web/issues/947 @@ -132,25 +99,15 @@ limitations under the License. * point, but instead we fudge it and make the middlePanel * flex itself. */ - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; } .mx_MatrixChat .mx_RightPanel { - -webkit-box-ordinal-group: 3; - -moz-box-ordinal-group: 3; - -ms-flex-order: 3; - -webkit-order: 3; order: 3; - -webkit-flex: 0 0 235px; flex: 0 0 235px; } .mx_MatrixChat .mx_RightPanel.collapsed { - -webkit-flex: 0 0 122px; flex: 0 0 122px; } diff --git a/src/skins/vector/css/matrix-react-sdk/structures/NotificationPanel.css b/src/skins/vector/css/matrix-react-sdk/structures/_NotificationPanel.scss similarity index 91% rename from src/skins/vector/css/matrix-react-sdk/structures/NotificationPanel.css rename to src/skins/vector/css/matrix-react-sdk/structures/_NotificationPanel.scss index 83b0a033b7..ef75678dce 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/NotificationPanel.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_NotificationPanel.scss @@ -15,13 +15,8 @@ limitations under the License. */ .mx_NotificationPanel { - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; - -webkit-flex: 1 1 0; flex: 1 1 0; width: 100%; @@ -51,7 +46,7 @@ limitations under the License. } .mx_NotificationPanel .mx_EventTile_roomName a { - color: #4a4a4a; + color: $primary-fg-color; } .mx_NotificationPanel .mx_EventTile_avatar { @@ -61,8 +56,7 @@ limitations under the License. .mx_NotificationPanel .mx_EventTile .mx_SenderProfile, .mx_NotificationPanel .mx_EventTile .mx_MessageTimestamp { - color: #000; - opacity: 0.3; + color: $primary-fg-color; font-size: 12px; display: inline; padding-left: 0px; @@ -94,7 +88,7 @@ limitations under the License. } .mx_NotificationPanel .mx_EventTile:hover .mx_EventTile_line { - background-color: #fff; + background-color: $primary-bg-color; } .mx_NotificationPanel .mx_EventTile_selected .mx_EventTile_line { diff --git a/src/skins/vector/css/matrix-react-sdk/structures/RoomStatusBar.css b/src/skins/vector/css/matrix-react-sdk/structures/_RoomStatusBar.scss similarity index 73% rename from src/skins/vector/css/matrix-react-sdk/structures/RoomStatusBar.css rename to src/skins/vector/css/matrix-react-sdk/structures/_RoomStatusBar.scss index ef0b69c4d0..d124f9c67f 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/RoomStatusBar.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_RoomStatusBar.scss @@ -21,10 +21,10 @@ limitations under the License. /* position the indicator in the same place horizontally as .mx_EventTile_avatar. */ .mx_RoomStatusBar_indicator { - padding-left: 18px; + padding-left: 17px; padding-right: 12px; margin-left: -73px; - margin-top: 13px; + margin-top: 8px; float: left; width: 24px; text-align: center; @@ -36,16 +36,16 @@ limitations under the License. } .mx_RoomStatusBar_placeholderIndicator span { - color: #4a4a4a; + color: $primary-fg-color; opacity: 0.5; position: relative; top: -4px; -/* +/* animation-duration: 1s; animation-name: bounce; animation-direction: alternate; animation-iteration-count: infinite; -*/ +*/ } .mx_RoomStatusBar_placeholderIndicator span:nth-child(1) { @@ -70,13 +70,43 @@ limitations under the License. } } +.mx_RoomStatusBar_typingIndicatorAvatars { + width: 52px; + text-align: left; +} + +.mx_RoomStatusBar_typingIndicatorAvatars .mx_BaseAvatar_image { + margin-right: -12px; + border: 1px solid $primary-bg-color; +} + +.mx_RoomStatusBar_typingIndicatorAvatars .mx_BaseAvatar_initial { + padding-left: 1px; + padding-top: 1px; +} + +.mx_RoomStatusBar_typingIndicatorRemaining { + display: inline-block; + color: #acacac; + background-color: #ddd; + border: 1px solid $primary-bg-color; + border-radius: 40px; + width: 24px; + height: 24px; + line-height: 24px; + font-size: 0.8em; + vertical-align: top; + text-align: center; + position: absolute; +} + .mx_RoomStatusBar_scrollDownIndicator { cursor: pointer; } .mx_RoomStatusBar_unreadMessagesBar { padding-top: 10px; - color: #ff0064; + color: $warning-color; cursor: pointer; } @@ -93,29 +123,29 @@ limitations under the License. } .mx_RoomStatusBar_connectionLostBar_title { - color: #ff0064; + color: $warning-color; } .mx_RoomStatusBar_connectionLostBar_desc { - color: #454545; + color: $primary-fg-color; font-size: 13px; opacity: 0.5; } .mx_RoomStatusBar_resend_link { - color: #454545 ! important; + color: $primary-fg-color ! important; text-decoration: underline ! important; cursor: pointer; } .mx_RoomStatusBar_tabCompleteBar { padding-top: 10px; - color: #4a4a4a; + color: $primary-fg-color; } .mx_RoomStatusBar_typingBar { padding-top: 10px; - color: #4a4a4a; + color: $primary-fg-color; opacity: 0.5; overflow-y: hidden; display: block; @@ -123,19 +153,16 @@ limitations under the License. .mx_RoomStatusBar_tabCompleteWrapper { display: flex; - display: -webkit-flex; height: 26px; } .mx_RoomStatusBar_tabCompleteWrapper .mx_TabCompleteBar { flex: 1 1 auto; - -webkit-flex: 1 1 auto; } .mx_RoomStatusBar_tabCompleteEol { flex: 0 0 auto; - -webkit-flex: 0 0 auto; - color: #76CFA6; + color: $accent-color; } .mx_RoomStatusBar_tabCompleteEol object { diff --git a/src/skins/vector/css/matrix-react-sdk/structures/RoomView.css b/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss similarity index 67% rename from src/skins/vector/css/matrix-react-sdk/structures/RoomView.css rename to src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss index c3f7ceed3b..37c68ad9e6 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/RoomView.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss @@ -18,25 +18,15 @@ limitations under the License. word-wrap: break-word; position: relative; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; width: 100%; flex-direction: column; - -webkit-flex-direction: column; } .mx_RoomView .mx_RoomHeader { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; order: 1; - -webkit-flex: 0 0 70px; flex: 0 0 70px; } @@ -53,14 +43,10 @@ limitations under the License. padding-right: 12px; margin-left: -12px; - -webkit-border-top-left-radius: 10px; - -webkit-border-top-right-radius: 10px; - -moz-border-radius-topleft: 10px; - -moz-border-radius-topright: 10px; border-top-left-radius: 10px; border-top-right-radius: 10px; - background-color: rgba(255, 255, 255, 0.9); + background-color: $droptarget-bg-color; border: 2px #e1dddd solid; border-bottom: none; position: absolute; @@ -77,10 +63,6 @@ limitations under the License. } .mx_RoomView_auxPanel { - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; min-width: 0px; @@ -89,28 +71,18 @@ limitations under the License. margin: auto; overflow: auto; - border-bottom: 1px solid #e5e5e5; + border-bottom: 1px solid $primary-hairline-color; - -webkit-flex: 0 0 auto; flex: 0 0 auto; } .mx_RoomView_topUnreadMessagesBar { - -webkit-box-ordinal-group: 3; - -moz-box-ordinal-group: 3; - -ms-flex-order: 3; - -webkit-order: 3; order: 3; } .mx_RoomView_messagePanel { - -webkit-box-ordinal-group: 4; - -moz-box-ordinal-group: 4; - -ms-flex-order: 4; - -webkit-order: 4; order: 4; - -webkit-flex: 1 1 0; flex: 1 1 0; width: 100%; @@ -124,22 +96,25 @@ limitations under the License. min-height: 100%; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; flex-direction: column; - -webkit-flex-direction: column; justify-content: flex-end; - -webkit-justify-content: flex-end; } .mx_RoomView_searchResultsPanel .mx_RoomView_messageListWrapper { justify-content: flex-start; - -webkit-justify-content: flex-start; +} + +.mx_RoomView_empty { + flex: 1 1 auto; + font-size: 13px; + padding-left: 3em; + padding-right: 3em; + margin-right: 20px; + margin-top: 33%; + text-align: center; } .mx_RoomView_MessageList { @@ -158,14 +133,10 @@ limitations under the License. margin-bottom: 8px; margin-left: 63px; padding-bottom: 6px; - border-bottom: 1px solid #e5e5e5; + border-bottom: 1px solid $primary-hairline-color; } .mx_RoomView_invitePrompt { - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; min-width: 0px; @@ -185,23 +156,32 @@ li.mx_RoomView_myReadMarker_container { } hr.mx_RoomView_myReadMarker { - border-top: solid 1px #76cfa6; - border-bottom: solid 1px #76cfa6; + border-top: solid 1px $accent-color; + border-bottom: solid 1px $accent-color; margin-top: 0px; position: relative; top: 5px; } .mx_RoomView_statusArea { - -webkit-box-ordinal-group: 5; - -moz-box-ordinal-group: 5; - -ms-flex-order: 5; - -webkit-order: 5; order: 5; width: 100%; - -webkit-flex: 0 0 auto; flex: 0 0 auto; + + max-height: 0px; + background-color: $primary-bg-color; + z-index: 1000; + overflow: hidden; + + -webkit-transition: all .2s ease-out; + -moz-transition: all .2s ease-out; + -ms-transition: all .2s ease-out; + -o-transition: all .2s ease-out; +} + +.mx_RoomView_statusArea_expanded { + max-height: 100px; } .mx_RoomView_statusAreaBox { @@ -212,16 +192,16 @@ hr.mx_RoomView_myReadMarker { .mx_RoomView_statusAreaBox_line { margin-left: 65px; - border-top: 1px solid #e5e5e5; + border-top: 1px solid $primary-hairline-color; height: 1px; } .mx_RoomView_callStatusBar .mx_UploadBar_uploadProgressInner { - background-color: #fff; + background-color: $primary-bg-color; } .mx_RoomView_callStatusBar .mx_UploadBar_uploadFilename { - color: #fff; + color: $accent-fg-color; opacity: 1.0; } @@ -234,8 +214,8 @@ hr.mx_RoomView_myReadMarker { } .mx_RoomView_inCall .mx_RoomView_statusAreaBox { - background-color: #76CFA6; - color: #fff; + background-color: $accent-color; + color: $accent-fg-color; position: relative; } @@ -257,14 +237,9 @@ hr.mx_RoomView_myReadMarker { } .mx_RoomView .mx_MessageComposer { - -webkit-box-ordinal-group: 6; - -moz-box-ordinal-group: 6; - -ms-flex-order: 6; - -webkit-order: 6; order: 6; width: 100%; - -webkit-flex: 0 0 auto; flex: 0 0 auto; margin-right: 2px; } @@ -272,13 +247,13 @@ hr.mx_RoomView_myReadMarker { .mx_RoomView_ongoingConfCallNotification { width: 100%; text-align: center; - background-color: #ff0064; - color: #fff; + background-color: $warning-color; + color: $accent-fg-color; font-weight: bold; padding: 6px 0; cursor: pointer; } .mx_RoomView_ongoingConfCallNotification a { - color: #fff ! important; + color: $accent-fg-color ! important; } \ No newline at end of file diff --git a/src/skins/vector/css/matrix-react-sdk/structures/SearchBox.css b/src/skins/vector/css/matrix-react-sdk/structures/_SearchBox.scss similarity index 94% rename from src/skins/vector/css/matrix-react-sdk/structures/SearchBox.css rename to src/skins/vector/css/matrix-react-sdk/structures/_SearchBox.scss index 0b5362593b..0f34f056a5 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/SearchBox.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_SearchBox.scss @@ -22,7 +22,6 @@ limitations under the License. padding-bottom: 22px; display: flex; - display: -webkit-flex; } .mx_SearchBox_searchButton { @@ -38,7 +37,6 @@ limitations under the License. .mx_SearchBox_search { flex: 1 1 auto; - -webkit-flex: 1 1 auto; width: 0px; font-family: 'Open Sans', Arial, Helvetica, Sans-Serif; font-size: 12px; @@ -46,7 +44,6 @@ limitations under the License. height: 24px; border: 0px ! important; /* border-bottom: 1px solid rgba(0, 0, 0, 0.1) ! important; */ - background-color: transparent; border: 0px; } diff --git a/src/skins/vector/css/matrix-react-sdk/structures/UploadBar.css b/src/skins/vector/css/matrix-react-sdk/structures/_UploadBar.scss similarity index 93% rename from src/skins/vector/css/matrix-react-sdk/structures/UploadBar.css rename to src/skins/vector/css/matrix-react-sdk/structures/_UploadBar.scss index b489e13265..d76c81668c 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/UploadBar.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_UploadBar.scss @@ -26,7 +26,7 @@ limitations under the License. } .mx_UploadBar_uploadProgressInner { - background-color: #76cfa6; + background-color: $accent-color; height: 5px; } @@ -34,7 +34,7 @@ limitations under the License. margin-top: 5px; margin-left: 65px; opacity: 0.5; - color: #4a4a4a; + color: $primary-fg-color; } .mx_UploadBar_uploadIcon { @@ -57,5 +57,5 @@ limitations under the License. float: right; margin-top: 5px; margin-right: 30px; - color: #76cfa6; + color: $accent-color; } diff --git a/src/skins/vector/css/matrix-react-sdk/structures/UserSettings.css b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss similarity index 85% rename from src/skins/vector/css/matrix-react-sdk/structures/UserSettings.css rename to src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss index 427369a5c7..5c1b4c5c7e 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/UserSettings.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss @@ -20,34 +20,19 @@ limitations under the License. margin-left: auto; margin-right: auto; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; flex-direction: column; - -webkit-flex-direction: column; } .mx_UserSettings .mx_RoomHeader { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; order: 1; - -webkit-flex: 0 0 70px; flex: 0 0 70px; } .mx_UserSettings_body { - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; - -webkit-flex: 1 1 0; flex: 1 1 0; margin-top: -20px; @@ -58,7 +43,7 @@ limitations under the License. clear: both; margin-left: 63px; text-transform: uppercase; - color: #3d3b39; + color: $h3-color; font-weight: 600; font-size: 13px; margin-top: 26px; @@ -84,8 +69,8 @@ limitations under the License. border-radius: 36px; font-weight: 400; font-size: 16px; - color: #fff; - background-color: #76cfa6; + color: $accent-fg-color; + background-color: $accent-color; width: auto; margin: auto; padding: 7px; @@ -95,7 +80,7 @@ limitations under the License. } .mx_UserSettings_button.danger { - background-color: #ff0064; + background-color: $warning-color; } .mx_UserSettings_section { @@ -166,10 +151,10 @@ limitations under the License. { display: inline-block; border: 0px; - border-bottom: 1px solid rgba(151, 151, 151, 0.5); + border-bottom: 1px solid $input-underline-color; padding: 0px; width: 240px; - color: rgba(74, 74, 74, 0.9); + color: $input-fg-color; font-family: 'Open Sans', Helvetica, Arial, Sans-Serif; font-size: 16px; } diff --git a/src/skins/vector/css/matrix-react-sdk/structures/login/Login.css b/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss similarity index 84% rename from src/skins/vector/css/matrix-react-sdk/structures/login/Login.css rename to src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss index 0f610b25da..a359627af3 100644 --- a/src/skins/vector/css/matrix-react-sdk/structures/login/Login.css +++ b/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss @@ -18,21 +18,15 @@ limitations under the License. width: 100%; height: 100%; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; - -webkit-align-items: center; align-items: center; - -webkit-justify-content: center; justify-content: center; overflow: auto; } .mx_Login h2 { - color: #4a4a4a; + color: $primary-fg-color; font-weight: 300; margin-top: 32px; margin-bottom: 20px; @@ -48,12 +42,24 @@ limitations under the License. .mx_Login_logo { text-align: center; + height: 195px; +} + +.mx_Login_logo img { + max-height: 100% +} + +.mx_Login_support { + text-align: center; + font-size: 13px; + margin-top: 0px; + opacity: 0.7; } .mx_Login_field { - width: 100%; + width: 280px; border-radius: 3px; - border: 1px solid #c7c7c7; + border: 1px solid $strong-input-border-color; font-weight: 300; font-size: 13px; padding: 9px; @@ -75,9 +81,9 @@ limitations under the License. border-radius: 40px; height: 40px; border: 0px; - background-color: #76cfa6; + background-color: $accent-color; font-size: 15px; - color: #fff; + color: $accent-fg-color; } .mx_Login_label { @@ -99,7 +105,7 @@ limitations under the License. } .mx_Login_create:link { - color: #4a4a4a; + color: $primary-fg-color; } .mx_Login_links { @@ -112,7 +118,7 @@ limitations under the License. } .mx_Login_links a:link { - color: #4a4a4a; + color: $primary-fg-color; } .mx_Login_prompt { @@ -127,7 +133,7 @@ limitations under the License. } .mx_Login_forgot:link { - color: #4a4a4a; + color: $primary-fg-color; } .mx_Login_loader { @@ -147,7 +153,7 @@ limitations under the License. } .mx_Login_error { - color: #ff2020; + color: $warning-color; font-weight: bold; text-align: center; /* diff --git a/src/skins/vector/css/matrix-react-sdk/views/avatars/BaseAvatar.css b/src/skins/vector/css/matrix-react-sdk/views/avatars/_BaseAvatar.scss similarity index 93% rename from src/skins/vector/css/matrix-react-sdk/views/avatars/BaseAvatar.css rename to src/skins/vector/css/matrix-react-sdk/views/avatars/_BaseAvatar.scss index 901a29599a..f23b929b81 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/avatars/BaseAvatar.css +++ b/src/skins/vector/css/matrix-react-sdk/views/avatars/_BaseAvatar.scss @@ -21,7 +21,7 @@ limitations under the License. .mx_BaseAvatar_initial { position: absolute; z-index: 1; - color: #fff; + color: $avatar-initial-color; text-align: center; speak: none; pointer-events: none; @@ -31,4 +31,5 @@ limitations under the License. .mx_BaseAvatar_image { border-radius: 40px; vertical-align: top; + background-color: #fff; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_BugReportDialog.scss b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_BugReportDialog.scss new file mode 100644 index 0000000000..0f47e974da --- /dev/null +++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_BugReportDialog.scss @@ -0,0 +1,20 @@ +/* +Copyright 2017 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. +*/ + +.mx_BugReportDialog_input { + width: 100%; + box-sizing: border-box; +} diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/ChatInviteDialog.css b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss similarity index 89% rename from src/skins/vector/css/matrix-react-sdk/views/dialogs/ChatInviteDialog.css rename to src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss index aa1dced80a..4a214b51ce 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/dialogs/ChatInviteDialog.css +++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss @@ -36,7 +36,7 @@ limitations under the License. .mx_ChatInviteDialog_inputContainer { border-radius: 3px; - border: solid 1px #f0f0f0; + border: solid 1px $input-border-color; line-height: 36px; padding-left: 4px; padding-right: 4px; @@ -49,7 +49,7 @@ limitations under the License. .mx_ChatInviteDialog_error { position: absolute; - color: #ff0064; + color: $warning-color; line-height: 36px; } @@ -63,3 +63,9 @@ limitations under the License. .mx_ChatInviteDialog_cancel object { pointer-events: none; } + +.mx_ChatInviteDialog_addressSelectHeader { + font-weight: bold; + line-height: 150%; + text-indent: 4px; +} diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/EncryptedEventDialog.css b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_EncryptedEventDialog.scss similarity index 90% rename from src/skins/vector/css/matrix-react-sdk/views/dialogs/EncryptedEventDialog.css rename to src/skins/vector/css/matrix-react-sdk/views/dialogs/_EncryptedEventDialog.scss index 5e72d7f8bf..cbc0195cac 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/dialogs/EncryptedEventDialog.css +++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_EncryptedEventDialog.scss @@ -24,7 +24,7 @@ limitations under the License. border: 0px; height: 36px; border-radius: 40px; - border: solid 1px #76cfa6; + border: solid 1px $accent-color; font-weight: 600; font-size: 14px; font-family: 'Open Sans', Arial, Helvetica, Sans-Serif; @@ -34,6 +34,6 @@ limitations under the License. padding-right: 1.5em; outline: none; cursor: pointer; - color: #76cfa6; - background-color: #fff; + color: $accent-color; + background-color: $primary-bg-color; } \ No newline at end of file diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/SetDisplayNameDialog.css b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss similarity index 85% rename from src/skins/vector/css/matrix-react-sdk/views/dialogs/SetDisplayNameDialog.css rename to src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss index 68409a803b..2f0750ad6b 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/dialogs/SetDisplayNameDialog.css +++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss @@ -16,9 +16,9 @@ limitations under the License. .mx_SetDisplayNameDialog_input { border-radius: 3px; - border: 1px solid #f0f0f0; + border: 1px solid $input-border-color; padding: 9px; - color: #454545; - background-color: #fff; + color: $primary-fg-color; + background-color: $primary-bg-color; font-size: 15px; } \ No newline at end of file diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss new file mode 100644 index 0000000000..804b3f419e --- /dev/null +++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss @@ -0,0 +1,67 @@ +/* +Copyright 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. +*/ + +// CSS voodoo to support a gemini-scrollbar for the contents of the dialog +.mx_Dialog_unknownDevice .mx_Dialog { + // ideally we'd shrink the height to fit when needed, but in practice this + // is a pain in the ass. plus might as well make the dialog big given how + // important it is. + height: 100%; + + // position the gemini scrollbar nicely + padding-right: 58px; +} + +.mx_UnknownDeviceDialog { + height: 100%; + display: flex; + flex-direction: column; +} + +.mx_UnknownDeviceDialog .mx_Dialog_content { + margin-bottom: 24px; +} + +.mx_UnknownDeviceDialog .mx_MemberDeviceInfo { + float: right; + clear: both; + padding: 0px; + padding-top: 8px; +} + +.mx_UnknownDeviceDialog .mx_MemberDeviceInfo_textButton { + border: 0px; + height: 24px; + border-radius: 40px; + border: solid 1px $accent-color; + font-weight: 600; + font-size: 13px; + font-family: 'Open Sans', Arial, Helvetica, Sans-Serif; + margin-left: 0px; + margin-right: 8px; + padding-left: 0.5em; + padding-right: 0.5em; + width: 85px; + outline: none; + cursor: pointer; + color: $accent-color; + background-color: $primary-bg-color; +} + +.mx_UnknownDeviceDialog .mx_UnknownDeviceDialog_deviceList li { + height: 40px; + border-bottom: 1px solid $primary-hairline-color; +} \ No newline at end of file diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/AddressSelector.css b/src/skins/vector/css/matrix-react-sdk/views/elements/_AddressSelector.scss similarity index 76% rename from src/skins/vector/css/matrix-react-sdk/views/elements/AddressSelector.css rename to src/skins/vector/css/matrix-react-sdk/views/elements/_AddressSelector.scss index aa0f8c6a4e..9871a7e881 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/elements/AddressSelector.css +++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_AddressSelector.scss @@ -16,13 +16,13 @@ limitations under the License. .mx_AddressSelector { position: absolute; - background-color: #fff; + background-color: $primary-bg-color; width: 485px; max-height: 116px; overflow-y: auto; border-radius: 3px; - background-color: #fff; - border: solid 1px #76cfa6; + background-color: $primary-bg-color; + border: solid 1px $accent-color; cursor: pointer; } @@ -31,15 +31,15 @@ limitations under the License. } .mx_AddressSelector_addressListElement .mx_AddressTile { - background-color: #fff; - border: solid 1px #fff; + background-color: $primary-bg-color; + border: solid 1px $primary-bg-color; } .mx_AddressSelector_addressListElement.mx_AddressSelector_selected { - background-color: #eaf5f0; /* selected colour */ + background-color: $selected-color; } .mx_AddressSelector_addressListElement.mx_AddressSelector_selected .mx_AddressTile { - background-color: #eaf5f0; /* selected colour */ - border: solid 1px #eaf5f0; /* selected colour */ + background-color: $selected-color; + border: solid 1px $selected-color; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/AddressTile.css b/src/skins/vector/css/matrix-react-sdk/views/elements/_AddressTile.scss similarity index 94% rename from src/skins/vector/css/matrix-react-sdk/views/elements/AddressTile.css rename to src/skins/vector/css/matrix-react-sdk/views/elements/_AddressTile.scss index 76c0e6032f..0ecfb17c83 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/elements/AddressTile.css +++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_AddressTile.scss @@ -18,9 +18,9 @@ limitations under the License. display: inline-block; border-radius: 3px; background-color: rgba(74, 73, 74, 0.1); - border: solid 1px #f0f0f0; + border: solid 1px $input-border-color; line-height: 26px; - color: #454545; + color: $primary-fg-color; font-size: 14px; font-weight: normal; margin-right: 4px; @@ -28,8 +28,8 @@ limitations under the License. .mx_AddressTile.mx_AddressTile_error { background-color: rgba(255, 0, 100, 0.1); - color: #ff0064; - border-color: #ff0064; + color: $warning-color; + border-color: $warning-color; } .mx_AddressTile_network { @@ -106,7 +106,7 @@ limitations under the License. } .mx_AddressTile_email.mx_AddressTile_justified { - width: 380px; /* name + id width */ + width: 200px; /* same as id width */ overflow: hidden; white-space: nowrap; text-overflow: ellipsis; diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/DirectorySearchBox.css b/src/skins/vector/css/matrix-react-sdk/views/elements/_DirectorySearchBox.scss similarity index 87% rename from src/skins/vector/css/matrix-react-sdk/views/elements/DirectorySearchBox.css rename to src/skins/vector/css/matrix-react-sdk/views/elements/_DirectorySearchBox.scss index 3a0922bcd2..94a92b23ce 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/elements/DirectorySearchBox.css +++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_DirectorySearchBox.scss @@ -17,19 +17,17 @@ limitations under the License. .mx_DirectorySearchBox { position: relative; border-radius: 3px; - border: 1px solid #c7c7c7; + border: 1px solid $strong-input-border-color; } .mx_DirectorySearchBox_container { display: flex; - display: -webkit-flex; padding-left: 9px; padding-right: 9px; } .mx_DirectorySearchBox_input { flex-grow: 1; - -webkit-flex-grow: 1; border: 0; padding: 0; font-weight: 300; @@ -44,9 +42,9 @@ input[type=text].mx_DirectorySearchBox_input:focus { padding: 3px; padding-left: 10px; padding-right: 10px; - background-color: #efefef; + background-color: $plinth-bg-color; border-radius: 3px; - background-image: url('img/icon-return.svg'); + background-image: url('../../img/icon-return.svg'); background-position: 8px 70%; background-repeat: no-repeat; text-indent: 18px; @@ -63,7 +61,7 @@ input[type=text].mx_DirectorySearchBox_input:focus { .mx_DirectorySearchBox_clear { display: inline-block; vertical-align: middle; - background: url('img/icon_context_delete.svg'); + background: url('../../img/icon_context_delete.svg'); background-position: 0 50%; background-repeat: no-repeat; width: 15px; diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/MemberEventListSummary.css b/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss similarity index 97% rename from src/skins/vector/css/matrix-react-sdk/views/elements/MemberEventListSummary.css rename to src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss index b8197805a0..7d1b059b3c 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/elements/MemberEventListSummary.css +++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss @@ -31,6 +31,6 @@ limitations under the License. } .mx_MemberEventListSummary_toggle { - color:#76cfa6; + color:$accent-color; cursor:pointer; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/ProgressBar.css b/src/skins/vector/css/matrix-react-sdk/views/elements/_ProgressBar.scss similarity index 88% rename from src/skins/vector/css/matrix-react-sdk/views/elements/ProgressBar.css rename to src/skins/vector/css/matrix-react-sdk/views/elements/_ProgressBar.scss index 7b5e0c7461..a3fee232d0 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/elements/ProgressBar.css +++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_ProgressBar.scss @@ -16,10 +16,10 @@ limitations under the License. .mx_ProgressBar { height: 5px; - border: 1px solid black; + border: 1px solid $progressbar-color; } .mx_ProgressBar_fill { height: 100%; - background-color: #000; + background-color: $progressbar-color; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/RichText.css b/src/skins/vector/css/matrix-react-sdk/views/elements/_RichText.scss similarity index 84% rename from src/skins/vector/css/matrix-react-sdk/views/elements/RichText.css rename to src/skins/vector/css/matrix-react-sdk/views/elements/_RichText.scss index f0b3c04645..72a4c0b7a4 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/elements/RichText.css +++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_RichText.scss @@ -1,14 +1,14 @@ .mx_UserPill { color: white; - background-color: #76cfa6; + background-color: $accent-color; padding: 2px 8px; border-radius: 16px; } .mx_RoomPill { background-color: white; - color: #76cfa6; - border: 1px solid #76cfa6; + color: $accent-color; + border: 1px solid $accent-color; padding: 2px 8px; border-radius: 16px; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/login/ServerConfig.css b/src/skins/vector/css/matrix-react-sdk/views/login/_ServerConfig.scss similarity index 96% rename from src/skins/vector/css/matrix-react-sdk/views/login/ServerConfig.css rename to src/skins/vector/css/matrix-react-sdk/views/login/_ServerConfig.scss index 75cd4170da..1ad195de29 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/login/ServerConfig.css +++ b/src/skins/vector/css/matrix-react-sdk/views/login/_ServerConfig.scss @@ -27,5 +27,5 @@ limitations under the License. opacity: 0.8; font-size: 13px; font-weight: 300; - color: #4a4a4a; + color: $primary-fg-color; } \ No newline at end of file diff --git a/src/skins/vector/css/matrix-react-sdk/views/messages/MImageBody.css b/src/skins/vector/css/matrix-react-sdk/views/messages/_MImageBody.scss similarity index 91% rename from src/skins/vector/css/matrix-react-sdk/views/messages/MImageBody.css rename to src/skins/vector/css/matrix-react-sdk/views/messages/_MImageBody.scss index 003ef1030c..83ae06160d 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/messages/MImageBody.css +++ b/src/skins/vector/css/matrix-react-sdk/views/messages/_MImageBody.scss @@ -22,18 +22,18 @@ limitations under the License. .mx_MImageBody_thumbnail { max-width: 100%; /* - background-color: #fff; - border: 2px solid #fff; + background-color: $primary-bg-color; + border: 2px solid $primary-bg-color; border-radius: 1px; */ } .mx_MImageBody_download { - color: #76cfa6; + color: $accent-color; } .mx_MImageBody_download a { - color: #76cfa6; + color: $accent-color; text-decoration: none; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/messages/MNoticeBody.css b/src/skins/vector/css/matrix-react-sdk/views/messages/_MNoticeBody.scss similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/messages/MNoticeBody.css rename to src/skins/vector/css/matrix-react-sdk/views/messages/_MNoticeBody.scss diff --git a/src/skins/vector/css/matrix-react-sdk/views/messages/MTextBody.css b/src/skins/vector/css/matrix-react-sdk/views/messages/_MTextBody.scss similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/messages/MTextBody.css rename to src/skins/vector/css/matrix-react-sdk/views/messages/_MTextBody.scss diff --git a/src/skins/vector/css/matrix-react-sdk/views/messages/TextualEvent.css b/src/skins/vector/css/matrix-react-sdk/views/messages/_TextualEvent.scss similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/messages/TextualEvent.css rename to src/skins/vector/css/matrix-react-sdk/views/messages/_TextualEvent.scss diff --git a/src/skins/vector/css/matrix-react-sdk/views/messages/UnknownBody.css b/src/skins/vector/css/matrix-react-sdk/views/messages/_UnknownBody.scss similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/messages/UnknownBody.css rename to src/skins/vector/css/matrix-react-sdk/views/messages/_UnknownBody.scss diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/Autocomplete.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_Autocomplete.scss similarity index 83% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/Autocomplete.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_Autocomplete.scss index 6d611b5ef3..062dd0bade 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/Autocomplete.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_Autocomplete.scss @@ -3,8 +3,8 @@ bottom: 0; z-index: 1000; width: 100%; - border: 1px solid #e5e5e5; - background: white; + border: 1px solid $primary-hairline-color; + background: $primary-bg-color; border-bottom: none; border-radius: 4px 4px 0 0; max-height: 50vh; @@ -12,7 +12,7 @@ } .mx_Autocomplete_ProviderSection { - border-bottom: 1px solid #e5e5e5; + border-bottom: 1px solid $primary-hairline-color; } .mx_Autocomplete_Completion_container_pill { @@ -28,7 +28,7 @@ user-select: none; cursor: pointer; align-items: center; - color: #4a4a4a; + color: $primary-fg-color; } .mx_Autocomplete_Completion_block * { @@ -42,7 +42,7 @@ user-select: none; cursor: pointer; align-items: center; - color: #4a4a4a; + color: $primary-fg-color; } .mx_Autocomplete_Completion_pill * { @@ -57,13 +57,13 @@ } .mx_Autocomplete_Completion.selected { - background: #f6f6f6; + background: $menu-bg-color; outline: none; } .mx_Autocomplete_provider_name { margin: 12px; - color: #454545; + color: $primary-fg-color; font-weight: 400; opacity: 0.4; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/EntityTile.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EntityTile.scss similarity index 96% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/EntityTile.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_EntityTile.scss index e52ece778d..3f360e79a0 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/EntityTile.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EntityTile.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_EntityTile { display: table-row; position: relative; - color: #454545; + color: $primary-fg-color; cursor: pointer; } @@ -77,12 +77,12 @@ limitations under the License. .mx_EntityTile_ellipsis .mx_EntityTile_name { font-style: italic; - font-color: #454545; + color: $primary-fg-color; } .mx_EntityTile_invitePlaceholder .mx_EntityTile_name { font-style: italic; - font-color: #454545; + color: $primary-fg-color; } .mx_EntityTile_unavailable .mx_EntityTile_avatar, diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/EventTile.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss similarity index 86% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/EventTile.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss index fd3f486b7d..29170a8305 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/EventTile.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss @@ -44,7 +44,7 @@ limitations under the License. } .mx_EventTile .mx_SenderProfile { - color: #454545; + color: $primary-fg-color; opacity: 0.5; font-size: 14px; display: block; /* anti-zalgo, with overflow hidden */ @@ -61,7 +61,7 @@ limitations under the License. display: block; visibility: hidden; white-space: nowrap; - color: #acacac; + color: $event-timestamp-color; font-size: 11px; left: 8px; position: absolute; @@ -93,20 +93,20 @@ limitations under the License. * TODO: ultimately we probably want some transition on here. */ .mx_EventTile_selected .mx_EventTile_line { - border-left: #76cfa6 5px solid; + border-left: $accent-color 5px solid; padding-left: 60px; - background-color: #f7f7f7; + background-color: $event-selected-color; } .mx_EventTile:hover .mx_EventTile_line, .mx_EventTile.menu .mx_EventTile_line { - background-color: #f7f7f7; + background-color: $event-selected-color; } .mx_EventTile_searchHighlight { - background-color: #76cfa6; - color: #fff; + background-color: $accent-color; + color: $accent-fg-color; border-radius: 5px; padding-left: 2px; padding-right: 2px; @@ -114,26 +114,26 @@ limitations under the License. } .mx_EventTile_searchHighlight a { - background-color: #76cfa6; - color: #fff; + background-color: $accent-color; + color: $accent-fg-color; } .mx_EventTile_encrypting { - color: #abddbc ! important; + color: $event-encrypting-color ! important; } .mx_EventTile_sending { - color: #ddd; + color: $event-sending-color; } .mx_EventTile_notSent { - color: #f44; + color: $event-notsent-color; } .mx_EventTile_highlight, .mx_EventTile_highlight .markdown-body { - color: #FF0064; + color: $warning-color; } .mx_EventTile_contextual { @@ -146,7 +146,12 @@ limitations under the License. z-index: 1; position: relative; width: 90px; - height: 1px; /* Hack to stop the height of this pushing the messages apart. Replaces marigin-top: -6px. This interacts better with a read marker being in between. Content overflows. */ + + /* Hack to stop the height of this pushing the messages apart. + Replaces margin-top: -6px. This interacts better with a read + marker being in between. Content overflows. */ + height: 1px; + margin-right: 10px; } @@ -172,6 +177,9 @@ limitations under the License. cursor: pointer; top: 6px; right: 6px; + width: 19px; + height: 19px; + background-image: url($edit-button-url); } .mx_EventTile:hover .mx_EventTile_editButton, @@ -204,7 +212,7 @@ limitations under the License. } .mx_EventTile_readAvatarRemainder { - color: #acacac; + color: $event-timestamp-color; font-size: 11px; position: absolute; } @@ -244,10 +252,10 @@ limitations under the License. } .mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line { - border-left: #76cfa5 5px solid; + border-left: $e2e-verified-color 5px solid; } .mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line { - border-left: #e8bf37 5px solid; + border-left: $e2e-unverified-color 5px solid; } .mx_EventTile:hover.mx_EventTile_verified .mx_MessageTimestamp, @@ -286,6 +294,10 @@ limitations under the License. overflow-y: visible; } +.mx_EventTile_content .markdown-body code { + background-color: #f8f8f8; +} + .mx_EventTile_content .markdown-body h1, .mx_EventTile_content .markdown-body h2, .mx_EventTile_content .markdown-body h3, @@ -297,7 +309,7 @@ limitations under the License. } .mx_EventTile_content .markdown-body a { - color: #76cfa6; + color: $accent-color; } .mx_EventTile_content .markdown-body .hljs { diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/LinkPreviewWidget.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_LinkPreviewWidget.scss similarity index 89% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/LinkPreviewWidget.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_LinkPreviewWidget.scss index 2e2d9f8046..33f283e0d3 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/LinkPreviewWidget.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_LinkPreviewWidget.scss @@ -18,14 +18,12 @@ limitations under the License. margin-top: 15px; margin-right: 15px; margin-bottom: 15px; - display: -webkit-flex; display: flex; - border-left: 4px solid #ddd; - color: #888; + border-left: 4px solid $preview-widget-bar-color; + color: $preview-widget-fg-color; } .mx_LinkPreviewWidget_image { - -webkit-flex: 0 0 100px; flex: 0 0 100px; margin-left: 15px; text-align: center; @@ -34,7 +32,6 @@ limitations under the License. .mx_LinkPreviewWidget_caption { margin-left: 15px; - -webkit-flex: 1 1 auto; flex: 1 1 auto; } @@ -56,7 +53,6 @@ limitations under the License. .mx_LinkPreviewWidget_cancel { visibility: hidden; cursor: pointer; - -webkit-flex: 0 0 40px; flex: 0 0 40px; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/MemberDeviceInfo.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberDeviceInfo.scss similarity index 90% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/MemberDeviceInfo.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberDeviceInfo.scss index 53379ac4ce..f1584d4e00 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/MemberDeviceInfo.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberDeviceInfo.scss @@ -20,8 +20,8 @@ limitations under the License. .mx_MemberDeviceInfo_textButton { - color: #fff; - background-color: #76cfa6; + color: $accent-fg-color; + background-color: $accent-color; border-radius: 17px; text-align: center; padding-left: 1em; @@ -50,13 +50,13 @@ limitations under the License. } /* "Unblacklist" is too long for a regular button: make it wider and - reduce the padding. */ + reduce the padding. */ .mx_EncryptedEventDialog .mx_MemberDeviceInfo_blacklist, .mx_EncryptedEventDialog .mx_MemberDeviceInfo_unblacklist { width: 8em; padding-left: 1em; padding-right: 1em; -} +} .mx_MemberDeviceInfo div.mx_MemberDeviceInfo_verified, .mx_MemberDeviceInfo div.mx_MemberDeviceInfo_unverified, @@ -66,13 +66,13 @@ limitations under the License. } .mx_MemberDeviceInfo div.mx_MemberDeviceInfo_verified { - color: #76cfa5; + color: $e2e-verified-color; } .mx_MemberDeviceInfo div.mx_MemberDeviceInfo_unverified { - color: #e8bf37; + color: $e2e-unverified-color; } .mx_MemberDeviceInfo div.mx_MemberDeviceInfo_blacklisted { - color: #ba6363; + color: $e2e-warning-color; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/MemberInfo.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberInfo.scss similarity index 94% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/MemberInfo.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberInfo.scss index 40b1524c27..d6fb5a19db 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/MemberInfo.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberInfo.scss @@ -61,7 +61,7 @@ limitations under the License. .mx_MemberInfo h3 { text-transform: uppercase; - color: #3d3b39; + color: $h3-color; font-weight: 600; font-size: 13px; margin-top: 16px; @@ -69,10 +69,9 @@ limitations under the License. } .mx_MemberInfo_profileField { - font-color: #999999; font-size: 13px; position: relative; - background-color: #fff; + background-color: $primary-bg-color; } .mx_MemberInfo_buttons { @@ -82,7 +81,7 @@ limitations under the License. .mx_MemberInfo_field { cursor: pointer; font-size: 13px; - color: #76cfa6; + color: $accent-color; margin-left: 8px; line-height: 23px; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/MemberList.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberList.scss similarity index 82% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/MemberList.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberList.scss index 7d38360601..d87bced43e 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/MemberList.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MemberList.scss @@ -20,22 +20,15 @@ limitations under the License. margin-top: 12px; margin-right: 20px; - -webkit-flex: 1; flex: 1; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; flex-direction: column; - -webkit-flex-direction: column; } .mx_MemberList .mx_Spinner { flex: 0; - -webkit-flex: 0; } .mx_MemberList_chevron { @@ -48,17 +41,16 @@ limitations under the License. overflow-y: auto; order: 1; - -webkit-flex: 1 1 0; flex: 1 1 0px; } .mx_MemberList_query { font-family: 'Open Sans', Arial, Helvetica, Sans-Serif; border-radius: 3px; - border: 1px solid #f0f0f0; + border: 1px solid $input-border-color; padding: 9px; - color: #454545; - background-color: #fff; + color: $primary-fg-color; + background-color: $primary-bg-color; margin-left: 3px; font-size: 14px; margin-bottom: 8px; @@ -66,13 +58,13 @@ limitations under the License. } .mx_MemberList_query::-moz-placeholder { - color: #454545; + color: $primary-fg-color; opacity: 0.5; font-size: 14px; } .mx_MemberList_query::-webkit-input-placeholder { - color: #454545; + color: $primary-fg-color; opacity: 0.5; font-size: 14px; } @@ -80,7 +72,6 @@ limitations under the License. .mx_MemberList_joined { order: 2; flex: 1 0 0; - -webkit-flex: 1 0 0; overflow-y: auto; } @@ -89,14 +80,13 @@ limitations under the License. .mx_MemberList_invited { order: 3; flex: 0 0 100px; - -webkit-flex: 0 0 100px; overflow-y: auto; } */ .mx_MemberList_invited h2 { text-transform: uppercase; - color: #3d3b39; + color: $h3-color; font-weight: 600; font-size: 13px; padding-left: 3px; diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/MessageComposer.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MessageComposer.scss similarity index 91% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/MessageComposer.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_MessageComposer.scss index 842f8db655..525cc1f654 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/MessageComposer.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MessageComposer.scss @@ -18,7 +18,7 @@ limitations under the License. max-width: 960px; vertical-align: middle; margin: auto; - border-top: 1px solid #e5e5e5; + border-top: 1px solid $primary-hairline-color; position: relative; } @@ -57,7 +57,7 @@ limitations under the License. height: 60px; text-align: center; font-style: italic; - color: #888; + color: $greyed-fg-color; } .mx_MessageComposer_input_wrapper { @@ -90,10 +90,10 @@ limitations under the License. } .mx_MessageComposer_input blockquote { - color: rgb(119, 119, 119); + color: $blockquote-fg-color; margin: 0 0 16px; padding: 0 15px; - border-left: 4px solid rgb(221, 221, 221); + border-left: 4px solid $blockquote-bar-color; } .mx_MessageComposer_input textarea { @@ -105,11 +105,9 @@ limitations under the License. border: 0px; resize: none; outline: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; box-shadow: none; - color: #454545; - background-color: #fff; + color: $primary-fg-color; + background-color: $primary-bg-color; font-size: 14px; max-height: 120px; overflow: auto; @@ -120,11 +118,11 @@ limitations under the License. /* hack for FF as vertical alignment of custom placeholder text is broken */ .mx_MessageComposer_input textarea::-moz-placeholder { line-height: 100%; - color: #76cfa6; + color: $accent-color; opacity: 1.0; } .mx_MessageComposer_input textarea::-webkit-input-placeholder { - color: #76cfa6; + color: $accent-color; } .mx_MessageComposer_upload, @@ -153,7 +151,7 @@ limitations under the License. .mx_MessageComposer_formatbar_wrapper { width: 100%; - background-color: #f7f7f7; + background-color: $menu-bg-color; box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.08); } @@ -170,7 +168,7 @@ limitations under the License. flex-direction: row; align-items: center; font-size: 10px; - color: #888; + color: $greyed-fg-color; } .mx_MessageComposer_formatbar * { diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/PresenceLabel.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_PresenceLabel.scss similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/PresenceLabel.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_PresenceLabel.scss diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomHeader.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss similarity index 77% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/RoomHeader.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss index 056fa8794b..4affc99490 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomHeader.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss @@ -16,7 +16,6 @@ limitations under the License. /* add 20px to the height of the header when editing */ .mx_RoomHeader_editing { - -webit-flex: 0 0 93px ! important; flex: 0 0 93px ! important; } @@ -24,63 +23,36 @@ limitations under the License. max-width: 960px; margin: auto; height: 70px; - - -webkit-align-items: center; align-items: center; - - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; } .mx_RoomHeader_leftRow { margin-left: -2px; - - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; order: 1; - - -webkit-flex: 1; flex: 1; } .mx_RoomHeader_spinner { height: 36px; - - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; - padding-left: 12px; padding-right: 12px; } .mx_RoomHeader_textButton { height: 36px; - background-color: #76cfa6; + background-color: $accent-color; border-radius: 36px; margin-right: 8px; - color: #fff; + color: $accent-fg-color; line-height: 34px; margin-top: -2px; text-align: center; - - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; - cursor: pointer; /* - -webkit-flex: 0 0 90px; flex: 0 0 90px; */ padding-left: 12px; @@ -88,27 +60,17 @@ limitations under the License. } .mx_RoomHeader_cancelButton { - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; - cursor: pointer; - padding-left: 12px; padding-right: 12px; } .mx_RoomHeader_rightRow { margin-top: 4px; - background-color: #fff; + background-color: $primary-bg-color; display: flex; align-items: center; - -webkit-box-ordinal-group: 3; - -moz-box-ordinal-group: 3; - -ms-flex-order: 3; - -webkit-order: 3; order: 3; } @@ -120,7 +82,7 @@ limitations under the License. .mx_RoomHeader_simpleHeader { line-height: 70px; - color: #454545; + color: $primary-fg-color; font-size: 22px; font-weight: bold; overflow: hidden; @@ -138,7 +100,7 @@ limitations under the License. width: 100%; height: 31px; overflow: hidden; - color: #454545; + color: $primary-fg-color; font-weight: bold; font-size: 22px; padding-left: 19px; @@ -153,7 +115,7 @@ limitations under the License. } .mx_RoomHeader_settingsHint { - color: #a2a2a2 ! important; + color: $settings-grey-fg-color ! important; } .mx_RoomHeader_searchStatus { @@ -174,21 +136,21 @@ limitations under the License. } .mx_RoomHeader_name:hover div:not(.mx_RoomHeader_editable) { - color: #76cfa6; + color: $accent-color; } .mx_RoomHeader_placeholder { - color: #a2a2a2 ! important; + color: $settings-grey-fg-color ! important; } .mx_RoomHeader_editable { - border-bottom: 1px solid #c7c7c7 ! important; + border-bottom: 1px solid $strong-input-border-color ! important; min-width: 150px; cursor: text; } .mx_RoomHeader_editable:focus { - border-bottom: 1px solid #76CFA6 ! important; + border-bottom: 1px solid $accent-color ! important; outline: none; box-shadow: none; } @@ -197,7 +159,7 @@ limitations under the License. vertical-align: bottom; float: left; max-height: 42px; - color: #A2A2A2; + color: $settings-grey-fg-color; font-weight: 300; font-size: 13px; margin-left: 19px; diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomList.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/RoomList.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomPreviewBar.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomPreviewBar.scss similarity index 77% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/RoomPreviewBar.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomPreviewBar.scss index 286a39f7d5..cc2e42787c 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomPreviewBar.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomPreviewBar.scss @@ -17,20 +17,10 @@ limitations under the License. .mx_RoomPreviewBar { text-align: center; height: 176px; - - -webkit-align-items: center; + background-color: $event-selected-color; align-items: center; - flex-direction: column; - -webkit-flex-direction: column; - justify-content: center; - -webkit-justify-content: center; - - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; } @@ -38,16 +28,16 @@ limitations under the License. } .mx_RoomPreviewBar_invite_text { - color: #454545; + color: $primary-fg-color; } .mx_RoomPreviewBar_join_text { - color: #ff0064; + color: $warning-color; } .mx_RoomPreviewBar_preview_text { margin-top: 25px; - color: #a4a4a4; + color: $settings-grey-fg-color; } .mx_RoomPreviewBar_join_text a { @@ -56,9 +46,7 @@ limitations under the License. } .mx_RoomPreviewBar_warning { - display: -webkit-flex; display: flex; - -webkit-align-items: center; align-items: center; padding: 8px; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomSettings.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomSettings.scss similarity index 92% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/RoomSettings.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomSettings.scss index 6a3b1ac8cb..ef115f6e9e 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomSettings.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomSettings.scss @@ -24,10 +24,10 @@ limitations under the License. .mx_RoomSettings_integrationsButton_error { position: relative; height: 36px; - background-color: #76cfa6; + background-color: $accent-color; border-radius: 36px; margin-right: 8px; - color: #fff; + color: $accent-fg-color; line-height: 34px; text-align: center; float: right; @@ -47,8 +47,8 @@ limitations under the License. font-size: 10pt; line-height: 1.5em; border-radius: 5px; - background-color: #000; - color: #fff; + background-color: $accent-color; + color: $accent-fg-color; } .mx_RoomSettings_e2eIcon { @@ -81,7 +81,7 @@ limitations under the License. .mx_RoomSettings h3 { text-transform: uppercase; - color: #3d3b39; + color: $h3-color; font-weight: 600; font-size: 13px; margin-top: 36px; @@ -174,7 +174,7 @@ limitations under the License. } .mx_RoomSettings_warning { - color: #ff0064; + color: $warning-color; font-weight: bold; margin-top: 8px; margin-bottom: 8px; @@ -182,13 +182,13 @@ limitations under the License. .mx_RoomSettings_editable { border: 0px; - border-bottom: 1px solid #c7c7c7; + border-bottom: 1px solid $strong-input-border-color; padding: 0px; min-width: 240px; } .mx_RoomSettings_editable:focus { - border-bottom: 1px solid #76CFA6; + border-bottom: 1px solid $accent-color; outline: none; box-shadow: none; } @@ -205,7 +205,7 @@ limitations under the License. } .mx_RoomSettings_aliasPlaceholder { - color: #a2a2a2; + color: $settings-grey-fg-color; } .mx_RoomSettings_buttons { @@ -220,8 +220,8 @@ limitations under the License. border-radius: 36px; font-weight: 400; font-size: 15px; - color: #fff; - background-color: #76cfa6; + color: $accent-fg-color; + background-color: $accent-color; width: auto; margin: auto; padding: 6px; diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomTile.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss similarity index 89% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/RoomTile.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss index 2822d82e88..34cc21d4a3 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/RoomTile.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss @@ -65,7 +65,7 @@ limitations under the License. position: absolute; content: ""; border-radius: 40px; - background-image: url("img/icons_ellipsis.svg"); + background-image: url("../../img/icons_ellipsis.svg"); background-size: 25px; width: 24px; height: 24px; @@ -78,7 +78,7 @@ limitations under the License. position: absolute; content: ""; border-radius: 40px; - background: #4A4A4A; + background: $primary-fg-color; bottom: 0; width: 24px; height: 24px; @@ -103,7 +103,7 @@ limitations under the License. padding-right: 6px; padding-top: 2px; padding-bottom: 3px; - color: rgba(69, 69, 69, 0.8); + color: $roomtile-name-color; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -142,7 +142,7 @@ limitations under the License. width: 0; height: 0; margin-left: 5px; - border-top: 5px solid #ff0064; + border-top: 5px solid $warning-color; border-right: 7px solid transparent; } @@ -154,7 +154,7 @@ limitations under the License. right: 8px; /*gutter */ top: 9px; border-radius: 8px; - color: #fff; + color: $accent-fg-color; font-weight: 600; font-size: 10px; text-align: center; @@ -171,15 +171,15 @@ limitations under the License. .mx_RoomTile.mx_RoomTile_noBadges .mx_RoomTile_badge.mx_RoomTile_badgeButton, .mx_RoomTile.mx_RoomTile_notificationStateMenu.mx_RoomTile_noBadges .mx_RoomTile_badge { - background-color: rgb(214, 214, 214); + background-color: $neutral-badge-color; } .mx_RoomTile_unreadNotify .mx_RoomTile_badge { - background-color: #76cfa6; + background-color: $accent-color; } .mx_RoomTile_highlight .mx_RoomTile_badge { - background-color: #ff0064; + background-color: $warning-color; } .mx_RoomTile_unread, .mx_RoomTile_highlight { @@ -187,7 +187,12 @@ limitations under the License. } .mx_RoomTile_selected { - background-color: rgba(255, 255, 255, 0.8); + background-color: $roomtile-selected-bg-color; +} + +.mx_RoomTile:focus { + outline: 0; + background-color: $roomtile-focused-bg-color; } .mx_RoomTile .mx_RoomTile_name.mx_RoomTile_badgeShown { diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/SearchableEntityList.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_SearchableEntityList.scss similarity index 84% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/SearchableEntityList.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_SearchableEntityList.scss index 76d9e21634..6116dd92ca 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/SearchableEntityList.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_SearchableEntityList.scss @@ -16,19 +16,17 @@ limitations under the License. .mx_SearchableEntityList { display: flex; - display: -webkit-flex; flex-direction: column; - -webkit-flex-direction: column; } .mx_SearchableEntityList_query { font-family: 'Open Sans', Arial, Helvetica, Sans-Serif; border-radius: 3px; - border: 1px solid #f0f0f0; + border: 1px solid $input-border-color; padding: 9px; - color: #454545; - background-color: #fff; + color: $primary-fg-color; + background-color: $primary-bg-color; margin-left: 3px; font-size: 15px; margin-bottom: 8px; @@ -36,20 +34,19 @@ limitations under the License. } .mx_SearchableEntityList_query::-moz-placeholder { - color: #454545; + color: $primary-fg-color; opacity: 0.5; font-size: 12px; } .mx_SearchableEntityList_query::-webkit-input-placeholder { - color: #454545; + color: $primary-fg-color; opacity: 0.5; font-size: 12px; } .mx_SearchableEntityList_listWrapper { flex: 1; - -webkit-flex: 1; overflow-y: auto; } @@ -67,14 +64,13 @@ limitations under the License. .mx_SearchableEntityList_hrWrapper { width: 100%; flex: 0 0 auto; - -webkit-flex: 0 0 auto; } .mx_SearchableEntityList hr { height: 1px; border: 0px; - color: #e1dddd; - background-color: #e1dddd; + color: $primary-fg-color; + background-color: $primary-fg-color; margin-right: 15px; margin-top: 11px; margin-bottom: 11px; diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/TabCompleteBar.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_TabCompleteBar.scss similarity index 92% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/TabCompleteBar.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_TabCompleteBar.scss index 1f8a345083..5dcbd21a47 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/TabCompleteBar.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_TabCompleteBar.scss @@ -27,7 +27,7 @@ limitations under the License. .mx_TabCompleteBar_command { margin-right: 8px; - background-color: #76CFA6; + background-color: $accent-color; padding-left: 8px; padding-right: 8px; padding-top: 2px; @@ -41,7 +41,7 @@ limitations under the License. .mx_TabCompleteBar_command .mx_TabCompleteBar_text { opacity: 1.0; vertical-align: initial; - color: #fff; + color: $accent-fg-color; } .mx_TabCompleteBar_item img { @@ -50,7 +50,7 @@ limitations under the License. } .mx_TabCompleteBar_text { - color: #4a4a4a; + color: $primary-fg-color; vertical-align: middle; opacity: 0.5; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/TopUnreadMessagesBar.css b/src/skins/vector/css/matrix-react-sdk/views/rooms/_TopUnreadMessagesBar.scss similarity index 95% rename from src/skins/vector/css/matrix-react-sdk/views/rooms/TopUnreadMessagesBar.css rename to src/skins/vector/css/matrix-react-sdk/views/rooms/_TopUnreadMessagesBar.scss index 77184d424f..7bbafcbe41 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/rooms/TopUnreadMessagesBar.css +++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_TopUnreadMessagesBar.scss @@ -19,7 +19,7 @@ limitations under the License. max-width: 960px; padding-top: 5px; padding-bottom: 5px; - border-bottom: 1px solid #e5e5e5; + border-bottom: 1px solid $primary-hairline-color; } .mx_TopUnreadMessagesBar_scrollUp { diff --git a/src/skins/vector/css/matrix-react-sdk/views/settings/DevicesPanel.css b/src/skins/vector/css/matrix-react-sdk/views/settings/_DevicesPanel.scss similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/settings/DevicesPanel.css rename to src/skins/vector/css/matrix-react-sdk/views/settings/_DevicesPanel.scss diff --git a/src/skins/vector/css/matrix-react-sdk/views/settings/IntegrationsManager.css b/src/skins/vector/css/matrix-react-sdk/views/settings/_IntegrationsManager.scss similarity index 95% rename from src/skins/vector/css/matrix-react-sdk/views/settings/IntegrationsManager.css rename to src/skins/vector/css/matrix-react-sdk/views/settings/_IntegrationsManager.scss index 93ee0e20fe..13fc9b2237 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/settings/IntegrationsManager.css +++ b/src/skins/vector/css/matrix-react-sdk/views/settings/_IntegrationsManager.scss @@ -24,7 +24,7 @@ limitations under the License. } .mx_IntegrationsManager iframe { - background-color: #fff; + background-color: $primary-bg-color; border: 0px; width: 100%; height: 100%; diff --git a/src/skins/vector/css/matrix-react-sdk/views/voip/CallView.css b/src/skins/vector/css/matrix-react-sdk/views/voip/_CallView.scss similarity index 91% rename from src/skins/vector/css/matrix-react-sdk/views/voip/CallView.css rename to src/skins/vector/css/matrix-react-sdk/views/voip/_CallView.scss index 8051b4d0d6..deb89a837c 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/voip/CallView.css +++ b/src/skins/vector/css/matrix-react-sdk/views/voip/_CallView.scss @@ -15,8 +15,8 @@ limitations under the License. */ .mx_CallView_voice { - background-color: #76cfa6; - color: #fff; + background-color: $accent-color; + color: $accent-fg-color; cursor: pointer; text-align: center; padding: 6px; diff --git a/src/skins/vector/css/matrix-react-sdk/views/voip/IncomingCallbox.css b/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss similarity index 90% rename from src/skins/vector/css/matrix-react-sdk/views/voip/IncomingCallbox.css rename to src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss index 5cf62091b3..64eac25d01 100644 --- a/src/skins/vector/css/matrix-react-sdk/views/voip/IncomingCallbox.css +++ b/src/skins/vector/css/matrix-react-sdk/views/voip/_IncomingCallbox.scss @@ -18,7 +18,7 @@ limitations under the License. text-align: center; border: 1px solid #a4a4a4; border-radius: 8px; - background-color: #fff; + background-color: $primary-bg-color; position: fixed; z-index: 1000; padding: 6px; @@ -41,14 +41,12 @@ limitations under the License. .mx_IncomingCallBox_buttons { display: flex; - display: -webkit-flex; } .mx_IncomingCallBox_buttons_cell { vertical-align: middle; padding: 6px; flex: 1; - -webkit-flex: 1; } .mx_IncomingCallBox_buttons_decline, @@ -58,14 +56,14 @@ limitations under the License. height: 36px; line-height: 36px; border-radius: 36px; - color: #fff; + color: $accent-fg-color; margin: auto; } .mx_IncomingCallBox_buttons_decline { - background-color: #f48080; + background-color: $voip-decline-color; } .mx_IncomingCallBox_buttons_accept { - background-color: #80f480; + background-color: $voip-accept-color; } diff --git a/src/skins/vector/css/matrix-react-sdk/views/voip/VideoView.css b/src/skins/vector/css/matrix-react-sdk/views/voip/_VideoView.scss similarity index 100% rename from src/skins/vector/css/matrix-react-sdk/views/voip/VideoView.css rename to src/skins/vector/css/matrix-react-sdk/views/voip/_VideoView.scss diff --git a/src/skins/vector/css/rethemendex.sh b/src/skins/vector/css/rethemendex.sh new file mode 100755 index 0000000000..a7d9a657ac --- /dev/null +++ b/src/skins/vector/css/rethemendex.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +cd `dirname $0` + +{ + echo "// autogenerated by rethemendex.sh" + + find . \! \( -path ./themes -prune \) -iname _\*.scss | + fgrep -v _components.scss | LC_ALL=C sort | + while read i; do + echo "@import \"$i\";" + done +} > _components.scss diff --git a/src/skins/vector/css/themes/_base.scss b/src/skins/vector/css/themes/_base.scss new file mode 100644 index 0000000000..7612c68144 --- /dev/null +++ b/src/skins/vector/css/themes/_base.scss @@ -0,0 +1,107 @@ + +// typical text (dark-on-white in light skin) +$primary-fg-color: #454545; +$primary-bg-color: #ffffff; + +// used for dialog box text +$light-fg-color: #747474; + +// used for focusing form controls +$focus-bg-color: #dddddd; + +// button UI (white-on-green in light skin) +$accent-fg-color: #ffffff; +$accent-color: #76CFA6; + +$selection-fg-color: $primary-bg-color; + +// red warning colour +$warning-color: #ff0064; + +// left-panel style muted accent color +$secondary-accent-color: #eaf5f0; + +// used by RoomDirectory permissions +$plinth-bg-color: $secondary-accent-color; + +// used by RoomDropTarget +$droptarget-bg-color: rgba(255,255,255,0.5); + +// used by AddressSelector +$selected-color: #eaf5f0; + +// selected for hoverover & selected event tiles +$event-selected-color: #f7f7f7; + +// used for the hairline dividers in RoomView +$primary-hairline-color: #e5e5e5; + +// used for the border of input text fields +$input-border-color: #f0f0f0; + +// apart from login forms, which have stronger border +$strong-input-border-color: #c7c7c7; + +// used for UserSettings EditableText +$input-underline-color: rgba(151, 151, 151, 0.5); +$input-fg-color: rgba(74, 74, 74, 0.9); + +// context menus +$menu-border-color: rgba(187, 187, 187, 0.5); +$menu-bg-color: #f6f6f6; + +$avatar-initial-color: #ffffff; + +$h3-color: #3d3b39; + +$dialog-background-bg-color: #e9e9e9; +$lightbox-background-bg-color: #000; + +$greyed-fg-color: #888; + +$neutral-badge-color: #dbdbdb; + +$preview-widget-bar-color: #ddd; +$preview-widget-fg-color: $greyed-fg-color; + +$blockquote-bar-color: #ddd; +$blockquote-fg-color: #777; + +$settings-grey-fg-color: #a2a2a2; + +$voip-decline-color: #f48080; +$voip-accept-color: #80f480; + +// ******************** + +$roomtile-name-color: rgba(69, 69, 69, 0.8); +$roomtile-selected-bg-color: rgba(255, 255, 255, 0.8); +$roomtile-focused-bg-color: rgba(255, 255, 255, 0.9); + +$roomsublist-label-fg-color: $h3-color; +$roomsublist-label-bg-color: #d3efe1; + +// ******************** + +// event tile lifecycle +$event-encrypting-color: #abddbc; +$event-sending-color: #ddd; +$event-notsent-color: #f44; + +// event timestamp +$event-timestamp-color: #acacac; + +$edit-button-url: "../../img/icon_context_message.svg"; + +// e2e +$e2e-verified-color: #76cfa5; // N.B. *NOT* the same as $accent-color +$e2e-unverified-color: #e8bf37; +$e2e-warning-color: #ba6363; + +/*** ImageView ***/ +$lightbox-bg-color: #454545; +$lightbox-fg-color: #ffffff; +$lightbox-border-color: #ffffff; + +// unused? +$progressbar-color: #000; \ No newline at end of file diff --git a/src/skins/vector/css/themes/_dark.scss b/src/skins/vector/css/themes/_dark.scss new file mode 100644 index 0000000000..54a117ea08 --- /dev/null +++ b/src/skins/vector/css/themes/_dark.scss @@ -0,0 +1,127 @@ + +// typical text (dark-on-white in light skin) +$primary-fg-color: #dddddd; +$primary-bg-color: #2d2d2d; + +// used for focusing form controls +$focus-bg-color: #101010; + +// used for dialog box text +$light-fg-color: #747474; + +// button UI (white-on-green in light skin) +$accent-fg-color: $primary-bg-color; +$accent-color: #76CFA6; + +$selection-fg-color: $primary-bg-color; + +// red warning colour +$warning-color: #ff0064; + +// left-panel style muted accent color +$secondary-accent-color: $primary-bg-color; + +// used by RoomDirectory permissions +$plinth-bg-color: #474747; + +// used by RoomDropTarget +$droptarget-bg-color: rgba(45,45,45,0.5); + +// used by AddressSelector +$selected-color: #eaf5f0; + +// selected for hoverover & selected event tiles +$event-selected-color: #353535; + +// used for the hairline dividers in RoomView +$primary-hairline-color: #474747; + +// used for the border of input text fields +$input-border-color: #3a3a3a; + +// apart from login forms, which have stronger border +$strong-input-border-color: #656565; + +// used for UserSettings EditableText +$input-underline-color: $primary-fg-color; +$input-fg-color: $primary-fg-color; + +// context menus +$menu-border-color: rgba(187, 187, 187, 0.5); +$menu-bg-color: #373737; + +$avatar-initial-color: #2d2d2d; + +$h3-color: $primary-fg-color; + +$dialog-background-bg-color: #000; +$lightbox-background-bg-color: #000; + +$greyed-fg-color: #888; + +$neutral-badge-color: #888; + +$preview-widget-bar-color: $menu-bg-color; +$preview-widget-fg-color: $greyed-fg-color; + +$blockquote-bar-color: #ddd; +$blockquote-fg-color: #777; + +$settings-grey-fg-color: #a2a2a2; + +$voip-decline-color: #f48080; +$voip-accept-color: #80f480; + +// ******************** + +$roomtile-name-color: rgba(186, 186, 186, 0.8); +$roomtile-selected-bg-color: rgba(255, 255, 255, 0.05); +$roomtile-focused-bg-color: rgba(255, 255, 255, 0.2); + +$roomsublist-label-fg-color: $h3-color; +$roomsublist-label-bg-color: #454545; + +// ******************** + +// event tile lifecycle +$event-encrypting-color: rgba(171, 221, 188, 0.4); +$event-sending-color: #ddd; +$event-notsent-color: #f44; + +// event timestamp +$event-timestamp-color: #acacac; + +$edit-button-url: "../../img/icon_context_message_dark.svg"; + +// e2e +$e2e-verified-color: #76cfa5; // N.B. *NOT* the same as $accent-color +$e2e-unverified-color: #e8bf37; +$e2e-warning-color: #ba6363; + +/*** ImageView ***/ +$lightbox-bg-color: #454545; +$lightbox-fg-color: #ffffff; +$lightbox-border-color: #ffffff; + +// unused? +$progressbar-color: #000; + +// Nasty hacks to apply a filter to arbitrary monochrome artwork to make it +// better match the theme. Typically applied to dark grey 'off' buttons or +// light grey 'on' buttons. +.mx_filterFlipColor { + filter: invert(); +} + +.gm-scrollbar .thumb { + filter: invert(); +} + +.mx_EventTile_content .markdown-body pre, +.mx_EventTile_content .markdown-body code { + filter: invert(); +} + +.mx_EventTile_content .markdown-body pre code { + filter: none; +} \ No newline at end of file diff --git a/src/skins/vector/css/themes/dark.scss b/src/skins/vector/css/themes/dark.scss new file mode 100644 index 0000000000..5a37d0368e --- /dev/null +++ b/src/skins/vector/css/themes/dark.scss @@ -0,0 +1,3 @@ +@import "_base.scss"; +@import "_dark.scss"; +@import "../_components.scss"; diff --git a/src/skins/vector/css/themes/light.scss b/src/skins/vector/css/themes/light.scss new file mode 100644 index 0000000000..ea0f93d5a3 --- /dev/null +++ b/src/skins/vector/css/themes/light.scss @@ -0,0 +1,2 @@ +@import "_base.scss"; +@import "../_components.scss"; \ No newline at end of file diff --git a/src/skins/vector/css/vector-web/fonts.css b/src/skins/vector/css/vector-web/_fonts.scss similarity index 57% rename from src/skins/vector/css/vector-web/fonts.css rename to src/skins/vector/css/vector-web/_fonts.scss index 719eeebcb4..52ac95b569 100644 --- a/src/skins/vector/css/vector-web/fonts.css +++ b/src/skins/vector/css/vector-web/_fonts.scss @@ -3,44 +3,46 @@ * Includes extended Latin, Greek, Cyrillic and Vietnamese character sets */ +/* the 'src' links are relative to the bundle.css, which is in a subdirectory. + */ @font-face { font-family: 'Open Sans'; - src: url('fonts/Open_Sans/OpenSans-Regular.ttf') format('truetype'); + src: url('../../fonts/Open_Sans/OpenSans-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; } @font-face { font-family: 'Open Sans'; - src: url('fonts/Open_Sans/OpenSans-Italic.ttf') format('truetype'); + src: url('../../fonts/Open_Sans/OpenSans-Italic.ttf') format('truetype'); font-weight: 400; font-style: italic; } @font-face { font-family: 'Open Sans'; - src: url('fonts/Open_Sans/OpenSans-Semibold.ttf') format('truetype'); + src: url('../../fonts/Open_Sans/OpenSans-Semibold.ttf') format('truetype'); font-weight: 600; font-style: normal; } @font-face { font-family: 'Open Sans'; - src: url('fonts/Open_Sans/OpenSans-SemiboldItalic.ttf') format('truetype'); + src: url('../../fonts/Open_Sans/OpenSans-SemiboldItalic.ttf') format('truetype'); font-weight: 600; font-style: italic; } @font-face { font-family: 'Open Sans'; - src: url('fonts/Open_Sans/OpenSans-Bold.ttf') format('truetype'); + src: url('../../fonts/Open_Sans/OpenSans-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; } @font-face { font-family: 'Open Sans'; - src: url('fonts/Open_Sans/OpenSans-BoldItalic.ttf') format('truetype'); + src: url('../../fonts/Open_Sans/OpenSans-BoldItalic.ttf') format('truetype'); font-weight: 700; font-style: italic; } @@ -52,14 +54,14 @@ @font-face { font-family: 'Fira Mono'; - src: url('fonts/Fira_Mono/FiraMono-Regular.ttf') format('truetype'); + src: url('../../fonts/Fira_Mono/FiraMono-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; } @font-face { font-family: 'Fira Mono'; - src: url('fonts/Fira_Mono/FiraMono-Bold.ttf') format('truetype'); + src: url('../../fonts/Fira_Mono/FiraMono-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; } diff --git a/src/skins/vector/css/vector-web/structures/CompatibilityPage.css b/src/skins/vector/css/vector-web/structures/_CompatibilityPage.scss similarity index 100% rename from src/skins/vector/css/vector-web/structures/CompatibilityPage.css rename to src/skins/vector/css/vector-web/structures/_CompatibilityPage.scss diff --git a/src/skins/vector/css/vector-web/structures/LeftPanel.css b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss similarity index 84% rename from src/skins/vector/css/vector-web/structures/LeftPanel.css rename to src/skins/vector/css/vector-web/structures/_LeftPanel.scss index 4e3281716e..1ce10e51f6 100644 --- a/src/skins/vector/css/vector-web/structures/LeftPanel.css +++ b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss @@ -17,13 +17,8 @@ limitations under the License. .mx_LeftPanel { position: relative; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; flex-direction: column; - -webkit-flex-direction: column; } .mx_LeftPanel_hideButton { @@ -39,13 +34,8 @@ limitations under the License. } .mx_LeftPanel .mx_RoomList_scrollbar { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; order: 1; - -webkit-flex: 1 1 0; flex: 1 1 0; overflow-y: auto; @@ -57,16 +47,11 @@ limitations under the License. } .mx_LeftPanel .mx_BottomLeftMenu { - -webkit-box-ordinal-group: 3; - -moz-box-ordinal-group: 3; - -ms-flex-order: 3; - -webkit-order: 3; order: 3; border-top: 1px solid rgba(118, 207, 166, 0.2); margin-left: 16px; /* gutter */ margin-right: 16px; /* gutter */ - -webkit-flex: 0 0 60px; flex: 0 0 60px; z-index: 1; } diff --git a/src/skins/vector/css/vector-web/structures/RightPanel.css b/src/skins/vector/css/vector-web/structures/_RightPanel.scss similarity index 72% rename from src/skins/vector/css/vector-web/structures/RightPanel.css rename to src/skins/vector/css/vector-web/structures/_RightPanel.scss index 5da4c4ab1a..c0872e82d7 100644 --- a/src/skins/vector/css/vector-web/structures/RightPanel.css +++ b/src/skins/vector/css/vector-web/structures/_RightPanel.scss @@ -17,26 +17,16 @@ limitations under the License. .mx_RightPanel { position: relative; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; flex-direction: column; - -webkit-flex-direction: column; } .mx_RightPanel_header { - -webkit-box-ordinal-group: 1; - -moz-box-ordinal-group: 1; - -ms-flex-order: 1; - -webkit-order: 1; order: 1; - border-bottom: 1px solid #e5e5e5; + border-bottom: 1px solid $primary-hairline-color; margin-right: 20px; - -webkit-flex: 0 0 70px; flex: 0 0 70px; } @@ -44,14 +34,15 @@ limitations under the License. .mx_RightPanel_headerButtonGroup { margin-top: 6px; - float: left; - background-color: #fff; + display: flex; + width: 100%; + background-color: $primary-bg-color; margin-left: 0px; } .mx_RightPanel_headerButton { cursor: pointer; - display: table-cell; + flex: 0; vertical-align: top; padding-left: 4px; padding-right: 5px; @@ -68,46 +59,43 @@ limitations under the License. width: 25px; height: 5px; border-radius: 5px; - background-color: rgba(118, 207, 166, 0.2); + background-color: $accent-color; + opacity: 0.2; } .mx_RightPanel_headerButton_badge { font-size: 11px; - color: #76cfa6; + color: $accent-color; font-weight: bold; padding-bottom: 2px; } +.mx_RightPanel_collapsebutton { + flex: 1; + text-align: right; + margin-top: 20px; +} + .mx_RightPanel .mx_MemberList, .mx_RightPanel .mx_MemberInfo, .mx_RightPanel_blank { - -webkit-box-ordinal-group: 2; - -moz-box-ordinal-group: 2; - -ms-flex-order: 2; - -webkit-order: 2; order: 2; flex: 1 1 0; - -webkit-flex: 1 1 0; } .mx_RightPanel_footer { - -webkit-box-ordinal-group: 3; - -moz-box-ordinal-group: 3; - -ms-flex-order: 3; - -webkit-order: 3; order: 3; - border-top: 1px solid #e5e5e5; + border-top: 1px solid $primary-hairline-color; margin-right: 20px; - -webkit-flex: 0 0 60px; flex: 0 0 60px; } .mx_RightPanel_footer .mx_RightPanel_invite { line-height: 35px; font-size: 14px; - color: #4A4A4A; + color: $primary-fg-color; padding-top: 13px; padding-left: 5px; cursor: pointer; diff --git a/src/skins/vector/css/vector-web/structures/RoomDirectory.css b/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss similarity index 82% rename from src/skins/vector/css/vector-web/structures/RoomDirectory.css rename to src/skins/vector/css/vector-web/structures/_RoomDirectory.scss index 563b1772c9..6e508ec78f 100644 --- a/src/skins/vector/css/vector-web/structures/RoomDirectory.css +++ b/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss @@ -20,35 +20,23 @@ limitations under the License. margin-left: auto; margin-right: auto; margin-bottom: 12px; - color: #4a4a4a; + color: $primary-fg-color; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; flex-direction: column; - -webkit-flex-direction: column; } .mx_RoomDirectory_list { - -webkit-flex: 1; flex: 1; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; flex-direction: column; - -webkit-flex-direction: column; } .mx_RoomDirectory_list .mx_RoomView_messageListWrapper { justify-content: flex-start; - -webkit-justify-content: flex-start; } .mx_RoomDirectory_listheader { @@ -72,13 +60,12 @@ limitations under the License. .mx_RoomDirectory_tableWrapper { overflow-y: auto; - -webkit-flex: 1 1 0; flex: 1 1 0; } .mx_RoomDirectory_table { font-size: 14px; - color: #4a4a4a; + color: $primary-fg-color; width: 100%; text-align: left; table-layout: fixed; @@ -110,11 +97,11 @@ limitations under the License. padding-right: 5px; height: 15px; border-radius: 11px; - background-color: #eaf5f0; + background-color: $plinth-bg-color; text-transform: uppercase; font-weight: 600; font-size: 11px; - color: #61c295; + color: $accent-color; } .mx_RoomDirectory_topic { @@ -123,7 +110,7 @@ limitations under the License. .mx_RoomDirectory_alias { font-size: 12px; - color: #b3b3b3; + color: $settings-grey-fg-color; } .mx_RoomDirectory_roomMemberCount { diff --git a/src/skins/vector/css/vector-web/structures/RoomSubList.css b/src/skins/vector/css/vector-web/structures/_RoomSubList.scss similarity index 87% rename from src/skins/vector/css/vector-web/structures/RoomSubList.css rename to src/skins/vector/css/vector-web/structures/_RoomSubList.scss index e6e81aefb1..0d56d6c378 100644 --- a/src/skins/vector/css/vector-web/structures/RoomSubList.css +++ b/src/skins/vector/css/vector-web/structures/_RoomSubList.scss @@ -29,7 +29,7 @@ limitations under the License. .mx_RoomSubList_label { position: relative; text-transform: uppercase; - color: #3d3b39; + color: $roomsublist-label-fg-color; font-weight: 600; font-size: 12px; width: 203px; /* padding + width = LHS Panel width */ @@ -39,8 +39,8 @@ limitations under the License. padding-top: 6px; padding-bottom: 6px; cursor: pointer; - background-color: #d3efe1; - border-top: solid 2px #eaf5f0; + background-color: $roomsublist-label-bg-color; + border-top: solid 2px $secondary-accent-color; } .mx_RoomSubList_label.mx_RoomSubList_fixed { @@ -63,7 +63,7 @@ limitations under the License. display: inline-block; font-size: 12px; font-weight: normal; - color: #76cfa6; + color: $accent-color; padding-left: 5px; text-transform: none; } @@ -80,14 +80,14 @@ limitations under the License. right: 8px; /*gutter */ top: 7px; border-radius: 8px; - color: #fff; + color: $accent-fg-color; font-weight: 600; font-size: 10px; text-align: center; padding-top: 1px; padding-left: 4px; padding-right: 4px; - background-color: #76cfa6; + background-color: $accent-color; } /* @@ -97,7 +97,7 @@ limitations under the License. */ .mx_RoomSubList_badgeHighlight { - background-color: #ff0064; + background-color: $warning-color; } /* This is the bottom of the speech bubble */ @@ -108,7 +108,7 @@ limitations under the License. width: 0; height: 0; margin-left: 5px; - border-top: 5px solid #ff0064; + border-top: 5px solid $warning-color; border-right: 7px solid transparent; } @@ -129,7 +129,7 @@ limitations under the License. height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; - border-top: 6px solid #76cfa6; + border-top: 6px solid $accent-color; } .mx_RoomSubList_chevronUp { @@ -137,14 +137,14 @@ limitations under the License. height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; - border-bottom: 6px solid #76cfa6; + border-bottom: 6px solid $accent-color; } .mx_RoomSubList_chevronRight { width: 0; height: 0; border-top: 5px solid transparent; - border-left: 6px solid #76cfa6; + border-left: 6px solid $accent-color; border-bottom: 5px solid transparent; } @@ -165,7 +165,7 @@ limitations under the License. .mx_RoomSubList_line { display: inline-block; width: 159px; - border-top: dotted 2px #76cfa6; + border-top: dotted 2px $accent-color; vertical-align: middle; } @@ -179,7 +179,7 @@ limitations under the License. font-size: 10px; font-weight: 600; text-align: left; - color: #76cfa6; + color: $accent-color; padding-left: 7px; padding-right: 7px; padding-left: 7px; @@ -198,20 +198,20 @@ limitations under the License. right: 8px; /*gutter */ top: -2px; border-radius: 8px; - border: solid 1px #76cfa6; - color: #fff; + border: solid 1px $accent-color; + color: $accent-fg-color; font-weight: 600; font-size: 10px; text-align: center; padding-top: 1px; padding-left: 3px; padding-right: 3px; - background-color: #fff; + background-color: $primary-bg-color; vertical-align: middle; } .mx_RoomSubList_moreBadge.mx_RoomSubList_moreBadgeNotify { - background-color: #76cfa6; + background-color: $accent-color; border: 0; padding-top: 3px; padding-left: 4px; @@ -219,7 +219,7 @@ limitations under the License. } .mx_RoomSubList_moreBadge.mx_RoomSubList_moreBadgeHighlight { - background-color: #ff0064; + background-color: $warning-color; border: 0; padding-top: 3px; padding-left: 4px; diff --git a/src/skins/vector/css/vector-web/structures/ViewSource.css b/src/skins/vector/css/vector-web/structures/_ViewSource.scss similarity index 100% rename from src/skins/vector/css/vector-web/structures/ViewSource.css rename to src/skins/vector/css/vector-web/structures/_ViewSource.scss diff --git a/src/skins/vector/css/vector-web/views/context_menus/MessageContextMenu.css b/src/skins/vector/css/vector-web/views/context_menus/_MessageContextMenu.scss similarity index 100% rename from src/skins/vector/css/vector-web/views/context_menus/MessageContextMenu.css rename to src/skins/vector/css/vector-web/views/context_menus/_MessageContextMenu.scss diff --git a/src/skins/vector/css/vector-web/views/context_menus/NotificationStateContextMenu.css b/src/skins/vector/css/vector-web/views/context_menus/_NotificationStateContextMenu.scss similarity index 100% rename from src/skins/vector/css/vector-web/views/context_menus/NotificationStateContextMenu.css rename to src/skins/vector/css/vector-web/views/context_menus/_NotificationStateContextMenu.scss diff --git a/src/skins/vector/css/vector-web/views/context_menus/RoomTagContextMenu.css b/src/skins/vector/css/vector-web/views/context_menus/_RoomTagContextMenu.scss similarity index 96% rename from src/skins/vector/css/vector-web/views/context_menus/RoomTagContextMenu.css rename to src/skins/vector/css/vector-web/views/context_menus/_RoomTagContextMenu.scss index 947fd480fe..16a3ab79b1 100644 --- a/src/skins/vector/css/vector-web/views/context_menus/RoomTagContextMenu.css +++ b/src/skins/vector/css/vector-web/views/context_menus/_RoomTagContextMenu.scss @@ -31,7 +31,7 @@ limitations under the License. .mx_RoomTagContextMenu_field:last-child { padding-bottom: 4px; - color: #ff0064; + color: $warning-color; } .mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldSet { @@ -70,8 +70,7 @@ limitations under the License. border-right-style: none; border-top-style: solid; border-top-width: 1px; - border-color: #bbbbbb; - opacity: 0.4; + border-color: $menu-border-color; } .mx_RoomTagContextMenu_fieldSet .mx_RoomTagContextMenu_icon { diff --git a/src/skins/vector/css/vector-web/views/dialogs/ChangelogDialog.css b/src/skins/vector/css/vector-web/views/dialogs/_ChangelogDialog.scss similarity index 100% rename from src/skins/vector/css/vector-web/views/dialogs/ChangelogDialog.css rename to src/skins/vector/css/vector-web/views/dialogs/_ChangelogDialog.scss diff --git a/src/skins/vector/css/vector-web/views/directory/NetworkDropdown.css b/src/skins/vector/css/vector-web/views/directory/_NetworkDropdown.scss similarity index 87% rename from src/skins/vector/css/vector-web/views/directory/NetworkDropdown.css rename to src/skins/vector/css/vector-web/views/directory/_NetworkDropdown.scss index 8b4c445996..84aa896a9d 100644 --- a/src/skins/vector/css/vector-web/views/directory/NetworkDropdown.css +++ b/src/skins/vector/css/vector-web/views/directory/_NetworkDropdown.scss @@ -21,14 +21,14 @@ limitations under the License. .mx_NetworkDropdown_input { position: relative; border-radius: 3px; - border: 1px solid #c7c7c7; + border: 1px solid $strong-input-border-color; font-weight: 300; font-size: 13px; user-select: none; } .mx_NetworkDropdown_arrow { - border-color: #4a4a4a transparent transparent; + border-color: $primary-fg-color transparent transparent; border-style: solid; border-width: 5px 5px 0; display: block; @@ -67,12 +67,12 @@ input.mx_NetworkDropdown_networkoption, input.mx_NetworkDropdown_networkoption:f margin: 0; padding: 0px; border-radius: 3px; - border: 1px solid #76cfa6; - background-color: white; + border: 1px solid $accent-color; + background-color: $primary-bg-color; } .mx_NetworkDropdown_menu .mx_NetworkDropdown_networkoption:hover { - background-color: #ddd; + background-color: $focus-bg-color; } .mx_NetworkDropdown_menu_network { diff --git a/src/skins/vector/css/vector-web/views/elements/ImageView.css b/src/skins/vector/css/vector-web/views/elements/_ImageView.scss similarity index 78% rename from src/skins/vector/css/vector-web/views/elements/ImageView.css rename to src/skins/vector/css/vector-web/views/elements/_ImageView.scss index 03223f259e..8ed0698a72 100644 --- a/src/skins/vector/css/vector-web/views/elements/ImageView.css +++ b/src/skins/vector/css/vector-web/views/elements/_ImageView.scss @@ -19,39 +19,27 @@ limitations under the License. */ .mx_ImageView { - display: -webkit-flex; display: flex; width: 100%; height: 100%; - -webkit-align-items: center; align-items: center; } .mx_ImageView_lhs { - -webkit-box-ordinal-group: 1; order: 1; - -webkit-flex: 1; flex: 1 1 10%; min-width: 60px; - /* - background-color: #080; - height: 20px; - */ + // background-color: #080; + // height: 20px; } .mx_ImageView_content { - -webkit-box-ordinal-group: 2; order: 2; /* min-width hack needed for FF */ min-width: 0px; height: 90%; - -webkit-flex: 15; flex: 15 15 0; - - display: -webkit-flex; display: flex; - -webkit-align-items: center; - -webkit-justify-content: center; align-items: center; justify-content: center; } @@ -62,7 +50,7 @@ limitations under the License. max-height: 100%; /* object-fit hack needed for Chrome due to Chrome not re-laying-out until you refresh */ object-fit: contain; - /* background-image: url('img/trans.png'); */ + /* background-image: url('../../img/trans.png'); */ pointer-events: all; } @@ -78,16 +66,13 @@ limitations under the License. .mx_ImageView_label { text-align: left; display: flex; - display: -webkit-flex; justify-content: center; - -webkit-justify-content: center; flex-direction: column; - -webkit-flex-direction: column; padding-left: 30px; padding-right: 30px; min-height: 100%; max-width: 240px; - color: #fff; + color: $lightbox-fg-color; } .mx_ImageView_cancel { @@ -114,10 +99,10 @@ limitations under the License. margin-top: 24px; margin-bottom: 6px; border-radius: 5px; - background-color: #454545; + background-color: $lightbox-bg-color; font-size: 14px; padding: 9px; - border: 1px solid #fff; + border: 1px solid $lightbox-border-color; } .mx_ImageView_size { @@ -125,7 +110,7 @@ limitations under the License. } .mx_ImageView_link { - color: #fff ! important; + color: $lightbox-fg-color ! important; text-decoration: none ! important; } @@ -141,13 +126,9 @@ limitations under the License. } .mx_ImageView_rhs { - -webkit-box-ordinal-group: 3; order: 3; - -webkit-flex: 1; flex: 1 1 10%; min-width: 300px; - /* - background-color: #800; - height: 20px; - */ + // background-color: #800; + // height: 20px; } diff --git a/src/skins/vector/css/vector-web/views/elements/Spinner.css b/src/skins/vector/css/vector-web/views/elements/_Spinner.scss similarity index 86% rename from src/skins/vector/css/vector-web/views/elements/Spinner.css rename to src/skins/vector/css/vector-web/views/elements/_Spinner.scss index 3831cc4c1c..aea5737918 100644 --- a/src/skins/vector/css/vector-web/views/elements/Spinner.css +++ b/src/skins/vector/css/vector-web/views/elements/_Spinner.scss @@ -15,16 +15,12 @@ limitations under the License. */ .mx_Spinner { - display: -webkit-flex; display: flex; - -webkit-align-items: center; - -webkit-justify-content: center; align-items: center; justify-content: center; width: 100%; height: 100%; flex: 1; - -webkit-flex: 1; } .mx_MatrixChat_middlePanel .mx_Spinner { diff --git a/src/skins/vector/css/vector-web/views/globals/GuestWarningBar.css b/src/skins/vector/css/vector-web/views/globals/_GuestWarningBar.scss similarity index 79% rename from src/skins/vector/css/vector-web/views/globals/GuestWarningBar.css rename to src/skins/vector/css/vector-web/views/globals/_GuestWarningBar.scss index 717d75afe4..f5bdbaf9ca 100644 --- a/src/skins/vector/css/vector-web/views/globals/GuestWarningBar.css +++ b/src/skins/vector/css/vector-web/views/globals/_GuestWarningBar.scss @@ -15,15 +15,10 @@ limitations under the License. */ .mx_GuestWarningBar { - background-color: #76cfa6; - color: #fff; + background-color: $accent-color; + color: $accent-fg-color; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; - -webkit-align-items: center; align-items: center; } @@ -34,7 +29,7 @@ limitations under the License. } .mx_GuestWarningBar a { - color: #fff ! important; + color: $accent-fg-color ! important; text-decoration: underline ! important; cursor: pointer; } diff --git a/src/skins/vector/css/vector-web/views/globals/MatrixToolbar.css b/src/skins/vector/css/vector-web/views/globals/_MatrixToolbar.scss similarity index 82% rename from src/skins/vector/css/vector-web/views/globals/MatrixToolbar.css rename to src/skins/vector/css/vector-web/views/globals/_MatrixToolbar.scss index 4e214e113f..5a0b23aeb1 100644 --- a/src/skins/vector/css/vector-web/views/globals/MatrixToolbar.css +++ b/src/skins/vector/css/vector-web/views/globals/_MatrixToolbar.scss @@ -15,15 +15,10 @@ limitations under the License. */ .mx_MatrixToolbar { - background-color: #76cfa6; - color: #fff; + background-color: $accent-color; + color: $accent-fg-color; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; display: flex; - -webkit-align-items: center; align-items: center; } @@ -34,13 +29,12 @@ limitations under the License. } .mx_MatrixToolbar_content { - -webkit-flex: 1; flex: 1; } .mx_MatrixToolbar_link { - color: #fff ! important; + color: $accent-fg-color ! important; text-decoration: underline ! important; cursor: pointer; } diff --git a/src/skins/vector/css/vector-web/views/messages/MessageTimestamp.css b/src/skins/vector/css/vector-web/views/messages/_MessageTimestamp.scss similarity index 100% rename from src/skins/vector/css/vector-web/views/messages/MessageTimestamp.css rename to src/skins/vector/css/vector-web/views/messages/_MessageTimestamp.scss diff --git a/src/skins/vector/css/vector-web/views/messages/SenderProfile.css b/src/skins/vector/css/vector-web/views/messages/_SenderProfile.scss similarity index 100% rename from src/skins/vector/css/vector-web/views/messages/SenderProfile.css rename to src/skins/vector/css/vector-web/views/messages/_SenderProfile.scss diff --git a/src/skins/vector/css/vector-web/views/rooms/RoomDropTarget.css b/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss similarity index 89% rename from src/skins/vector/css/vector-web/views/rooms/RoomDropTarget.css rename to src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss index 003215aff2..e91658e8a8 100644 --- a/src/skins/vector/css/vector-web/views/rooms/RoomDropTarget.css +++ b/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss @@ -22,9 +22,9 @@ limitations under the License. margin-bottom: 7px; padding-top: 5px; padding-bottom: 5px; - border: 1px dashed #76cfa6; - color: #454545; - background-color: rgba(255,255,255,0.5); + border: 1px dashed $accent-color; + color: $primary-fg-color; + background-color: $droptarget-bg-color; border-radius: 4px; } @@ -39,7 +39,7 @@ limitations under the License. } .mx_RoomDropTarget_avatar { - background-color: #fff; + background-color: $primary-bg-color; border-radius: 24px; width: 24px; height: 24px; diff --git a/src/skins/vector/css/vector-web/views/rooms/RoomTooltip.css b/src/skins/vector/css/vector-web/views/rooms/_RoomTooltip.scss similarity index 82% rename from src/skins/vector/css/vector-web/views/rooms/RoomTooltip.css rename to src/skins/vector/css/vector-web/views/rooms/_RoomTooltip.scss index 192fa77b39..5469a9e6d3 100644 --- a/src/skins/vector/css/vector-web/views/rooms/RoomTooltip.css +++ b/src/skins/vector/css/vector-web/views/rooms/_RoomTooltip.scss @@ -21,16 +21,16 @@ limitations under the License. width: 0; height: 0; border-top: 8px solid transparent; - border-right: 8px solid rgba(187, 187, 187, 0.5); + border-right: 8px solid $menu-border-color; border-bottom: 8px solid transparent; } -.mx_RoomTooltip_chevron:after{ +.mx_RoomTooltip_chevron:after { content:''; width: 0; height: 0; border-top: 7px solid transparent; - border-right: 7px solid #fff; + border-right: 7px solid $primary-bg-color; border-bottom: 7px solid transparent; position:absolute; top: -7px; @@ -40,14 +40,14 @@ limitations under the License. .mx_RoomTooltip { display: none; position: fixed; - border: 1px solid rgba(187, 187, 187, 0.5); + border: 1px solid $menu-border-color; border-radius: 5px; - background-color: #fff; + background-color: $primary-bg-color; z-index: 2000; padding: 5px; pointer-events: none; line-height: 14px; font-size: 13px; - color: rgba(0, 0, 0, 0.7); + color: $primary-fg-color; } diff --git a/src/skins/vector/css/vector-web/views/rooms/SearchBar.css b/src/skins/vector/css/vector-web/views/rooms/_SearchBar.scss similarity index 85% rename from src/skins/vector/css/vector-web/views/rooms/SearchBar.css rename to src/skins/vector/css/vector-web/views/rooms/_SearchBar.scss index 7ec1a17ad5..079ea16c68 100644 --- a/src/skins/vector/css/vector-web/views/rooms/SearchBar.css +++ b/src/skins/vector/css/vector-web/views/rooms/_SearchBar.scss @@ -18,21 +18,18 @@ limitations under the License. padding-top: 5px; padding-bottom: 5px; display: flex; - display: -webkit-flex; align-items: center; - -webkit-align-items: center; } .mx_SearchBar_input { display: inline block; border-radius: 3px 0px 0px 3px; - border: 1px solid #f0f0f0; + border: 1px solid $input-border-color; font-size: 15px; padding: 9px; padding-left: 11px; width: auto; flex: 1 1 0; - -webkit-flex: 1 1 0; } .mx_SearchBar_searchButton { @@ -41,7 +38,7 @@ limitations under the License. width: 37px; height: 37px; border-radius: 0px 3px 3px 0px; - background-color: #76CFA6; + background-color: $accent-color; } @keyframes pulsate { @@ -61,8 +58,8 @@ limitations under the License. border-radius: 36px; font-weight: 400; font-size: 15px; - color: #fff; - background-color: #76cfa6; + color: $accent-fg-color; + background-color: $accent-color; width: auto; margin: auto; margin-left: 7px; @@ -74,9 +71,9 @@ limitations under the License. } .mx_SearchBar_unselected { - background-color: #fff; - color: #76CFA6; - border: #76CFA6 1px solid; + background-color: $primary-bg-color; + color: $accent-color; + border: $accent-color 1px solid; } .mx_SearchBar_cancel { diff --git a/src/skins/vector/css/vector-web/views/settings/Notifications.css b/src/skins/vector/css/vector-web/views/settings/_Notifications.scss similarity index 98% rename from src/skins/vector/css/vector-web/views/settings/Notifications.css rename to src/skins/vector/css/vector-web/views/settings/_Notifications.scss index 7a93f3f7b2..4c88e44952 100644 --- a/src/skins/vector/css/vector-web/views/settings/Notifications.css +++ b/src/skins/vector/css/vector-web/views/settings/_Notifications.scss @@ -58,7 +58,7 @@ limitations under the License. .mx_UserNotifSettings_keywords { cursor: pointer; - color: #76cfa6; + color: $accent-color; } .mx_UserSettings_devicesTable td { diff --git a/src/skins/vector/img/icon-call.svg b/src/skins/vector/img/icon-call.svg index 2d96b1456b..0ca5c29e9d 100644 --- a/src/skins/vector/img/icon-call.svg +++ b/src/skins/vector/img/icon-call.svg @@ -2,7 +2,7 @@ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="35" height="35" viewBox="0, 0, 35, 35"> <g id="Symbols"> - <path d="M17.5,35 C27.165,35 35,27.165 35,17.5 C35,7.835 27.165,0 17.5,0 C7.835,0 0,7.835 0,17.5 C0,27.165 7.835,35 17.5,35 z" fill="#EAF5F0" id="Oval-109"/> + <path d="M17.5,35 C27.165,35 35,27.165 35,17.5 C35,7.835 27.165,0 17.5,0 C7.835,0 0,7.835 0,17.5 C0,27.165 7.835,35 17.5,35 z" fill="#76CFA6" opacity="0.15" id="Oval-109"/> <path d="M23,28 C21.195,28 16.807,25.624 13.122,20.524 C9.675,15.755 8,12.309 8,9.99 C8,8.164 9.225,7.293 9.883,6.825 L10.045,6.708 C10.773,6.173 11.903,6 12.337,6 C13.097,6 13.417,6.458 13.611,6.857 C13.776,7.195 15.141,10.212 15.28,10.587 C15.492,11.164 15.422,12.005 14.766,12.488 L14.65,12.571 C14.324,12.804 13.718,13.236 13.634,13.761 C13.594,14.016 13.677,14.283 13.889,14.577 C14.946,16.043 18.32,20.346 18.928,20.931 C19.405,21.389 20.009,21.455 20.42,21.098 C20.846,20.729 21.035,20.511 21.037,20.508 L21.081,20.465 C21.116,20.434 21.449,20.162 21.992,20.162 C22.385,20.162 22.783,20.302 23.178,20.576 C24.201,21.287 26.51,22.876 26.51,22.876 L26.547,22.906 C26.842,23.166 27.269,23.917 26.772,24.893 C26.256,25.907 24.655,28 23,28 L23,28 z" fill-opacity="0" stroke="#76CFA6" stroke-width="1" id="path-1"/> </g> </svg> diff --git a/src/skins/vector/img/icon_context_message_dark.svg b/src/skins/vector/img/icon_context_message_dark.svg new file mode 100644 index 0000000000..b4336cc377 --- /dev/null +++ b/src/skins/vector/img/icon_context_message_dark.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg width="19px" height="19px" viewBox="0 0 19 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <!-- Generator: sketchtool 39.1 (31720) - http://www.bohemiancoding.com/sketch --> + <title>ED5D3E59-2561-4AC1-9B43-82FBC51767FC</title> + <desc>Created with sketchtool.</desc> + <defs></defs> + <g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g id="icon_context"> + <g> + <path d="M9.5,19 C14.7467051,19 19,14.7467051 19,9.5 C19,4.25329488 14.7467051,0 9.5,0 C4.25329488,0 0,4.25329488 0,9.5 C0,14.7467051 4.25329488,19 9.5,19 Z" id="Oval-69" fill="#000" opacity="0.2"></path> + <path d="M4.5,9.50063771 C4.5,9.13148623 4.59887838,8.85242947 4.7966381,8.66345907 C4.99439782,8.47448867 5.28224377,8.38000488 5.66018457,8.38000488 C6.0249414,8.38000488 6.3072941,8.47668596 6.50725115,8.67005103 C6.70720821,8.86341609 6.80718523,9.14027555 6.80718523,9.50063771 C6.80718523,9.84781589 6.70610956,10.1213794 6.50395517,10.3213365 C6.30180079,10.5212935 6.02054674,10.6212705 5.66018457,10.6212705 C5.29103309,10.6212705 5.00538444,10.5234908 4.80323006,10.3279284 C4.60107568,10.132366 4.5,9.85660521 4.5,9.50063771 L4.5,9.50063771 Z M8.3431114,9.50063771 C8.3431114,9.13148623 8.44198978,8.85242947 8.63974951,8.66345907 C8.83750923,8.47448867 9.12755247,8.38000488 9.50988794,8.38000488 C9.87464476,8.38000488 10.1569975,8.47668596 10.3569545,8.67005103 C10.5569116,8.86341609 10.6568886,9.14027555 10.6568886,9.50063771 C10.6568886,9.84781589 10.5558129,10.1213794 10.3536585,10.3213365 C10.1515042,10.5212935 9.8702501,10.6212705 9.50988794,10.6212705 C9.13634179,10.6212705 8.84849585,10.5234908 8.64634146,10.3279284 C8.44418708,10.132366 8.3431114,9.85660521 8.3431114,9.50063771 L8.3431114,9.50063771 Z M12.1928148,9.50063771 C12.1928148,9.13148623 12.2916931,8.85242947 12.4894529,8.66345907 C12.6872126,8.47448867 12.9750585,8.38000488 13.3529993,8.38000488 C13.7177562,8.38000488 14.0001089,8.47668596 14.2000659,8.67005103 C14.400023,8.86341609 14.5,9.14027555 14.5,9.50063771 C14.5,9.84781589 14.3989243,10.1213794 14.1967699,10.3213365 C13.9946156,10.5212935 13.7133615,10.6212705 13.3529993,10.6212705 C12.9838479,10.6212705 12.6981992,10.5234908 12.4960448,10.3279284 C12.2938904,10.132366 12.1928148,9.85660521 12.1928148,9.50063771 L12.1928148,9.50063771 Z" id="…" fill="#FFF" opacity="0.6"></path> + </g> + </g> + </g> +</svg> diff --git a/src/skins/vector/img/icons-close-button.svg b/src/skins/vector/img/icons-close-button.svg index f17940f58c..f960d73a3c 100644 --- a/src/skins/vector/img/icons-close-button.svg +++ b/src/skins/vector/img/icons-close-button.svg @@ -7,7 +7,7 @@ <g id="1:1-chat" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Chat-People-2-Invite-modal-(similar-to-chat-group-5)" transform="translate(-909.000000, -263.000000)"> <g id="icons_close" transform="translate(909.000000, 263.000000)"> - <path d="M17.5,35 C27.1649831,35 35,27.1649831 35,17.5 C35,7.83501688 27.1649831,0 17.5,0 C7.83501688,0 0,7.83501688 0,17.5 C0,27.1649831 7.83501688,35 17.5,35 Z" id="Oval-1-Copy-7" fill="#EAF5F0"></path> + <path d="M17.5,35 C27.1649831,35 35,27.1649831 35,17.5 C35,7.83501688 27.1649831,0 17.5,0 C7.83501688,0 0,7.83501688 0,17.5 C0,27.1649831 7.83501688,35 17.5,35 Z" id="Oval-1-Copy-7" fill="#76CFA6" opacity="0.15"></path> <polyline id="icon_close" fill="#76CFA6" opacity="0.9" transform="translate(17.468897, 17.470577) rotate(-315.000000) translate(-17.468897, -17.470577) " points="18.2115394 5.97057742 16.674774 5.97057742 16.674774 16.7275762 5.9688975 16.7275762 5.9688975 18.2642903 16.674774 18.2642903 16.674774 28.9705774 18.2115394 28.9705774 18.2115394 18.2642903 28.9688975 18.2642903 28.9688975 16.7275762 18.2115394 16.7275762 18.2115394 5.97057742"></polyline> </g> </g> diff --git a/src/skins/vector/img/icons-close.svg b/src/skins/vector/img/icons-close.svg index 6feb660aff..453b51082f 100644 --- a/src/skins/vector/img/icons-close.svg +++ b/src/skins/vector/img/icons-close.svg @@ -3,7 +3,7 @@ <svg version="1.1" id="Layer_1" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-11 13 24 24" xml:space="preserve"> <style type="text/css"> - .st1{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linecap:round;} + .st1{fill:none;stroke-width:2;stroke-linecap:round;} </style> <title>icons_create_room</title> <desc>Created with sketchtool.</desc> @@ -13,8 +13,8 @@ <g id="Room-list_x2F_Footer" transform="translate(0.000000, 708.000000)" sketch:type="MSShapeGroup"> <g id="icons_create_room" transform="translate(20.000000, 18.000000)"> <circle id="Oval-1-Copy-7" fill="#76CFA6" cx="1" cy="25" r="12"/> - <path id="Line" class="st1" d="M-2.5,28.5l7.1-7.1"/> - <path id="Line_1_" class="st1" d="M-2.5,21.5l7.1,7.1"/> + <path id="Line" class="st1" stroke="#FFFFFF" d="M-2.5,28.5l7.1-7.1"/> + <path id="Line_1_" class="st1" stroke="#FFFFFF" d="M-2.5,21.5l7.1,7.1"/> </g> </g> </g> diff --git a/src/skins/vector/img/icons-search.svg b/src/skins/vector/img/icons-search.svg index 4f5002ab79..d85709e66c 100644 --- a/src/skins/vector/img/icons-search.svg +++ b/src/skins/vector/img/icons-search.svg @@ -2,7 +2,7 @@ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="35" height="35" viewBox="0, 0, 35, 35"> <g id="Symbols"> - <path d="M17.5,35 C27.165,35 35,27.165 35,17.5 C35,7.835 27.165,0 17.5,0 C7.835,0 0,7.835 0,17.5 C0,27.165 7.835,35 17.5,35 z" fill="#EAF5F0" id="Oval-1-Copy-7"/> + <path d="M17.5,35 C27.165,35 35,27.165 35,17.5 C35,7.835 27.165,0 17.5,0 C7.835,0 0,7.835 0,17.5 C0,27.165 7.835,35 17.5,35 z" fill="#76CFA6" opacity="0.15" id="Oval-1-Copy-7"/> <path d="M22.4,15.4 C22.4,19.266 19.266,22.4 15.4,22.4 C11.534,22.4 8.4,19.266 8.4,15.4 C8.4,11.534 11.534,8.4 15.4,8.4 C19.266,8.4 22.4,11.534 22.4,15.4 z" fill-opacity="0" stroke="#76CFA6" stroke-width="1" stroke-linecap="round" id="path-1" opacity="0.7"/> <path d="M20.3,20.3 L25.25,25.25" fill-opacity="0" stroke="#76CFA6" stroke-width="1" stroke-linecap="round" id="Line" opacity="0.7"/> </g> diff --git a/src/skins/vector/img/icons-upload.svg b/src/skins/vector/img/icons-upload.svg index 9074fcf9fa..b0101e87a0 100644 --- a/src/skins/vector/img/icons-upload.svg +++ b/src/skins/vector/img/icons-upload.svg @@ -2,7 +2,7 @@ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="35" height="35" viewBox="0, 0, 35, 35"> <g id="Symbols"> - <path d="M17.5,35 C27.165,35 35,27.165 35,17.5 C35,7.835 27.165,0 17.5,0 C7.835,0 0,7.835 0,17.5 C0,27.165 7.835,35 17.5,35 z" fill="#EAF5F0" id="Oval-109-Copy"/> + <path d="M17.5,35 C27.165,35 35,27.165 35,17.5 C35,7.835 27.165,0 17.5,0 C7.835,0 0,7.835 0,17.5 C0,27.165 7.835,35 17.5,35 z" fill="#76CFA6" opacity="0.15" id="Oval-109-Copy"/> <g id="file"> <path d="M10,10.01 C10,7.795 11.782,6 14.004,6 L18.402,6 C18.402,6 25,12.492 25,12.492 L25,24.006 C25,26.212 23.206,28 21,28 L14,28 C11.791,28 10,26.2 10,23.99 L10,10.01 z" fill-opacity="0" stroke="#76CFA6" stroke-width="1" id="path-1"/> <path d="M25,13 L20.157,13 C18.966,13 18,12.034 18,10.843 L18,6" fill-opacity="0" stroke="#76CFA6" stroke-width="1" id="path-3"/> diff --git a/src/skins/vector/img/icons-video.svg b/src/skins/vector/img/icons-video.svg index a35df49bb1..d367f49609 100644 --- a/src/skins/vector/img/icons-video.svg +++ b/src/skins/vector/img/icons-video.svg @@ -7,7 +7,7 @@ <g id="Extra-icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Extra-icons-sheet" transform="translate(-542.000000, -366.000000)"> <g id="icons_video" transform="translate(542.000000, 366.000000)"> - <path d="M17.5,35 C27.1649831,35 35,27.1649831 35,17.5 C35,7.83501688 27.1649831,0 17.5,0 C7.83501688,0 0,7.83501688 0,17.5 C0,27.1649831 7.83501688,35 17.5,35 Z" id="Oval-109-Copy-2" fill="#EAF5F0"></path> + <path d="M17.5,35 C27.1649831,35 35,27.1649831 35,17.5 C35,7.83501688 27.1649831,0 17.5,0 C7.83501688,0 0,7.83501688 0,17.5 C0,27.1649831 7.83501688,35 17.5,35 Z" id="Oval-109-Copy-2" fill="#76CFA6" opacity="0.15"></path> <g transform="translate(9.000000, 11.500000)" id="Rectangle-20-+-Path-16" stroke="#76CFA6"> <g transform="scale(1.0, 0.8)"> <rect id="Rectangle-20" x="0" y="0" width="13" height="17" rx="4"></rect> diff --git a/src/skins/vector/img/logos/riot-logo-1.svg b/src/skins/vector/img/logos/riot-logo-1.svg new file mode 100644 index 0000000000..6b79dd9e8a --- /dev/null +++ b/src/skins/vector/img/logos/riot-logo-1.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 174.99 143.93"><defs><style>.cls-1{fill:#764d80;}.cls-2{fill:#7dc8a2;}.cls-3{fill:#afdbc5;}</style></defs><title>Asset 4</title><g id="Layer_2" data-name="Layer 2"><g id="Design"><path class="cls-1" d="M146.53,51.12h25.61a2.57,2.57,0,0,0,0-5.14H146.53a2.57,2.57,0,0,0,0,5.14Z"/><path class="cls-1" d="M146.53,5.14h7.66v7.79l-.05,0-9,6.32a2.57,2.57,0,0,0,2.95,4.21l7.23-5.06a10.24,10.24,0,0,0,19.42-4.59V2.64s0,0,0-.07A2.57,2.57,0,0,0,172.14,0H146.53a2.57,2.57,0,0,0,0,5.14Zm23,8.71a5.12,5.12,0,1,1-10.23,0V5.14h10.23Z"/><path class="cls-1" d="M172.14,118.28a2.57,2.57,0,0,0-2.57,2.57v7.6h-23A2.57,2.57,0,0,0,144,131h0a2.57,2.57,0,0,0,2.57,2.57h23v7.78a2.57,2.57,0,0,0,5.14,0V131h0V120.85A2.57,2.57,0,0,0,172.14,118.28Z"/><path class="cls-1" d="M159.34,72.63A15.65,15.65,0,1,0,175,88.28,15.67,15.67,0,0,0,159.34,72.63Zm0,26.16a10.51,10.51,0,1,1,10.51-10.51A10.52,10.52,0,0,1,159.34,98.79Z"/><path class="cls-2" d="M62.33,0H21.22A20.56,20.56,0,0,0,.66,20.57v102.8a20.56,20.56,0,0,0,41.12,0V102.79H62.33A51.38,51.38,0,0,0,62.33,0Z"/><path class="cls-3" d="M21.22,138.81A15.45,15.45,0,0,1,5.79,123.37V20.57A15.45,15.45,0,0,1,21.09,5.14H62.33a46.26,46.26,0,0,1,0,92.51H36.65v25.71A15.45,15.45,0,0,1,21.22,138.81Z"/><path class="cls-2" d="M21.22,133.68a10.32,10.32,0,0,1-10.3-10.3V20.57A10.33,10.33,0,0,1,21,10.27H62.33a41.13,41.13,0,0,1,0,82.26H31.52v30.84A10.32,10.32,0,0,1,21.22,133.68Z"/><path class="cls-3" d="M21.22,128.55A5.18,5.18,0,0,1,16,123.37V20.57a5.2,5.2,0,0,1,5-5.17H62.33a36,36,0,0,1,0,72H26.39v36A5.18,5.18,0,0,1,21.22,128.55Z"/><path class="cls-2" d="M21.27,82.28H62.33a30.87,30.87,0,0,0,0-61.75H21.22Z"/><path class="cls-3" d="M26.39,77.15l0-51.49h36a25.75,25.75,0,0,1,0,51.49Z"/><path class="cls-2" d="M31.51,72l0-41.23H62.33a20.62,20.62,0,0,1,0,41.23Z"/><path class="cls-3" d="M36.64,66.9l0-31H62.33a15.49,15.49,0,0,1,0,31Z"/><path class="cls-2" d="M41.76,61.77l0-20.72H62.33a10.36,10.36,0,0,1,0,20.72Z"/><path class="cls-3" d="M46.89,56.64V46.18H62.33a5.23,5.23,0,0,1,0,10.47Z"/><circle class="cls-1" cx="20.56" cy="20.57" r="20.56" transform="translate(-8.08 15.51) rotate(-35)"/><path class="cls-1" d="M109.34,111.57a20.56,20.56,0,1,1-33.69,23.59l-30.79-44A20.56,20.56,0,0,1,78.55,67.58Z"/></g></g></svg> \ No newline at end of file diff --git a/src/skins/vector/img/logos/riot-logo-2.svg b/src/skins/vector/img/logos/riot-logo-2.svg new file mode 100644 index 0000000000..96e0bbb189 --- /dev/null +++ b/src/skins/vector/img/logos/riot-logo-2.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 174.36 143.93"><defs><style>.cls-1{fill:#764d80;}.cls-2{fill:#f69e98;}</style></defs><title>Asset 2</title><g id="Layer_2" data-name="Layer 2"><g id="Design"><path class="cls-1" d="M61.67,0H20.56A20.56,20.56,0,0,0,0,20.57v102.8a20.56,20.56,0,0,0,41.12,0V102.79H61.67A51.38,51.38,0,0,0,61.67,0Z"/><path class="cls-2" d="M20.56,139.54A16.19,16.19,0,0,1,4.39,123.37V20.57a16.21,16.21,0,0,1,16-16.17H61.67a47,47,0,0,1,0,94H36.73v25A16.19,16.19,0,0,1,20.56,139.54ZM20.39,5.9A14.7,14.7,0,0,0,5.89,20.57v102.8a14.67,14.67,0,0,0,29.34,0V96.9H61.67a45.49,45.49,0,0,0,0-91H20.39Z"/><path class="cls-2" d="M20.56,134.4a11,11,0,0,1-11-11V20.57a11.09,11.09,0,0,1,10.79-11H61.67a41.85,41.85,0,0,1,0,83.7H31.59v30.11A11,11,0,0,1,20.56,134.4ZM20.3,11A9.57,9.57,0,0,0,11,20.57v102.8a9.53,9.53,0,1,0,19.05,0V91.75H61.67a40.35,40.35,0,0,0,0-80.7H20.3Z"/><path class="cls-2" d="M20.56,129.25a5.89,5.89,0,0,1-5.88-5.88V20.57a5.94,5.94,0,0,1,5.61-5.88H61.67a36.71,36.71,0,0,1,0,73.42H26.44v35.25A5.89,5.89,0,0,1,20.56,129.25ZM20.31,16.19a4.42,4.42,0,0,0-4.13,4.38v102.8a4.38,4.38,0,0,0,8.77,0V86.61H61.67a35.21,35.21,0,0,0,0-70.42Z"/><path class="cls-2" d="M61.67,83H19.81V19.83H61.67a31.57,31.57,0,0,1,0,63.14Zm-40.36-1.5H61.67a30.07,30.07,0,0,0,0-60.14H21.32Z"/><path class="cls-2" d="M61.67,77.83H25V25H61.67a26.43,26.43,0,0,1,0,52.85Zm-35.22-1.5H61.67a24.93,24.93,0,0,0,0-49.85H26.46Z"/><path class="cls-2" d="M61.67,72.69H30.1V30.12H61.67a21.29,21.29,0,0,1,0,42.57ZM31.6,71.19H61.67a19.79,19.79,0,0,0,0-39.57H31.6Z"/><path class="cls-2" d="M61.67,67.55H35.24V35.26H61.67a16.14,16.14,0,0,1,0,32.29ZM36.74,66H61.67a14.64,14.64,0,0,0,0-29.29H36.74Z"/><path class="cls-2" d="M61.67,62.41H40.38v-22H61.67a11,11,0,0,1,0,22Zm-19.79-1.5H61.67a9.5,9.5,0,0,0,0-19H41.88Z"/><path class="cls-2" d="M61.67,57.26H45.52V45.54H61.67a5.86,5.86,0,0,1,0,11.72ZM47,55.76H61.67a4.36,4.36,0,0,0,0-8.72H47Z"/><path class="cls-2" d="M61.18,52.16H51.89a.75.75,0,1,1,0-1.5h9.29a.75.75,0,0,1,0,1.5Z"/><path class="cls-2" d="M20.56,124.12a.75.75,0,0,1-.75-.75v-36a.75.75,0,0,1,1.5,0v36A.75.75,0,0,1,20.56,124.12Z"/><circle class="cls-2" cx="20.59" cy="20.57" r="20.56" transform="translate(-8.07 15.53) rotate(-35)"/><path class="cls-2" d="M109.36,111.56a20.56,20.56,0,1,1-33.69,23.59l-30.79-44A20.56,20.56,0,0,1,78.58,67.57Z"/><path class="cls-2" d="M145.91,51.12h25.61a2.57,2.57,0,0,0,0-5.14H145.91a2.57,2.57,0,1,0,0,5.14Z"/><path class="cls-2" d="M145.91,5.14h7.66v7.79l-.05,0-9,6.32a2.57,2.57,0,0,0,2.95,4.21l7.23-5.06a10.24,10.24,0,0,0,19.42-4.59V2.64s0,0,0-.07A2.57,2.57,0,0,0,171.51,0H145.91a2.57,2.57,0,1,0,0,5.14Zm23,8.71a5.12,5.12,0,1,1-10.23,0V5.14h10.23Z"/><path class="cls-2" d="M171.51,118.28a2.57,2.57,0,0,0-2.57,2.57v7.6h-23a2.57,2.57,0,0,0-2.57,2.57h0a2.57,2.57,0,0,0,2.57,2.57h23v7.78a2.57,2.57,0,0,0,5.14,0V131h0V120.85A2.57,2.57,0,0,0,171.51,118.28Z"/><path class="cls-2" d="M158.71,72.63a15.65,15.65,0,1,0,15.65,15.65A15.67,15.67,0,0,0,158.71,72.63Zm0,26.16a10.51,10.51,0,1,1,10.51-10.51A10.52,10.52,0,0,1,158.71,98.79Z"/></g></g></svg> \ No newline at end of file diff --git a/src/skins/vector/img/logos/riot-logo-3.svg b/src/skins/vector/img/logos/riot-logo-3.svg new file mode 100644 index 0000000000..985b9c9f72 --- /dev/null +++ b/src/skins/vector/img/logos/riot-logo-3.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 174.99 143.93"><defs><style>.cls-1{fill:#fac79e;}.cls-2{fill:#e45e5d;}.cls-3{fill:#f8a05f;}</style></defs><title>Asset 5</title><g id="Layer_2" data-name="Layer 2"><g id="Design"><path class="cls-1" d="M146.53,51.12h25.61a2.57,2.57,0,0,0,0-5.14H146.53a2.57,2.57,0,0,0,0,5.14Z"/><path class="cls-1" d="M146.53,5.14h7.66v7.79l-.05,0-9,6.32a2.57,2.57,0,0,0,2.95,4.21l7.23-5.06a10.24,10.24,0,0,0,19.42-4.59V2.64s0,0,0-.07A2.57,2.57,0,0,0,172.14,0H146.53a2.57,2.57,0,0,0,0,5.14Zm23,8.71a5.12,5.12,0,1,1-10.23,0V5.14h10.23Z"/><path class="cls-1" d="M172.14,118.28a2.57,2.57,0,0,0-2.57,2.57v7.6h-23A2.57,2.57,0,0,0,144,131h0a2.57,2.57,0,0,0,2.57,2.57h23v7.78a2.57,2.57,0,0,0,5.14,0V131h0V120.85A2.57,2.57,0,0,0,172.14,118.28Z"/><path class="cls-1" d="M159.34,72.63A15.65,15.65,0,1,0,175,88.28,15.67,15.67,0,0,0,159.34,72.63Zm0,26.16a10.51,10.51,0,1,1,10.51-10.51A10.52,10.52,0,0,1,159.34,98.79Z"/><path class="cls-2" d="M61.67,0H20.56A20.56,20.56,0,0,0,0,20.57v102.8a20.56,20.56,0,0,0,41.12,0V102.79H61.67A51.38,51.38,0,0,0,61.67,0Z"/><polygon class="cls-3" points="47.03 0.01 40.32 0.01 0 48.06 0 56.05 47.03 0.01"/><polygon class="cls-3" points="60.45 0.01 53.74 0.01 0 64.05 0 72.04 60.45 0.01"/><path class="cls-3" d="M72.83,1.24a51,51,0,0,0-5.9-1L0,80v8Z"/><polygon class="cls-3" points="33.61 0.01 26.9 0.01 0 32.06 0 40.06 33.61 0.01"/><path class="cls-3" d="M83.27,4.78a51,51,0,0,0-5-2L0,96v8Z"/><path class="cls-3" d="M41.12,102.78h.18l64.78-77.2a51.55,51.55,0,0,0-2.94-4.49L5.55,137.38a20.62,20.62,0,0,0,3.95,3.29L41.12,103Z"/><path class="cls-3" d="M112.22,42.23l-50.8,60.54h.25a51.55,51.55,0,0,0,6.85-.47L113,49.3A51.32,51.32,0,0,0,112.22,42.23Z"/><path class="cls-3" d="M40.71,127.46l-12.59,15A20.58,20.58,0,0,0,40.71,127.46Z"/><path class="cls-3" d="M110,68.88a51,51,0,0,0,2.67-11.18L76.73,100.52a51.1,51.1,0,0,0,10.6-4.64Z"/><path class="cls-3" d="M92.22,10.1a51.58,51.58,0,0,0-4.3-2.87L0,112v8Z"/><path class="cls-3" d="M99.83,17q-1.73-1.92-3.64-3.66L.42,127.5a20.41,20.41,0,0,0,2,5.58Z"/><path class="cls-3" d="M41.12,119v-8l-26.82,32a20.53,20.53,0,0,0,5.9,1Z"/><path class="cls-3" d="M110.71,36a51,51,0,0,0-2.09-5.5L48,102.78h6.71Z"/><circle class="cls-1" cx="20.59" cy="20.57" r="20.56" transform="translate(-8.07 15.53) rotate(-35)"/><path class="cls-1" d="M109.36,111.56a20.56,20.56,0,1,1-33.69,23.59l-30.79-44A20.56,20.56,0,0,1,78.58,67.57Z"/></g></g></svg> \ No newline at end of file diff --git a/src/skins/vector/img/logos/riot-logo-4.svg b/src/skins/vector/img/logos/riot-logo-4.svg new file mode 100644 index 0000000000..24a7ddabe6 --- /dev/null +++ b/src/skins/vector/img/logos/riot-logo-4.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 175.64 143.93"><defs><style>.cls-1{fill:#e45e5d;}.cls-2{fill:#c7bdcd;}.cls-3{fill:#f69e98;}</style></defs><title>Asset 3</title><g id="Layer_2" data-name="Layer 2"><g id="Design"><path class="cls-1" d="M61.67,0H20.56A20.56,20.56,0,0,0,0,20.57v102.8a20.56,20.56,0,0,0,41.12,0V102.79H61.67A51.38,51.38,0,0,0,61.67,0Z"/><path class="cls-2" d="M147.19,51.12h25.61a2.57,2.57,0,1,0,0-5.14H147.19a2.57,2.57,0,0,0,0,5.14Z"/><path class="cls-2" d="M147.19,5.14h7.66v7.79l-.05,0-9,6.32a2.57,2.57,0,0,0,2.95,4.21l7.23-5.06a10.24,10.24,0,0,0,19.42-4.59V2.64s0,0,0-.07A2.57,2.57,0,0,0,172.79,0H147.19a2.57,2.57,0,0,0,0,5.14Zm23,8.71a5.12,5.12,0,1,1-10.23,0V5.14h10.23Z"/><path class="cls-2" d="M172.79,118.28a2.57,2.57,0,0,0-2.57,2.57v7.6h-23a2.57,2.57,0,0,0-2.57,2.57h0a2.57,2.57,0,0,0,2.57,2.57h23v7.78a2.57,2.57,0,0,0,5.14,0V131h0V120.85A2.57,2.57,0,0,0,172.79,118.28Z"/><path class="cls-2" d="M160,72.63a15.65,15.65,0,1,0,15.65,15.65A15.67,15.67,0,0,0,160,72.63Zm0,26.16A10.51,10.51,0,1,1,170.5,88.28,10.52,10.52,0,0,1,160,98.79Z"/><path class="cls-3" d="M2.77,133.64A20.62,20.62,0,0,0,7,138.77H34.14a20.62,20.62,0,0,0,4.21-5.13Z"/><path class="cls-3" d="M0,92.52v5.14H84a51.48,51.48,0,0,0,8.41-5.14Z"/><rect class="cls-3" y="102.8" width="41.12" height="5.13"/><rect class="cls-3" y="113.08" width="41.12" height="5.14"/><path class="cls-3" d="M.68,15.41H98.3a51.8,51.8,0,0,0-5.86-5.14H2.78A20.41,20.41,0,0,0,.68,15.41Z"/><path class="cls-3" d="M0,123.36H0a20.53,20.53,0,0,0,.67,5.12H40.45a20.53,20.53,0,0,0,.67-5.12H0Z"/><path class="cls-3" d="M0,56.53H112.8c.17-1.69.26-3.4.26-5.13H0Z"/><path class="cls-3" d="M0,82.24v5.14H98.32a51.79,51.79,0,0,0,4.43-5.14Z"/><path class="cls-3" d="M0,20.57V25.7H106.14a51.58,51.58,0,0,0-3.39-5.14Z"/><path class="cls-3" d="M20.81,0h-.25A20.46,20.46,0,0,0,7,5.14H84A51.07,51.07,0,0,0,61.67,0Z"/><path class="cls-3" d="M0,30.85V36H110.69a51,51,0,0,0-1.94-5.14Z"/><path class="cls-3" d="M0,72v5.13H106.14A51.24,51.24,0,0,0,108.75,72Z"/><path class="cls-3" d="M0,61.68v5.14H110.69A50.92,50.92,0,0,0,112,61.68Z"/><path class="cls-3" d="M0,41.22v5.14H112.8a51.15,51.15,0,0,0-.77-5.14Z"/><circle class="cls-2" cx="20.59" cy="20.57" r="20.56" transform="translate(-8.07 15.53) rotate(-35)"/><path class="cls-2" d="M109.36,111.56a20.56,20.56,0,0,1-33.69,23.59l-30.79-44A20.56,20.56,0,0,1,78.58,67.57Z"/></g></g></svg> \ No newline at end of file diff --git a/src/skins/vector/img/logos/riot-logo-5.svg b/src/skins/vector/img/logos/riot-logo-5.svg new file mode 100644 index 0000000000..6a2c61dfec --- /dev/null +++ b/src/skins/vector/img/logos/riot-logo-5.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 174.99 143.93"><defs><style>.cls-1{fill:#764d80;}.cls-2{fill:#afdbc5;}</style></defs><title>Asset 1</title><g id="Layer_2" data-name="Layer 2"><g id="Design"><path class="cls-1" d="M61.67,0H20.56A20.56,20.56,0,0,0,0,20.57v102.8a20.56,20.56,0,0,0,41.12,0V102.79H61.67A51.38,51.38,0,0,0,61.67,0Z"/><circle class="cls-2" cx="20.59" cy="20.57" r="20.56" transform="matrix(0.82, -0.57, 0.57, 0.82, -8.07, 15.53)"/><path class="cls-2" d="M109.36,111.56a20.56,20.56,0,1,1-33.69,23.59l-30.79-44A20.56,20.56,0,0,1,78.58,67.57Z"/><path class="cls-2" d="M146.53,51.12h25.61a2.57,2.57,0,0,0,0-5.14H146.53a2.57,2.57,0,0,0,0,5.14Z"/><path class="cls-2" d="M146.53,5.14h7.66v7.79l-.05,0-9,6.32a2.57,2.57,0,1,0,2.95,4.21l7.23-5.06a10.24,10.24,0,0,0,19.42-4.59V2.64s0,0,0-.07A2.57,2.57,0,0,0,172.14,0H146.53a2.57,2.57,0,0,0,0,5.14Zm23,8.71a5.12,5.12,0,1,1-10.23,0V5.14h10.23Z"/><path class="cls-2" d="M172.14,118.28a2.57,2.57,0,0,0-2.57,2.57v7.6h-23A2.57,2.57,0,0,0,144,131h0a2.57,2.57,0,0,0,2.57,2.57h23v7.78a2.57,2.57,0,0,0,5.14,0V131h0V120.85A2.57,2.57,0,0,0,172.14,118.28Z"/><path class="cls-2" d="M159.34,72.63A15.65,15.65,0,1,0,175,88.28,15.67,15.67,0,0,0,159.34,72.63Zm0,26.16a10.51,10.51,0,1,1,10.51-10.51A10.52,10.52,0,0,1,159.34,98.79Z"/></g></g></svg> \ No newline at end of file diff --git a/src/skins/vector/img/logos/riot-logo-bw.svg b/src/skins/vector/img/logos/riot-logo-bw.svg new file mode 100644 index 0000000000..cb6d77d63b --- /dev/null +++ b/src/skins/vector/img/logos/riot-logo-bw.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 174.99 143.93"><defs><style>.cls-1{fill:#fff;}</style></defs><title>Asset 6</title><g id="Layer_2" data-name="Layer 2"><g id="Design"><path d="M146.53,51.12h25.61a2.57,2.57,0,0,0,0-5.14H146.53a2.57,2.57,0,0,0,0,5.14Z"/><path d="M146.53,5.14h7.66v7.79l-.05,0-9,6.32a2.57,2.57,0,0,0,2.95,4.21l7.23-5.06a10.24,10.24,0,0,0,19.42-4.59V2.64s0,0,0-.07A2.57,2.57,0,0,0,172.14,0H146.53a2.57,2.57,0,0,0,0,5.14Zm23,8.71a5.12,5.12,0,1,1-10.23,0V5.14h10.23Z"/><path d="M172.14,118.28a2.57,2.57,0,0,0-2.57,2.57v7.6h-23A2.57,2.57,0,0,0,144,131h0a2.57,2.57,0,0,0,2.57,2.57h23v7.78a2.57,2.57,0,0,0,5.14,0V131h0V120.85A2.57,2.57,0,0,0,172.14,118.28Z"/><path d="M159.34,72.63A15.65,15.65,0,1,0,175,88.28,15.67,15.67,0,0,0,159.34,72.63Zm0,26.16a10.51,10.51,0,1,1,10.51-10.51A10.52,10.52,0,0,1,159.34,98.79Z"/><path d="M62.33,0H21.22A20.56,20.56,0,0,0,.66,20.57v102.8a20.56,20.56,0,0,0,41.12,0V102.79H62.33A51.38,51.38,0,0,0,62.33,0Z"/><path class="cls-1" d="M21.22,138.81A15.45,15.45,0,0,1,5.79,123.37V20.57A15.45,15.45,0,0,1,21.09,5.14H62.33a46.26,46.26,0,0,1,0,92.51H36.65v25.71A15.45,15.45,0,0,1,21.22,138.81Z"/><path d="M21.22,133.68a10.32,10.32,0,0,1-10.3-10.3V20.57A10.33,10.33,0,0,1,21,10.27H62.33a41.13,41.13,0,0,1,0,82.26H31.52v30.84A10.32,10.32,0,0,1,21.22,133.68Z"/><path class="cls-1" d="M21.22,128.55A5.18,5.18,0,0,1,16,123.37V20.57a5.2,5.2,0,0,1,5-5.17H62.33a36,36,0,0,1,0,72H26.39v36A5.18,5.18,0,0,1,21.22,128.55Z"/><path d="M21.27,82.28H62.33a30.87,30.87,0,0,0,0-61.75H21.22Z"/><path class="cls-1" d="M26.39,77.15l0-51.49h36a25.75,25.75,0,0,1,0,51.49Z"/><path d="M31.51,72l0-41.23H62.33a20.62,20.62,0,0,1,0,41.23Z"/><path class="cls-1" d="M36.64,66.9l0-31H62.33a15.49,15.49,0,0,1,0,31Z"/><path d="M41.76,61.77l0-20.72H62.33a10.36,10.36,0,0,1,0,20.72Z"/><path class="cls-1" d="M46.89,56.64V46.18H62.33a5.23,5.23,0,0,1,0,10.47Z"/><circle cx="20.56" cy="20.57" r="20.56" transform="translate(-8.08 15.51) rotate(-35)"/><path d="M109.34,111.57a20.56,20.56,0,1,1-33.69,23.59l-30.79-44A20.56,20.56,0,0,1,78.55,67.58Z"/></g></g></svg> \ No newline at end of file diff --git a/src/skins/vector/img/logos/riot-logo.svg b/src/skins/vector/img/logos/riot-logo.svg new file mode 100644 index 0000000000..cbfaa62577 --- /dev/null +++ b/src/skins/vector/img/logos/riot-logo.svg @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 400 400" style="enable-background:new 0 0 400 400;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#7DC8A2;} + .st1{fill:#AFDBC5;} + .st2{fill:#764D80;} +</style> +<g> + <path class="st0" d="M212.8,38.8h-91.2c-0.2,0-0.4,0-0.6,0c-25.3,0-45.9,20.5-45.9,45.9v229.5c0,25.3,20.5,45.9,45.9,45.9 + s45.9-20.5,45.9-45.9v-45.9h45.9c63.2,0,114.7-51.5,114.7-114.7S276,38.8,212.8,38.8z"/> + <path class="st1" d="M121,348.6c-19,0-34.4-15.5-34.4-34.4V84.7c0-18.9,15.3-34.3,34.2-34.4c0.2,0,0.5,0,0.7,0h91.3 + c56.9,0,103.3,46.3,103.3,103.3s-46.3,103.3-103.3,103.3h-57.3v57.4C155.4,333.2,140,348.6,121,348.6z"/> + <path class="st0" d="M121,337.2c-12.7,0-23-10.3-23-23V84.7c0-12.5,10.1-22.7,22.5-23c0.2,0,0.5,0,0.7,0l91.5,0 + c50.6,0,91.8,41.2,91.8,91.8s-41.2,91.8-91.8,91.8H144v68.8C144,326.9,133.7,337.2,121,337.2z"/> + <path class="st1" d="M121,325.7c-6.4,0-11.6-5.2-11.6-11.6V84.7c0-6.2,5-11.3,11.1-11.5l0.5,0l91.8,0c44.3,0,80.4,36.1,80.4,80.4 + s-36,80.4-80.4,80.4h-80.2v80.3C132.6,320.5,127.4,325.7,121,325.7z"/> + <path class="st0" d="M121.1,222.4h91.7c38,0,68.9-30.9,68.9-68.9s-30.9-68.9-68.9-68.9H121L121.1,222.4z"/> + <path class="st1" d="M132.5,211l-0.1-114.9h80.3c31.7,0,57.5,25.8,57.5,57.5S244.5,211,212.8,211H132.5z"/> + <path class="st0" d="M144,199.6l-0.1-92h68.9c25.4,0,46,20.6,46,46s-20.6,46-46,46H144z"/> + <path class="st1" d="M155.4,188.1l-0.1-69.1h57.4c19.1,0,34.6,15.5,34.6,34.6s-15.5,34.6-34.6,34.6H155.4z"/> + <path class="st0" d="M166.9,176.7l0-46.3h45.9c12.8,0,23.1,10.4,23.1,23.1s-10.4,23.1-23.1,23.1H166.9z"/> + <path class="st1" d="M178.3,165.2l0-23.4h34.5c6.4,0,11.7,5.2,11.7,11.7s-5.2,11.7-11.7,11.7H178.3z"/> + <g> + + <ellipse transform="matrix(0.8192 -0.5736 0.5736 0.8192 -26.9642 83.8822)" class="st2" cx="119.5" cy="84.7" rx="45.9" ry="45.9"/> + <path class="st2" d="M317.7,287.8c14.5,20.8,9.5,49.4-11.3,63.9c-20.8,14.5-49.4,9.5-63.9-11.3l-68.7-98.2 + c-14.5-20.8-9.5-49.4,11.3-63.9c20.8-14.5,49.4-9.5,63.9,11.3L317.7,287.8z"/> + </g> +</g> +</svg> diff --git a/src/vector/index.html b/src/vector/index.html index 73cdd2dfc8..3ab667ccf8 100644 --- a/src/vector/index.html +++ b/src/vector/index.html @@ -20,14 +20,24 @@ <meta name="msapplication-TileImage" content="vector-icons/mstile-144x144.png"> <meta name="msapplication-config" content="vector-icons/browserconfig.xml"> <meta name="theme-color" content="#ffffff"> - <% for(var i=0; i<htmlWebpackPlugin.files.css.length; i++) {%> - <link href="<%= htmlWebpackPlugin.files.css[i] %>" rel="stylesheet"> - <% } %> + <% for (var i=0; i < htmlWebpackPlugin.files.css.length; i++) { + var file = htmlWebpackPlugin.files.css[i]; + var match = file.match(/^bundles\/.*?\/theme-(.*)\.css$/); + if (match) { + var title = match[1].charAt(0).toUpperCase() + match[1].slice(1); + var light = match[1] == 'light'; + %> + <link rel="<%= light ? '' : 'alternate ' %>stylesheet" title="<%= title %>" + href="<%= file %>"> + <% } else { %> + <link rel="stylesheet" href="<%= file %>"> + <% } + } %> </head> <body style="height: 100%;"> <section id="matrixchat" style="height: 100%;"></section> <noscript>Sorry, Riot requires JavaScript to be enabled.</noscript> - <% for(var i=0; i<htmlWebpackPlugin.files.js.length; i++) {%> + <% for (var i=0; i < htmlWebpackPlugin.files.js.length; i++) {%> <script src="<%= htmlWebpackPlugin.files.js[i] %>"></script> <% } %> <img src="img/warning.svg" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/> diff --git a/src/vector/index.js b/src/vector/index.js index 8231950b49..d7072d09fc 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -28,14 +28,22 @@ limitations under the License. // https://babeljs.io/docs/plugins/transform-runtime/ require('babel-polyfill'); -// CSS requires: just putting them here for now as CSS is going to be -// refactored "soon" anyway -require('../../build/components.css'); +// Require common CSS here; this will make webpack process it into bundle.css. +// Our own CSS (which is themed) is imported via separate webpack entry points +// in webpack.config.js require('gemini-scrollbar/gemini-scrollbar.css'); require('gfm.css/gfm.css'); require('highlight.js/styles/github.css'); require('draft-js/dist/Draft.css'); +const rageshake = require("./rageshake"); +rageshake.init().then(() => { + console.log("Initialised rageshake: See https://bugs.chromium.org/p/chromium/issues/detail?id=583193 to fix line numbers on Chrome."); + rageshake.cleanup(); +}, (err) => { + console.error("Failed to initialise rageshake: " + err); +}); + // add React and ReactPerf to the global namespace, to make them easier to // access via the console @@ -233,6 +241,7 @@ async function loadApp() { let configError; try { configJson = await getConfig(); + rageshake.setBugReportEndpoint(configJson.bug_report_endpoint_url); } catch (e) { configError = e; } diff --git a/src/vector/platform/ElectronPlatform.js b/src/vector/platform/ElectronPlatform.js index 68df88b096..c10f2f83c0 100644 --- a/src/vector/platform/ElectronPlatform.js +++ b/src/vector/platform/ElectronPlatform.js @@ -58,6 +58,7 @@ function platformFriendlyName() { export default class ElectronPlatform extends VectorBasePlatform { setNotificationCount(count: number) { + if (this.notificationCount === count) return; super.setNotificationCount(count); // this sometimes throws because electron is made of fail: // https://github.com/electron/electron/issues/7351 @@ -97,7 +98,10 @@ export default class ElectronPlatform extends VectorBasePlatform { room_id: room.roomId }); global.focus(); - electron.remote.getCurrentWindow().restore(); + const currentWin = electron.remote.getCurrentWindow(); + currentWin.show(); + currentWin.restore(); + currentWin.focus(); }; return notification; @@ -131,4 +135,8 @@ export default class ElectronPlatform extends VectorBasePlatform { screenCaptureErrorString() { return null; } + + requestNotificationPermission() : Promise { + return q('granted'); + } } diff --git a/src/vector/platform/WebPlatform.js b/src/vector/platform/WebPlatform.js index 2029822b61..bf4175132e 100644 --- a/src/vector/platform/WebPlatform.js +++ b/src/vector/platform/WebPlatform.js @@ -60,11 +60,13 @@ export default class WebPlatform extends VectorBasePlatform { } setNotificationCount(count: number) { + if (this.notificationCount === count) return; super.setNotificationCount(count); this._updateFavicon(); } setErrorStatus(errorDidOccur: boolean) { + if (this.errorDidOccur === errorDidOccur) return; super.setErrorStatus(errorDidOccur); this._updateFavicon(); } diff --git a/src/vector/rageshake.js b/src/vector/rageshake.js new file mode 100644 index 0000000000..61e29a312d --- /dev/null +++ b/src/vector/rageshake.js @@ -0,0 +1,501 @@ +/* +Copyright 2017 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. +*/ + +import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg'; +import request from "browser-request"; +import q from "q"; + +// This module contains all the code needed to log the console, persist it to +// disk and submit bug reports. Rationale is as follows: +// - Monkey-patching the console is preferable to having a log library because +// we can catch logs by other libraries more easily, without having to all +// depend on the same log framework / pass the logger around. +// - We use IndexedDB to persists logs because it has generous disk space +// limits compared to local storage. IndexedDB does not work in incognito +// mode, in which case this module will not be able to write logs to disk. +// However, the logs will still be stored in-memory, so can still be +// submitted in a bug report should the user wish to: we can also store more +// logs in-memory than in local storage, which does work in incognito mode. +// We also need to handle the case where there are 2+ tabs. Each JS runtime +// generates a random string which serves as the "ID" for that tab/session. +// These IDs are stored along with the log lines. +// - Bug reports are sent as a POST over HTTPS: it purposefully does not use +// Matrix as bug reports may be made when Matrix is not responsive (which may +// be the cause of the bug). We send the most recent N MB of UTF-8 log data, +// starting with the most recent, which we know because the "ID"s are +// actually timestamps. We then purge the remaining logs. We also do this +// purge on startup to prevent logs from accumulating. + +const FLUSH_RATE_MS = 30 * 1000; + +// A class which monkey-patches the global console and stores log lines. +class ConsoleLogger { + constructor() { + this.logs = ""; + } + + monkeyPatch(consoleObj) { + // Monkey-patch console logging + const consoleFunctionsToLevels = { + log: "I", + info: "I", + warn: "W", + error: "E", + }; + Object.keys(consoleFunctionsToLevels).forEach((fnName) => { + const level = consoleFunctionsToLevels[fnName]; + let originalFn = consoleObj[fnName].bind(consoleObj); + consoleObj[fnName] = (...args) => { + this.log(level, ...args); + originalFn(...args); + } + }); + } + + log(level, ...args) { + // We don't know what locale the user may be running so use ISO strings + const ts = new Date().toISOString(); + // Some browsers support string formatting which we're not doing here + // so the lines are a little more ugly but easy to implement / quick to + // run. + // Example line: + // 2017-01-18T11:23:53.214Z W Failed to set badge count + const line = `${ts} ${level} ${args.join(' ')}\n`; + // Using + really is the quickest way in JS + // http://jsperf.com/concat-vs-plus-vs-join + this.logs += line; + } + + /** + * Retrieve log lines to flush to disk. + * @param {boolean} keepLogs True to not delete logs after flushing. + * @return {string} \n delimited log lines to flush. + */ + flush(keepLogs) { + // The ConsoleLogger doesn't care how these end up on disk, it just + // flushes them to the caller. + if (keepLogs) { + return this.logs; + } + const logsToFlush = this.logs; + this.logs = ""; + return logsToFlush; + } +} + +// A class which stores log lines in an IndexedDB instance. +class IndexedDBLogStore { + constructor(indexedDB, logger) { + this.indexedDB = indexedDB; + this.logger = logger; + this.id = "instance-" + Math.random() + Date.now(); + this.index = 0; + this.db = null; + this.flushPromise = null; + // set if flush() is called whilst one is ongoing + this.flushAgainPromise = null; + } + + /** + * @return {Promise} Resolves when the store is ready. + */ + connect() { + let req = this.indexedDB.open("logs"); + return q.Promise((resolve, reject) => { + req.onsuccess = (event) => { + this.db = event.target.result; + // Periodically flush logs to local storage / indexeddb + setInterval(this.flush.bind(this), FLUSH_RATE_MS); + resolve(); + }; + + req.onerror = (event) => { + const err = ( + "Failed to open log database: " + event.target.errorCode + ); + console.error(err); + reject(new Error(err)); + }; + + // First time: Setup the object store + req.onupgradeneeded = (event) => { + const db = event.target.result; + const logObjStore = db.createObjectStore("logs", { + keyPath: ["id", "index"] + }); + // Keys in the database look like: [ "instance-148938490", 0 ] + // Later on we need to query everything based on an instance id. + // In order to do this, we need to set up indexes "id". + logObjStore.createIndex("id", "id", { unique: false }); + + logObjStore.add( + this._generateLogEntry( + new Date() + " ::: Log database was created." + ) + ); + + const lastModifiedStore = db.createObjectStore("logslastmod", { + keyPath: "id", + }); + lastModifiedStore.add(this._generateLastModifiedTime()); + } + }); + } + + /** + * Flush logs to disk. + * + * There are guards to protect against race conditions in order to ensure + * that all previous flushes have completed before the most recent flush. + * Consider without guards: + * - A calls flush() periodically. + * - B calls flush() and wants to send logs immediately afterwards. + * - If B doesn't wait for A's flush to complete, B will be missing the + * contents of A's flush. + * To protect against this, we set 'flushPromise' when a flush is ongoing. + * Subsequent calls to flush() during this period will chain another flush, + * then keep returning that same chained flush. + * + * This guarantees that we will always eventually do a flush when flush() is + * called. + * + * @return {Promise} Resolved when the logs have been flushed. + */ + flush() { + // check if a flush() operation is ongoing + if (this.flushPromise && this.flushPromise.isPending()) { + if (this.flushAgainPromise && this.flushAgainPromise.isPending()) { + // this is the 3rd+ time we've called flush() : return the same + // promise. + return this.flushAgainPromise; + } + // queue up a flush to occur immediately after the pending one + // completes. + this.flushAgainPromise = this.flushPromise.then(() => { + return this.flush(); + }); + return this.flushAgainPromise; + } + // there is no flush promise or there was but it has finished, so do + // a brand new one, destroying the chain which may have been built up. + this.flushPromise = q.Promise((resolve, reject) => { + if (!this.db) { + // not connected yet or user rejected access for us to r/w to + // the db. + reject(new Error("No connected database")); + return; + } + const lines = this.logger.flush(); + if (lines.length === 0) { + resolve(); + return; + } + let txn = this.db.transaction(["logs", "logslastmod"], "readwrite"); + let objStore = txn.objectStore("logs"); + objStore.add(this._generateLogEntry(lines)); + let lastModStore = txn.objectStore("logslastmod"); + lastModStore.put(this._generateLastModifiedTime()); + txn.oncomplete = (event) => { + resolve(); + }; + txn.onerror = (event) => { + console.error( + "Failed to flush logs : ", event + ); + reject( + new Error("Failed to write logs: " + event.target.errorCode) + ); + } + }); + return this.flushPromise; + } + + /** + * Consume the most recent logs and return them. Older logs which are not + * returned are deleted at the same time, so this can be called at startup + * to do house-keeping to keep the logs from growing too large. + * + * @return {Promise<Object[]>} Resolves to an array of objects. The array is + * sorted in time (oldest first) based on when the log file was created (the + * log ID). The objects have said log ID in an "id" field and "lines" which + * is a big string with all the new-line delimited logs. + */ + async consume() { + const MAX_LOG_SIZE = 1024 * 1024 * 50; // 50 MB + const db = this.db; + + // Returns: a string representing the concatenated logs for this ID. + function fetchLogs(id) { + const o = db.transaction("logs", "readonly").objectStore("logs"); + return selectQuery(o.index("id"), IDBKeyRange.only(id), + (cursor) => { + return { + lines: cursor.value.lines, + index: cursor.value.index, + } + }).then((linesArray) => { + // We have been storing logs periodically, so string them all + // together *in order of index* now + linesArray.sort((a, b) => { + return a.index - b.index; + }) + return linesArray.map((l) => l.lines).join(""); + }); + } + + // Returns: A sorted array of log IDs. (newest first) + function fetchLogIds() { + // To gather all the log IDs, query for all records in logslastmod. + const o = db.transaction("logslastmod", "readonly").objectStore( + "logslastmod" + ); + return selectQuery(o, undefined, (cursor) => { + return { + id: cursor.value.id, + ts: cursor.value.ts, + }; + }).then((res) => { + // Sort IDs by timestamp (newest first) + return res.sort((a, b) => { + return b.ts - a.ts; + }).map((a) => a.id); + }); + } + + function deleteLogs(id) { + return q.Promise((resolve, reject) => { + const txn = db.transaction( + ["logs", "logslastmod"], "readwrite" + ); + const o = txn.objectStore("logs"); + // only load the key path, not the data which may be huge + const query = o.index("id").openKeyCursor(IDBKeyRange.only(id)); + query.onsuccess = (event) => { + const cursor = event.target.result; + if (!cursor) { + return; + } + o.delete(cursor.primaryKey); + cursor.continue(); + } + txn.oncomplete = () => { + resolve(); + }; + txn.onerror = (event) => { + reject( + new Error( + "Failed to delete logs for " + + `'${id}' : ${event.target.errorCode}` + ) + ); + }; + // delete last modified entries + const lastModStore = txn.objectStore("logslastmod"); + lastModStore.delete(id); + }); + } + + let allLogIds = await fetchLogIds(); + let removeLogIds = []; + let logs = []; + let size = 0; + for (let i = 0; i < allLogIds.length; i++) { + let lines = await fetchLogs(allLogIds[i]); + logs.push({ + lines: lines, + id: allLogIds[i], + }); + size += lines.length; + if (size > MAX_LOG_SIZE) { + // the remaining log IDs should be removed. If we go out of + // bounds this is just [] + removeLogIds = allLogIds.slice(i + 1); + break; + } + } + if (removeLogIds.length > 0) { + console.log("Removing logs: ", removeLogIds); + // Don't await this because it's non-fatal if we can't clean up + // logs. + Promise.all(removeLogIds.map((id) => deleteLogs(id))).then(() => { + console.log(`Removed ${removeLogIds.length} old logs.`); + }, (err) => { + console.error(err); + }) + } + return logs; + } + + _generateLogEntry(lines) { + return { + id: this.id, + lines: lines, + index: this.index++ + }; + } + + _generateLastModifiedTime() { + return { + id: this.id, + ts: Date.now(), + }; + } +} + +/** + * Helper method to collect results from a Cursor and promiseify it. + * @param {ObjectStore|Index} store The store to perform openCursor on. + * @param {IDBKeyRange=} keyRange Optional key range to apply on the cursor. + * @param {Function} resultMapper A function which is repeatedly called with a + * Cursor. + * Return the data you want to keep. + * @return {Promise<T[]>} Resolves to an array of whatever you returned from + * resultMapper. + */ +function selectQuery(store, keyRange, resultMapper) { + const query = store.openCursor(keyRange); + return q.Promise((resolve, reject) => { + let results = []; + query.onerror = (event) => { + reject(new Error("Query failed: " + event.target.errorCode)); + }; + // collect results + query.onsuccess = (event) => { + const cursor = event.target.result; + if (!cursor) { + resolve(results); + return; // end of results + } + results.push(resultMapper(cursor)); + cursor.continue(); + } + }); +} + + +let store = null; +let logger = null; +let initPromise = null; +let bugReportEndpoint = null; +module.exports = { + + /** + * Configure rage shaking support for sending bug reports. + * Modifies globals. + * @return {Promise} Resolves when set up. + */ + init: function() { + if (initPromise) { + return initPromise; + } + logger = new ConsoleLogger(); + logger.monkeyPatch(window.console); + if (window.indexedDB) { + store = new IndexedDBLogStore(window.indexedDB, logger); + initPromise = store.connect(); + return initPromise; + } + initPromise = Promise.resolve(); + return initPromise; + }, + + /** + * Clean up old logs. + * @return Promise Resolves if cleaned logs. + */ + cleanup: async function() { + if (!store) { + return; + } + await store.consume(); + }, + + setBugReportEndpoint: function(url) { + bugReportEndpoint = url; + }, + + /** + * Send a bug report. + * @param {string} userText Any additional user input. + * @param {boolean} sendLogs True to send logs + * @return {Promise} Resolved when the bug report is sent. + */ + sendBugReport: async function(userText, sendLogs) { + if (!logger) { + throw new Error( + "No console logger, did you forget to call init()?" + ); + } + if (!bugReportEndpoint) { + throw new Error("No bug report endpoint has been set."); + } + + let version = "UNKNOWN"; + try { + version = await PlatformPeg.get().getAppVersion(); + } + catch (err) {} // PlatformPeg already logs this. + + let userAgent = "UNKNOWN"; + if (window.navigator && window.navigator.userAgent) { + userAgent = window.navigator.userAgent; + } + + // If in incognito mode, store is null, but we still want bug report + // sending to work going off the in-memory console logs. + console.log("Sending bug report."); + let logs = []; + if (sendLogs) { + if (store) { + // flush most recent logs + await store.flush(); + logs = await store.consume(); + } + else { + logs.push({ + lines: logger.flush(true), + id: "-", + }); + } + } + + await q.Promise((resolve, reject) => { + request({ + method: "POST", + url: bugReportEndpoint, + body: { + logs: logs, + text: ( + userText || "User did not supply any additional text." + ), + version: version, + user_agent: userAgent, + }, + json: true, + }, (err, res) => { + if (err) { + reject(err); + return; + } + if (res.status < 200 || res.status >= 400) { + reject(new Error(`HTTP ${res.status}`)); + return; + } + resolve(); + }) + }); + } +}; diff --git a/test/.eslintrc.js b/test/.eslintrc.js new file mode 100644 index 0000000000..4cc4659d7d --- /dev/null +++ b/test/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + env: { + mocha: true, + }, +} diff --git a/test/app-tests/loading.js b/test/app-tests/loading.js index 03a4d11e14..d2cb78d04b 100644 --- a/test/app-tests/loading.js +++ b/test/app-tests/loading.js @@ -94,13 +94,13 @@ describe('loading:', function () { loadCompletePromise = loadCompleteDefer.promise; function onNewScreen(screen) { - console.log("newscreen "+screen); + console.log(Date.now() + " newscreen "+screen); if (!appLoaded) { lastLoadedScreen = screen; } else { var hash = '#/' + screen; windowLocation.hash = hash; - console.log("browser URI now "+ windowLocation); + console.log(Date.now() + " browser URI now "+ windowLocation); } } @@ -122,22 +122,22 @@ describe('loading:', function () { ); function routeUrl(location, matrixChat) { - console.log("Routing URL "+location); + console.log(Date.now() + " Routing URL "+location); var fragparts = parseQsFromFragment(location); matrixChat.showScreen(fragparts.location.substring(1), fragparts.params); } // pause for a cycle, then simulate the window.onload handler - q.delay(0).then(() => { - console.log("simulating window.onload"); + window.setTimeout(() => { + console.log(Date.now() + " simulating window.onload"); routeUrl(windowLocation, matrixChat); appLoaded = true; if (lastLoadedScreen) { onNewScreen(lastLoadedScreen); lastLoadedScreen = null; } - }).done(); + }, 0); } describe("Clean load with no stored credentials:", function() { @@ -193,6 +193,7 @@ describe('loading:', function () { expect(req.data.password).toEqual('pass'); }).respond(200, { user_id: '@user:id', + device_id: 'DEVICE_ID', access_token: 'access_token', }); login.onPasswordLogin("user", "pass") @@ -209,14 +210,11 @@ describe('loading:', function () { httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' }); httpBackend.when('GET', '/sync').respond(200, {}); return httpBackend.flush(); - }).then(() => { - // Wait for another trip around the event loop for the UI to update - return q.delay(1); }).then(() => { // once the sync completes, we should have a room view + return awaitRoomView(matrixChat); + }).then(() => { httpBackend.verifyNoOutstandingExpectation(); - ReactTestUtils.findRenderedComponentWithType( - matrixChat, sdk.getComponent('structures.RoomView')); expect(windowLocation.hash).toEqual("#/room/!room:id"); // and the localstorage should have been updated @@ -243,10 +241,8 @@ describe('loading:', function () { loadApp(); - q.delay(1).then(() => { - // we expect a spinner - assertAtSyncingSpinner(matrixChat); - + return awaitSyncingSpinner(matrixChat).then(() => { + // we got a sync spinner - let the sync complete return httpBackend.flush(); }).then(() => { // once the sync completes, we should have a directory @@ -266,16 +262,14 @@ describe('loading:', function () { uriFragment: "#/room/!room:id", }); - q.delay(1).then(() => { - // we expect a spinner - assertAtSyncingSpinner(matrixChat); - + return awaitSyncingSpinner(matrixChat).then(() => { + // we got a sync spinner - let the sync complete return httpBackend.flush(); }).then(() => { // once the sync completes, we should have a room view + return awaitRoomView(matrixChat); + }).then(() => { httpBackend.verifyNoOutstandingExpectation(); - ReactTestUtils.findRenderedComponentWithType( - matrixChat, sdk.getComponent('structures.RoomView')); expect(windowLocation.hash).toEqual("#/room/!room:id"); }).done(done, done); @@ -300,12 +294,9 @@ describe('loading:', function () { return httpBackend.flush(); }).then(() => { - // Wait for another trip around the event loop for the UI to update - return q.delay(1); + return awaitSyncingSpinner(matrixChat); }).then(() => { - // now we should have a spinner with a logout link - assertAtSyncingSpinner(matrixChat); - + // we got a sync spinner - let the sync complete httpBackend.when('GET', '/sync').respond(200, {}); return httpBackend.flush(); }).then(() => { @@ -338,12 +329,8 @@ describe('loading:', function () { return httpBackend.flush(); }).then(() => { - // Wait for another trip around the event loop for the UI to update - return q.delay(1); + return awaitSyncingSpinner(matrixChat); }).then(() => { - // now we should have a spinner with a logout link - assertAtSyncingSpinner(matrixChat); - httpBackend.when('GET', '/sync').check(function(req) { expect(req.path).toMatch(new RegExp("^https://homeserver/")); }).respond(200, {}); @@ -377,22 +364,15 @@ describe('loading:', function () { return httpBackend.flush(); }).then(() => { - // Wait for another trip around the event loop for the UI to update - return q.delay(1); + return awaitSyncingSpinner(matrixChat); }).then(() => { - // now we should have a spinner with a logout link - assertAtSyncingSpinner(matrixChat); - httpBackend.when('GET', '/sync').respond(200, {}); return httpBackend.flush(); - }).then(() => { - // Wait for another trip around the event loop for the UI to update - return q.delay(1); }).then(() => { // once the sync completes, we should have a room view + return awaitRoomView(matrixChat); + }).then(() => { httpBackend.verifyNoOutstandingExpectation(); - ReactTestUtils.findRenderedComponentWithType( - matrixChat, sdk.getComponent('structures.RoomView')); expect(windowLocation.hash).toEqual("#/room/!room:id"); }).done(done, done); }); @@ -414,6 +394,7 @@ describe('loading:', function () { expect(req.data.token).toEqual("secretToken"); }).respond(200, { user_id: "@user:localhost", + device_id: 'DEVICE_ID', access_token: "access_token", }); @@ -448,6 +429,32 @@ function assertAtLoadingSpinner(matrixChat) { // we've got login creds, and are waiting for the sync to finish. // the page includes a logout link. +function awaitSyncingSpinner(matrixChat, retryLimit, retryCount) { + if (retryLimit === undefined) { + retryLimit = 5; + } + if (retryCount === undefined) { + retryCount = 0; + } + + if (matrixChat.state.loading) { + console.log(Date.now() + " Awaiting sync spinner: still loading."); + if (retryCount >= retryLimit) { + throw new Error("MatrixChat still not loaded after " + + retryCount + " tries"); + } + return q.delay(0).then(() => { + return awaitSyncingSpinner(matrixChat, retryLimit, retryCount + 1); + }); + } + + console.log(Date.now() + " Awaiting sync spinner: load complete."); + + // state looks good, check the rendered output + assertAtSyncingSpinner(matrixChat); + return q(); +} + function assertAtSyncingSpinner(matrixChat) { var domComponent = ReactDOM.findDOMNode(matrixChat); expect(domComponent.className).toEqual("mx_MatrixChat_splash"); @@ -458,3 +465,30 @@ function assertAtSyncingSpinner(matrixChat) { matrixChat, 'a'); expect(logoutLink.text).toEqual("Logout"); } + +function awaitRoomView(matrixChat, retryLimit, retryCount) { + if (retryLimit === undefined) { + retryLimit = 5; + } + if (retryCount === undefined) { + retryCount = 0; + } + + if (!matrixChat.state.ready) { + console.log(Date.now() + " Awaiting room view: not ready yet."); + if (retryCount >= retryLimit) { + throw new Error("MatrixChat still not ready after " + + retryCount + " tries"); + } + return q.delay(0).then(() => { + return awaitRoomView(matrixChat, retryLimit, retryCount + 1); + }); + } + + console.log(Date.now() + " Awaiting room view: now ready."); + + // state looks good, check the rendered output + ReactTestUtils.findRenderedComponentWithType( + matrixChat, sdk.getComponent('structures.RoomView')); + return q(); +} diff --git a/webpack.config.js b/webpack.config.js index 3500fedcb6..f3cffa0ea7 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -15,6 +15,10 @@ module.exports = { // point, so that it doesn't block the pageload, but that is a separate // problem) "olm": "./src/vector/olm-loader.js", + + // CSS themes + "theme-light": "./src/skins/vector/css/themes/light.scss", + "theme-dark": "./src/skins/vector/css/themes/dark.scss" }, module: { preLoaders: [ @@ -23,8 +27,25 @@ module.exports = { loaders: [ { test: /\.json$/, loader: "json" }, { test: /\.js$/, loader: "babel", include: path.resolve('./src') }, - // css-raw-loader loads CSS but doesn't try to treat url()s as require()s - { test: /\.css$/, loader: ExtractTextPlugin.extract("css-raw-loader") }, + { + test: /\.scss$/, + + // 1. postcss-loader turns the SCSS into normal CSS. + // 2. css-raw-loader turns the CSS into a javascript module + // whose default export is a string containing the CSS. + // (css-raw-loader is similar to css-loader, but the latter + // would also drag in the imgs and fonts that our CSS refers to + // as webpack inputs.) + // 3. ExtractTextPlugin turns that string into a separate asset. + loader: ExtractTextPlugin.extract( + "css-raw-loader!postcss-loader?config=postcss.config.js" + ), + }, + { + // this works similarly to the scss case, without postcss. + test: /\.css$/, + loader: ExtractTextPlugin.extract("css-raw-loader"), + }, ], noParse: [ // don't parse the languages within highlight.js. They cause stack @@ -40,7 +61,17 @@ module.exports = { }, output: { path: path.join(__dirname, "webapp"), - filename: "[name].[chunkhash].js", + + // the generated js (and CSS, from the ExtractTextPlugin) are put in a + // unique subdirectory for the build. There will only be one such + // 'bundle' directory in the generated tarball; however, hosting + // servers can collect 'bundles' from multiple versions into one + // directory and symlink it into place - this allows users who loaded + // an older version of the application to continue to access webpack + // chunks even after the app is redeployed. + // + filename: "bundles/[hash]/[name].js", + chunkFilename: "bundles/[hash]/[name].js", devtoolModuleFilenameTemplate: function(info) { // Reading input source maps gives only relative paths here for // everything. Until I figure out how to fix this, this is a @@ -79,7 +110,7 @@ module.exports = { }), new ExtractTextPlugin( - "[name].[contenthash].css", + "bundles/[hash]/[name].css", { allChunks: true } @@ -101,6 +132,11 @@ module.exports = { devServer: { // serve unwebpacked assets from webapp. contentBase: './webapp', + + stats: { + // don't fill the console up with a mahoosive list of modules + chunks: false, + }, }, };