Skip to content

Commit

Permalink
Add safe search filter for NSFW rooms (#208)
Browse files Browse the repository at this point in the history
Fix #89
  • Loading branch information
MadLittleMods authored May 3, 2023
1 parent 858c9dd commit b70439e
Show file tree
Hide file tree
Showing 13 changed files with 547 additions and 141 deletions.
85 changes: 67 additions & 18 deletions client/css/room-directory.css
Original file line number Diff line number Diff line change
Expand Up @@ -237,24 +237,22 @@
color: #abb5be;
}

.RoomDirectoryView_roomList {
display: grid;
gap: 20px;
.RoomDirectoryView_mainContentSection {
width: 100%;
max-width: 1180px;
padding-left: 20px;
padding-right: 20px;
margin-top: 20px;
margin-top: 15px;
margin-bottom: 0;
}

.RoomDirectoryView_roomList {
display: grid;
gap: 20px;
}

.RoomDirectoryView_roomListError {
display: block;
width: 100%;
max-width: 1180px;
padding-left: 20px;
padding-right: 20px;
margin-top: 20px;

line-height: 1.5;
}
Expand All @@ -269,17 +267,14 @@
}

@media (min-width: 750px) {
.RoomDirectoryView_roomList {
grid-template-columns: repeat(2, 1fr);
margin-top: 40px;
.RoomDirectoryView_mainContentSection {
margin-top: 30px;
padding-left: 40px;
padding-right: 40px;
}

.RoomDirectoryView_roomListError {
margin-top: 40px;
padding-left: 40px;
padding-right: 40px;
.RoomDirectoryView_roomList {
grid-template-columns: repeat(2, 1fr);
}
}

Expand All @@ -289,6 +284,40 @@
}
}

.RoomDirectoryView_safeSearchToggleSection {
display: flex;
justify-content: flex-end;
}

.RoomDirectoryView_safeSearchToggle {
display: flex;
align-items: center;
}

.RoomDirectoryView_safeSearchToggleLabel {
padding-left: 0.3em;
}

.RoomDirectoryView_safeSearchToggleCheckbox {
appearance: none;

position: relative;
width: 20px;
height: 10px;

background-color: #ffffff;
border: 2px solid rgba(200, 200, 200, 1);
box-shadow: inset -10px 0px 0px 0px rgba(200, 200, 200, 1);
border-radius: 10px;

transition: all 0.2s ease;
}

.RoomDirectoryView_safeSearchToggleCheckbox:checked {
border: 2px solid #2774c2;
box-shadow: inset 10px 0px 0px 0px #2774c2;
}

.RoomCardView {
overflow: hidden;
display: flex;
Expand All @@ -301,6 +330,10 @@
border-radius: 8px;
}

.RoomCardView.blockedBySafeSearch {
background-color: #d0d9e1;
}

.RoomCardView_header {
display: flex;
align-items: top;
Expand Down Expand Up @@ -350,6 +383,14 @@
text-overflow: ellipsis;
}

.RoomCardView_blockedBySafeSearchTopic {
margin-top: 8px;
margin-bottom: 8px;

line-height: 1.2em;
font-style: italic;
}

