Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/add_basic_hiding_rooms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: minor
---

Add per Space setting for when to show room icons in sidebar
2 changes: 1 addition & 1 deletion .changeset/fix-various-banner-fixes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
default: fix
default: patch
---

Various small banner changes
39 changes: 37 additions & 2 deletions src/app/components/GlobalKeyboardShortcuts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import { getCanonicalAliasOrRoomId } from '$utils/matrix';
import { announce } from '$utils/announce';
import { roomIdToReplyDraftAtomFamily } from '$state/room/roomInputDrafts';
import type { Room } from '$types/matrix-sdk';
import { useSetting } from '$state/hooks/settings';
import { settingsAtom } from '$state/settings';
import { allRoomsAtom } from '$state/room-list/roomList';
import { useSelectedRoom } from '$hooks/router/useSelectedRoom';

export function GlobalKeyboardShortcuts() {
const navigate = useNavigate();
Expand All @@ -32,6 +36,16 @@ export function GlobalKeyboardShortcuts() {
const roomToUnread = useAtomValue(roomToUnreadAtom);
const unreadIndexRef = useRef(0);

const allRooms = useAtomValue(allRoomsAtom);
const [isHidingRooms, setIsHidingRooms] = useSetting(settingsAtom, 'isHidingRooms');
const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms');
const [hiddenSpaces] = useSetting(settingsAtom, 'hiddenSpaces');
const selectedRoomId = useSelectedRoom();

const filteredRooms = allRooms.filter(
Comment thread
nushea marked this conversation as resolved.
Outdated
(item) => !hiddenRooms.includes(item) && !hiddenSpaces.includes(item)
);

// Derive the current room ID from the URL so we know which room is active.
const roomMatch =
matchPath(HOME_ROOM_PATH, location.pathname) ??
Expand All @@ -54,7 +68,7 @@ export function GlobalKeyboardShortcuts() {

/** Navigate to a room by ID and announce it to screen readers. */
const navigateToRoom = useCallback(
(roomId: string, remaining: number) => {
(roomId: string, remaining?: number) => {
const roomIdOrAliasToNav = getCanonicalAliasOrRoomId(mx, roomId);
const isDirect = mDirects.has(roomId);
if (isDirect) {
Expand All @@ -75,7 +89,9 @@ export function GlobalKeyboardShortcuts() {
}
const roomName = mx.getRoom(roomId)?.name ?? 'Room';
const roomType = isDirect ? 'Direct Message' : 'Group Room';
announce(`${roomName}, ${roomType}. ${remaining} room${remaining === 1 ? '' : 's'} unread.`);
announce(
`${roomName}, ${roomType}.${remaining && `${remaining} room${remaining === 1 ? '' : 's'} unread.`}`
Comment thread
nushea marked this conversation as resolved.
Outdated
);
},
[mx, mDirects, roomToParents, navigate]
);
Expand Down Expand Up @@ -151,9 +167,28 @@ export function GlobalKeyboardShortcuts() {
[currentRoom, replyDraft, setReplyDraft]
);

/** Alt+Shift+H: Toggle Hide Rooms. */
const handleHideRoomsKeyDown = useCallback(
(evt: KeyboardEvent) => {
if (!isKeyHotkey('alt+shift+h', evt)) return;
evt.preventDefault();
announce(`${isHidingRooms ? 'Disabling' : 'Enabling'} hiding rooms.`);
setIsHidingRooms(!isHidingRooms);
if (
selectedRoomId &&
filteredRooms.length > 0 &&
filteredRooms[0] &&
!filteredRooms.includes(selectedRoomId)
)
navigateToRoom(filteredRooms[0]);
},
[setIsHidingRooms, isHidingRooms, navigateToRoom, filteredRooms, selectedRoomId]
);

useKeyDown(window, handleNextUnreadKeyDown);
useKeyDown(window, handleUnreadNavKeyDown);
useKeyDown(window, handleReplyKeyDown);
useKeyDown(window, handleHideRoomsKeyDown);

return null;
}
27 changes: 21 additions & 6 deletions src/app/components/user-profile/UserChips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import { SettingTile } from '$components/setting-tile';
import { RoomAvatar, RoomIcon } from '$components/room-avatar';
import { heroMenuItemStyle } from './heroMenuItemStyle';
import * as css from './styles.css';
import { useSetting } from '$state/hooks/settings';
import { settingsAtom } from '$state/settings';

export function ServerChip({
server,
Expand Down Expand Up @@ -368,6 +370,21 @@ export function MutualRoomsChip({

const [cords, setCords] = useState<RectCords>();

const [isHidingRooms] = useSetting(settingsAtom, 'isHidingRooms');
const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms');
const [hiddenSpaces] = useSetting(settingsAtom, 'hiddenSpaces');
const baseMutualRooms = useMemo(
() =>
(mutualRoomsState.status === AsyncStatus.Success &&
(!isHidingRooms
? mutualRoomsState.data
: mutualRoomsState.data.filter(
(item) => !hiddenRooms.includes(item) && !hiddenSpaces.includes(item)
))) ||
[],
[isHidingRooms, hiddenRooms, hiddenSpaces, mutualRoomsState]
);

const open: MouseEventHandler<HTMLButtonElement> = (evt) => {
setCords(evt.currentTarget.getBoundingClientRect());
};
Expand All @@ -382,7 +399,7 @@ export function MutualRoomsChip({
};

if (mutualRoomsState.status === AsyncStatus.Success) {
const mutualRooms = mutualRoomsState.data
const mutualRooms = baseMutualRooms
.toSorted(factoryRoomIdByAtoZ(mx))
.map(getRoom)
.filter((room) => !!room);
Expand All @@ -399,7 +416,7 @@ export function MutualRoomsChip({
});
}
return data;
}, [mutualRoomsState, getRoom, directs, mx]);
}, [mutualRoomsState, getRoom, directs, mx, baseMutualRooms]);

if (
userId === mx.getSafeUserId() ||
Expand Down Expand Up @@ -541,9 +558,7 @@ export function MutualRoomsChip({
variant={cardColor ? undefined : 'SurfaceVariant'}
radii="Pill"
before={mutualRoomsState.status === AsyncStatus.Loading && <Spinner size="50" />}
disabled={
mutualRoomsState.status !== AsyncStatus.Success || mutualRoomsState.data.length === 0
}
disabled={mutualRoomsState.status !== AsyncStatus.Success || baseMutualRooms.length === 0}
onClick={open}
aria-pressed={!!cords}
className={cardColor ? css.UserHeroChipThemed : css.UserHeroBrightnessHover}
Expand All @@ -554,7 +569,7 @@ export function MutualRoomsChip({
>
<Text size="B300" style={{ color: textColor }}>
{mutualRoomsState.status === AsyncStatus.Success &&
`${mutualRoomsState.data.length} Mutual Rooms`}
`${baseMutualRooms.length} Mutual Rooms`}
{mutualRoomsState.status === AsyncStatus.Loading && 'Mutual Rooms'}
</Text>
</Chip>
Expand Down
44 changes: 39 additions & 5 deletions src/app/features/common-settings/appearance/Appearance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
MenuItem,
PopOut,
type RectCords,
Switch,
} from 'folds';
import { Page, PageContent, PageHeader } from '$components/page';
import { SequenceCard } from '$components/sequence-card';
Expand Down Expand Up @@ -98,11 +99,35 @@ export function SelectShowPerRoomRoomIcon({ roomId }: { roomId: string }) {
);
}

export function SelectHideRoom({ roomId, isSpace }: { roomId: string; isSpace?: boolean }) {
const [hideRoom, setHideRoom] = useSetting(
settingsAtom,
isSpace ? 'hiddenSpaces' : 'hiddenRooms'
);
const isHidden = hideRoom.includes(roomId);

function handleHideRoom() {
const newHideRoomList = !isHidden
? [...hideRoom, roomId]
: hideRoom.filter((roomItem) => roomItem !== roomId);
setHideRoom(newHideRoomList);
}

return (
<SettingTile
title="Add Room to Hide list"
description="Should this room be hidden upon enabling the Hide Rooms option?"
after={<Switch variant="Primary" value={isHidden} onChange={handleHideRoom} />}
/>
);
}

type AppearanceProps = {
requestClose: () => void;
};
export function Appearance({ requestClose }: AppearanceProps) {
const room = useRoom();
const isSpace = room.isSpaceRoom();

return (
<Page>
Expand All @@ -126,16 +151,25 @@ export function Appearance({ requestClose }: AppearanceProps) {
<Box direction="Column" gap="700">
<Box direction="Column" gap="100">
<Text size="L400">Visual Tweaks</Text>
{isSpace && (
<SequenceCard
className={SequenceCardStyle}
variant="SurfaceVariant"
direction="Column"
>
<SettingTile
title="Show Room Icons In Sidebar"
description="When do you want to show the specific room icons in the sidebar within this space?"
after={<SelectShowPerRoomRoomIcon roomId={room.roomId} />}
/>
</SequenceCard>
)}
<SequenceCard
className={SequenceCardStyle}
variant="SurfaceVariant"
direction="Column"
>
<SettingTile
title="Show Room Icons In Sidebar"
description="When do you want to show the specific room icons in the sidebar within this space?"
after={<SelectShowPerRoomRoomIcon roomId={room.roomId} />}
/>
<SelectHideRoom roomId={room.roomId} isSpace={isSpace} />
</SequenceCard>
</Box>
</Box>
Expand Down
10 changes: 10 additions & 0 deletions src/app/features/room-settings/RoomSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useSetting } from '$state/hooks/settings';
import { Permissions } from './permissions';
import { General } from './general';
import { RoomAbbreviations } from './abbreviations/RoomAbbreviations';
import { Appearance } from '$features/common-settings/appearance/Appearance';

type RoomSettingsMenuItem = {
page: RoomSettingsPage;
Expand Down Expand Up @@ -70,6 +71,12 @@ const useRoomSettingsMenuItems = (): RoomSettingsMenuItem[] =>
name: 'Developer Tools',
icon: Icons.Terminal,
},
{
page: RoomSettingsPage.AppearancePage,
name: 'Appearance',
icon: Icons.Alphabet,
activeIcon: Icons.AlphabetUnderline,
},
],
[]
);
Expand Down Expand Up @@ -209,6 +216,9 @@ export function RoomSettings({ initialPage, requestClose }: RoomSettingsProps) {
{activePage === RoomSettingsPage.AbbreviationsPage && (
<RoomAbbreviations requestClose={handlePageRequestClose} />
)}
{activePage === RoomSettingsPage.AppearancePage && (
<Appearance requestClose={handlePageRequestClose} />
)}
</PageRoot>
</SwipeableOverlayWrapper>
);
Expand Down
36 changes: 36 additions & 0 deletions src/app/features/settings/cosmetics/Themes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Chip,
config,
Icon,
IconButton,
Icons,
Input,
Menu,
Expand Down Expand Up @@ -787,6 +788,9 @@ export function Appearance({
const [twitterEmoji, setTwitterEmoji] = useSetting(settingsAtom, 'twitterEmoji');
const [customDMCards, setCustomDMCards] = useSetting(settingsAtom, 'customDMCards');
const [showEasterEggs, setShowEasterEggs] = useSetting(settingsAtom, 'showEasterEggs');
const [isHidingRooms, setIsHidingRooms] = useSetting(settingsAtom, 'isHidingRooms');
const [hiddenSpaces, setHiddenSpaces] = useSetting(settingsAtom, 'hiddenSpaces');
const [hiddenRooms, setHiddenRooms] = useSetting(settingsAtom, 'hiddenRooms');
const [themeBrowserOpen, setThemeBrowserOpen] = useState(false);
const [closeFoldersByDefault, setCloseFoldersByDefault] = useSetting(
settingsAtom,
Expand Down Expand Up @@ -855,6 +859,38 @@ export function Appearance({
/>
</SequenceCard>

<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<SettingTile
title="Hide rooms"
focusId="toggle-hide-rooms"
description="Hide the rooms that are set to be in the hidden list"
after={
<Switch variant="Primary" value={isHidingRooms} onChange={setIsHidingRooms} />
}
/>
</SequenceCard>

<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<SettingTile
title="Clear Hidden Room List"
focusId="clear-hidden-room-list"
description="Clear the list of rooms and spaces that should be hidden"
after={
<IconButton
size="300"
onClick={() => {
setHiddenRooms([]);
setHiddenSpaces([]);
}}
radii="300"
disabled={hiddenRooms?.length === 0 && hiddenSpaces?.length === 0}
>
<Icon src={Icons.Reload} />
</IconButton>
}
/>
</SequenceCard>

<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<SettingTile title="Page Zoom" focusId="page-zoom" after={<PageZoomInput />} />
</SequenceCard>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const SHORTCUT_CATEGORIES: ShortcutCategory[] = [
{ keys: 'Ctrl+U / ⌘+U', description: 'Underline' },
],
},
{
name: 'Other',
shortcuts: [{ keys: 'Alt+Shift+H', description: 'Toggle Hiding Rooms' }],
},
];

function ShortcutRow({ keys, description }: ShortcutEntry) {
Expand Down
2 changes: 2 additions & 0 deletions src/app/features/settings/settingsLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ const settingsLinkFocusIdsBySection: Record<SettingsSectionId, readonly string[]
'saturation',
'selected-language-for-pronouns',
'show-easter-eggs',
'toggle-hide-rooms',
'clear-hidden-room-list',
'show-pronoun-pills',
'show-pronouns-only-in-selected-language',
'subspace-hierarchy-limit',
Expand Down
18 changes: 15 additions & 3 deletions src/app/pages/client/direct/Direct.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,11 @@ export function Direct() {
const roomToUnread = useAtomValue(roomToUnreadAtom);
const navigate = useNavigate();
const [customDMCards] = useSetting(settingsAtom, 'customDMCards');
const [hiddenRooms] = useSetting(settingsAtom, 'hiddenRooms');
const [isHidingRooms] = useSetting(settingsAtom, 'isHidingRooms');

const [roomSidebarWidth, setRoomSidebarWidth] = useSetting(settingsAtom, 'roomSidebarWidth');
const [curWidth, setCurWidth] = useState(roomSidebarWidth);

useEffect(() => {
setCurWidth(roomSidebarWidth);
}, [roomSidebarWidth]);
Expand Down Expand Up @@ -233,7 +235,8 @@ export function Direct() {

const sortedDirects = useMemo(() => {
void activityCounter;
const items = Array.from(directs).toSorted(factoryRoomIdByActivity(mx));
let items = Array.from(directs).toSorted(factoryRoomIdByActivity(mx));
if (isHidingRooms) items = items.filter((rId) => !hiddenRooms.includes(rId));
const hasUnread = (roomId: string) => {
const unread = roomToUnread.get(roomId);
return !!unread && (unread.total > 0 || unread.highlight > 0);
Expand All @@ -242,7 +245,16 @@ export function Direct() {
return items.filter((rId) => hasUnread(rId) || rId === selectedRoomId);
}
return items;
}, [mx, directs, closedCategories, roomToUnread, selectedRoomId, activityCounter]);
}, [
mx,
directs,
closedCategories,
roomToUnread,
selectedRoomId,
activityCounter,
hiddenRooms,
isHidingRooms,
]);

const virtualizer = useVirtualizer({
count: sortedDirects.length,
Expand Down
Loading
Loading