Proof of concept for a flair tab in user settings

This commit is contained in:
Travis Ralston 2019-01-25 15:35:32 -07:00
parent 2061ce2dbf
commit 57e45e7e7c
7 changed files with 79 additions and 65 deletions

View file

@ -44,3 +44,8 @@ limitations under the License.
.mx_UserSettingsDialog_labsIcon:before { .mx_UserSettingsDialog_labsIcon:before {
mask-image: url('$(res)/img/feather-icons/flag.svg'); mask-image: url('$(res)/img/feather-icons/flag.svg');
} }
.mx_UserSettingsDialog_flairIcon:before {
// TODO: Use the real icon
mask-image: url('$(res)/img/feather-icons/flag.svg');
}

View file

@ -20,19 +20,8 @@ limitations under the License.
margin: 8px; margin: 8px;
} }
.mx_GroupPublicity_toggle > label {
display: flex;
align-items: flex-start;
}
.mx_GroupPublicity_toggle > label,
.mx_GroupPublicity_toggle .mx_GroupTile { .mx_GroupPublicity_toggle .mx_GroupTile {
width: 50%; width: calc(100% - 60px); // 48px switch + some padding
}
.mx_GroupPublicity_toggle input {
margin-right: 8px;
vertical-align: -4px;
} }
.mx_GroupPublicity_toggle .mx_GroupTile { .mx_GroupPublicity_toggle .mx_GroupTile {
@ -40,3 +29,7 @@ limitations under the License.
align-items: flex-start; align-items: flex-start;
cursor: pointer; cursor: pointer;
} }
.mx_GroupPublicity_toggle .mx_ToggleSwitch {
float: right;
}

View file