.RoomCardView_footer {
display: flex;
/**
Expand Down Expand Up @@ -398,14 +439,22 @@
cursor: pointer;
}

.RoomCardView_viewButton[disabled] {
border-color: #2774c299;

color: #2774c299;

cursor: auto;
}

@media (max-width: 750px) {
.RoomCardView_viewButton {
padding: 8px 32px;
}
}

.RoomCardView_viewButtonWrapperLink:hover > .RoomCardView_viewButton,
.RoomCardView_viewButtonWrapperLink:focus > .RoomCardView_viewButton {
.RoomCardView_viewButtonWrapperLink:hover > .RoomCardView_viewButton:not([disabled]),
.RoomCardView_viewButtonWrapperLink:focus > .RoomCardView_viewButton:not([disabled]) {
background-color: #2774c2;
color: #ffffff;
}
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"dompurify": "^2.3.9",
"escape-string-regexp": "^4.0.0",
"express": "^4.17.2",
"hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.26.0-scratch",
"hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.27.0-scratch",
"json5": "^2.2.1",
"linkedom": "^0.14.17",
"matrix-public-archive-shared": "file:./shared/",
Expand Down
29 changes: 29 additions & 0 deletions shared/lib/local-storage-keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

const assert = require('./assert');

const LOCAL_STORAGE_KEYS = {
addedHomeservers: 'addedHomeservers',
safeSearchEnabled: 'safeSearchEnabled',
debugActiveDateIntersectionObserver: 'debugActiveDateIntersectionObserver',
};

// Just make sure they match for sanity. All we really care about is that they are
// unique amongst each other.
Object.keys(LOCAL_STORAGE_KEYS).every((key) => {
const value = LOCAL_STORAGE_KEYS[key];
const doesKeyMatchValue = key === value;
assert(
doesKeyMatchValue,
`LOCAL_STORAGE_KEYS should have keys that are the same as their values for sanity but saw ${key}=${value}.`
);
});

// Make sure all of the keys/values are unique
assert(
new Set(Object.values(LOCAL_STORAGE_KEYS)).length !== Object.values(LOCAL_STORAGE_KEYS).length,
'Duplicate values in LOCAL_STORAGE_KEYS. They should be unique otherwise ' +
'there will be collisions and LocalStorage will be overwritten.'
);

module.exports = LOCAL_STORAGE_KEYS;
1 change: 1 addition & 0 deletions shared/room-directory-vm-render-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ async function mountHydrogen() {
urlRouter: urlRouter,
history: archiveHistory,
// Our options
basePath: config.basePath,
homeserverUrl: config.matrixServerUrl,
homeserverName: config.matrixServerName,
matrixPublicArchiveURLCreator,
Expand Down
2 changes: 1 addition & 1 deletion shared/viewmodels/AvatarViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class AvatarViewModel extends ViewModel {

const { homeserverUrlToPullMediaFrom, avatarUrl, avatarTitle, avatarLetterString, entityId } =
options;
assert(homeserverUrlToPullMediaFrom);
assert(!avatarUrl || homeserverUrlToPullMediaFrom);
assert(avatarTitle);
assert(avatarLetterString);
assert(entityId);
Expand Down
11 changes: 6 additions & 5 deletions shared/viewmodels/DeveloperOptionsContentViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

const { ViewModel } = require('hydrogen-view-sdk');

const DEBUG_ACTIVE_DATE_INTERSECTION_OBSERVER_LOCAL_STORAGE_KEY =
'debugActiveDateIntersectionObserver';
const LOCAL_STORAGE_KEYS = require('matrix-public-archive-shared/lib/local-storage-keys');

class DeveloperOptionsContentViewModel extends ViewModel {
constructor(options) {
Expand All @@ -17,11 +16,13 @@ class DeveloperOptionsContentViewModel extends ViewModel {
loadValuesFromPersistence() {
if (window.localStorage) {
this._debugActiveDateIntersectionObserver = JSON.parse(
window.localStorage.getItem(DEBUG_ACTIVE_DATE_INTERSECTION_OBSERVER_LOCAL_STORAGE_KEY)
window.localStorage.getItem(LOCAL_STORAGE_KEYS.debugActiveDateIntersectionObserver)
);
this.emitChange('debugActiveDateIntersectionObserver');
} else {
console.warn(`Skipping read from LocalStorage since LocalStorage not available`);
console.warn(
`Skipping \`${LOCAL_STORAGE_KEYS.debugActiveDateIntersectionObserver}\` read from LocalStorage since LocalStorage is not available`
);
}
}

Expand All @@ -32,7 +33,7 @@ class DeveloperOptionsContentViewModel extends ViewModel {
toggleDebugActiveDateIntersectionObserver(checkedValue) {
this._debugActiveDateIntersectionObserver = checkedValue;
window.localStorage.setItem(
DEBUG_ACTIVE_DATE_INTERSECTION_OBSERVER_LOCAL_STORAGE_KEY,
LOCAL_STORAGE_KEYS.debugActiveDateIntersectionObserver,
this._debugActiveDateIntersectionObserver
);
this.emitChange('debugActiveDateIntersectionObserver');
Expand Down
82 changes: 82 additions & 0 deletions shared/viewmodels/RoomCardViewModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use strict';

const { ViewModel } = require('hydrogen-view-sdk');

const assert = require('matrix-public-archive-shared/lib/assert');
const MatrixPublicArchiveURLCreator = require('matrix-public-archive-shared/lib/url-creator');

class RoomCardViewModel extends ViewModel {
constructor(options) {
super(options);
const { room, basePath, homeserverUrlToPullMediaFrom, viaServers } = options;
assert(room);
assert(basePath);
assert(homeserverUrlToPullMediaFrom);
assert(viaServers);

this._matrixPublicArchiveURLCreator = new MatrixPublicArchiveURLCreator(basePath);

this._roomId = room.room_id;
this._canonicalAlias = room.canonical_alias;
this._name = room.name;
this._mxcAvatarUrl = room.avatar_url;
this._homeserverUrlToPullMediaFrom = homeserverUrlToPullMediaFrom;
this._numJoinedMembers = room.num_joined_members;
this._topic = room.topic;

this._viaServers = viaServers;

this._blockedBySafeSearch = false;
}

get roomId() {
return this._roomId;
}

get canonicalAlias() {
return this._canonicalAlias;
}

get name() {
return this._name;
}

get mxcAvatarUrl() {
return this._mxcAvatarUrl;
}

get homeserverUrlToPullMediaFrom() {
return this._homeserverUrlToPullMediaFrom;
}

get numJoinedMembers() {
return this._numJoinedMembers;
}

get topic() {
return this._topic;
}

get archiveRoomUrl() {
return this._matrixPublicArchiveURLCreator.archiveUrlForRoom(
this._canonicalAlias || this._roomId,
{
// Only include via servers when we have to fallback to the room ID
viaServers: this._canonicalAlias ? undefined : this._viaServers,
}
);
}

get blockedBySafeSearch() {
return this._blockedBySafeSearch;
}

setBlockedBySafeSearch(blockedBySafeSearch) {
if (blockedBySafeSearch !== this._blockedBySafeSearch) {
this._blockedBySafeSearch = blockedBySafeSearch;
this.emitChange('blockedBySafeSearch');
}
}
}

module.exports = RoomCardViewModel;
Loading

0 comments on commit b70439e

Please sign in to comment.