Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share
This commit is contained in:
commit
340bbeec4f
9 changed files with 32 additions and 21 deletions
|
@ -36,6 +36,7 @@ limitations under the License.
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomSummaryCard_avatar {
|
.mx_RoomSummaryCard_avatar {
|
||||||
|
|
|
@ -152,7 +152,7 @@ const Tile: React.FC<ITileProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
let description = _t("%(count)s members", { count: room.num_joined_members });
|
let description = _t("%(count)s members", { count: room.num_joined_members });
|
||||||
if (numChildRooms) {
|
if (numChildRooms !== undefined) {
|
||||||
description += " · " + _t("%(count)s rooms", { count: numChildRooms });
|
description += " · " + _t("%(count)s rooms", { count: numChildRooms });
|
||||||
}
|
}
|
||||||
if (room.topic) {
|
if (room.topic) {
|
||||||
|
|
|
@ -45,6 +45,7 @@ import {ChevronFace, ContextMenuTooltipButton, useContextMenu} from "../../struc
|
||||||
import WidgetContextMenu from "../context_menus/WidgetContextMenu";
|
import WidgetContextMenu from "../context_menus/WidgetContextMenu";
|
||||||
import {useRoomMemberCount} from "../../../hooks/useRoomMembers";
|
import {useRoomMemberCount} from "../../../hooks/useRoomMembers";
|
||||||
import { Container, MAX_PINNED, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
|
import { Container, MAX_PINNED, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
|
||||||
|
import RoomName from "../elements/RoomName";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -249,7 +250,13 @@ const RoomSummaryCard: React.FC<IProps> = ({ room, onClose }) => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 title={room.name}>{ room.name }</h2>
|
<RoomName room={room}>
|
||||||
|
{ name => (
|
||||||
|
<h2 title={name}>
|
||||||
|
{ name }
|
||||||
|
</h2>
|
||||||
|
)}
|
||||||
|
</RoomName>
|
||||||
<div className="mx_RoomSummaryCard_alias" title={alias}>
|
<div className="mx_RoomSummaryCard_alias" title={alias}>
|
||||||
{ alias }
|
{ alias }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -133,6 +133,12 @@ export default class MemberList extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get canInvite() {
|
||||||
|
const cli = MatrixClientPeg.get();
|
||||||
|
const room = cli.getRoom(this.props.roomId);
|
||||||
|
return room && room.canInvite(cli.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
_getMembersState(members) {
|
_getMembersState(members) {
|
||||||
// set the state after determining _showPresence to make sure it's
|
// set the state after determining _showPresence to make sure it's
|
||||||
// taken into account while rerendering
|
// taken into account while rerendering
|
||||||
|
@ -141,6 +147,7 @@ export default class MemberList extends React.Component {
|
||||||
members: members,
|
members: members,
|
||||||
filteredJoinedMembers: this._filterMembers(members, 'join'),
|
filteredJoinedMembers: this._filterMembers(members, 'join'),
|
||||||
filteredInvitedMembers: this._filterMembers(members, 'invite'),
|
filteredInvitedMembers: this._filterMembers(members, 'invite'),
|
||||||
|
canInvite: this.canInvite,
|
||||||
|
|
||||||
// ideally we'd size this to the page height, but
|
// ideally we'd size this to the page height, but
|
||||||
// in practice I find that a little constraining
|
// in practice I find that a little constraining
|
||||||
|
@ -196,6 +203,8 @@ export default class MemberList extends React.Component {
|
||||||
event.getType() === "m.room.third_party_invite") {
|
event.getType() === "m.room.third_party_invite") {
|
||||||
this._updateList();
|
this._updateList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.canInvite !== this.state.canInvite) this.setState({ canInvite: this.canInvite });
|
||||||
};
|
};
|
||||||
|
|
||||||
_updateList = rate_limited_func(() => {
|
_updateList = rate_limited_func(() => {
|
||||||
|
@ -455,8 +464,6 @@ export default class MemberList extends React.Component {
|
||||||
let inviteButton;
|
let inviteButton;
|
||||||
|
|
||||||
if (room && room.getMyMembership() === 'join') {
|
if (room && room.getMyMembership() === 'join') {
|
||||||
const canInvite = room.canInvite(cli.getUserId());
|
|
||||||
|
|
||||||
let inviteButtonText = _t("Invite to this room");
|
let inviteButtonText = _t("Invite to this room");
|
||||||
const chat = CommunityPrototypeStore.instance.getSelectedCommunityGeneralChat();
|
const chat = CommunityPrototypeStore.instance.getSelectedCommunityGeneralChat();
|
||||||
if (chat && chat.roomId === this.props.roomId) {
|
if (chat && chat.roomId === this.props.roomId) {
|
||||||
|
@ -467,7 +474,7 @@ export default class MemberList extends React.Component {
|
||||||
|
|
||||||
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
||||||
inviteButton =
|
inviteButton =
|
||||||
<AccessibleButton className="mx_MemberList_invite" onClick={this.onInviteButtonClick} disabled={!canInvite}>
|
<AccessibleButton className="mx_MemberList_invite" onClick={this.onInviteButtonClick} disabled={!this.state.canInvite}>
|
||||||
<span>{ inviteButtonText }</span>
|
<span>{ inviteButtonText }</span>
|
||||||
</AccessibleButton>;
|
</AccessibleButton>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { createRef, ReactComponentElement } from "react";
|
import { createRef, ReactComponentElement } from "react";
|
||||||
|
import { normalize } from "matrix-js-sdk/src/utils";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { RovingAccessibleButton, RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
import { RovingAccessibleButton, RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
||||||
|
@ -259,7 +260,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
const nameCondition = RoomListStore.instance.getFirstNameFilterCondition();
|
const nameCondition = RoomListStore.instance.getFirstNameFilterCondition();
|
||||||
if (nameCondition) {
|
if (nameCondition) {
|
||||||
stateUpdates.filteredExtraTiles = this.props.extraTiles
|
stateUpdates.filteredExtraTiles = this.props.extraTiles
|
||||||
.filter(t => nameCondition.matches(t.props.displayName || ""));
|
.filter(t => nameCondition.matches(normalize(t.props.displayName || "")));
|
||||||
} else if (this.state.filteredExtraTiles) {
|
} else if (this.state.filteredExtraTiles) {
|
||||||
stateUpdates.filteredExtraTiles = null;
|
stateUpdates.filteredExtraTiles = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -344,7 +344,10 @@ export function setLanguage(preferredLangs: string | string[]) {
|
||||||
counterpart.registerTranslations(langToUse, langData);
|
counterpart.registerTranslations(langToUse, langData);
|
||||||
counterpart.setLocale(langToUse);
|
counterpart.setLocale(langToUse);
|
||||||
SettingsStore.setValue("language", null, SettingLevel.DEVICE, langToUse);
|
SettingsStore.setValue("language", null, SettingLevel.DEVICE, langToUse);
|
||||||
console.log("set language to " + langToUse);
|
// Adds a lot of noise to test runs, so disable logging there.
|
||||||
|
if (process.env.NODE_ENV !== "test") {
|
||||||
|
console.log("set language to " + langToUse);
|
||||||
|
}
|
||||||
|
|
||||||
// Set 'en' as fallback language:
|
// Set 'en' as fallback language:
|
||||||
if (langToUse !== "en") {
|
if (langToUse !== "en") {
|
||||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./IFilterCondition";
|
import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./IFilterCondition";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { removeHiddenChars } from "matrix-js-sdk/src/utils";
|
import { normalize } from "matrix-js-sdk/src/utils";
|
||||||
import { throttle } from "lodash";
|
import { throttle } from "lodash";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,20 +62,10 @@ export class NameFilterCondition extends EventEmitter implements IFilterConditio
|
||||||
|
|
||||||
if (!room.name) return false; // should realistically not happen: the js-sdk always calculates a name
|
if (!room.name) return false; // should realistically not happen: the js-sdk always calculates a name
|
||||||
|
|
||||||
return this.matches(room.name);
|
return this.matches(room.normalizedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private normalize(val: string): string {
|
public matches(normalizedName: string): boolean {
|
||||||
// Note: we have to match the filter with the removeHiddenChars() room name because the
|
return normalizedName.includes(normalize(this.search));
|
||||||
// function strips spaces and other characters (M becomes RN for example, in lowercase).
|
|
||||||
return removeHiddenChars(val.toLowerCase())
|
|
||||||
// Strip all punctuation
|
|
||||||
.replace(/[\\'!"#$%&()*+,\-./:;<=>?@[\]^_`{|}~\u2000-\u206f\u2e00-\u2e7f]/g, "")
|
|
||||||
// We also doubly convert to lowercase to work around oddities of the library.
|
|
||||||
.toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
public matches(val: string): boolean {
|
|
||||||
return this.normalize(val).includes(this.normalize(this.search));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,7 @@ describe('MemberList', () => {
|
||||||
};
|
};
|
||||||
memberListRoom.currentState = {
|
memberListRoom.currentState = {
|
||||||
members: {},
|
members: {},
|
||||||
|
getMember: jest.fn(),
|
||||||
getStateEvents: (eventType, stateKey) => stateKey === undefined ? [] : null, // ignore 3pid invites
|
getStateEvents: (eventType, stateKey) => stateKey === undefined ? [] : null, // ignore 3pid invites
|
||||||
};
|
};
|
||||||
for (const member of [...adminUsers, ...moderatorUsers, ...defaultUsers]) {
|
for (const member of [...adminUsers, ...moderatorUsers, ...defaultUsers]) {
|
||||||
|
|
|
@ -246,6 +246,7 @@ export function mkStubRoom(roomId = null) {
|
||||||
maySendMessage: jest.fn().mockReturnValue(true),
|
maySendMessage: jest.fn().mockReturnValue(true),
|
||||||
currentState: {
|
currentState: {
|
||||||
getStateEvents: jest.fn(),
|
getStateEvents: jest.fn(),
|
||||||
|
getMember: jest.fn(),
|
||||||
mayClientSendStateEvent: jest.fn().mockReturnValue(true),
|
mayClientSendStateEvent: jest.fn().mockReturnValue(true),
|
||||||
maySendStateEvent: jest.fn().mockReturnValue(true),
|
maySendStateEvent: jest.fn().mockReturnValue(true),
|
||||||
maySendEvent: jest.fn().mockReturnValue(true),
|
maySendEvent: jest.fn().mockReturnValue(true),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue