diff --git a/res/css/views/dialogs/_InviteDialog.scss b/res/css/views/dialogs/_InviteDialog.scss index a77d0bfbba..b9063f46b9 100644 --- a/res/css/views/dialogs/_InviteDialog.scss +++ b/res/css/views/dialogs/_InviteDialog.scss @@ -89,6 +89,13 @@ limitations under the License. font-weight: bold; text-transform: uppercase; } + + .mx_InviteDialog_subname { + margin-bottom: 10px; + margin-top: -10px; // HACK: Positioning with margins is bad + font-size: $font-12px; + color: $muted-fg-color; + } } .mx_InviteDialog_roomTile { @@ -226,3 +233,7 @@ limitations under the License. .mx_InviteDialog_addressBar { margin-right: 45px; } + +.mx_InviteDialog_helpText .mx_AccessibleButton_kind_link { + padding: 0; +} diff --git a/src/RoomInvite.js b/src/RoomInvite.js index 420561ea41..cae4501901 100644 --- a/src/RoomInvite.js +++ b/src/RoomInvite.js @@ -24,6 +24,7 @@ import * as sdk from './'; import { _t } from './languageHandler'; import {KIND_DM, KIND_INVITE} from "./components/views/dialogs/InviteDialog"; import CommunityPrototypeInviteDialog from "./components/views/dialogs/CommunityPrototypeInviteDialog"; +import GroupStore from "./stores/GroupStore"; /** * Invites multiple addresses to a room @@ -64,6 +65,24 @@ export function showCommunityRoomInviteDialog(roomId, communityName) { ); } +export function showCommunityInviteDialog(communityId) { + const rooms = GroupStore.getGroupRooms(communityId) + .map(r => MatrixClientPeg.get().getRoom(r.roomId)) + .filter(r => !!r); + let chat = rooms.find(r => { + const idState = r.currentState.getStateEvents("im.vector.general_chat", ""); + if (!idState || idState.getContent()['groupId'] !== communityId) return false; + return true; + }); + if (!chat) chat = rooms[0]; + if (chat) { + const summary = GroupStore.getSummary(communityId); + showCommunityRoomInviteDialog(chat.roomId, summary?.profile?.name || communityId); + } else { + throw new Error("Failed to locate appropriate room to start an invite in"); + } +} + /** * Checks if the given MatrixEvent is a valid 3rd party user invite. * @param {MatrixEvent} event The event to check diff --git a/src/components/views/dialogs/InviteDialog.js b/src/components/views/dialogs/InviteDialog.js index 6cd0b22505..934ed12ac1 100644 --- a/src/components/views/dialogs/InviteDialog.js +++ b/src/components/views/dialogs/InviteDialog.js @@ -32,11 +32,13 @@ import IdentityAuthClient from "../../../IdentityAuthClient"; import Modal from "../../../Modal"; import {humanizeTime} from "../../../utils/humanize"; import createRoom, {canEncryptToAllUsers, privateShouldBeEncrypted} from "../../../createRoom"; -import {inviteMultipleToRoom} from "../../../RoomInvite"; +import {inviteMultipleToRoom, showCommunityInviteDialog} from "../../../RoomInvite"; import {Key} from "../../../Keyboard"; import {Action} from "../../../dispatcher/actions"; import {DefaultTagID} from "../../../stores/room-list/models"; import RoomListStore from "../../../stores/room-list/RoomListStore"; +import TagOrderStore from "../../../stores/TagOrderStore"; +import GroupStore from "../../../stores/GroupStore"; // we have a number of types defined from the Matrix spec which can't reasonably be altered here. /* eslint-disable camelcase */ @@ -909,12 +911,24 @@ export default class InviteDialog extends React.PureComponent { this.props.onFinished(); }; + _onCommunityInviteClick = (e) => { + this.props.onFinished(); + showCommunityInviteDialog(TagOrderStore.getSelectedPrototypeTag()); + }; + _renderSection(kind: "recents"|"suggestions") { let sourceMembers = kind === 'recents' ? this.state.recents : this.state.suggestions; 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; let sectionName = kind === 'recents' ? _t("Recent Conversations") : _t("Suggestions"); + let sectionSubname = null; + + if (kind === 'suggestions' && TagOrderStore.getSelectedPrototypeTag()) { + const summary = GroupStore.getSummary(TagOrderStore.getSelectedPrototypeTag()); + const communityName = summary?.profile?.name || TagOrderStore.getSelectedPrototypeTag(); + sectionSubname = _t("May include members not in %(communityName)s", {communityName}); + } if (this.props.kind === KIND_INVITE) { sectionName = kind === 'recents' ? _t("Recently Direct Messaged") : _t("Suggestions"); @@ -993,6 +1007,7 @@ export default class InviteDialog extends React.PureComponent { return (

{sectionName}

+ {sectionSubname ?

{sectionSubname}

: null} {tiles} {showMore}
@@ -1083,6 +1098,34 @@ export default class InviteDialog extends React.PureComponent { return {userId}; }}, ); + if (TagOrderStore.getSelectedPrototypeTag()) { + const communityId = TagOrderStore.getSelectedPrototypeTag(); + const communityName = GroupStore.getSummary(communityId)?.profile?.name || communityId; + helpText = _t( + "Start a conversation with someone using their name, username (like ) or email address. " + + "This won't invite them to %(communityName)s. To invite someone to %(communityName)s, click " + + "here.", + {communityName}, { + userId: () => { + return ( + {userId} + ); + }, + a: (sub) => { + return ( + {sub} + ); + }, + }, + ); + } buttonText = _t("Go"); goButtonFn = this._startDm; } else { // KIND_INVITE diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 442f07499c..0d01fd47c8 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1709,9 +1709,11 @@ "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", + "May include members not in %(communityName)s": "May include members not in %(communityName)s", "Recently Direct Messaged": "Recently Direct Messaged", "Direct Messages": "Direct Messages", "Start a conversation with someone using their name, username (like ) or email address.": "Start a conversation with someone using their name, username (like ) or email address.", + "Start a conversation with someone using their name, username (like ) or email address. This won't invite them to %(communityName)s. To invite someone to %(communityName)s, click here.": "Start a conversation with someone using their name, username (like ) or email address. This won't invite them to %(communityName)s. To invite someone to %(communityName)s, click here.", "Go": "Go", "Invite someone using their name, username (like ), email address or share this room.": "Invite someone using their name, username (like ), email address or share this room.", "a new master key signature": "a new master key signature",