Browse Source

Merge branch 'develop' into fix-emoji

pull/1935/head
Aviral Dasgupta 6 years ago
parent
commit
19d5063814
  1. 39
      README.md
  2. 16
      package.json
  3. 21
      scripts/staticfiles.js
  4. 4
      src/component-index.js
  5. 6
      src/components/structures/BottomLeftMenu.js
  6. 2
      src/components/structures/RightPanel.js
  7. 5
      src/components/structures/RoomDirectory.js
  8. 6
      src/components/structures/RoomSubList.js
  9. 2
      src/components/structures/SearchBox.js
  10. 12
      src/components/views/context_menus/MessageContextMenu.js
  11. 153
      src/components/views/context_menus/NotificationStateContextMenu.js
  12. 3
      src/components/views/globals/MatrixToolbar.js
  13. 56
      src/components/views/settings/IntegrationsManager.js
  14. 91
      src/skins/vector/css/common.css
  15. 106
      src/skins/vector/css/matrix-react-sdk/structures/ContextualMenu.css
  16. 4
      src/skins/vector/css/matrix-react-sdk/structures/MatrixChat.css
  17. 8
      src/skins/vector/css/matrix-react-sdk/structures/SearchBox.css
  18. 4
      src/skins/vector/css/matrix-react-sdk/structures/UserSettings.css
  19. 16
      src/skins/vector/css/matrix-react-sdk/views/messages/UnknownBody.css
  20. 1
      src/skins/vector/css/matrix-react-sdk/views/rooms/MemberInfo.css
  21. 18
      src/skins/vector/css/matrix-react-sdk/views/rooms/MessageComposer.css
  22. 19
      src/skins/vector/css/matrix-react-sdk/views/rooms/RoomHeader.css
  23. 97
      src/skins/vector/css/matrix-react-sdk/views/rooms/RoomTile.css
  24. 47
      src/skins/vector/css/matrix-react-sdk/views/settings/DevicesPanel.css
  25. 33
      src/skins/vector/css/matrix-react-sdk/views/settings/IntegrationsManager.css
  26. 13
      src/skins/vector/css/vector-web/structures/LeftPanel.css
  27. 25
      src/skins/vector/css/vector-web/structures/RightPanel.css
  28. 4
      src/skins/vector/css/vector-web/structures/RoomSubList.css
  29. 25
      src/skins/vector/css/vector-web/views/context_menus/MessageContextMenu.css
  30. 56
      src/skins/vector/css/vector-web/views/context_menus/NotificationStateContextMenu.css
  31. 1
      src/skins/vector/css/vector-web/views/elements/ImageView.css
  32. 8
      src/skins/vector/css/vector-web/views/globals/MatrixToolbar.css
  33. 5
      src/skins/vector/css/vector-web/views/rooms/RoomDropTarget.css
  34. 16
      src/skins/vector/css/vector-web/views/rooms/RoomTooltip.css
  35. 8
      src/skins/vector/img/icon-call.svg
  36. 11
      src/skins/vector/img/icon-context-mute-mentions.svg
  37. 10
      src/skins/vector/img/icon-context-mute-off-copy.svg
  38. 9
      src/skins/vector/img/icon-context-mute-off.svg
  39. 9
      src/skins/vector/img/icon-context-mute.svg
  40. 24
      src/skins/vector/img/icons-create-room.svg
  41. 32
      src/skins/vector/img/icons-directory.svg
  42. 9
      src/skins/vector/img/icons-people.svg
  43. 10
      src/skins/vector/img/icons-search-copy.svg
  44. 9
      src/skins/vector/img/icons-search.svg
  45. 15
      src/skins/vector/img/icons-settings-room.svg
  46. 20
      src/skins/vector/img/icons-settings.svg
  47. 12
      src/skins/vector/img/icons-upload.svg
  48. 20
      src/skins/vector/img/icons-video.svg
  49. BIN
      src/skins/vector/img/members.png
  50. 14
      src/skins/vector/img/members.svg
  51. 20
      src/skins/vector/img/notif-active.svg
  52. 22
      src/skins/vector/img/notif-slider.svg
  53. 4
      src/vector/index.js
  54. 8
      test/app-tests/joining.js
  55. 3
      vector/config.sample.json
  56. 2
      vector/index.html
  57. 26
      webpack.config.js

39
README.md

