diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js
index d52bbbb0d0..dc3893785d 100644
--- a/src/components/views/rooms/RoomPreviewBar.js
+++ b/src/components/views/rooms/RoomPreviewBar.js
@@ -26,6 +26,8 @@ import classNames from 'classnames';
import { _t } from '../../../languageHandler';
import SdkConfig from "../../../SdkConfig";
import IdentityAuthClient from '../../../IdentityAuthClient';
+import {CommunityPrototypeStore} from "../../../stores/CommunityPrototypeStore";
+import {UPDATE_EVENT} from "../../../stores/AsyncStore";
const MessageCase = Object.freeze({
NotLoggedIn: "NotLoggedIn",
@@ -100,6 +102,7 @@ export default createReactClass({
componentDidMount: function() {
this._checkInvitedEmail();
+ CommunityPrototypeStore.instance.on(UPDATE_EVENT, this._onCommunityUpdate);
},
componentDidUpdate: function(prevProps, prevState) {
@@ -108,6 +111,10 @@ export default createReactClass({
}
},
+ componentWillUnmount: function() {
+ CommunityPrototypeStore.instance.off(UPDATE_EVENT, this._onCommunityUpdate);
+ },
+
_checkInvitedEmail: async function() {
// If this is an invite and we've been told what email address was
// invited, fetch the user's account emails and discovery bindings so we
@@ -143,6 +150,13 @@ export default createReactClass({
}
},
+ _onCommunityUpdate: function (roomId) {
+ if (this.props.room && this.props.room.roomId !== roomId) {
+ return;
+ }
+ this.forceUpdate(); // we have nothing to update
+ },
+
_getMessageCase() {
const isGuest = MatrixClientPeg.get().isGuest();
@@ -219,8 +233,15 @@ export default createReactClass({
}
},
+ _communityProfile: function() {
+ if (this.props.room) return CommunityPrototypeStore.instance.getInviteProfile(this.props.room.roomId);
+ return {displayName: null, avatarMxc: null};
+ },
+
_roomName: function(atStart = false) {
- const name = this.props.room ? this.props.room.name : this.props.roomAlias;
+ let name = this.props.room ? this.props.room.name : this.props.roomAlias;
+ const profile = this._communityProfile();
+ if (profile.displayName) name = profile.displayName;
if (name) {
return name;
} else if (atStart) {
@@ -439,7 +460,10 @@ export default createReactClass({
}
case MessageCase.Invite: {
const RoomAvatar = sdk.getComponent("views.avatars.RoomAvatar");
- const avatar = ;
+ const oobData = Object.assign({}, this.props.oobData, {
+ avatarUrl: this._communityProfile().avatarMxc,
+ });
+ const avatar = ;
const inviteMember = this._getInviteMember();
let inviterElement;
diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx
index 0c99b98e1a..a09853d762 100644
--- a/src/components/views/rooms/RoomTile.tsx
+++ b/src/components/views/rooms/RoomTile.tsx
@@ -27,7 +27,7 @@ import defaultDispatcher from '../../../dispatcher/dispatcher';
import { Key } from "../../../Keyboard";
import ActiveRoomObserver from "../../../ActiveRoomObserver";
import { _t } from "../../../languageHandler";
-import { ChevronFace, ContextMenuTooltipButton, MenuItemRadio } from "../../structures/ContextMenu";
+import { ChevronFace, ContextMenuTooltipButton } from "../../structures/ContextMenu";
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
import { MessagePreviewStore, ROOM_PREVIEW_CHANGED } from "../../../stores/room-list/MessagePreviewStore";
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
@@ -47,8 +47,11 @@ import { PROPERTY_UPDATED } from "../../../stores/local-echo/GenericEchoChamber"
import IconizedContextMenu, {
IconizedContextMenuCheckbox,
IconizedContextMenuOption,
- IconizedContextMenuOptionList, IconizedContextMenuRadio
+ IconizedContextMenuOptionList,
+ IconizedContextMenuRadio
} from "../context_menus/IconizedContextMenu";
+import { CommunityPrototypeStore, IRoomProfile } from "../../../stores/CommunityPrototypeStore";
+import { UPDATE_EVENT } from "../../../stores/AsyncStore";
interface IProps {
room: Room;
@@ -101,6 +104,7 @@ export default class RoomTile extends React.PureComponent {
this.notificationState.on(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate);
this.roomProps = EchoChamber.forRoom(this.props.room);
this.roomProps.on(PROPERTY_UPDATED, this.onRoomPropertyUpdate);
+ CommunityPrototypeStore.instance.on(UPDATE_EVENT, this.onCommunityUpdate);
}
private onNotificationUpdate = () => {
@@ -140,6 +144,7 @@ export default class RoomTile extends React.PureComponent {
defaultDispatcher.unregister(this.dispatcherRef);
MessagePreviewStore.instance.off(ROOM_PREVIEW_CHANGED, this.onRoomPreviewChanged);
this.notificationState.off(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate);
+ CommunityPrototypeStore.instance.off(UPDATE_EVENT, this.onCommunityUpdate);
}
private onAction = (payload: ActionPayload) => {
@@ -150,6 +155,11 @@ export default class RoomTile extends React.PureComponent {
}
};
+ private onCommunityUpdate = (roomId: string) => {
+ if (roomId !== this.props.room.roomId) return;
+ this.forceUpdate(); // we don't have anything to actually update
+ };
+
private onRoomPreviewChanged = (room: Room) => {
if (this.props.room && room.roomId === this.props.room.roomId) {
// generatePreview() will return nothing if the user has previews disabled
@@ -461,11 +471,21 @@ export default class RoomTile extends React.PureComponent {
'mx_RoomTile_minimized': this.props.isMinimized,
});
+ let roomProfile: IRoomProfile = {displayName: null, avatarMxc: null};
+ if (this.props.tag === DefaultTagID.Invite) {
+ roomProfile = CommunityPrototypeStore.instance.getInviteProfile(this.props.room.roomId);
+ }
+
+ let name = roomProfile.displayName || this.props.room.name;
+ if (typeof name !== 'string') name = '';
+ name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
+
const roomAvatar = ;
let badge: React.ReactNode;
@@ -482,10 +502,6 @@ export default class RoomTile extends React.PureComponent {
);
}
- let name = this.props.room.name;
- if (typeof name !== 'string') name = '';
- name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
-
let messagePreview = null;
if (this.showMessagePreview && this.state.messagePreview) {
messagePreview = (
diff --git a/src/stores/CommunityPrototypeStore.ts b/src/stores/CommunityPrototypeStore.ts
new file mode 100644
index 0000000000..581f8a97c8
--- /dev/null
+++ b/src/stores/CommunityPrototypeStore.ts
@@ -0,0 +1,100 @@
+/*
+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 { AsyncStoreWithClient } from "./AsyncStoreWithClient";
+import defaultDispatcher from "../dispatcher/dispatcher";
+import { ActionPayload } from "../dispatcher/payloads";
+import { Room } from "matrix-js-sdk/src/models/room";
+import { EffectiveMembership, getEffectiveMembership } from "../utils/membership";
+import SettingsStore from "../settings/SettingsStore";
+import * as utils from "matrix-js-sdk/src/utils";
+import { UPDATE_EVENT } from "./AsyncStore";
+
+interface IState {
+ // nothing of value - we use account data
+}
+
+export interface IRoomProfile {
+ displayName: string;
+ avatarMxc: string;
+}
+
+export class CommunityPrototypeStore extends AsyncStoreWithClient {
+ private static internalInstance = new CommunityPrototypeStore();
+
+ private constructor() {
+ super(defaultDispatcher, {});
+ }
+
+ public static get instance(): CommunityPrototypeStore {
+ return CommunityPrototypeStore.internalInstance;
+ }
+
+ protected async onAction(payload: ActionPayload): Promise {
+ if (!this.matrixClient || !SettingsStore.getValue("feature_communities_v2_prototypes")) {
+ return;
+ }
+
+ if (payload.action === "MatrixActions.Room.myMembership") {
+ const room: Room = payload.room;
+ const membership = getEffectiveMembership(payload.membership);
+ const oldMembership = getEffectiveMembership(payload.oldMembership);
+ if (membership === oldMembership) return;
+
+ if (membership === EffectiveMembership.Invite) {
+ try {
+ const path = utils.encodeUri("/rooms/$roomId/group_info", {$roomId: room.roomId});
+ const profile = await this.matrixClient._http.authedRequest(
+ undefined, "GET", path,
+ undefined, undefined,
+ {prefix: "/_matrix/client/unstable/im.vector.custom"});
+ // we use global account data because per-room account data on invites is unreliable
+ await this.matrixClient.setAccountData("im.vector.group_info." + room.roomId, profile);
+ } catch (e) {
+ console.warn("Non-fatal error getting group information for invite:", e);
+ }
+ }
+ } else if (payload.action === "MatrixActions.accountData") {
+ if (payload.event_type.startsWith("im.vector.group_info.")) {
+ this.emit(UPDATE_EVENT, payload.event_type.substring("im.vector.group_info.".length));
+ }
+ }
+ }
+
+ public getInviteProfile(roomId: string): IRoomProfile {
+ if (!this.matrixClient) return {displayName: null, avatarMxc: null};
+ const room = this.matrixClient.getRoom(roomId);
+ if (SettingsStore.getValue("feature_communities_v2_prototypes")) {
+ const data = this.matrixClient.getAccountData("im.vector.group_info." + roomId);
+ if (data && data.getContent()) {
+ return {displayName: data.getContent().name, avatarMxc: data.getContent().avatar_url};
+ }
+ }
+ return {displayName: room.name, avatarMxc: room.avatar_url};
+ }
+
+ protected async onReady(): Promise {
+ for (const room of this.matrixClient.getRooms()) {
+ const myMember = room.currentState.getMembers().find(m => m.userId === this.matrixClient.getUserId());
+ if (!myMember) continue;
+ if (getEffectiveMembership(myMember.membership) === EffectiveMembership.Invite) {
+ // Fake an update for anything that might have started listening before the invite
+ // data was available (eg: RoomPreviewBar after a refresh)
+ this.emit(UPDATE_EVENT, room.roomId);
+ }
+ }
+ }
+}