Browse Source

fix: change scrollbars to "tiny" style, improved message scrolling, fixed bug with message input

pull/586/head
Dan Ditomaso 1 year ago
parent
commit
2a145e13a9
  1. 2
      src/App.tsx
  2. 4
      src/components/BatteryStatus.tsx
  3. 47
      src/components/PageComponents/Messages/ChannelChat.tsx
  4. 5
      src/components/PageComponents/Messages/MessageInput.tsx

2
src/App.tsx

@ -37,7 +37,7 @@ export const App = (): JSX.Element => {
/> />
<Toaster /> <Toaster />
<DeviceWrapper device={device}> <DeviceWrapper device={device}>
<div className="flex h-screen flex-col bg-background-primary text-text-primary"> <div className="flex h-screen flex-col bg-background-primary text-text-primary" style={{ scrollbarWidth: 'thin' }}>
<SidebarProvider> <SidebarProvider>
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
{device ? ( {device ? (

4
src/components/BatteryStatus.tsx

@ -27,7 +27,7 @@ const batteryStates: BatteryStateConfig[] = [
{ {
condition: level => level > 100, condition: level => level > 100,
Icon: PlugZapIcon, Icon: PlugZapIcon,
className: 'text-gray-600', className: 'text-gray-500',
text: () => 'Plugged in', text: () => 'Plugged in',
}, },
{ {
@ -39,7 +39,7 @@ const batteryStates: BatteryStateConfig[] = [
{ {
condition: level => level > 20, condition: level => level > 20,
Icon: BatteryMediumIcon, Icon: BatteryMediumIcon,
className: 'text-yellow-400', className: 'text-yellow-500',
text: level => `${level}% charging`, text: level => `${level}% charging`,
}, },
{ {

47
src/components/PageComponents/Messages/ChannelChat.tsx

@ -14,55 +14,66 @@ const EmptyState = () => (
</div> </div>
); );
export const ChannelChat = ({ export const ChannelChat = ({ messages = [] }: ChannelChatProps) => {
messages = [],
}: ChannelChatProps) => {
const messagesEndRef = useRef<HTMLDivElement>(null); const messagesEndRef = useRef<HTMLDivElement>(null);
const scrollContainerRef = useRef<HTMLUListElement>(null); const scrollContainerRef = useRef<HTMLUListElement>(null);
const userScrolledUpRef = useRef(false);
const scrollToBottom = useCallback((behavior: ScrollBehavior = 'smooth') => { const scrollToBottom = useCallback((behavior: ScrollBehavior = 'smooth') => {
const scrollContainer = scrollContainerRef.current; requestAnimationFrame(() => {
if (!scrollContainer) return;
const scrollThreshold = 50; // How close to bottom to trigger smooth scroll
const isNearBottom = scrollContainer.scrollHeight - scrollContainer.scrollTop - scrollContainer.clientHeight < scrollThreshold;
if (behavior === 'instant' || isNearBottom) {
messagesEndRef.current?.scrollIntoView({ behavior }); messagesEndRef.current?.scrollIntoView({ behavior });
} });
}, []); }, []);
useEffect(() => { useEffect(() => {
if (messages.length > 0) { const scrollContainer = scrollContainerRef.current;
if (!scrollContainer) return;
const isScrolledToBottom = scrollContainer.scrollHeight - scrollContainer.scrollTop - scrollContainer.clientHeight <= 10;
if (isScrolledToBottom || !userScrolledUpRef.current) {
scrollToBottom('smooth'); scrollToBottom('smooth');
} }
}, [messages, scrollToBottom]); }, [messages, scrollToBottom]);
useEffect(() => {
const scrollContainer = scrollContainerRef.current;
const handleScroll = () => {
if (!scrollContainer) return;
const isAtBottom = scrollContainer.scrollHeight - scrollContainer.scrollTop - scrollContainer.clientHeight <= 10;
userScrolledUpRef.current = !isAtBottom;
};
scrollContainer?.addEventListener('scroll', handleScroll);
return () => {
scrollContainer?.removeEventListener('scroll', handleScroll);
};
}, []);
if (!messages?.length) { if (!messages?.length) {
return ( return (
<ul ref={scrollContainerRef} className="flex flex-1 flex-col items-center justify-center"> <div className="flex flex-1 flex-col items-center justify-center">
<EmptyState /> <EmptyState />
<div ref={messagesEndRef} /> <div ref={messagesEndRef} />
</ul> </div>
); );
} }
return ( return (
<ul <ul
ref={scrollContainerRef} ref={scrollContainerRef}
className="mt-auto overflow-y-auto px-3 py-2" className="flex-grow overflow-y-auto px-3 py-2"
> >
<div ref={messagesEndRef} className="h-px" />
{messages?.map((message) => { {messages?.map((message) => {
return ( return (
<MessageItem <MessageItem
key={message?.messageId ?? `${message?.from}-${message?.date}`} key={message.messageId ?? `${message.from}-${message.date}`}
message={message} message={message}
/> />
); );
})} })}
<div ref={messagesEndRef} className="h-px" />
</ul> </ul>
); );
}; };

5
src/components/PageComponents/Messages/MessageInput.tsx

@ -56,10 +56,7 @@ export const MessageInput = ({
if (byteLength <= maxBytes) { if (byteLength <= maxBytes) {
setLocalDraft(newValue); setLocalDraft(newValue);
setMessageBytes(byteLength); setMessageBytes(byteLength);
setDraft(to, newValue);
startTransition(() => {
setDraft(to, newValue);
});
} }
}; };

Loading…
Cancel
Save