Skip to content

Commit

Permalink
Merge pull request #3360 from tloncorp/po/land-1701-rerendering-on-ed…
Browse files Browse the repository at this point in the history
…iting-reply-message

edit: fix issue with re-renders on editing reply message
  • Loading branch information
patosullivan authored Mar 25, 2024
2 parents 5f776bc + 8bbfa06 commit 0f2272f
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 272 deletions.
19 changes: 6 additions & 13 deletions apps/tlon-web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,16 @@ const SuspendedDiaryAddNote = (
);

interface RoutesProps {
state: { backgroundLocation?: Location } | null;
location: Location;
isMobile: boolean;
isSmall: boolean;
}

function GroupsRoutes({ state, location, isMobile, isSmall }: RoutesProps) {
const GroupsRoutes = React.memo(({ isMobile, isSmall }: RoutesProps) => {
const groupsTitle = 'Tlon';
const loaded = useSettingsLoaded();
const location = useLocation();

const state = location.state as { backgroundLocation?: Location } | null;

useEffect(() => {
if (loaded) {
Expand Down Expand Up @@ -558,7 +559,7 @@ function GroupsRoutes({ state, location, isMobile, isSmall }: RoutesProps) {
) : null}
</>
);
}
});

function authRedirect() {
document.location = `${document.location.protocol}//${document.location.host}`;
Expand Down Expand Up @@ -613,7 +614,6 @@ function App() {
useNativeBridge();
const navigate = useNavigate();
const handleError = useErrorHandler();
const location = useLocation();
const isMobile = useIsMobile();
const isSmall = useMedia('(max-width: 1023px)');

Expand All @@ -637,20 +637,13 @@ function App() {
})();
}, [handleError]);

const state = location.state as { backgroundLocation?: Location } | null;

