Merge pull request #4039 from vector-im/new-guest-access

New guest access
This commit is contained in:
Luke Barnard 2017-06-07 13:40:00 +01:00 committed by GitHub
commit a158549a4c
300 changed files with 1201 additions and 221 deletions

View file

@ -1,5 +1,6 @@
/*
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.
@ -14,21 +15,21 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import sdk from 'matrix-react-sdk';
import dis from 'matrix-react-sdk/lib/dispatcher';
import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
import Velocity from 'velocity-vector';
import 'velocity-vector/velocity.ui';
var React = require('react');
var ReactDOM = require('react-dom');
var sdk = require('matrix-react-sdk');
import { _t } from 'matrix-react-sdk/lib/languageHandler';
var dis = require('matrix-react-sdk/lib/dispatcher');
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
const CALLOUT_ANIM_DURATION = 1000;
module.exports = React.createClass({
displayName: 'BottomLeftMenu',
propTypes: {
collapsed: React.PropTypes.bool.isRequired,
teamToken: React.PropTypes.string,
},
getInitialState: function() {
@ -41,6 +42,18 @@ module.exports = React.createClass({
});
},
componentWillMount: function() {
this._dispatcherRef = dis.register(this.onAction);
this._peopleButton = null;
this._directoryButton = null;
this._createRoomButton = null;
this._lastCallouts = {};
},
componentWillUnmount: function() {
dis.unregister(this._dispatcherRef);
},
// Room events
onDirectoryClick: function() {
dis.dispatch({ action: 'view_room_directory' });
@ -105,6 +118,30 @@ module.exports = React.createClass({
this.setState({ settingsHover: false });
},
onAction: function(payload) {
let calloutElement;
switch (payload.action) {
// Incoming instruction: dance!
case 'callout_start_chat':
calloutElement = this._peopleButton;
break;
case 'callout_room_directory':
calloutElement = this._directoryButton;
break;
case 'callout_create_room':
calloutElement = this._createRoomButton;
break;
}
if (calloutElement) {
const lastCallout = this._lastCallouts[payload.action];
const now = Date.now();
if (lastCallout == undefined || lastCallout < now - CALLOUT_ANIM_DURATION) {
this._lastCallouts[payload.action] = now;
Velocity(ReactDOM.findDOMNode(calloutElement), "callout.bounce", CALLOUT_ANIM_DURATION);
}
}
},
// Get the label/tooltip to show
getLabel: function(label, show) {
if (show) {
@ -113,39 +150,41 @@ module.exports = React.createClass({
}
},
render: function() {
var TintableSvg = sdk.getComponent('elements.TintableSvg');
_collectPeopleButton: function(e) {
this._peopleButton = e;
},
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(_t("Welcome page"), this.state.homeHover) }
</AccessibleButton>
);
}
_collectDirectoryButton: function(e) {
this._directoryButton = e;
},
_collectCreateRoomButton: function(e) {
this._createRoomButton = e;
},
render: function() {
const HomeButton = sdk.getComponent('elements.HomeButton');
const StartChatButton = sdk.getComponent('elements.StartChatButton');
const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton');
const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton');
const SettingsButton = sdk.getComponent('elements.SettingsButton');
return (
<div className="mx_BottomLeftMenu">
<div className="mx_BottomLeftMenu_options">
{ homeButton }
<AccessibleButton className="mx_BottomLeftMenu_people" onClick={ this.onPeopleClick } onMouseEnter={ this.onPeopleMouseEnter } onMouseLeave={ this.onPeopleMouseLeave } >
<TintableSvg src="img/icons-people.svg" width="25" height="25" />
{ this.getLabel(_t("Start chat"), this.state.peopleHover) }
</AccessibleButton>
<AccessibleButton className="mx_BottomLeftMenu_directory" onClick={ this.onDirectoryClick } onMouseEnter={ this.onDirectoryMouseEnter } onMouseLeave={ this.onDirectoryMouseLeave } >
<TintableSvg src="img/icons-directory.svg" width="25" height="25"/>
{ this.getLabel(_t("Room directory"), this.state.directoryHover) }
</AccessibleButton>
<AccessibleButton className="mx_BottomLeftMenu_createRoom" onClick={ this.onRoomsClick } onMouseEnter={ this.onRoomsMouseEnter } onMouseLeave={ this.onRoomsMouseLeave } >
<TintableSvg src="img/icons-create-room.svg" width="25" height="25" />
{ this.getLabel(_t("Create new room"), this.state.roomsHover) }
</AccessibleButton>
<AccessibleButton className="mx_BottomLeftMenu_settings" onClick={ this.onSettingsClick } onMouseEnter={ this.onSettingsMouseEnter } onMouseLeave={ this.onSettingsMouseLeave } >
<TintableSvg src="img/icons-settings.svg" width="25" height="25" />
{ this.getLabel(_t("Settings"), this.state.settingsHover) }
</AccessibleButton>
<HomeButton tooltip={true} />
<div ref={this._collectPeopleButton}>
<StartChatButton tooltip={true} />
</div>
<div ref={this._collectDirectoryButton}>
<RoomDirectoryButton tooltip={true} />
</div>
<div ref={this._collectCreateRoomButton}>
<CreateRoomButton tooltip={true} />
</div>
<span className="mx_BottomLeftMenu_settings">
<SettingsButton tooltip={true} />
</span>
</div>
</div>
);

View file

@ -20,21 +20,74 @@ limitations under the License.
import React from 'react';
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
import sdk from 'matrix-react-sdk';
import GeminiScrollbar from 'react-gemini-scrollbar';
import request from 'browser-request';
import { _t } from 'matrix-react-sdk/lib/languageHandler';
import sanitizeHtml from 'sanitize-html';
module.exports = React.createClass({
displayName: 'HomePage',
propTypes: {
teamServerUrl: React.PropTypes.string.isRequired,
teamToken: React.PropTypes.string.isRequired,
collapsedRhs: React.PropTypes.bool,
// URL base of the team server. Optional.
teamServerUrl: React.PropTypes.string,
// Team token. Optional. If set, used to get the static homepage of the team
// associated. If unset, homePageUrl will be used.
teamToken: React.PropTypes.string,
// URL to use as the iFrame src. Defaults to /home.html.
homePageUrl: React.PropTypes.string,
},
getInitialState: function() {
return {
iframeSrc: '',
page: '',
};
},
componentWillMount: function() {
if (this.props.teamToken && this.props.teamServerUrl) {
this.setState({
iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`
});
}
else {
// we use request() to inline the homepage into the react component
// so that it can inherit CSS and theming easily rather than mess around
// with iframes and trying to synchronise document.stylesheets.
let src = this.props.homePageUrl || 'home.html';
request(
{ method: "GET", url: src },
(err, response, body) => {
if (err || response.status < 200 || response.status >= 300) {
console.log(err);
this.setState({ page: "Couldn't load home page" });
}
body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>{ return sanitizeHtml(_t(g1)) });
this.setState({ page: body });
}
);
}
},
render: function() {
return (
<div className="mx_HomePage">
<iframe src={`${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`}/>
</div>
);
if (this.state.iframeSrc) {
return (
<div className="mx_HomePage">
<iframe src={ this.state.iframeSrc } />
</div>
);
}
else {
return (
<GeminiScrollbar autoshow={true} className="mx_HomePage">
<div className="mx_HomePage_body" dangerouslySetInnerHTML={{ __html: this.state.page }}>
</div>
</GeminiScrollbar>
);
}
}
});

View file

@ -21,16 +21,18 @@ var DragDropContext = require('react-dnd').DragDropContext;
var HTML5Backend = require('react-dnd-html5-backend');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
var VectorConferenceHandler = require('../../VectorConferenceHandler');
var CallHandler = require("matrix-react-sdk/lib/CallHandler");
import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
var LeftPanel = React.createClass({
displayName: 'LeftPanel',
propTypes: {
collapsed: React.PropTypes.bool.isRequired,
teamToken: React.PropTypes.string,
},
getInitialState: function() {
@ -97,17 +99,21 @@ var LeftPanel = React.createClass({
render: function() {
var RoomList = sdk.getComponent('rooms.RoomList');
var BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu');
var SearchBox = sdk.getComponent('structures.SearchBox');
var collapseButton;
var topBox;
if (MatrixClientPeg.get().isGuest()) {
var LoginBox = sdk.getComponent('structures.LoginBox');
topBox = <LoginBox collapsed={ this.props.collapsed }/>;
}
else {
var SearchBox = sdk.getComponent('structures.SearchBox');
topBox = <SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />;
}
var classes = "mx_LeftPanel mx_fadable";
if (this.props.collapsed) {
classes += " collapsed";
}
else {
// Hide the collapse button until we work out how to display it in the new skin
// collapseButton = <img className="mx_LeftPanel_hideButton" onClick={ this.onHideClick } src="img/hide.png" width="12" height="20" alt="<"/>
}
var callPreview;
if (this.state.showCallElement && !this.props.collapsed) {
@ -121,15 +127,14 @@ var LeftPanel = React.createClass({
return (
<aside className={classes} style={{ opacity: this.props.opacity }}>
<SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />
{ collapseButton }
{ topBox }
{ callPreview }
<RoomList
selectedRoom={this.props.selectedRoom}
collapsed={this.props.collapsed}
searchFilter={this.state.searchFilter}
ConferenceHandler={VectorConferenceHandler} />
<BottomLeftMenu collapsed={this.props.collapsed} teamToken={this.props.teamToken}/>
<BottomLeftMenu collapsed={this.props.collapsed}/>
</aside>
);
}

View file

@ -0,0 +1,86 @@
/*
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';
var React = require('react');
import { _t } from 'matrix-react-sdk/lib/languageHandler';
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
module.exports = React.createClass({
displayName: 'LoginBox',
propTypes: {
collapsed: React.PropTypes.bool,
},
onToggleCollapse: function(show) {
if (show) {
dis.dispatch({
action: 'show_left_panel',
});
}
else {
dis.dispatch({
action: 'hide_left_panel',
});
}
},
onLoginClick: function() {
dis.dispatch({ action: 'start_login' });
},
render: function() {
var TintableSvg = sdk.getComponent('elements.TintableSvg');
var toggleCollapse;
if (this.props.collapsed) {
toggleCollapse =
<AccessibleButton className="mx_SearchBox_maximise" onClick={ this.onToggleCollapse.bind(this, true) }>
<TintableSvg src="img/maximise.svg" width="10" height="16" alt="Expand panel"/>
</AccessibleButton>
}
else {
toggleCollapse =
<AccessibleButton className="mx_SearchBox_minimise" onClick={ this.onToggleCollapse.bind(this, false) }>
<TintableSvg src="img/minimise.svg" width="10" height="16" alt="Collapse panel"/>
</AccessibleButton>
}
var loginButton;
if (!this.props.collapsed) {
loginButton = (
<div className="mx_LoginBox_loginButton_wrapper">
<AccessibleButton className="mx_LoginBox_loginButton" element="button" onClick={this.onLoginClick}>
{ _t("Login") }
</AccessibleButton>
</div>
);
}
var self = this;
return (
<div className="mx_SearchBox">
{ loginButton }
{ toggleCollapse }
</div>
);
}
});

View file

@ -93,11 +93,7 @@ module.exports = React.createClass({
onInviteButtonClick: function() {
if (MatrixClientPeg.get().isGuest()) {
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
Modal.createDialog(NeedToRegisterDialog, {
title: _t('Please Register'),
description: _t('Guest users can\'t invite users. Please register to invite.')
});
dis.dispatch({action: 'view_set_mxid'});
return;
}
@ -224,7 +220,7 @@ module.exports = React.createClass({
<div className="mx_RightPanel_headerButton mx_RightPanel_collapsebutton" title={ _t("Hide panel") } onClick={ this.onCollapseClick }>
<TintableSvg src="img/minimise.svg" width="10" height="16"/>
</div>
</div>;
</div>;
}
if (!this.props.collapsed) {

View file

@ -353,11 +353,7 @@ module.exports = React.createClass({
// to the directory.
if (MatrixClientPeg.get().isGuest()) {
if (!room.world_readable && !room.guest_can_join) {
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
Modal.createDialog(NeedToRegisterDialog, {
title: _t('Failed to join the room'),
description: _t('This room is inaccessible to guests. You may be able to join if you register.')
});
dis.dispatch({action: 'view_set_mxid'});
return;
}
}

View file

@ -1,4 +1,5 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2015, 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
@ -84,6 +85,8 @@ var RoomSubList = React.createClass({
incomingCall: React.PropTypes.object,
onShowMoreRooms: React.PropTypes.func,
searchFilter: React.PropTypes.string,
emptyContent: React.PropTypes.node, // content shown if the list is empty
headerItems: React.PropTypes.node, // content shown in the sublist header
},
getInitialState: function() {
@ -522,16 +525,15 @@ var RoomSubList = React.createClass({
render: function() {
var connectDropTarget = this.props.connectDropTarget;
var RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget');
var TruncatedList = sdk.getComponent('elements.TruncatedList');
var label = this.props.collapsed ? null : this.props.label;
//console.log("render: " + JSON.stringify(this.state.sortedList));
var target;
if (this.state.sortedList.length == 0 && this.props.editable) {
target = <RoomDropTarget label={ _t("Drop here %(toAction)s", {toAction: this.props.verb}) }/>;
let content;
if (this.state.sortedList.length == 0) {
content = this.props.emptyContent;
} else {
content = this.makeRoomTiles();
}
if (this.state.sortedList.length > 0 || this.props.editable) {
@ -541,8 +543,7 @@ var RoomSubList = React.createClass({
if (!this.state.hidden) {
subList = <TruncatedList className={ classes } truncateAt={this.state.truncateAt}
createOverflowElement={this._createOverflowTile} >
{ target }
{ this.makeRoomTiles() }
{ content }
</TruncatedList>;
}
else {

View file

@ -0,0 +1,118 @@
/*
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 React from 'react';
import sdk from 'matrix-react-sdk';
import { _t } from 'matrix-react-sdk/lib/languageHandler';
/**
* Prompt the user to set a password
*
* On success, `onFinished()` when finished
*/
export default React.createClass({
displayName: 'SetPasswordDialog',
propTypes: {
onFinished: React.PropTypes.func.isRequired,
},
getInitialState: function() {
return {
error: null,
success: false,
};
},
_onPasswordChanged: function() {
this.setState({
success: true,
});
},
_onContinueClicked: function() {
this.props.onFinished(true);
},
_onPasswordChangeError: function(err) {
let errMsg = err.error || "";
if (err.httpStatus === 403) {
errMsg = _t('Failed to change password. Is your password correct?');
} else if (err.httpStatus) {
errMsg += _t(
' (HTTP status %(httpStatus))',
{ httpStatus: err.httpStatus },
);
}
this.setState({
error: errMsg,
});
},
render: function() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const ChangePassword = sdk.getComponent('views.settings.ChangePassword');
if (this.state.success) {
return (
<BaseDialog className="mx_SetPasswordDialog"
onFinished={this.props.onFinished}
title={ _t('You have successfully set a password!') }
>
<div className="mx_Dialog_content">
<p>
{ _t('You can now return to your account after signing out, and sign in on other devices.') }
</p>
</div>
<div className="mx_Dialog_buttons">
<button
className="mx_Dialog_primary"
autoFocus={true}
onClick={this._onContinueClicked}>
{ _t('Continue') }
</button>
</div>
</BaseDialog>
);
}
return (
<BaseDialog className="mx_SetPasswordDialog"
onFinished={this.props.onFinished}
title={ _t('Please set a password!') }
>
<div className="mx_Dialog_content">
<p>
{ _t('This will allow you to return to your account after signing out, and sign in on other devices.') }
</p>
<ChangePassword
className="mx_SetPasswordDialog_change_password"
rowClassName=""
rowLabelClassName=""
rowInputClassName=""
buttonClassName="mx_Dialog_primary mx_SetPasswordDialog_change_password_button"
confirm={false}
autoFocusNewPasswordInput={true}
onError={this._onPasswordChangeError}
onFinished={this._onPasswordChanged} />
<div className="error">
{ this.state.error }
</div>
</div>
</BaseDialog>
);
},
});

