Message input multiline
This commit is contained in:
@@ -2,16 +2,20 @@
|
|||||||
|
|
||||||
import AppSidebar from "@/components/Sidebar";
|
import AppSidebar from "@/components/Sidebar";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { useIsMobile } from "@/hooks/is-mobile";
|
||||||
import useApp from "@/hooks/use-app";
|
import useApp from "@/hooks/use-app";
|
||||||
|
|
||||||
export default function Chat() {
|
export default function Chat() {
|
||||||
const app = useApp();
|
const app = useApp();
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppSidebar app={app}>
|
<AppSidebar app={app}>
|
||||||
<Card className="bg-background w-full">
|
<Card className="bg-background w-full">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Direct Messages</CardTitle>
|
<CardTitle onClick={() => isMobile && app.setSidebarOpen(true)}>
|
||||||
|
Direct Messages
|
||||||
|
</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent></CardContent>
|
<CardContent></CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import {
|
|||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "./ui/dropdown-menu";
|
} from "./ui/dropdown-menu";
|
||||||
import { ChevronLeftIcon, SmilePlusIcon } from "lucide-react";
|
import { ChevronLeftIcon, SendIcon, SmilePlusIcon } from "lucide-react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { format, isToday, isYesterday } from "date-fns";
|
import { format, isToday, isYesterday } from "date-fns";
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
@@ -20,6 +20,7 @@ import axios from "axios";
|
|||||||
import ProfilePicture from "./ProfilePicture";
|
import ProfilePicture from "./ProfilePicture";
|
||||||
import App from "@/types/app";
|
import App from "@/types/app";
|
||||||
import { useIsMobile } from "@/hooks/use-mobile";
|
import { useIsMobile } from "@/hooks/use-mobile";
|
||||||
|
import { Textarea } from "./ui/textarea";
|
||||||
|
|
||||||
function MessageContainer({ message, app }: { message: Message; app: App }) {
|
function MessageContainer({ message, app }: { message: Message; app: App }) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -144,6 +145,7 @@ export default function MessageBox({
|
|||||||
}) {
|
}) {
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const inputRef = useRef<any>(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-svh w-full max-h-svh flex flex-col pb-5 pl-5 gap-5">
|
<div className="h-svh w-full max-h-svh flex flex-col pb-5 pl-5 gap-5">
|
||||||
@@ -164,21 +166,64 @@ export default function MessageBox({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<footer className="flex gap-3 pr-5 w-full h-max">
|
<footer className="flex gap-3 pr-5 w-full h-max">
|
||||||
<Input
|
{text.includes("\n") ? (
|
||||||
className=""
|
<Textarea
|
||||||
placeholder="Type a message..."
|
ref={inputRef}
|
||||||
value={text}
|
className="resize-none"
|
||||||
onChange={(e) => setText(e.target.value)}
|
placeholder="Type a message..."
|
||||||
onKeyDown={(e) => {
|
value={text}
|
||||||
if (e.key === "Enter") {
|
onChange={(e) => {
|
||||||
sendMessage(text);
|
if (!e.target.value.includes("\n") && text.includes("\n")) {
|
||||||
setText("");
|
setTimeout(() => {
|
||||||
}
|
if (inputRef.current) {
|
||||||
}}
|
inputRef.current.selectionStart = text.length + 1;
|
||||||
/>
|
inputRef.current.selectionEnd = text.length + 1;
|
||||||
|
inputRef.current.focus();
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(e.target.value);
|
||||||
|
}}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
if (!e.shiftKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
sendMessage(text);
|
||||||
|
setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Input
|
||||||
|
placeholder="Type a message..."
|
||||||
|
ref={inputRef}
|
||||||
|
value={text}
|
||||||
|
onChange={(e) => setText(e.target.value)}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
if (e.shiftKey) {
|
||||||
|
setText((p) => p + "\n");
|
||||||
|
setTimeout(() => {
|
||||||
|
if (inputRef.current) {
|
||||||
|
inputRef.current.selectionStart = text.length + 1;
|
||||||
|
inputRef.current.selectionEnd = text.length + 1;
|
||||||
|
inputRef.current.focus();
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
} else {
|
||||||
|
sendMessage(text.trim());
|
||||||
|
setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="secondary">
|
<Button variant="secondary" className="hidden md:block">
|
||||||
<SmilePlusIcon />
|
<SmilePlusIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
@@ -190,6 +235,10 @@ export default function MessageBox({
|
|||||||
/>
|
/>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
||||||
|
<Button variant="secondary">
|
||||||
|
<SendIcon />
|
||||||
|
</Button>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user