mirror of https://github.com/vector-im/riot-web
Allow requesting to join knock rooms via spotlight (#11482)
Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net>pull/28788/head^2
parent
200631f3a5
commit
50160b9969
|
@ -24,6 +24,7 @@ import {
|
||||||
RoomType,
|
RoomType,
|
||||||
Room,
|
Room,
|
||||||
HierarchyRoom,
|
HierarchyRoom,
|
||||||
|
JoinRule,
|
||||||
} from "matrix-js-sdk/src/matrix";
|
} from "matrix-js-sdk/src/matrix";
|
||||||
import { normalize } from "matrix-js-sdk/src/utils";
|
import { normalize } from "matrix-js-sdk/src/utils";
|
||||||
import React, { ChangeEvent, RefObject, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
import React, { ChangeEvent, RefObject, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
@ -276,6 +277,10 @@ const roomAriaUnreadLabel = (room: Room, notification: RoomNotificationState): s
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const canAskToJoin = (joinRule?: JoinRule): boolean => {
|
||||||
|
return SettingsStore.getValue("feature_ask_to_join") && JoinRule.Knock === joinRule;
|
||||||
|
};
|
||||||
|
|
||||||
interface IDirectoryOpts {
|
interface IDirectoryOpts {
|
||||||
limit: number;
|
limit: number;
|
||||||
query: string;
|
query: string;
|
||||||
|
@ -514,7 +519,14 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
|
||||||
}, [results, filter]);
|
}, [results, filter]);
|
||||||
|
|
||||||
const viewRoom = (
|
const viewRoom = (
|
||||||
room: { roomId: string; roomAlias?: string; autoJoin?: boolean; shouldPeek?: boolean; viaServers?: string[] },
|
room: {
|
||||||
|
roomId: string;
|
||||||
|
roomAlias?: string;
|
||||||
|
autoJoin?: boolean;
|
||||||
|
shouldPeek?: boolean;
|
||||||
|
viaServers?: string[];
|
||||||
|
joinRule?: IPublicRoomsChunkRoom["join_rule"];
|
||||||
|
},
|
||||||
persist = false,
|
persist = false,
|
||||||
viaKeyboard = false,
|
viaKeyboard = false,
|
||||||
): void => {
|
): void => {
|
||||||
|
@ -538,10 +550,15 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
|
||||||
metricsViaKeyboard: viaKeyboard,
|
metricsViaKeyboard: viaKeyboard,
|
||||||
room_id: room.roomId,
|
room_id: room.roomId,
|
||||||
room_alias: room.roomAlias,
|
room_alias: room.roomAlias,
|
||||||
auto_join: room.autoJoin,
|
auto_join: room.autoJoin && !canAskToJoin(room.joinRule),
|
||||||
should_peek: room.shouldPeek,
|
should_peek: room.shouldPeek,
|
||||||
via_servers: room.viaServers,
|
via_servers: room.viaServers,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (canAskToJoin(room.joinRule)) {
|
||||||
|
defaultDispatcher.dispatch({ action: Action.PromptAskToJoin });
|
||||||
|
}
|
||||||
|
|
||||||
onFinished();
|
onFinished();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -647,12 +664,15 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
|
||||||
}
|
}
|
||||||
if (isPublicRoomResult(result)) {
|
if (isPublicRoomResult(result)) {
|
||||||
const clientRoom = cli.getRoom(result.publicRoom.room_id);
|
const clientRoom = cli.getRoom(result.publicRoom.room_id);
|
||||||
|
const joinRule = result.publicRoom.join_rule;
|
||||||
// Element Web currently does not allow guests to join rooms, so we
|
// Element Web currently does not allow guests to join rooms, so we
|
||||||
// instead show them view buttons for all rooms. If the room is not
|
// instead show them view buttons for all rooms. If the room is not
|
||||||
// world readable, a modal will appear asking you to register first. If
|
// world readable, a modal will appear asking you to register first. If
|
||||||
// it is readable, the preview appears as normal.
|
// it is readable, the preview appears as normal.
|
||||||
const showViewButton =
|
const showViewButton =
|
||||||
clientRoom?.getMyMembership() === "join" || result.publicRoom.world_readable || cli.isGuest();
|
clientRoom?.getMyMembership() === "join" ||
|
||||||
|
(result.publicRoom.world_readable && !canAskToJoin(joinRule)) ||
|
||||||
|
cli.isGuest();
|
||||||
|
|
||||||
const listener = (ev: ButtonEvent): void => {
|
const listener = (ev: ButtonEvent): void => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
@ -665,12 +685,20 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
|
||||||
autoJoin: !result.publicRoom.world_readable && !cli.isGuest(),
|
autoJoin: !result.publicRoom.world_readable && !cli.isGuest(),
|
||||||
shouldPeek: result.publicRoom.world_readable || cli.isGuest(),
|
shouldPeek: result.publicRoom.world_readable || cli.isGuest(),
|
||||||
viaServers: config ? [config.roomServer] : undefined,
|
viaServers: config ? [config.roomServer] : undefined,
|
||||||
|
joinRule,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
ev.type !== "click",
|
ev.type !== "click",
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let buttonLabel;
|
||||||
|
if (showViewButton) {
|
||||||
|
buttonLabel = _t("action|view");
|
||||||
|
} else {
|
||||||
|
buttonLabel = canAskToJoin(joinRule) ? _t("action|ask_to_join") : _t("action|join");
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Option
|
<Option
|
||||||
id={`mx_SpotlightDialog_button_result_${result.publicRoom.room_id}`}
|
id={`mx_SpotlightDialog_button_result_${result.publicRoom.room_id}`}
|
||||||
|
@ -683,7 +711,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
|
||||||
onClick={listener}
|
onClick={listener}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
>
|
>
|
||||||
{showViewButton ? _t("action|view") : _t("action|join")}
|
{buttonLabel}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
}
|
}
|
||||||
aria-labelledby={`mx_SpotlightDialog_button_result_${result.publicRoom.room_id}_name`}
|
aria-labelledby={`mx_SpotlightDialog_button_result_${result.publicRoom.room_id}_name`}
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
"resend": "Resend",
|
"resend": "Resend",
|
||||||
"next": "Next",
|
"next": "Next",
|
||||||
"view": "View",
|
"view": "View",
|
||||||
|
"ask_to_join": "Ask to join",
|
||||||
"forward": "Forward",
|
"forward": "Forward",
|
||||||
"copy_link": "Copy link",
|
"copy_link": "Copy link",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
ConnectionError,
|
ConnectionError,
|
||||||
IProtocol,
|
IProtocol,
|
||||||
IPublicRoomsChunkRoom,
|
IPublicRoomsChunkRoom,
|
||||||
|
JoinRule,
|
||||||
MatrixClient,
|
MatrixClient,
|
||||||
Room,
|
Room,
|
||||||
RoomMember,
|
RoomMember,
|
||||||
|
@ -38,6 +39,7 @@ import SettingsStore from "../../../../src/settings/SettingsStore";
|
||||||
import { SettingLevel } from "../../../../src/settings/SettingLevel";
|
import { SettingLevel } from "../../../../src/settings/SettingLevel";
|
||||||
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
||||||
import SdkConfig from "../../../../src/SdkConfig";
|
import SdkConfig from "../../../../src/SdkConfig";
|
||||||
|
import { Action } from "../../../../src/dispatcher/actions";
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
@ -574,4 +576,75 @@ describe("Spotlight Dialog", () => {
|
||||||
|
|
||||||
expect(screen.getByText("Failed to query public rooms")).toBeInTheDocument();
|
expect(screen.getByText("Failed to query public rooms")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("knock rooms", () => {
|
||||||
|
const knockRoom: IPublicRoomsChunkRoom = {
|
||||||
|
guest_can_join: false,
|
||||||
|
join_rule: JoinRule.Knock,
|
||||||
|
num_joined_members: 0,
|
||||||
|
room_id: "some-room-id",
|
||||||
|
world_readable: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewRoomParams = {
|
||||||
|
action: Action.ViewRoom,
|
||||||
|
metricsTrigger: "WebUnifiedSearch",
|
||||||
|
metricsViaKeyboard: false,
|
||||||
|
room_alias: undefined,
|
||||||
|
room_id: knockRoom.room_id,
|
||||||
|
should_peek: false,
|
||||||
|
via_servers: ["example.tld"],
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => (mockedClient = mockClient({ rooms: [knockRoom] })));
|
||||||
|
|
||||||
|
describe("when disabling feature", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) =>
|
||||||
|
setting === "feature_ask_to_join" ? false : [],
|
||||||
|
);
|
||||||
|
|
||||||
|
render(<SpotlightDialog initialFilter={Filter.PublicRooms} onFinished={() => {}} />);
|
||||||
|
|
||||||
|
// search is debounced
|
||||||
|
jest.advanceTimersByTime(200);
|
||||||
|
await flushPromisesWithFakeTimers();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "View" }));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not skip to auto join", async () => {
|
||||||
|
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ ...viewRoomParams, auto_join: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not prompt ask to join", async () => {
|
||||||
|
expect(defaultDispatcher.dispatch).not.toHaveBeenCalledWith({ action: Action.PromptAskToJoin });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when enabling feature", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) =>
|
||||||
|
setting === "feature_ask_to_join" ? true : [],
|
||||||
|
);
|
||||||
|
jest.spyOn(mockedClient, "getRoom").mockReturnValue(null);
|
||||||
|
|
||||||
|
render(<SpotlightDialog initialFilter={Filter.PublicRooms} onFinished={() => {}} />);
|
||||||
|
|
||||||
|
// search is debounced
|
||||||
|
jest.advanceTimersByTime(200);
|
||||||
|
await flushPromisesWithFakeTimers();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "Ask to join" }));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should skip to auto join", async () => {
|
||||||
|
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ ...viewRoomParams, auto_join: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should prompt ask to join", async () => {
|
||||||
|
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ action: Action.PromptAskToJoin });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue