mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-09 03:18:04 +00:00
updated the text input
This commit is contained in:
parent
6e93cac9b5
commit
6725f67b32
7 changed files with 140 additions and 46 deletions
|
|
@ -6,7 +6,9 @@ import { useEffect } from "react";
|
|||
|
||||
export default function GlobalError({ error }: { error: Error & { digest?: string } }) {
|
||||
useEffect(() => {
|
||||
Sentry.captureException(error);
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
Sentry.captureException(error);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -38,8 +38,7 @@ export function AppHeader() {
|
|||
<>
|
||||
<header className="w-full h-16 px-4 flex items-center justify-between">
|
||||
<Link
|
||||
href="https://supermemory.ai"
|
||||
target="_blank"
|
||||
href="/"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@
|
|||
import { useChat, useCompletion } from "@ai-sdk/react";
|
||||
import { cn } from "@lib/utils";
|
||||
import { Button } from "@ui/components/button";
|
||||
import { Input } from "@ui/components/input";
|
||||
import { DefaultChatTransport } from "ai";
|
||||
import {
|
||||
ArrowUp,
|
||||
Check,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
Copy,
|
||||
Plus,
|
||||
RotateCcw,
|
||||
UserIcon,
|
||||
X,
|
||||
|
|
@ -218,8 +217,10 @@ export function ChatMessages() {
|
|||
getCurrentChat,
|
||||
} = usePersistentChat();
|
||||
|
||||
const [input, setInput] = useState("");
|
||||
const activeChatIdRef = useRef<string | null>(null);
|
||||
const shouldGenerateTitleRef = useRef<boolean>(false);
|
||||
const hasRunInitialMessageRef = useRef<boolean>(false);
|
||||
|
||||
const { setDocumentIds } = useGraphHighlights();
|
||||
|
||||
|
|
@ -254,6 +255,16 @@ export function ChatMessages() {
|
|||
activeChatIdRef.current = currentChatId ?? id ?? null;
|
||||
}, [currentChatId, id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentChatId && !hasRunInitialMessageRef.current) {
|
||||
const msgs = getCurrentConversation();
|
||||
if (msgs && msgs.length === 1) {
|
||||
sendMessage({ text: msgs[0].content });
|
||||
hasRunInitialMessageRef.current = true;
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (id && id !== currentChatId) {
|
||||
setCurrentChatId(id);
|
||||
|
|
@ -262,7 +273,11 @@ export function ChatMessages() {
|
|||
|
||||
useEffect(() => {
|
||||
const msgs = getCurrentConversation();
|
||||
setMessages(msgs ?? []);
|
||||
if (msgs && msgs.length > 0) {
|
||||
setMessages(msgs);
|
||||
} else if (!currentChatId) {
|
||||
setMessages([]);
|
||||
}
|
||||
setInput("");
|
||||
}, [currentChatId]);
|
||||
|
||||
|
|
@ -273,7 +288,6 @@ export function ChatMessages() {
|
|||
}
|
||||
}, [messages, currentChatId, id, setConversation]);
|
||||
|
||||
const [input, setInput] = useState("");
|
||||
const { complete } = useCompletion({
|
||||
api: `${process.env.NEXT_PUBLIC_BACKEND_URL}/chat/title`,
|
||||
credentials: "include",
|
||||
|
|
@ -336,7 +350,13 @@ export function ChatMessages() {
|
|||
ref={scrollContainerRef}
|
||||
>
|
||||
{messages.map((message) => (
|
||||
<div className={cn("flex", message.role === "user" ? "items-center gap-2" : "flex-col")} key={message.id}>
|
||||
<div
|
||||
className={cn(
|
||||
"flex",
|
||||
message.role === "user" ? "items-center gap-2" : "flex-col",
|
||||
)}
|
||||
key={message.id}
|
||||
>
|
||||
{message.role === "user" && (
|
||||
<UserIcon className="size-4 text-muted-foreground" />
|
||||
)}
|
||||
|
|
@ -517,40 +537,92 @@ export function ChatMessages() {
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<form
|
||||
className="flex gap-2 px-4 pb-4 pt-1 relative flex-shrink-0"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
if (status === "submitted") return;
|
||||
if (status === "streaming") {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (input.trim()) {
|
||||
enableAutoScroll();
|
||||
scrollToBottom("auto");
|
||||
sendMessage({ text: input });
|
||||
setInput("");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
className="w-full"
|
||||
disabled={status === "submitted"}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
placeholder="Say something..."
|
||||
value={input}
|
||||
/>
|
||||
<Button disabled={status === "submitted"} type="submit">
|
||||
{status === "ready" ? (
|
||||
<ArrowUp className="size-4" />
|
||||
) : status === "submitted" ? (
|
||||
<Spinner className="size-4" />
|
||||
) : (
|
||||
<X className="size-4" />
|
||||
)}
|
||||
</Button>
|
||||
</form>
|
||||
<div className="px-4 pb-4 pt-1 relative flex-shrink-0">
|
||||
<div className="bg-gradient-to-r from-blue-500 to-blue-600 p-[3px] rounded-3xl shadow-lg">
|
||||
<div className="flex p-2 gap-2">
|
||||
<div className="backdrop-blur-md bg-white/10 border border-white/20 rounded-xl px-4 py-2 text-white text-sm hover:bg-white/15 transition-all duration-200 cursor-pointer shadow-lg">
|
||||
Suggest me best hotels in Liechtenstein
|
||||
</div>
|
||||
<div className="backdrop-blur-md bg-white/10 border border-white/20 rounded-xl px-4 py-2 text-white/90 text-sm hover:bg-white/15 transition-all duration-200 cursor-pointer shadow-lg">
|
||||
Prepare a full itinerary to Liechtenstein
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
className="flex flex-col items-end gap-3 bg-white rounded-[22px] p-2"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
if (status === "submitted") return;
|
||||
if (status === "streaming") {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (input.trim()) {
|
||||
enableAutoScroll();
|
||||
scrollToBottom("auto");
|
||||
sendMessage({ text: input });
|
||||
setInput("");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<textarea
|
||||
className="w-full text-black placeholder-black/40 rounded-md outline-none resize-none text-base leading-relaxed p-2"
|
||||
disabled={status === "submitted"}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
placeholder="Yo, describe my fav destination..."
|
||||
rows={2}
|
||||
value={input}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
if (input.trim() && status !== "submitted") {
|
||||
enableAutoScroll();
|
||||
scrollToBottom("auto");
|
||||
sendMessage({ text: input });
|
||||
setInput("");
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="flex items-center gap-2 w-full justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
className="bg-white/20 hover:bg-white/30 text-black border-[#EBEBEB] rounded-lg size-10"
|
||||
size="icon"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
<img src="/icons/attach.svg" alt="Attach" className="w-5 h-5" />
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-white/20 hover:bg-white/30 text-black border-[#EBEBEB] rounded-lg px-4 py-2 h-10"
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
<Plus className="size-4 mr-2" />
|
||||
Link Project
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="flex items-center justify-center bg-white"
|
||||
disabled={status === "submitted"}
|
||||
size="icon"
|
||||
type="submit"
|
||||
variant="ghost"
|
||||
>
|
||||
{status === "ready" ? (
|
||||
<img src="/icons/send.svg" alt="Send" className="w-7 h-7" />
|
||||
) : status === "submitted" ? (
|
||||
<Spinner className="size-5" />
|
||||
) : (
|
||||
<X className="size-5" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
Sentry.init({
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
Sentry.init({
|
||||
dsn: 'https://2451ebfd1a7490f05fa7776482df81b6@o4508385422802944.ingest.us.sentry.io/4509872269819904',
|
||||
|
||||
// Add optional integrations for additional features
|
||||
|
|
@ -25,6 +26,7 @@ Sentry.init({
|
|||
|
||||
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||
debug: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
|
||||
export const onRouterTransitionStart = process.env.NODE_ENV !== 'development' ? Sentry.captureRouterTransitionStart : () => {};
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const nextConfig: NextConfig = {
|
|||
skipTrailingSlashRedirect: true,
|
||||
};
|
||||
|
||||
export default withSentryConfig(nextConfig, {
|
||||
export default process.env.NODE_ENV === 'development' ? nextConfig : withSentryConfig(nextConfig, {
|
||||
// For all available options, see:
|
||||
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
||||
|
||||
|
|
|
|||
3
apps/web/public/icons/attach.svg
Normal file
3
apps/web/public/icons/attach.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.7768 10.6259L8.66084 12.7418C7.48724 13.9154 7.48724 15.8086 8.66084 16.9822C9.83445 18.1558 11.7276 18.1558 12.9013 16.9822L16.2336 13.6498C18.5723 11.3112 18.5723 7.50768 16.2336 5.16903C13.895 2.83038 10.0914 2.83038 7.7528 5.16903L4.12061 8.80122C2.11605 10.8058 2.11605 14.061 4.12061 16.0742" stroke="black" stroke-width="1.28497" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 502 B |
16
apps/web/public/icons/send.svg
Normal file
16
apps/web/public/icons/send.svg
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="36" height="36" rx="10" fill="#0B90EF"/>
|
||||
<g clip-path="url(#clip0_4433_12553)">
|
||||
<mask id="mask0_4433_12553" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="6" y="6" width="24" height="24">
|
||||
<path d="M30 6H6V30H30V6Z" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_4433_12553)">
|
||||
<path d="M24.0673 14.5111L15.5073 10.2311C9.75733 7.35111 7.39733 9.71111 10.2773 15.4611L11.1473 17.2011C11.3973 17.7111 11.3973 18.3011 11.1473 18.8111L10.2773 20.5411C7.39733 26.2911 9.74733 28.6511 15.5073 25.7711L24.0673 21.4911C27.9073 19.5711 27.9073 16.4311 24.0673 14.5111ZM20.8373 18.7511H15.4373C15.0273 18.7511 14.6873 18.4111 14.6873 18.0011C14.6873 17.5911 15.0273 17.2511 15.4373 17.2511H20.8373C21.2473 17.2511 21.5873 17.5911 21.5873 18.0011C21.5873 18.4111 21.2473 18.7511 20.8373 18.7511Z" fill="white"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_4433_12553">
|
||||
<rect width="24" height="24" fill="white" transform="translate(6 6)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1 KiB |
Loading…
Add table
Reference in a new issue