+
diff --git a/apps/web/src/components/app/ChatPanel/EmojiSearch.tsx b/apps/web/src/components/app/ChatPanel/EmojiSearch.tsx
index 74e3e03..746f6b5 100644
--- a/apps/web/src/components/app/ChatPanel/EmojiSearch.tsx
+++ b/apps/web/src/components/app/ChatPanel/EmojiSearch.tsx
@@ -28,25 +28,27 @@ export function EmojiSearch({
useEffect(() => {
const beforeCursor = message.substring(0, cursorPosition);
const match = beforeCursor.match(/:[\w\-+]*$/);
-
+
if (match) {
const term = match[0].substring(1);
setSearchTerm(term);
-
+
if (term.length > 0) {
const localResults = Array.from(emojiMap.keys())
- .filter(name => name.toLowerCase().includes(term.toLowerCase()))
+ .filter((name) => name.toLowerCase().includes(term.toLowerCase()))
.slice(0, 5);
-
+
if (localResults.length > 0) {
setSearchResults(localResults);
}
-
+
if (socket && socket.readyState === WebSocket.OPEN) {
- socket.send(JSON.stringify({
- type: 'emojiSearch',
- searchTerm: term
- }));
+ socket.send(
+ JSON.stringify({
+ type: 'emojiSearch',
+ searchTerm: term,
+ })
+ );
}
} else {
setSearchResults([]);
@@ -63,22 +65,22 @@ export function EmojiSearch({
const handleEmojiSearchResponse = (event: MessageEvent) => {
try {
const data = JSON.parse(event.data);
-
+
if (data.type === 'emojiSearchResponse') {
const serverResults = data.results || [];
-
+
const localResults = Array.from(emojiMap.keys())
- .filter(name => searchTerm && name.toLowerCase().includes(searchTerm.toLowerCase()))
+ .filter((name) => searchTerm && name.toLowerCase().includes(searchTerm.toLowerCase()))
.slice(0, 5);
-
+
const combinedResults = [...serverResults];
-
- localResults.forEach(name => {
+
+ localResults.forEach((name) => {
if (!combinedResults.includes(name)) {
combinedResults.push(name);
}
});
-
+
setSearchResults(combinedResults.slice(0, 10));
setSelectedIndex(0);
}
@@ -95,18 +97,18 @@ export function EmojiSearch({
useEffect(() => {
if (!textareaRef.current) return;
-
+
const handleKeyDown = (e: KeyboardEvent) => {
if (!searchTerm || searchResults.length === 0) return;
-
+
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
- setSelectedIndex(prev => (prev + 1) % searchResults.length);
+ setSelectedIndex((prev) => (prev + 1) % searchResults.length);
break;
case 'ArrowUp':
e.preventDefault();
- setSelectedIndex(prev => (prev - 1 + searchResults.length) % searchResults.length);
+ setSelectedIndex((prev) => (prev - 1 + searchResults.length) % searchResults.length);
break;
case 'Enter':
if (searchResults[selectedIndex]) {
@@ -127,10 +129,10 @@ export function EmojiSearch({
break;
}
};
-
+
const textarea = textareaRef.current;
textarea.addEventListener('keydown', handleKeyDown);
-
+
return () => {
textarea.removeEventListener('keydown', handleKeyDown);
};
@@ -150,25 +152,25 @@ export function EmojiSearch({
}
return (
-
+
{searchResults.map((emojiName, index) => {
const isSelected = index === selectedIndex;
const emojiUrl = emojiMap.get(emojiName);
-
+
return (
onSelect(emojiName)}
>
{emojiUrl && (
-
+
)}
- {emojiName}
- {isSelected && }
+ {emojiName}
+ {isSelected && }
);
})}
diff --git a/apps/web/src/components/app/ChatPanel/message.tsx b/apps/web/src/components/app/ChatPanel/message.tsx
index 04e7993..fb76fe2 100644
--- a/apps/web/src/components/app/ChatPanel/message.tsx
+++ b/apps/web/src/components/app/ChatPanel/message.tsx
@@ -7,28 +7,26 @@ import { Bot } from 'lucide-react';
export function Message({ user, message, type, emojiMap }: MessageProps) {
if (type === 'systemMsg') {
return (
-
-
{message}
+
+ {message}
);
}
return (
-
-
-
-
- {user?.isBot && (
-
- {' '}
-
-
- )}
- {user?.displayName || user?.username}
-
-
+
+
+
+ {user?.isBot && }
+ {user?.displayName || user?.username}
+
+
-
+
);
@@ -50,12 +48,8 @@ export function EmojiRenderer({ text, emojiMap }: EmojiRendererProps) {
return (
-
-
+
+
{part};
+ // Preserve text as-is, handling whitespace properly
+ if (part) {
+ return {part};
+ }
+ return null;
})}
>
);
diff --git a/apps/web/src/components/app/Livestream/Livestream.tsx b/apps/web/src/components/app/Livestream/Livestream.tsx
index 19ba626..bedc86f 100644
--- a/apps/web/src/components/app/Livestream/Livestream.tsx
+++ b/apps/web/src/components/app/Livestream/Livestream.tsx
@@ -19,7 +19,7 @@ export default function LiveStream(props: Props) {
const [isRefreshing, setIsRefreshing] = useState(false);
useEffect(() => {
- const currentStream = channels.find(s => s.username === props.username);
+ const currentStream = channels.find((s) => s.username === props.username);
if (currentStream?.channel?.isRestricted) {
setIsRestricted(true);
setRestrictionExpiresAt(currentStream.channel.restrictionExpiresAt || null);
@@ -50,32 +50,28 @@ export default function LiveStream(props: Props) {
Restriction lifts: {format(new Date(restrictionExpiresAt), 'PPP p')}
)}
-
);
}
-
+
return (
-
+
{isMobile && (
-
-
+
{!isMobile && (
-
+
)}
@@ -86,4 +82,4 @@ export default function LiveStream(props: Props) {
interface Props {
username: string;
streamInfo: StreamInfo & { channel: Channel };
-}
\ No newline at end of file
+}