Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 88cd2f8

Browse files
authored
Fix unfocused paste handling and focus return for file uploads (#7625)
1 parent e53427f commit 88cd2f8

File tree

4 files changed

+39
-16
lines changed

4 files changed

+39
-16
lines changed

src/ContentMessages.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import encrypt from "browser-encrypt-attachment";
2424
import extractPngChunks from "png-chunks-extract";
2525
import { IAbortablePromise, IImageInfo } from "matrix-js-sdk/src/@types/partials";
2626
import { logger } from "matrix-js-sdk/src/logger";
27-
import { IEventRelation } from "matrix-js-sdk/src";
27+
import { IEventRelation, ISendEventResponse } from "matrix-js-sdk/src";
2828

2929
import { IEncryptedFile, IMediaEventInfo } from "./customisations/models/IMediaEventContent";
3030
import dis from './dispatcher/dispatcher';
@@ -46,6 +46,7 @@ import { IUpload } from "./models/IUpload";
4646
import { BlurhashEncoder } from "./BlurhashEncoder";
4747
import SettingsStore from "./settings/SettingsStore";
4848
import { decorateStartSendingTime, sendRoundTripMetric } from "./sendTimePerformanceMetrics";
49+
import { TimelineRenderingType } from "./contexts/RoomContext";
4950

5051
const MAX_WIDTH = 800;
5152
const MAX_HEIGHT = 600;
@@ -421,14 +422,14 @@ export default class ContentMessages {
421422
private inprogress: IUpload[] = [];
422423
private mediaConfig: IMediaConfig = null;
423424

424-
sendStickerContentToRoom(
425+
public sendStickerContentToRoom(
425426
url: string,
426427
roomId: string,
427428
threadId: string | null,
428429
info: IImageInfo,
429430
text: string,
430431
matrixClient: MatrixClient,
431-
) {
432+
): Promise<ISendEventResponse> {
432433
const startTime = CountlyAnalytics.getTimestamp();
433434
const prom = matrixClient.sendStickerMessage(roomId, threadId, url, info, text).catch((e) => {
434435
logger.warn(`Failed to send content with URL ${url} to room ${roomId}`, e);
@@ -438,20 +439,21 @@ export default class ContentMessages {
438439
return prom;
439440
}
440441

441-
getUploadLimit() {
442+
public getUploadLimit(): number | null {
442443
if (this.mediaConfig !== null && this.mediaConfig["m.upload.size"] !== undefined) {
443444
return this.mediaConfig["m.upload.size"];
444445
} else {
445446
return null;
446447
}
447448
}
448449

449-
async sendContentListToRoom(
450+
public async sendContentListToRoom(
450451
files: File[],
451452
roomId: string,
452453
relation: IEventRelation | null,
453454
matrixClient: MatrixClient,
454-
) {
455+
context = TimelineRenderingType.Room,
456+
): Promise<void> {
455457
if (matrixClient.isGuest()) {
456458
dis.dispatch({ action: 'require_registration' });
457459
return;
@@ -530,9 +532,15 @@ export default class ContentMessages {
530532

531533
promBefore = this.sendContentToRoom(file, roomId, relation, matrixClient, promBefore);
532534
}
535+
536+
// Focus the correct composer
537+
dis.dispatch({
538+
action: Action.FocusSendMessageComposer,
539+
context,
540+
});
533541
}
534542

535-
getCurrentUploads(relation?: IEventRelation) {
543+
public getCurrentUploads(relation?: IEventRelation): IUpload[] {
536544
return this.inprogress.filter(upload => {
537545
const noRelation = !relation && !upload.relation;
538546
const matchingRelation = relation && upload.relation
@@ -543,7 +551,7 @@ export default class ContentMessages {
543551
});
544552
}
545553

546-
cancelUpload(promise: Promise<any>, matrixClient: MatrixClient) {
554+
public cancelUpload(promise: Promise<any>, matrixClient: MatrixClient): void {
547555
let upload: IUpload;
548556
for (let i = 0; i < this.inprogress.length; ++i) {
549557
if (this.inprogress[i].promise === promise) {
@@ -632,9 +640,6 @@ export default class ContentMessages {
632640
this.inprogress.push(upload);
633641
dis.dispatch<UploadStartedPayload>({ action: Action.UploadStarted, upload });
634642

635-
// Focus the composer view
636-
dis.fire(Action.FocusSendMessageComposer);
637-
638643
function onProgress(ev) {
639644
upload.total = ev.total;
640645
upload.loaded = ev.loaded;

src/components/structures/LoggedInView.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import LegacyCommunityPreview from "./LegacyCommunityPreview";
6969
import { UserTab } from "../views/dialogs/UserSettingsDialog";
7070
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
7171
import RightPanelStore from '../../stores/right-panel/RightPanelStore';
72+
import { TimelineRenderingType } from "../../contexts/RoomContext";
7273

7374
// We need to fetch each pinned message individually (if we don't already have it)
7475
// so each pinned message may trigger a request. Limit the number per room for sanity.
@@ -386,15 +387,20 @@ class LoggedInView extends React.Component<IProps, IState> {
386387

387388
private onPaste = (ev: ClipboardEvent) => {
388389
const element = ev.target as HTMLElement;
389-
const inputableElement = getInputableElement(element) || document.activeElement as HTMLElement;
390+
const inputableElement = getInputableElement(element);
391+
if (inputableElement === document.activeElement) return; // nothing to do
390392

391393
if (inputableElement?.focus) {
392394
inputableElement.focus();
393395
} else {
396+
const inThread = !!document.activeElement.closest(".mx_ThreadView");
394397
// refocusing during a paste event will make the
395398
// paste end up in the newly focused element,
396399
// so dispatch synchronously before paste happens
397-
dis.fire(Action.FocusSendMessageComposer, true);
400+
dis.dispatch({
401+
action: Action.FocusSendMessageComposer,
402+
context: inThread ? TimelineRenderingType.Thread : TimelineRenderingType.Room,
403+
}, true);
398404
}
399405
};
400406

@@ -552,8 +558,12 @@ class LoggedInView extends React.Component<IProps, IState> {
552558
// If the user is entering a printable character outside of an input field
553559
// redirect it to the composer for them.
554560
if (!isClickShortcut && isPrintable && !getInputableElement(ev.target as HTMLElement)) {
561+
const inThread = !!document.activeElement.closest(".mx_ThreadView");
555562
// synchronous dispatch so we focus before key generates input
556-
dis.fire(Action.FocusSendMessageComposer, true);
563+
dis.dispatch({
564+
action: Action.FocusSendMessageComposer,
565+
context: inThread ? TimelineRenderingType.Thread : TimelineRenderingType.Room,
566+
}, true);
557567
ev.stopPropagation();
558568
// we should *not* preventDefault() here as that would prevent typing in the now-focused composer
559569
}

src/components/views/rooms/MessageComposer.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,11 @@ class UploadButton extends React.Component<IUploadButtonProps> {
160160
}
161161

162162
ContentMessages.sharedInstance().sendContentListToRoom(
163-
tfiles, this.props.roomId, this.props.relation, MatrixClientPeg.get(),
163+
tfiles,
164+
this.props.roomId,
165+
this.props.relation,
166+
MatrixClientPeg.get(),
167+
this.context.timelineRenderingType,
164168
);
165169

166170
// This is the onChange handler for a file form control, but we're

src/components/views/rooms/SendMessageComposer.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,11 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
560560
// it puts the filename in as text/plain which we want to ignore.
561561
if (clipboardData.files.length && !clipboardData.types.includes("text/rtf")) {
562562
ContentMessages.sharedInstance().sendContentListToRoom(
563-
Array.from(clipboardData.files), this.props.room.roomId, this.props.relation, this.props.mxClient,
563+
Array.from(clipboardData.files),
564+
this.props.room.roomId,
565+
this.props.relation,
566+
this.props.mxClient,
567+
this.context.timelineRenderingType,
564568
);
565569
return true; // to skip internal onPaste handler
566570
}

0 commit comments

Comments
 (0)