Implement new design for uploading/removing avatars
parent
2569b78db3
commit
9fa2680dc6
|
@ -175,6 +175,7 @@
|
||||||
@import "./views/rooms/_Stickers.scss";
|
@import "./views/rooms/_Stickers.scss";
|
||||||
@import "./views/rooms/_TopUnreadMessagesBar.scss";
|
@import "./views/rooms/_TopUnreadMessagesBar.scss";
|
||||||
@import "./views/rooms/_WhoIsTypingTile.scss";
|
@import "./views/rooms/_WhoIsTypingTile.scss";
|
||||||
|
@import "./views/settings/_AvatarSetting.scss";
|
||||||
@import "./views/settings/_CrossSigningPanel.scss";
|
@import "./views/settings/_CrossSigningPanel.scss";
|
||||||
@import "./views/settings/_DevicesPanel.scss";
|
@import "./views/settings/_DevicesPanel.scss";
|
||||||
@import "./views/settings/_EmailAddresses.scss";
|
@import "./views/settings/_EmailAddresses.scss";
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
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_AvatarSetting_avatar {
|
||||||
|
width: 88px;
|
||||||
|
height: 88px;
|
||||||
|
margin-left: 13px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
width: 88px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton.mx_AccessibleButton_kind_primary {
|
||||||
|
margin-top: 8px;
|
||||||
|
|
||||||
|
div {
|
||||||
|
position: relative;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
display: inline;
|
||||||
|
padding-right: 6px; // 0.5 * 12px
|
||||||
|
left: -6px; // 0.5 * 12px
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
|
||||||
|
background-color: $button-primary-fg-color;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: contain;
|
||||||
|
mask-image: url('$(res)/img/feather-customised/upload.svg');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton.mx_AccessibleButton_kind_link_sm {
|
||||||
|
color: $button-danger-bg-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > img,
|
||||||
|
.mx_AvatarSetting_avatarPlaceholder {
|
||||||
|
display: block;
|
||||||
|
height: 88px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AvatarSetting_avatarPlaceholder::before {
|
||||||
|
background-color: $settings-profile-overlay-placeholder-fg-color;
|
||||||
|
mask: url("$(res)/img/feather-customised/user.svg");
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: 36px;
|
||||||
|
mask-position: center;
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AvatarSetting_avatar .mx_AvatarSetting_avatarPlaceholder {
|
||||||
|
background-color: $settings-profile-placeholder-bg-color;
|
||||||
|
}
|
|
@ -38,91 +38,6 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_ProfileSettings_avatar {
|
|
||||||
width: 88px;
|
|
||||||
height: 88px;
|
|
||||||
margin-left: 13px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatar > * {
|
|
||||||
display: block;
|
|
||||||
width: 88px;
|
|
||||||
height: 88px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatar .mx_ProfileSettings_avatarOverlay_disabled {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatar .mx_ProfileSettings_avatarPlaceholder {
|
|
||||||
background-color: $settings-profile-placeholder-bg-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatarOverlay {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
display: none;
|
|
||||||
text-align: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
font-size: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatar:hover .mx_ProfileSettings_avatarOverlay:not(.mx_ProfileSettings_avatarOverlay_disabled) {
|
|
||||||
display: inline-block;
|
|
||||||
opacity: 0.5 !important;
|
|
||||||
color: $settings-profile-overlay-fg-color !important;
|
|
||||||
background-color: $settings-profile-overlay-bg-color !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatarOverlay_show {
|
|
||||||
display: inline-block;
|
|
||||||
opacity: 1;
|
|
||||||
color: $settings-profile-overlay-placeholder-fg-color;
|
|
||||||
background-color: $settings-profile-overlay-placeholder-bg-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatarOverlayText {
|
|
||||||
display: block;
|
|
||||||
margin-top: 17px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_noAvatarText {
|
|
||||||
display: block;
|
|
||||||
margin: 34px auto auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatarOverlayImgContainer {
|
|
||||||
position: relative;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatarOverlayImg::before {
|
|
||||||
background-color: $settings-profile-overlay-placeholder-fg-color;
|
|
||||||
mask: url("$(res)/img/feather-customised/upload.svg");
|
|
||||||
mask-repeat: no-repeat;
|
|
||||||
mask-size: 14px;
|
|
||||||
mask-position: center;
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatar:hover .mx_ProfileSettings_avatarOverlayImg::before {
|
|
||||||
background-color: $settings-profile-overlay-fg-color !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ProfileSettings_avatarUpload {
|
.mx_ProfileSettings_avatarUpload {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@ import PropTypes from 'prop-types';
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
import MatrixClientPeg from "../../../MatrixClientPeg";
|
import MatrixClientPeg from "../../../MatrixClientPeg";
|
||||||
import Field from "../elements/Field";
|
import Field from "../elements/Field";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import sdk from "../../../index";
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
// TODO: Merge with ProfileSettings?
|
// TODO: Merge with ProfileSettings?
|
||||||
export default class RoomProfileSettings extends React.Component {
|
export default class RoomProfileSettings extends React.Component {
|
||||||
|
@ -62,13 +61,20 @@ export default class RoomProfileSettings extends React.Component {
|
||||||
this._avatarUpload = createRef();
|
this._avatarUpload = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
_uploadAvatar = (e) => {
|
_uploadAvatar = () => {
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
this._avatarUpload.current.click();
|
this._avatarUpload.current.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_removeAvatar = () => {
|
||||||
|
// clear file upload field so same file can be selected
|
||||||
|
this._avatarUpload.current.value = "";
|
||||||
|
this.setState({
|
||||||
|
avatarUrl: undefined,
|
||||||
|
avatarFile: undefined,
|
||||||
|
enableProfileSave: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
_saveProfile = async (e) => {
|
_saveProfile = async (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -139,45 +145,8 @@ export default class RoomProfileSettings extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// TODO: Why is rendering a box with an overlay so complicated? Can the DOM be reduced?
|
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||||
|
const AvatarSetting = sdk.getComponent('settings.AvatarSetting');
|
||||||
let showOverlayAnyways = true;
|
|
||||||
let avatarElement = <div className="mx_ProfileSettings_avatarPlaceholder" />;
|
|
||||||
if (this.state.avatarUrl) {
|
|
||||||
showOverlayAnyways = false;
|
|
||||||
avatarElement = <img src={this.state.avatarUrl}
|
|
||||||
alt={_t("Room avatar")} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const avatarOverlayClasses = classNames({
|
|
||||||
"mx_ProfileSettings_avatarOverlay": true,
|
|
||||||
"mx_ProfileSettings_avatarOverlay_show": showOverlayAnyways,
|
|
||||||
});
|
|
||||||
let avatarHoverElement = (
|
|
||||||
<div className={avatarOverlayClasses} onClick={this._uploadAvatar}>
|
|
||||||
<span className="mx_ProfileSettings_avatarOverlayText">{_t("Upload room avatar")}</span>
|
|
||||||
<div className="mx_ProfileSettings_avatarOverlayImgContainer">
|
|
||||||
<div className="mx_ProfileSettings_avatarOverlayImg" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
if (!this.state.canSetAvatar) {
|
|
||||||
if (!showOverlayAnyways) {
|
|
||||||
avatarHoverElement = null;
|
|
||||||
} else {
|
|
||||||
const disabledOverlayClasses = classNames({
|
|
||||||
"mx_ProfileSettings_avatarOverlay": true,
|
|
||||||
"mx_ProfileSettings_avatarOverlay_show": true,
|
|
||||||
"mx_ProfileSettings_avatarOverlay_disabled": true,
|
|
||||||
});
|
|
||||||
avatarHoverElement = (
|
|
||||||
<div className={disabledOverlayClasses}>
|
|
||||||
<span className="mx_ProfileSettings_noAvatarText">{_t("No room avatar")}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
|
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
|
||||||
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
||||||
|
@ -191,10 +160,11 @@ export default class RoomProfileSettings extends React.Component {
|
||||||
type="text" value={this.state.topic} autoComplete="off"
|
type="text" value={this.state.topic} autoComplete="off"
|
||||||
onChange={this._onTopicChanged} element="textarea" />
|
onChange={this._onTopicChanged} element="textarea" />
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_ProfileSettings_avatar">
|
<AvatarSetting
|
||||||
{avatarElement}
|
avatarUrl={this.state.avatarUrl}
|
||||||
{avatarHoverElement}
|
avatarAltText={_t("Room avatar")}
|
||||||
</div>
|
uploadAvatar={this.state.canSetAvatar ? this._uploadAvatar : undefined}
|
||||||
|
removeAvatar={this.state.canSetAvatar ? this._removeAvatar : undefined} />
|
||||||
</div>
|
</div>
|
||||||
<AccessibleButton onClick={this._saveProfile} kind="primary"
|
<AccessibleButton onClick={this._saveProfile} kind="primary"
|
||||||
disabled={!this.state.enableProfileSave}>
|
disabled={!this.state.enableProfileSave}>
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
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 PropTypes from "prop-types";
|
||||||
|
|
||||||
|
import sdk from "../../../index";
|
||||||
|
import {_t} from "../../../languageHandler";
|
||||||
|
|
||||||
|
const AvatarSetting = ({avatarUrl, avatarAltText, uploadAvatar, removeAvatar}) => {
|
||||||
|
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||||
|
|
||||||
|
let avatarElement = <div className="mx_AvatarSetting_avatarPlaceholder" />;
|
||||||
|
if (avatarUrl) {
|
||||||
|
avatarElement = <img src={avatarUrl} alt={avatarAltText} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uploadAvatarBtn;
|
||||||
|
if (uploadAvatar) {
|
||||||
|
// insert an empty div to be the host for a css mask containing the upload.svg
|
||||||
|
uploadAvatarBtn = <AccessibleButton onClick={uploadAvatar} kind="primary">
|
||||||
|
<div> </div>
|
||||||
|
{_t("Upload")}
|
||||||
|
</AccessibleButton>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let removeAvatarBtn;
|
||||||
|
if (avatarUrl && removeAvatar) {
|
||||||
|
removeAvatarBtn = <AccessibleButton onClick={removeAvatar} kind="link_sm">
|
||||||
|
{_t("Remove")}
|
||||||
|
</AccessibleButton>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="mx_AvatarSetting_avatar">
|
||||||
|
{ avatarElement }
|
||||||
|
{ uploadAvatarBtn }
|
||||||
|
{ removeAvatarBtn }
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
AvatarSetting.propTypes = {
|
||||||
|
avatarUrl: PropTypes.string,
|
||||||
|
uploadAvatar: PropTypes.func,
|
||||||
|
removeAvatar: PropTypes.func,
|
||||||
|
avatarAltText: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AvatarSetting;
|
|
@ -18,10 +18,9 @@ import React, {createRef} from 'react';
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
import MatrixClientPeg from "../../../MatrixClientPeg";
|
import MatrixClientPeg from "../../../MatrixClientPeg";
|
||||||
import Field from "../elements/Field";
|
import Field from "../elements/Field";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import {User} from "matrix-js-sdk";
|
import {User} from "matrix-js-sdk";
|
||||||
import { getHostingLink } from '../../../utils/HostingLink';
|
import { getHostingLink } from '../../../utils/HostingLink';
|
||||||
|
import sdk from "../../../index";
|
||||||
|
|
||||||
export default class ProfileSettings extends React.Component {
|
export default class ProfileSettings extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -52,13 +51,20 @@ export default class ProfileSettings extends React.Component {
|
||||||
this._avatarUpload = createRef();
|
this._avatarUpload = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
_uploadAvatar = (e) => {
|
_uploadAvatar = () => {
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
this._avatarUpload.current.click();
|
this._avatarUpload.current.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_removeAvatar = () => {
|
||||||
|
// clear file upload field so same file can be selected
|
||||||
|
this._avatarUpload.current.value = "";
|
||||||
|
this.setState({
|
||||||
|
avatarUrl: undefined,
|
||||||
|
avatarFile: undefined,
|
||||||
|
enableProfileSave: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
_saveProfile = async (e) => {
|
_saveProfile = async (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -117,29 +123,6 @@ export default class ProfileSettings extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// TODO: Why is rendering a box with an overlay so complicated? Can the DOM be reduced?
|
|
||||||
|
|
||||||
let showOverlayAnyways = true;
|
|
||||||
let avatarElement = <div className="mx_ProfileSettings_avatarPlaceholder" />;
|
|
||||||
if (this.state.avatarUrl) {
|
|
||||||
showOverlayAnyways = false;
|
|
||||||
avatarElement = <img src={this.state.avatarUrl}
|
|
||||||
alt={_t("Profile picture")} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const avatarOverlayClasses = classNames({
|
|
||||||
"mx_ProfileSettings_avatarOverlay": true,
|
|
||||||
"mx_ProfileSettings_avatarOverlay_show": showOverlayAnyways,
|
|
||||||
});
|
|
||||||
const avatarHoverElement = (
|
|
||||||
<div className={avatarOverlayClasses} onClick={this._uploadAvatar}>
|
|
||||||
<span className="mx_ProfileSettings_avatarOverlayText">{_t("Upload profile picture")}</span>
|
|
||||||
<div className="mx_ProfileSettings_avatarOverlayImgContainer">
|
|
||||||
<div className="mx_ProfileSettings_avatarOverlayImg" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const hostingSignupLink = getHostingLink('user-settings');
|
const hostingSignupLink = getHostingLink('user-settings');
|
||||||
let hostingSignup = null;
|
let hostingSignup = null;
|
||||||
if (hostingSignupLink) {
|
if (hostingSignupLink) {
|
||||||
|
@ -156,6 +139,8 @@ export default class ProfileSettings extends React.Component {
|
||||||
</span>;
|
</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||||
|
const AvatarSetting = sdk.getComponent('settings.AvatarSetting');
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
|
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
|
||||||
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
||||||
|
@ -170,10 +155,11 @@ export default class ProfileSettings extends React.Component {
|
||||||
type="text" value={this.state.displayName} autoComplete="off"
|
type="text" value={this.state.displayName} autoComplete="off"
|
||||||
onChange={this._onDisplayNameChanged} />
|
onChange={this._onDisplayNameChanged} />
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_ProfileSettings_avatar">
|
<AvatarSetting
|
||||||
{avatarElement}
|
avatarUrl={this.state.avatarUrl}
|
||||||
{avatarHoverElement}
|
avatarAltText={_t("Profile picture")}
|
||||||
</div>
|
uploadAvatar={this._uploadAvatar}
|
||||||
|
removeAvatar={this._removeAvatar} />
|
||||||
</div>
|
</div>
|
||||||
<AccessibleButton onClick={this._saveProfile} kind="primary"
|
<AccessibleButton onClick={this._saveProfile} kind="primary"
|
||||||
disabled={!this.state.enableProfileSave}>
|
disabled={!this.state.enableProfileSave}>
|
||||||
|
|
|
@ -499,6 +499,8 @@
|
||||||
"Pin": "Pin",
|
"Pin": "Pin",
|
||||||
"Decline (%(counter)s)": "Decline (%(counter)s)",
|
"Decline (%(counter)s)": "Decline (%(counter)s)",
|
||||||
"Accept <policyLink /> to continue:": "Accept <policyLink /> to continue:",
|
"Accept <policyLink /> to continue:": "Accept <policyLink /> to continue:",
|
||||||
|
"Upload": "Upload",
|
||||||
|
"Remove": "Remove",
|
||||||
"Failed to upload profile picture!": "Failed to upload profile picture!",
|
"Failed to upload profile picture!": "Failed to upload profile picture!",
|
||||||
"Upload new:": "Upload new:",
|
"Upload new:": "Upload new:",
|
||||||
"No display name": "No display name",
|
"No display name": "No display name",
|
||||||
|
@ -597,10 +599,9 @@
|
||||||
"Off": "Off",
|
"Off": "Off",
|
||||||
"On": "On",
|
"On": "On",
|
||||||
"Noisy": "Noisy",
|
"Noisy": "Noisy",
|
||||||
"Profile picture": "Profile picture",
|
|
||||||
"Upload profile picture": "Upload profile picture",
|
|
||||||
"<a>Upgrade</a> to your own domain": "<a>Upgrade</a> to your own domain",
|
"<a>Upgrade</a> to your own domain": "<a>Upgrade</a> to your own domain",
|
||||||
"Display Name": "Display Name",
|
"Display Name": "Display Name",
|
||||||
|
"Profile picture": "Profile picture",
|
||||||
"Save": "Save",
|
"Save": "Save",
|
||||||
"Identity Server URL must be HTTPS": "Identity Server URL must be HTTPS",
|
"Identity Server URL must be HTTPS": "Identity Server URL must be HTTPS",
|
||||||
"Not a valid Identity Server (status code %(code)s)": "Not a valid Identity Server (status code %(code)s)",
|
"Not a valid Identity Server (status code %(code)s)": "Not a valid Identity Server (status code %(code)s)",
|
||||||
|
@ -691,7 +692,6 @@
|
||||||
"User rules": "User rules",
|
"User rules": "User rules",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
"You have not ignored anyone.": "You have not ignored anyone.",
|
"You have not ignored anyone.": "You have not ignored anyone.",
|
||||||
"Remove": "Remove",
|
|
||||||
"You are currently ignoring:": "You are currently ignoring:",
|
"You are currently ignoring:": "You are currently ignoring:",
|
||||||
"You are not subscribed to any lists": "You are not subscribed to any lists",
|
"You are not subscribed to any lists": "You are not subscribed to any lists",
|
||||||
"Unsubscribe": "Unsubscribe",
|
"Unsubscribe": "Unsubscribe",
|
||||||
|
@ -1097,11 +1097,9 @@
|
||||||
"Showing flair for these communities:": "Showing flair for these communities:",
|
"Showing flair for these communities:": "Showing flair for these communities:",
|
||||||
"This room is not showing flair for any communities": "This room is not showing flair for any communities",
|
"This room is not showing flair for any communities": "This room is not showing flair for any communities",
|
||||||
"New community ID (e.g. +foo:%(localDomain)s)": "New community ID (e.g. +foo:%(localDomain)s)",
|
"New community ID (e.g. +foo:%(localDomain)s)": "New community ID (e.g. +foo:%(localDomain)s)",
|
||||||
"Room avatar": "Room avatar",
|
|
||||||
"Upload room avatar": "Upload room avatar",
|
|
||||||
"No room avatar": "No room avatar",
|
|
||||||
"Room Name": "Room Name",
|
"Room Name": "Room Name",
|
||||||
"Room Topic": "Room Topic",
|
"Room Topic": "Room Topic",
|
||||||
|
"Room avatar": "Room avatar",
|
||||||
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
|
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
|
||||||
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
|
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
|
||||||
"URL previews are enabled by default for participants in this room.": "URL previews are enabled by default for participants in this room.",
|
"URL previews are enabled by default for participants in this room.": "URL previews are enabled by default for participants in this room.",
|
||||||
|
@ -1545,7 +1543,6 @@
|
||||||
"Upload files (%(current)s of %(total)s)": "Upload files (%(current)s of %(total)s)",
|
"Upload files (%(current)s of %(total)s)": "Upload files (%(current)s of %(total)s)",
|
||||||
"Upload files": "Upload files",
|
"Upload files": "Upload files",
|
||||||
"Upload all": "Upload all",
|
"Upload all": "Upload all",
|
||||||
"Upload": "Upload",
|
|
||||||
"This file is <b>too large</b> to upload. The file size limit is %(limit)s but this file is %(sizeOfThisFile)s.": "This file is <b>too large</b> to upload. The file size limit is %(limit)s but this file is %(sizeOfThisFile)s.",
|
"This file is <b>too large</b> to upload. The file size limit is %(limit)s but this file is %(sizeOfThisFile)s.": "This file is <b>too large</b> to upload. The file size limit is %(limit)s but this file is %(sizeOfThisFile)s.",
|
||||||
"These files are <b>too large</b> to upload. The file size limit is %(limit)s.": "These files are <b>too large</b> to upload. The file size limit is %(limit)s.",
|
"These files are <b>too large</b> to upload. The file size limit is %(limit)s.": "These files are <b>too large</b> to upload. The file size limit is %(limit)s.",
|
||||||
"Some files are <b>too large</b> to be uploaded. The file size limit is %(limit)s.": "Some files are <b>too large</b> to be uploaded. The file size limit is %(limit)s.",
|
"Some files are <b>too large</b> to be uploaded. The file size limit is %(limit)s.": "Some files are <b>too large</b> to be uploaded. The file size limit is %(limit)s.",
|
||||||
|
|
Loading…
Reference in New Issue