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

Commit 168f6df

Browse files
author
Kerry
authored
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
1 parent 03e4b96 commit 168f6df

File tree

5 files changed

+86
-2
lines changed

5 files changed

+86
-2
lines changed

src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
8989
"useOnlyCurrentProfiles",
9090
];
9191

92+
private static ROOM_DIRECTORY_SETTINGS = ["SpotlightSearch.showNsfwPublicRooms"];
93+
9294
private static GENERAL_SETTINGS = [
9395
"promptBeforeInviteUnknownUsers",
9496
// Start automatically after startup (electron-only)
@@ -234,6 +236,11 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
234236
{this.renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)}
235237
</div>
236238

239+
<div className="mx_SettingsTab_section">
240+
<span className="mx_SettingsTab_subheading">{_t("Room directory")}</span>
241+
{this.renderGroup(PreferencesUserSettingsTab.ROOM_DIRECTORY_SETTINGS)}
242+
</div>
243+
237244
<div className="mx_SettingsTab_section">
238245
<span className="mx_SettingsTab_subheading">{_t("General")}</span>
239246
{this.renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)}

src/hooks/usePublicRoomDirectory.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import SdkConfig from "../SdkConfig";
2525
import SettingsStore from "../settings/SettingsStore";
2626
import { Protocols } from "../utils/DirectoryUtils";
2727
import { useLatestResult } from "./useLatestResult";
28+
import { useSettingValue } from "./useSettings";
2829