@ -6,9 +6,12 @@ Vector is a Matrix web client built using the Matrix React SDK (https://github.c
Getting Started
===============
Vector is a modular webapp built with modern ES6 and requires and npm build system to build.
Instructions for building are below, but building from source shouldn't be necessary
for simple deployments.
The easiest way to test Vector is to just use the hosted copy at https://vector.im/beta.
The develop branch is continuously deployed by Jenkins at https://vector.im/develop for
those who like living dangerously.
To host your own copy of Vector, the quickest bet is to use a pre-built released version
of Vector:
1. Download the latest version from https://vector.im/packages/
1. Untar the tarball on your web server
@ -20,7 +23,7 @@ for simple deployments.
Building From Source
====================
If you do wish to build vector from source:
Vector is a modular webapp built with modern ES6 and requires a npm build system to build.
1. Install or update `node.js` so that your `npm` is at least at version `2.0.0`
1. Clone the repo: `git clone https://github.com/vector-im/vector-web.git`
@ -50,8 +53,32 @@ You can configure the app by copying `vector/config.sample.json` to
1. `default_hs_url` is the default home server url.
1. `default_is_url` is the default identity server url (this is the server used
for verifying third party identifiers like email addresses). If this is blank,
registering with an email address or adding an email address to your account
will not work.
registering with an email address, adding an email address to your account,
or inviting users via email address will not work. Matrix identity servers are
very simple web services which map third party identifiers (currently only email
addresses) to matrix IDs: see http://matrix.org/docs/spec/identity_service/unstable.html
for more details. Currently the only public matrix identity servers are https://matrix.org
and https://vector.im. In future identity servers will be decentralised.
Running as a Desktop app
========================
In future we'll do an official distribution of Vector as an desktop app. Meanwhile,
there are a few options:
@asdf:matrix.org points out that you can use nativefier and it just works(tm):
```
sudo npm install nativefier -g
nativefier https://vector.im/beta/
```
krisa has a dedicated electron project at https://github.com/krisak/vector-electron-desktop
(although you should swap out the 'vector' folder for the latest vector tarball you want to run)
There's also a (much) older electron distribution at https://github.com/stevenhammerton/vector-desktop
Development
===========

16
package.json

@ -18,17 +18,18 @@
"build:compile": "babel --source-maps -d lib src",
"build:bundle": "NODE_ENV=production webpack -p lib/vector/index.js vector/bundle.js",
"build:bundle:dev": "NODE_ENV=production webpack --optimize-occurence-order lib/vector/index.js vector/bundle.js",
"build": "npm run build:css && npm run build:emojione && npm run build:compile && npm run build:bundle",
"build:dev": "npm run build:css && npm run build:compile && npm run build:bundle:dev",
"build:staticfiles": "scripts/staticfiles.js",
"build": "npm run build:staticfiles && npm run build:emojione && npm run build:css && npm run build:compile && npm run build:bundle",
"build:dev": "npm run build:staticfiles && npm run build:emojione && npm run build:css && npm run build:compile && npm run build:bundle:dev",
"package": "scripts/package.sh",
"start:emojione": "cpx \"node_modules/emojione/assets/svg/*\" vector/emojione/svg/ -w",
"start:js": "webpack -w src/vector/index.js vector/bundle.js",
"start:js:prod": "NODE_ENV=production webpack -w src/vector/index.js vector/bundle.js",
"start:skins:css": "catw \"src/skins/vector/css/**/*.css\" -o vector/components.css",
"//cache": "Note the -c 1 below due to https://code.google.com/p/chromium/issues/detail?id=508270",
"start": "parallelshell \"npm run start:js\" \"npm run start:emojione\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
"start:prod": "parallelshell \"npm run start:js:prod\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
"clean": "rimraf lib vector/bundle.css vector/bundle.js vector/bundle.js.map vector/webpack.css* vector/emojione",
"start": "parallelshell \"npm run build:staticfiles\" \"npm run start:emojione\" \"npm run start:js\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
"start:prod": "parallelshell \"npm run build:staticfiles\" \"npm run start:emojione\" \"npm run start:js:prod\" \"npm run start:skins:css\" \"http-server -c 1 vector\"",
"clean": "rimraf lib vector/olm.js vector/bundle.css vector/bundle.js vector/bundle.js.map vector/webpack.css* vector/emojione",
"prepublish": "npm run build:css && npm run build:compile",
"test": "karma start --single-run=true --autoWatch=false --browsers PhantomJS --colors=false",
"test:multi": "karma start"
@ -41,7 +42,7 @@
"extract-text-webpack-plugin": "^0.9.1",
"filesize": "^3.1.2",
"flux": "~2.0.3",
"gemini-scrollbar": "matrix-org/gemini-scrollbar#468544d",
"gemini-scrollbar": "matrix-org/gemini-scrollbar#b302279",
"gfm.css": "^1.1.1",
"highlight.js": "^9.0.0",
"linkifyjs": "^2.0.0-beta.4",
@ -53,7 +54,7 @@
"react-dnd": "^2.1.4",
"react-dnd-html5-backend": "^2.1.2",
"react-dom": "^15.2.1",
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#dbf0abf",
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef",
"sanitize-html": "^1.11.1"
},
"devDependencies": {
@ -65,6 +66,7 @@
"css-raw-loader": "^0.1.1",
"emojione": "^2.2.3",
"expect": "^1.16.0",
"fs-extra": "^0.30.0",
"http-server": "^0.8.4",
"json-loader": "^0.5.3",
"karma": "^0.13.22",

21
scripts/staticfiles.js

@ -0,0 +1,21 @@
#!/usr/bin/env node
// copy static files from node_modules to the vector directory
//
var fs = require('fs-extra');
function exists(f) {
try {
fs.statSync(f);
return true;
} catch(e) {
return false;
}
}
const olm = 'node_modules/olm/olm.js';
if (exists(olm)) {
console.log("copy", olm, "-> vector");
fs.copySync(olm, 'vector/olm.js');
}

4
src/component-index.js

@ -34,6 +34,8 @@ module.exports.components['structures.RoomDirectory'] = require('./components/st
module.exports.components['structures.RoomSubList'] = require('./components/structures/RoomSubList');
module.exports.components['structures.SearchBox'] = require('./components/structures/SearchBox');
module.exports.components['structures.ViewSource'] = require('./components/structures/ViewSource');
module.exports.components['views.context_menus.MessageContextMenu'] = require('./components/views/context_menus/MessageContextMenu');
module.exports.components['views.context_menus.NotificationStateContextMenu'] = require('./components/views/context_menus/NotificationStateContextMenu');
module.exports.components['views.elements.ImageView'] = require('./components/views/elements/ImageView');
module.exports.components['views.elements.Spinner'] = require('./components/views/elements/Spinner');
module.exports.components['views.globals.GuestWarningBar'] = require('./components/views/globals/GuestWarningBar');
@ -45,9 +47,9 @@ module.exports.components['views.login.VectorLoginHeader'] = require('./componen
module.exports.components['views.messages.DateSeparator'] = require('./components/views/messages/DateSeparator');
module.exports.components['views.messages.MessageTimestamp'] = require('./components/views/messages/MessageTimestamp');
module.exports.components['views.rooms.BottomLeftMenuTile'] = require('./components/views/rooms/BottomLeftMenuTile');
module.exports.components['views.rooms.MessageContextMenu'] = require('./components/views/rooms/MessageContextMenu');
module.exports.components['views.rooms.RoomDNDView'] = require('./components/views/rooms/RoomDNDView');
module.exports.components['views.rooms.RoomDropTarget'] = require('./components/views/rooms/RoomDropTarget');
module.exports.components['views.rooms.RoomTooltip'] = require('./components/views/rooms/RoomTooltip');
module.exports.components['views.rooms.SearchBar'] = require('./components/views/rooms/SearchBar');
module.exports.components['views.settings.IntegrationsManager'] = require('./components/views/settings/IntegrationsManager');
module.exports.components['views.settings.Notifications'] = require('./components/views/settings/Notifications');

6
src/components/structures/BottomLeftMenu.js

@ -52,13 +52,13 @@ module.exports = React.createClass({
<div className="mx_BottomLeftMenu">
<div className="mx_BottomLeftMenu_options">
<div className="mx_BottomLeftMenu_createRoom" title="Start chat" onClick={ this.onCreateRoomClick }>
<TintableSvg src="img/icons-create-room.svg" width="24" height="24"/>
<TintableSvg src="img/icons-create-room.svg" width="25" height="25"/>
</div>
<div className="mx_BottomLeftMenu_directory" title="Room directory" onClick={ this.onRoomDirectoryClick }>
<TintableSvg src="img/icons-directory.svg" width="24" height="24"/>
<TintableSvg src="img/icons-directory.svg" width="25" height="25"/>
</div>
<div className="mx_BottomLeftMenu_settings" title="Settings" onClick={ this.onSettingsClick }>
<TintableSvg src="img/icons-settings.svg" width="24" height="24"/>
<TintableSvg src="img/icons-settings.svg" width="25" height="25"/>
</div>
</div>
</div>

2
src/components/structures/RightPanel.js

@ -136,8 +136,8 @@ module.exports = React.createClass({
buttonGroup =
<div className="mx_RightPanel_headerButtonGroup">
<div className="mx_RightPanel_headerButton" title="Members" onClick={ this.onMemberListButtonClick }>
<TintableSvg src="img/members.svg" width="17" height="22"/>
{ membersBadge }
<TintableSvg src="img/icons-people.svg" width="25" height="25"/>
{ membersHighlight }
</div>
<div className="mx_RightPanel_headerButton mx_RightPanel_filebutton" title="Files">

5
src/components/structures/RoomDirectory.js

@ -21,7 +21,7 @@ var React = require('react');
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var ContentRepo = require("matrix-js-sdk").ContentRepo;
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk')
var sdk = require('matrix-react-sdk');
var dis = require('matrix-react-sdk/lib/dispatcher');
var GeminiScrollbar = require('react-gemini-scrollbar');
@ -282,8 +282,7 @@ module.exports = React.createClass({
<SimpleRoomHeader title="Directory" />
<div className="mx_RoomDirectory_list">
<input ref="roomAlias" placeholder="Join a room (e.g. #foo:domain.com)" className="mx_RoomDirectory_input" size="64" onKeyUp={ this.onKeyUp }/>
<GeminiScrollbar className="mx_RoomDirectory_tableWrapper"
relayoutOnUpdate={false} >
<GeminiScrollbar className="mx_RoomDirectory_tableWrapper">
<table ref="directory_table" className="mx_RoomDirectory_table">
<tbody>
{ this.getRows(this.state.roomAlias) }

6
src/components/structures/RoomSubList.js

@ -61,8 +61,12 @@ var RoomSubList = React.createClass({
label: React.PropTypes.string.isRequired,
tagName: React.PropTypes.string,
editable: React.PropTypes.bool,
order: React.PropTypes.string.isRequired,
selectedRoom: React.PropTypes.string.isRequired,
// undefined if no room is selected (eg we are showing settings)
selectedRoom: React.PropTypes.string,
startAsHidden: React.PropTypes.bool,
showSpinner: React.PropTypes.bool, // true to show a spinner if 0 elements when expanded
collapsed: React.PropTypes.bool.isRequired, // is LeftPanel collapsed?

2
src/components/structures/SearchBox.js

@ -94,7 +94,7 @@ module.exports = React.createClass({
<TintableSvg
key="button"
className="mx_SearchBox_searchButton"
src="img/right_search.svg" width="24" height="24"
src="img/icons-search-copy.svg" width="13" height="13"
/>,
<input
key="searchfield"

12
src/components/views/rooms/MessageContextMenu.js → src/components/views/context_menus/MessageContextMenu.js

@ -95,7 +95,7 @@ module.exports = React.createClass({
if (eventStatus === 'not_sent') {
resendButton = (
<div className="mx_ContextualMenu_field" onClick={this.onResendClick}>
<div className="mx_MessageContextMenu_field" onClick={this.onResendClick}>
Resend
</div>
);
@ -103,7 +103,7 @@ module.exports = React.createClass({
if (!eventStatus) { // sent
redactButton = (
<div className="mx_ContextualMenu_field" onClick={this.onRedactClick}>
<div className="mx_MessageContextMenu_field" onClick={this.onRedactClick}>
Redact
</div>
);
@ -111,14 +111,14 @@ module.exports = React.createClass({
if (eventStatus === "queued" || eventStatus === "not_sent") {
cancelButton = (
<div className="mx_ContextualMenu_field" onClick={this.onCancelSendClick}>
<div className="mx_MessageContextMenu_field" onClick={this.onCancelSendClick}>
Cancel Sending
</div>
);
}
viewSourceButton = (
<div className="mx_ContextualMenu_field" onClick={this.onViewSourceClick}>
<div className="mx_MessageContextMenu_field" onClick={this.onViewSourceClick}>
View Source
</div>
);
@ -126,7 +126,7 @@ module.exports = React.createClass({
if (this.props.eventTileOps) {
if (this.props.eventTileOps.isWidgetHidden()) {
unhidePreviewButton = (
<div className="mx_ContextualMenu_field" onClick={this.onUnhidePreviewClick}>
<div className="mx_MessageContextMenu_field" onClick={this.onUnhidePreviewClick}>
Unhide Preview
</div>
)
@ -136,7 +136,7 @@ module.exports = React.createClass({
// XXX: this should be https://matrix.to.
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
permalinkButton = (
<div className="mx_ContextualMenu_field">
<div className="mx_MessageContextMenu_field">
<a href={ "#/room/" + this.props.mxEvent.getRoomId() +"/"+ this.props.mxEvent.getId() }
onClick={ this.onPermalinkClick }>Permalink</a>
</div>

153
src/components/views/context_menus/NotificationStateContextMenu.js

@ -0,0 +1,153 @@
/*
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');
module.exports = React.createClass({
displayName: 'NotificationStateContextMenu',
propTypes: {
room: React.PropTypes.object.isRequired,
/* callback called when the menu is dismissed */
onFinished: React.PropTypes.func,
},
getInitialState: function() {
var areNotifsMuted = false;
var cli = MatrixClientPeg.get();
if (!cli.isGuest()) {
var roomPushRule = cli.getRoomPushRule("global", this.props.room.roomId);
if (roomPushRule) {
if (0 <= roomPushRule.actions.indexOf("dont_notify")) {
areNotifsMuted = true;
}
}
}
return {
areNotifsMuted: areNotifsMuted,
};
},
_save: function( areNotifsMuted ) {
var self = this;
const roomId = this.props.room.roomId;
var cli = MatrixClientPeg.get();
if (!cli.isGuest()) {
// Wrapping this in a q promise, as setRoomMutePushRule can return
// a promise or a value
q(cli.setRoomMutePushRule("global", roomId, areNotifsMuted))
.then(function(s) {
self.setState({areNotifsMuted: areNotifsMuted});
// delay slightly so that the user can see their state change
// before closing the menu
return q.delay(500).then(function() {
// tell everyone that wants to know of the change in
// notification state
dis.dispatch({
action: 'notification_change',
roomId: self.props.room.roomId,
areNotifsMuted: areNotifsMuted,
});
// Close the context menu
if (self.props.onFinished) {
self.props.onFinished();
};
});
}).fail(function(error) {
// TODO: some form of error notification to the user
// to inform them that their state change failed.
});
}
},
_onClickAlertMe: function() {
// Placeholder
},
_onClickAllNotifs: function() {
this._save(false);
},
_onClickMentions: function() {
this._save(true);
},
_onClickMute: function() {
// Placeholder
},
render: function() {
var cli = MatrixClientPeg.get();
var alertMeClasses = classNames({
'mx_NotificationStateContextMenu_field': true,
'mx_NotificationStateContextMenu_fieldDisabled': true,
});
var allNotifsClasses = classNames({
'mx_NotificationStateContextMenu_field': true,
'mx_NotificationStateContextMenu_fieldSet': !this.state.areNotifsMuted,
});
var mentionsClasses = classNames({
'mx_NotificationStateContextMenu_field': true,
'mx_NotificationStateContextMenu_fieldSet': this.state.areNotifsMuted,
});
var muteNotifsClasses = classNames({
'mx_NotificationStateContextMenu_field': true,
'mx_NotificationStateContextMenu_fieldDisabled': true,
});
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" src="img/icon-context-mute-off-copy.svg" width="16" height="12" />
All messages (loud)
</div>
<div className={ allNotifsClasses } onClick={this._onClickAllNotifs} >
<img className="mx_NotificationStateContextMenu_activeIcon" src="img/notif-active.svg" width="12" height="12" />
<img className="mx_NotificationStateContextMenu_icon" src="img/icon-context-mute-off.svg" width="16" height="12" />
All messages
</div>
<div className={ mentionsClasses } onClick={this._onClickMentions} >
<img className="mx_NotificationStateContextMenu_activeIcon" src="img/notif-active.svg" width="12" height="12" />
<img className="mx_NotificationStateContextMenu_icon" src="img/icon-context-mute-mentions.svg" width="16" height="12" />
Mentions only
</div>
<div className={ muteNotifsClasses } onClick={this._onClickMute} >
<img className="mx_NotificationStateContextMenu_activeIcon" src="img/notif-active.svg" width="12" height="12" />
<img className="mx_NotificationStateContextMenu_icon" src="img/icon-context-mute.svg" width="16" height="12" />
Mute
</div>
</div>
);
}
});

3
src/components/views/globals/MatrixToolbar.js

@ -35,7 +35,7 @@ module.exports = React.createClass({
return (
<div className="mx_MatrixToolbar">
<img className="mx_MatrixToolbar_warning" src="img/warning.svg" width="24" height="23" alt="/!\"/>
<div>
<div className="mx_MatrixToolbar_content">
You are not receiving desktop notifications. <a className="mx_MatrixToolbar_link" onClick={ this.onClick }>Enable them now</a>
</div>
<div className="mx_MatrixToolbar_close"><img src="img/cancel.svg" width="18" height="18" onClick={ this.hideToolbar } /></div>
@ -43,4 +43,3 @@ module.exports = React.createClass({
);
}
});

56
src/components/views/settings/IntegrationsManager.js

@ -0,0 +1,56 @@
/*
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 React = require('react');
var sdk = require('matrix-react-sdk');
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
module.exports = React.createClass({
displayName: 'IntegrationsManager',
propTypes: {
src: React.PropTypes.string.isRequired, // the source of the integration manager being embedded
onFinished: React.PropTypes.func.isRequired, // callback when the lightbox is dismissed
},
// XXX: keyboard shortcuts for managing dialogs should be done by the modal
// dialog base class somehow, surely...
componentDidMount: function() {
document.addEventListener("keydown", this.onKeyDown);
},
componentWillUnmount: function() {
document.removeEventListener("keydown", this.onKeyDown);
},
onKeyDown: function(ev) {
if (ev.keyCode == 27) { // escape
ev.stopPropagation();
ev.preventDefault();
this.props.onFinished();
}
},
render: function() {
return (
<div className="mx_IntegrationsManager">
<iframe src={ this.props.src }></iframe>
</div>
);
}
});

91
src/skins/vector/css/common.css

@ -52,6 +52,10 @@ a:visited {
color: #76cfa6;
}
input[type=text].error, input[type=password].error {
border: 1px solid red;
}
input[type=text]:focus, textarea:focus {
border: 1px solid #76CFA6;
outline: none;
@ -80,53 +84,27 @@ input[type=text]:focus, textarea:focus {
position: absolute;
}
/* hack to avoid accidental click-throughs if you miss the narrow scrollbar */
.gm-scrollbar.-vertical {
border-left: 6px solid transparent;
}
.mx_ContextualMenu_background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 1.0;
z-index: 2000;
}
.mx_ContextualMenu {
border: 1px solid #a4a4a4;
border-radius: 8px;
background-color: #fff;
color: #747474;
position: fixed;
z-index: 2001;
padding: 6px;
/* Expand thumbs on hoverover */
.gm-scrollbar {
border-radius: 5px ! important;
}
.mx_ContextualMenu_chevron_right {
padding: 12px;
position: absolute;
right: -21px;
top: 0px;
.gm-scrollbar.-vertical {
width: 6px;
transition: width 120ms ease-out ! important;
}
.mx_ContextualMenu_chevron_left {
padding: 12px;
position: absolute;
left: -21px;
top: 0px;
.gm-scrollbar.-vertical:hover,
.gm-scrollbar.-vertical:active {
width: 8px;
transition: width 120ms ease-out ! important;
}
.mx_ContextualMenu_field {
padding: 3px 6px 3px 6px;
cursor: pointer;
.gm-scrollbar.-horizontal {
height: 6px;
transition: height 120ms ease-out ! important;
}
.mx_ContextualMenu_spinner {
display: block;
margin: 0 auto;
.gm-scrollbar.-horizontal:hover,
.gm-scrollbar.-horizontal:active {
height: 8px;
transition: height 120ms ease-out ! important;
}
.mx_Dialog_wrapper {
@ -233,6 +211,17 @@ input[type=text]:focus, textarea:focus {
background-color: #76cfa6;
}
.mx_Dialog button.danger, .mx_Dialog input[type="submit"].danger {
background-color: #ff0064;
border: solid 1px #ff0064;
}
.mx_Dialog button:disabled, .mx_Dialog input[type="submit"]:disabled {
background-color: #777777;
border: solid 1px #777777;
opacity: 0.7;
}
.mx_Dialog_title {
min-height: 16px;
padding-top: 40px;
@ -242,6 +231,10 @@ input[type=text]:focus, textarea:focus {
color: #454545;
}
.mx_Dialog_title.danger {
color: #ff0064;
}
.mx_TextInputDialog_label {
text-align: left;
padding-bottom: 12px;
@ -270,3 +263,15 @@ input[type=text]:focus, textarea:focus {
background-color: #76CFA6;
color: white;
}
/** green button with rounded corners */
.textButton {
color: #fff;
background-color: #76cfa6;
border-radius: 17px;
text-align: center;
padding-left: 1em;
padding-right: 1em;
cursor: pointer;
display: inline;
}

106
src/skins/vector/css/matrix-react-sdk/structures/ContextualMenu.css

@ -0,0 +1,106 @@
/*
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_ContextualMenu_wrapper {
position: fixed;
z-index: 2000;
}
.mx_ContextualMenu_background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 1.0;
z-index: 2000;
}
.mx_ContextualMenu {
border: solid 1px rgba(187, 187, 187, 0.5);
border-radius: 4px;
background-color: #f6f6f6;
color: #4a4a4a;
position: absolute;
padding: 6px;
font-size: 14px;
z-index: 2001;
}
.mx_ContextualMenu.mx_ContextualMenu_right {
right: 8px;
}
.mx_ContextualMenu_chevron_right {
position: absolute;
right: -8px;
top: 0px;
width: 0;
height: 0;
border-top: 8px solid transparent;
border-left: 8px solid rgba(187, 187, 187, 0.5);
border-bottom: 8px solid transparent;
}
.mx_ContextualMenu_chevron_right:after{
content:'';
width: 0;
height: 0;
border-top: 7px solid transparent;
border-left: 7px solid #f6f6f6;
border-bottom: 7px solid transparent;
position:absolute;
top: -7px;
right: 1px;
}
.mx_ContextualMenu.mx_ContextualMenu_left {
left: 8px;
}
.mx_ContextualMenu_chevron_left {
position: absolute;
left: -8px;
top: 0px;
width: 0;
height: 0;
border-top: 8px solid transparent;
border-right: 8px solid rgba(187, 187, 187, 0.5);
border-bottom: 8px solid transparent;
}
.mx_ContextualMenu_chevron_left:after{
content:'';
width: 0;
height: 0;
border-top: 7px solid transparent;
border-right: 7px solid #f6f6f6;
border-bottom: 7px solid transparent;
position:absolute;
top: -7px;
left: 1px;
}
.mx_ContextualMenu_field {
padding: 3px 6px 3px 6px;
cursor: pointer;
white-space: nowrap;
}
.mx_ContextualMenu_spinner {
display: block;
margin: 0 auto;
}

4
src/skins/vector/css/matrix-react-sdk/structures/MatrixChat.css

@ -93,8 +93,8 @@ limitations under the License.
background-color: #eaf5f0;
-webkit-flex: 0 0 210px;
flex: 0 0 210px;
-webkit-flex: 0 0 235px;
flex: 0 0 235px;
}
.mx_MatrixChat .mx_LeftPanel.collapsed {

8
src/skins/vector/css/matrix-react-sdk/structures/SearchBox.css

@ -16,8 +16,8 @@ limitations under the License.
.mx_SearchBox {
height: 24px;
margin-left: 16px;
margin-right: 20px;
margin-left: 18px;
margin-right: 18px;
padding-top: 24px;
padding-bottom: 22px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
@ -28,11 +28,13 @@ limitations under the License.
.mx_SearchBox_searchButton {
margin-right: 10px;
margin-top: 5px;
pointer-events: none;
}
.mx_SearchBox_closeButton {
cursor: pointer;
margin-top: -5px;
}
.mx_SearchBox_search {
@ -65,4 +67,4 @@ limitations under the License.
.mx_SearchBox object {
pointer-events: none;
}
}

4
src/skins/vector/css/matrix-react-sdk/structures/UserSettings.css

@ -94,6 +94,10 @@ limitations under the License.
cursor: pointer;
}
.mx_UserSettings_button.danger {
background-color: #ff0064;
}
.mx_UserSettings_section {
margin-left: 63px;
margin-top: 28px;

16
src/skins/vector/css/matrix-react-sdk/views/messages/UnknownBody.css

@ -0,0 +1,16 @@
/*
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_UnknownBody {
white-space: pre-wrap;
}

1
src/skins/vector/css/matrix-react-sdk/views/rooms/MemberInfo.css

@ -17,6 +17,7 @@ limitations under the License.
.mx_MemberInfo {
margin-top: 20px;
height: 100%;
overflow-y: auto;
}
.mx_MemberInfo h2 {

18
src/skins/vector/css/matrix-react-sdk/views/rooms/MessageComposer.css

@ -109,9 +109,10 @@ limitations under the License.
.mx_MessageComposer_videocall {
/*display: table-cell;*/
/*vertical-align: middle;*/
padding-left: 10px;
padding-right: 10px;
/*padding-left: 10px;*/
padding-right: 5px;
cursor: pointer;
padding-top: 4px;
}
.mx_MessageComposer_upload object,
@ -121,16 +122,3 @@ limitations under the License.
pointer-events: none;
}
.mx_MessageComposer_videocall {
padding-right: 10px;
padding-top: 4px;
}
.mx_MessageComposer_voicecall {
padding-right: 10px;
padding-top: 4px;
}
.mx_MessageComposer_upload object {
margin-top: 5px;
}

19
src/skins/vector/css/matrix-react-sdk/views/rooms/RoomHeader.css

@ -103,7 +103,8 @@ limitations under the License.
.mx_RoomHeader_rightRow {
margin-top: 4px;
background-color: #fff;
display: flex;
align-items: center;
-webkit-box-ordinal-group: 3;
-moz-box-ordinal-group: 3;
-ms-flex-order: 3;
@ -161,13 +162,6 @@ limitations under the License.
opacity: 0.6;
}
.mx_RoomHeader_settingsButton {
display: inline-block;
position: relative;
bottom: 10px;
left: 4px;
}
.mx_RoomHeader_settingsButton object {
pointer-events: none;
}
@ -183,10 +177,6 @@ limitations under the License.
color: #76cfa6;
}
.mx_RoomHeader_leaveButton {
margin-top: -1px;
}
.mx_RoomHeader_placeholder {
color: #a2a2a2 ! important;
}
@ -243,10 +233,7 @@ limitations under the License.
}
.mx_RoomHeader_button {
display: table-cell;
vertical-align: top;
padding-left: 8px;
padding-right: 8px;
margin-left: 8px;
cursor: pointer;
}

97
src/skins/vector/css/matrix-react-sdk/views/rooms/RoomTile.css

@ -15,18 +15,25 @@ limitations under the License.
*/
.mx_RoomTile {
position: relative;
cursor: pointer;
/* This fixes wrapping of long room names, but breaks drag & drop previews */
/* display: table-row; */
font-size: 13px;
display: block;
height: 34px;
}
.mx_RoomTile_nameContainer {
display: inline-block;
width: 180px;
height: 24px;
}
.mx_RoomTile_avatar {
display: inline-block;
padding-top: 6px;
padding-bottom: 6px;
padding-top: 5px;
padding-bottom: 5px;
padding-left: 18px;
padding-right: 6px;
width: 24px;
height: 24px;
vertical-align: middle;
@ -34,13 +41,17 @@ limitations under the License.
.mx_RoomTile_name {
display: inline-block;
width: 100px;
position: relative;
width: 165px;
vertical-align: middle;
overflow: hidden;
word-break: break-word;
padding-left: 11px;
padding-right: 15px;
padding-left: 6px;
padding-right: 6px;
padding-top: 2px;
padding-bottom: 3px;
color: rgba(69, 69, 69, 0.8);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mx_RoomTile_ellipsis .mx_RoomTile_name {
@ -53,17 +64,16 @@ limitations under the License.
*/
}
.collapsed .mx_RoomTile_name {
display: none;
.collapsed .mx_RoomTile_nameContainer {
height: 0;
}
.collapsed .mx_RoomTile {
height: 36px;
.collapsed .mx_RoomTile_name {
display: none;
}
.collapsed .mx_RoomTile_badge {
top: -40px;
left: 30px;
top: -2px;
min-width: 12px;
height: 16px;
border-radius: 16px;
@ -71,6 +81,11 @@ limitations under the License.
z-index: 200;
}
/* Hide the bottom of speech bubble */
.collapsed .mx_RoomTile_highlight .mx_RoomTile_badge:after {
display: none;
}
/* This is the bottom of the speech bubble */
.mx_RoomTile_highlight .mx_RoomTile_badge:after {
content: "";
@ -78,39 +93,39 @@ limitations under the License.
display: block;
width: 0;
height: 0;
margin-left: 4px;
margin-left: 6px;
border-top: 8px solid #ff0064;
border-right: 10px solid transparent;
}
/* Because the specificity of this and the above ".mx_RoomTile_highlight .mx_RoomTile_badge:after"
style are the same, this style needs to be AFTER it to take effect when matched */
.collapsed .mx_RoomTile_badge:after {
display: none;
}
.mx_RoomTile_badge {
display: inline-block;
min-width: 14px;
height: 18px;
position: relative;
left: 8px;
top: 2px;
border-radius: 18px;
min-width: 19px;
height: 17px;
position: absolute;
right: 8px; /*gutter */
top: 9px;
border-radius: 14px;
color: #fff;
font-weight: bold;
font-weight: 600;
font-size: 11px;
text-align: center;
padding-top: 2px;
padding-top: 1px;
padding-left: 4px;
padding-right: 4px;
}
.mx_RoomTile_badge:hover {
.mx_RoomTile .mx_RoomTile_badge.mx_RoomTile_badgeButton,
.mx_RoomTile.mx_RoomTile_menu .mx_RoomTile_badge {
letter-spacing: 0.1em;
opacity: 1;
}
.mx_RoomTile.mx_RoomTile_noBadges .mx_RoomTile_badge.mx_RoomTile_badgeButton,
.mx_RoomTile.mx_RoomTile_menu.mx_RoomTile_noBadges .mx_RoomTile_badge {
background-color: rgb(214, 214, 214);
}
.mx_RoomTile_unreadNotify .mx_RoomTile_badge {
background-color: #76cfa6;
}
@ -119,26 +134,18 @@ style are the same, this style needs to be AFTER it to take effect when matched
background-color: #ff0064;
}
.mx_RoomTile_badge_no_unread {
background-color: rgb(214, 214, 214);
opacity: 0;
}
.mx_RoomTile_unread, .mx_RoomTile_highlight {
font-weight: bold;
font-weight: 800;
}
.mx_RoomTile_selected .mx_RoomTile_name span {
display: inline-block;
position: relative;
width: 100%;
padding: 4px;
margin-top: -4px;
margin-bottom: -4px;
border-radius: 2px;
.mx_RoomTile_selected {
background-color: rgba(118,207,166,0.2);
}
.mx_RoomTile .mx_RoomTile_name.mx_RoomTile_badgeShown {
width: 140px;
}
.mx_RoomTile_arrow {
position: absolute;
right: 0px;

47
src/skins/vector/css/matrix-react-sdk/views/settings/DevicesPanel.css

@ -0,0 +1,47 @@
/*
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_DevicesPanel {
display: table;
table-layout: fixed;
width: 880px;
border-spacing: 2px;
}
.mx_DevicesPanel_header {
display: table-header-group;
font-weight: bold;
}
.mx_DevicesPanel_header > div {
display: table-cell;
}
.mx_DevicesPanel_header .mx_DevicesPanel_deviceLastSeen {
width: 30%;
}
.mx_DevicesPanel_header .mx_DevicesPanel_deviceButtons {
width: 20%;
}
.mx_DevicesPanel_device {
display: table-row;
}
.mx_DevicesPanel_device > div {
display: table-cell;
}

33
src/skins/vector/css/matrix-react-sdk/views/settings/IntegrationsManager.css

@ -0,0 +1,33 @@
/*
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_IntegrationsManager {
display: -webkit-flex;
display: flex;
width: 100%;
height: 100%;
-webkit-align-items: center;
align-items: center;
justify-content: center;
-webkit-justify-content: center;
}
.mx_IntegrationsManager iframe {
background-color: #fff;
border: 0px;
width: 720px;
height: 512px;
}

13
src/skins/vector/css/vector-web/structures/LeftPanel.css

@ -51,6 +51,10 @@ limitations under the License.
overflow-y: auto;
}
.mx_LeftPanel.collapsed .mx_BottomLeftMenu {
flex: 0 0 120px;
}
.mx_LeftPanel .mx_BottomLeftMenu {
-webkit-box-ordinal-group: 3;
-moz-box-ordinal-group: 3;
@ -59,10 +63,11 @@ limitations under the License.
order: 3;
border-top: 1px solid rgba(0, 0, 0, 0.1);
margin-left: 18px;
margin-right: 18px;
margin-left: 16px; /* gutter */
margin-right: 16px; /* gutter */
-webkit-flex: 0 0 60px;
flex: 0 0 60px;
z-index: 1;
}
.mx_LeftPanel .mx_BottomLeftMenu_options {
@ -95,3 +100,7 @@ limitations under the License.
.mx_LeftPanel .mx_BottomLeftMenu_settings {
float: right;
}
.mx_LeftPanel.collapsed .mx_BottomLeftMenu_settings {
float: none;
}

25
src/skins/vector/css/vector-web/structures/RightPanel.css

@ -43,7 +43,7 @@ limitations under the License.
/** Fixme - factor this out with the main header **/
.mx_RightPanel_headerButtonGroup {
margin-top: 25px;
margin-top: 6px;
float: left;
background-color: #fff;
margin-left: -4px;
@ -55,34 +55,27 @@ limitations under the License.
vertical-align: middle;
padding-left: 15px;
padding-right: 15px;
text-align: center;
position: relative;
}
.mx_RightPanel_headerButton object {
pointer-events: none;
padding-bottom: 3px;
}
.mx_RightPanel_headerButton_highlight {
position: absolute;
bottom: -2px;
left: 10px;
width: 25px;
height: 4px;
background-color: #76cfa6;
height: 5px;
border-radius: 5px;
background-color: rgba(118, 207, 166, 0.2);
}
.mx_RightPanel_headerButton_badge {
position: absolute;
top: 4px;
left: 28px;
font-size: 12px;
background-color: #76cfa6;
color: #fff;
font-size: 11px;
color: #76cfa6;
font-weight: bold;
border-radius: 20px;
padding-left: 4px;
padding-righ