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

Commit

Permalink
Allow sending files as replies as per MSC3676 (#8020)
Browse files Browse the repository at this point in the history
  • Loading branch information
t3chguy authored Mar 21, 2022
1 parent 14653d1 commit dd53b22
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 55 deletions.
44 changes: 21 additions & 23 deletions src/ContentMessages.tsx → src/ContentMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,21 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { IUploadOpts } from "matrix-js-sdk/src/@types/requests";
import { MsgType } from "matrix-js-sdk/src/@types/event";
import encrypt from "browser-encrypt-attachment";
import extractPngChunks from "png-chunks-extract";
import { IAbortablePromise, IImageInfo } from "matrix-js-sdk/src/@types/partials";
import { logger } from "matrix-js-sdk/src/logger";
import { IEventRelation, ISendEventResponse } from "matrix-js-sdk/src/matrix";
import { IEventRelation, ISendEventResponse, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";

import { IEncryptedFile, IMediaEventInfo } from "./customisations/models/IMediaEventContent";
import dis from './dispatcher/dispatcher';
import * as sdk from './index';
import { _t } from './languageHandler';
import Modal from './Modal';
import RoomViewStore from './stores/RoomViewStore';
import Spinner from "./components/views/elements/Spinner";
import { Action } from "./dispatcher/actions";
import {
Expand All @@ -47,6 +45,8 @@ import { BlurhashEncoder } from "./BlurhashEncoder";
import SettingsStore from "./settings/SettingsStore";
import { decorateStartSendingTime, sendRoundTripMetric } from "./sendTimePerformanceMetrics";
import { TimelineRenderingType } from "./contexts/RoomContext";
import RoomViewStore from "./stores/RoomViewStore";
import { addReplyToMessageContent } from "./utils/Reply";

const MAX_WIDTH = 800;
const MAX_HEIGHT = 600;
Expand Down Expand Up @@ -457,25 +457,7 @@ export default class ContentMessages {
return;
}

const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
if (isQuoting) {
// FIXME: Using an import will result in Element crashing
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const { finished } = Modal.createTrackedDialog<[boolean]>('Upload Reply Warning', '', QuestionDialog, {
title: _t('Replying With Files'),
description: (
<div>{ _t(
'At this time it is not possible to reply with a file. ' +
'Would you like to upload this file without replying?',
) }</div>
),
hasCancelButton: true,
button: _t("Continue"),
});
const [shouldUpload] = await finished;
if (!shouldUpload) return;
}

const replyToEvent = RoomViewStore.getQuotingEvent();
if (!this.mediaConfig) { // hot-path optimization to not flash a spinner if we don't need to
const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner');
await this.ensureMediaConfigFetched(matrixClient);
Expand Down Expand Up @@ -528,7 +510,16 @@ export default class ContentMessages {
}
}

promBefore = this.sendContentToRoom(file, roomId, relation, matrixClient, promBefore);
promBefore = this.sendContentToRoom(file, roomId, relation, matrixClient, replyToEvent, promBefore);
}

if (replyToEvent) {
// Clear event being replied to
dis.dispatch({
action: "reply_to_event",
event: null,
context,
});
}

// Focus the correct composer
Expand Down Expand Up @@ -569,6 +560,7 @@ export default class ContentMessages {
roomId: string,
relation: IEventRelation | undefined,
matrixClient: MatrixClient,
replyToEvent: MatrixEvent | undefined,
promBefore: Promise<any>,
) {
const content: IContent = {
Expand All @@ -583,6 +575,12 @@ export default class ContentMessages {
content["m.relates_to"] = relation;
}

if (replyToEvent) {
addReplyToMessageContent(content, replyToEvent, {
includeLegacyFallback: false,
});
}

if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) {
decorateStartSendingTime(content);
}
Expand Down
30 changes: 1 addition & 29 deletions src/components/views/rooms/SendMessageComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,35 +58,7 @@ import { ComposerType } from "../../../dispatcher/payloads/ComposerInsertPayload
import { getSlashCommand, isSlashCommand, runSlashCommand, shouldSendAnyway } from "../../../editor/commands";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import { PosthogAnalytics } from "../../../PosthogAnalytics";
import { getNestedReplyText, makeReplyMixIn } from '../../../utils/Reply';

interface IAddReplyOpts {
permalinkCreator?: RoomPermalinkCreator;
includeLegacyFallback?: boolean;
}

function addReplyToMessageContent(
content: IContent,
replyToEvent: MatrixEvent,
opts: IAddReplyOpts = {
includeLegacyFallback: true,
},
): void {
const replyContent = makeReplyMixIn(replyToEvent);
Object.assign(content, replyContent);

if (opts.includeLegacyFallback) {
// Part of Replies fallback support - prepend the text we're sending
// with the text we're replying to
const nestedReply = getNestedReplyText(replyToEvent, opts.permalinkCreator);
if (nestedReply) {
if (content.formatted_body) {
content.formatted_body = nestedReply.html + content.formatted_body;
}
content.body = nestedReply.body + content.body;
}
}
}
import { addReplyToMessageContent } from '../../../utils/Reply';

export function attachRelation(
content: IContent,
Expand Down
4 changes: 1 addition & 3 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@
"You do not have permission to start a conference call in this room": "You do not have permission to start a conference call in this room",
"End conference": "End conference",
"This will end the conference for everyone. Continue?": "This will end the conference for everyone. Continue?",
"Replying With Files": "Replying With Files",
"At this time it is not possible to reply with a file. Would you like to upload this file without replying?": "At this time it is not possible to reply with a file. Would you like to upload this file without replying?",
"Continue": "Continue",
"The file '%(fileName)s' failed to upload.": "The file '%(fileName)s' failed to upload.",
"The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "The file '%(fileName)s' exceeds this homeserver's size limit for uploads",
"Upload Failed": "Upload Failed",
Expand Down Expand Up @@ -455,6 +452,7 @@
"Invites user with given id to current room": "Invites user with given id to current room",
"Use an identity server": "Use an identity server",
"Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.",
"Continue": "Continue",
"Use an identity server to invite by email. Manage in Settings.": "Use an identity server to invite by email. Manage in Settings.",
"Joins room with given address": "Joins room with given address",
"Leave room": "Leave room",
Expand Down
28 changes: 28 additions & 0 deletions src/utils/Reply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,31 @@ export function shouldDisplayReply(event: MatrixEvent): boolean {

return !!inReplyTo.event_id;
}

interface IAddReplyOpts {
permalinkCreator?: RoomPermalinkCreator;
includeLegacyFallback?: boolean;
}

export function addReplyToMessageContent(
content: IContent,
replyToEvent: MatrixEvent,
opts: IAddReplyOpts = {
includeLegacyFallback: true,
},
): void {
const replyContent = makeReplyMixIn(replyToEvent);
Object.assign(content, replyContent);

if (opts.includeLegacyFallback) {
// Part of Replies fallback support - prepend the text we're sending
// with the text we're replying to
const nestedReply = getNestedReplyText(replyToEvent, opts.permalinkCreator);
if (nestedReply) {
if (content.formatted_body) {
content.formatted_body = nestedReply.html + content.formatted_body;
}
content.body = nestedReply.body + content.body;
}
}
}

0 comments on commit dd53b22

Please sign in to comment.