Merge branch 'release-v0.9.8'
This commit is contained in:
commit
a12d7a2b66
72 changed files with 1531 additions and 794 deletions
23
.editorconfig
Normal file
23
.editorconfig
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Copyright 2017 Aviral Dasgupta
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset=utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = true
|
|
@ -10,3 +10,6 @@ include:
|
||||||
|
|
||||||
* Florent VIOLLEAU (https://github.com/floviolleau) <floviolleau at gmail dot com>
|
* Florent VIOLLEAU (https://github.com/floviolleau) <floviolleau at gmail dot com>
|
||||||
Improve README.md for a better understanding of installation instructions
|
Improve README.md for a better understanding of installation instructions
|
||||||
|
|
||||||
|
* Michael Telatynski (https://github.com/t3chguy)
|
||||||
|
Improved consistency of inverted elements in dark theme across browsers
|
||||||
|
|
119
CHANGELOG.md
119
CHANGELOG.md
|
@ -1,3 +1,122 @@
|
||||||
|
Changes in [0.9.8](https://github.com/vector-im/riot-web/releases/tag/v0.9.8) (2017-04-12)
|
||||||
|
==========================================================================================
|
||||||
|
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8-rc.3...v0.9.8)
|
||||||
|
|
||||||
|
* No changes
|
||||||
|
|
||||||
|
Changes in [0.9.8-rc.3](https://github.com/vector-im/riot-web/releases/tag/v0.9.8-rc.3) (2017-04-11)
|
||||||
|
====================================================================================================
|
||||||
|
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8-rc.2...v0.9.8-rc.3)
|
||||||
|
|
||||||
|
* Make the clear cache button work on desktop
|
||||||
|
[\#3598](https://github.com/vector-im/riot-web/pull/3598)
|
||||||
|
|
||||||
|
Changes in [0.9.8-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.9.8-rc.2) (2017-04-10)
|
||||||
|
====================================================================================================
|
||||||
|
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.8-rc.1...v0.9.8-rc.2)
|
||||||
|
|
||||||
|
* Redacted events bg: black lozenge -> torn paper
|
||||||
|
[\#3596](https://github.com/vector-im/riot-web/pull/3596)
|
||||||
|
* Add 'app' parameter to rageshake report
|
||||||
|
[\#3594](https://github.com/vector-im/riot-web/pull/3594)
|
||||||
|
|
||||||
|
Changes in [0.9.8-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.8-rc.1) (2017-04-07)
|
||||||
|
====================================================================================================
|
||||||
|
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.7...v0.9.8-rc.1)
|
||||||
|
|
||||||
|
* Add support for indexeddb sync in webworker
|
||||||
|
[\#3578](https://github.com/vector-im/riot-web/pull/3578)
|
||||||
|
* Add CSS to make Emote sender cursor : pointer
|
||||||
|
[\#3574](https://github.com/vector-im/riot-web/pull/3574)
|
||||||
|
* Remove rageshake server
|
||||||
|
[\#3565](https://github.com/vector-im/riot-web/pull/3565)
|
||||||
|
* Adjust CSS for matrix-org/matrix-react-sdk#789
|
||||||
|
[\#3566](https://github.com/vector-im/riot-web/pull/3566)
|
||||||
|
* Fix tests to reflect recent changes
|
||||||
|
[\#3537](https://github.com/vector-im/riot-web/pull/3537)
|
||||||
|
* Do not assume getTs will return comparable integer
|
||||||
|
[\#3536](https://github.com/vector-im/riot-web/pull/3536)
|
||||||
|
* Rename ReactPerf to Perf
|
||||||
|
[\#3535](https://github.com/vector-im/riot-web/pull/3535)
|
||||||
|
* Don't show phone number as target for email notifs
|
||||||
|
[\#3530](https://github.com/vector-im/riot-web/pull/3530)
|
||||||
|
* Fix people section again
|
||||||
|
[\#3458](https://github.com/vector-im/riot-web/pull/3458)
|
||||||
|
* dark theme invert inconsistent across browsers
|
||||||
|
[\#3479](https://github.com/vector-im/riot-web/pull/3479)
|
||||||
|
* CSS for adding phone number in UserSettings
|
||||||
|
[\#3451](https://github.com/vector-im/riot-web/pull/3451)
|
||||||
|
* Support for phone number registration/signin, mk2
|
||||||
|
[\#3426](https://github.com/vector-im/riot-web/pull/3426)
|
||||||
|
* Confirm redactions with a dialog
|
||||||
|
[\#3470](https://github.com/vector-im/riot-web/pull/3470)
|
||||||
|
* Better CSS for redactions
|
||||||
|
[\#3453](https://github.com/vector-im/riot-web/pull/3453)
|
||||||
|
* Fix the people section
|
||||||
|
[\#3448](https://github.com/vector-im/riot-web/pull/3448)
|
||||||
|
* Merge the two RoomTile context menus into one
|
||||||
|
[\#3395](https://github.com/vector-im/riot-web/pull/3395)
|
||||||
|
* Refactor screen set after login
|
||||||
|
[\#3385](https://github.com/vector-im/riot-web/pull/3385)
|
||||||
|
* CSS for redacted EventTiles
|
||||||
|
[\#3379](https://github.com/vector-im/riot-web/pull/3379)
|
||||||
|
* Height:100% for welcome pages on Safari
|
||||||
|
[\#3340](https://github.com/vector-im/riot-web/pull/3340)
|
||||||
|
* `view_room` dispatch from `onClick` RoomTile
|
||||||
|
[\#3376](https://github.com/vector-im/riot-web/pull/3376)
|
||||||
|
* Hide statusAreaBox_line entirely when inCall
|
||||||
|
[\#3350](https://github.com/vector-im/riot-web/pull/3350)
|
||||||
|
* Set padding-bottom: 0px for .mx_Dialog spinner
|
||||||
|
[\#3351](https://github.com/vector-im/riot-web/pull/3351)
|
||||||
|
* Support InteractiveAuth based registration
|
||||||
|
[\#3333](https://github.com/vector-im/riot-web/pull/3333)
|
||||||
|
* Expose notification option for username/MXID
|
||||||
|
[\#3334](https://github.com/vector-im/riot-web/pull/3334)
|
||||||
|
* Float the toggle in the top right of MELS
|
||||||
|
[\#3190](https://github.com/vector-im/riot-web/pull/3190)
|
||||||
|
* More aggressive rageshake log culling
|
||||||
|
[\#3311](https://github.com/vector-im/riot-web/pull/3311)
|
||||||
|
* Don't overflow directory network options
|
||||||
|
[\#3282](https://github.com/vector-im/riot-web/pull/3282)
|
||||||
|
* CSS for ban / kick reason prompt
|
||||||
|
[\#3250](https://github.com/vector-im/riot-web/pull/3250)
|
||||||
|
* Allow forgetting rooms you're banned from
|
||||||
|
[\#3246](https://github.com/vector-im/riot-web/pull/3246)
|
||||||
|
* Fix icon paths in manifest
|
||||||
|
[\#3245](https://github.com/vector-im/riot-web/pull/3245)
|
||||||
|
* Fix broken tests caused by adding IndexedDB support
|
||||||
|
[\#3242](https://github.com/vector-im/riot-web/pull/3242)
|
||||||
|
* CSS for un-ban button in RoomSettings
|
||||||
|
[\#3227](https://github.com/vector-im/riot-web/pull/3227)
|
||||||
|
* Remove z-index property on avatar initials
|
||||||
|
[\#3239](https://github.com/vector-im/riot-web/pull/3239)
|
||||||
|
* Reposition certain icons in the status bar
|
||||||
|
[\#3233](https://github.com/vector-im/riot-web/pull/3233)
|
||||||
|
* CSS for kick/ban confirmation dialog
|
||||||
|
[\#3224](https://github.com/vector-im/riot-web/pull/3224)
|
||||||
|
* Style for split-out interactive auth
|
||||||
|
[\#3217](https://github.com/vector-im/riot-web/pull/3217)
|
||||||
|
* Use the teamToken threaded through from react sdk
|
||||||
|
[\#3196](https://github.com/vector-im/riot-web/pull/3196)
|
||||||
|
* rageshake: Add file server with basic auth
|
||||||
|
[\#3169](https://github.com/vector-im/riot-web/pull/3169)
|
||||||
|
* Fix bug with home icon not appearing when logged in as team member
|
||||||
|
[\#3162](https://github.com/vector-im/riot-web/pull/3162)
|
||||||
|
* Add ISSUE_TEMPLATE
|
||||||
|
[\#2836](https://github.com/vector-im/riot-web/pull/2836)
|
||||||
|
* Store bug reports in separate directories
|
||||||
|
[\#3150](https://github.com/vector-im/riot-web/pull/3150)
|
||||||
|
* Quick and dirty support for custom welcome pages.
|
||||||
|
[\#2575](https://github.com/vector-im/riot-web/pull/2575)
|
||||||
|
* RTS Welcome Pages
|
||||||
|
[\#3103](https://github.com/vector-im/riot-web/pull/3103)
|
||||||
|
* rageshake: Abide by Go standards
|
||||||
|
[\#3149](https://github.com/vector-im/riot-web/pull/3149)
|
||||||
|
* Bug report server script
|
||||||
|
[\#3072](https://github.com/vector-im/riot-web/pull/3072)
|
||||||
|
* Bump olm version
|
||||||
|
[\#3125](https://github.com/vector-im/riot-web/pull/3125)
|
||||||
|
|
||||||
Changes in [0.9.7](https://github.com/vector-im/riot-web/releases/tag/v0.9.7) (2017-02-04)
|
Changes in [0.9.7](https://github.com/vector-im/riot-web/releases/tag/v0.9.7) (2017-02-04)
|
||||||
==========================================================================================
|
==========================================================================================
|
||||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.7-rc.3...v0.9.7)
|
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.7-rc.3...v0.9.7)
|
||||||
|
|
18
README.md
18
README.md
|
@ -21,6 +21,9 @@ released version of Riot:
|
||||||
as desired. See below for details.
|
as desired. See below for details.
|
||||||
1. Enter the URL into your browser and log into Riot!
|
1. Enter the URL into your browser and log into Riot!
|
||||||
|
|
||||||
|
Releases are signed by PGP, and can be checked against the public key
|
||||||
|
at https://riot.im/packages/keys/riot-master.asc
|
||||||
|
|
||||||
Note that Chrome does not allow microphone or webcam access for sites served
|
Note that Chrome does not allow microphone or webcam access for sites served
|
||||||
over http (except localhost), so for working VoIP you will need to serve Riot
|
over http (except localhost), so for working VoIP you will need to serve Riot
|
||||||
over https.
|
over https.
|
||||||
|
@ -64,6 +67,18 @@ to build.
|
||||||
(cd node_modules/matrix-js-sdk && npm install)
|
(cd node_modules/matrix-js-sdk && npm install)
|
||||||
(cd node_modules/matrix-react-sdk && npm install)
|
(cd node_modules/matrix-react-sdk && npm install)
|
||||||
```
|
```
|
||||||
|
Whenever you git pull on riot-web you will also probably need to force an update
|
||||||
|
to these dependencies - the easiest way is probably:
|
||||||
|
```
|
||||||
|
rm -rf node_modules/matrjx-{js,react}-sdk && npm i
|
||||||
|
(cd node_modules/matrix-js-sdk && npm install)
|
||||||
|
(cd node_modules/matrix-react-sdk && npm install)
|
||||||
|
```
|
||||||
|
However, we recommend setting up a proper development environment (see "Setting
|
||||||
|
up a development environment" below) if you want to run your own copy of the
|
||||||
|
`develop` branch, as it makes it much easier to keep these dependencies
|
||||||
|
up-to-date. Or just use https://riot.im/develop - the continuous integration
|
||||||
|
release of the develop branch.
|
||||||
1. Configure the app by copying `config.sample.json` to `config.json` and
|
1. Configure the app by copying `config.sample.json` to `config.json` and
|
||||||
modifying it (see below for details)
|
modifying it (see below for details)
|
||||||
1. `npm run dist` to build a tarball to deploy. Untaring this file will give
|
1. `npm run dist` to build a tarball to deploy. Untaring this file will give
|
||||||
|
@ -114,7 +129,8 @@ built it yourself.
|
||||||
|
|
||||||
To run as a desktop app:
|
To run as a desktop app:
|
||||||
|
|
||||||
1. Follow the instructions in 'Building From Source' above
|
1. Follow the instructions in 'Building From Source' above, but run
|
||||||
|
`npm run build` instead of `npm run dist` (since we don't need the tarball).
|
||||||
2. Install electron and run it:
|
2. Install electron and run it:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"brand": "Riot",
|
"brand": "Riot",
|
||||||
"integrations_ui_url": "https://scalar.vector.im/",
|
"integrations_ui_url": "https://scalar.vector.im/",
|
||||||
"integrations_rest_url": "https://scalar.vector.im/api",
|
"integrations_rest_url": "https://scalar.vector.im/api",
|
||||||
|
"bug_report_endpoint_url": "https://riot.im/bugreports/submit",
|
||||||
"enableLabs": true,
|
"enableLabs": true,
|
||||||
"roomDirectory": {
|
"roomDirectory": {
|
||||||
"servers": [
|
"servers": [
|
||||||
|
|
10
package.json
10
package.json
|
@ -2,7 +2,7 @@
|
||||||
"name": "riot-web",
|
"name": "riot-web",
|
||||||
"productName": "Riot",
|
"productName": "Riot",
|
||||||
"main": "electron/src/electron-main.js",
|
"main": "electron/src/electron-main.js",
|
||||||
"version": "0.9.7",
|
"version": "0.9.8",
|
||||||
"description": "A feature-rich client for Matrix.org",
|
"description": "A feature-rich client for Matrix.org",
|
||||||
"author": "Vector Creations Ltd.",
|
"author": "Vector Creations Ltd.",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -62,8 +62,8 @@
|
||||||
"gfm.css": "^1.1.1",
|
"gfm.css": "^1.1.1",
|
||||||
"highlight.js": "^9.0.0",
|
"highlight.js": "^9.0.0",
|
||||||
"linkifyjs": "^2.1.3",
|
"linkifyjs": "^2.1.3",
|
||||||
"matrix-js-sdk": "0.7.5",
|
"matrix-js-sdk": "0.7.6",
|
||||||
"matrix-react-sdk": "0.8.6",
|
"matrix-react-sdk": "0.8.7",
|
||||||
"modernizr": "^3.1.0",
|
"modernizr": "^3.1.0",
|
||||||
"q": "^1.4.1",
|
"q": "^1.4.1",
|
||||||
"react": "^15.4.0",
|
"react": "^15.4.0",
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
"css-raw-loader": "^0.1.1",
|
"css-raw-loader": "^0.1.1",
|
||||||
"electron-builder": "^11.2.4",
|
"electron-builder": "^11.2.4",
|
||||||
"electron-builder-squirrel-windows": "^11.2.1",
|
"electron-builder-squirrel-windows": "^11.2.1",
|
||||||
"emojione": "^2.2.3",
|
"emojione": "^2.2.7",
|
||||||
"eslint": "^3.14.0",
|
"eslint": "^3.14.0",
|
||||||
"eslint-config-google": "^0.7.1",
|
"eslint-config-google": "^0.7.1",
|
||||||
"eslint-plugin-flowtype": "^2.30.0",
|
"eslint-plugin-flowtype": "^2.30.0",
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "im.riot.app",
|
"appId": "im.riot.app",
|
||||||
"category": "Network",
|
"category": "Network",
|
||||||
"electronVersion": "1.4.14",
|
"electronVersion": "1.6.2",
|
||||||
"//asar=false": "https://github.com/electron-userland/electron-builder/issues/675",
|
"//asar=false": "https://github.com/electron-userland/electron-builder/issues/675",
|
||||||
"asar": false,
|
"asar": false,
|
||||||
"dereference": true,
|
"dereference": true,
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -2,37 +2,37 @@
|
||||||
"name": "Riot",
|
"name": "Riot",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "\/icons\/android-chrome-36x36.png",
|
"src": "android-chrome-36x36.png",
|
||||||
"sizes": "36x36",
|
"sizes": "36x36",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "0.75"
|
"density": "0.75"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/icons\/android-chrome-48x48.png",
|
"src": "android-chrome-48x48.png",
|
||||||
"sizes": "48x48",
|
"sizes": "48x48",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "1.0"
|
"density": "1.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/icons\/android-chrome-72x72.png",
|
"src": "android-chrome-72x72.png",
|
||||||
"sizes": "72x72",
|
"sizes": "72x72",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "1.5"
|
"density": "1.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/icons\/android-chrome-96x96.png",
|
"src": "android-chrome-96x96.png",
|
||||||
"sizes": "96x96",
|
"sizes": "96x96",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "2.0"
|
"density": "2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/icons\/android-chrome-144x144.png",
|
"src": "android-chrome-144x144.png",
|
||||||
"sizes": "144x144",
|
"sizes": "144x144",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "3.0"
|
"density": "3.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "\/icons\/android-chrome-192x192.png",
|
"src": "android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image\/png",
|
"type": "image\/png",
|
||||||
"density": "4.0"
|
"density": "4.0"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
export NVM_DIR="/home/jenkins/.nvm"
|
export NVM_DIR="$HOME/.nvm"
|
||||||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
||||||
nvm use 6
|
nvm use 6
|
||||||
|
|
||||||
|
@ -11,13 +11,18 @@ set -x
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
# apparently npm 3.10.3 on node 6.4.0 doesn't upgrade #develop target with npm install unless explicitly asked.
|
# apparently npm 3.10.3 on node 6.4.0 doesn't upgrade #develop target with npm install unless explicitly asked.
|
||||||
npm install matrix-react-sdk matrix-js-sdk
|
npm install matrix-react-sdk matrix-js-sdk olm
|
||||||
|
|
||||||
# install olm. A naive 'npm i ./olm/olm-*.tgz' fails because it uses the url
|
# install olm. A naive 'npm i ./olm/olm-*.tgz' fails because it uses the url
|
||||||
# from our package.json (or even matrix-js-sdk's) in preference.
|
# from our package.json (or even matrix-js-sdk's) in preference.
|
||||||
tar -C olm -xz < olm/olm-*.tgz
|
#
|
||||||
rm -r node_modules/olm
|
# disabled for now, to avoid the annoying scenario of a release doing something
|
||||||
cp -r olm/package node_modules/olm
|
# different to /develop. Instead, add it to the 'npm install' list above.
|
||||||
|
# -- rav 2016/02/03
|
||||||
|
#tar -C olm -xz < olm/olm-*.tgz
|
||||||
|
#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
|
# 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 install)
|
(cd node_modules/matrix-js-sdk && npm install)
|
||||||
|
|
|
@ -30,6 +30,8 @@ import structures$BottomLeftMenu from './components/structures/BottomLeftMenu';
|
||||||
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';
|
import structures$CompatibilityPage from './components/structures/CompatibilityPage';
|
||||||
structures$CompatibilityPage && (module.exports.components['structures.CompatibilityPage'] = structures$CompatibilityPage);
|
structures$CompatibilityPage && (module.exports.components['structures.CompatibilityPage'] = structures$CompatibilityPage);
|
||||||
|
import structures$HomePage from './components/structures/HomePage';
|
||||||
|
structures$HomePage && (module.exports.components['structures.HomePage'] = structures$HomePage);
|
||||||
import structures$LeftPanel from './components/structures/LeftPanel';
|
import structures$LeftPanel from './components/structures/LeftPanel';
|
||||||
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';
|
import structures$RightPanel from './components/structures/RightPanel';
|
||||||
|
@ -44,10 +46,8 @@ import structures$ViewSource from './components/structures/ViewSource';
|
||||||
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';
|
import views$context_menus$MessageContextMenu from './components/views/context_menus/MessageContextMenu';
|
||||||
views$context_menus$MessageContextMenu && (module.exports.components['views.context_menus.MessageContextMenu'] = views$context_menus$MessageContextMenu);
|
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';
|
import views$context_menus$RoomTileContextMenu from './components/views/context_menus/RoomTileContextMenu';
|
||||||
views$context_menus$NotificationStateContextMenu && (module.exports.components['views.context_menus.NotificationStateContextMenu'] = views$context_menus$NotificationStateContextMenu);
|
views$context_menus$RoomTileContextMenu && (module.exports.components['views.context_menus.RoomTileContextMenu'] = views$context_menus$RoomTileContextMenu);
|
||||||
import views$context_menus$RoomTagContextMenu from './components/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';
|
import views$dialogs$BugReportDialog from './components/views/dialogs/BugReportDialog';
|
||||||
views$dialogs$BugReportDialog && (module.exports.components['views.dialogs.BugReportDialog'] = views$dialogs$BugReportDialog);
|
views$dialogs$BugReportDialog && (module.exports.components['views.dialogs.BugReportDialog'] = views$dialogs$BugReportDialog);
|
||||||
import views$dialogs$ChangelogDialog from './components/views/dialogs/ChangelogDialog';
|
import views$dialogs$ChangelogDialog from './components/views/dialogs/ChangelogDialog';
|
||||||
|
|
|
@ -27,12 +27,14 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
collapsed: React.PropTypes.bool.isRequired,
|
collapsed: React.PropTypes.bool.isRequired,
|
||||||
|
teamToken: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return({
|
return({
|
||||||
directoryHover : false,
|
directoryHover : false,
|
||||||
roomsHover : false,
|
roomsHover : false,
|
||||||
|
homeHover: false,
|
||||||
peopleHover : false,
|
peopleHover : false,
|
||||||
settingsHover : false,
|
settingsHover : false,
|
||||||
});
|
});
|
||||||
|
@ -63,6 +65,19 @@ module.exports = React.createClass({
|
||||||
this.setState({ roomsHover: false });
|
this.setState({ roomsHover: false });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Home button events
|
||||||
|
onHomeClick: function() {
|
||||||
|
dis.dispatch({ action: 'view_home_page' });
|
||||||
|
},
|
||||||
|
|
||||||
|
onHomeMouseEnter: function() {
|
||||||
|
this.setState({ homeHover: true });
|
||||||
|
},
|
||||||
|
|
||||||
|
onHomeMouseLeave: function() {
|
||||||
|
this.setState({ homeHover: false });
|
||||||
|
},
|
||||||
|
|
||||||
// People events
|
// People events
|
||||||
onPeopleClick: function() {
|
onPeopleClick: function() {
|
||||||
dis.dispatch({ action: 'view_create_chat' });
|
dis.dispatch({ action: 'view_create_chat' });
|
||||||
|
@ -99,9 +114,21 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var TintableSvg = sdk.getComponent('elements.TintableSvg');
|
var TintableSvg = sdk.getComponent('elements.TintableSvg');
|
||||||
|
|
||||||
|
var homeButton;
|
||||||
|
if (this.props.teamToken) {
|
||||||
|
homeButton = (
|
||||||
|
<AccessibleButton className="mx_BottomLeftMenu_homePage" onClick={ this.onHomeClick } onMouseEnter={ this.onHomeMouseEnter } onMouseLeave={ this.onHomeMouseLeave } >
|
||||||
|
<TintableSvg src="img/icons-home.svg" width="25" height="25" />
|
||||||
|
{ this.getLabel("Welcome page", this.state.homeHover) }
|
||||||
|
</AccessibleButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_BottomLeftMenu">
|
<div className="mx_BottomLeftMenu">
|
||||||
<div className="mx_BottomLeftMenu_options">
|
<div className="mx_BottomLeftMenu_options">
|
||||||
|
{ homeButton }
|
||||||
<AccessibleButton className="mx_BottomLeftMenu_people" onClick={ this.onPeopleClick } onMouseEnter={ this.onPeopleMouseEnter } onMouseLeave={ this.onPeopleMouseLeave } >
|
<AccessibleButton className="mx_BottomLeftMenu_people" onClick={ this.onPeopleClick } onMouseEnter={ this.onPeopleMouseEnter } onMouseLeave={ this.onPeopleMouseLeave } >
|
||||||
<TintableSvg src="img/icons-people.svg" width="25" height="25" />
|
<TintableSvg src="img/icons-people.svg" width="25" height="25" />
|
||||||
{ this.getLabel("Start chat", this.state.peopleHover) }
|
{ this.getLabel("Start chat", this.state.peopleHover) }
|
||||||
|
|
40
src/components/structures/HomePage.js
Normal file
40
src/components/structures/HomePage.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||||
|
import sdk from 'matrix-react-sdk';
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
displayName: 'HomePage',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
teamServerUrl: React.PropTypes.string.isRequired,
|
||||||
|
teamToken: React.PropTypes.string.isRequired,
|
||||||
|
collapsedRhs: React.PropTypes.bool,
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
<div className="mx_HomePage">
|
||||||
|
<iframe src={`${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
|
@ -28,6 +28,11 @@ var CallHandler = require("matrix-react-sdk/lib/CallHandler");
|
||||||
var LeftPanel = React.createClass({
|
var LeftPanel = React.createClass({
|
||||||
displayName: 'LeftPanel',
|
displayName: 'LeftPanel',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
collapsed: React.PropTypes.bool.isRequired,
|
||||||
|
teamToken: React.PropTypes.string,
|
||||||
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
showCallElement: null,
|
showCallElement: null,
|
||||||
|
@ -124,7 +129,7 @@ var LeftPanel = React.createClass({
|
||||||
collapsed={this.props.collapsed}
|
collapsed={this.props.collapsed}
|
||||||
searchFilter={this.state.searchFilter}
|
searchFilter={this.state.searchFilter}
|
||||||
ConferenceHandler={VectorConferenceHandler} />
|
ConferenceHandler={VectorConferenceHandler} />
|
||||||
<BottomLeftMenu collapsed={this.props.collapsed}/>
|
<BottomLeftMenu collapsed={this.props.collapsed} teamToken={this.props.teamToken}/>
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@ module.exports = React.createClass({
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to get public room list",
|
title: "Failed to get public room list",
|
||||||
description: err.message
|
description: "The server may be unavailable or overloaded",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -208,9 +208,10 @@ module.exports = React.createClass({
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
modal.close();
|
modal.close();
|
||||||
this.refreshRoomList();
|
this.refreshRoomList();
|
||||||
|
console.error("Failed to " + step + ": " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to "+step,
|
title: "Error",
|
||||||
description: err.toString()
|
description: "Failed to " + step,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,12 +146,20 @@ var RoomSubList = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onRoomTileClick(roomId) {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'view_room',
|
||||||
|
room_id: roomId,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
tsOfNewestEvent: function(room) {
|
tsOfNewestEvent: function(room) {
|
||||||
for (var i = room.timeline.length - 1; i >= 0; --i) {
|
for (var i = room.timeline.length - 1; i >= 0; --i) {
|
||||||
var ev = room.timeline[i];
|
var ev = room.timeline[i];
|
||||||
if (Unread.eventTriggersUnreadCount(ev) ||
|
if (ev.getTs() &&
|
||||||
(ev.sender && ev.sender.userId === MatrixClientPeg.get().credentials.userId))
|
(Unread.eventTriggersUnreadCount(ev) ||
|
||||||
{
|
(ev.getSender() === MatrixClientPeg.get().credentials.userId))
|
||||||
|
) {
|
||||||
return ev.getTs();
|
return ev.getTs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +167,7 @@ var RoomSubList = React.createClass({
|
||||||
// we might only have events that don't trigger the unread indicator,
|
// we might only have events that don't trigger the unread indicator,
|
||||||
// in which case use the oldest event even if normally it wouldn't count.
|
// in which case use the oldest event even if normally it wouldn't count.
|
||||||
// This is better than just assuming the last event was forever ago.
|
// This is better than just assuming the last event was forever ago.
|
||||||
if (room.timeline.length) {
|
if (room.timeline.length && room.timeline[0].getTs()) {
|
||||||
return room.timeline[0].getTs();
|
return room.timeline[0].getTs();
|
||||||
} else {
|
} else {
|
||||||
return Number.MAX_SAFE_INTEGER;
|
return Number.MAX_SAFE_INTEGER;
|
||||||
|
@ -364,7 +372,9 @@ var RoomSubList = React.createClass({
|
||||||
highlight={ room.getUnreadNotificationCount('highlight') > 0 || self.props.label === 'Invites' }
|
highlight={ room.getUnreadNotificationCount('highlight') > 0 || self.props.label === 'Invites' }
|
||||||
isInvite={ self.props.label === 'Invites' }
|
isInvite={ self.props.label === 'Invites' }
|
||||||
refreshSubList={ self._updateSubListCount }
|
refreshSubList={ self._updateSubListCount }
|
||||||
incomingCall={ null } />
|
incomingCall={ null }
|
||||||
|
onClick={ self.onRoomTileClick }
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -408,7 +418,7 @@ var RoomSubList = React.createClass({
|
||||||
if (this.props.incomingCall) {
|
if (this.props.incomingCall) {
|
||||||
var self = this;
|
var self = this;
|
||||||
// Check if the incoming call is for this section
|
// Check if the incoming call is for this section
|
||||||
var incomingCallRoom = this.state.sortedList.filter(function(room) {
|
var incomingCallRoom = this.props.list.filter(function(room) {
|
||||||
return self.props.incomingCall.roomId === room.roomId;
|
return self.props.incomingCall.roomId === room.roomId;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -496,9 +506,10 @@ var RoomSubList = React.createClass({
|
||||||
// Do any final stuff here
|
// Do any final stuff here
|
||||||
}).fail(function(err) {
|
}).fail(function(err) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to add tag " + self.props.tagName + " to room" + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to add tag " + self.props.tagName + " to room",
|
title: "Error",
|
||||||
description: err.toString()
|
description: "Failed to add tag " + self.props.tagName + " to room",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -45,6 +45,9 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onAction: function(payload) {
|
onAction: function(payload) {
|
||||||
|
// Disabling this as I find it really really annoying, and was used to the
|
||||||
|
// previous behaviour - see https://github.com/vector-im/riot-web/issues/3348
|
||||||
|
/*
|
||||||
switch (payload.action) {
|
switch (payload.action) {
|
||||||
// Clear up the text field when a room is selected.
|
// Clear up the text field when a room is selected.
|
||||||
case 'view_room':
|
case 'view_room':
|
||||||
|
@ -53,6 +56,7 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange: function() {
|
onChange: function() {
|
||||||
|
|
|
@ -62,19 +62,24 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onRedactClick: function() {
|
onRedactClick: function() {
|
||||||
MatrixClientPeg.get().redactEvent(
|
const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
|
||||||
this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()
|
Modal.createDialog(ConfirmRedactDialog, {
|
||||||
).done(function() {
|
onFinished: (proceed) => {
|
||||||
// message should disappear by itself
|
if (!proceed) return;
|
||||||
}, function(e) {
|
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
MatrixClientPeg.get().redactEvent(
|
||||||
// display error message stating you couldn't delete this.
|
this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()
|
||||||
var code = e.errcode || e.statusCode;
|
).catch(function(e) {
|
||||||
Modal.createDialog(ErrorDialog, {
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
title: "Error",
|
// display error message stating you couldn't delete this.
|
||||||
description: "You cannot delete this message. (" + code + ")"
|
var code = e.errcode || e.statusCode;
|
||||||
});
|
Modal.createDialog(ErrorDialog, {
|
||||||
});
|
title: "Error",
|
||||||
|
description: "You cannot delete this message. (" + code + ")"
|
||||||
|
});
|
||||||
|
}).done();
|
||||||
|
},
|
||||||
|
}, 'mx_Dialog_confirmredact');
|
||||||
if (this.props.onFinished) this.props.onFinished();
|
if (this.props.onFinished) this.props.onFinished();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -121,7 +126,7 @@ module.exports = React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eventStatus) { // sent
|
if (!eventStatus && !this.props.mxEvent.isRedacted()) { // sent and not redacted
|
||||||
redactButton = (
|
redactButton = (
|
||||||
<div className="mx_MessageContextMenu_field" onClick={this.onRedactClick}>
|
<div className="mx_MessageContextMenu_field" onClick={this.onRedactClick}>
|
||||||
Redact
|
Redact
|
||||||
|
|
|
@ -1,144 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var q = require("q");
|
|
||||||
var React = require('react');
|
|
||||||
var classNames = require('classnames');
|
|
||||||
var RoomNotifs = require('matrix-react-sdk/lib/RoomNotifs');
|
|
||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'NotificationStateContextMenu',
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
room: React.PropTypes.object.isRequired,
|
|
||||||
/* callback called when the menu is dismissed */
|
|
||||||
onFinished: React.PropTypes.func,
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState() {
|
|
||||||
return {
|
|
||||||
roomNotifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillMount: function() {
|
|
||||||
this._unmounted = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
this._unmounted = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_save: function(newState) {
|
|
||||||
const oldState = this.state.roomNotifState;
|
|
||||||
const roomId = this.props.room.roomId;
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
|
|
||||||
if (cli.isGuest()) return;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
roomNotifState: newState,
|
|
||||||
});
|
|
||||||
RoomNotifs.setRoomNotifsState(this.props.room.roomId, newState).done(() => {
|
|
||||||
// delay slightly so that the user can see their state change
|
|
||||||
// before closing the menu
|
|
||||||
return q.delay(500).then(() => {
|
|
||||||
if (this._unmounted) return;
|
|
||||||
// Close the context menu
|
|
||||||
if (this.props.onFinished) {
|
|
||||||
this.props.onFinished();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}, (error) => {
|
|
||||||
// TODO: some form of error notification to the user
|
|
||||||
// to inform them that their state change failed.
|
|
||||||
// For now we at least set the state back
|
|
||||||
if (this._unmounted) return;
|
|
||||||
this.setState({
|
|
||||||
roomNotifState: oldState,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickAlertMe: function() {
|
|
||||||
this._save(RoomNotifs.ALL_MESSAGES_LOUD);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickAllNotifs: function() {
|
|
||||||
this._save(RoomNotifs.ALL_MESSAGES);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickMentions: function() {
|
|
||||||
this._save(RoomNotifs.MENTIONS_ONLY);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickMute: function() {
|
|
||||||
this._save(RoomNotifs.MUTE);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var alertMeClasses = classNames({
|
|
||||||
'mx_NotificationStateContextMenu_field': true,
|
|
||||||
'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD,
|
|
||||||
});
|
|
||||||
|
|
||||||
var allNotifsClasses = classNames({
|
|
||||||
'mx_NotificationStateContextMenu_field': true,
|
|
||||||
'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES,
|
|
||||||
});
|
|
||||||
|
|
||||||
var mentionsClasses = classNames({
|
|
||||||
'mx_NotificationStateContextMenu_field': true,
|
|
||||||
'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.MENTIONS_ONLY,
|
|
||||||
});
|
|
||||||
|
|
||||||
var muteNotifsClasses = classNames({
|
|
||||||
'mx_NotificationStateContextMenu_field': true,
|
|
||||||
'mx_NotificationStateContextMenu_fieldSet': this.state.roomNotifState == RoomNotifs.MUTE,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="mx_NotificationStateContextMenu_picker" >
|
|
||||||
<img src="img/notif-slider.svg" width="20" height="107" />
|
|
||||||
</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 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 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 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 mx_filterFlipColor" src="img/icon-context-mute.svg" width="16" height="12" />
|
|
||||||
Mute
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,253 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var q = require("q");
|
|
||||||
var React = require('react');
|
|
||||||
var classNames = require('classnames');
|
|
||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
|
||||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
|
||||||
var DMRoomMap = require('matrix-react-sdk/lib/utils/DMRoomMap');
|
|
||||||
var Rooms = require('matrix-react-sdk/lib/Rooms');
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'RoomTagContextMenu',
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
room: React.PropTypes.object.isRequired,
|
|
||||||
/* callback called when the menu is dismissed */
|
|
||||||
onFinished: React.PropTypes.func,
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
|
|
||||||
return {
|
|
||||||
isFavourite: this.props.room.tags.hasOwnProperty("m.favourite"),
|
|
||||||
isLowPriority: this.props.room.tags.hasOwnProperty("m.lowpriority"),
|
|
||||||
isDirectMessage: Boolean(dmRoomMap.getUserIdForRoomId(this.props.room.roomId)),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
_toggleTag: function(tagNameOn, tagNameOff) {
|
|
||||||
var self = this;
|
|
||||||
const roomId = this.props.room.roomId;
|
|
||||||
var cli = MatrixClientPeg.get();
|
|
||||||
if (!cli.isGuest()) {
|
|
||||||
q.delay(500).then(function() {
|
|
||||||
if (tagNameOff !== null && tagNameOff !== undefined) {
|
|
||||||
cli.deleteRoomTag(roomId, tagNameOff).finally(function() {
|
|
||||||
// Close the context menu
|
|
||||||
if (self.props.onFinished) {
|
|
||||||
self.props.onFinished();
|
|
||||||
};
|
|
||||||
}).fail(function(err) {
|
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
||||||
Modal.createDialog(ErrorDialog, {
|
|
||||||
title: "Failed to remove tag " + tagNameOff + " from room",
|
|
||||||
description: err.toString()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagNameOn !== null && tagNameOn !== undefined) {
|
|
||||||
// If the tag ordering meta data is required, it is added by
|
|
||||||
// the RoomSubList when it sorts its rooms
|
|
||||||
cli.setRoomTag(roomId, tagNameOn, {}).finally(function() {
|
|
||||||
// Close the context menu
|
|
||||||
if (self.props.onFinished) {
|
|
||||||
self.props.onFinished();
|
|
||||||
};
|
|
||||||
}).fail(function(err) {
|
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
||||||
Modal.createDialog(ErrorDialog, {
|
|
||||||
title: "Failed to add tag " + tagNameOn + " to room",
|
|
||||||
description: err.toString()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickFavourite: function() {
|
|
||||||
// Tag room as 'Favourite'
|
|
||||||
if (!this.state.isFavourite && this.state.isLowPriority) {
|
|
||||||
this.setState({
|
|
||||||
isFavourite: true,
|
|
||||||
isLowPriority: false,
|
|
||||||
});
|
|
||||||
this._toggleTag("m.favourite", "m.lowpriority");
|
|
||||||
} else if (this.state.isFavourite) {
|
|
||||||
this.setState({isFavourite: false});
|
|
||||||
this._toggleTag(null, "m.favourite");
|
|
||||||
} else if (!this.state.isFavourite) {
|
|
||||||
this.setState({isFavourite: true});
|
|
||||||
this._toggleTag("m.favourite");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickLowPriority: function() {
|
|
||||||
// Tag room as 'Low Priority'
|
|
||||||
if (!this.state.isLowPriority && this.state.isFavourite) {
|
|
||||||
this.setState({
|
|
||||||
isFavourite: false,
|
|
||||||
isLowPriority: true,
|
|
||||||
});
|
|
||||||
this._toggleTag("m.lowpriority", "m.favourite");
|
|
||||||
} else if (this.state.isLowPriority) {
|
|
||||||
this.setState({isLowPriority: false});
|
|
||||||
this._toggleTag(null, "m.lowpriority");
|
|
||||||
} else if (!this.state.isLowPriority) {
|
|
||||||
this.setState({isLowPriority: true});
|
|
||||||
this._toggleTag("m.lowpriority");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickDM: function() {
|
|
||||||
const newIsDirectMessage = !this.state.isDirectMessage;
|
|
||||||
this.setState({
|
|
||||||
isDirectMessage: newIsDirectMessage,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (MatrixClientPeg.get().isGuest()) return;
|
|
||||||
|
|
||||||
let newTarget;
|
|
||||||
if (newIsDirectMessage) {
|
|
||||||
const guessedTarget = Rooms.guessDMRoomTarget(
|
|
||||||
this.props.room,
|
|
||||||
this.props.room.getMember(MatrixClientPeg.get().credentials.userId),
|
|
||||||
);
|
|
||||||
newTarget = guessedTarget.userId;
|
|
||||||
} else {
|
|
||||||
newTarget = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// give some time for the user to see the icon change first, since
|
|
||||||
// this will hide the context menu once it completes
|
|
||||||
q.delay(500).done(() => {
|
|
||||||
return Rooms.setDMRoom(this.props.room.roomId, newTarget).finally(() => {
|
|
||||||
// Close the context menu
|
|
||||||
if (this.props.onFinished) {
|
|
||||||
this.props.onFinished();
|
|
||||||
};
|
|
||||||
}, (err) => {
|
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
||||||
Modal.createDialog(ErrorDialog, {
|
|
||||||
title: "Failed to set Direct Message status of room",
|
|
||||||
description: err.toString()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickLeave: function() {
|
|
||||||
// Leave room
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'leave_room',
|
|
||||||
room_id: this.props.room.roomId,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Close the context menu
|
|
||||||
if (this.props.onFinished) {
|
|
||||||
this.props.onFinished();
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClickForget: function() {
|
|
||||||
// FIXME: duplicated with RoomSettings (and dead code in RoomView)
|
|
||||||
MatrixClientPeg.get().forget(this.props.room.roomId).done(function() {
|
|
||||||
dis.dispatch({ action: 'view_next_room' });
|
|
||||||
}, function(err) {
|
|
||||||
var errCode = err.errcode || "unknown error code";
|
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
||||||
Modal.createDialog(ErrorDialog, {
|
|
||||||
title: "Error",
|
|
||||||
description: `Failed to forget room (${errCode})`
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Close the context menu
|
|
||||||
if (this.props.onFinished) {
|
|
||||||
this.props.onFinished();
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
const myUserId = MatrixClientPeg.get().credentials.userId;
|
|
||||||
const myMember = this.props.room.getMember(myUserId);
|
|
||||||
|
|
||||||
const favouriteClasses = classNames({
|
|
||||||
'mx_RoomTagContextMenu_field': true,
|
|
||||||
'mx_RoomTagContextMenu_fieldSet': this.state.isFavourite,
|
|
||||||
'mx_RoomTagContextMenu_fieldDisabled': false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const lowPriorityClasses = classNames({
|
|
||||||
'mx_RoomTagContextMenu_field': true,
|
|
||||||
'mx_RoomTagContextMenu_fieldSet': this.state.isLowPriority,
|
|
||||||
'mx_RoomTagContextMenu_fieldDisabled': false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const leaveClasses = classNames({
|
|
||||||
'mx_RoomTagContextMenu_field': true,
|
|
||||||
'mx_RoomTagContextMenu_fieldSet': false,
|
|
||||||
'mx_RoomTagContextMenu_fieldDisabled': false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const dmClasses = classNames({
|
|
||||||
'mx_RoomTagContextMenu_field': true,
|
|
||||||
'mx_RoomTagContextMenu_fieldSet': this.state.isDirectMessage,
|
|
||||||
'mx_RoomTagContextMenu_fieldDisabled': false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (myMember && myMember.membership === "leave") {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className={ leaveClasses } onClick={ this._onClickForget } >
|
|
||||||
<img className="mx_RoomTagContextMenu_icon" src="img/icon_context_delete.svg" width="15" height="15" />
|
|
||||||
Forget
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className={ favouriteClasses } onClick={this._onClickFavourite} >
|
|
||||||
<img className="mx_RoomTagContextMenu_icon" src="img/icon_context_fave.svg" width="15" height="15" />
|
|
||||||
<img className="mx_RoomTagContextMenu_icon_set" src="img/icon_context_fave_on.svg" width="15" height="15" />
|
|
||||||
Favourite
|
|
||||||
</div>
|
|
||||||
<div className={ lowPriorityClasses } onClick={this._onClickLowPriority} >
|
|
||||||
<img className="mx_RoomTagContextMenu_icon" src="img/icon_context_low.svg" width="15" height="15" />
|
|
||||||
<img className="mx_RoomTagContextMenu_icon_set" src="img/icon_context_low_on.svg" width="15" height="15" />
|
|
||||||
Low Priority
|
|
||||||
</div>
|
|
||||||
<div className={ dmClasses } onClick={this._onClickDM} >
|
|
||||||
<img className="mx_RoomTagContextMenu_icon" src="img/icon_context_person.svg" width="15" height="15" />
|
|
||||||
<img className="mx_RoomTagContextMenu_icon_set" src="img/icon_context_person_on.svg" width="15" height="15" />
|
|
||||||
Direct Chat
|
|
||||||
</div>
|
|
||||||
<hr className="mx_RoomTagContextMenu_separator" />
|
|
||||||
<div className={ leaveClasses } onClick={(myMember && myMember.membership === "join") ? this._onClickLeave : null} >
|
|
||||||
<img className="mx_RoomTagContextMenu_icon" src="img/icon_context_delete.svg" width="15" height="15" />
|
|
||||||
Leave
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
392
src/components/views/context_menus/RoomTileContextMenu.js
Normal file
392
src/components/views/context_menus/RoomTileContextMenu.js
Normal file
|
@ -0,0 +1,392 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import q from 'q';
|
||||||
|
import React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import sdk from 'matrix-react-sdk';
|
||||||
|
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||||
|
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||||
|
import DMRoomMap from 'matrix-react-sdk/lib/utils/DMRoomMap';
|
||||||
|
import * as Rooms from 'matrix-react-sdk/lib/Rooms';
|
||||||
|
import * as RoomNotifs from 'matrix-react-sdk/lib/RoomNotifs';
|
||||||
|
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
displayName: 'RoomTileContextMenu',
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
room: React.PropTypes.object.isRequired,
|
||||||
|
/* callback called when the menu is dismissed */
|
||||||
|
onFinished: React.PropTypes.func,
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
const dmRoomMap = new DMRoomMap(MatrixClientPeg.get());
|
||||||
|
return {
|
||||||
|
roomNotifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
||||||
|
isFavourite: this.props.room.tags.hasOwnProperty("m.favourite"),
|
||||||
|
isLowPriority: this.props.room.tags.hasOwnProperty("m.lowpriority"),
|
||||||
|
isDirectMessage: Boolean(dmRoomMap.getUserIdForRoomId(this.props.room.roomId)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillMount: function() {
|
||||||
|
this._unmounted = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillUnmount: function() {
|
||||||
|
this._unmounted = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_toggleTag: function(tagNameOn, tagNameOff) {
|
||||||
|
var self = this;
|
||||||
|
const roomId = this.props.room.roomId;
|
||||||
|
var cli = MatrixClientPeg.get();
|
||||||
|
if (!cli.isGuest()) {
|
||||||
|
q.delay(500).then(function() {
|
||||||
|
if (tagNameOff !== null && tagNameOff !== undefined) {
|
||||||
|
cli.deleteRoomTag(roomId, tagNameOff).finally(function() {
|
||||||
|
// Close the context menu
|
||||||
|
if (self.props.onFinished) {
|
||||||
|
self.props.onFinished();
|
||||||
|
};
|
||||||
|
}).fail(function(err) {
|
||||||
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Failed to remove tag " + tagNameOff + " from room",
|
||||||
|
description: err.toString()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagNameOn !== null && tagNameOn !== undefined) {
|
||||||
|
// If the tag ordering meta data is required, it is added by
|
||||||
|
// the RoomSubList when it sorts its rooms
|
||||||
|
cli.setRoomTag(roomId, tagNameOn, {}).finally(function() {
|
||||||
|
// Close the context menu
|
||||||
|
if (self.props.onFinished) {
|
||||||
|
self.props.onFinished();
|
||||||
|
};
|
||||||
|
}).fail(function(err) {
|
||||||
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Failed to add tag " + tagNameOn + " to room",
|
||||||
|
description: err.toString()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickFavourite: function() {
|
||||||
|
// Tag room as 'Favourite'
|
||||||
|
if (!this.state.isFavourite && this.state.isLowPriority) {
|
||||||
|
this.setState({
|
||||||
|
isFavourite: true,
|
||||||
|
isLowPriority: false,
|
||||||
|
});
|
||||||
|
this._toggleTag("m.favourite", "m.lowpriority");
|
||||||
|
} else if (this.state.isFavourite) {
|
||||||
|
this.setState({isFavourite: false});
|
||||||
|
this._toggleTag(null, "m.favourite");
|
||||||
|
} else if (!this.state.isFavourite) {
|
||||||
|
this.setState({isFavourite: true});
|
||||||
|
this._toggleTag("m.favourite");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickLowPriority: function() {
|
||||||
|
// Tag room as 'Low Priority'
|
||||||
|
if (!this.state.isLowPriority && this.state.isFavourite) {
|
||||||
|
this.setState({
|
||||||
|
isFavourite: false,
|
||||||
|
isLowPriority: true,
|
||||||
|
});
|
||||||
|
this._toggleTag("m.lowpriority", "m.favourite");
|
||||||
|
} else if (this.state.isLowPriority) {
|
||||||
|
this.setState({isLowPriority: false});
|
||||||
|
this._toggleTag(null, "m.lowpriority");
|
||||||
|
} else if (!this.state.isLowPriority) {
|
||||||
|
this.setState({isLowPriority: true});
|
||||||
|
this._toggleTag("m.lowpriority");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickDM: function() {
|
||||||
|
const newIsDirectMessage = !this.state.isDirectMessage;
|
||||||
|
this.setState({
|
||||||
|
isDirectMessage: newIsDirectMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (MatrixClientPeg.get().isGuest()) return;
|
||||||
|
|
||||||
|
Rooms.guessAndSetDMRoom(
|
||||||
|
this.props.room, newIsDirectMessage
|
||||||
|
).delay(500).finally(() => {
|
||||||
|
// Close the context menu
|
||||||
|
if (this.props.onFinished) {
|
||||||
|
this.props.onFinished();
|
||||||
|
};
|
||||||
|
}, (err) => {
|
||||||
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Failed to set Direct Message status of room",
|
||||||
|
description: err.toString()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickLeave: function() {
|
||||||
|
// Leave room
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'leave_room',
|
||||||
|
room_id: this.props.room.roomId,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the context menu
|
||||||
|
if (this.props.onFinished) {
|
||||||
|
this.props.onFinished();
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickReject: function() {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'reject_invite',
|
||||||
|
room_id: this.props.room.roomId,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the context menu
|
||||||
|
if (this.props.onFinished) {
|
||||||
|
this.props.onFinished();
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickForget: function() {
|
||||||
|
// FIXME: duplicated with RoomSettings (and dead code in RoomView)
|
||||||
|
MatrixClientPeg.get().forget(this.props.room.roomId).done(function() {
|
||||||
|
dis.dispatch({ action: 'view_next_room' });
|
||||||
|
}, function(err) {
|
||||||
|
var errCode = err.errcode || "unknown error code";
|
||||||
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Error",
|
||||||
|
description: `Failed to forget room (${errCode})`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the context menu
|
||||||
|
if (this.props.onFinished) {
|
||||||
|
this.props.onFinished();
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_saveNotifState: function(newState) {
|
||||||
|
const oldState = this.state.roomNotifState;
|
||||||
|
const roomId = this.props.room.roomId;
|
||||||
|
var cli = MatrixClientPeg.get();
|
||||||
|
|
||||||
|
if (cli.isGuest()) return;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
roomNotifState: newState,
|
||||||
|
});
|
||||||
|
RoomNotifs.setRoomNotifsState(this.props.room.roomId, newState).done(() => {
|
||||||
|
// delay slightly so that the user can see their state change
|
||||||
|
// before closing the menu
|
||||||
|
return q.delay(500).then(() => {
|
||||||
|
if (this._unmounted) return;
|
||||||
|
// Close the context menu
|
||||||
|
if (this.props.onFinished) {
|
||||||
|
this.props.onFinished();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, (error) => {
|
||||||
|
// TODO: some form of error notification to the user
|
||||||
|
// to inform them that their state change failed.
|
||||||
|
// For now we at least set the state back
|
||||||
|
if (this._unmounted) return;
|
||||||
|
this.setState({
|
||||||
|
roomNotifState: oldState,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickAlertMe: function() {
|
||||||
|
this._saveNotifState(RoomNotifs.ALL_MESSAGES_LOUD);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickAllNotifs: function() {
|
||||||
|
this._saveNotifState(RoomNotifs.ALL_MESSAGES);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickMentions: function() {
|
||||||
|
this._saveNotifState(RoomNotifs.MENTIONS_ONLY);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClickMute: function() {
|
||||||
|
this._saveNotifState(RoomNotifs.MUTE);
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderNotifMenu: function() {
|
||||||
|
var alertMeClasses = classNames({
|
||||||
|
'mx_RoomTileContextMenu_notif_field': true,
|
||||||
|
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD,
|
||||||
|
});
|
||||||
|
|
||||||
|
var allNotifsClasses = classNames({
|
||||||
|
'mx_RoomTileContextMenu_notif_field': true,
|
||||||
|
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES,
|
||||||
|
});
|
||||||
|
|
||||||
|
var mentionsClasses = classNames({
|
||||||
|
'mx_RoomTileContextMenu_notif_field': true,
|
||||||
|
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.MENTIONS_ONLY,
|
||||||
|
});
|
||||||
|
|
||||||
|
var muteNotifsClasses = classNames({
|
||||||
|
'mx_RoomTileContextMenu_notif_field': true,
|
||||||
|
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.MUTE,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="mx_RoomTileContextMenu_notif_picker" >
|
||||||
|
<img src="img/notif-slider.svg" width="20" height="107" />
|
||||||
|
</div>
|
||||||
|
<div className={ alertMeClasses } onClick={this._onClickAlertMe} >
|
||||||
|
<img className="mx_RoomTileContextMenu_notif_activeIcon" src="img/notif-active.svg" width="12" height="12" />
|
||||||
|
<img className="mx_RoomTileContextMenu_notif_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_RoomTileContextMenu_notif_activeIcon" src="img/notif-active.svg" width="12" height="12" />
|
||||||
|
<img className="mx_RoomTileContextMenu_notif_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_RoomTileContextMenu_notif_activeIcon" src="img/notif-active.svg" width="12" height="12" />
|
||||||
|
<img className="mx_RoomTileContextMenu_notif_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_RoomTileContextMenu_notif_activeIcon" src="img/notif-active.svg" width="12" height="12" />
|
||||||
|
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src="img/icon-context-mute.svg" width="16" height="12" />
|
||||||
|
Mute
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderLeaveMenu: function(membership) {
|
||||||
|
if (!membership) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let leaveClickHandler = null;
|
||||||
|
let leaveText = null;
|
||||||
|
|
||||||
|
switch (membership) {
|
||||||
|
case "join":
|
||||||
|
leaveClickHandler = this._onClickLeave;
|
||||||
|
leaveText = "Leave";
|
||||||
|
break;
|
||||||
|
case "leave":
|
||||||
|
case "ban":
|
||||||
|
leaveClickHandler = this._onClickForget;
|
||||||
|
leaveText = "Forget";
|
||||||
|
break;
|
||||||
|
case "invite":
|
||||||
|
leaveClickHandler = this._onClickReject;
|
||||||
|
leaveText = "Reject";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="mx_RoomTileContextMenu_leave" onClick={ leaveClickHandler } >
|
||||||
|
<img className="mx_RoomTileContextMenu_tag_icon" src="img/icon_context_delete.svg" width="15" height="15" />
|
||||||
|
{ leaveText }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
_renderRoomTagMenu: function() {
|
||||||
|
const favouriteClasses = classNames({
|
||||||
|
'mx_RoomTileContextMenu_tag_field': true,
|
||||||
|
'mx_RoomTileContextMenu_tag_fieldSet': this.state.isFavourite,
|
||||||
|
'mx_RoomTileContextMenu_tag_fieldDisabled': false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const lowPriorityClasses = classNames({
|
||||||
|
'mx_RoomTileContextMenu_tag_field': true,
|
||||||
|
'mx_RoomTileContextMenu_tag_fieldSet': this.state.isLowPriority,
|
||||||
|
'mx_RoomTileContextMenu_tag_fieldDisabled': false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const dmClasses = classNames({
|
||||||
|
'mx_RoomTileContextMenu_tag_field': true,
|
||||||
|
'mx_RoomTileContextMenu_tag_fieldSet': this.state.isDirectMessage,
|
||||||
|
'mx_RoomTileContextMenu_tag_fieldDisabled': false,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={ favouriteClasses } onClick={this._onClickFavourite} >
|
||||||
|
<img className="mx_RoomTileContextMenu_tag_icon" src="img/icon_context_fave.svg" width="15" height="15" />
|
||||||
|
<img className="mx_RoomTileContextMenu_tag_icon_set" src="img/icon_context_fave_on.svg" width="15" height="15" />
|
||||||
|
Favourite
|
||||||
|
</div>
|
||||||
|
<div className={ lowPriorityClasses } onClick={this._onClickLowPriority} >
|
||||||
|
<img className="mx_RoomTileContextMenu_tag_icon" src="img/icon_context_low.svg" width="15" height="15" />
|
||||||
|
<img className="mx_RoomTileContextMenu_tag_icon_set" src="img/icon_context_low_on.svg" width="15" height="15" />
|
||||||
|
Low Priority
|
||||||
|
</div>
|
||||||
|
<div className={ dmClasses } onClick={this._onClickDM} >
|
||||||
|
<img className="mx_RoomTileContextMenu_tag_icon" src="img/icon_context_person.svg" width="15" height="15" />
|
||||||
|
<img className="mx_RoomTileContextMenu_tag_icon_set" src="img/icon_context_person_on.svg" width="15" height="15" />
|
||||||
|
Direct Chat
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
const myMember = this.props.room.getMember(
|
||||||
|
MatrixClientPeg.get().credentials.userId
|
||||||
|
);
|
||||||
|
|
||||||
|
// Can't set notif level or tags on non-join rooms
|
||||||
|
if (myMember.membership !== 'join') {
|
||||||
|
return this._renderLeaveMenu(myMember.membership);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{ this._renderNotifMenu() }
|
||||||
|
<hr className="mx_RoomTileContextMenu_separator" />
|
||||||
|
{ this._renderLeaveMenu(myMember.membership) }
|
||||||
|
<hr className="mx_RoomTileContextMenu_separator" />
|
||||||
|
{ this._renderRoomTagMenu() }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
|
@ -23,6 +23,8 @@ var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||||
var DateUtils = require('matrix-react-sdk/lib/DateUtils');
|
var DateUtils = require('matrix-react-sdk/lib/DateUtils');
|
||||||
var filesize = require('filesize');
|
var filesize = require('filesize');
|
||||||
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
|
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
|
||||||
|
const Modal = require('matrix-react-sdk/lib/Modal');
|
||||||
|
const sdk = require('matrix-react-sdk');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'ImageView',
|
displayName: 'ImageView',
|
||||||
|
@ -62,19 +64,23 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onRedactClick: function() {
|
onRedactClick: function() {
|
||||||
var self = this;
|
const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
|
||||||
MatrixClientPeg.get().redactEvent(
|
Modal.createDialog(ConfirmRedactDialog, {
|
||||||
this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()
|
onFinished: (proceed) => {
|
||||||
).done(function() {
|
if (!proceed) return;
|
||||||
if (self.props.onFinished) self.props.onFinished();
|
var self = this;
|
||||||
}, function(e) {
|
MatrixClientPeg.get().redactEvent(
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()
|
||||||
// display error message stating you couldn't delete this.
|
).catch(function(e) {
|
||||||
var code = e.errcode || e.statusCode;
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createDialog(ErrorDialog, {
|
// display error message stating you couldn't delete this.
|
||||||
title: "Error",
|
var code = e.errcode || e.statusCode;
|
||||||
description: "You cannot delete this image. (" + code + ")"
|
Modal.createDialog(ErrorDialog, {
|
||||||
});
|
title: "Error",
|
||||||
|
description: "You cannot delete this image. (" + code + ")"
|
||||||
|
});
|
||||||
|
}).done();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,16 @@ limitations under the License.
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var React = require('react');
|
import React from 'react';
|
||||||
var DragSource = require('react-dnd').DragSource;
|
import {DragSource} from 'react-dnd';
|
||||||
var DropTarget = require('react-dnd').DropTarget;
|
import {DropTarget} from 'react-dnd';
|
||||||
|
|
||||||
var dis = require("matrix-react-sdk/lib/dispatcher");
|
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||||
var sdk = require('matrix-react-sdk');
|
import sdk from 'matrix-react-sdk';
|
||||||
var RoomTile = require('matrix-react-sdk/lib/components/views/rooms/RoomTile');
|
import RoomTile from 'matrix-react-sdk/lib/components/views/rooms/RoomTile';
|
||||||
|
import * as Rooms from 'matrix-react-sdk/lib/Rooms';
|
||||||
|
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a new Component, DNDRoomTile that wraps RoomTile, making it draggable.
|
* Defines a new Component, DNDRoomTile that wraps RoomTile, making it draggable.
|
||||||
|
@ -72,21 +74,49 @@ var roomTileSource = {
|
||||||
item.targetList.forceUpdate(); // as we're not using state
|
item.targetList.forceUpdate(); // as we're not using state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const prevTag = item.originalList.props.tagName;
|
||||||
|
const newTag = item.targetList.props.tagName;
|
||||||
|
|
||||||
if (monitor.didDrop() && item.targetList.props.editable) {
|
if (monitor.didDrop() && item.targetList.props.editable) {
|
||||||
|
// Evil hack to get DMs behaving
|
||||||
|
if ((prevTag === undefined && newTag === 'im.vector.fake.direct') ||
|
||||||
|
(prevTag === 'im.vector.fake.direct' && newTag === undefined)
|
||||||
|
) {
|
||||||
|
Rooms.guessAndSetDMRoom(
|
||||||
|
item.room, newTag === 'im.vector.fake.direct',
|
||||||
|
).done(() => {
|
||||||
|
item.originalList.removeRoomTile(item.room);
|
||||||
|
}, (err) => {
|
||||||
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to set direct chat tag " + err);
|
||||||
|
Modal.createDialog(ErrorDialog, {
|
||||||
|
title: "Error",
|
||||||
|
description: "Failed to set direct chat tag",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// More evilness: We will still be dealing with moving to favourites/low prio,
|
||||||
|
// but we avoid ever doing a request with 'im.vector.fake.direct`.
|
||||||
|
|
||||||
// if we moved lists, remove the old tag
|
// if we moved lists, remove the old tag
|
||||||
if (item.targetList !== item.originalList && item.originalList.props.tagName) {
|
if (prevTag && prevTag !== 'im.vector.fake.direct' &&
|
||||||
|
item.targetList !== item.originalList
|
||||||
|
) {
|
||||||
// commented out attempts to set a spinner on our target component as component is actually
|
// commented out attempts to set a spinner on our target component as component is actually
|
||||||
// the original source component being dragged, not our target. To fix we just need to
|
// the original source component being dragged, not our target. To fix we just need to
|
||||||
// move all of this to endDrop in the target instead. FIXME later.
|
// move all of this to endDrop in the target instead. FIXME later.
|
||||||
|
|
||||||
//component.state.set({ spinner: component.state.spinner ? component.state.spinner++ : 1 });
|
//component.state.set({ spinner: component.state.spinner ? component.state.spinner++ : 1 });
|
||||||
MatrixClientPeg.get().deleteRoomTag(item.room.roomId, item.originalList.props.tagName).finally(function() {
|
MatrixClientPeg.get().deleteRoomTag(item.room.roomId, prevTag).finally(function() {
|
||||||
//component.state.set({ spinner: component.state.spinner-- });
|
//component.state.set({ spinner: component.state.spinner-- });
|
||||||
}).fail(function(err) {
|
}).fail(function(err) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to remove tag " + prevTag + " from room: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to remove tag " + item.originalList.props.tagName + " from room",
|
title: "Error",
|
||||||
description: err.toString()
|
description: "Failed to remove tag " + prevTag + " from room",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -97,15 +127,18 @@ var roomTileSource = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we moved lists or the ordering changed, add the new tag
|
// if we moved lists or the ordering changed, add the new tag
|
||||||
if (item.targetList.props.tagName && (item.targetList !== item.originalList || newOrder)) {
|
if (newTag && newTag !== 'im.vector.fake.direct' &&
|
||||||
|
(item.targetList !== item.originalList || newOrder)
|
||||||
|
) {
|
||||||
//component.state.set({ spinner: component.state.spinner ? component.state.spinner++ : 1 });
|
//component.state.set({ spinner: component.state.spinner ? component.state.spinner++ : 1 });
|
||||||
MatrixClientPeg.get().setRoomTag(item.room.roomId, item.targetList.props.tagName, newOrder).finally(function() {
|
MatrixClientPeg.get().setRoomTag(item.room.roomId, newTag, newOrder).finally(function() {
|
||||||
//component.state.set({ spinner: component.state.spinner-- });
|
//component.state.set({ spinner: component.state.spinner-- });
|
||||||
}).fail(function(err) {
|
}).fail(function(err) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to add tag " + newTag + " to room: " + err);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Failed to add tag " + item.targetList.props.tagName + " to room",
|
title: "Error",
|
||||||
description: err.toString()
|
description: "Failed to add tag " + newTag + " to room",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ module.exports = React.createClass({
|
||||||
else {
|
else {
|
||||||
return (
|
return (
|
||||||
<div className="mx_RoomDropTarget">
|
<div className="mx_RoomDropTarget">
|
||||||
<div className="mx_RoomDropTarget_avatar"></div>
|
|
||||||
<div className="mx_RoomDropTarget_label">
|
<div className="mx_RoomDropTarget_label">
|
||||||
{ this.props.label }
|
{ this.props.label }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -238,9 +238,10 @@ module.exports = React.createClass({
|
||||||
self._refreshFromServer();
|
self._refreshFromServer();
|
||||||
}, function(error) {
|
}, function(error) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to change settings: " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Can't change settings",
|
title: "Error",
|
||||||
description: error.toString(),
|
description: "Failed to change settings",
|
||||||
onFinished: self._refreshFromServer
|
onFinished: self._refreshFromServer
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -307,9 +308,10 @@ module.exports = React.createClass({
|
||||||
self._refreshFromServer();
|
self._refreshFromServer();
|
||||||
}, function(error) {
|
}, function(error) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Can't update user notification settings: " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Can't update user notification settings",
|
title: "Error",
|
||||||
description: error.toString(),
|
description: "Can't update user notification settings",
|
||||||
onFinished: self._refreshFromServer
|
onFinished: self._refreshFromServer
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -348,9 +350,10 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
var onError = function(error) {
|
var onError = function(error) {
|
||||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
|
console.error("Failed to update keywords: " + error);
|
||||||
Modal.createDialog(ErrorDialog, {
|
Modal.createDialog(ErrorDialog, {
|
||||||
title: "Can't update keywords",
|
title: "Error",
|
||||||
description: error.toString(),
|
description: "Failed to update keywords",
|
||||||
onFinished: self._refreshFromServer
|
onFinished: self._refreshFromServer
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -458,8 +461,8 @@ module.exports = React.createClass({
|
||||||
'.m.rule.master': 'master',
|
'.m.rule.master': 'master',
|
||||||
|
|
||||||
// The default push rules displayed by Vector UI
|
// The default push rules displayed by Vector UI
|
||||||
// XXX: .m.rule.contains_user_name is not managed (not a fancy rule for Vector?)
|
|
||||||
'.m.rule.contains_display_name': 'vector',
|
'.m.rule.contains_display_name': 'vector',
|
||||||
|
'.m.rule.contains_user_name': 'vector',
|
||||||
'.m.rule.room_one_to_one': 'vector',
|
'.m.rule.room_one_to_one': 'vector',
|
||||||
'.m.rule.message': 'vector',
|
'.m.rule.message': 'vector',
|
||||||
'.m.rule.invite_for_me': 'vector',
|
'.m.rule.invite_for_me': 'vector',
|
||||||
|
@ -512,6 +515,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
var vectorRuleIds = [
|
var vectorRuleIds = [
|
||||||
'.m.rule.contains_display_name',
|
'.m.rule.contains_display_name',
|
||||||
|
'.m.rule.contains_user_name',
|
||||||
'_keywords',
|
'_keywords',
|
||||||
'.m.rule.room_one_to_one',
|
'.m.rule.room_one_to_one',
|
||||||
'.m.rule.message',
|
'.m.rule.message',
|
||||||
|
@ -715,20 +719,17 @@ module.exports = React.createClass({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var emailNotificationsRow;
|
const emailThreepids = this.props.threepids.filter((tp) => tp.medium === "email");
|
||||||
if (this.props.threepids.filter(function(tp) {
|
let emailNotificationsRow;
|
||||||
if (tp.medium == "email") {
|
if (emailThreepids.length === 0) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}).length == 0) {
|
|
||||||
emailNotificationsRow = <div>
|
emailNotificationsRow = <div>
|
||||||
Add an email address above to configure email notifications
|
Add an email address above to configure email notifications
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
// This only supports the first email address in your profile for now
|
// This only supports the first email address in your profile for now
|
||||||
emailNotificationsRow = this.emailNotificationsRow(
|
emailNotificationsRow = this.emailNotificationsRow(
|
||||||
this.props.threepids[0].address,
|
emailThreepids[0].address,
|
||||||
"Enable email notifications ("+this.props.threepids[0].address+")"
|
"Enable email notifications ("+emailThreepids[0].address+")"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,20 @@ class VectorPushRuleDefinition {
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// Messages containing user's display name
|
// Messages containing user's display name
|
||||||
// (skip contains_user_name which is too geeky)
|
|
||||||
".m.rule.contains_display_name": new VectorPushRuleDefinition({
|
".m.rule.contains_display_name": new VectorPushRuleDefinition({
|
||||||
kind: "override",
|
kind: "override",
|
||||||
description: "Messages containing my name",
|
description: "Messages containing my display name",
|
||||||
|
vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
|
||||||
|
on: StandardActions.ACTION_NOTIFY,
|
||||||
|
loud: StandardActions.ACTION_HIGHLIGHT_DEFAULT_SOUND,
|
||||||
|
off: StandardActions.ACTION_DISABLED
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Messages containing user's username (localpart/MXID)
|
||||||
|
".m.rule.contains_user_name": new VectorPushRuleDefinition({
|
||||||
|
kind: "override",
|
||||||
|
description: "Messages containing my user name",
|
||||||
vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
|
vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
|
||||||
on: StandardActions.ACTION_NOTIFY,
|
on: StandardActions.ACTION_NOTIFY,
|
||||||
loud: StandardActions.ACTION_HIGHLIGHT_DEFAULT_SOUND,
|
loud: StandardActions.ACTION_HIGHLIGHT_DEFAULT_SOUND,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -134,7 +135,7 @@ textarea {
|
||||||
.mx_Dialog_wrapper.mx_Dialog_spinner .mx_Dialog {
|
.mx_Dialog_wrapper.mx_Dialog_spinner .mx_Dialog {
|
||||||
width: auto;
|
width: auto;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding-left: 0px;
|
padding: 0px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +153,7 @@ textarea {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 58px;
|
padding-left: 58px;
|
||||||
|
padding-bottom: 36px;
|
||||||
width: 60%;
|
width: 60%;
|
||||||
max-width: 704px;
|
max-width: 704px;
|
||||||
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2);
|
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2);
|
||||||
|
@ -184,6 +186,17 @@ textarea {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_Dialog_cancelButton {
|
||||||
|
position: absolute;
|
||||||
|
right: 11px;
|
||||||
|
top: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dialog_cancelButton object {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_Dialog_content {
|
.mx_Dialog_content {
|
||||||
margin: 24px 58px 68px 0;
|
margin: 24px 58px 68px 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -191,10 +204,6 @@ textarea {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_Dialog_buttons {
|
|
||||||
padding-bottom: 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_Dialog button, .mx_Dialog input[type="submit"] {
|
.mx_Dialog button, .mx_Dialog input[type="submit"] {
|
||||||
border: 0px;
|
border: 0px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
@ -286,6 +295,10 @@ textarea {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_button_row {
|
||||||
|
margin-top: 69px;
|
||||||
|
}
|
||||||
|
|
||||||
.changelog_text {
|
.changelog_text {
|
||||||
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,17 +13,22 @@
|
||||||
@import "./matrix-react-sdk/structures/login/_Login.scss";
|
@import "./matrix-react-sdk/structures/login/_Login.scss";
|
||||||
@import "./matrix-react-sdk/views/avatars/_BaseAvatar.scss";
|
@import "./matrix-react-sdk/views/avatars/_BaseAvatar.scss";
|
||||||
@import "./matrix-react-sdk/views/dialogs/_BugReportDialog.scss";
|
@import "./matrix-react-sdk/views/dialogs/_BugReportDialog.scss";
|
||||||
|
@import "./matrix-react-sdk/views/dialogs/_ChatCreateOrReuseChatDialog.scss";
|
||||||
@import "./matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss";
|
@import "./matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss";
|
||||||
|
@import "./matrix-react-sdk/views/dialogs/_ConfirmUserActionDialog.scss";
|
||||||
@import "./matrix-react-sdk/views/dialogs/_EncryptedEventDialog.scss";
|
@import "./matrix-react-sdk/views/dialogs/_EncryptedEventDialog.scss";
|
||||||
@import "./matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss";
|
@import "./matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss";
|
||||||
@import "./matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss";
|
@import "./matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss";
|
||||||
@import "./matrix-react-sdk/views/elements/_AddressSelector.scss";
|
@import "./matrix-react-sdk/views/elements/_AddressSelector.scss";
|
||||||
@import "./matrix-react-sdk/views/elements/_AddressTile.scss";
|
@import "./matrix-react-sdk/views/elements/_AddressTile.scss";
|
||||||
@import "./matrix-react-sdk/views/elements/_DirectorySearchBox.scss";
|
@import "./matrix-react-sdk/views/elements/_DirectorySearchBox.scss";
|
||||||
|
@import "./matrix-react-sdk/views/elements/_Dropdown.scss";
|
||||||
@import "./matrix-react-sdk/views/elements/_MemberEventListSummary.scss";
|
@import "./matrix-react-sdk/views/elements/_MemberEventListSummary.scss";
|
||||||
@import "./matrix-react-sdk/views/elements/_ProgressBar.scss";
|
@import "./matrix-react-sdk/views/elements/_ProgressBar.scss";
|
||||||
@import "./matrix-react-sdk/views/elements/_RichText.scss";
|
@import "./matrix-react-sdk/views/elements/_RichText.scss";
|
||||||
|
@import "./matrix-react-sdk/views/login/_InteractiveAuthEntryComponents.scss";
|
||||||
@import "./matrix-react-sdk/views/login/_ServerConfig.scss";
|
@import "./matrix-react-sdk/views/login/_ServerConfig.scss";
|
||||||
|
@import "./matrix-react-sdk/views/messages/_MEmoteBody.scss";
|
||||||
@import "./matrix-react-sdk/views/messages/_MImageBody.scss";
|
@import "./matrix-react-sdk/views/messages/_MImageBody.scss";
|
||||||
@import "./matrix-react-sdk/views/messages/_MNoticeBody.scss";
|
@import "./matrix-react-sdk/views/messages/_MNoticeBody.scss";
|
||||||
@import "./matrix-react-sdk/views/messages/_MTextBody.scss";
|
@import "./matrix-react-sdk/views/messages/_MTextBody.scss";
|
||||||
|
@ -53,14 +58,14 @@
|
||||||
@import "./matrix-react-sdk/views/voip/_VideoView.scss";
|
@import "./matrix-react-sdk/views/voip/_VideoView.scss";
|
||||||
@import "./vector-web/_fonts.scss";
|
@import "./vector-web/_fonts.scss";
|
||||||
@import "./vector-web/structures/_CompatibilityPage.scss";
|
@import "./vector-web/structures/_CompatibilityPage.scss";
|
||||||
|
@import "./vector-web/structures/_HomePage.scss";
|
||||||
@import "./vector-web/structures/_LeftPanel.scss";
|
@import "./vector-web/structures/_LeftPanel.scss";
|
||||||
@import "./vector-web/structures/_RightPanel.scss";
|
@import "./vector-web/structures/_RightPanel.scss";
|
||||||
@import "./vector-web/structures/_RoomDirectory.scss";
|
@import "./vector-web/structures/_RoomDirectory.scss";
|
||||||
@import "./vector-web/structures/_RoomSubList.scss";
|
@import "./vector-web/structures/_RoomSubList.scss";
|
||||||
@import "./vector-web/structures/_ViewSource.scss";
|
@import "./vector-web/structures/_ViewSource.scss";
|
||||||
@import "./vector-web/views/context_menus/_MessageContextMenu.scss";
|
@import "./vector-web/views/context_menus/_MessageContextMenu.scss";
|
||||||
@import "./vector-web/views/context_menus/_NotificationStateContextMenu.scss";
|
@import "./vector-web/views/context_menus/_RoomTileContextMenu.scss";
|
||||||
@import "./vector-web/views/context_menus/_RoomTagContextMenu.scss";
|
|
||||||
@import "./vector-web/views/dialogs/_ChangelogDialog.scss";
|
@import "./vector-web/views/dialogs/_ChangelogDialog.scss";
|
||||||
@import "./vector-web/views/directory/_NetworkDropdown.scss";
|
@import "./vector-web/views/directory/_NetworkDropdown.scss";
|
||||||
@import "./vector-web/views/elements/_ImageView.scss";
|
@import "./vector-web/views/elements/_ImageView.scss";
|
||||||
|
|
|
@ -90,16 +90,13 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
|
||||||
/* XXX: Hack: apparently if you try to nest a flex-box
|
|
||||||
* within a non-flex-box within a flex-box, the height
|
|
||||||
* of the innermost element gets miscalculated if the
|
|
||||||
* parents are both auto. Height has to be auto here
|
|
||||||
* for RoomView to correctly fit when the Toolbar is shown.
|
|
||||||
* Ideally we'd launch straight into the RoomView at this
|
|
||||||
* point, but instead we fudge it and make the middlePanel
|
|
||||||
* flex itself.
|
|
||||||
*/
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
/* To fix https://github.com/vector-im/riot-web/issues/3298 where Safari
|
||||||
|
needed height 100% all the way down to the HomePage. Height does not
|
||||||
|
have to be auto, empirically.
|
||||||
|
*/
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MatrixChat .mx_RightPanel {
|
.mx_MatrixChat .mx_RightPanel {
|
||||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_RoomStatusBar {
|
.mx_RoomStatusBar {
|
||||||
margin-left: 65px;
|
margin-left: 65px;
|
||||||
min-height: 34px;
|
min-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* position the indicator in the same place horizontally as .mx_EventTile_avatar. */
|
/* position the indicator in the same place horizontally as .mx_EventTile_avatar. */
|
||||||
|
@ -24,7 +24,7 @@ limitations under the License.
|
||||||
padding-left: 17px;
|
padding-left: 17px;
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
margin-left: -73px;
|
margin-left: -73px;
|
||||||
margin-top: 8px;
|
margin-top: 15px;
|
||||||
float: left;
|
float: left;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -72,6 +72,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_RoomStatusBar_typingIndicatorAvatars {
|
.mx_RoomStatusBar_typingIndicatorAvatars {
|
||||||
width: 52px;
|
width: 52px;
|
||||||
|
margin-top: -1px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +103,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_RoomStatusBar_scrollDownIndicator {
|
.mx_RoomStatusBar_scrollDownIndicator {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
padding-left: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomStatusBar_unreadMessagesBar {
|
.mx_RoomStatusBar_unreadMessagesBar {
|
||||||
|
@ -112,7 +114,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_RoomStatusBar_connectionLostBar {
|
.mx_RoomStatusBar_connectionLostBar {
|
||||||
margin-top: 19px;
|
margin-top: 19px;
|
||||||
height: 58px;
|
min-height: 58px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomStatusBar_connectionLostBar img {
|
.mx_RoomStatusBar_connectionLostBar img {
|
||||||
|
@ -144,7 +146,9 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomStatusBar_typingBar {
|
.mx_RoomStatusBar_typingBar {
|
||||||
padding-top: 10px;
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
|
||||||
color: $primary-fg-color;
|
color: $primary-fg-color;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|
|
@ -206,11 +206,14 @@ hr.mx_RoomView_myReadMarker {
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomView_inCall .mx_RoomView_statusAreaBox_line {
|
.mx_RoomView_inCall .mx_RoomView_statusAreaBox_line {
|
||||||
border-top: 1px hidden;
|
margin-top: 2px;
|
||||||
|
border: none;
|
||||||
|
height: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomView_inCall .mx_MessageComposer_wrapper {
|
.mx_RoomView_inCall .mx_MessageComposer_wrapper {
|
||||||
border-top: 2px hidden;
|
border-top: 2px hidden;
|
||||||
|
padding-top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomView_inCall .mx_RoomView_statusAreaBox {
|
.mx_RoomView_inCall .mx_RoomView_statusAreaBox {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -101,6 +102,15 @@ limitations under the License.
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_UserSettings_importExportButtons {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-left: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_UserSettings_importExportButtons .mx_UserSettings_button {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_UserSettings_toggle input {
|
.mx_UserSettings_toggle input {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
@ -166,6 +176,12 @@ limitations under the License.
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.mx_UserSettings_phoneNumberField {
|
||||||
|
margin-left: 3px;
|
||||||
|
width: 172px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_UserSettings_changePasswordButton {
|
.mx_UserSettings_changePasswordButton {
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: 32px;
|
margin-right: 32px;
|
||||||
|
|
|
@ -66,6 +66,10 @@ limitations under the License.
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_Login_username {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_Login_fieldLabel {
|
.mx_Login_fieldLabel {
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -163,3 +167,16 @@ limitations under the License.
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_Login_phoneSection {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Login_phoneCountry {
|
||||||
|
display: table-cell;
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Login_phoneNumberField {
|
||||||
|
width: 210px;
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_BaseAvatar_initial {
|
.mx_BaseAvatar_initial {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
|
||||||
color: $avatar-initial-color;
|
color: $avatar-initial-color;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
speak: none;
|
speak: none;
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_ChatCreateOrReuseDialog .mx_ChatCreateOrReuseDialog_tiles {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_ChatCreateOrReuseDialog .mx_Dialog_content {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_ChatCreateOrReuseDialog .mx_RoomTile_badge {
|
||||||
|
display: none;
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 Vector Creations Ltd.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
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_ConfirmUserActionDialog .mx_Dialog_content {
|
||||||
|
min-height: 48px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_ConfirmUserActionDialog_avatar {
|
||||||
|
float: left;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_ConfirmUserActionDialog_name {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_ConfirmUserActionDialog_userId {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_ConfirmUserActionDialog_reasonField {
|
||||||
|
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: $primary-fg-color;
|
||||||
|
|
||||||
|
border-radius: 3px;
|
||||||
|
border: solid 1px $input-border-color;
|
||||||
|
line-height: 36px;
|
||||||
|
padding-left: 16px;
|
||||||
|
padding-right: 16px;
|
||||||
|
padding-top: 1px;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
width: 90%;
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
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_Dropdown {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dropdown_input {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid $strong-input-border-color;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 13px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dropdown_arrow {
|
||||||
|
border-color: $primary-fg-color transparent transparent;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 5px 5px 0;
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 14px;
|
||||||
|
width: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dropdown_option {
|
||||||
|
height: 35px;
|
||||||
|
line-height: 35px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dropdown_option img {
|
||||||
|
margin: 5px;
|
||||||
|
width: 25px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.mx_Dropdown_option, input.mx_Dropdown_option:focus {
|
||||||
|
border: 0;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
// XXX: hack to prevent text box being too big and pushing
|
||||||
|
// its parent out / overlapping the dropdown arrow. Only really
|
||||||
|
// works in the Country dropdown.
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dropdown_menu {
|
||||||
|
position: absolute;
|
||||||
|
left: -1px;
|
||||||
|
right: -1px;
|
||||||
|
top: 100%;
|
||||||
|
z-index: 2;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid $accent-color;
|
||||||
|
background-color: $primary-bg-color;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dropdown_menu .mx_Dropdown_option_highlight {
|
||||||
|
background-color: $focus-bg-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dropdown_menu {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Dropdown_searchPrompt {
|
||||||
|
font-weight: normal;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,10 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.mx_MemberEventListSummary {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_TextualEvent.mx_MemberEventListSummary_summary {
|
.mx_TextualEvent.mx_MemberEventListSummary_summary {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +35,15 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MemberEventListSummary_toggle {
|
.mx_MemberEventListSummary_toggle {
|
||||||
color:$accent-color;
|
color: $accent-color;
|
||||||
cursor:pointer;
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_MemberEventListSummary_line {
|
||||||
|
border-bottom: 1px solid $primary-hairline-color;
|
||||||
|
margin-left: 63px;
|
||||||
|
line-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// XXX: bleurgh, what is this? These classes totally break the component
|
||||||
|
// naming scheme; it's completely unclear where or how they're being used
|
||||||
|
// --Matthew
|
||||||
|
|
||||||
.mx_UserPill {
|
.mx_UserPill {
|
||||||
color: white;
|
color: white;
|
||||||
background-color: $accent-color;
|
background-color: $accent-color;
|
||||||
|
@ -25,13 +29,13 @@
|
||||||
padding: .2em 0;
|
padding: .2em 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 85%;
|
font-size: 85%;
|
||||||
background-color: rgba(0,0,0,.04);
|
background-color: $rte-code-bg-color;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_Markdown_HR {
|
.mx_Markdown_HR {
|
||||||
display: block;
|
display: block;
|
||||||
background: #e7e7e7;
|
background: $rte-bg-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_Markdown_STRIKETHROUGH {
|
.mx_Markdown_STRIKETHROUGH {
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
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_InteractiveAuthEntryComponents_msisdnWrapper {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_InteractiveAuthEntryComponents_msisdnEntry {
|
||||||
|
font-size: 200%;
|
||||||
|
font-weight: bold;
|
||||||
|
border: 1px solid $strong-input-border-color;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: 6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_InteractiveAuthEntryComponents_msisdnEntry:focus {
|
||||||
|
border: 1px solid $accent-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_InteractiveAuthEntryComponents_msisdnSubmit {
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: This should be a common button class
|
||||||
|
.mx_InteractiveAuthEntryComponents_msisdnSubmit:disabled {
|
||||||
|
background-color: $light-fg-color;
|
||||||
|
cursor: default;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 Vector Creations Ltd.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
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_MEmoteBody_sender {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
|
@ -130,6 +130,23 @@ limitations under the License.
|
||||||
color: $event-notsent-color;
|
color: $event-notsent-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_EventTile_redacted .mx_EventTile_line .mx_UnknownBody {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 36px;
|
||||||
|
background-image: $event-redacted-img;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_EventTile.mx_EventTile_redacted .mx_EventTile_line {
|
||||||
|
/*
|
||||||
|
Prevent changing colour of the background because
|
||||||
|
$event-redacted-img matches $primary-bg-color
|
||||||
|
*/
|
||||||
|
background-color: initial !important;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_EventTile_highlight,
|
.mx_EventTile_highlight,
|
||||||
.mx_EventTile_highlight .markdown-body
|
.mx_EventTile_highlight .markdown-body
|
||||||
{
|
{
|
||||||
|
@ -251,6 +268,12 @@ limitations under the License.
|
||||||
padding-left: 60px;
|
padding-left: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_EventTile_selected.mx_EventTile_info .mx_EventTile_line,
|
||||||
|
.mx_EventTile:hover.mx_EventTile_verified.mx_EventTile_info .mx_EventTile_line,
|
||||||
|
.mx_EventTile:hover.mx_EventTile_unverified.mx_EventTile_info .mx_EventTile_line {
|
||||||
|
padding-left: 78px;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line {
|
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line {
|
||||||
border-left: $e2e-verified-color 5px solid;
|
border-left: $e2e-verified-color 5px solid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ limitations under the License.
|
||||||
.mx_LinkPreviewWidget_title {
|
.mx_LinkPreviewWidget_title {
|
||||||
display: inline;
|
display: inline;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_LinkPreviewWidget_siteName {
|
.mx_LinkPreviewWidget_siteName {
|
||||||
|
|
|
@ -48,11 +48,10 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MemberInfo_avatar .mx_BaseAvatar {
|
.mx_MemberInfo_avatar .mx_BaseAvatar {
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MemberInfo_avatar .mx_BaseAvatar.mx_BaseAvatar_image {
|
.mx_MemberInfo_avatar .mx_BaseAvatar.mx_BaseAvatar_image {
|
||||||
cursor: pointer;
|
cursor: zoom-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MemberInfo_profile {
|
.mx_MemberInfo_profile {
|
||||||
|
|
|
@ -28,7 +28,7 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MemberList .mx_Spinner {
|
.mx_MemberList .mx_Spinner {
|
||||||
flex: 0;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_MemberList_chevron {
|
.mx_MemberList_chevron {
|
||||||
|
|
|
@ -22,6 +22,8 @@ limitations under the License.
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
background-color: $preview-bar-bg-color;
|
||||||
|
-webkit-align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomPreviewBar_wrapper {
|
.mx_RoomPreviewBar_wrapper {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -20,6 +21,7 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomSettings_leaveButton,
|
.mx_RoomSettings_leaveButton,
|
||||||
|
.mx_RoomSettings_unbanButton,
|
||||||
.mx_RoomSettings_integrationsButton,
|
.mx_RoomSettings_integrationsButton,
|
||||||
.mx_RoomSettings_integrationsButton_error {
|
.mx_RoomSettings_integrationsButton_error {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -30,11 +32,15 @@ limitations under the License.
|
||||||
color: $accent-fg-color;
|
color: $accent-fg-color;
|
||||||
line-height: 34px;
|
line-height: 34px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
float: right;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
}
|
}
|
||||||
|
.mx_RoomSettings_leaveButton,
|
||||||
|
.mx_RoomSettings_integrationsButton,
|
||||||
|
.mx_RoomSettings_integrationsButton_error {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
.mx_RoomSettings_integrationsButton_error {
|
.mx_RoomSettings_integrationsButton_error {
|
||||||
pointer: not-allowed;
|
pointer: not-allowed;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +56,9 @@ limitations under the License.
|
||||||
background-color: $accent-color;
|
background-color: $accent-color;
|
||||||
color: $accent-fg-color;
|
color: $accent-fg-color;
|
||||||
}
|
}
|
||||||
|
.mx_RoomSettings_unbanButton {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_RoomSettings_e2eIcon {
|
.mx_RoomSettings_e2eIcon {
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
|
@ -227,4 +236,4 @@ limitations under the License.
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,41 +59,6 @@ limitations under the License.
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomTile:hover .mx_RoomTile_avatar_container:before,
|
|
||||||
.mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:before {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
content: "";
|
|
||||||
border-radius: 40px;
|
|
||||||
background-image: url("../../img/icons_ellipsis.svg");
|
|
||||||
background-size: 25px;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
z-index: 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTile:hover .mx_RoomTile_avatar_container:after,
|
|
||||||
.mx_RoomTile_avatar_container.mx_RoomTile_avatar_roomTagMenu:after {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
content: "";
|
|
||||||
border-radius: 40px;
|
|
||||||
background: $primary-fg-color;
|
|
||||||
bottom: 0;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
opacity: 0.6;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsed .mx_RoomTile:hover .mx_RoomTile_avatar_container:after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTile_name {
|
.mx_RoomTile_name {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -164,13 +129,13 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomTile .mx_RoomTile_badge.mx_RoomTile_badgeButton,
|
.mx_RoomTile .mx_RoomTile_badge.mx_RoomTile_badgeButton,
|
||||||
.mx_RoomTile.mx_RoomTile_notificationStateMenu .mx_RoomTile_badge {
|
.mx_RoomTile.mx_RoomTile_menuDisplayed .mx_RoomTile_badge {
|
||||||
letter-spacing: 0.1em;
|
letter-spacing: 0.1em;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomTile.mx_RoomTile_noBadges .mx_RoomTile_badge.mx_RoomTile_badgeButton,
|
.mx_RoomTile.mx_RoomTile_noBadges .mx_RoomTile_badge.mx_RoomTile_badgeButton,
|
||||||
.mx_RoomTile.mx_RoomTile_notificationStateMenu.mx_RoomTile_noBadges .mx_RoomTile_badge {
|
.mx_RoomTile.mx_RoomTile_menuDisplayed.mx_RoomTile_noBadges .mx_RoomTile_badge {
|
||||||
background-color: $neutral-badge-color;
|
background-color: $neutral-badge-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,17 @@ limitations under the License.
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
border-bottom: 1px solid $primary-hairline-color;
|
border-bottom: 1px solid $primary-hairline-color;
|
||||||
|
|
||||||
|
/* in absence of img */
|
||||||
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_TopUnreadMessagesBar_scrollUp {
|
.mx_TopUnreadMessagesBar_scrollUp {
|
||||||
display: inline;
|
display: inline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
/* in absence of img */
|
||||||
|
padding-left: 65px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_TopUnreadMessagesBar_scrollUp img {
|
.mx_TopUnreadMessagesBar_scrollUp img {
|
||||||
|
|
|
@ -24,7 +24,7 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_IntegrationsManager iframe {
|
.mx_IntegrationsManager iframe {
|
||||||
background-color: $primary-bg-color;
|
background-color: #fff;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -18,6 +18,8 @@ $selection-fg-color: $primary-bg-color;
|
||||||
// red warning colour
|
// red warning colour
|
||||||
$warning-color: #ff0064;
|
$warning-color: #ff0064;
|
||||||
|
|
||||||
|
$preview-bar-bg-color: #f7f7f7;
|
||||||
|
|
||||||
// left-panel style muted accent color
|
// left-panel style muted accent color
|
||||||
$secondary-accent-color: #eaf5f0;
|
$secondary-accent-color: #eaf5f0;
|
||||||
|
|
||||||
|
@ -72,6 +74,9 @@ $settings-grey-fg-color: #a2a2a2;
|
||||||
$voip-decline-color: #f48080;
|
$voip-decline-color: #f48080;
|
||||||
$voip-accept-color: #80f480;
|
$voip-accept-color: #80f480;
|
||||||
|
|
||||||
|
$rte-bg-color: #e9e9e9;
|
||||||
|
$rte-code-bg-color: rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
// ********************
|
// ********************
|
||||||
|
|
||||||
$roomtile-name-color: rgba(69, 69, 69, 0.8);
|
$roomtile-name-color: rgba(69, 69, 69, 0.8);
|
||||||
|
@ -88,6 +93,9 @@ $event-encrypting-color: #abddbc;
|
||||||
$event-sending-color: #ddd;
|
$event-sending-color: #ddd;
|
||||||
$event-notsent-color: #f44;
|
$event-notsent-color: #f44;
|
||||||
|
|
||||||
|
// event redaction
|
||||||
|
$event-redacted-img: url('../../img/redacted.jpg');
|
||||||
|
|
||||||
// event timestamp
|
// event timestamp
|
||||||
$event-timestamp-color: #acacac;
|
$event-timestamp-color: #acacac;
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,13 @@ $light-fg-color: #747474;
|
||||||
$accent-fg-color: $primary-bg-color;
|
$accent-fg-color: $primary-bg-color;
|
||||||
$accent-color: #76CFA6;
|
$accent-color: #76CFA6;
|
||||||
|
|
||||||
$selection-fg-color: $primary-bg-color;
|
$selection-fg-color: $primary-fg-color;
|
||||||
|
|
||||||
// red warning colour
|
// red warning colour
|
||||||
$warning-color: #ff0064;
|
$warning-color: #ff0064;
|
||||||
|
|
||||||
|
$preview-bar-bg-color: #333;
|
||||||
|
|
||||||
// left-panel style muted accent color
|
// left-panel style muted accent color
|
||||||
$secondary-accent-color: $primary-bg-color;
|
$secondary-accent-color: $primary-bg-color;
|
||||||
|
|
||||||
|
@ -28,7 +30,7 @@ $plinth-bg-color: #474747;
|
||||||
$droptarget-bg-color: rgba(45,45,45,0.5);
|
$droptarget-bg-color: rgba(45,45,45,0.5);
|
||||||
|
|
||||||
// used by AddressSelector
|
// used by AddressSelector
|
||||||
$selected-color: #eaf5f0;
|
$selected-color: #000000;
|
||||||
|
|
||||||
// selected for hoverover & selected event tiles
|
// selected for hoverover & selected event tiles
|
||||||
$event-selected-color: #353535;
|
$event-selected-color: #353535;
|
||||||
|
@ -72,6 +74,9 @@ $settings-grey-fg-color: #a2a2a2;
|
||||||
$voip-decline-color: #f48080;
|
$voip-decline-color: #f48080;
|
||||||
$voip-accept-color: #80f480;
|
$voip-accept-color: #80f480;
|
||||||
|
|
||||||
|
$rte-bg-color: #353535;
|
||||||
|
$rte-code-bg-color: #000;
|
||||||
|
|
||||||
// ********************
|
// ********************
|
||||||
|
|
||||||
$roomtile-name-color: rgba(186, 186, 186, 0.8);
|
$roomtile-name-color: rgba(186, 186, 186, 0.8);
|
||||||
|
@ -85,9 +90,12 @@ $roomsublist-label-bg-color: #454545;
|
||||||
|
|
||||||
// event tile lifecycle
|
// event tile lifecycle
|
||||||
$event-encrypting-color: rgba(171, 221, 188, 0.4);
|
$event-encrypting-color: rgba(171, 221, 188, 0.4);
|
||||||
$event-sending-color: #ddd;
|
$event-sending-color: #888;
|
||||||
$event-notsent-color: #f44;
|
$event-notsent-color: #f44;
|
||||||
|
|
||||||
|
// event redaction
|
||||||
|
$event-redacted-img: url('../../img/redacted-dark.jpg');
|
||||||
|
|
||||||
// event timestamp
|
// event timestamp
|
||||||
$event-timestamp-color: #acacac;
|
$event-timestamp-color: #acacac;
|
||||||
|
|
||||||
|
@ -110,18 +118,30 @@ $progressbar-color: #000;
|
||||||
// better match the theme. Typically applied to dark grey 'off' buttons or
|
// better match the theme. Typically applied to dark grey 'off' buttons or
|
||||||
// light grey 'on' buttons.
|
// light grey 'on' buttons.
|
||||||
.mx_filterFlipColor {
|
.mx_filterFlipColor {
|
||||||
filter: invert();
|
filter: invert(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.gm-scrollbar .thumb {
|
.gm-scrollbar .thumb {
|
||||||
filter: invert();
|
filter: invert(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile_content .markdown-body pre,
|
// markdown overrides:
|
||||||
.mx_EventTile_content .markdown-body code {
|
.mx_EventTile_content .markdown-body {
|
||||||
filter: invert();
|
pre, code {
|
||||||
}
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
|
||||||
.mx_EventTile_content .markdown-body pre code {
|
pre code {
|
||||||
filter: none;
|
filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
tr {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(2n) {
|
||||||
|
background-color: #080808;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
34
src/skins/vector/css/vector-web/structures/_HomePage.scss
Normal file
34
src/skins/vector/css/vector-web/structures/_HomePage.scss
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
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_HomePage {
|
||||||
|
max-width: 960px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
.mx_HomePage iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 90%;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_HomePage_body {
|
||||||
|
margin-left: 63px;
|
||||||
|
}
|
|
@ -64,6 +64,7 @@ limitations under the License.
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_LeftPanel .mx_BottomLeftMenu_homePage,
|
||||||
.mx_LeftPanel .mx_BottomLeftMenu_directory,
|
.mx_LeftPanel .mx_BottomLeftMenu_directory,
|
||||||
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
|
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
|
||||||
.mx_LeftPanel .mx_BottomLeftMenu_people,
|
.mx_LeftPanel .mx_BottomLeftMenu_people,
|
||||||
|
@ -72,6 +73,7 @@ limitations under the License.
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collapsed .mx_BottomLeftMenu_homePage,
|
||||||
.collapsed .mx_BottomLeftMenu_directory,
|
.collapsed .mx_BottomLeftMenu_directory,
|
||||||
.collapsed .mx_BottomLeftMenu_createRoom,
|
.collapsed .mx_BottomLeftMenu_createRoom,
|
||||||
.collapsed .mx_BottomLeftMenu_people,
|
.collapsed .mx_BottomLeftMenu_people,
|
||||||
|
@ -81,6 +83,7 @@ limitations under the License.
|
||||||
padding-bottom: 3px ! important;
|
padding-bottom: 3px ! important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_LeftPanel .mx_BottomLeftMenu_homePage,
|
||||||
.mx_LeftPanel .mx_BottomLeftMenu_directory,
|
.mx_LeftPanel .mx_BottomLeftMenu_directory,
|
||||||
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
|
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
|
||||||
.mx_LeftPanel .mx_BottomLeftMenu_people {
|
.mx_LeftPanel .mx_BottomLeftMenu_people {
|
||||||
|
|
|
@ -42,7 +42,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_RightPanel_headerButton {
|
.mx_RightPanel_headerButton {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
flex: 0;
|
flex: 0 0 auto;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.mx_NotificationStateContextMenu_picker {
|
|
||||||
position: absolute;
|
|
||||||
top: 16px;
|
|
||||||
left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_NotificationStateContextMenu_field {
|
|
||||||
padding-top: 4px;
|
|
||||||
padding-right: 6px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
padding-left: 8px; /* 20px */
|
|
||||||
cursor: pointer;
|
|
||||||
white-space: nowrap;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_NotificationStateContextMenu_field.mx_NotificationStateContextMenu_fieldSet {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_NotificationStateContextMenu_field.mx_NotificationStateContextMenu_fieldDisabled {
|
|
||||||
color: rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_NotificationStateContextMenu_icon {
|
|
||||||
padding-right: 4px;
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_NotificationStateContextMenu_activeIcon {
|
|
||||||
display: inline-block;
|
|
||||||
opacity: 0;
|
|
||||||
position: relative;
|
|
||||||
left: -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_NotificationStateContextMenu_fieldSet .mx_NotificationStateContextMenu_activeIcon {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_field {
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-right: 20px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
white-space: nowrap;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
line-height: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_field:first-child {
|
|
||||||
padding-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_field:last-child {
|
|
||||||
padding-bottom: 4px;
|
|
||||||
color: $warning-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldSet {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldSet .mx_RoomTagContextMenu_icon {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldSet .mx_RoomTagContextMenu_icon_set {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_field.mx_RoomTagContextMenu_fieldDisabled {
|
|
||||||
color: rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_icon {
|
|
||||||
padding-right: 8px;
|
|
||||||
padding-left: 4px;
|
|
||||||
display: inline-block
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_icon_set {
|
|
||||||
padding-right: 8px;
|
|
||||||
padding-left: 4px;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_separator {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
border-bottom-style: none;
|
|
||||||
border-left-style: none;
|
|
||||||
border-right-style: none;
|
|
||||||
border-top-style: solid;
|
|
||||||
border-top-width: 1px;
|
|
||||||
border-color: $menu-border-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomTagContextMenu_fieldSet .mx_RoomTagContextMenu_icon {
|
|
||||||
/* Something to indicate that the icon is the set tag */
|
|
||||||
}
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_tag_field, .mx_RoomTileContextMenu_leave {
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-right: 20px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet .mx_RoomTileContextMenu_tag_icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldSet .mx_RoomTileContextMenu_tag_icon_set {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_tag_field.mx_RoomTileContextMenu_tag_fieldDisabled {
|
||||||
|
color: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_tag_icon {
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-left: 4px;
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_tag_icon_set {
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-left: 4px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_separator {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom-style: none;
|
||||||
|
border-left-style: none;
|
||||||
|
border-right-style: none;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 1px;
|
||||||
|
border-color: $menu-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_leave {
|
||||||
|
color: $warning-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_tag_fieldSet .mx_RoomTileContextMenu_tag_icon {
|
||||||
|
/* Something to indicate that the icon is the set tag */
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_notif_picker {
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_notif_field {
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-right: 6px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-left: 8px; /* 20px */
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_notif_field.mx_RoomTileContextMenu_notif_fieldSet {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_notif_field.mx_RoomTileContextMenu_notif_fieldDisabled {
|
||||||
|
color: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_notif_icon {
|
||||||
|
padding-right: 4px;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_notif_activeIcon {
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 0;
|
||||||
|
position: relative;
|
||||||
|
left: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_RoomTileContextMenu_notif_fieldSet .mx_RoomTileContextMenu_notif_activeIcon {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
|
@ -44,6 +44,9 @@ limitations under the License.
|
||||||
line-height: 35px;
|
line-height: 35px;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_NetworkDropdown_networkoption img {
|
.mx_NetworkDropdown_networkoption img {
|
||||||
|
|
|
@ -38,21 +38,12 @@ limitations under the License.
|
||||||
padding-bottom: 1px;
|
padding-bottom: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomDropTarget_avatar {
|
|
||||||
background-color: $primary-bg-color;
|
|
||||||
border-radius: 24px;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
float: left;
|
|
||||||
margin-left: 7px;
|
|
||||||
margin-right: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomDropTarget_label {
|
.mx_RoomDropTarget_label {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
line-height: 21px;
|
line-height: 21px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsed .mx_RoomDropTarget_avatar {
|
.collapsed .mx_RoomDropTarget_avatar {
|
||||||
|
|
27
src/skins/vector/img/icons-home.svg
Normal file
27
src/skins/vector/img/icons-home.svg
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?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" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 25 25" style="enable-background:new 0 0 25 25;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st1{fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||||
|
</style>
|
||||||
|
<g id="Layer_1">
|
||||||
|
<title>81230A28-D944-4572-B5DB-C03CAA2B1FCA</title>
|
||||||
|
<desc>Created with sketchtool.</desc>
|
||||||
|
<g id="Symbols">
|
||||||
|
<g id="Left-nav-default" transform="translate(-50.000000, -725.000000)">
|
||||||
|
<g id="Left-panel">
|
||||||
|
<g>
|
||||||
|
<g id="icons_people" transform="translate(50.000000, 725.000000)">
|
||||||
|
<path id="Oval-1-Copy-7" fill="#76cfa6" d="M12.5,25C19.4,25,25,19.4,25,12.5S19.4,0,12.5,0S0,5.6,0,12.5S5.6,25,12.5,25z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Layer_2">
|
||||||
|
<rect x="7.8" y="10.7" class="st1" stroke="#ffffff" width="9.4" height="7.4"/>
|
||||||
|
<polygon class="st1" stroke="#ffffff" points="12.5,6 6.2,10.7 18.8,10.7 "/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/skins/vector/img/redacted-dark.jpg
Normal file
BIN
src/skins/vector/img/redacted-dark.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
src/skins/vector/img/redacted.jpg
Normal file
BIN
src/skins/vector/img/redacted.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
|
@ -37,8 +37,19 @@
|
||||||
<body style="height: 100%;">
|
<body style="height: 100%;">
|
||||||
<section id="matrixchat" style="height: 100%;"></section>
|
<section id="matrixchat" style="height: 100%;"></section>
|
||||||
<noscript>Sorry, Riot requires JavaScript to be enabled.</noscript>
|
<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>
|
// Not a particularly graceful way of not putting the indexeddb worker script
|
||||||
|
// into the main page
|
||||||
|
if (_.endsWith(htmlWebpackPlugin.files.js[i], 'indexeddb-worker.js')) {
|
||||||
|
%>
|
||||||
|
<script>
|
||||||
|
window.vector_indexeddb_worker_script = '<%= htmlWebpackPlugin.files.js[i] %>';
|
||||||
|
</script>
|
||||||
|
<%
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
<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;"/>
|
<img src="img/warning.svg" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||||
<audio id="messageAudio">
|
<audio id="messageAudio">
|
||||||
|
@ -62,24 +73,5 @@
|
||||||
<source src="media/busy.mp3" type="audio/mpeg" />
|
<source src="media/busy.mp3" type="audio/mpeg" />
|
||||||
</audio>
|
</audio>
|
||||||
<audio id="remoteAudio"/>
|
<audio id="remoteAudio"/>
|
||||||
<script>
|
|
||||||
if (
|
|
||||||
window.location.host === 'www.vector.im' ||
|
|
||||||
window.location.host === 'vector.im' ||
|
|
||||||
window.location.host === 'www.riot.im' ||
|
|
||||||
window.location.host === 'riot.im'
|
|
||||||
) {
|
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
||||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
|
||||||
|
|
||||||
ga('create', 'UA-54779209-2', 'auto');
|
|
||||||
ga('send', 'pageview', window.location.pathname + window.location.search + window.location.hash);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var ga = null;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2015, 2016 OpenMarket Ltd
|
Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -49,7 +50,7 @@ rageshake.init().then(() => {
|
||||||
// access via the console
|
// access via the console
|
||||||
global.React = require("react");
|
global.React = require("react");
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
global.ReactPerf = require("react-addons-perf");
|
global.Perf = require("react-addons-perf");
|
||||||
}
|
}
|
||||||
|
|
||||||
var RunModernizrTests = require("./modernizr"); // this side-effects a global
|
var RunModernizrTests = require("./modernizr"); // this side-effects a global
|
||||||
|
@ -67,11 +68,15 @@ import url from 'url';
|
||||||
import {parseQs, parseQsFromFragment} from './url_utils';
|
import {parseQs, parseQsFromFragment} from './url_utils';
|
||||||
import Platform from './platform';
|
import Platform from './platform';
|
||||||
|
|
||||||
|
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||||
|
|
||||||
var lastLocationHashSet = null;
|
var lastLocationHashSet = null;
|
||||||
|
|
||||||
var CallHandler = require("matrix-react-sdk/lib/CallHandler");
|
var CallHandler = require("matrix-react-sdk/lib/CallHandler");
|
||||||
CallHandler.setConferenceHandler(VectorConferenceHandler);
|
CallHandler.setConferenceHandler(VectorConferenceHandler);
|
||||||
|
|
||||||
|
MatrixClientPeg.setIndexedDbWorkerScript(window.vector_indexeddb_worker_script);
|
||||||
|
|
||||||
function checkBrowserFeatures(featureList) {
|
function checkBrowserFeatures(featureList) {
|
||||||
if (!window.Modernizr) {
|
if (!window.Modernizr) {
|
||||||
console.error("Cannot check features - Modernizr global is missing.");
|
console.error("Cannot check features - Modernizr global is missing.");
|
||||||
|
@ -101,15 +106,24 @@ var validBrowser = checkBrowserFeatures([
|
||||||
"objectfit"
|
"objectfit"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Parse the given window.location and return parameters that can be used when calling
|
||||||
|
// MatrixChat.showScreen(screen, params)
|
||||||
|
function getScreenFromLocation(location) {
|
||||||
|
const fragparts = parseQsFromFragment(location);
|
||||||
|
return {
|
||||||
|
screen: fragparts.location.substring(1),
|
||||||
|
params: fragparts.params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Here, we do some crude URL analysis to allow
|
// Here, we do some crude URL analysis to allow
|
||||||
// deep-linking.
|
// deep-linking.
|
||||||
function routeUrl(location) {
|
function routeUrl(location) {
|
||||||
if (!window.matrixChat) return;
|
if (!window.matrixChat) return;
|
||||||
|
|
||||||
console.log("Routing URL "+location);
|
console.log("Routing URL ", location.href);
|
||||||
var fragparts = parseQsFromFragment(location);
|
const s = getScreenFromLocation(location);
|
||||||
window.matrixChat.showScreen(fragparts.location.substring(1),
|
window.matrixChat.showScreen(s.screen, s.params);
|
||||||
fragparts.params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onHashChange(ev) {
|
function onHashChange(ev) {
|
||||||
|
@ -120,23 +134,13 @@ function onHashChange(ev) {
|
||||||
routeUrl(window.location);
|
routeUrl(window.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
var loaded = false;
|
|
||||||
var lastLoadedScreen = null;
|
|
||||||
|
|
||||||
// This will be called whenever the SDK changes screens,
|
// This will be called whenever the SDK changes screens,
|
||||||
// so a web page can update the URL bar appropriately.
|
// so a web page can update the URL bar appropriately.
|
||||||
var onNewScreen = function(screen) {
|
var onNewScreen = function(screen) {
|
||||||
console.log("newscreen "+screen);
|
console.log("newscreen "+screen);
|
||||||
// just remember the most recent screen while we are loading, so that the
|
var hash = '#/' + screen;
|
||||||
// user doesn't see the URL bar doing a dance
|
lastLocationHashSet = hash;
|
||||||
if (!loaded) {
|
window.location.hash = hash;
|
||||||
lastLoadedScreen = screen;
|
|
||||||
} else {
|
|
||||||
var hash = '#/' + screen;
|
|
||||||
lastLocationHashSet = hash;
|
|
||||||
window.location.hash = hash;
|
|
||||||
if (ga) ga('send', 'pageview', window.location.pathname + window.location.search + window.location.hash);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use this to work out what URL the SDK should
|
// We use this to work out what URL the SDK should
|
||||||
|
@ -148,16 +152,30 @@ var onNewScreen = function(screen) {
|
||||||
// If we're in electron, we should never pass through a file:// URL otherwise
|
// If we're in electron, we should never pass through a file:// URL otherwise
|
||||||
// the identity server will try to 302 the browser to it, which breaks horribly.
|
// the identity server will try to 302 the browser to it, which breaks horribly.
|
||||||
// so in that instance, hardcode to use riot.im/app for now instead.
|
// so in that instance, hardcode to use riot.im/app for now instead.
|
||||||
var makeRegistrationUrl = function() {
|
var makeRegistrationUrl = function(params) {
|
||||||
|
let url;
|
||||||
if (window.location.protocol === "file:") {
|
if (window.location.protocol === "file:") {
|
||||||
return 'https://riot.im/app/#/register';
|
url = 'https://riot.im/app/#/register';
|
||||||
|
} else {
|
||||||
|
url = (
|
||||||
|
window.location.protocol + '//' +
|
||||||
|
window.location.host +
|
||||||
|
window.location.pathname +
|
||||||
|
'#/register'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return window.location.protocol + '//' +
|
const keys = Object.keys(params);
|
||||||
window.location.host +
|
for (let i = 0; i < keys.length; ++i) {
|
||||||
window.location.pathname +
|
if (i == 0) {
|
||||||
'#/register';
|
url += '?';
|
||||||
|
} else {
|
||||||
|
url += '&';
|
||||||
|
}
|
||||||
|
const k = keys[i];
|
||||||
|
url += k + '=' + encodeURIComponent(params[k]);
|
||||||
}
|
}
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('hashchange', onHashChange);
|
window.addEventListener('hashchange', onHashChange);
|
||||||
|
@ -254,31 +272,22 @@ async function loadApp() {
|
||||||
} else if (validBrowser) {
|
} else if (validBrowser) {
|
||||||
UpdateChecker.start();
|
UpdateChecker.start();
|
||||||
|
|
||||||
var MatrixChat = sdk.getComponent('structures.MatrixChat');
|
const MatrixChat = sdk.getComponent('structures.MatrixChat');
|
||||||
|
|
||||||
window.matrixChat = ReactDOM.render(
|
window.matrixChat = ReactDOM.render(
|
||||||
<MatrixChat
|
<MatrixChat
|
||||||
onNewScreen={onNewScreen}
|
onNewScreen={onNewScreen}
|
||||||
registrationUrl={makeRegistrationUrl()}
|
makeRegistrationUrl={makeRegistrationUrl}
|
||||||
ConferenceHandler={VectorConferenceHandler}
|
ConferenceHandler={VectorConferenceHandler}
|
||||||
config={configJson}
|
config={configJson}
|
||||||
realQueryParams={params}
|
realQueryParams={params}
|
||||||
startingFragmentQueryParams={fragparts.params}
|
startingFragmentQueryParams={fragparts.params}
|
||||||
enableGuest={true}
|
enableGuest={true}
|
||||||
onLoadCompleted={onLoadCompleted}
|
onLoadCompleted={onLoadCompleted}
|
||||||
|
initialScreenAfterLogin={getScreenFromLocation(window.location)}
|
||||||
defaultDeviceDisplayName={PlatformPeg.get().getDefaultDeviceDisplayName()}
|
defaultDeviceDisplayName={PlatformPeg.get().getDefaultDeviceDisplayName()}
|
||||||
/>,
|
/>,
|
||||||
document.getElementById('matrixchat')
|
document.getElementById('matrixchat')
|
||||||
);
|
);
|
||||||
|
|
||||||
routeUrl(window.location);
|
|
||||||
|
|
||||||
// we didn't propagate screen changes to the URL bar while we were loading; do it now.
|
|
||||||
loaded = true;
|
|
||||||
if (lastLoadedScreen) {
|
|
||||||
onNewScreen(lastLoadedScreen);
|
|
||||||
lastLoadedScreen = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.error("Browser is missing required features.");
|
console.error("Browser is missing required features.");
|
||||||
|
|
21
src/vector/indexedbd-worker.js
Normal file
21
src/vector/indexedbd-worker.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 Vector Creations Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
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 {IndexedDBStoreWorker} from 'matrix-js-sdk/lib/indexeddb-worker.js';
|
||||||
|
|
||||||
|
const remoteWorker = new IndexedDBStoreWorker(postMessage);
|
||||||
|
|
||||||
|
onmessage = remoteWorker.onMessage;
|
|
@ -139,4 +139,8 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
requestNotificationPermission() : Promise {
|
requestNotificationPermission() : Promise {
|
||||||
return q('granted');
|
return q('granted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
electron.remote.getCurrentWebContents().reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,4 +206,10 @@ export default class WebPlatform extends VectorBasePlatform {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
// forceReload=false since we don't really need new HTML/JS files
|
||||||
|
// we just need to restart the JS runtime.
|
||||||
|
window.location.reload(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,17 +314,24 @@ class IndexedDBLogStore {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
for (let i = 0; i < allLogIds.length; i++) {
|
for (let i = 0; i < allLogIds.length; i++) {
|
||||||
let lines = await fetchLogs(allLogIds[i]);
|
let lines = await fetchLogs(allLogIds[i]);
|
||||||
|
|
||||||
|
// always include at least one log file, but only include
|
||||||
|
// subsequent ones if they won't take us over the MAX_LOG_SIZE
|
||||||
|
if (i > 0 && size + lines.length > MAX_LOG_SIZE) {
|
||||||
|
// the remaining log IDs should be removed. If we go out of
|
||||||
|
// bounds this is just []
|
||||||
|
//
|
||||||
|
// XXX: there's nothing stopping the current session exceeding
|
||||||
|
// MAX_LOG_SIZE. We ought to think about culling it.
|
||||||
|
removeLogIds = allLogIds.slice(i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
logs.push({
|
logs.push({
|
||||||
lines: lines,
|
lines: lines,
|
||||||
id: allLogIds[i],
|
id: allLogIds[i],
|
||||||
});
|
});
|
||||||
size += lines.length;
|
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) {
|
if (removeLogIds.length > 0) {
|
||||||
console.log("Removing logs: ", removeLogIds);
|
console.log("Removing logs: ", removeLogIds);
|
||||||
|
@ -481,10 +488,12 @@ module.exports = {
|
||||||
text: (
|
text: (
|
||||||
userText || "User did not supply any additional text."
|
userText || "User did not supply any additional text."
|
||||||
),
|
),
|
||||||
|
app: 'riot-web',
|
||||||
version: version,
|
version: version,
|
||||||
user_agent: userAgent,
|
user_agent: userAgent,
|
||||||
},
|
},
|
||||||
json: true,
|
json: true,
|
||||||
|
timeout: 5 * 60 * 1000,
|
||||||
}, (err, res) => {
|
}, (err, res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
|
|
|
@ -23,6 +23,7 @@ var jssdk = require('matrix-js-sdk');
|
||||||
var sdk = require('matrix-react-sdk');
|
var sdk = require('matrix-react-sdk');
|
||||||
var peg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
var peg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||||
|
var PageTypes = require('matrix-react-sdk/lib/PageTypes');
|
||||||
var MatrixChat = sdk.getComponent('structures.MatrixChat');
|
var MatrixChat = sdk.getComponent('structures.MatrixChat');
|
||||||
var RoomDirectory = sdk.getComponent('structures.RoomDirectory');
|
var RoomDirectory = sdk.getComponent('structures.RoomDirectory');
|
||||||
var RoomPreviewBar = sdk.getComponent('rooms.RoomPreviewBar');
|
var RoomPreviewBar = sdk.getComponent('rooms.RoomPreviewBar');
|
||||||
|
@ -90,12 +91,13 @@ describe('joining a room', function () {
|
||||||
matrixChat = ReactDOM.render(mc, parentDiv);
|
matrixChat = ReactDOM.render(mc, parentDiv);
|
||||||
|
|
||||||
// switch to the Directory
|
// switch to the Directory
|
||||||
dis.dispatch({
|
matrixChat._setPage(PageTypes.RoomDirectory);
|
||||||
action: 'view_room_directory',
|
|
||||||
});
|
|
||||||
|
|
||||||
var roomView;
|
var roomView;
|
||||||
httpBackend.flush().then(() => {
|
// wait for /sync to happen
|
||||||
|
return q.delay(1).then(() => {
|
||||||
|
return httpBackend.flush();
|
||||||
|
}).then(() => {
|
||||||
var roomDir = ReactTestUtils.findRenderedComponentWithType(
|
var roomDir = ReactTestUtils.findRenderedComponentWithType(
|
||||||
matrixChat, RoomDirectory);
|
matrixChat, RoomDirectory);
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,23 @@ describe('loading:', function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse the given window.location and return parameters that can be used when calling
|
||||||
|
// MatrixChat.showScreen(screen, params)
|
||||||
|
function getScreenFromLocation(location) {
|
||||||
|
const fragparts = parseQsFromFragment(location);
|
||||||
|
return {
|
||||||
|
screen: fragparts.location.substring(1),
|
||||||
|
params: fragparts.params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function routeUrl(location, matrixChat) {
|
||||||
|
console.log(Date.now() + "Routing URL " + location);
|
||||||
|
const s = getScreenFromLocation(location);
|
||||||
|
console.log("Showing screen", s);
|
||||||
|
matrixChat.showScreen(s.screen, s.params);
|
||||||
|
}
|
||||||
|
|
||||||
const MatrixChat = sdk.getComponent('structures.MatrixChat');
|
const MatrixChat = sdk.getComponent('structures.MatrixChat');
|
||||||
const fragParts = parseQsFromFragment(windowLocation);
|
const fragParts = parseQsFromFragment(windowLocation);
|
||||||
var params = parseQs(windowLocation);
|
var params = parseQs(windowLocation);
|
||||||
|
@ -118,16 +135,10 @@ describe('loading:', function () {
|
||||||
startingFragmentQueryParams={fragParts.params}
|
startingFragmentQueryParams={fragParts.params}
|
||||||
enableGuest={true}
|
enableGuest={true}
|
||||||
onLoadCompleted={loadCompleteDefer.resolve}
|
onLoadCompleted={loadCompleteDefer.resolve}
|
||||||
|
initialScreenAfterLogin={getScreenFromLocation(windowLocation)}
|
||||||
/>, parentDiv
|
/>, parentDiv
|
||||||
);
|
);
|
||||||
|
|
||||||
function routeUrl(location, matrixChat) {
|
|
||||||
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
|
// pause for a cycle, then simulate the window.onload handler
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
console.log(Date.now() + " simulating window.onload");
|
console.log(Date.now() + " simulating window.onload");
|
||||||
|
@ -188,15 +199,17 @@ describe('loading:', function () {
|
||||||
let login = ReactTestUtils.findRenderedComponentWithType(
|
let login = ReactTestUtils.findRenderedComponentWithType(
|
||||||
matrixChat, sdk.getComponent('structures.login.Login'));
|
matrixChat, sdk.getComponent('structures.login.Login'));
|
||||||
httpBackend.when('POST', '/login').check(function(req) {
|
httpBackend.when('POST', '/login').check(function(req) {
|
||||||
|
console.log(req);
|
||||||
expect(req.data.type).toEqual('m.login.password');
|
expect(req.data.type).toEqual('m.login.password');
|
||||||
expect(req.data.user).toEqual('user');
|
expect(req.data.identifier.type).toEqual('m.id.user');
|
||||||
|
expect(req.data.identifier.user).toEqual('user');
|
||||||
expect(req.data.password).toEqual('pass');
|
expect(req.data.password).toEqual('pass');
|
||||||
}).respond(200, {
|
}).respond(200, {
|
||||||
user_id: '@user:id',
|
user_id: '@user:id',
|
||||||
device_id: 'DEVICE_ID',
|
device_id: 'DEVICE_ID',
|
||||||
access_token: 'access_token',
|
access_token: 'access_token',
|
||||||
});
|
});
|
||||||
login.onPasswordLogin("user", "pass")
|
login.onPasswordLogin("user", undefined, undefined, "pass")
|
||||||
return httpBackend.flush();
|
return httpBackend.flush();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// Wait for another trip around the event loop for the UI to update
|
// Wait for another trip around the event loop for the UI to update
|
||||||
|
@ -474,7 +487,8 @@ function awaitRoomView(matrixChat, retryLimit, retryCount) {
|
||||||
retryCount = 0;
|
retryCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!matrixChat.state.ready) {
|
if (matrixChat.state.loading ||
|
||||||
|
!(matrixChat.state.loggedIn && matrixChat.state.ready)) {
|
||||||
console.log(Date.now() + " Awaiting room view: not ready yet.");
|
console.log(Date.now() + " Awaiting room view: not ready yet.");
|
||||||
if (retryCount >= retryLimit) {
|
if (retryCount >= retryLimit) {
|
||||||
throw new Error("MatrixChat still not ready after " +
|
throw new Error("MatrixChat still not ready after " +
|
||||||
|
|
|
@ -6,6 +6,7 @@ var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: {
|
entry: {
|
||||||
"bundle": "./src/vector/index.js",
|
"bundle": "./src/vector/index.js",
|
||||||
|
"indexeddb-worker": "./src/vector/indexedbd-worker.js",
|
||||||
|
|
||||||
// We ship olm.js as a separate lump of javascript. This makes it get
|
// We ship olm.js as a separate lump of javascript. This makes it get
|
||||||
// loaded via a separate <script/> tag in index.html (which loads it
|
// loaded via a separate <script/> tag in index.html (which loads it
|
||||||
|
|
Loading…
Reference in a new issue