return (
<div className="flex h-full w-full flex-col">
<DisconnectNotice />
<LeapProvider>
<ChatInputFocusProvider>
<DragAndDropProvider>
<GroupsRoutes
state={state}
location={location}
isMobile={isMobile}
isSmall={isSmall}
/>
<GroupsRoutes isMobile={isMobile} isSmall={isSmall} />
</DragAndDropProvider>
</ChatInputFocusProvider>
<Leap />
Expand Down
4 changes: 2 additions & 2 deletions apps/tlon-web/src/chat/ChatChannel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { useRouteGroup } from '@/state/groups/groups';

import ChatThread from './ChatThread/ChatThread';

function ChatChannel({ title }: ViewProps) {
const ChatChannel = React.memo(({ title }: ViewProps) => {
const { isChatInputFocused } = useChatInputFocus();
// TODO: We need to reroute users who can't read the channel
// const navigate = useNavigate();
Expand Down Expand Up @@ -195,6 +195,6 @@ function ChatChannel({ title }: ViewProps) {
</Routes>
</>
);
}
});

export default ChatChannel;
16 changes: 13 additions & 3 deletions apps/tlon-web/src/chat/ChatInput/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,21 @@ export default function ChatInput({
const myLastMessage = useMyLastMessage(whom, replying);
const lastMessageId = myLastMessage ? myLastMessage.seal.id : '';
const lastMessageIdRef = useRef(lastMessageId);
const isReplyingRef = useRef(!!replying);

useEffect(() => {
if (lastMessageId && lastMessageId !== lastMessageIdRef.current) {
lastMessageIdRef.current = lastMessageId;
}
}, [lastMessageId]);

useEffect(() => {
if (isReplyingRef.current && !replying) {
isReplyingRef.current = false;
}
isReplyingRef.current = !!replying;
}, [replying]);

const handleUnblockClick = useCallback(() => {
unblockShip({
ship: whom,
Expand Down Expand Up @@ -400,9 +408,11 @@ export default function ChatInput({
!isDmOrMultiDM
) {
setSearchParams(
{
edit: lastMessageIdRef.current,
},
isReplyingRef.current
? { editReply: lastMessageIdRef.current }
: {
edit: lastMessageIdRef.current,
},
{ replace: true }
);
editor.commands.blur();
Expand Down
83 changes: 28 additions & 55 deletions apps/tlon-web/src/chat/ChatSearch/ChatSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import * as Dialog from '@radix-ui/react-dialog';
import { ChatMap } from '@tloncorp/shared/dist/urbit/channel';
import cn from 'classnames';
import React, { PropsWithChildren, useCallback } from 'react';
import React, { PropsWithChildren, useCallback, useRef } from 'react';
import { useNavigate } from 'react-router';
import { Link } from 'react-router-dom';
import { VirtuosoHandle } from 'react-virtuoso';
import { useOnClickOutside } from 'usehooks-ts';

import useActiveTab from '@/components/Sidebar/util';
import { useSafeAreaInsets } from '@/logic/native';
import useMedia, { useIsMobile } from '@/logic/useMedia';
import { disableDefault } from '@/logic/utils';

import ChatSearchResults from './ChatSearchResults';
import SearchBar from './SearchBar';
Expand Down Expand Up @@ -45,8 +43,8 @@ export default function ChatSearch({
const navigate = useNavigate();
const isMobile = useIsMobile();
const isSmall = useMedia('(min-width: 768px) and (max-width: 1099px)');
const activeTab = useActiveTab();
const safeAreaInsets = useSafeAreaInsets();
const containerRef = useRef<HTMLDivElement>(null);
const scrollerRef = React.useRef<VirtuosoHandle>(null);
const { selected, rawInput, onChange, onKeyDown } = useChatSearchInput({
root,
Expand All @@ -68,23 +66,7 @@ export default function ChatSearch({
}, []),
});

const preventClose = useCallback((e: Event) => {
const target = e.target as HTMLElement;
const hasNavAncestor = target.id === 'search' || target.closest('#search');

if (hasNavAncestor) {
e.preventDefault();
}
}, []);

const onOpenChange = useCallback(
(open: boolean) => {
if (!open) {
navigate(root);
}
},
[navigate, root]
);
useOnClickOutside(containerRef, () => navigate(root));

return (
<div
Expand All @@ -96,6 +78,7 @@ export default function ChatSearch({
'flex w-full flex-1 items-center justify-between space-x-2',
isSmall || isMobile ? 'p-3' : 'p-2'
)}
ref={containerRef}
>
<div className="max-w-[240px] flex-none">
{!isMobile && !isSmall ? children : null}
Expand All @@ -112,40 +95,30 @@ export default function ChatSearch({
isSmall={isSmall}
/>
</label>
<Dialog.Root
open
modal={activeTab === 'messages' ? true : false}
onOpenChange={onOpenChange}
>
<Dialog.Content
onInteractOutside={preventClose}
onOpenAutoFocus={disableDefault}
className="absolute left-0 top-[40px] z-50 w-full outline-none"
<div className="absolute left-0 top-[40px] z-50 w-full outline-none">
<section
tabIndex={0}
role="listbox"
aria-setsize={scan?.size || 0}
id="search-results"
className={cn(
'default-focus dialog border-2 border-transparent shadow-lg dark:border-gray-50',
query ? 'flex h-[60vh] min-h-[480px] flex-col' : 'h-[200px]'
)}
>
<section
tabIndex={0}
role="listbox"
aria-setsize={scan?.size || 0}
id="search-results"
className={cn(
'default-focus dialog border-2 border-transparent shadow-lg dark:border-gray-50',
query ? 'flex h-[60vh] min-h-[480px] flex-col' : 'h-[200px]'
)}
>
<ChatSearchResults
ref={scrollerRef}
whom={whom}
root={root}
scan={scan}
searchDetails={searchDetails}
isLoading={isLoading}
query={query}
selected={selected.index}
endReached={endReached}
/>
</section>
</Dialog.Content>
</Dialog.Root>
<ChatSearchResults
ref={scrollerRef}
whom={whom}
root={root}
scan={scan}
searchDetails={searchDetails}
isLoading={isLoading}
query={query}
selected={selected.index}
endReached={endReached}
/>
</section>
</div>
</div>
{!isSmall && (
<Link to={root} className="default-focus secondary-button">
Expand Down
4 changes: 3 additions & 1 deletion apps/tlon-web/src/chat/ChatThread/ChatThread.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useDragAndDrop } from '@/logic/DragAndDropContext';
import { useChannelCompatibility, useChannelFlag } from '@/logic/channel';
import { useBottomPadding } from '@/logic/position';
import { useIsScrolling } from '@/logic/scroll';
import useIsEditingMessage from '@/logic/useIsEditingMessage';
import useMedia, { useIsMobile } from '@/logic/useMedia';
import {
useAddReplyMutation,
Expand Down Expand Up @@ -48,6 +49,7 @@ export default function ChatThread() {
}>();
const isMobile = useIsMobile();
const { isChatInputFocused } = useChatInputFocus();
const isEditing = useIsEditingMessage();
const scrollerRef = useRef<VirtuosoHandle>(null);
const flag = useChannelFlag()!;
const nest = `chat/${flag}`;
Expand Down Expand Up @@ -259,7 +261,7 @@ export default function ChatThread() {
</div>
<div
className={cn(
isDragging || isOver || !canWrite
isDragging || isOver || !canWrite || (isEditing && isMobile)
? ''
: 'sticky bottom-0 border-t-2 border-gray-50 bg-white p-3 sm:p-4'
)}
Expand Down
Loading

0 comments on commit 0f2272f

Please sign in to comment.