Filter NSFW content in room directory (#10196)
* add SpotlightSearch.showNsfwPublicRooms setting * use setting in publicroomsearch * add nsfw keyword filter and setting for room directory * unit tests * remove assertions
This commit is contained in:
parent
03e4b96037
commit
168f6df7c8
5 changed files with 86 additions and 2 deletions
|
@ -89,6 +89,8 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
|
||||||
"useOnlyCurrentProfiles",
|
"useOnlyCurrentProfiles",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private static ROOM_DIRECTORY_SETTINGS = ["SpotlightSearch.showNsfwPublicRooms"];
|
||||||
|
|
||||||
private static GENERAL_SETTINGS = [
|
private static GENERAL_SETTINGS = [
|
||||||
"promptBeforeInviteUnknownUsers",
|
"promptBeforeInviteUnknownUsers",
|
||||||
// Start automatically after startup (electron-only)
|
// Start automatically after startup (electron-only)
|
||||||
|
@ -234,6 +236,11 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
|
||||||
{this.renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)}
|
{this.renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="mx_SettingsTab_section">
|
||||||
|
<span className="mx_SettingsTab_subheading">{_t("Room directory")}</span>
|
||||||
|
{this.renderGroup(PreferencesUserSettingsTab.ROOM_DIRECTORY_SETTINGS)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="mx_SettingsTab_section">
|
<div className="mx_SettingsTab_section">
|
||||||
<span className="mx_SettingsTab_subheading">{_t("General")}</span>
|
<span className="mx_SettingsTab_subheading">{_t("General")}</span>
|
||||||
{this.renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)}
|
{this.renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import SdkConfig from "../SdkConfig";
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import { Protocols } from "../utils/DirectoryUtils";
|
import { Protocols } from "../utils/DirectoryUtils";
|
||||||
import { useLatestResult } from "./useLatestResult";
|
import { useLatestResult } from "./useLatestResult";
|
||||||
|
import { useSettingValue } from "./useSettings";
|
||||||
|
|
||||||
export const ALL_ROOMS = "ALL_ROOMS";
|
export const ALL_ROOMS = "ALL_ROOMS";
|
||||||
const LAST_SERVER_KEY = "mx_last_room_directory_server";
|
const LAST_SERVER_KEY = "mx_last_room_directory_server";
|
||||||
|
@ -38,6 +39,10 @@ export interface IPublicRoomsOpts {
|
||||||
|
|
||||||
let thirdParty: Protocols;
|
let thirdParty: Protocols;
|
||||||
|
|
||||||
|
const NSFW_KEYWORD = "nsfw";
|
||||||
|
const cheapNsfwFilter = (room: IPublicRoomsChunkRoom): boolean =>
|
||||||
|
!room.name?.toLocaleLowerCase().includes(NSFW_KEYWORD) && !room.topic?.toLocaleLowerCase().includes(NSFW_KEYWORD);
|
||||||
|
|
||||||
export const usePublicRoomDirectory = (): {
|
export const usePublicRoomDirectory = (): {
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
@ -58,6 +63,8 @@ export const usePublicRoomDirectory = (): {
|
||||||
|
|
||||||
const [updateQuery, updateResult] = useLatestResult<IRoomDirectoryOptions, IPublicRoomsChunkRoom[]>(setPublicRooms);
|
const [updateQuery, updateResult] = useLatestResult<IRoomDirectoryOptions, IPublicRoomsChunkRoom[]>(setPublicRooms);
|
||||||
|
|
||||||
|
const showNsfwPublicRooms = useSettingValue<boolean>("SpotlightSearch.showNsfwPublicRooms");
|
||||||
|
|
||||||
async function initProtocols(): Promise<void> {
|
async function initProtocols(): Promise<void> {
|
||||||
if (!MatrixClientPeg.get()) {
|
if (!MatrixClientPeg.get()) {
|
||||||
// We may not have a client yet when invoked from welcome page
|
// We may not have a client yet when invoked from welcome page
|
||||||
|
@ -108,7 +115,7 @@ export const usePublicRoomDirectory = (): {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const { chunk } = await MatrixClientPeg.get().publicRooms(opts);
|
const { chunk } = await MatrixClientPeg.get().publicRooms(opts);
|
||||||
updateResult(opts, chunk);
|
updateResult(opts, showNsfwPublicRooms ? chunk : chunk.filter(cheapNsfwFilter));
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Could not fetch public rooms for params", opts, e);
|
console.error("Could not fetch public rooms for params", opts, e);
|
||||||
|
@ -118,7 +125,7 @@ export const usePublicRoomDirectory = (): {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[config, updateQuery, updateResult],
|
[config, updateQuery, updateResult, showNsfwPublicRooms],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -1018,6 +1018,7 @@
|
||||||
"Automatic gain control": "Automatic gain control",
|
"Automatic gain control": "Automatic gain control",
|
||||||
"Echo cancellation": "Echo cancellation",
|
"Echo cancellation": "Echo cancellation",
|
||||||
"Noise suppression": "Noise suppression",
|
"Noise suppression": "Noise suppression",
|
||||||
|
"Show NSFW content": "Show NSFW content",
|
||||||
"Send analytics data": "Send analytics data",
|
"Send analytics data": "Send analytics data",
|
||||||
"Record the client name, version, and url to recognise sessions more easily in session manager": "Record the client name, version, and url to recognise sessions more easily in session manager",
|
"Record the client name, version, and url to recognise sessions more easily in session manager": "Record the client name, version, and url to recognise sessions more easily in session manager",
|
||||||
"Never send encrypted messages to unverified sessions from this session": "Never send encrypted messages to unverified sessions from this session",
|
"Never send encrypted messages to unverified sessions from this session": "Never send encrypted messages to unverified sessions from this session",
|
||||||
|
@ -1619,6 +1620,7 @@
|
||||||
"Code blocks": "Code blocks",
|
"Code blocks": "Code blocks",
|
||||||
"Images, GIFs and videos": "Images, GIFs and videos",
|
"Images, GIFs and videos": "Images, GIFs and videos",
|
||||||
"Timeline": "Timeline",
|
"Timeline": "Timeline",
|
||||||
|
"Room directory": "Room directory",
|
||||||
"Enable hardware acceleration (restart %(appName)s to take effect)": "Enable hardware acceleration (restart %(appName)s to take effect)",
|
"Enable hardware acceleration (restart %(appName)s to take effect)": "Enable hardware acceleration (restart %(appName)s to take effect)",
|
||||||
"Autocomplete delay (ms)": "Autocomplete delay (ms)",
|
"Autocomplete delay (ms)": "Autocomplete delay (ms)",
|
||||||
"Read Marker lifetime (ms)": "Read Marker lifetime (ms)",
|
"Read Marker lifetime (ms)": "Read Marker lifetime (ms)",
|
||||||
|
|
|
@ -743,6 +743,11 @@ export const SETTINGS: { [setting: string]: ISetting } = {
|
||||||
supportedLevels: [SettingLevel.ACCOUNT],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: [], // list of room IDs, most recent first
|
default: [], // list of room IDs, most recent first
|
||||||
},
|
},
|
||||||
|
"SpotlightSearch.showNsfwPublicRooms": {
|
||||||
|
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||||
|
displayName: _td("Show NSFW content"),
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
"room_directory_servers": {
|
"room_directory_servers": {
|
||||||
supportedLevels: [SettingLevel.ACCOUNT],
|
supportedLevels: [SettingLevel.ACCOUNT],
|
||||||
default: [],
|
default: [],
|
||||||
|
|
|
@ -367,4 +367,67 @@ describe("Spotlight Dialog", () => {
|
||||||
expect(screen.queryByText("give feedback")).not.toBeInTheDocument();
|
expect(screen.queryByText("give feedback")).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("nsfw public rooms filter", () => {
|
||||||
|
const nsfwNameRoom: IPublicRoomsChunkRoom = {
|
||||||
|
room_id: "@room1:matrix.org",
|
||||||
|
name: "Room 1 [NSFW]",
|
||||||
|
topic: undefined,
|
||||||
|
world_readable: false,
|
||||||
|
num_joined_members: 1,
|
||||||
|
guest_can_join: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nsfwTopicRoom: IPublicRoomsChunkRoom = {
|
||||||
|
room_id: "@room2:matrix.org",
|
||||||
|
name: "Room 2",
|
||||||
|
topic: "A room with a topic that includes nsfw",
|
||||||
|
world_readable: false,
|
||||||
|
num_joined_members: 1,
|
||||||
|
guest_can_join: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const potatoRoom: IPublicRoomsChunkRoom = {
|
||||||
|
room_id: "@room3:matrix.org",
|
||||||
|
name: "Potato Room 3",
|
||||||
|
topic: "Room where we discuss potatoes",
|
||||||
|
world_readable: false,
|
||||||
|
num_joined_members: 1,
|
||||||
|
guest_can_join: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockedClient = mockClient({ rooms: [nsfwNameRoom, nsfwTopicRoom, potatoRoom], users: [testPerson] });
|
||||||
|
SettingsStore.setValue("SpotlightSearch.showNsfwPublicRooms", null, SettingLevel.DEVICE, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
SettingsStore.setValue("SpotlightSearch.showNsfwPublicRooms", null, SettingLevel.DEVICE, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not display rooms with nsfw keywords in results when showNsfwPublicRooms is falsy", async () => {
|
||||||
|
render(<SpotlightDialog initialFilter={Filter.PublicRooms} onFinished={() => null} />);
|
||||||
|
|
||||||
|
// search is debounced
|
||||||
|
jest.advanceTimersByTime(200);
|
||||||
|
await flushPromisesWithFakeTimers();
|
||||||
|
|
||||||
|
expect(screen.getByText(potatoRoom.name)).toBeInTheDocument();
|
||||||
|
expect(screen.queryByText(nsfwTopicRoom.name)).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByText(nsfwTopicRoom.name)).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("displays rooms with nsfw keywords in results when showNsfwPublicRooms is truthy", async () => {
|
||||||
|
SettingsStore.setValue("SpotlightSearch.showNsfwPublicRooms", null, SettingLevel.DEVICE, true);
|
||||||
|
render(<SpotlightDialog initialFilter={Filter.PublicRooms} onFinished={() => null} />);
|
||||||
|
|
||||||
|
// search is debounced
|
||||||
|
jest.advanceTimersByTime(200);
|
||||||
|
await flushPromisesWithFakeTimers();
|
||||||
|
|
||||||
|
expect(screen.getByText(nsfwTopicRoom.name)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(nsfwNameRoom.name)).toBeInTheDocument();
|
||||||
|
expect(screen.getByText(potatoRoom.name)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue