mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-03-12 14:10:01 +01:00
Hidden Typing & Read Receipts (#2230)
Some checks are pending
Deploy to Netlify (dev) / Deploy to Netlify (push) Waiting to run
Some checks are pending
Deploy to Netlify (dev) / Deploy to Netlify (push) Waiting to run
* add hide activity toggle * stop sending/receiving typing status * send private read receipt when setting toggle is activated * prevent showing read-receipt when feature toggle in on
This commit is contained in:
parent
5c94471956
commit
b7e5e0db3e
21 changed files with 165 additions and 66 deletions
|
@ -39,6 +39,8 @@ import { getMatrixToRoom } from '../../plugins/matrix-to';
|
||||||
import { getCanonicalAliasOrRoomId, isRoomAlias } from '../../utils/matrix';
|
import { getCanonicalAliasOrRoomId, isRoomAlias } from '../../utils/matrix';
|
||||||
import { getViaServers } from '../../plugins/via-servers';
|
import { getViaServers } from '../../plugins/via-servers';
|
||||||
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
|
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
|
||||||
|
import { useSetting } from '../../state/hooks/settings';
|
||||||
|
import { settingsAtom } from '../../state/settings';
|
||||||
|
|
||||||
type RoomNavItemMenuProps = {
|
type RoomNavItemMenuProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -47,13 +49,14 @@ type RoomNavItemMenuProps = {
|
||||||
const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
|
const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
|
||||||
({ room, requestClose }, ref) => {
|
({ room, requestClose }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
||||||
const powerLevels = usePowerLevels(room);
|
const powerLevels = usePowerLevels(room);
|
||||||
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
||||||
const canInvite = canDoAction('invite', getPowerLevel(mx.getUserId() ?? ''));
|
const canInvite = canDoAction('invite', getPowerLevel(mx.getUserId() ?? ''));
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
markAsRead(mx, room.roomId);
|
markAsRead(mx, room.roomId, hideActivity);
|
||||||
requestClose();
|
requestClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ export function Room() {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
|
||||||
const [isDrawer] = useSetting(settingsAtom, 'isPeopleDrawer');
|
const [isDrawer] = useSetting(settingsAtom, 'isPeopleDrawer');
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const screenSize = useScreenSizeContext();
|
const screenSize = useScreenSizeContext();
|
||||||
const powerLevels = usePowerLevels(room);
|
const powerLevels = usePowerLevels(room);
|
||||||
const members = useRoomMembers(mx, room.roomId);
|
const members = useRoomMembers(mx, room.roomId);
|
||||||
|
@ -29,10 +30,10 @@ export function Room() {
|
||||||
useCallback(
|
useCallback(
|
||||||
(evt) => {
|
(evt) => {
|
||||||
if (isKeyHotkey('escape', evt)) {
|
if (isKeyHotkey('escape', evt)) {
|
||||||
markAsRead(mx, room.roomId);
|
markAsRead(mx, room.roomId, hideActivity);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[mx, room.roomId]
|
[mx, room.roomId, hideActivity]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
|
||||||
const useAuthentication = useMediaAuthentication();
|
const useAuthentication = useMediaAuthentication();
|
||||||
const [enterForNewline] = useSetting(settingsAtom, 'enterForNewline');
|
const [enterForNewline] = useSetting(settingsAtom, 'enterForNewline');
|
||||||
const [isMarkdown] = useSetting(settingsAtom, 'isMarkdown');
|
const [isMarkdown] = useSetting(settingsAtom, 'isMarkdown');
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const commands = useCommands(mx, room);
|
const commands = useCommands(mx, room);
|
||||||
const emojiBtnRef = useRef<HTMLButtonElement>(null);
|
const emojiBtnRef = useRef<HTMLButtonElement>(null);
|
||||||
const roomToParents = useAtomValue(roomToParentsAtom);
|
const roomToParents = useAtomValue(roomToParentsAtom);
|
||||||
|
@ -382,7 +383,9 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTypingStatus(!isEmptyEditor(editor));
|
if (!hideActivity) {
|
||||||
|
sendTypingStatus(!isEmptyEditor(editor));
|
||||||
|
}
|
||||||
|
|
||||||
const prevWordRange = getPrevWorldRange(editor);
|
const prevWordRange = getPrevWorldRange(editor);
|
||||||
const query = prevWordRange
|
const query = prevWordRange
|
||||||
|
@ -390,7 +393,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
|
||||||
: undefined;
|
: undefined;
|
||||||
setAutocompleteQuery(query);
|
setAutocompleteQuery(query);
|
||||||
},
|
},
|
||||||
[editor, sendTypingStatus]
|
[editor, sendTypingStatus, hideActivity]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCloseAutocomplete = useCallback(() => {
|
const handleCloseAutocomplete = useCallback(() => {
|
||||||
|
|
|
@ -424,6 +424,7 @@ const getRoomUnreadInfo = (room: Room, scrollTo = false) => {
|
||||||
export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimelineProps) {
|
export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimelineProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const useAuthentication = useMediaAuthentication();
|
const useAuthentication = useMediaAuthentication();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const [messageLayout] = useSetting(settingsAtom, 'messageLayout');
|
const [messageLayout] = useSetting(settingsAtom, 'messageLayout');
|
||||||
const [messageSpacing] = useSetting(settingsAtom, 'messageSpacing');
|
const [messageSpacing] = useSetting(settingsAtom, 'messageSpacing');
|
||||||
const [hideMembershipEvents] = useSetting(settingsAtom, 'hideMembershipEvents');
|
const [hideMembershipEvents] = useSetting(settingsAtom, 'hideMembershipEvents');
|
||||||
|
@ -589,7 +590,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
// Check if the document is in focus (user is actively viewing the app),
|
// Check if the document is in focus (user is actively viewing the app),
|
||||||
// and either there are no unread messages or the latest message is from the current user.
|
// and either there are no unread messages or the latest message is from the current user.
|
||||||
// If either condition is met, trigger the markAsRead function to send a read receipt.
|
// If either condition is met, trigger the markAsRead function to send a read receipt.
|
||||||
requestAnimationFrame(() => markAsRead(mx, mEvt.getRoomId()!));
|
requestAnimationFrame(() => markAsRead(mx, mEvt.getRoomId()!, hideActivity));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!document.hasFocus() && !unreadInfo) {
|
if (!document.hasFocus() && !unreadInfo) {
|
||||||
|
@ -613,7 +614,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
setUnreadInfo(getRoomUnreadInfo(room));
|
setUnreadInfo(getRoomUnreadInfo(room));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[mx, room, unreadInfo]
|
[mx, room, unreadInfo, hideActivity]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -682,15 +683,15 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
const tryAutoMarkAsRead = useCallback(() => {
|
const tryAutoMarkAsRead = useCallback(() => {
|
||||||
const readUptoEventId = readUptoEventIdRef.current;
|
const readUptoEventId = readUptoEventIdRef.current;
|
||||||
if (!readUptoEventId) {
|
if (!readUptoEventId) {
|
||||||
requestAnimationFrame(() => markAsRead(mx, room.roomId));
|
requestAnimationFrame(() => markAsRead(mx, room.roomId, hideActivity));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const evtTimeline = getEventTimeline(room, readUptoEventId);
|
const evtTimeline = getEventTimeline(room, readUptoEventId);
|
||||||
const latestTimeline = evtTimeline && getFirstLinkedTimeline(evtTimeline, Direction.Forward);
|
const latestTimeline = evtTimeline && getFirstLinkedTimeline(evtTimeline, Direction.Forward);
|
||||||
if (latestTimeline === room.getLiveTimeline()) {
|
if (latestTimeline === room.getLiveTimeline()) {
|
||||||
requestAnimationFrame(() => markAsRead(mx, room.roomId));
|
requestAnimationFrame(() => markAsRead(mx, room.roomId, hideActivity));
|
||||||
}
|
}
|
||||||
}, [mx, room]);
|
}, [mx, room, hideActivity]);
|
||||||
|
|
||||||
const debounceSetAtBottom = useDebounce(
|
const debounceSetAtBottom = useDebounce(
|
||||||
useCallback((entry: IntersectionObserverEntry) => {
|
useCallback((entry: IntersectionObserverEntry) => {
|
||||||
|
@ -872,7 +873,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
markAsRead(mx, room.roomId);
|
markAsRead(mx, room.roomId, hideActivity);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOpenReply: MouseEventHandler = useCallback(
|
const handleOpenReply: MouseEventHandler = useCallback(
|
||||||
|
@ -1047,6 +1048,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
{mEvent.isRedacted() ? (
|
{mEvent.isRedacted() ? (
|
||||||
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
|
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
|
||||||
|
@ -1119,6 +1121,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
<EncryptedContent mEvent={mEvent}>
|
<EncryptedContent mEvent={mEvent}>
|
||||||
{() => {
|
{() => {
|
||||||
|
@ -1215,6 +1218,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
{mEvent.isRedacted() ? (
|
{mEvent.isRedacted() ? (
|
||||||
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
|
<RedactedContent reason={mEvent.getUnsigned().redacted_because?.content.reason} />
|
||||||
|
@ -1256,6 +1260,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
highlight={highlighted}
|
highlight={highlighted}
|
||||||
messageSpacing={messageSpacing}
|
messageSpacing={messageSpacing}
|
||||||
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
<EventContent
|
<EventContent
|
||||||
messageLayout={messageLayout}
|
messageLayout={messageLayout}
|
||||||
|
@ -1291,6 +1296,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
highlight={highlighted}
|
highlight={highlighted}
|
||||||
messageSpacing={messageSpacing}
|
messageSpacing={messageSpacing}
|
||||||
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
<EventContent
|
<EventContent
|
||||||
messageLayout={messageLayout}
|
messageLayout={messageLayout}
|
||||||
|
@ -1327,6 +1333,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
highlight={highlighted}
|
highlight={highlighted}
|
||||||
messageSpacing={messageSpacing}
|
messageSpacing={messageSpacing}
|
||||||
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
<EventContent
|
<EventContent
|
||||||
messageLayout={messageLayout}
|
messageLayout={messageLayout}
|
||||||
|
@ -1363,6 +1370,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
highlight={highlighted}
|
highlight={highlighted}
|
||||||
messageSpacing={messageSpacing}
|
messageSpacing={messageSpacing}
|
||||||
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
<EventContent
|
<EventContent
|
||||||
messageLayout={messageLayout}
|
messageLayout={messageLayout}
|
||||||
|
@ -1401,6 +1409,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
highlight={highlighted}
|
highlight={highlighted}
|
||||||
messageSpacing={messageSpacing}
|
messageSpacing={messageSpacing}
|
||||||
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
<EventContent
|
<EventContent
|
||||||
messageLayout={messageLayout}
|
messageLayout={messageLayout}
|
||||||
|
@ -1444,6 +1453,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
|
||||||
highlight={highlighted}
|
highlight={highlighted}
|
||||||
messageSpacing={messageSpacing}
|
messageSpacing={messageSpacing}
|
||||||
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
canDelete={canRedact || mEvent.getSender() === mx.getUserId()}
|
||||||
|
hideReadReceipts={hideActivity}
|
||||||
>
|
>
|
||||||
<EventContent
|
<EventContent
|
||||||
messageLayout={messageLayout}
|
messageLayout={messageLayout}
|
||||||
|
|
|
@ -13,12 +13,14 @@ import { RoomTimeline } from './RoomTimeline';
|
||||||
import { RoomViewTyping } from './RoomViewTyping';
|
import { RoomViewTyping } from './RoomViewTyping';
|
||||||
import { RoomTombstone } from './RoomTombstone';
|
import { RoomTombstone } from './RoomTombstone';
|
||||||
import { RoomInput } from './RoomInput';
|
import { RoomInput } from './RoomInput';
|
||||||
import { RoomViewFollowing } from './RoomViewFollowing';
|
import { RoomViewFollowing, RoomViewFollowingPlaceholder } from './RoomViewFollowing';
|
||||||
import { Page } from '../../components/page';
|
import { Page } from '../../components/page';
|
||||||
import { RoomViewHeader } from './RoomViewHeader';
|
import { RoomViewHeader } from './RoomViewHeader';
|
||||||
import { useKeyDown } from '../../hooks/useKeyDown';
|
import { useKeyDown } from '../../hooks/useKeyDown';
|
||||||
import { editableActiveElement } from '../../utils/dom';
|
import { editableActiveElement } from '../../utils/dom';
|
||||||
import navigation from '../../../client/state/navigation';
|
import navigation from '../../../client/state/navigation';
|
||||||
|
import { settingsAtom } from '../../state/settings';
|
||||||
|
import { useSetting } from '../../state/hooks/settings';
|
||||||
|
|
||||||
const FN_KEYS_REGEX = /^F\d+$/;
|
const FN_KEYS_REGEX = /^F\d+$/;
|
||||||
const shouldFocusMessageField = (evt: KeyboardEvent): boolean => {
|
const shouldFocusMessageField = (evt: KeyboardEvent): boolean => {
|
||||||
|
@ -57,6 +59,8 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
|
||||||
const roomInputRef = useRef<HTMLDivElement>(null);
|
const roomInputRef = useRef<HTMLDivElement>(null);
|
||||||
const roomViewRef = useRef<HTMLDivElement>(null);
|
const roomViewRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
|
|
||||||
const { roomId } = room;
|
const { roomId } = room;
|
||||||
const editor = useEditor();
|
const editor = useEditor();
|
||||||
|
|
||||||
|
@ -133,7 +137,7 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<RoomViewFollowing room={room} />
|
{hideActivity ? <RoomViewFollowingPlaceholder /> : <RoomViewFollowing room={room} />}
|
||||||
</Box>
|
</Box>
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
|
import { style } from '@vanilla-extract/css';
|
||||||
import { recipe } from '@vanilla-extract/recipes';
|
import { recipe } from '@vanilla-extract/recipes';
|
||||||
import { DefaultReset, color, config, toRem } from 'folds';
|
import { DefaultReset, color, config, toRem } from 'folds';
|
||||||
|
|
||||||
|
export const RoomViewFollowingPlaceholder = style([
|
||||||
|
DefaultReset,
|
||||||
|
{
|
||||||
|
height: toRem(28),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
export const RoomViewFollowing = recipe({
|
export const RoomViewFollowing = recipe({
|
||||||
base: [
|
base: [
|
||||||
DefaultReset,
|
DefaultReset,
|
||||||
|
|
|
@ -24,6 +24,10 @@ import { useRoomEventReaders } from '../../hooks/useRoomEventReaders';
|
||||||
import { EventReaders } from '../../components/event-readers';
|
import { EventReaders } from '../../components/event-readers';
|
||||||
import { stopPropagation } from '../../utils/keyboard';
|
import { stopPropagation } from '../../utils/keyboard';
|
||||||
|
|
||||||
|
export function RoomViewFollowingPlaceholder() {
|
||||||
|
return <div className={css.RoomViewFollowingPlaceholder} />;
|
||||||
|
}
|
||||||
|
|
||||||
export type RoomViewFollowingProps = {
|
export type RoomViewFollowingProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,7 +33,7 @@ import { RoomTopicViewer } from '../../components/room-topic-viewer';
|
||||||
import { StateEvent } from '../../../types/matrix/room';
|
import { StateEvent } from '../../../types/matrix/room';
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
import { useRoom } from '../../hooks/useRoom';
|
import { useRoom } from '../../hooks/useRoom';
|
||||||
import { useSetSetting } from '../../state/hooks/settings';
|
import { useSetSetting, useSetting } from '../../state/hooks/settings';
|
||||||
import { settingsAtom } from '../../state/settings';
|
import { settingsAtom } from '../../state/settings';
|
||||||
import { useSpaceOptionally } from '../../hooks/useSpace';
|
import { useSpaceOptionally } from '../../hooks/useSpace';
|
||||||
import { getHomeSearchPath, getSpaceSearchPath, withSearchParam } from '../../pages/pathUtils';
|
import { getHomeSearchPath, getSpaceSearchPath, withSearchParam } from '../../pages/pathUtils';
|
||||||
|
@ -64,13 +64,14 @@ type RoomMenuProps = {
|
||||||
};
|
};
|
||||||
const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose }, ref) => {
|
const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
||||||
const powerLevels = usePowerLevelsContext();
|
const powerLevels = usePowerLevelsContext();
|
||||||
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
||||||
const canInvite = canDoAction('invite', getPowerLevel(mx.getUserId() ?? ''));
|
const canInvite = canDoAction('invite', getPowerLevel(mx.getUserId() ?? ''));
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
markAsRead(mx, room.roomId);
|
markAsRead(mx, room.roomId, hideActivity);
|
||||||
requestClose();
|
requestClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -671,6 +671,7 @@ export type MessageProps = {
|
||||||
onReactionToggle: (targetEventId: string, key: string, shortcode?: string) => void;
|
onReactionToggle: (targetEventId: string, key: string, shortcode?: string) => void;
|
||||||
reply?: ReactNode;
|
reply?: ReactNode;
|
||||||
reactions?: ReactNode;
|
reactions?: ReactNode;
|
||||||
|
hideReadReceipts?: boolean;
|
||||||
};
|
};
|
||||||
export const Message = as<'div', MessageProps>(
|
export const Message = as<'div', MessageProps>(
|
||||||
(
|
(
|
||||||
|
@ -695,6 +696,7 @@ export const Message = as<'div', MessageProps>(
|
||||||
onEditId,
|
onEditId,
|
||||||
reply,
|
reply,
|
||||||
reactions,
|
reactions,
|
||||||
|
hideReadReceipts,
|
||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
},
|
},
|
||||||
|
@ -992,11 +994,13 @@ export const Message = as<'div', MessageProps>(
|
||||||
</Text>
|
</Text>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
<MessageReadReceiptItem
|
{!hideReadReceipts && (
|
||||||
room={room}
|
<MessageReadReceiptItem
|
||||||
eventId={mEvent.getId() ?? ''}
|
room={room}
|
||||||
onClose={closeMenu}
|
eventId={mEvent.getId() ?? ''}
|
||||||
/>
|
onClose={closeMenu}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<MessageSourceCodeItem room={room} mEvent={mEvent} onClose={closeMenu} />
|
<MessageSourceCodeItem room={room} mEvent={mEvent} onClose={closeMenu} />
|
||||||
<MessageCopyLinkItem room={room} mEvent={mEvent} onClose={closeMenu} />
|
<MessageCopyLinkItem room={room} mEvent={mEvent} onClose={closeMenu} />
|
||||||
{canPinEvent && (
|
{canPinEvent && (
|
||||||
|
@ -1071,9 +1075,23 @@ export type EventProps = {
|
||||||
highlight: boolean;
|
highlight: boolean;
|
||||||
canDelete?: boolean;
|
canDelete?: boolean;
|
||||||
messageSpacing: MessageSpacing;
|
messageSpacing: MessageSpacing;
|
||||||
|
hideReadReceipts?: boolean;
|
||||||
};
|
};
|
||||||
export const Event = as<'div', EventProps>(
|
export const Event = as<'div', EventProps>(
|
||||||
({ className, room, mEvent, highlight, canDelete, messageSpacing, children, ...props }, ref) => {
|
(
|
||||||
|
{
|
||||||
|
className,
|
||||||
|
room,
|
||||||
|
mEvent,
|
||||||
|
highlight,
|
||||||
|
canDelete,
|
||||||
|
messageSpacing,
|
||||||
|
hideReadReceipts,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
},
|
||||||
|
ref
|
||||||
|
) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const [hover, setHover] = useState(false);
|
const [hover, setHover] = useState(false);
|
||||||
const { hoverProps } = useHover({ onHoverChange: setHover });
|
const { hoverProps } = useHover({ onHoverChange: setHover });
|
||||||
|
@ -1138,11 +1156,13 @@ export const Event = as<'div', EventProps>(
|
||||||
>
|
>
|
||||||
<Menu {...props} ref={ref}>
|
<Menu {...props} ref={ref}>
|
||||||
<Box direction="Column" gap="100" className={css.MessageMenuGroup}>
|
<Box direction="Column" gap="100" className={css.MessageMenuGroup}>
|
||||||
<MessageReadReceiptItem
|
{!hideReadReceipts && (
|
||||||
room={room}
|
<MessageReadReceiptItem
|
||||||
eventId={mEvent.getId() ?? ''}
|
room={room}
|
||||||
onClose={closeMenu}
|
eventId={mEvent.getId() ?? ''}
|
||||||
/>
|
onClose={closeMenu}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<MessageSourceCodeItem room={room} mEvent={mEvent} onClose={closeMenu} />
|
<MessageSourceCodeItem room={room} mEvent={mEvent} onClose={closeMenu} />
|
||||||
<MessageCopyLinkItem room={room} mEvent={mEvent} onClose={closeMenu} />
|
<MessageCopyLinkItem room={room} mEvent={mEvent} onClose={closeMenu} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -344,6 +344,7 @@ function Appearance() {
|
||||||
function Editor() {
|
function Editor() {
|
||||||
const [enterForNewline, setEnterForNewline] = useSetting(settingsAtom, 'enterForNewline');
|
const [enterForNewline, setEnterForNewline] = useSetting(settingsAtom, 'enterForNewline');
|
||||||
const [isMarkdown, setIsMarkdown] = useSetting(settingsAtom, 'isMarkdown');
|
const [isMarkdown, setIsMarkdown] = useSetting(settingsAtom, 'isMarkdown');
|
||||||
|
const [hideActivity, setHideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box direction="Column" gap="100">
|
<Box direction="Column" gap="100">
|
||||||
|
@ -363,6 +364,13 @@ function Editor() {
|
||||||
after={<Switch variant="Primary" value={isMarkdown} onChange={setIsMarkdown} />}
|
after={<Switch variant="Primary" value={isMarkdown} onChange={setIsMarkdown} />}
|
||||||
/>
|
/>
|
||||||
</SequenceCard>
|
</SequenceCard>
|
||||||
|
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||||
|
<SettingTile
|
||||||
|
title="Hide Typing & Read Receipts"
|
||||||
|
description="Turn off both typing status and read receipts to keep your activity private."
|
||||||
|
after={<Switch variant="Primary" value={hideActivity} onChange={setHideActivity} />}
|
||||||
|
/>
|
||||||
|
</SequenceCard>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -555,7 +563,13 @@ function Messages() {
|
||||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||||
<SettingTile
|
<SettingTile
|
||||||
title="Disable Media Auto Load"
|
title="Disable Media Auto Load"
|
||||||
after={<Switch variant="Primary" value={!mediaAutoLoad} onChange={(v) => setMediaAutoLoad(!v)} />}
|
after={
|
||||||
|
<Switch
|
||||||
|
variant="Primary"
|
||||||
|
value={!mediaAutoLoad}
|
||||||
|
onChange={(v) => setMediaAutoLoad(!v)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</SequenceCard>
|
</SequenceCard>
|
||||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||||
|
|
|
@ -45,18 +45,21 @@ import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCatego
|
||||||
import { useRoomsUnread } from '../../../state/hooks/unread';
|
import { useRoomsUnread } from '../../../state/hooks/unread';
|
||||||
import { markAsRead } from '../../../../client/action/notifications';
|
import { markAsRead } from '../../../../client/action/notifications';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
|
import { useSetting } from '../../../state/hooks/settings';
|
||||||
|
import { settingsAtom } from '../../../state/settings';
|
||||||
|
|
||||||
type DirectMenuProps = {
|
type DirectMenuProps = {
|
||||||
requestClose: () => void;
|
requestClose: () => void;
|
||||||
};
|
};
|
||||||
const DirectMenu = forwardRef<HTMLDivElement, DirectMenuProps>(({ requestClose }, ref) => {
|
const DirectMenu = forwardRef<HTMLDivElement, DirectMenuProps>(({ requestClose }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const orphanRooms = useDirectRooms();
|
const orphanRooms = useDirectRooms();
|
||||||
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
|
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
if (!unread) return;
|
if (!unread) return;
|
||||||
orphanRooms.forEach((rId) => markAsRead(mx, rId));
|
orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity));
|
||||||
requestClose();
|
requestClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -48,18 +48,21 @@ import { useRoomsUnread } from '../../../state/hooks/unread';
|
||||||
import { markAsRead } from '../../../../client/action/notifications';
|
import { markAsRead } from '../../../../client/action/notifications';
|
||||||
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
|
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
|
import { useSetting } from '../../../state/hooks/settings';
|
||||||
|
import { settingsAtom } from '../../../state/settings';
|
||||||
|
|
||||||
type HomeMenuProps = {
|
type HomeMenuProps = {
|
||||||
requestClose: () => void;
|
requestClose: () => void;
|
||||||
};
|
};
|
||||||
const HomeMenu = forwardRef<HTMLDivElement, HomeMenuProps>(({ requestClose }, ref) => {
|
const HomeMenu = forwardRef<HTMLDivElement, HomeMenuProps>(({ requestClose }, ref) => {
|
||||||
const orphanRooms = useHomeRooms();
|
const orphanRooms = useHomeRooms();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
|
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
if (!unread) return;
|
if (!unread) return;
|
||||||
orphanRooms.forEach((rId) => markAsRead(mx, rId));
|
orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity));
|
||||||
requestClose();
|
requestClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,7 @@ type RoomNotificationsGroupProps = {
|
||||||
notifications: INotification[];
|
notifications: INotification[];
|
||||||
mediaAutoLoad?: boolean;
|
mediaAutoLoad?: boolean;
|
||||||
urlPreview?: boolean;
|
urlPreview?: boolean;
|
||||||
|
hideActivity: boolean;
|
||||||
onOpen: (roomId: string, eventId: string) => void;
|
onOpen: (roomId: string, eventId: string) => void;
|
||||||
};
|
};
|
||||||
function RoomNotificationsGroupComp({
|
function RoomNotificationsGroupComp({
|
||||||
|
@ -189,6 +190,7 @@ function RoomNotificationsGroupComp({
|
||||||
notifications,
|
notifications,
|
||||||
mediaAutoLoad,
|
mediaAutoLoad,
|
||||||
urlPreview,
|
urlPreview,
|
||||||
|
hideActivity,
|
||||||
onOpen,
|
onOpen,
|
||||||
}: RoomNotificationsGroupProps) {
|
}: RoomNotificationsGroupProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
@ -362,7 +364,7 @@ function RoomNotificationsGroupComp({
|
||||||
onOpen(room.roomId, eventId);
|
onOpen(room.roomId, eventId);
|
||||||
};
|
};
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
markAsRead(mx, room.roomId);
|
markAsRead(mx, room.roomId, hideActivity);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -496,6 +498,7 @@ const DEFAULT_REFRESH_MS = 7000;
|
||||||
|
|
||||||
export function Notifications() {
|
export function Notifications() {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
|
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
|
||||||
const [urlPreview] = useSetting(settingsAtom, 'urlPreview');
|
const [urlPreview] = useSetting(settingsAtom, 'urlPreview');
|
||||||
const screenSize = useScreenSizeContext();
|
const screenSize = useScreenSizeContext();
|
||||||
|
@ -656,6 +659,7 @@ export function Notifications() {
|
||||||
notifications={group.notifications}
|
notifications={group.notifications}
|
||||||
mediaAutoLoad={mediaAutoLoad}
|
mediaAutoLoad={mediaAutoLoad}
|
||||||
urlPreview={urlPreview}
|
urlPreview={urlPreview}
|
||||||
|
hideActivity={hideActivity}
|
||||||
onOpen={navigateRoom}
|
onOpen={navigateRoom}
|
||||||
/>
|
/>
|
||||||
</VirtualTile>
|
</VirtualTile>
|
||||||
|
|
|
@ -23,18 +23,21 @@ import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
|
||||||
import { useDirectRooms } from '../direct/useDirectRooms';
|
import { useDirectRooms } from '../direct/useDirectRooms';
|
||||||
import { markAsRead } from '../../../../client/action/notifications';
|
import { markAsRead } from '../../../../client/action/notifications';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
|
import { settingsAtom } from '../../../state/settings';
|
||||||
|
import { useSetting } from '../../../state/hooks/settings';
|
||||||
|
|
||||||
type DirectMenuProps = {
|
type DirectMenuProps = {
|
||||||
requestClose: () => void;
|
requestClose: () => void;
|
||||||
};
|
};
|
||||||
const DirectMenu = forwardRef<HTMLDivElement, DirectMenuProps>(({ requestClose }, ref) => {
|
const DirectMenu = forwardRef<HTMLDivElement, DirectMenuProps>(({ requestClose }, ref) => {
|
||||||
const orphanRooms = useDirectRooms();
|
const orphanRooms = useDirectRooms();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
|
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
if (!unread) return;
|
if (!unread) return;
|
||||||
orphanRooms.forEach((rId) => markAsRead(mx, rId));
|
orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity));
|
||||||
requestClose();
|
requestClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,21 @@ import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
|
||||||
import { useHomeRooms } from '../home/useHomeRooms';
|
import { useHomeRooms } from '../home/useHomeRooms';
|
||||||
import { markAsRead } from '../../../../client/action/notifications';
|
import { markAsRead } from '../../../../client/action/notifications';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
|
import { useSetting } from '../../../state/hooks/settings';
|
||||||
|
import { settingsAtom } from '../../../state/settings';
|
||||||
|
|
||||||
type HomeMenuProps = {
|
type HomeMenuProps = {
|
||||||
requestClose: () => void;
|
requestClose: () => void;
|
||||||
};
|
};
|
||||||
const HomeMenu = forwardRef<HTMLDivElement, HomeMenuProps>(({ requestClose }, ref) => {
|
const HomeMenu = forwardRef<HTMLDivElement, HomeMenuProps>(({ requestClose }, ref) => {
|
||||||
const orphanRooms = useHomeRooms();
|
const orphanRooms = useHomeRooms();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
|
const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom);
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
if (!unread) return;
|
if (!unread) return;
|
||||||
orphanRooms.forEach((rId) => markAsRead(mx, rId));
|
orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity));
|
||||||
requestClose();
|
requestClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,8 @@ import { getMatrixToRoom } from '../../../plugins/matrix-to';
|
||||||
import { getViaServers } from '../../../plugins/via-servers';
|
import { getViaServers } from '../../../plugins/via-servers';
|
||||||
import { getRoomAvatarUrl } from '../../../utils/room';
|
import { getRoomAvatarUrl } from '../../../utils/room';
|
||||||
import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication';
|
import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication';
|
||||||
|
import { useSetting } from '../../../state/hooks/settings';
|
||||||
|
import { settingsAtom } from '../../../state/settings';
|
||||||
|
|
||||||
type SpaceMenuProps = {
|
type SpaceMenuProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -97,6 +99,7 @@ type SpaceMenuProps = {
|
||||||
const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
|
const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
|
||||||
({ room, requestClose, onUnpin }, ref) => {
|
({ room, requestClose, onUnpin }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const roomToParents = useAtomValue(roomToParentsAtom);
|
const roomToParents = useAtomValue(roomToParentsAtom);
|
||||||
const powerLevels = usePowerLevels(room);
|
const powerLevels = usePowerLevels(room);
|
||||||
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
||||||
|
@ -110,7 +113,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
|
||||||
const unread = useRoomsUnread(allChild, roomToUnreadAtom);
|
const unread = useRoomsUnread(allChild, roomToUnreadAtom);
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
allChild.forEach((childRoomId) => markAsRead(mx, childRoomId));
|
allChild.forEach((childRoomId) => markAsRead(mx, childRoomId, hideActivity));
|
||||||
requestClose();
|
requestClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,18 +230,18 @@ const useDraggableItem = (
|
||||||
return !target
|
return !target
|
||||||
? undefined
|
? undefined
|
||||||
: draggable({
|
: draggable({
|
||||||
element: target,
|
element: target,
|
||||||
dragHandle,
|
dragHandle,
|
||||||
getInitialData: () => ({ item }),
|
getInitialData: () => ({ item }),
|
||||||
onDragStart: () => {
|
onDragStart: () => {
|
||||||
setDragging(true);
|
setDragging(true);
|
||||||
onDragging?.(item);
|
onDragging?.(item);
|
||||||
},
|
},
|
||||||
onDrop: () => {
|
onDrop: () => {
|
||||||
setDragging(false);
|
setDragging(false);
|
||||||
onDragging?.(undefined);
|
onDragging?.(undefined);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [targetRef, dragHandleRef, item, onDragging]);
|
}, [targetRef, dragHandleRef, item, onDragging]);
|
||||||
|
|
||||||
return dragging;
|
return dragging;
|
||||||
|
@ -388,9 +391,9 @@ function SpaceTab({
|
||||||
() =>
|
() =>
|
||||||
folder
|
folder
|
||||||
? {
|
? {
|
||||||
folder,
|
folder,
|
||||||
spaceId: space.roomId,
|
spaceId: space.roomId,
|
||||||
}
|
}
|
||||||
: space.roomId,
|
: space.roomId,
|
||||||
[folder, space]
|
[folder, space]
|
||||||
);
|
);
|
||||||
|
|
|
@ -69,6 +69,8 @@ import { StateEvent } from '../../../../types/matrix/room';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
import { getMatrixToRoom } from '../../../plugins/matrix-to';
|
import { getMatrixToRoom } from '../../../plugins/matrix-to';
|
||||||
import { getViaServers } from '../../../plugins/via-servers';
|
import { getViaServers } from '../../../plugins/via-servers';
|
||||||
|
import { useSetting } from '../../../state/hooks/settings';
|
||||||
|
import { settingsAtom } from '../../../state/settings';
|
||||||
|
|
||||||
type SpaceMenuProps = {
|
type SpaceMenuProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -76,6 +78,7 @@ type SpaceMenuProps = {
|
||||||
};
|
};
|
||||||
const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClose }, ref) => {
|
const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClose }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
const roomToParents = useAtomValue(roomToParentsAtom);
|
const roomToParents = useAtomValue(roomToParentsAtom);
|
||||||
const powerLevels = usePowerLevels(room);
|
const powerLevels = usePowerLevels(room);
|
||||||
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
||||||
|
@ -89,7 +92,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
|
||||||
const unread = useRoomsUnread(allChild, roomToUnreadAtom);
|
const unread = useRoomsUnread(allChild, roomToUnreadAtom);
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
const handleMarkAsRead = () => {
|
||||||
allChild.forEach((childRoomId) => markAsRead(mx, childRoomId));
|
allChild.forEach((childRoomId) => markAsRead(mx, childRoomId, hideActivity));
|
||||||
requestClose();
|
requestClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -228,20 +228,18 @@ export const useBindRoomToUnreadAtom = (
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleReceipt = (mEvent: MatrixEvent, room: Room) => {
|
const handleReceipt = (mEvent: MatrixEvent, room: Room) => {
|
||||||
if (mEvent.getType() === 'm.receipt') {
|
const myUserId = mx.getUserId();
|
||||||
const myUserId = mx.getUserId();
|
if (!myUserId) return;
|
||||||
if (!myUserId) return;
|
if (room.isSpaceRoom()) return;
|
||||||
if (room.isSpaceRoom()) return;
|
const content = mEvent.getContent<ReceiptContent>();
|
||||||
const content = mEvent.getContent<ReceiptContent>();
|
|
||||||
|
|
||||||
const isMyReceipt = Object.keys(content).find((eventId) =>
|
const isMyReceipt = Object.keys(content).find((eventId) =>
|
||||||
(Object.keys(content[eventId]) as ReceiptType[]).find(
|
(Object.keys(content[eventId]) as ReceiptType[]).find(
|
||||||
(receiptType) => content[eventId][receiptType][myUserId]
|
(receiptType) => content[eventId][receiptType][myUserId]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (isMyReceipt) {
|
if (isMyReceipt) {
|
||||||
setUnreadAtom({ type: 'DELETE', roomId: room.roomId });
|
setUnreadAtom({ type: 'DELETE', roomId: room.roomId });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mx.on(RoomEvent.Receipt, handleReceipt);
|
mx.on(RoomEvent.Receipt, handleReceipt);
|
||||||
|
|
|
@ -17,6 +17,7 @@ export interface Settings {
|
||||||
editorToolbar: boolean;
|
editorToolbar: boolean;
|
||||||
twitterEmoji: boolean;
|
twitterEmoji: boolean;
|
||||||
pageZoom: number;
|
pageZoom: number;
|
||||||
|
hideActivity: boolean;
|
||||||
|
|
||||||
isPeopleDrawer: boolean;
|
isPeopleDrawer: boolean;
|
||||||
memberSortFilterIndex: number;
|
memberSortFilterIndex: number;
|
||||||
|
@ -45,6 +46,7 @@ const defaultSettings: Settings = {
|
||||||
editorToolbar: false,
|
editorToolbar: false,
|
||||||
twitterEmoji: false,
|
twitterEmoji: false,
|
||||||
pageZoom: 100,
|
pageZoom: 100,
|
||||||
|
hideActivity: false,
|
||||||
|
|
||||||
isPeopleDrawer: true,
|
isPeopleDrawer: true,
|
||||||
memberSortFilterIndex: 0,
|
memberSortFilterIndex: 0,
|
||||||
|
|
|
@ -2,6 +2,8 @@ import produce from 'immer';
|
||||||
import { atom, useSetAtom } from 'jotai';
|
import { atom, useSetAtom } from 'jotai';
|
||||||
import { MatrixClient, RoomMemberEvent, RoomMemberEventHandlerMap } from 'matrix-js-sdk';
|
import { MatrixClient, RoomMemberEvent, RoomMemberEventHandlerMap } from 'matrix-js-sdk';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import { useSetting } from './hooks/settings';
|
||||||
|
import { settingsAtom } from './settings';
|
||||||
|
|
||||||
export const TYPING_TIMEOUT_MS = 5000; // 5 seconds
|
export const TYPING_TIMEOUT_MS = 5000; // 5 seconds
|
||||||
|
|
||||||
|
@ -127,12 +129,16 @@ export const useBindRoomIdToTypingMembersAtom = (
|
||||||
typingMembersAtom: typeof roomIdToTypingMembersAtom
|
typingMembersAtom: typeof roomIdToTypingMembersAtom
|
||||||
) => {
|
) => {
|
||||||
const setTypingMembers = useSetAtom(typingMembersAtom);
|
const setTypingMembers = useSetAtom(typingMembersAtom);
|
||||||
|
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleTypingEvent: RoomMemberEventHandlerMap[RoomMemberEvent.Typing] = (
|
const handleTypingEvent: RoomMemberEventHandlerMap[RoomMemberEvent.Typing] = (
|
||||||
event,
|
event,
|
||||||
member
|
member
|
||||||
) => {
|
) => {
|
||||||
|
if (hideActivity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setTypingMembers({
|
setTypingMembers({
|
||||||
type: member.typing ? 'PUT' : 'DELETE',
|
type: member.typing ? 'PUT' : 'DELETE',
|
||||||
roomId: member.roomId,
|
roomId: member.roomId,
|
||||||
|
@ -145,5 +151,5 @@ export const useBindRoomIdToTypingMembersAtom = (
|
||||||
return () => {
|
return () => {
|
||||||
mx.removeListener(RoomMemberEvent.Typing, handleTypingEvent);
|
mx.removeListener(RoomMemberEvent.Typing, handleTypingEvent);
|
||||||
};
|
};
|
||||||
}, [mx, setTypingMembers]);
|
}, [mx, setTypingMembers, hideActivity]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { MatrixClient } from "matrix-js-sdk";
|
import { MatrixClient, ReceiptType } from 'matrix-js-sdk';
|
||||||
|
|
||||||
export async function markAsRead(mx: MatrixClient, roomId: string) {
|
export async function markAsRead(mx: MatrixClient, roomId: string, privateReceipt: boolean) {
|
||||||
const room = mx.getRoom(roomId);
|
const room = mx.getRoom(roomId);
|
||||||
if (!room) return;
|
if (!room) return;
|
||||||
|
|
||||||
|
@ -19,5 +19,8 @@ export async function markAsRead(mx: MatrixClient, roomId: string) {
|
||||||
const latestEvent = getLatestValidEvent();
|
const latestEvent = getLatestValidEvent();
|
||||||
if (latestEvent === null) return;
|
if (latestEvent === null) return;
|
||||||
|
|
||||||
await mx.sendReadReceipt(latestEvent);
|
await mx.sendReadReceipt(
|
||||||
|
latestEvent,
|
||||||
|
privateReceipt ? ReceiptType.ReadPrivate : ReceiptType.Read
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue