Skip to content

feat: Devtool for sticky events MSC4354#32741

Merged
BillCarsonFr merged 23 commits intodevelopfrom
valere/devtool_sticky_event
Mar 16, 2026
Merged

feat: Devtool for sticky events MSC4354#32741
BillCarsonFr merged 23 commits intodevelopfrom
valere/devtool_sticky_event

Conversation

@BillCarsonFr
Copy link
Copy Markdown
Member

Adds a new devtool the explore the current sticky state of a room. A bit similar to the room state explorer.

image
image
image

Checklist

@BillCarsonFr BillCarsonFr linked an issue Mar 5, 2026 that may be closed by this pull request
@BillCarsonFr BillCarsonFr marked this pull request as ready for review March 6, 2026 10:59
@BillCarsonFr BillCarsonFr requested a review from a team as a code owner March 6, 2026 10:59
@BillCarsonFr BillCarsonFr requested review from dbkr and t3chguy March 6, 2026 10:59
@BillCarsonFr
Copy link
Copy Markdown
Member Author

@AndrewFerr FYI

If I have some spare time later, I will see how to add a delayed event devtool. Will think about how to mix them for sticky delayed


const rowStyle: React.CSSProperties = {
cursor: "pointer",
background: hover ? "rgba(0,0,0,0.03)" : "transparent",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be using :hover selector in CSS rather than JS hover tracking. Also probably needs keyboard accessibility styling rather than just mouse pointer hover

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done for hover.
I don't know what is keyboard accessibility styling? maybe it is using :focus css ? can you give me some advice to fix it?

Copy link
Copy Markdown
Member

@t3chguy t3chguy Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:focus-visible - :focus also applies to cursor where you already have :hover. So if you click it you leave :focus on it whereas :focus-visible only applies to forms of focus which should display a visible highlight for a11y

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed most of that code 7f7cd1b
keyboard navigation is still working.
Hope it fixes the problem? I really don't know much about css

Comment on lines +267 to +273
<th style={{ textAlign: "left", padding: "8px 12px", width: "35%" }}>{_t("devtools|users")}</th>
<th style={{ textAlign: "left", padding: "8px 12px", width: "50%" }}>
{_t("devtools|sticky_key")}
</th>
<th style={{ textAlign: "right", padding: "8px 12px", width: "15%" }}>
{_t("devtools|expires_in")}
</th>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CSS please.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done here eabe6b2
I kept just the width part that change for each column, I have seen it done in other parts of the code

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept just the width part that change for each column, I have seen it done in other parts of the code

That doesn't make it right unfortunately, we have a lot of tech debt given the age of the codebase

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@BillCarsonFr
Copy link
Copy Markdown
Member Author

Added a quick commit 0d458b7 to display when the homeserver does not support sticky events, as I noticed that matrix.org does not.

Comment on lines +38 to +39
const [eventType, setEventType] = useState<string | null>(null);
const [event, setEvent] = useState<MatrixEvent | null>(null);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The preferred way is this

Suggested change
const [eventType, setEventType] = useState<string | null>(null);
const [event, setEvent] = useState<MatrixEvent | null>(null);
const [eventType, setEventType] = useState<string>();
const [event, setEvent] = useState<MatrixEvent>();

and the type will be T | undefined

const cli = useContext(MatrixClientContext);
// Check if the server supports sticky events and show a message if it doesn't.
// undefined means we are still checking, true/false means we have the result.
const [stickyEventsSupported, setStickyEventsSupported] = useState<boolean | undefined>(undefined);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const [stickyEventsSupported, setStickyEventsSupported] = useState<boolean | undefined>(undefined);
const [stickyEventsSupported, setStickyEventsSupported] = useState<boolean>();

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +47 to +55
useEffect(() => {
cli.doesServerSupportUnstableFeature("org.matrix.msc4354")
.then((result) => {
setStickyEventsSupported(result);
})
.catch((ex) => {
logger.warn("Failed to check if sticky events are supported", ex);
});
}, [cli]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could use useAsyncMemo

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx, done 63e49ac

Comment on lines +59 to +64
const refresh = (): void => setEvents([...context.room._unstable_getStickyEvents()]);
context.room.on(RoomStickyEventsEvent.Update, refresh);

return () => {
context.room.off(RoomStickyEventsEvent.Update, refresh);
};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should use useTypedEventEmitterState

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done here a27cb71

Copy link
Copy Markdown
Member

@t3chguy t3chguy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks sane otherwise

Copy link
Copy Markdown
Member

@dbkr dbkr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looking good though I think

return <p>{_t("devtools|no_sticky_events")}</p>;
}

const onAction = async (): Promise<void> => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why's this async? Also probably ought to be useCallback().

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is because BaseTool IProps expects onAction(this: void): Promise<string | void>

*/
const StickyEventTableLine: React.FC<StateEventButtonProps> = ({ userId, stickyKey, expiresAt, onClick }) => {
const [timeRemaining, setTimeRemaining] = useState<string>("");
const [isExpired, setIsExpired] = useState<boolean>(false);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This state feels a bit redundant? Isn't it just a function of timeRemaining?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, done b626701

@dbkr
Copy link
Copy Markdown
Member

dbkr commented Mar 16, 2026

Thanks!

@BillCarsonFr BillCarsonFr added this pull request to the merge queue Mar 16, 2026
Merged via the queue into develop with commit 3e88689 Mar 16, 2026
46 checks passed
@BillCarsonFr BillCarsonFr deleted the valere/devtool_sticky_event branch March 16, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dev Tool for sticky events?

3 participants