Use MiniAvatarUploader for the new NewRoomIntro component
This commit is contained in:
parent
6aeea3e38e
commit
664079a127
6 changed files with 208 additions and 4 deletions
|
@ -184,6 +184,7 @@
|
||||||
@import "./views/rooms/_MemberList.scss";
|
@import "./views/rooms/_MemberList.scss";
|
||||||
@import "./views/rooms/_MessageComposer.scss";
|
@import "./views/rooms/_MessageComposer.scss";
|
||||||
@import "./views/rooms/_MessageComposerFormatBar.scss";
|
@import "./views/rooms/_MessageComposerFormatBar.scss";
|
||||||
|
@import "./views/rooms/_NewRoomIntro.scss";
|
||||||
@import "./views/rooms/_NotificationBadge.scss";
|
@import "./views/rooms/_NotificationBadge.scss";
|
||||||
@import "./views/rooms/_PinnedEventTile.scss";
|
@import "./views/rooms/_PinnedEventTile.scss";
|
||||||
@import "./views/rooms/_PinnedEventsPanel.scss";
|
@import "./views/rooms/_PinnedEventsPanel.scss";
|
||||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_CreateEvent {
|
.mx_CreateEvent {
|
||||||
&::before {
|
&::before {
|
||||||
background-color: $primary-fg-color;
|
background-color: $composer-e2e-icon-color;
|
||||||
mask-image: url('$(res)/img/element-icons/chat-bubbles.svg');
|
mask-image: url('$(res)/img/element-icons/chat-bubbles.svg');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
67
res/css/views/rooms/_NewRoomIntro.scss
Normal file
67
res/css/views/rooms/_NewRoomIntro.scss
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
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_NewRoomIntro {
|
||||||
|
margin: 80px 0 48px 64px;
|
||||||
|
|
||||||
|
.mx_MiniAvatarUploader_hasAvatar:not(.mx_MiniAvatarUploader_busy):not(:hover) {
|
||||||
|
&::before, &::after {
|
||||||
|
content: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton_kind_link {
|
||||||
|
padding: 0;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_NewRoomIntro_buttons {
|
||||||
|
margin-top: 28px;
|
||||||
|
|
||||||
|
.mx_AccessibleButton {
|
||||||
|
line-height: $font-24px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
background-color: $button-fg-color;
|
||||||
|
mask-position: center;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: 20px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 5px;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_NewRoomIntro_inviteButton::before {
|
||||||
|
mask-image: url('$(res)/img/element-icons/room/invite.svg');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> h2 {
|
||||||
|
margin-top: 24px;
|
||||||
|
font-size: $font-24px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
> p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: $font-15px;
|
||||||
|
color: $secondary-fg-color;
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ import {haveTileForEvent} from "../views/rooms/EventTile";
|
||||||
import {textForEvent} from "../../TextForEvent";
|
import {textForEvent} from "../../TextForEvent";
|
||||||
import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResizer";
|
import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResizer";
|
||||||
import DMRoomMap from "../../utils/DMRoomMap";
|
import DMRoomMap from "../../utils/DMRoomMap";
|
||||||
|
import NewRoomIntro from "../views/rooms/NewRoomIntro";
|
||||||
|
|
||||||
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||||
const continuedTypes = ['m.sticker', 'm.room.message'];
|
const continuedTypes = ['m.sticker', 'm.room.message'];
|
||||||
|
@ -955,13 +956,16 @@ class CreationGrouper {
|
||||||
const ev = this.events[this.events.length - 1];
|
const ev = this.events[this.events.length - 1];
|
||||||
|
|
||||||
let summaryText;
|
let summaryText;
|
||||||
|
const roomId = ev.getRoomId();
|
||||||
const creator = ev.sender ? ev.sender.name : ev.getSender();
|
const creator = ev.sender ? ev.sender.name : ev.getSender();
|
||||||
if (DMRoomMap.shared().getUserIdForRoomId(ev.getRoomId())) {
|
if (DMRoomMap.shared().getUserIdForRoomId(roomId)) {
|
||||||
summaryText = _t("%(creator)s created this DM.", { creator });
|
summaryText = _t("%(creator)s created this DM.", { creator });
|
||||||
} else {
|
} else {
|
||||||
summaryText = _t("%(creator)s created and configured the room.", { creator });
|
summaryText = _t("%(creator)s created and configured the room.", { creator });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret.push(<NewRoomIntro />);
|
||||||
|
|
||||||
ret.push(
|
ret.push(
|
||||||
<EventListSummary
|
<EventListSummary
|
||||||
key="roomcreationsummary"
|
key="roomcreationsummary"
|
||||||
|
|
|
@ -35,6 +35,7 @@ interface IProps {
|
||||||
height?: number;
|
height?: number;
|
||||||
resizeMethod?: ResizeMethod;
|
resizeMethod?: ResizeMethod;
|
||||||
viewAvatarOnClick?: boolean;
|
viewAvatarOnClick?: boolean;
|
||||||
|
onClick?(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -130,7 +131,7 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {room, oobData, viewAvatarOnClick, ...otherProps} = this.props;
|
const {room, oobData, viewAvatarOnClick, onClick, ...otherProps} = this.props;
|
||||||
|
|
||||||
const roomName = room ? room.name : oobData.name;
|
const roomName = room ? room.name : oobData.name;
|
||||||
|
|
||||||
|
@ -139,7 +140,7 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
|
||||||
name={roomName}
|
name={roomName}
|
||||||
idName={room ? room.roomId : null}
|
idName={room ? room.roomId : null}
|
||||||
urls={this.state.urls}
|
urls={this.state.urls}
|
||||||
onClick={viewAvatarOnClick && this.state.urls[0] ? this.onRoomAvatarClick : null}
|
onClick={viewAvatarOnClick && this.state.urls[0] ? this.onRoomAvatarClick : onClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
131
src/components/views/rooms/NewRoomIntro.tsx
Normal file
131
src/components/views/rooms/NewRoomIntro.tsx
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
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, {useContext} from "react";
|
||||||
|
import {EventType} from "matrix-js-sdk/src/@types/event";
|
||||||
|
|
||||||
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
|
import RoomContext from "../../../contexts/RoomContext";
|
||||||
|
import DMRoomMap from "../../../utils/DMRoomMap";
|
||||||
|
import {_t} from "../../../languageHandler";
|
||||||
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
|
import MiniAvatarUploader, {AVATAR_SIZE} from "../elements/MiniAvatarUploader";
|
||||||
|
import RoomAvatar from "../avatars/RoomAvatar";
|
||||||
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
|
import {ViewUserPayload} from "../../../dispatcher/payloads/ViewUserPayload";
|
||||||
|
import {Action} from "../../../dispatcher/actions";
|
||||||
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
|
|
||||||
|
const NewRoomIntro = () => {
|
||||||
|
const cli = useContext(MatrixClientContext);
|
||||||
|
const {room, roomId} = useContext(RoomContext);
|
||||||
|
|
||||||
|
const dmPartner = DMRoomMap.shared().getUserIdForRoomId(roomId);
|
||||||
|
let body;
|
||||||
|
if (dmPartner) {
|
||||||
|
let caption;
|
||||||
|
if ((room.getJoinedMemberCount() + room.getInvitedMemberCount()) === 2) {
|
||||||
|
caption = _t("Only the two of you are in this conversation, unless either of you invites anyone to join.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const member = room?.getMember(dmPartner);
|
||||||
|
const displayName = member?.rawDisplayName || dmPartner;
|
||||||
|
body = <React.Fragment>
|
||||||
|
<RoomAvatar room={room} width={AVATAR_SIZE} height={AVATAR_SIZE} onClick={() => {
|
||||||
|
defaultDispatcher.dispatch<ViewUserPayload>({
|
||||||
|
action: Action.ViewUser,
|
||||||
|
// XXX: We should be using a real member object and not assuming what the receiver wants.
|
||||||
|
member: member || {userId: dmPartner},
|
||||||
|
});
|
||||||
|
}} />
|
||||||
|
|
||||||
|
<h2>{ room.name }</h2>
|
||||||
|
|
||||||
|
<p>{_t("This is the beginning of your direct message history with <displayName/>.", {}, {
|
||||||
|
displayName: () => <b>{ displayName }</b>,
|
||||||
|
})}</p>
|
||||||
|
{ caption && <p>{ caption }</p> }
|
||||||
|
</React.Fragment>;
|
||||||
|
} else {
|
||||||
|
const topic = room.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic;
|
||||||
|
const canAddTopic = room.currentState.maySendStateEvent(EventType.RoomTopic, cli.getUserId());
|
||||||
|
|
||||||
|
const onTopicClick = () => {
|
||||||
|
dis.dispatch({
|
||||||
|
action: "open_room_settings",
|
||||||
|
room_id: roomId,
|
||||||
|
}, true);
|
||||||
|
// focus the topic field to help the user find it as it'll gain an outline
|
||||||
|
setImmediate(() => {
|
||||||
|
window.document.getElementById("profileTopic").focus();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let topicText;
|
||||||
|
if (canAddTopic && topic) {
|
||||||
|
topicText = _t("Topic: %(topic)s (<a>edit</a>)", { topic }, {
|
||||||
|
a: sub => <AccessibleButton kind="link" onClick={onTopicClick}>{ sub }</AccessibleButton>,
|
||||||
|
});
|
||||||
|
} else if (topic) {
|
||||||
|
topicText = _t("Topic: %(topic)s ", { topic });
|
||||||
|
} else if (canAddTopic) {
|
||||||
|
topicText = _t("<a>Add a topic</a> to help people know what it is about.", {}, {
|
||||||
|
a: sub => <AccessibleButton kind="link" onClick={onTopicClick}>{ sub }</AccessibleButton>,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const creator = room.currentState.getStateEvents(EventType.RoomCreate, "")?.getSender();
|
||||||
|
const creatorName = room?.getMember(creator)?.rawDisplayName || creator;
|
||||||
|
|
||||||
|
let createdText;
|
||||||
|
if (creator === cli.getUserId()) {
|
||||||
|
createdText = _t("You created this room.");
|
||||||
|
} else {
|
||||||
|
createdText = _t("%(displayName)s created this room.", {
|
||||||
|
displayName: creatorName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const avatarUrl = room.currentState.getStateEvents(EventType.RoomAvatar, "")?.getContent()?.url;
|
||||||
|
body = <React.Fragment>
|
||||||
|
<MiniAvatarUploader
|
||||||
|
hasAvatar={!!avatarUrl}
|
||||||
|
noAvatarLabel={_t("Add a photo, so people can easily spot your room.")}
|
||||||
|
setAvatarUrl={url => cli.sendStateEvent(roomId, EventType.RoomAvatar, { url }, '')}
|
||||||
|
>
|
||||||
|
<RoomAvatar room={room} width={AVATAR_SIZE} height={AVATAR_SIZE} />
|
||||||
|
</MiniAvatarUploader>
|
||||||
|
|
||||||
|
<h2>{ room.name }</h2>
|
||||||
|
|
||||||
|
<p>{createdText} {_t("This is the start of <roomName/>.", {}, {
|
||||||
|
roomName: () => <b>{ room.name }</b>,
|
||||||
|
})}</p>
|
||||||
|
<p>{topicText}</p>
|
||||||
|
<div className="mx_NewRoomIntro_buttons">
|
||||||
|
<AccessibleButton className="mx_NewRoomIntro_inviteButton" kind="primary">
|
||||||
|
{_t("Invite to this room")}
|
||||||
|
</AccessibleButton>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="mx_NewRoomIntro">
|
||||||
|
{ body }
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NewRoomIntro;
|
Loading…
Add table
Add a link
Reference in a new issue