@ -28,6 +28,7 @@ import NotificationSettingsTab from "../settings/tabs/NotificationSettingsTab";
import PreferencesSettingsTab from "../settings/tabs/PreferencesSettingsTab"; import PreferencesSettingsTab from "../settings/tabs/PreferencesSettingsTab";
import VoiceSettingsTab from "../settings/tabs/VoiceSettingsTab"; import VoiceSettingsTab from "../settings/tabs/VoiceSettingsTab";
import HelpSettingsTab from "../settings/tabs/HelpSettingsTab"; import HelpSettingsTab from "../settings/tabs/HelpSettingsTab";
import FlairSettingsTab from "../settings/tabs/FlairSettingsTab";
// TODO: Ditch this whole component // TODO: Ditch this whole component
export class TempTab extends React.Component { export class TempTab extends React.Component {
@ -58,6 +59,11 @@ export default class UserSettingsDialog extends React.Component {
"mx_UserSettingsDialog_settingsIcon", "mx_UserSettingsDialog_settingsIcon",
<GeneralSettingsTab />, <GeneralSettingsTab />,
)); ));
tabs.push(new Tab(
_td("Flair"),
"mx_UserSettingsDialog_flairIcon",
<FlairSettingsTab />,
));
tabs.push(new Tab( tabs.push(new Tab(
_td("Notifications"), _td("Notifications"),
"mx_UserSettingsDialog_bellIcon", "mx_UserSettingsDialog_bellIcon",

View file

@ -18,7 +18,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import sdk from '../../../index'; import sdk from '../../../index';
import GroupStore from '../../../stores/GroupStore'; import GroupStore from '../../../stores/GroupStore';
import { _t } from '../../../languageHandler.js'; import ToggleSwitch from "../elements/ToggleSwitch";
export default React.createClass({ export default React.createClass({
displayName: 'GroupPublicityToggle', displayName: 'GroupPublicityToggle',
@ -52,8 +52,7 @@ export default React.createClass({
if (this._groupStoreToken) this._groupStoreToken.unregister(); if (this._groupStoreToken) this._groupStoreToken.unregister();
}, },
_onPublicityToggle: function(e) { _onPublicityToggle: function() {
e.stopPropagation();
this.setState({ this.setState({
busy: true, busy: true,
// Optimistic early update // Optimistic early update
@ -68,21 +67,11 @@ export default React.createClass({
render() { render() {
const GroupTile = sdk.getComponent('groups.GroupTile'); const GroupTile = sdk.getComponent('groups.GroupTile');
const input = <input type="checkbox"
onChange={this._onPublicityToggle}
checked={this.state.isGroupPublicised}
/>;
const labelText = !this.state.ready ? _t("Loading...") :
(this.state.isGroupPublicised ?
_t("Flair will appear if enabled in room settings") :
_t("Flair will not appear")
);
return <div className="mx_GroupPublicity_toggle"> return <div className="mx_GroupPublicity_toggle">
<GroupTile groupId={this.props.groupId} showDescription={false} avatarHeight={40} /> <GroupTile groupId={this.props.groupId} showDescription={false} avatarHeight={40} />
<label onClick={this._onPublicityToggle}> <ToggleSwitch checked={this.state.isGroupPublicised}
{ input } disabled={!this.state.ready || this.state.busy}
{ labelText } onChange={this._onPublicityToggle} />
</label>
</div>; </div>;
}, },
}); });

View file

@ -43,9 +43,9 @@ export default React.createClass({
}); });
}, },
_renderGroupPublicity() { render() {
let text = ""; let text = "";
let scrollbox = <div />; let groupPublicityToggles = null;
const groups = this.state.groups; const groups = this.state.groups;
if (this.state.error) { if (this.state.error) {
@ -54,16 +54,10 @@ export default React.createClass({
text = _t('Loading...'); text = _t('Loading...');
} else if (groups.length > 0) { } else if (groups.length > 0) {
const GroupPublicityToggle = sdk.getComponent('groups.GroupPublicityToggle'); const GroupPublicityToggle = sdk.getComponent('groups.GroupPublicityToggle');
const GeminiScrollbarWrapper = sdk.getComponent('elements.GeminiScrollbarWrapper'); groupPublicityToggles = groups.map((groupId, index) => {
const groupPublicityToggles = groups.map((groupId, index) => {
return <GroupPublicityToggle key={index} groupId={groupId} />; return <GroupPublicityToggle key={index} groupId={groupId} />;
}); });
text = _t('Display your community flair in rooms configured to show it.'); text = _t('Display your community flair in rooms configured to show it.');
scrollbox = <div className="mx_GroupUserSettings_groupPublicity_scrollbox">
<GeminiScrollbarWrapper>
{ groupPublicityToggles }
</GeminiScrollbarWrapper>
</div>;
} else { } else {
text = _t("You're not currently a member of any communities."); text = _t("You're not currently a member of any communities.");
} }
@ -71,16 +65,10 @@ export default React.createClass({
return ( return (
<div> <div>
<p className="mx_SettingsTab_subsectionText">{ text }</p> <p className="mx_SettingsTab_subsectionText">{ text }</p>
{ scrollbox } <div className='mx_SettingsTab_subsectionText'>
{ groupPublicityToggles }
</div>
</div> </div>
); );
}, },
render() {
const groupPublicity = this._renderGroupPublicity();
return <div>
{ groupPublicity }
</div>;
},
}); });

View file

@ -0,0 +1,52 @@
/*
Copyright 2019 New Vector 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 {_t} from "../../../../languageHandler";
import {DragDropContext} from "react-beautiful-dnd";
import GroupUserSettings from "../../groups/GroupUserSettings";
import MatrixClientPeg from "../../../../MatrixClientPeg";
import PropTypes from "prop-types";
import {MatrixClient} from "matrix-js-sdk";
export default class FlairSettingsTab extends React.Component {
static childContextTypes = {
matrixClient: PropTypes.instanceOf(MatrixClient),
};
constructor() {
super();
}
getChildContext() {
return {
matrixClient: MatrixClientPeg.get(),
};
}
render() {
return (
<div className="mx_SettingsTab">
<span className="mx_SettingsTab_heading">{_t("Flair")}</span>
<div className="mx_SettingsTab_section">
<DragDropContext>
<GroupUserSettings />
</DragDropContext>
</div>
</div>
);
}
}

View file

@ -16,11 +16,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import {_t} from "../../../../languageHandler"; import {_t} from "../../../../languageHandler";
import MatrixClientPeg from "../../../../MatrixClientPeg";
import GroupUserSettings from "../../groups/GroupUserSettings";
import PropTypes from "prop-types";
import {MatrixClient} from "matrix-js-sdk"; import {MatrixClient} from "matrix-js-sdk";
import { DragDropContext } from 'react-beautiful-dnd';
import ProfileSettings from "../ProfileSettings"; import ProfileSettings from "../ProfileSettings";
import EmailAddresses from "../EmailAddresses"; import EmailAddresses from "../EmailAddresses";
import PhoneNumbers from "../PhoneNumbers"; import PhoneNumbers from "../PhoneNumbers";
@ -37,10 +33,6 @@ const Modal = require("../../../../Modal");
const dis = require("../../../../dispatcher"); const dis = require("../../../../dispatcher");
export default class GeneralSettingsTab extends React.Component { export default class GeneralSettingsTab extends React.Component {
static childContextTypes = {
matrixClient: PropTypes.instanceOf(MatrixClient),
};
constructor() { constructor() {
super(); super();
@ -50,12 +42,6 @@ export default class GeneralSettingsTab extends React.Component {
}; };
} }
getChildContext() {
return {
matrixClient: MatrixClientPeg.get(),
};
}
_onLanguageChange = (newLanguage) => { _onLanguageChange = (newLanguage) => {
if (this.state.language === newLanguage) return; if (this.state.language === newLanguage) return;
@ -110,11 +96,6 @@ export default class GeneralSettingsTab extends React.Component {
<div className="mx_SettingsTab_section"> <div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Profile")}</span> <span className="mx_SettingsTab_subheading">{_t("Profile")}</span>
<ProfileSettings /> <ProfileSettings />
<span className="mx_SettingsTab_subheading">{_t("Flair")}</span>
<DragDropContext>
<GroupUserSettings />
</DragDropContext>
</div> </div>
); );
} }