fix: address confirmed bugs from LOTUS_BUGS.md audit
- useFileDrop: reset drag overlay when mouse leaves browser window (relatedTarget === null signals viewport exit, counter was getting stuck) - useDeviceVerificationStatus: add member count to useMemo deps so new room members' devices get checked, not just initial joined members - index.css: define --bg-surface-variant used by VoiceMessageRecorder, MessageSearch, SearchFilters, UserRoomProfile (was falling back to transparent) - syntaxHighlight: fix Python inline comments — # after space/tab was treated as plain text; only start-of-line was recognised - usePresenceUpdater: replace internal baseUrl cast with mx.getHomeserverUrl() - useLocalMessageSearch: scan all linked timelines via getUnfilteredTimelineSet() not just the live window, so scrolled-back history is included in E2EE search - RoomViewHeader: show search button in encrypted rooms — local search is implemented and handles them; the guard was a holdover from before it existed - recent-emoji: return emojis in recency order (array is already unshifted on use) instead of sorting by total usage count Skipped: media gallery memory leak (needs virtualization refactor), bookmark race condition (needs queue/lock), Night Light portal coverage (position:fixed already covers full viewport — not a real bug). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -50,7 +50,10 @@ export const useLocalMessageSearch = () => {
|
||||
|
||||
encryptedRoomsCount += 1;
|
||||
|
||||
const events = room.getLiveTimeline().getEvents();
|
||||
const events = room
|
||||
.getUnfilteredTimelineSet()
|
||||
.getTimelines()
|
||||
.flatMap((tl) => tl.getEvents());
|
||||
if (events.length === 0) continue;
|
||||
|
||||
searchedRoomsCount += 1;
|
||||
|
||||
@@ -558,7 +558,7 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) {
|
||||
</Box>
|
||||
|
||||
<Box shrink="No">
|
||||
{!encryptedRoom && (
|
||||
{(
|
||||
<TooltipProvider
|
||||
position="Bottom"
|
||||
offset={4}
|
||||
|
||||
@@ -115,8 +115,10 @@ export const useRoomUnverifiedDeviceCount = (
|
||||
|
||||
const memberIds = useMemo(
|
||||
() => room.getJoinedMembers().map((m) => m.userId),
|
||||
// room.roomId guards against room changes; getJoinedMemberCount() ensures
|
||||
// the list refreshes when members join/leave so new devices get checked.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[room.roomId],
|
||||
[room.roomId, room.getJoinedMemberCount()],
|
||||
);
|
||||
|
||||
const updateCount = useCallback(async () => {
|
||||
|
||||
@@ -42,7 +42,13 @@ export const useFileDropZone = (
|
||||
setActive(true);
|
||||
}
|
||||
};
|
||||
const handleDragLeave = () => {
|
||||
const handleDragLeave = (evt: DragEvent) => {
|
||||
if (evt.relatedTarget === null) {
|
||||
// Mouse left the browser window — reset unconditionally
|
||||
dragCounterRef.current = 0;
|
||||
setActive(false);
|
||||
return;
|
||||
}
|
||||
dragCounterRef.current -= 1;
|
||||
if (dragCounterRef.current <= 0) {
|
||||
dragCounterRef.current = 0;
|
||||
|
||||
@@ -77,7 +77,7 @@ export function usePresenceUpdater() {
|
||||
const handlePageHide = () => {
|
||||
const userId = mx.getUserId();
|
||||
const token = mx.getAccessToken();
|
||||
const baseUrl = (mx as unknown as { baseUrl: string }).baseUrl;
|
||||
const baseUrl = mx.getHomeserverUrl();
|
||||
if (!userId || !token || !baseUrl) return;
|
||||
|
||||
fetch(`${baseUrl}/_matrix/client/v3/presence/${encodeURIComponent(userId)}/status`, {
|
||||
|
||||
@@ -16,7 +16,6 @@ export const getRecentEmojis = (mx: MatrixClient, limit?: number): IEmoji[] => {
|
||||
if (!Array.isArray(recentEmoji)) return [];
|
||||
|
||||
return recentEmoji
|
||||
.sort((e1, e2) => e2[1] - e1[1])
|
||||
.slice(0, limit)
|
||||
.reduce<IEmoji[]>((list, [unicode]) => {
|
||||
const emoji = emojis.find((e) => e.unicode === unicode);
|
||||
|
||||
@@ -222,7 +222,7 @@ export function tokenize(code: string, lang: string): SyntaxToken[] {
|
||||
if (
|
||||
code[i] === '#' &&
|
||||
(normalised === 'python' || normalised === 'py') &&
|
||||
(i === 0 || code[i - 1] === '\n')
|
||||
(i === 0 || code[i - 1] === '\n' || code[i - 1] === ' ' || code[i - 1] === '\t')
|
||||
) {
|
||||
const nlHash = code.indexOf('\n', i);
|
||||
const closeIdx = nlHash === -1 ? len : nlHash;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
/* semantic surface vars used by poll, location, upload card, gif picker */
|
||||
--bg-surface: #ffffff;
|
||||
--bg-surface-low: rgba(0, 0, 0, 0.04);
|
||||
--bg-surface-variant: rgba(0, 0, 0, 0.07);
|
||||
--bg-surface-active: rgba(0, 0, 0, 0.1);
|
||||
--bg-surface-border: rgba(0, 0, 0, 0.14);
|
||||
--text-primary: #1a1a1a;
|
||||
@@ -37,6 +38,7 @@
|
||||
/* semantic surface vars — dark overrides */
|
||||
--bg-surface: #25272e;
|
||||
--bg-surface-low: rgba(255, 255, 255, 0.05);
|
||||
--bg-surface-variant: rgba(255, 255, 255, 0.08);
|
||||
--bg-surface-active: rgba(255, 255, 255, 0.1);
|
||||
--bg-surface-border: rgba(255, 255, 255, 0.12);
|
||||
--text-primary: #e0e5ed;
|
||||
|
||||
Reference in New Issue
Block a user