Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions src/app/features/room/RoomTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export function RoomTimeline({
);
const [incomingInlineImagesMaxHeight] = useSetting(settingsAtom, 'incomingInlineImagesMaxHeight');
const [hideMemberInReadOnly] = useSetting(settingsAtom, 'hideMembershipInReadOnly');
const [messageGroupingThreshold] = useSetting(settingsAtom, 'messageGroupingThreshold');

const showUrlPreview = room.hasEncryptionStateEvent() ? encUrlPreview : urlPreview;
const showClientUrlPreview = room.hasEncryptionStateEvent()
Expand Down Expand Up @@ -784,6 +785,7 @@ export function RoomTimeline({
hideNickAvatarEvents,
isReadOnly,
hideMemberInReadOnly,
messageGroupingThreshold,
});

processedEventsRef.current = processedEvents;
Expand Down
2 changes: 2 additions & 0 deletions src/app/features/settings/experimental/Experimental.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Sync } from '../general';
import { SettingsSectionPage } from '../SettingsSectionPage';
import { BandwidthSavingEmojis } from './BandwithSavingEmojis';
import { MSC4268HistoryShare } from './MSC4268HistoryShare';
import { MessageGrouping } from './MessageGrouping';

function PersonaToggle() {
const [showPersonaSetting, setShowPersonaSetting] = useSetting(
Expand Down Expand Up @@ -59,6 +60,7 @@ export function Experimental({ requestBack, requestClose }: Readonly<Experimenta
<br />
<Box direction="Column" gap="700">
<Sync />
<MessageGrouping />
<MSC4268HistoryShare />
<BandwidthSavingEmojis />
<PersonaToggle />
Expand Down
53 changes: 53 additions & 0 deletions src/app/features/settings/experimental/MessageGrouping.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Box, Text, config } from 'folds';
import { settingsAtom } from '$state/settings';
import { useSetting } from '$state/hooks/settings';
import { SequenceCardStyle } from '$features/common-settings/styles.css';
import { SettingTile } from '$components/setting-tile';
import { SequenceCard } from '$components/sequence-card';

const THRESHOLD_OPTIONS: { value: number; label: string }[] = [
{ value: 2, label: '2 min (default)' },
{ value: 5, label: '5 min' },
{ value: 15, label: '15 min (Discord-style)' },
{ value: 30, label: '30 min' },
{ value: 60, label: '60 min' },
];

export function MessageGrouping() {
const [threshold, setThreshold] = useSetting(settingsAtom, 'messageGroupingThreshold');

return (
<Box direction="Column" gap="100">
<Text size="L400">Message Grouping</Text>
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<SettingTile
title="Group consecutive messages"
focusId="message-grouping-threshold"
description="Hide the sender header when the same person sends multiple messages within the chosen time window. Longer windows mean more messages are grouped together."
after={
<select
id="message-grouping-threshold"
value={threshold}
onChange={(e) => setThreshold(Number(e.target.value))}
style={{
background: 'var(--bg-surface)',
color: 'var(--tc-surface-high)',
border: '1px solid var(--bg-surface-border)',
borderRadius: config.radii.R300,
padding: `${config.space.S100} ${config.space.S200}`,
fontSize: config.fontSize.T300,
cursor: 'pointer',
}}
>
{THRESHOLD_OPTIONS.map(({ value, label }) => (
<option key={value} value={value}>
{label}
</option>
))}
</select>
}
/>
</SequenceCard>
</Box>
);
}
11 changes: 10 additions & 1 deletion src/app/hooks/timeline/useProcessedTimeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export interface UseProcessedTimelineOptions {
* where every reply legitimately has `threadRootId` set to the root.
*/
skipThreadFilter?: boolean;
/**
* Minutes of inactivity before a new message from the same sender gets a
* full user header. Defaults to 2 (the original behaviour). Set higher
* (e.g. 15) for Discord-style compact grouping.
*/
messageGroupingThreshold?: number;
}

export interface ProcessedEvent {
Expand Down Expand Up @@ -78,6 +84,7 @@ export function useProcessedTimeline({
isReadOnly,
hideMemberInReadOnly,
skipThreadFilter,
messageGroupingThreshold = 2,
}: UseProcessedTimelineOptions): ProcessedEvent[] {
return useMemo(() => {
let prevEvent: MatrixEvent | undefined;
Expand Down Expand Up @@ -157,7 +164,8 @@ export function useProcessedTimeline({
let collapsed = false;
if (isPrevRendered && !dayDivider && prevEvent !== undefined) {
if (isMessageEvent) {
const withinTimeThreshold = minuteDifference(prevEvent.getTs(), mEvent.getTs()) < 2;
const withinTimeThreshold =
minuteDifference(prevEvent.getTs(), mEvent.getTs()) < messageGroupingThreshold;
const senderMatch = prevEvent.getSender() === eventSender;
const typeMatch =
normalizeMessageType(prevEvent.getType()) === normalizeMessageType(type);
Expand Down Expand Up @@ -211,5 +219,6 @@ export function useProcessedTimeline({
isReadOnly,
hideMemberInReadOnly,
skipThreadFilter,
messageGroupingThreshold,
]);
}
6 changes: 6 additions & 0 deletions src/app/state/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ export interface Settings {
vcmsgSidebarWidth: number;
widgetSidebarWidth: number;

// experimental
messageGroupingThreshold: number;

// furry stuff
renderAnimals: boolean;

Expand Down Expand Up @@ -297,6 +300,9 @@ export const defaultSettings: Settings = {
threadRootHeight: 220,
vcmsgSidebarWidth: 399,
widgetSidebarWidth: 420,

// experimental
messageGroupingThreshold: 2,
// furry stuff
renderAnimals: true,

Expand Down
Loading