Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9bc92ef
reverse message render order (bottom -> top instead of top -> bottom)
7w1 Mar 11, 2026
921b0d6
fix context menu not being hoverable
7w1 Mar 11, 2026
0714534
stabilize pagination hopefully
7w1 Mar 11, 2026
2528f83
fix a possible memory leak :p
7w1 Mar 11, 2026
6fc1829
make the listeners listen better by not destroying themselves every f…
7w1 Mar 11, 2026
9810a99
plz work mobile scroll thanks
7w1 Mar 11, 2026
6fc2aec
plz work attempt 2
7w1 Mar 11, 2026
9beff5d
plz work part 3 electric boogalee
7w1 Mar 11, 2026
b4bff80
fix thingy
7w1 Mar 11, 2026
88e9efa
fix hover and maybe scroll idk
7w1 Mar 11, 2026
fecfe3d
delete the manual math and hope it works?
7w1 Mar 11, 2026
fc303e2
Merge branch 'dev' into timeline-rewrite
7w1 Mar 13, 2026
74ece9e
merge
7w1 Mar 18, 2026
1ef961e
begin pulling apart the giant timeline file smh
7w1 Mar 18, 2026
a9704a0
Merge branch 'dev' into timeline-rewrite
7w1 Mar 18, 2026
13bd62a
make better yes
7w1 Mar 18, 2026
b396cce
remove the comments >:D and merge the updated roomtimeline to have th…
7w1 Mar 18, 2026
21dc9c5
pull out scroll logic
7w1 Mar 18, 2026
6d60ff7
initial big refractor, probably broke stuff and forgot stuff but oh w…
7w1 Mar 18, 2026
9efbce6
make linter happy
7w1 Mar 18, 2026
e41c45a
stop the failed to load messages 24/7
7w1 Mar 19, 2026
db17610
Redo ALLLLLL the scrollllllllllll
7w1 Mar 19, 2026
475011d
happy linter happy 7
7w1 Mar 19, 2026
0b94854
mobile scroll fixes attempttttt
7w1 Mar 19, 2026
b0f5fa0
hopefully fix typing indicator weirdness
7w1 Mar 19, 2026
3146411
unbreak the typing indicator?
7w1 Mar 19, 2026
0c53afc
update paginator? what am i doing again?
7w1 Mar 19, 2026
4a09b16
if i delete more itll work right
7w1 Mar 19, 2026
bfff0e3
i.... did things?
7w1 Mar 19, 2026
6a47453
Update package.json
7w1 Mar 19, 2026
6d7b911
Update pnpm-lock.yaml
7w1 Mar 19, 2026
1ffc741
mmmm kinda works
7w1 Mar 19, 2026
0b99933
fixed collapsing broke jumping shrug
7w1 Mar 19, 2026
afb71b7
almost flawless
7w1 Mar 19, 2026
56a607b
scroll hover thing
7w1 Mar 19, 2026
33b5393
read only room fixes
7w1 Mar 20, 2026
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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"slate-history": "^0.113.1",
"slate-react": "^0.123.0",
"ua-parser-js": "^1.0.41",
"virtua": "^0.48.8",
"workbox-precaching": "^7.4.0"
},
"devDependencies": {
Expand Down Expand Up @@ -137,4 +138,4 @@
"vitest": "^4.1.0",
"wrangler": "^4.70.0"
}
}
}
28 changes: 28 additions & 0 deletions pnpm-lock.yaml

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

79 changes: 79 additions & 0 deletions src/app/components/PaginationPlaceholders.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Box, Chip, Spinner, Text, color, config } from 'folds';
import { MessageBase, CompactPlaceholder, DefaultPlaceholder } from '$components/message';

export type PaginationStatus = 'idle' | 'loading' | 'error';

export interface PaginationLoaderProps {
status: PaginationStatus;
direction: 'backward' | 'forward';
isCompact: boolean;
isEmpty: boolean;
onRetry: () => void;
observerRef?: (node: HTMLElement | null) => void;
}

