mirror of
https://github.com/element-hq/element-web
synced 2024-11-25 18:55:58 +03:00
Add new create group dialog
This commit is contained in:
parent
8feda74156
commit
7c1a9993e3
12 changed files with 474 additions and 5 deletions
|
@ -72,6 +72,7 @@
|
||||||
@import "./views/dialogs/_KeyboardShortcutsDialog.scss";
|
@import "./views/dialogs/_KeyboardShortcutsDialog.scss";
|
||||||
@import "./views/dialogs/_MessageEditHistoryDialog.scss";
|
@import "./views/dialogs/_MessageEditHistoryDialog.scss";
|
||||||
@import "./views/dialogs/_NewSessionReviewDialog.scss";
|
@import "./views/dialogs/_NewSessionReviewDialog.scss";
|
||||||
|
@import "./views/dialogs/_PrototypeCreateGroupDialog.scss";
|
||||||
@import "./views/dialogs/_RoomSettingsDialog.scss";
|
@import "./views/dialogs/_RoomSettingsDialog.scss";
|
||||||
@import "./views/dialogs/_RoomSettingsDialogBridges.scss";
|
@import "./views/dialogs/_RoomSettingsDialogBridges.scss";
|
||||||
@import "./views/dialogs/_RoomUpgradeDialog.scss";
|
@import "./views/dialogs/_RoomUpgradeDialog.scss";
|
||||||
|
@ -106,6 +107,7 @@
|
||||||
@import "./views/elements/_FormButton.scss";
|
@import "./views/elements/_FormButton.scss";
|
||||||
@import "./views/elements/_IconButton.scss";
|
@import "./views/elements/_IconButton.scss";
|
||||||
@import "./views/elements/_ImageView.scss";
|
@import "./views/elements/_ImageView.scss";
|
||||||
|
@import "./views/elements/_InfoTooltip.scss";
|
||||||
@import "./views/elements/_InlineSpinner.scss";
|
@import "./views/elements/_InlineSpinner.scss";
|
||||||
@import "./views/elements/_ManageIntegsButton.scss";
|
@import "./views/elements/_ManageIntegsButton.scss";
|
||||||
@import "./views/elements/_PowerSelector.scss";
|
@import "./views/elements/_PowerSelector.scss";
|
||||||
|
|
102
res/css/views/dialogs/_PrototypeCreateGroupDialog.scss
Normal file
102
res/css/views/dialogs/_PrototypeCreateGroupDialog.scss
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 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_PrototypeCreateGroupDialog {
|
||||||
|
.mx_Dialog_content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.mx_PrototypeCreateGroupDialog_colName {
|
||||||
|
flex-basis: 66.66%;
|
||||||
|
padding-right: 100px;
|
||||||
|
|
||||||
|
.mx_Field input {
|
||||||
|
font-size: $font-16px;
|
||||||
|
line-height: $font-20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_PrototypeCreateGroupDialog_subtext {
|
||||||
|
display: block;
|
||||||
|
color: $muted-fg-color;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mx_PrototypeCreateGroupDialog_subtext_error {
|
||||||
|
color: $warning-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_PrototypeCreateGroupDialog_communityId {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.mx_InfoTooltip {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton {
|
||||||
|
display: block;
|
||||||
|
height: 32px;
|
||||||
|
font-size: $font-16px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_PrototypeCreateGroupDialog_colAvatar {
|
||||||
|
flex-basis: 33.33%;
|
||||||
|
|
||||||
|
.mx_PrototypeCreateGroupDialog_avatarContainer {
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.mx_PrototypeCreateGroupDialog_avatar,
|
||||||
|
.mx_PrototypeCreateGroupDialog_placeholderAvatar {
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
border-radius: 96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_PrototypeCreateGroupDialog_placeholderAvatar {
|
||||||
|
background-color: #368BD6; // hardcoded for both themes
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #fff; // hardcoded because the background is
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: 96px;
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
mask-position: center;
|
||||||
|
content: '';
|
||||||
|
vertical-align: middle;
|
||||||
|
mask-image: url('$(res)/img/element-icons/add-photo.svg');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_PrototypeCreateGroupDialog_tip {
|
||||||
|
&>b, &>span {
|
||||||
|
display: block;
|
||||||
|
color: $muted-fg-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
res/css/views/elements/_InfoTooltip.scss
Normal file
34
res/css/views/elements/_InfoTooltip.scss
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 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_InfoTooltip_icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_InfoTooltip_icon::before {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: $muted-fg-color;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: 16px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
mask-position: center;
|
||||||
|
content: '';
|
||||||
|
vertical-align: middle;
|
||||||
|
mask-image: url('$(res)/img/element-icons/info.svg');
|
||||||
|
}
|
5
res/img/element-icons/add-photo.svg
Normal file
5
res/img/element-icons/add-photo.svg
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<svg width="84" height="84" viewBox="0 0 84 84" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M36.7988 34.9062C37.077 33.5217 38.2978 32.5 39.7396 32.5H44.2604C45.7022 32.5 46.923 33.5217 47.2012 34.9062C47.2429 35.1137 47.3232 35.3141 47.4627 35.4731L48.0649 36.1595C48.2548 36.3759 48.5287 36.5 48.8166 36.5H52C53.1046 36.5 54 37.3954 54 38.5V49.5C54 50.6046 53.1046 51.5 52 51.5H32C30.8954 51.5 30 50.6046 30 49.5V38.5C30 37.3954 30.8954 36.5 32 36.5H35.1834C35.4713 36.5 35.7452 36.3759 35.9351 36.1595L36.5373 35.4731C36.6768 35.3141 36.7571 35.1137 36.7988 34.9062ZM42 47.5C44.2091 47.5 46 45.7091 46 43.5C46 41.2909 44.2091 39.5 42 39.5C39.7909 39.5 38 41.2909 38 43.5C38 45.7091 39.7909 47.5 42 47.5Z" fill="white"/>
|
||||||
|
<rect x="32" y="35" width="3" height="1" rx="0.5" fill="white"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M59.75 27C59.75 26.5858 59.4142 26.25 59 26.25C58.5858 26.25 58.25 26.5858 58.25 27V31.25L54 31.25C53.5858 31.25 53.25 31.5858 53.25 32C53.25 32.4142 53.5858 32.75 54 32.75L58.25 32.75V37C58.25 37.4142 58.5858 37.75 59 37.75C59.4142 37.75 59.75 37.4142 59.75 37V32.75L64 32.75C64.4142 32.75 64.75 32.4142 64.75 32C64.75 31.5858 64.4142 31.25 64 31.25L59.75 31.25V27Z" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
4
res/img/element-icons/info.svg
Normal file
4
res/img/element-icons/info.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="10" cy="10" r="9.5" stroke="#787878"/>
|
||||||
|
<path d="M9.79248 14H11.2065V8H9.79248V14ZM10.5034 7.14844C10.9526 7.14844 11.3198 6.80469 11.3198 6.38281C11.3198 5.95703 10.9526 5.61328 10.5034 5.61328C10.0503 5.61328 9.68311 5.95703 9.68311 6.38281C9.68311 6.80469 10.0503 7.14844 10.5034 7.14844Z" fill="#787878"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 424 B |
|
@ -77,6 +77,7 @@ import ErrorDialog from "../views/dialogs/ErrorDialog";
|
||||||
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
|
||||||
import { SettingLevel } from "../../settings/SettingLevel";
|
import { SettingLevel } from "../../settings/SettingLevel";
|
||||||
import { leaveRoomBehaviour } from "../../utils/membership";
|
import { leaveRoomBehaviour } from "../../utils/membership";
|
||||||
|
import PrototypeCreateGroupDialog from "../views/dialogs/PrototypeCreateGroupDialog";
|
||||||
|
|
||||||
/** constants for MatrixChat.state.view */
|
/** constants for MatrixChat.state.view */
|
||||||
export enum Views {
|
export enum Views {
|
||||||
|
@ -620,7 +621,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
this.createRoom(payload.public);
|
this.createRoom(payload.public);
|
||||||
break;
|
break;
|
||||||
case 'view_create_group': {
|
case 'view_create_group': {
|
||||||
const CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog");
|
let CreateGroupDialog = sdk.getComponent("dialogs.CreateGroupDialog")
|
||||||
|
if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
|
||||||
|
CreateGroupDialog = PrototypeCreateGroupDialog;
|
||||||
|
}
|
||||||
Modal.createTrackedDialog('Create Community', '', CreateGroupDialog);
|
Modal.createTrackedDialog('Create Community', '', CreateGroupDialog);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
19
src/components/views/dialogs/IDialogProps.ts
Normal file
19
src/components/views/dialogs/IDialogProps.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface IDialogProps {
|
||||||
|
onFinished: (bool) => void;
|
||||||
|
}
|
217
src/components/views/dialogs/PrototypeCreateGroupDialog.tsx
Normal file
217
src/components/views/dialogs/PrototypeCreateGroupDialog.tsx
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 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, { ChangeEvent } from 'react';
|
||||||
|
import BaseDialog from "./BaseDialog";
|
||||||
|
import { _t } from "../../../languageHandler";
|
||||||
|
import { IDialogProps } from "./IDialogProps";
|
||||||
|
import Field from "../elements/Field";
|
||||||
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
import InfoTooltip from "../elements/InfoTooltip";
|
||||||
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
|
|
||||||
|
interface IProps extends IDialogProps {
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
name: string;
|
||||||
|
localpart: string;
|
||||||
|
error: string;
|
||||||
|
busy: boolean;
|
||||||
|
avatarFile: File;
|
||||||
|
avatarPreview: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class PrototypeCreateGroupDialog extends React.PureComponent<IProps, IState> {
|
||||||
|
private avatarUploadRef: React.RefObject<HTMLInputElement> = React.createRef();
|
||||||
|
|
||||||
|
constructor(props: IProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
name: "",
|
||||||
|
localpart: "",
|
||||||
|
error: null,
|
||||||
|
busy: false,
|
||||||
|
avatarFile: null,
|
||||||
|
avatarPreview: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private onNameChange = (ev: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const localpart = (ev.target.value || "").toLowerCase().replace(/[^a-z0-9.\-_]/g, '-');
|
||||||
|
this.setState({name: ev.target.value, localpart});
|
||||||
|
};
|
||||||
|
|
||||||
|
private onSubmit = async (ev) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
if (this.state.busy) return;
|
||||||
|
|
||||||
|
// We'll create the community now to see if it's taken, leaving it active in
|
||||||
|
// the background for the user to look at while they invite people.
|
||||||
|
this.setState({busy: true});
|
||||||
|
try {
|
||||||
|
let avatarUrl = null;
|
||||||
|
if (this.state.avatarFile) {
|
||||||
|
avatarUrl = await MatrixClientPeg.get().uploadContent(this.state.avatarFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await MatrixClientPeg.get().createGroup({
|
||||||
|
localpart: this.state.localpart,
|
||||||
|
profile: {
|
||||||
|
name: this.state.name,
|
||||||
|
avatar_url: avatarUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ensure the tag gets selected now that we've created it
|
||||||
|
dis.dispatch({action: 'deselect_tags'}, true);
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'select_tag',
|
||||||
|
tag: result.group_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.room_id) {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'view_room',
|
||||||
|
room_id: result.room_id,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'view_group',
|
||||||
|
group_id: result.group_id,
|
||||||
|
group_is_new: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Show invite dialog
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
this.setState({
|
||||||
|
busy: false,
|
||||||
|
error: _t(
|
||||||
|
"There was an error creating your community. The name may be taken or the " +
|
||||||
|
"server is unable to process your request.",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private onAvatarChanged = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (!e.target.files || !e.target.files.length) {
|
||||||
|
this.setState({avatarFile: null});
|
||||||
|
} else {
|
||||||
|
this.setState({busy: true});
|
||||||
|
const file = e.target.files[0];
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (ev: ProgressEvent<FileReader>) => {
|
||||||
|
this.setState({avatarFile: file, busy: false, avatarPreview: ev.target.result as string});
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private onChangeAvatar = () => {
|
||||||
|
if (this.avatarUploadRef.current) this.avatarUploadRef.current.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
let communityId = null;
|
||||||
|
if (this.state.localpart) {
|
||||||
|
communityId = (
|
||||||
|
<span className="mx_PrototypeCreateGroupDialog_communityId">
|
||||||
|
{_t("Community ID: +<localpart />:%(domain)s", {
|
||||||
|
domain: MatrixClientPeg.getHomeserverName(),
|
||||||
|
}, {
|
||||||
|
localpart: () => <u>{this.state.localpart}</u>,
|
||||||
|
})}
|
||||||
|
<InfoTooltip
|
||||||
|
tooltip={_t(
|
||||||
|
"Use this when referencing your community to others. The community ID " +
|
||||||
|
"cannot be changed.",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let helpText = (
|
||||||
|
<span className="mx_PrototypeCreateGroupDialog_subtext">
|
||||||
|
{_t("You can change this later if needed.")}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
if (this.state.error) {
|
||||||
|
helpText = (
|
||||||
|
<span className="mx_PrototypeCreateGroupDialog_subtext mx_PrototypeCreateGroupDialog_subtext_error">
|
||||||
|
{this.state.error}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let preview = <img src={this.state.avatarPreview} className="mx_PrototypeCreateGroupDialog_avatar" />;
|
||||||
|
if (!this.state.avatarPreview) {
|
||||||
|
preview = <div className="mx_PrototypeCreateGroupDialog_placeholderAvatar" />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseDialog
|
||||||
|
className="mx_PrototypeCreateGroupDialog"
|
||||||
|
onFinished={this.props.onFinished}
|
||||||
|
title={_t("What's the name of your community or team?")}
|
||||||
|
>
|
||||||
|
<form onSubmit={this.onSubmit}>
|
||||||
|
<div className="mx_Dialog_content">
|
||||||
|
<div className="mx_PrototypeCreateGroupDialog_colName">
|
||||||
|
<Field
|
||||||
|
value={this.state.name}
|
||||||
|
onChange={this.onNameChange}
|
||||||
|
placeholder={_t("Enter name")}
|
||||||
|
label={_t("Enter name")}
|
||||||
|
/>
|
||||||
|
{helpText}
|
||||||
|
<span className="mx_PrototypeCreateGroupDialog_subtext">
|
||||||
|
{/*nbsp is to reserve the height of this element when there's nothing*/}
|
||||||
|
{communityId}
|
||||||
|
</span>
|
||||||
|
<AccessibleButton kind="primary" onClick={this.onSubmit} disabled={this.state.busy}>
|
||||||
|
{_t("Create")}
|
||||||
|
</AccessibleButton>
|
||||||
|
</div>
|
||||||
|
<div className="mx_PrototypeCreateGroupDialog_colAvatar">
|
||||||
|
<input
|
||||||
|
type="file" style={{display: "none"}}
|
||||||
|
ref={this.avatarUploadRef} accept="image/*"
|
||||||
|
onChange={this.onAvatarChanged}
|
||||||
|
/>
|
||||||
|
<AccessibleButton onClick={this.onChangeAvatar} className="mx_PrototypeCreateGroupDialog_avatarContainer">
|
||||||
|
{preview}
|
||||||
|
</AccessibleButton>
|
||||||
|
<div className="mx_PrototypeCreateGroupDialog_tip">
|
||||||
|
<b>{_t("PRO TIP")}</b>
|
||||||
|
<span>
|
||||||
|
{_t("An image will help people identify your community.")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</BaseDialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,9 +27,9 @@ import Spinner from "../elements/Spinner";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
|
import { IDialogProps } from "./IDialogProps";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps extends IDialogProps {
|
||||||
onFinished: (bool) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ServerOfflineDialog extends React.PureComponent<IProps> {
|
export default class ServerOfflineDialog extends React.PureComponent<IProps> {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {toRightOf} from "../../structures/ContextMenu";
|
||||||
import {copyPlaintext, selectText} from "../../../utils/strings";
|
import {copyPlaintext, selectText} from "../../../utils/strings";
|
||||||
import StyledCheckbox from '../elements/StyledCheckbox';
|
import StyledCheckbox from '../elements/StyledCheckbox';
|
||||||
import AccessibleTooltipButton from '../elements/AccessibleTooltipButton';
|
import AccessibleTooltipButton from '../elements/AccessibleTooltipButton';
|
||||||
|
import { IDialogProps } from "./IDialogProps";
|
||||||
|
|
||||||
const socials = [
|
const socials = [
|
||||||
{
|
{
|
||||||
|
@ -60,8 +61,7 @@ const socials = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
interface IProps {
|
interface IProps extends IDialogProps {
|
||||||
onFinished: () => void;
|
|
||||||
target: Room | User | Group | RoomMember | MatrixEvent;
|
target: Room | User | Group | RoomMember | MatrixEvent;
|
||||||
permalinkCreator: RoomPermalinkCreator;
|
permalinkCreator: RoomPermalinkCreator;
|
||||||
}
|
}
|
||||||
|
|
73
src/components/views/elements/InfoTooltip.tsx
Normal file
73
src/components/views/elements/InfoTooltip.tsx
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||||
|
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 classNames from 'classnames';
|
||||||
|
|
||||||
|
import AccessibleButton from "./AccessibleButton";
|
||||||
|
import Tooltip from './Tooltip';
|
||||||
|
import { _t } from "../../../languageHandler";
|
||||||
|
|
||||||
|
interface ITooltipProps {
|
||||||
|
tooltip?: React.ReactNode;
|
||||||
|
tooltipClassName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
hover: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class InfoTooltip extends React.PureComponent<ITooltipProps, IState> {
|
||||||
|
constructor(props: ITooltipProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
hover: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseOver = () => {
|
||||||
|
this.setState({
|
||||||
|
hover: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMouseLeave = () => {
|
||||||
|
this.setState({
|
||||||
|
hover: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {tooltip, children, tooltipClassName} = this.props;
|
||||||
|
const title = _t("Information");
|
||||||
|
|
||||||
|
// Tooltip are forced on the right for a more natural feel to them on info icons
|
||||||
|
const tip = this.state.hover ? <Tooltip
|
||||||
|
className="mx_InfoTooltip_container"
|
||||||
|
tooltipClassName={classNames("mx_InfoTooltip_tooltip", tooltipClassName)}
|
||||||
|
label={tooltip || title}
|
||||||
|
forceOnRight={true}
|
||||||
|
/> : <div />;
|
||||||
|
return (
|
||||||
|
<div onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave} className="mx_InfoTooltip">
|
||||||
|
<span className="mx_InfoTooltip_icon" aria-label={title} />
|
||||||
|
{children}
|
||||||
|
{tip}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1484,6 +1484,7 @@
|
||||||
"Rotate Right": "Rotate Right",
|
"Rotate Right": "Rotate Right",
|
||||||
"Rotate clockwise": "Rotate clockwise",
|
"Rotate clockwise": "Rotate clockwise",
|
||||||
"Download this file": "Download this file",
|
"Download this file": "Download this file",
|
||||||
|
"Information": "Information",
|
||||||
"Language Dropdown": "Language Dropdown",
|
"Language Dropdown": "Language Dropdown",
|
||||||
"Manage Integrations": "Manage Integrations",
|
"Manage Integrations": "Manage Integrations",
|
||||||
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
|
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
|
||||||
|
@ -1728,6 +1729,14 @@
|
||||||
"Use this session to verify your new one, granting it access to encrypted messages:": "Use this session to verify your new one, granting it access to encrypted messages:",
|
"Use this session to verify your new one, granting it access to encrypted messages:": "Use this session to verify your new one, granting it access to encrypted messages:",
|
||||||
"If you didn’t sign in to this session, your account may be compromised.": "If you didn’t sign in to this session, your account may be compromised.",
|
"If you didn’t sign in to this session, your account may be compromised.": "If you didn’t sign in to this session, your account may be compromised.",
|
||||||
"This wasn't me": "This wasn't me",
|
"This wasn't me": "This wasn't me",
|
||||||
|
"There was an error creating your community. The name may be taken or the server is unable to process your request.": "There was an error creating your community. The name may be taken or the server is unable to process your request.",
|
||||||
|
"Community ID: +<localpart />:%(domain)s": "Community ID: +<localpart />:%(domain)s",
|
||||||
|
"Use this when referencing your community to others. The community ID cannot be changed.": "Use this when referencing your community to others. The community ID cannot be changed.",
|
||||||
|
"You can change this later if needed.": "You can change this later if needed.",
|
||||||
|
"What's the name of your community or team?": "What's the name of your community or team?",
|
||||||
|
"Enter name": "Enter name",
|
||||||
|
"PRO TIP": "PRO TIP",
|
||||||
|
"An image will help people identify your community.": "An image will help people identify your community.",
|
||||||
"If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.": "If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.",
|
"If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.": "If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.",
|
||||||
"To help avoid duplicate issues, please <existingIssuesLink>view existing issues</existingIssuesLink> first (and add a +1) or <newIssueLink>create a new issue</newIssueLink> if you can't find it.": "To help avoid duplicate issues, please <existingIssuesLink>view existing issues</existingIssuesLink> first (and add a +1) or <newIssueLink>create a new issue</newIssueLink> if you can't find it.",
|
"To help avoid duplicate issues, please <existingIssuesLink>view existing issues</existingIssuesLink> first (and add a +1) or <newIssueLink>create a new issue</newIssueLink> if you can't find it.": "To help avoid duplicate issues, please <existingIssuesLink>view existing issues</existingIssuesLink> first (and add a +1) or <newIssueLink>create a new issue</newIssueLink> if you can't find it.",
|
||||||
"Report bugs & give feedback": "Report bugs & give feedback",
|
"Report bugs & give feedback": "Report bugs & give feedback",
|
||||||
|
|
Loading…
Reference in a new issue