diff --git a/res/css/_components.scss b/res/css/_components.scss
index a9a114a4cf..60f749de9c 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -57,13 +57,13 @@
 @import "./views/dialogs/_ConfirmUserActionDialog.scss";
 @import "./views/dialogs/_CreateGroupDialog.scss";
 @import "./views/dialogs/_CreateRoomDialog.scss";
-@import "./views/dialogs/_DMInviteDialog.scss";
 @import "./views/dialogs/_DeactivateAccountDialog.scss";
 @import "./views/dialogs/_DeviceVerifyDialog.scss";
 @import "./views/dialogs/_DevtoolsDialog.scss";
 @import "./views/dialogs/_EncryptedEventDialog.scss";
 @import "./views/dialogs/_GroupAddressPicker.scss";
 @import "./views/dialogs/_IncomingSasDialog.scss";
+@import "./views/dialogs/_InviteDialog.scss";
 @import "./views/dialogs/_MessageEditHistoryDialog.scss";
 @import "./views/dialogs/_RoomSettingsDialog.scss";
 @import "./views/dialogs/_RoomUpgradeDialog.scss";
diff --git a/res/css/views/dialogs/_DMInviteDialog.scss b/res/css/views/dialogs/_InviteDialog.scss
similarity index 86%
rename from res/css/views/dialogs/_DMInviteDialog.scss
rename to res/css/views/dialogs/_InviteDialog.scss
index 5d58f3ae8b..d0b53b7766 100644
--- a/res/css/views/dialogs/_DMInviteDialog.scss
+++ b/res/css/views/dialogs/_InviteDialog.scss
@@ -14,11 +14,11 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-.mx_DMInviteDialog_addressBar {
+.mx_InviteDialog_addressBar {
     display: flex;
     flex-direction: row;
 
-    .mx_DMInviteDialog_editor {
+    .mx_InviteDialog_editor {
         flex: 1;
         width: 100%; // Needed to make the Field inside grow
         background-color: $user-tile-hover-bg-color;
@@ -28,7 +28,7 @@ limitations under the License.
         overflow-x: hidden;
         overflow-y: auto;
 
-        .mx_DMInviteDialog_userTile {
+        .mx_InviteDialog_userTile {
             display: inline-block;
             float: left;
             position: relative;
@@ -61,14 +61,14 @@ limitations under the License.
         }
     }
 
-    .mx_DMInviteDialog_goButton {
+    .mx_InviteDialog_goButton {
         width: 48px;
         margin-left: 10px;
         height: 25px;
         line-height: 25px;
     }
 
-    .mx_DMInviteDialog_buttonAndSpinner {
+    .mx_InviteDialog_buttonAndSpinner {
         .mx_Spinner {
             // Width and height are required to trick the layout engine.
             width: 20px;
@@ -80,7 +80,7 @@ limitations under the License.
     }
 }
 
-.mx_DMInviteDialog_section {
+.mx_InviteDialog_section {
     padding-bottom: 10px;
 
     h3 {
@@ -91,7 +91,7 @@ limitations under the License.
     }
 }
 
-.mx_DMInviteDialog_roomTile {
+.mx_InviteDialog_roomTile {
     cursor: pointer;
     padding: 5px 10px;
 
@@ -104,7 +104,7 @@ limitations under the License.
         vertical-align: middle;
     }
 
-    .mx_DMInviteDialog_roomTile_avatarStack {
+    .mx_InviteDialog_roomTile_avatarStack {
         display: inline-block;
         position: relative;
         width: 36px;
@@ -117,7 +117,7 @@ limitations under the License.
         }
     }
 
-    .mx_DMInviteDialog_roomTile_selected {
+    .mx_InviteDialog_roomTile_selected {
         width: 36px;
         height: 36px;
         border-radius: 36px;
@@ -141,20 +141,20 @@ limitations under the License.
         }
     }
 
-    .mx_DMInviteDialog_roomTile_name {
+    .mx_InviteDialog_roomTile_name {
         font-weight: 600;
         font-size: 14px;
         color: $primary-fg-color;
         margin-left: 7px;
     }
 
-    .mx_DMInviteDialog_roomTile_userId {
+    .mx_InviteDialog_roomTile_userId {
         font-size: 12px;
         color: $muted-fg-color;
         margin-left: 7px;
     }
 
-    .mx_DMInviteDialog_roomTile_time {
+    .mx_InviteDialog_roomTile_time {
         text-align: right;
         font-size: 12px;
         color: $muted-fg-color;
@@ -162,16 +162,16 @@ limitations under the License.
         line-height: 36px; // Height of the avatar to keep the time vertically aligned
     }
 
-    .mx_DMInviteDialog_roomTile_highlight {
+    .mx_InviteDialog_roomTile_highlight {
         font-weight: 900;
     }
 }
 
 // Many of these styles are stolen from mx_UserPill, but adjusted for the invite dialog.
-.mx_DMInviteDialog_userTile {
+.mx_InviteDialog_userTile {
     margin-right: 8px;
 
-    .mx_DMInviteDialog_userTile_pill {
+    .mx_InviteDialog_userTile_pill {
         background-color: $username-variant1-color;
         border-radius: 12px;
         display: inline-block;
@@ -181,27 +181,27 @@ limitations under the License.
         padding-right: 8px;
         color: #ffffff; // this is fine without a var because it's for both themes
 
-        .mx_DMInviteDialog_userTile_avatar {
+        .mx_InviteDialog_userTile_avatar {
             border-radius: 20px;
             position: relative;
             left: -5px;
             top: 2px;
         }
 
-        img.mx_DMInviteDialog_userTile_avatar {
+        img.mx_InviteDialog_userTile_avatar {
             vertical-align: top;
         }
 
-        .mx_DMInviteDialog_userTile_name {
+        .mx_InviteDialog_userTile_name {
             vertical-align: top;
         }
 
-        .mx_DMInviteDialog_userTile_threepidAvatar {
+        .mx_InviteDialog_userTile_threepidAvatar {
             background-color: #ffffff; // this is fine without a var because it's for both themes
         }
     }
 
-    .mx_DMInviteDialog_userTile_remove {
+    .mx_InviteDialog_userTile_remove {
         display: inline-block;
         margin-left: 4px;
     }
diff --git a/src/RoomInvite.js b/src/RoomInvite.js
index 8b7324d4f5..2eccf69b0f 100644
--- a/src/RoomInvite.js
+++ b/src/RoomInvite.js
@@ -1,6 +1,7 @@
 /*
 Copyright 2016 OpenMarket Ltd
 Copyright 2017, 2018 New Vector Ltd
+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.
@@ -26,6 +27,7 @@ import dis from './dispatcher';
 import DMRoomMap from './utils/DMRoomMap';
 import { _t } from './languageHandler';
 import SettingsStore from "./settings/SettingsStore";
+import {KIND_DM, KIND_INVITE} from "./components/views/dialogs/InviteDialog";
 
 /**
  * Invites multiple addresses to a room
@@ -44,9 +46,9 @@ export function inviteMultipleToRoom(roomId, addrs) {
 export function showStartChatInviteDialog() {
     if (SettingsStore.isFeatureEnabled("feature_ftue_dms")) {
         // This new dialog handles the room creation internally - we don't need to worry about it.
-        const DMInviteDialog = sdk.getComponent("dialogs.DMInviteDialog");
+        const InviteDialog = sdk.getComponent("dialogs.InviteDialog");
         Modal.createTrackedDialog(
-            'Start DM', '', DMInviteDialog, {},
+            'Start DM', '', InviteDialog, {kind: KIND_DM},
             /*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
         );
         return;
@@ -72,6 +74,16 @@ export function showStartChatInviteDialog() {
 }
 
 export function showRoomInviteDialog(roomId) {
+    if (SettingsStore.isFeatureEnabled("feature_ftue_dms")) {
+        // This new dialog handles the room creation internally - we don't need to worry about it.
+        const InviteDialog = sdk.getComponent("dialogs.InviteDialog");
+        Modal.createTrackedDialog(
+            'Invite Users', '', InviteDialog, {kind: KIND_INVITE, roomId},
+            /*className=*/null, /*isPriority=*/false, /*isStatic=*/true,
+        );
+        return;
+    }
+
     const AddressPickerDialog = sdk.getComponent("dialogs.AddressPickerDialog");
 
     Modal.createTrackedDialog('Chat Invite', '', AddressPickerDialog, {
diff --git a/src/components/views/dialogs/DMInviteDialog.js b/src/components/views/dialogs/InviteDialog.js
similarity index 82%
rename from src/components/views/dialogs/DMInviteDialog.js
rename to src/components/views/dialogs/InviteDialog.js
index 2a5c896a75..1b7a50c084 100644
--- a/src/components/views/dialogs/DMInviteDialog.js
+++ b/src/components/views/dialogs/InviteDialog.js
@@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
 import {_t} from "../../../languageHandler";
 import * as sdk from "../../../index";
 import {MatrixClientPeg} from "../../../MatrixClientPeg";
-import {makeUserPermalink} from "../../../utils/permalinks/Permalinks";
+import {makeRoomPermalink, makeUserPermalink} from "../../../utils/permalinks/Permalinks";
 import DMRoomMap from "../../../utils/DMRoomMap";
 import {RoomMember} from "matrix-js-sdk/src/matrix";
 import SdkConfig from "../../../SdkConfig";
@@ -34,7 +34,8 @@ import {humanizeTime} from "../../../utils/humanize";
 import createRoom from "../../../createRoom";
 import {inviteMultipleToRoom} from "../../../RoomInvite";
 
-// TODO: [TravisR] Make this generic for all kinds of invites
+export const KIND_DM = "dm";
+export const KIND_INVITE = "invite";
 
 const INITIAL_ROOMS_SHOWN = 3; // Number of rooms to show at first
 const INCREMENT_ROOMS_SHOWN = 5; // Number of rooms to add when 'show more' is clicked
@@ -140,11 +141,11 @@ class DMUserTile extends React.PureComponent {
         const avatarSize = 20;
         const avatar = this.props.member.isEmail
             ? <img
-                className='mx_DMInviteDialog_userTile_avatar mx_DMInviteDialog_userTile_threepidAvatar'
+                className='mx_InviteDialog_userTile_avatar mx_InviteDialog_userTile_threepidAvatar'
                 src={require("../../../../res/img/icon-email-pill-avatar.svg")}
                 width={avatarSize} height={avatarSize} />
             : <BaseAvatar
-                className='mx_DMInviteDialog_userTile_avatar'
+                className='mx_InviteDialog_userTile_avatar'
                 url={getHttpUriForMxc(
                     MatrixClientPeg.get().getHomeserverUrl(), this.props.member.getMxcAvatarUrl(),
                     avatarSize, avatarSize, "crop")}
@@ -154,13 +155,13 @@ class DMUserTile extends React.PureComponent {
                 height={avatarSize} />;
 
         return (
-            <span className='mx_DMInviteDialog_userTile'>
-                <span className='mx_DMInviteDialog_userTile_pill'>
+            <span className='mx_InviteDialog_userTile'>
+                <span className='mx_InviteDialog_userTile_pill'>
                     {avatar}
-                    <span className='mx_DMInviteDialog_userTile_name'>{this.props.member.name}</span>
+                    <span className='mx_InviteDialog_userTile_name'>{this.props.member.name}</span>
                 </span>
                 <AccessibleButton
-                    className='mx_DMInviteDialog_userTile_remove'
+                    className='mx_InviteDialog_userTile_remove'
                     onClick={this._onRemove}
                 >
                     <img src={require("../../../../res/img/icon-pill-remove.svg")} alt={_t('Remove')} width={8} height={8} />
@@ -211,7 +212,7 @@ class DMRoomTile extends React.PureComponent {
 
             // Highlight the word the user entered
             const substr = str.substring(i, filterStr.length + i);
-            result.push(<span className='mx_DMInviteDialog_roomTile_highlight' key={i + 'bold'}>{substr}</span>);
+            result.push(<span className='mx_InviteDialog_roomTile_highlight' key={i + 'bold'}>{substr}</span>);
             i += substr.length;
         }
 
@@ -229,7 +230,7 @@ class DMRoomTile extends React.PureComponent {
         let timestamp = null;
         if (this.props.lastActiveTs) {
             const humanTs = humanizeTime(this.props.lastActiveTs);
-            timestamp = <span className='mx_DMInviteDialog_roomTile_time'>{humanTs}</span>;
+            timestamp = <span className='mx_InviteDialog_roomTile_time'>{humanTs}</span>;
         }
 
         const avatarSize = 36;
@@ -249,47 +250,74 @@ class DMRoomTile extends React.PureComponent {
         let checkmark = null;
         if (this.props.isSelected) {
             // To reduce flickering we put the 'selected' room tile above the real avatar
-            checkmark = <div className='mx_DMInviteDialog_roomTile_selected' />;
+            checkmark = <div className='mx_InviteDialog_roomTile_selected' />;
         }
 
         // To reduce flickering we put the checkmark on top of the actual avatar (prevents
         // the browser from reloading the image source when the avatar remounts).
         const stackedAvatar = (
-            <span className='mx_DMInviteDialog_roomTile_avatarStack'>
+            <span className='mx_InviteDialog_roomTile_avatarStack'>
                 {avatar}
                 {checkmark}
             </span>
         );
 
         return (
-            <div className='mx_DMInviteDialog_roomTile' onClick={this._onClick}>
+            <div className='mx_InviteDialog_roomTile' onClick={this._onClick}>
                 {stackedAvatar}
-                <span className='mx_DMInviteDialog_roomTile_name'>{this._highlightName(this.props.member.name)}</span>
-                <span className='mx_DMInviteDialog_roomTile_userId'>{this._highlightName(this.props.member.userId)}</span>
+                <span className='mx_InviteDialog_roomTile_name'>{this._highlightName(this.props.member.name)}</span>
+                <span className='mx_InviteDialog_roomTile_userId'>{this._highlightName(this.props.member.userId)}</span>
                 {timestamp}
             </div>
         );
     }
 }
 
-export default class DMInviteDialog extends React.PureComponent {
+export default class InviteDialog extends React.PureComponent {
     static propTypes = {
         // Takes an array of user IDs/emails to invite.
         onFinished: PropTypes.func.isRequired,
+
+        // The kind of invite being performed. Assumed to be KIND_DM if
+        // not provided.
+        kind: PropTypes.string,
+
+        // The room ID this dialog is for. Only required for KIND_INVITE.
+        roomId: PropTypes.string,
+    };
+
+    static defaultProps = {
+        kind: KIND_DM,
     };
 
     _debounceTimer: number = null;
     _editorRef: any = null;
 
-    constructor() {
-        super();
+    constructor(props) {
+        super(props);
+
+        if (props.kind === KIND_INVITE && !props.roomId) {
+            throw new Error("When using KIND_INVITE a roomId is required for an InviteDialog");
+        }
+
+        let alreadyInvited = [];
+        if (props.roomId) {
+            const room = MatrixClientPeg.get().getRoom(props.roomId);
+            if (!room) throw new Error("Room ID given to InviteDialog does not look like a room");
+            alreadyInvited = [
+                ...room.getMembersWithMembership('invite'),
+                ...room.getMembersWithMembership('join'),
+                ...room.getMembersWithMembership('ban'), // so we don't try to invite them
+            ].map(m => m.userId);
+        }
+
 
         this.state = {
             targets: [], // array of Member objects (see interface above)
             filterText: "",
-            recents: this._buildRecents(),
+            recents: this._buildRecents(alreadyInvited),
             numRecentsShown: INITIAL_ROOMS_SHOWN,
-            suggestions: this._buildSuggestions(),
+            suggestions: this._buildSuggestions(alreadyInvited),
             numSuggestionsShown: INITIAL_ROOMS_SHOWN,
             serverResultsMixin: [], // { user: DirectoryMember, userId: string }[], like recents and suggestions
             threepidResultsMixin: [], // { user: ThreepidMember, userId: string}[], like recents and suggestions
@@ -304,10 +332,13 @@ export default class DMInviteDialog extends React.PureComponent {
         this._editorRef = createRef();
     }
 
-    _buildRecents(): {userId: string, user: RoomMember, lastActive: number} {
+    _buildRecents(excludedTargetIds: string[]): {userId: string, user: RoomMember, lastActive: number} {
         const rooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals();
         const recents = [];
         for (const userId in rooms) {
+            // Filter out user IDs that are already in the room / should be excluded
+            if (excludedTargetIds.includes(userId)) continue;
+
             const room = rooms[userId];
             const member = room.getMember(userId);
             if (!member) continue; // just skip people who don't have memberships for some reason
@@ -326,7 +357,7 @@ export default class DMInviteDialog extends React.PureComponent {
         return recents;
     }
 
-    _buildSuggestions(): {userId: string, user: RoomMember} {
+    _buildSuggestions(excludedTargetIds: string[]): {userId: string, user: RoomMember} {
         const maxConsideredMembers = 200;
         const client = MatrixClientPeg.get();
         const excludedUserIds = [client.getUserId(), SdkConfig.get()['welcomeUserId']];
@@ -343,6 +374,11 @@ export default class DMInviteDialog extends React.PureComponent {
 
             const joinedMembers = room.getJoinedMembers().filter(u => !excludedUserIds.includes(u.userId));
             for (const member of joinedMembers) {
+                // Filter out user IDs that are already in the room / should be excluded
+                if (excludedTargetIds.includes(member.userId)) {
+                    continue;
+                }
+
                 if (!members[member.userId]) {
                     members[member.userId] = {
                         member: member,
@@ -390,6 +426,21 @@ export default class DMInviteDialog extends React.PureComponent {
         return members.map(m => ({userId: m.member.userId, user: m.member}));
     }
 
+    _shouldAbortAfterInviteError(result): boolean {
+        const failedUsers = Object.keys(result.states).filter(a => result.states[a] === 'error');
+        if (failedUsers.length > 0) {
+            console.log("Failed to invite users: ", result);
+            this.setState({
+                busy: false,
+                errorText: _t("Failed to invite the following users to chat: %(csvUsers)s", {
+                    csvUsers: failedUsers.join(", "),
+                }),
+            });
+            return true; // abort
+        }
+        return false;
+    }
+
     _startDm = () => {
         this.setState({busy: true});
         const targetIds = this.state.targets.map(t => t.userId);
@@ -417,15 +468,7 @@ export default class DMInviteDialog extends React.PureComponent {
             createRoomPromise = createRoom().then(roomId => {
                 return inviteMultipleToRoom(roomId, targetIds);
             }).then(result => {
-                const failedUsers = Object.keys(result.states).filter(a => result.states[a] === 'error');
-                if (failedUsers.length > 0) {
-                    console.log("Failed to invite users: ", result);
-                    this.setState({
-                        busy: false,
-                        errorText: _t("Failed to invite the following users to chat: %(csvUsers)s", {
-                            csvUsers: failedUsers.join(", "),
-                        }),
-                    });
+                if (this._shouldAbortAfterInviteError(result)) {
                     return true; // abort
                 }
             });
@@ -444,6 +487,35 @@ export default class DMInviteDialog extends React.PureComponent {
         });
     };
 
+    _inviteUsers = () => {
+        this.setState({busy: true});
+        const targetIds = this.state.targets.map(t => t.userId);
+
+        const room = MatrixClientPeg.get().getRoom(this.props.roomId);
+        if (!room) {
+            console.error("Failed to find the room to invite users to");
+            this.setState({
+                busy: false,
+                errorText: _t("Something went wrong trying to invite the users."),
+            });
+            return;
+        }
+
+        inviteMultipleToRoom(this.props.roomId, targetIds).then(result => {
+            if (!this._shouldAbortAfterInviteError(result)) { // handles setting error message too
+                this.props.onFinished();
+            }
+        }).catch(err => {
+            console.error(err);
+            this.setState({
+                busy: false,
+                errorText: _t(
+                    "We couldn't invite those users. Please check the users you want to invite and try again.",
+                ),
+            });
+        });
+    };
+
     _cancel = () => {
         // We do not want the user to close the dialog while an action is in progress
         if (this.state.busy) return;
@@ -658,7 +730,11 @@ export default class DMInviteDialog extends React.PureComponent {
         let showNum = kind === 'recents' ? this.state.numRecentsShown : this.state.numSuggestionsShown;
         const showMoreFn = kind === 'recents' ? this._showMoreRecents.bind(this) : this._showMoreSuggestions.bind(this);
         const lastActive = (m) => kind === 'recents' ? m.lastActive : null;
-        const sectionName = kind === 'recents' ? _t("Recent Conversations") : _t("Suggestions");
+        let sectionName = kind === 'recents' ? _t("Recent Conversations") : _t("Suggestions");
+
+        if (this.props.kind === KIND_INVITE) {
+            sectionName = kind === 'recents' ? _t("Recently Direct Messaged") : _t("Suggestions");
+        }
 
         // Mix in the server results if we have any, but only if we're searching. We track the additional
         // members separately because we want to filter sourceMembers but trust the mixin arrays to have
@@ -690,7 +766,7 @@ export default class DMInviteDialog extends React.PureComponent {
 
             if (sourceMembers.length === 0 && additionalMembers.length === 0) {
                 return (
-                    <div className='mx_DMInviteDialog_section'>
+                    <div className='mx_InviteDialog_section'>
                         <h3>{sectionName}</h3>
                         <p>{_t("No results")}</p>
                     </div>
@@ -731,7 +807,7 @@ export default class DMInviteDialog extends React.PureComponent {
             />
         ));
         return (
-            <div className='mx_DMInviteDialog_section'>
+            <div className='mx_InviteDialog_section'>
                 <h3>{sectionName}</h3>
                 {tiles}
                 {showMore}
@@ -754,7 +830,7 @@ export default class DMInviteDialog extends React.PureComponent {
             />
         );
         return (
-            <div className='mx_DMInviteDialog_editor' onClick={this._onClickInputArea}>
+            <div className='mx_InviteDialog_editor' onClick={this._onClickInputArea}>
                 {targets}
                 {input}
             </div>
@@ -805,33 +881,54 @@ export default class DMInviteDialog extends React.PureComponent {
             spinner = <Spinner w={20} h={20} />;
         }
 
-        const userId = MatrixClientPeg.get().getUserId();
+
+        let title;
+        let helpText;
+        let buttonText;
+        let goButtonFn;
+
+        if (this.props.kind === KIND_DM) {
+            const userId = MatrixClientPeg.get().getUserId();
+
+            title = _t("Direct Messages");
+            helpText = _t(
+                "If you can't find someone, ask them for their username, or share your " +
+                "username (%(userId)s) or <a>profile link</a>.",
+                {userId},
+                {a: (sub) => <a href={makeUserPermalink(userId)} rel="noopener" target="_blank">{sub}</a>},
+            );
+            buttonText = _t("Go");
+            goButtonFn = this._startDm;
+        } else { // KIND_INVITE
+            title = _t("Invite to this room");
+            helpText = _t(
+                "If you can't find someone, ask them for their username (e.g. @user:server.com) or " +
+                "<a>share this room</a>.", {},
+                {a: (sub) => <a href={makeRoomPermalink(this.props.roomId)} rel="noopener" target="_blank">{sub}</a>},
+            );
+            buttonText = _t("Invite");
+            goButtonFn = this._inviteUsers;
+        }
+
         return (
             <BaseDialog
-                className='mx_DMInviteDialog'
+                className='mx_InviteDialog'
                 hasCancel={true}
                 onFinished={this._cancel}
-                title={_t("Direct Messages")}
+                title={title}
             >
-                <div className='mx_DMInviteDialog_content'>
-                    <p>
-                        {_t(
-                            "If you can't find someone, ask them for their username, or share your " +
-                            "username (%(userId)s) or <a>profile link</a>.",
-                            {userId},
-                            {a: (sub) => <a href={makeUserPermalink(userId)} rel="noopener" target="_blank">{sub}</a>},
-                        )}
-                    </p>
-                    <div className='mx_DMInviteDialog_addressBar'>
+                <div className='mx_InviteDialog_content'>
+                    <p>{helpText}</p>
+                    <div className='mx_InviteDialog_addressBar'>
                         {this._renderEditor()}
-                        <div className='mx_DMInviteDialog_buttonAndSpinner'>
+                        <div className='mx_InviteDialog_buttonAndSpinner'>
                             <AccessibleButton
                                 kind="primary"
-                                onClick={this._startDm}
-                                className='mx_DMInviteDialog_goButton'
+                                onClick={goButtonFn}
+                                className='mx_InviteDialog_goButton'
                                 disabled={this.state.busy}
                             >
-                                {_t("Go")}
+                                {buttonText}
                             </AccessibleButton>
                             {spinner}
                         </div>
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index b6f61570cd..f8b17db7c5 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -372,7 +372,7 @@
     "Render simple counters in room header": "Render simple counters in room header",
     "Multiple integration managers": "Multiple integration managers",
     "Try out new ways to ignore people (experimental)": "Try out new ways to ignore people (experimental)",
-    "New DM invite dialog (under development)": "New DM invite dialog (under development)",
+    "New invite dialog": "New invite dialog",
     "Show a presence dot next to DMs in the room list": "Show a presence dot next to DMs in the room list",
     "Enable cross-signing to verify per-user instead of per-device (in development)": "Enable cross-signing to verify per-user instead of per-device (in development)",
     "Enable local event indexing and E2EE search (requires restart)": "Enable local event indexing and E2EE search (requires restart)",
@@ -1438,16 +1438,6 @@
     "View Servers in Room": "View Servers in Room",
     "Toolbox": "Toolbox",
     "Developer Tools": "Developer Tools",
-    "Failed to invite the following users to chat: %(csvUsers)s": "Failed to invite the following users to chat: %(csvUsers)s",
-    "We couldn't create your DM. Please check the users you want to invite and try again.": "We couldn't create your DM. Please check the users you want to invite and try again.",
-    "Failed to find the following users": "Failed to find the following users",
-    "The following users might not exist or are invalid, and cannot be invited: %(csvNames)s": "The following users might not exist or are invalid, and cannot be invited: %(csvNames)s",
-    "Recent Conversations": "Recent Conversations",
-    "Suggestions": "Suggestions",
-    "Show more": "Show more",
-    "Direct Messages": "Direct Messages",
-    "If you can't find someone, ask them for their username, or share your username (%(userId)s) or <a>profile link</a>.": "If you can't find someone, ask them for their username, or share your username (%(userId)s) or <a>profile link</a>.",
-    "Go": "Go",
     "An error has occurred.": "An error has occurred.",
     "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.": "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.",
     "Verifying this user will mark their device as trusted, and also mark your device as trusted to them.": "Verifying this user will mark their device as trusted, and also mark your device as trusted to them.",
@@ -1457,6 +1447,20 @@
     "Enable 'Manage Integrations' in Settings to do this.": "Enable 'Manage Integrations' in Settings to do this.",
     "Integrations not allowed": "Integrations not allowed",
     "Your Riot doesn't allow you to use an Integration Manager to do this. Please contact an admin.": "Your Riot doesn't allow you to use an Integration Manager to do this. Please contact an admin.",
+    "Failed to invite the following users to chat: %(csvUsers)s": "Failed to invite the following users to chat: %(csvUsers)s",
+    "We couldn't create your DM. Please check the users you want to invite and try again.": "We couldn't create your DM. Please check the users you want to invite and try again.",
+    "Something went wrong trying to invite the users.": "Something went wrong trying to invite the users.",
+    "We couldn't invite those users. Please check the users you want to invite and try again.": "We couldn't invite those users. Please check the users you want to invite and try again.",
+    "Failed to find the following users": "Failed to find the following users",
+    "The following users might not exist or are invalid, and cannot be invited: %(csvNames)s": "The following users might not exist or are invalid, and cannot be invited: %(csvNames)s",
+    "Recent Conversations": "Recent Conversations",
+    "Suggestions": "Suggestions",
+    "Recently Direct Messaged": "Recently Direct Messaged",
+    "Show more": "Show more",
+    "Direct Messages": "Direct Messages",
+    "If you can't find someone, ask them for their username, or share your username (%(userId)s) or <a>profile link</a>.": "If you can't find someone, ask them for their username, or share your username (%(userId)s) or <a>profile link</a>.",
+    "Go": "Go",
+    "If you can't find someone, ask them for their username (e.g. @user:server.com) or <a>share this room</a>.": "If you can't find someone, ask them for their username (e.g. @user:server.com) or <a>share this room</a>.",
     "You added a new device '%(displayName)s', which is requesting encryption keys.": "You added a new device '%(displayName)s', which is requesting encryption keys.",
     "Your unverified device '%(displayName)s' is requesting encryption keys.": "Your unverified device '%(displayName)s' is requesting encryption keys.",
     "Start verification": "Start verification",
diff --git a/src/settings/Settings.js b/src/settings/Settings.js
index 2b8c0aef89..eacf63e55d 100644
--- a/src/settings/Settings.js
+++ b/src/settings/Settings.js
@@ -130,7 +130,7 @@ export const SETTINGS = {
     },
     "feature_ftue_dms": {
         isFeature: true,
-        displayName: _td("New DM invite dialog (under development)"),
+        displayName: _td("New invite dialog"),
         supportedLevels: LEVELS_FEATURE,
         default: false,
     },