Merge branch 'develop' into travis/msc2873

This commit is contained in:
Travis Ralston 2021-05-17 16:27:20 -06:00
commit 6ccb0d487a
13 changed files with 189 additions and 19 deletions

View file

@ -27,7 +27,7 @@ import CallMediaHandler from '../../CallMediaHandler';
import { fixupColorFonts } from '../../utils/FontManager';
import * as sdk from '../../index';
import dis from '../../dispatcher/dispatcher';
import {MatrixClientPeg, IMatrixClientCreds} from '../../MatrixClientPeg';
import { IMatrixClientCreds } from '../../MatrixClientPeg';
import SettingsStore from "../../settings/SettingsStore";
import TagOrderActions from '../../actions/TagOrderActions';
@ -219,16 +219,6 @@ class LoggedInView extends React.Component<IProps, IState> {
});
};
// Child components assume that the client peg will not be null, so give them some
// sort of assurance here by only allowing a re-render if the client is truthy.
//
// This is required because `LoggedInView` maintains its own state and if this state
// updates after the client peg has been made null (during logout), then it will
// attempt to re-render and the children will throw errors.
shouldComponentUpdate() {
return Boolean(MatrixClientPeg.get());
}
canResetTimelineInRoom = (roomId) => {
if (!this._roomView.current) {
return true;

View file

@ -473,7 +473,7 @@ export default class MessagePanel extends React.Component {
}
get _roomHasPendingEdit() {
return localStorage.getItem(`mx_edit_room_${this.props.room.roomId}`);
return this.props.room && localStorage.getItem(`mx_edit_room_${this.props.room.roomId}`);
}
_getEventTiles() {

View file

@ -217,6 +217,7 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
value={this.state.otherHomeserver}
validateOnChange={false}
validateOnFocus={false}
id="mx_homeserverInput"
/>
</StyledRadioButton>
<p>

View file

@ -345,6 +345,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
<form className="mx_AccessSecretStorageDialog_primaryContainer" onSubmit={this.onPassPhraseNext}>
<input
type="password"
id="mx_passPhraseInput"
className="mx_AccessSecretStorageDialog_passPhraseInput"
onChange={this.onPassPhraseChange}
value={this.state.passPhrase}

View file

@ -50,6 +50,10 @@ const ReactButton = ({ mxEvent, reactions }: IProps) => {
})}
title={_t("Add reaction")}
onClick={openMenu}
onContextMenu={e => {
e.preventDefault();
openMenu();
}}
isExpanded={menuDisplayed}
inputRef={button}
/>
@ -174,6 +178,8 @@ export default class ReactionsRow extends React.PureComponent<IProps, IState> {
/>;
}).filter(item => !!item);
if (!items.length) return null;
// Show the first MAX_ITEMS if there are MAX_ITEMS + 1 or more items.
// The "+ 1" ensure that the "show all" reveals something that takes up
// more space than the button itself.

View file

@ -600,6 +600,10 @@
"See when the avatar changes in this room": "See when the avatar changes in this room",
"Change the avatar of your active room": "Change the avatar of your active room",
"See when the avatar changes in your active room": "See when the avatar changes in your active room",
"Kick, ban, or invite people to this room, and make you leave": "Kick, ban, or invite people to this room, and make you leave",
"See when people join, leave, or are invited to this room": "See when people join, leave, or are invited to this room",
"Kick, ban, or invite people to your active room, and make you leave": "Kick, ban, or invite people to your active room, and make you leave",
"See when people join, leave, or are invited to your active room": "See when people join, leave, or are invited to your active room",
"Send stickers to this room as you": "Send stickers to this room as you",
"See when a sticker is posted in this room": "See when a sticker is posted in this room",
"Send stickers to your active room as you": "Send stickers to your active room as you",

View file

@ -62,7 +62,7 @@ export const getOrder = (order: string, creationTs: number, roomId: string): Arr
if (typeof order === "string" && Array.from(order).every((c: string) => {
const charCode = c.charCodeAt(0);
return charCode >= 0x20 && charCode <= 0x7F;
return charCode >= 0x20 && charCode <= 0x7E;
})) {
validatedOrder = order;
}

View file

@ -44,6 +44,7 @@ import { CHAT_EFFECTS } from "../../effects";
import { containsEmoji } from "../../effects/utils";
import dis from "../../dispatcher/dispatcher";
import {tryTransformPermalinkToLocalHref} from "../../utils/permalinks/Permalinks";
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
// TODO: Purge this from the universe
@ -144,6 +145,52 @@ export class StopGapWidgetDriver extends WidgetDriver {
return {roomId, eventId: r.event_id};
}
public async readRoomEvents(eventType: string, msgtype: string | undefined, limit: number): Promise<MatrixEvent[]> {
limit = limit > 0 ? Math.min(limit, 25) : 25; // arbitrary choice
const client = MatrixClientPeg.get();
const roomId = ActiveRoomObserver.activeRoomId;
const room = client.getRoom(roomId);
if (!client || !roomId || !room) throw new Error("Not in a room or not attached to a client");
const results: MatrixEvent[] = [];
const events = room.getLiveTimeline().getEvents(); // timelines are most recent last
for (let i = events.length - 1; i > 0; i--) {
if (results.length >= limit) break;
const ev = events[i];
if (ev.getType() !== eventType) continue;
if (eventType === EventType.RoomMessage && msgtype && msgtype !== ev.getContent()['msgtype']) continue;
results.push(ev);
}
return results.map(e => e.event);
}
public async readStateEvents(
eventType: string, stateKey: string | undefined, limit: number,
): Promise<MatrixEvent[]> {
limit = limit > 0 ? Math.min(limit, 100) : 100; // arbitrary choice
const client = MatrixClientPeg.get();
const roomId = ActiveRoomObserver.activeRoomId;
const room = client.getRoom(roomId);
if (!client || !roomId || !room) throw new Error("Not in a room or not attached to a client");
const results: MatrixEvent[] = [];
const state = room.currentState.events.get(eventType);
if (state) {
if (stateKey === "" || !!stateKey) {
const forKey = state.get(stateKey);
if (forKey) results.push(forKey);
} else {
results.push(...Array.from(state.values()));
}
}
return results.slice(0, limit).map(e => e.event);
}
public async askOpenID(observer: SimpleObservable<IOpenIDUpdate>) {
const oidcState = WidgetPermissionStore.instance.getOIDCState(
this.forWidget, this.forWidgetKind, this.inRoomId,

View file

@ -96,6 +96,16 @@ export class CapabilityText {
[EventDirection.Receive]: _td("See when the avatar changes in your active room"),
},
},
[EventType.RoomMember]: {
[WidgetKind.Room]: {
[EventDirection.Send]: _td("Kick, ban, or invite people to this room, and make you leave"),
[EventDirection.Receive]: _td("See when people join, leave, or are invited to this room"),
},
[GENERIC_WIDGET_KIND]: {
[EventDirection.Send]: _td("Kick, ban, or invite people to your active room, and make you leave"),
[EventDirection.Receive]: _td("See when people join, leave, or are invited to your active room"),
},
},
};
private static nonStateSendRecvCaps: ISendRecvStaticCapText = {