View file

@ -1,54 +0,0 @@
/*
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.
*/
var React = require('react');
var dis = require('matrix-react-sdk/lib/dispatcher');
import { _tJsx } from 'matrix-react-sdk/lib/languageHandler';
module.exports = React.createClass({
displayName: 'GuestWarningBar',
onRegisterClicked: function() {
dis.dispatch({'action': 'start_upgrade_registration'});
},
onLoginClicked: function() {
dis.dispatch({'action': 'logout'});
dis.dispatch({'action': 'start_login'});
},
render: function() {
return (
<div className="mx_GuestWarningBar">
<img className="mx_GuestWarningBar_warning" src="img/warning.svg" width="24" height="23" alt="/!\"/>
<div>
{ _tJsx(
"You are Rioting as a guest. <a>Register</a> or <a>sign in</a> to access more rooms and features!",
[
/<a>(.*?)<\/a>/,
/<a>(.*?)<\/a>/
],
[
(sub) => <a onClick={this.onRegisterClicked}>{sub}</a>,
(sub) => <a onClick={this.onLoginClicked}>{sub}</a>
]
) }
</div>
</div>
);
}
});

View file

@ -0,0 +1,60 @@
/*
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 sdk from 'matrix-react-sdk';
import Modal from 'matrix-react-sdk/lib/Modal';
import dis from 'matrix-react-sdk/lib/dispatcher';
export default React.createClass({
onUpdateClicked: function() {
const SetPasswordDialog = sdk.getComponent('dialogs.SetPasswordDialog');
Modal.createDialog(SetPasswordDialog, {
onFinished: (passwordChanged) => {
if (!passwordChanged) {
return;
}
// Notify SessionStore that the user's password was changed
dis.dispatch({
action: 'password_changed',
});
}
});
},
render: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const toolbarClasses = "mx_MatrixToolbar mx_MatrixToolbar_clickable";
return (
<div className={toolbarClasses} onClick={this.onUpdateClicked}>
<img className="mx_MatrixToolbar_warning"
src="img/warning.svg"
width="24"
height="23"
alt="Warning"
/>
<div className="mx_MatrixToolbar_content">
To return to your account in future you need to <u>set a password</u>
</div>
<button className="mx_MatrixToolbar_action">
Set Password
</button>
</div>
);
}
});

View file

@ -67,6 +67,7 @@
"Invite to this room": "Invite to this room",
"Keywords": "Keywords",
"Leave": "Leave",
"Login": "Login",
"Loading bug report module": "Loading bug report module",
"Low Priority": "Low Priority",
"Members": "Members",
@ -160,5 +161,39 @@
"OK": "OK",
"You need to be using HTTPS to place a screen-sharing call.": "You need to be using HTTPS to place a screen-sharing call.",
"Welcome page": "Welcome page",
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!"
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!",
"Welcome to Riot.im": "Welcome to Riot.im",
"Decentralised, encrypted chat &amp; collaboration powered by": "Decentralised, encrypted chat &amp; collaboration powered by",
"Search the room directory": "Search the room directory",
"Chat with Riot Bot": "Chat with Riot Bot",
"Get started with some tips from Riot Bot!": "Get started with some tips from Riot Bot!",
"General discussion about Matrix": "General discussion about Matrix",
"Discussion of all things Matrix!": "Discussion of all things Matrix!",
"Riot/Web &amp; Desktop chat": "Riot/Web &amp; Desktop chat",
"Riot/iOS &amp; matrix-ios-sdk chat": "Riot/iOS &amp; matrix-ios-sdk chat",
"Riot/Android &amp; matrix-android-sdk chat": "Riot/Android &amp; matrix-android-sdk chat",
"Matrix technical discussions": "Matrix technical discussions",
"Running Matrix services": "Running Matrix services",
"Community-run support for Synapse": "Community-run support for Synapse",
"Admin support for Dendrite": "Admin support for Dendrite",
"Announcements about Synapse releases": "Announcements about Synapse releases",
"Support for those using and running matrix-appservice-irc": "Support for those using and running matrix-appservice-irc",
"Building services on Matrix": "Building services on Matrix",
"Support for those using the Matrix spec": "Support for those using the Matrix spec",
"Design and implementation of E2E in Matrix": "Design and implementation of E2E in Matrix",
"Implementing VR services with Matrix": "Implementing VR services with Matrix",
"Implementing VoIP services with Matrix": "Implementing VoIP services with Matrix",
"Discussion of the Identity Service API": "Discussion of the Identity Service API",
"Support for those using, running and writing other bridges": "Support for those using, running and writing other bridges",
"Contributing code to Matrix and Riot": "Contributing code to Matrix and Riot",
"Dev chat for the Riot/Web dev team": "Dev chat for the Riot/Web dev team",
"Dev chat for the Dendrite dev team": "Dev chat for the Dendrite dev team",
"Co-ordination for Riot/Web translators": "Co-ordination for Riot/Web translators",
"Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!",
"Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
"You have successfully set a password!": "You have successfully set a password!",
"You can now return to your account after signing out, and sign in on other devices.": "You can now return to your account after signing out, and sign in on other devices.",
"Continue": "Continue",
"Please set a password!": "Please set a password!",
"This will allow you to return to your account after signing out, and sign in on other devices.": "This will allow you to return to your account after signing out, and sign in on other devices."
}

View file

@ -3,6 +3,7 @@
@import "./matrix-react-sdk/structures/_ContextualMenu.scss";
@import "./matrix-react-sdk/structures/_CreateRoom.scss";
@import "./matrix-react-sdk/structures/_FilePanel.scss";
@import "./matrix-react-sdk/structures/_LoginBox.scss";
@import "./matrix-react-sdk/structures/_MatrixChat.scss";
@import "./matrix-react-sdk/structures/_NotificationPanel.scss";
@import "./matrix-react-sdk/structures/_RoomStatusBar.scss";
@ -17,7 +18,7 @@
@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/_SetDisplayNameDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_SetMxIdDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss";
@import "./matrix-react-sdk/views/elements/_AccessibleButton.scss";
@import "./matrix-react-sdk/views/elements/_AddressSelector.scss";
@ -27,6 +28,7 @@
@import "./matrix-react-sdk/views/elements/_MemberEventListSummary.scss";
@import "./matrix-react-sdk/views/elements/_ProgressBar.scss";
@import "./matrix-react-sdk/views/elements/_RichText.scss";
@import "./matrix-react-sdk/views/elements/_RoleButton.scss";
@import "./matrix-react-sdk/views/login/_InteractiveAuthEntryComponents.scss";
@import "./matrix-react-sdk/views/login/_ServerConfig.scss";
@import "./matrix-react-sdk/views/messages/_MEmoteBody.scss";
@ -69,10 +71,10 @@
@import "./vector-web/views/context_menus/_MessageContextMenu.scss";
@import "./vector-web/views/context_menus/_RoomTileContextMenu.scss";
@import "./vector-web/views/dialogs/_ChangelogDialog.scss";
@import "./vector-web/views/dialogs/_SetPasswordDialog.scss";
@import "./vector-web/views/directory/_NetworkDropdown.scss";
@import "./vector-web/views/elements/_ImageView.scss";
@import "./vector-web/views/elements/_Spinner.scss";
@import "./vector-web/views/globals/_GuestWarningBar.scss";
@import "./vector-web/views/globals/_MatrixToolbar.scss";
@import "./vector-web/views/messages/_MessageTimestamp.scss";
@import "./vector-web/views/messages/_SenderProfile.scss";

View file

@ -1,5 +1,5 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
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.
@ -14,23 +14,23 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_GuestWarningBar {
.mx_LoginBox_loginButton_wrapper {
text-align: center;
width: 100%;
}
.mx_LoginBox_loginButton {
margin-top: -8px;
height: 40px;
border: 0px;
border-radius: 40px;
padding-left: 1em;
padding-right: 1em;
background-color: $accent-color;
color: $accent-fg-color;
color: $primary-bg-color;
display: flex;
align-items: center;
}
.mx_GuestWarningBar_warning {
margin-left: 16px;
margin-right: 8px;
margin-top: -2px;
}
.mx_GuestWarningBar a {
color: $accent-fg-color ! important;
text-decoration: underline ! important;
cursor: pointer;
}
font-size: 15px;
}

View file

@ -41,12 +41,6 @@ limitations under the License.
height: 40px;
}
.mx_GuestWarningBar {
order: 1;
height: 40px;
}
.mx_MatrixChat_toolbarShowing {
height: auto;
}

View file

@ -20,8 +20,22 @@ limitations under the License.
.mx_ChatCreateOrReuseDialog .mx_Dialog_content {
margin-bottom: 24px;
/*
To stop spinner that mx_ChatCreateOrReuseDialog_profile replaces from causing a
height change
*/
min-height: 100px;
}
.mx_ChatCreateOrReuseDialog .mx_RoomTile_badge {
display: none;
}
.mx_ChatCreateOrReuseDialog_profile {
display: flex;
}
.mx_ChatCreateOrReuseDialog_profile_name {
padding: 14px;
}

View file

@ -0,0 +1,50 @@
/*
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.
*/
.mx_SetMxIdDialog .mx_Dialog_title {
padding-right: 40px;
}
.mx_SetMxIdDialog_input_group {
display: flex;
}
.mx_SetMxIdDialog_input {
border-radius: 3px;
border: 1px solid $input-border-color;
padding: 9px;
color: $primary-fg-color;
background-color: $primary-bg-color;
font-size: 15px;
width: 100%;
max-width: 280px;
}
.mx_SetMxIdDialog_input.error,
.mx_SetMxIdDialog_input.error:focus {
border: 1px solid $warning-color;
}
.mx_SetMxIdDialog_input_group .mx_Spinner {
height: 37px;
padding-left: 10px;
justify-content: flex-start;
}
.mx_SetMxIdDialog .success {
color: $accent-color;
}

View file

@ -0,0 +1,33 @@
/*
Copyright 2107 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_RoleButton {
margin-left: 4px;
margin-right: 4px;
cursor: pointer;
display: inline-block;
}
.mx_RoleButton object {
pointer-events: none;
}
.mx_RoleButton_tooltip {
display: inline-block;
position: relative;
top: -25px;
left: 6px;
}

View file

@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2107 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.
@ -37,3 +38,25 @@ limitations under the License.
.mx_RoomList_scrollbar .gm-scrollbar.-vertical {
z-index: 6;
}
.mx_RoomList_emptySubListTip {
font-size: 13px;
margin-left: 18px;
margin-right: 18px;
margin-top: 8px;
margin-bottom: 7px;
padding: 5px;
border: 1px dashed $accent-color;
color: $primary-fg-color;
background-color: $droptarget-bg-color;
border-radius: 4px;
}
.mx_RoomList_emptySubListTip .mx_RoleButton {
vertical-align: -3px;
}
.mx_RoomList_headerButtons {
position: absolute;
right: 60px;
}

View file

@ -30,5 +30,5 @@ limitations under the License.
}
.mx_HomePage_body {
margin-left: 63px;
// margin-left: 63px;
}

View file

@ -64,47 +64,33 @@ limitations under the License.
pointer-events: none;
}
.mx_LeftPanel .mx_BottomLeftMenu_homePage,
.mx_LeftPanel .mx_BottomLeftMenu_directory,
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
.mx_LeftPanel .mx_BottomLeftMenu_people,
.mx_LeftPanel .mx_BottomLeftMenu_settings {
display: inline-block;
cursor: pointer;
}
.collapsed .mx_BottomLeftMenu_homePage,
.collapsed .mx_BottomLeftMenu_directory,
.collapsed .mx_BottomLeftMenu_createRoom,
.collapsed .mx_BottomLeftMenu_people,
.collapsed .mx_BottomLeftMenu_settings {
.collapsed .mx_RoleButton {
margin-right: 0px ! important;
padding-top: 3px ! important;
padding-bottom: 3px ! important;
}
.mx_LeftPanel .mx_BottomLeftMenu_homePage,
.mx_LeftPanel .mx_BottomLeftMenu_directory,
.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
.mx_LeftPanel .mx_BottomLeftMenu_people {
.mx_BottomLeftMenu_options > div {
display: inline-block;
}
.mx_BottomLeftMenu_options .mx_RoleButton {
margin-left: 0px;
margin-right: 10px;
}
.mx_LeftPanel .mx_BottomLeftMenu_settings {
.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings {
float: right;
}
.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings .mx_RoleButton {
margin-right: 0px;
}
.mx_LeftPanel.collapsed .mx_BottomLeftMenu_settings {
float: none;
}
.mx_LeftPanel .mx_BottomLeftMenu_tooltip {
display: inline-block;
position: relative;
top: -25px;
left: 6px;
}
.mx_MatrixChat_useCompactLayout {
.mx_LeftPanel .mx_BottomLeftMenu {
flex: 0 0 50px;

View file

@ -1,5 +1,5 @@
/*
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.
@ -14,11 +14,22 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_SetDisplayNameDialog_input {
.mx_SetPasswordDialog_change_password input {
border-radius: 3px;
border: 1px solid $input-border-color;
padding: 9px;
color: $primary-fg-color;
background-color: $primary-bg-color;
font-size: 15px;
}
width: 100%;
max-width: 280px;
margin-bottom: 10px;
}
.mx_SetPasswordDialog_change_password_button {
margin-top: 68px;
}
.mx_SetPasswordDialog .mx_Dialog_content {
margin-bottom: 0px;
}

View file

@ -39,6 +39,10 @@ limitations under the License.
cursor: pointer;
}
.mx_MatrixToolbar_clickable {
cursor: pointer;
}
.mx_MatrixToolbar_close {
cursor: pointer;
}