2930
export const ALL_ROOMS = "ALL_ROOMS";
3031
const LAST_SERVER_KEY = "mx_last_room_directory_server";
@@ -38,6 +39,10 @@ export interface IPublicRoomsOpts {
3839

3940
let thirdParty: Protocols;
4041

42+
const NSFW_KEYWORD = "nsfw";
43+
const cheapNsfwFilter = (room: IPublicRoomsChunkRoom): boolean =>
44+
!room.name?.toLocaleLowerCase().includes(NSFW_KEYWORD) && !room.topic?.toLocaleLowerCase().includes(NSFW_KEYWORD);
45+
4146
export const usePublicRoomDirectory = (): {
4247
ready: boolean;
4348
loading: boolean;
@@ -58,6 +63,8 @@ export const usePublicRoomDirectory = (): {
5863

5964
const [updateQuery, updateResult] = useLatestResult<IRoomDirectoryOptions, IPublicRoomsChunkRoom[]>(setPublicRooms);
6065

66+
const showNsfwPublicRooms = useSettingValue<boolean>("SpotlightSearch.showNsfwPublicRooms");
67+
6168
async function initProtocols(): Promise<void> {
6269
if (!MatrixClientPeg.get()) {
6370
// We may not have a client yet when invoked from welcome page
@@ -108,7 +115,7 @@ export const usePublicRoomDirectory = (): {
108115
try {
109116
setLoading(true);
110117
const { chunk } = await MatrixClientPeg.get().publicRooms(opts);
111-
updateResult(opts, chunk);
118+
updateResult(opts, showNsfwPublicRooms ? chunk : chunk.filter(cheapNsfwFilter));
112119
return true;
113120
} catch (e) {
114121
console.error("Could not fetch public rooms for params", opts, e);
@@ -118,7 +125,7 @@ export const usePublicRoomDirectory = (): {
118125
setLoading(false);
119126
}
120127
},
121-
[config, updateQuery, updateResult],
128+
[config, updateQuery, updateResult, showNsfwPublicRooms],
122129
);
123130

124131
useEffect(() => {

src/i18n/strings/en_EN.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,7 @@
10181018
"Automatic gain control": "Automatic gain control",
10191019
"Echo cancellation": "Echo cancellation",
10201020
"Noise suppression": "Noise suppression",
1021+
"Show NSFW content": "Show NSFW content",
10211022
"Send analytics data": "Send analytics data",
10221023
"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",
10231024
"Never send encrypted messages to unverified sessions from this session": "Never send encrypted messages to unverified sessions from this session",
@@ -1619,6 +1620,7 @@
16191620
"Code blocks": "Code blocks",
16201621
"Images, GIFs and videos": "Images, GIFs and videos",
16211622
"Timeline": "Timeline",
1623+
"Room directory": "Room directory",
16221624
"Enable hardware acceleration (restart %(appName)s to take effect)": "Enable hardware acceleration (restart %(appName)s to take effect)",
16231625
"Autocomplete delay (ms)": "Autocomplete delay (ms)",
16241626
"Read Marker lifetime (ms)": "Read Marker lifetime (ms)",

src/settings/Settings.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,11 @@ export const SETTINGS: { [setting: string]: ISetting } = {
743743
supportedLevels: [SettingLevel.ACCOUNT],
744744
default: [], // list of room IDs, most recent first
745745
},
746+
"SpotlightSearch.showNsfwPublicRooms": {
747+
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
748+
displayName: _td("Show NSFW content"),
749+
default: false,
750+
},
746751
"room_directory_servers": {
747752
supportedLevels: [SettingLevel.ACCOUNT],
748753
default: [],

test/components/views/dialogs/SpotlightDialog-test.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,4 +367,67 @@ describe("Spotlight Dialog", () => {
367367
expect(screen.queryByText("give feedback")).not.toBeInTheDocument();
368368
});
369369
});
370+
371+
describe("nsfw public rooms filter", () => {
372+
const nsfwNameRoom: IPublicRoomsChunkRoom = {
373+
room_id: "@room1:matrix.org",
374+
name: "Room 1 [NSFW]",
375+
topic: undefined,
376+
world_readable: false,
377+
num_joined_members: 1,
378+
guest_can_join: false,
379+
};
380+
381+
const nsfwTopicRoom: IPublicRoomsChunkRoom = {
382+
room_id: "@room2:matrix.org",
383+
name: "Room 2",
384+
topic: "A room with a topic that includes nsfw",
385+
world_readable: false,
386+
num_joined_members: 1,
387+
guest_can_join: false,
388+
};
389+
390+
const potatoRoom: IPublicRoomsChunkRoom = {
391+
room_id: "@room3:matrix.org",
392+
name: "Potato Room 3",
393+
topic: "Room where we discuss potatoes",
394+
world_readable: false,
395+
num_joined_members: 1,
396+
guest_can_join: false,
397+
};
398+
399+
beforeEach(() => {
400+
mockedClient = mockClient({ rooms: [nsfwNameRoom, nsfwTopicRoom, potatoRoom], users: [testPerson] });
401+
SettingsStore.setValue("SpotlightSearch.showNsfwPublicRooms", null, SettingLevel.DEVICE, false);
402+
});
403+
404+
afterAll(() => {
405+
SettingsStore.setValue("SpotlightSearch.showNsfwPublicRooms", null, SettingLevel.DEVICE, false);
406+
});
407+
408+
it("does not display rooms with nsfw keywords in results when showNsfwPublicRooms is falsy", async () => {
409+
render(<SpotlightDialog initialFilter={Filter.PublicRooms} onFinished={() => null} />);
410+
411+
// search is debounced
412+
jest.advanceTimersByTime(200);
413+
await flushPromisesWithFakeTimers();
414+
415+
expect(screen.getByText(potatoRoom.name)).toBeInTheDocument();
416+
expect(screen.queryByText(nsfwTopicRoom.name)).not.toBeInTheDocument();
417+
expect(screen.queryByText(nsfwTopicRoom.name)).not.toBeInTheDocument();
418+
});
419+
420+
it("displays rooms with nsfw keywords in results when showNsfwPublicRooms is truthy", async () => {
421+
SettingsStore.setValue("SpotlightSearch.showNsfwPublicRooms", null, SettingLevel.DEVICE, true);
422+
render(<SpotlightDialog initialFilter={Filter.PublicRooms} onFinished={() => null} />);
423+
424+
// search is debounced
425+
jest.advanceTimersByTime(200);
426+
await flushPromisesWithFakeTimers();
427+
428+
expect(screen.getByText(nsfwTopicRoom.name)).toBeInTheDocument();
429+
expect(screen.getByText(nsfwNameRoom.name)).toBeInTheDocument();
430+
expect(screen.getByText(potatoRoom.name)).toBeInTheDocument();
431+
});
432+
});
370433
});

0 commit comments

Comments
 (0)