export function PaginationLoader({
status,
direction,
isCompact,
isEmpty,
onRetry,
observerRef,
}: PaginationLoaderProps) {
if (status === 'error') {
return (
<Box
justifyContent="Center"
alignItems="Center"
gap="200"
style={{ padding: config.space.S300 }}
>
<Text style={{ color: color.Critical.Main }} size="T300">
{direction === 'backward' ? 'Failed to load history.' : 'Failed to load messages.'}
</Text>
<Chip variant="SurfaceVariant" radii="Pill" outlined onClick={onRetry}>
<Text size="B300">Retry</Text>
</Chip>
</Box>
);
}

if (isEmpty) {
const count = isCompact ? 5 : 3;
const anchorIndex = direction === 'backward' ? count - 1 : 0;
const skeletonKeys = Array.from({ length: count }, (_, idx) => `skeleton-${direction}-${idx}`);

return (
<>
{skeletonKeys.map((skeletonKey, i) => {
const attachRef = i === anchorIndex ? observerRef : undefined;
return (
<MessageBase key={skeletonKey} ref={attachRef}>
{isCompact ? <CompactPlaceholder /> : <DefaultPlaceholder />}
</MessageBase>
);
})}
</>
);
}

return (
<Box style={{ position: 'relative', width: '100%', height: '60px', overflowAnchor: 'none' }}>
<div
ref={observerRef}
style={{
position: 'absolute',
[direction === 'backward' ? 'top' : 'bottom']: 0,
width: '100%',
height: '1px',
}}
/>

{status === 'loading' && (
<Box justifyContent="Center" alignItems="Center" style={{ position: 'absolute', inset: 0 }}>
<Spinner variant="Secondary" size="400" />
</Box>
)}
</Box>
);
}
64 changes: 59 additions & 5 deletions src/app/features/room/RoomTimeline.css.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { globalStyle, style } from '@vanilla-extract/css';
import { RecipeVariants, recipe } from '@vanilla-extract/recipes';
import { DefaultReset, config } from 'folds';
import { DefaultReset, color, config, toRem } from 'folds';

export const TimelineFloat = recipe({
base: [
Expand Down Expand Up @@ -29,17 +29,71 @@ export const TimelineFloat = recipe({
});

export type TimelineFloatVariants = RecipeVariants<typeof TimelineFloat>;

export const messageList = style({
display: 'flex',
flexDirection: 'column',
width: '100%',
overflowY: 'scroll',
scrollbarGutter: 'stable',

'@supports': {
'not selector(::-webkit-scrollbar)': {
scrollbarWidth: 'auto',
selectors: {
'&:hover, &:has(*:hover)': {
scrollbarColor: `${color.SurfaceVariant.ContainerLine} ${color.SurfaceVariant.ContainerActive}`,
},
},
},
},

selectors: {
'&::-webkit-scrollbar': {
width: toRem(16),
height: toRem(16),
},
'&::-webkit-scrollbar-corner': {
backgroundColor: 'transparent',
},
'&::-webkit-scrollbar-thumb': {
backgroundColor: 'transparent',
borderRadius: config.radii.Pill,
minHeight: toRem(35),
border: `${toRem(4)} solid transparent`,
backgroundClip: 'padding-box',
},
'&::-webkit-scrollbar-track': {
backgroundColor: 'transparent',
borderRadius: config.radii.Pill,
border: `${toRem(4)} solid transparent`,
backgroundClip: 'padding-box',
},
'&:hover::-webkit-scrollbar-thumb, &:has(*:hover)::-webkit-scrollbar-thumb': {
backgroundColor: color.SurfaceVariant.ContainerLine,
},
'&:hover::-webkit-scrollbar-track, &:has(*:hover)::-webkit-scrollbar-track': {
backgroundColor: color.SurfaceVariant.ContainerActive,
},
},
});
globalStyle(`${messageList} > *`, {
scrollbarWidth: 'auto',
scrollbarColor: 'auto',
});

globalStyle(`body ${messageList} > *`, {
overflowAnchor: 'none',
});

globalStyle(`body ${messageList} [data-message-id]`, {
overflowAnchor: 'auto',
transition: 'background-color 0.1s ease-in-out !important',
position: 'relative',
zIndex: 1,
});

globalStyle(`body ${messageList} [data-message-id]:hover`, {
backgroundColor: 'var(--sable-surface-container-hover) !important',
zIndex: 2,
});

globalStyle(`body ${messageList} [data-message-id]:focus-within`, {
zIndex: 10,
});
Loading
Loading