This commit is contained in:
Saatvik Arya 2024-07-25 20:12:35 -07:00
parent 00239d6d01
commit dcf6b589da
13 changed files with 629 additions and 622 deletions

View file

@ -31,400 +31,400 @@ export default function ContentApp({
token: string | undefined;
shadowRoot: ShadowRoot;
}) {
const [hover, setHover] = useState(false);
const [hover, setHover] = useState(false);
const { toast } = useToast();
const { toast } = useToast();
const [loading, setLoading] = useState(false);
const [loading, setLoading] = useState(false);
const [webNote, setWebNote] = useState<string>("");
const [webNote, setWebNote] = useState<string>("");
const [importedCount, setImportedCount] = useState(0);
const [isImporting, setIsImporting] = useState(false);
const [importDone, setImportDone] = useState(false);
const [importedCount, setImportedCount] = useState(0);
const [isImporting, setIsImporting] = useState(false);
const [importDone, setImportDone] = useState(false);
const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(
null,
);
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const [isPopover2Open, setIsPopover2Open] = useState(false);
const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(
null,
);
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const [isPopover2Open, setIsPopover2Open] = useState(false);
const [spacesOptions, setSpacesOptions] = useState<
{ id: number; name: string }[]
>([]);
const [selectedSpace, setSelectedSpace] = useState<string>();
const [spacesOptions, setSpacesOptions] = useState<
{ id: number; name: string }[]
>([]);
const [selectedSpace, setSelectedSpace] = useState<string>();
const [userNotLoggedIn, setUserNotLoggedIn] = useState(false);
const [userNotLoggedIn, setUserNotLoggedIn] = useState(false);
const showLoginToast = async () => {
setUserNotLoggedIn(true);
const showLoginToast = async () => {
setUserNotLoggedIn(true);
const NOSHOW_TOAST = ["accounts.google.com", "supermemory.ai"];
const NOSHOW_TOAST = ["accounts.google.com", "supermemory.ai"];
const noLoginWarning = await chrome.storage.local.get("noLoginWarning");
if (Object.keys(noLoginWarning).length > 0) {
return;
}
const noLoginWarning = await chrome.storage.local.get("noLoginWarning");
if (Object.keys(noLoginWarning).length > 0) {
return;
}
if (!NOSHOW_TOAST.includes(window.location.host)) {
const t = toast({
title: "Please login to supermemory.ai to use this extension.",
action: (
<div className="flex flex-col gap-2">
<button
onClick={() =>
window.open("https://supermemory.ai/signin", "_blank")
}
>
Login
</button>
if (!NOSHOW_TOAST.includes(window.location.host)) {
const t = toast({
title: "Please login to supermemory.ai to use this extension.",
action: (
<div className="flex flex-col gap-2">
<button
onClick={() =>
window.open("https://supermemory.ai/signin", "_blank")
}
>
Login
</button>
<button
className="text-xs"
onClick={async () => {
await chrome.storage.local.set({
noLoginWarning: true,
});
t.dismiss();
}}
>
Ignore
</button>
</div>
),
});
}
};
<button
className="text-xs"
onClick={async () => {
await chrome.storage.local.set({
noLoginWarning: true,
});
t.dismiss();
}}
>
Ignore
</button>
</div>
),
});
}
};
useEffect(() => {
document.addEventListener("mousemove", (e) => {
const percentageX = (e.clientX / window.innerWidth) * 100;
const percentageY = (e.clientY / window.innerHeight) * 100;
useEffect(() => {
document.addEventListener("mousemove", (e) => {
const percentageX = (e.clientX / window.innerWidth) * 100;
const percentageY = (e.clientY / window.innerHeight) * 100;
if (percentageX > 75 && percentageY > 75) {
setHover(true);
} else {
setHover(false);
}
});
if (percentageX > 75 && percentageY > 75) {
setHover(true);
} else {
setHover(false);
}
});
const getUserData = () => {
chrome.runtime.sendMessage({ type: "getJwt" });
};
const getUserData = () => {
chrome.runtime.sendMessage({ type: "getJwt" });
};
getUserData();
getUserData();
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === "import-update") {
setIsImporting(true);
setImportedCount(request.importedCount);
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === "import-update") {
setIsImporting(true);
setImportedCount(request.importedCount);
}
if (request.type === "import-done") {
setIsImporting(false);
setImportDone(true);
}
if (request.type === "import-done") {
setIsImporting(false);
setImportDone(true);
}
if (request.type === "supermemory-message") {
toast({
title: request.message,
});
}
});
if (request.type === "supermemory-message") {
toast({
title: request.message,
});
}
});
const portalDiv = document.createElement("div");
portalDiv.id = "popover-portal";
shadowRoot.appendChild(portalDiv);
setPortalContainer(portalDiv);
const portalDiv = document.createElement("div");
portalDiv.id = "popover-portal";
shadowRoot.appendChild(portalDiv);
setPortalContainer(portalDiv);
return () => {
document.removeEventListener("mousemove", () => {});
};
}, []);
return () => {
document.removeEventListener("mousemove", () => {});
};
}, []);
const getSpaces = async () => {
const response = await fetch(`${BACKEND_URL}/api/spaces`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
const getSpaces = async () => {
const response = await fetch(`${BACKEND_URL}/api/spaces`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (response.status === 401) {
showLoginToast();
return;
}
if (response.status === 401) {
showLoginToast();
return;
}
try {
const data = await response.json();
setSpacesOptions(data.data);
} catch (e) {
console.error(
`Error in supermemory.ai extension: ${e}. Please contact the developer https://x.com/dhravyashah`,
);
}
};
try {
const data = await response.json();
setSpacesOptions(data.data);
} catch (e) {
console.error(
`Error in supermemory.ai extension: ${e}. Please contact the developer https://x.com/dhravyashah`,
);
}
};
async function sendUrlToAPI(spaces: string[]) {
setLoading(true);
async function sendUrlToAPI(spaces: string[]) {
setLoading(true);
setTimeout(() => {
setLoading(false);
}, 1500);
setTimeout(() => {
setLoading(false);
}, 1500);
// get the current URL
const url = window.location.href;
// get the current URL
const url = window.location.href;
const blacklist: string[] = [];
// check if the URL is blacklisted
if (blacklist.some((blacklisted) => url.includes(blacklisted))) {
return;
} else {
const clone = document.cloneNode(true) as Document;
const article = new Readability(clone).parse();
const blacklist: string[] = [];
// check if the URL is blacklisted
if (blacklist.some((blacklisted) => url.includes(blacklisted))) {
return;
} else {
const clone = document.cloneNode(true) as Document;
const article = new Readability(clone).parse();
const ogImage = document
.querySelector('meta[property="og:image"]')
?.getAttribute("content");
const ogImage = document
.querySelector('meta[property="og:image"]')
?.getAttribute("content");
const favicon = (
document.querySelector('link[rel="icon"]') as HTMLLinkElement
)?.href;
const favicon = (
document.querySelector('link[rel="icon"]') as HTMLLinkElement
)?.href;
setLoading(true);
setLoading(true);
setIsPopoverOpen(false);
setIsPopoverOpen(false);
await fetch(`${BACKEND_URL}/api/store`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
pageContent:
(webNote ? `Note about this website: ${webNote}\n\n` : "") +
article?.textContent,
url: url + "#supermemory-user-" + Math.random(),
title: article?.title.slice(0, 500),
spaces: spaces,
description: article?.excerpt.slice(0, 250),
ogImage: ogImage?.slice(0, 1000),
image: favicon,
}),
}).then(async (rep) => {
if (rep.status === 401) {
showLoginToast();
return;
}
await fetch(`${BACKEND_URL}/api/store`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
pageContent:
(webNote ? `Note about this website: ${webNote}\n\n` : "") +
article?.textContent,
url: url + "#supermemory-user-" + Math.random(),
title: article?.title.slice(0, 500),
spaces: spaces,
description: article?.excerpt.slice(0, 250),
ogImage: ogImage?.slice(0, 1000),
image: favicon,
}),
}).then(async (rep) => {
if (rep.status === 401) {
showLoginToast();
return;
}
const d = await rep.json();
const d = await rep.json();
if (rep.status === 200) {
toast({
title: "Saved to supermemory.ai",
});
} else {
toast({
title: `Failed to save to supermemory.ai: ${d.error ?? "Unknown error"}`,
});
}
setLoading(false);
return rep;
});
}
}
if (rep.status === 200) {
toast({
title: "Saved to supermemory.ai",
});
} else {
toast({
title: `Failed to save to supermemory.ai: ${d.error ?? "Unknown error"}`,
});
}
setLoading(false);
return rep;
});
}
}
if (!shadowRoot || !portalContainer) {
return null;
}
if (!shadowRoot || !portalContainer) {
return null;
}
return (
<div className="flex justify-end items-end min-h-screen h-full w-full">
<Toaster />
return (
<div className="flex justify-end items-end min-h-screen h-full w-full">
<Toaster />
<Popover
open={isPopoverOpen}
onOpenChange={() => setIsPopoverOpen(!isPopoverOpen)}
>
<TooltipProvider>
<Tooltip>
<TooltipTrigger onClick={async () => await getSpaces()} asChild>
<PopoverTrigger
className={`${hover || isPopoverOpen ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-20 items-center text-lg`}
>
<svg
className={`w-full h-full size-8 ${loading && "animate-spin"}`}
width={24}
height={24}
viewBox="0 0 42 42"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19.0357 8C20.5531 8 21 9.27461 21 10.8438V16.3281H23.5536V14.2212C23.5536 13.1976 23.9468 12.216 24.6467 11.4922L25.0529 11.0721C24.9729 10.8772 24.9286 10.6627 24.9286 10.4375C24.9286 9.54004 25.6321 8.8125 26.5 8.8125C27.3679 8.8125 28.0714 9.54004 28.0714 10.4375C28.0714 11.335 27.3679 12.0625 26.5 12.0625C26.2822 12.0625 26.0748 12.0167 25.8863 11.9339L25.4801 12.354C25.0012 12.8492 24.7321 13.5209 24.7321 14.2212V16.3281H28.9714C29.2045 15.7326 29.7691 15.3125 30.4286 15.3125C31.2964 15.3125 32 16.04 32 16.9375C32 17.835 31.2964 18.5625 30.4286 18.5625C29.7691 18.5625 29.2045 18.1424 28.9714 17.5469H21V21.2031H25.0428C25.2759 20.6076 25.8405 20.1875 26.5 20.1875C27.3679 20.1875 28.0714 20.915 28.0714 21.8125C28.0714 22.71 27.3679 23.4375 26.5 23.4375C25.8405 23.4375 25.2759 23.0174 25.0428 22.4219H21V26.0781H24.4125C25.4023 26.0781 26.3516 26.4847 27.0515 27.2085L29.0292 29.2536C29.2177 29.1708 29.4251 29.125 29.6429 29.125C30.5107 29.125 31.2143 29.8525 31.2143 30.75C31.2143 31.6475 30.5107 32.375 29.6429 32.375C28.775 32.375 28.0714 31.6475 28.0714 30.75C28.0714 30.5248 28.1157 30.3103 28.1958 30.1154L26.2181 28.0703C25.7392 27.5751 25.0897 27.2969 24.4125 27.2969H21V31.1562C21 32.7254 20.5531 34 19.0357 34C17.6165 34 16.4478 32.8879 16.3004 31.4559C16.0451 31.527 15.775 31.5625 15.5 31.5625C13.7665 31.5625 12.3571 30.1051 12.3571 28.3125C12.3571 27.9367 12.421 27.5711 12.5339 27.2359C11.0509 26.657 10 25.1742 10 23.4375C10 21.8176 10.9183 20.416 12.2491 19.766C11.8219 19.2125 11.5714 18.5117 11.5714 17.75C11.5714 16.191 12.6321 14.891 14.0464 14.5711C13.9679 14.2918 13.9286 13.9922 13.9286 13.6875C13.9286 12.1691 14.9402 10.8895 16.3004 10.534C16.4478 9.11211 17.6165 8 19.0357 8Z"
fill={loading ? "gray" : "#fff"}
/>
</svg>
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent side="left">
{userNotLoggedIn ? (
<>You need to login to use this extension.</>
) : (
<p>Add to supermemory.ai</p>
)}
</TooltipContent>
</Tooltip>
</TooltipProvider>
<PopoverContent
key={userNotLoggedIn ? "login" : "spaces"}
container={portalContainer}
>
{userNotLoggedIn ? (
<div className="flex flex-col gap-2">
<button
onClick={() => {
window.open("https://supermemory.ai/signin", "_blank");
}}
className="bg-slate-700 text-white p-2 rounded-md"
>
Login to supermemory.ai
</button>
</div>
) : (
<div className="flex flex-col gap-2">
<Select onValueChange={(value) => setSelectedSpace(value)}>
<SelectTrigger className="text-white">
<SelectValue
className="placeholder:font-semibold placeholder:text-white"
placeholder="Select a space"
/>
</SelectTrigger>
<SelectContent container={portalContainer}>
<SelectGroup>
<SelectLabel>Your spaces</SelectLabel>
{spacesOptions.map((space) => (
<SelectItem key={space.id} value={`${space.id}`}>
{space.name}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<Popover
open={isPopoverOpen}
onOpenChange={() => setIsPopoverOpen(!isPopoverOpen)}
>
<TooltipProvider>
<Tooltip>
<TooltipTrigger onClick={async () => await getSpaces()} asChild>
<PopoverTrigger
className={`${hover || isPopoverOpen ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-20 items-center text-lg`}
>
<svg
className={`w-full h-full size-8 ${loading && "animate-spin"}`}
width={24}
height={24}
viewBox="0 0 42 42"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19.0357 8C20.5531 8 21 9.27461 21 10.8438V16.3281H23.5536V14.2212C23.5536 13.1976 23.9468 12.216 24.6467 11.4922L25.0529 11.0721C24.9729 10.8772 24.9286 10.6627 24.9286 10.4375C24.9286 9.54004 25.6321 8.8125 26.5 8.8125C27.3679 8.8125 28.0714 9.54004 28.0714 10.4375C28.0714 11.335 27.3679 12.0625 26.5 12.0625C26.2822 12.0625 26.0748 12.0167 25.8863 11.9339L25.4801 12.354C25.0012 12.8492 24.7321 13.5209 24.7321 14.2212V16.3281H28.9714C29.2045 15.7326 29.7691 15.3125 30.4286 15.3125C31.2964 15.3125 32 16.04 32 16.9375C32 17.835 31.2964 18.5625 30.4286 18.5625C29.7691 18.5625 29.2045 18.1424 28.9714 17.5469H21V21.2031H25.0428C25.2759 20.6076 25.8405 20.1875 26.5 20.1875C27.3679 20.1875 28.0714 20.915 28.0714 21.8125C28.0714 22.71 27.3679 23.4375 26.5 23.4375C25.8405 23.4375 25.2759 23.0174 25.0428 22.4219H21V26.0781H24.4125C25.4023 26.0781 26.3516 26.4847 27.0515 27.2085L29.0292 29.2536C29.2177 29.1708 29.4251 29.125 29.6429 29.125C30.5107 29.125 31.2143 29.8525 31.2143 30.75C31.2143 31.6475 30.5107 32.375 29.6429 32.375C28.775 32.375 28.0714 31.6475 28.0714 30.75C28.0714 30.5248 28.1157 30.3103 28.1958 30.1154L26.2181 28.0703C25.7392 27.5751 25.0897 27.2969 24.4125 27.2969H21V31.1562C21 32.7254 20.5531 34 19.0357 34C17.6165 34 16.4478 32.8879 16.3004 31.4559C16.0451 31.527 15.775 31.5625 15.5 31.5625C13.7665 31.5625 12.3571 30.1051 12.3571 28.3125C12.3571 27.9367 12.421 27.5711 12.5339 27.2359C11.0509 26.657 10 25.1742 10 23.4375C10 21.8176 10.9183 20.416 12.2491 19.766C11.8219 19.2125 11.5714 18.5117 11.5714 17.75C11.5714 16.191 12.6321 14.891 14.0464 14.5711C13.9679 14.2918 13.9286 13.9922 13.9286 13.6875C13.9286 12.1691 14.9402 10.8895 16.3004 10.534C16.4478 9.11211 17.6165 8 19.0357 8Z"
fill={loading ? "gray" : "#fff"}
/>
</svg>
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent side="left">
{userNotLoggedIn ? (
<>You need to login to use this extension.</>
) : (
<p>Add to supermemory.ai</p>
)}
</TooltipContent>
</Tooltip>
</TooltipProvider>
<PopoverContent
key={userNotLoggedIn ? "login" : "spaces"}
container={portalContainer}
>
{userNotLoggedIn ? (
<div className="flex flex-col gap-2">
<button
onClick={() => {
window.open("https://supermemory.ai/signin", "_blank");
}}
className="bg-slate-700 text-white p-2 rounded-md"
>
Login to supermemory.ai
</button>
</div>
) : (
<div className="flex flex-col gap-2">
<Select onValueChange={(value) => setSelectedSpace(value)}>
<SelectTrigger className="text-white">
<SelectValue
className="placeholder:font-semibold placeholder:text-white"
placeholder="Select a space"
/>
</SelectTrigger>
<SelectContent container={portalContainer}>
<SelectGroup>
<SelectLabel>Your spaces</SelectLabel>
{spacesOptions.map((space) => (
<SelectItem key={space.id} value={`${space.id}`}>
{space.name}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<Label className="text-slate-400" htmlFor="input-note">
Add a note
</Label>
<Textarea
value={webNote}
onChange={(e) => setWebNote(e.target.value)}
placeholder="Add a note"
className="text-white"
id="input-note"
/>
<Label className="text-slate-400" htmlFor="input-note">
Add a note
</Label>
<Textarea
value={webNote}
onChange={(e) => setWebNote(e.target.value)}
placeholder="Add a note"
className="text-white"
id="input-note"
/>
<button
onClick={async () => {
await sendUrlToAPI(selectedSpace ? [selectedSpace] : []);
}}
className="bg-slate-700 text-white p-2 rounded-md"
>
Add to{" "}
{selectedSpace
? spacesOptions.find((s) => s.id === parseInt(selectedSpace))
?.name
: "supermemory.ai"}
</button>
</div>
)}
</PopoverContent>
</Popover>
<button
onClick={async () => {
await sendUrlToAPI(selectedSpace ? [selectedSpace] : []);
}}
className="bg-slate-700 text-white p-2 rounded-md"
>
Add to{" "}
{selectedSpace
? spacesOptions.find((s) => s.id === parseInt(selectedSpace))
?.name
: "supermemory.ai"}
</button>
</div>
)}
</PopoverContent>
</Popover>
{(window.location.host === "twitter.com" ||
window.location.host === "x.com") && (
<Popover open={isPopover2Open} onOpenChange={setIsPopover2Open}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<PopoverTrigger
className={`${hover || isPopover2Open ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-6 items-center text-lg`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="size-8"
>
<path d="M12 1.5a.75.75 0 0 1 .75.75V7.5h-1.5V2.25A.75.75 0 0 1 12 1.5ZM11.25 7.5v5.69l-1.72-1.72a.75.75 0 0 0-1.06 1.06l3 3a.75.75 0 0 0 1.06 0l3-3a.75.75 0 1 0-1.06-1.06l-1.72 1.72V7.5h3.75a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3h-9a3 3 0 0 1-3-3v-9a3 3 0 0 1 3-3h3.75Z" />
</svg>
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent side="left">
{userNotLoggedIn ? (
<>You need to login to use this extension.</>
) : (
<p>Import all twitter bookmarks</p>
)}
</TooltipContent>
</Tooltip>
</TooltipProvider>
<PopoverContent
key={userNotLoggedIn ? "login" : "spaces"}
container={portalContainer}
>
{userNotLoggedIn ? (
<div className="flex flex-col gap-2">
<button
onClick={() => {
window.open("https://supermemory.ai/signin", "_blank");
}}
className="bg-slate-700 text-white p-2 rounded-md"
>
Login to supermemory.ai
</button>
</div>
) : (
<div className="flex flex-col gap-2">
<button
disabled={isImporting}
onClick={async () => {
setIsImporting(true);
chrome.runtime.sendMessage({ type: "batchImportAll" });
}}
className="bg-slate-700 text-white p-2 rounded-md disabled:bg-slate-700/50 disabled:pointer-events-none"
>
Import all Twitter bookmarks
</button>
{(window.location.host === "twitter.com" ||
window.location.host === "x.com") && (
<Popover open={isPopover2Open} onOpenChange={setIsPopover2Open}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<PopoverTrigger
className={`${hover || isPopover2Open ? "opacity-100" : "opacity-75 pointer-events-none translate-x-3/4"} focus-within:translate-x-0 focus-visible:translate-x-0 size-12 hover:bg-black p-2 rounded-l-2xl transition bg-secondary border-2 border-border opacity-0 absolute flex bottom-6 items-center text-lg`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="size-8"
>
<path d="M12 1.5a.75.75 0 0 1 .75.75V7.5h-1.5V2.25A.75.75 0 0 1 12 1.5ZM11.25 7.5v5.69l-1.72-1.72a.75.75 0 0 0-1.06 1.06l3 3a.75.75 0 0 0 1.06 0l3-3a.75.75 0 1 0-1.06-1.06l-1.72 1.72V7.5h3.75a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3h-9a3 3 0 0 1-3-3v-9a3 3 0 0 1 3-3h3.75Z" />
</svg>
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent side="left">
{userNotLoggedIn ? (
<>You need to login to use this extension.</>
) : (
<p>Import all twitter bookmarks</p>
)}
</TooltipContent>
</Tooltip>
</TooltipProvider>
<PopoverContent
key={userNotLoggedIn ? "login" : "spaces"}
container={portalContainer}
>
{userNotLoggedIn ? (
<div className="flex flex-col gap-2">
<button
onClick={() => {
window.open("https://supermemory.ai/signin", "_blank");
}}
className="bg-slate-700 text-white p-2 rounded-md"
>
Login to supermemory.ai
</button>
</div>
) : (
<div className="flex flex-col gap-2">
<button
disabled={isImporting}
onClick={async () => {
setIsImporting(true);
chrome.runtime.sendMessage({ type: "batchImportAll" });
}}
className="bg-slate-700 text-white p-2 rounded-md disabled:bg-slate-700/50 disabled:pointer-events-none"
>
Import all Twitter bookmarks
</button>
{isImporting && (
<div className="flex items-center gap-2">
<p>Imported {importedCount} bookmarks</p>
<svg
className="animate-spin w-6 h-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/>
</svg>
</div>
)}
{isImporting && (
<div className="flex items-center gap-2">
<p>Imported {importedCount} bookmarks</p>
<svg
className="animate-spin w-6 h-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/>
</svg>
</div>
)}
{importDone && (
<p className="text-green-500">
All your twitter bookmarks have been imported!
</p>
)}
</div>
)}
</PopoverContent>
</Popover>
)}
</div>
);
{importDone && (
<p className="text-green-500">
All your twitter bookmarks have been imported!
</p>
)}
</div>
)}
</PopoverContent>
</Popover>
)}
</div>
);
}

View file

@ -1,12 +1,12 @@
import React from 'react';
import { Toaster } from '@repo/ui/shadcn/sonner';
import React from "react";
import { Toaster } from "@repo/ui/shadcn/sonner";
function Layout({ children }: { children: React.ReactNode }) {
return (
<div>
{children} <Toaster />
</div>
);
return (
<div>
{children} <Toaster />
</div>
);
}
export default Layout;

View file

@ -24,7 +24,7 @@ export default function Home() {
useEffect(() => {
const updateDb = async () => {
await completeOnboarding();
}
};
if (currStep > 3) {
updateDb().then(() => {
push("/home?q=what%20is%20supermemory");
@ -389,7 +389,7 @@ function Navbar() {
const handleSkip = async () => {
await completeOnboarding();
router.push("/home?q=what%20is%20supermemory");
}
};
return (
<div className="flex items-center justify-between p-4 fixed top-0 left-0 w-full">
@ -399,7 +399,9 @@ function Navbar() {
className="hover:brightness-125 duration-200 size-12"
/>
<button className="text-sm" onClick={handleSkip}>Skip</button>
<button className="text-sm" onClick={handleSkip}>
Skip
</button>
</div>
);
}

View file

@ -5,13 +5,18 @@ export default function SignOutButton() {
return (
<form
action={async () => {
"use server"
await signOut()
"use server";
await signOut();
}}
>
<Button variant="ghost" size="sm" type="submit" className="text-[#7D8994]">
<Button
variant="ghost"
size="sm"
type="submit"
className="text-[#7D8994]"
>
Sign Out
</Button>
</form>
);
}
}

View file

@ -63,8 +63,8 @@ export function FilterSpaces({
onKeyDown={handleKeyDown}
className="text-white peer placeholder:text-white"
onChangeCapture={(e: React.ChangeEvent<HTMLInputElement>) =>
setInput(e.target.value)
}
setInput(e.target.value)
}
value={input}
/>
</div>

View file

@ -1,16 +1,16 @@
import { Loader, Loader2 } from "lucide-react";
const Generating = ({ className }: { className?: string }) => {
return (
<div
className={`flex items-center md:h-[3.5rem] px-6 bg-n-8/80 rounded-[1.7rem] ${
className || ""
} text-base`}
>
<Loader2 className="w-5 h-5 mr-2" />
Searching your second brain...
</div>
);
return (
<div
className={`flex items-center md:h-[3.5rem] px-6 bg-n-8/80 rounded-[1.7rem] ${
className || ""
} text-base`}
>
<Loader2 className="w-5 h-5 mr-2" />
Searching your second brain...
</div>
);
};
export default Generating;

View file

@ -5,219 +5,219 @@ import Image from "next/image";
import { AnimatedBeamShow } from "../CardPatterns/AnimatedBeamWithOutput";
const Services = () => {
return (
<div id="how-to-use">
<div className="container">
<div className="mr-auto max-w-5xl">
<h1 className="mr-auto text-left font-geistSans tracking-tighter text-4xl md:text-5xl lg:text-6xl text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Sounds super cool? There's more.
</h1>
<p className="mb-10 ml-auto text-lg tracking-tight text-left font-nomral"></p>
</div>
return (
<div id="how-to-use">
<div className="container">
<div className="mr-auto max-w-5xl">
<h1 className="mr-auto text-left font-geistSans tracking-tighter text-4xl md:text-5xl lg:text-6xl text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Sounds super cool? There's more.
</h1>
<p className="mb-10 ml-auto text-lg tracking-tight text-left font-nomral"></p>
</div>
<div className="relative bg-page-gradient">
<div className="flex overflow-hidden relative items-stretch p-8 mb-5 rounded-3xl border lg:p-20 z-1 h-[55rem] md:h-[45rem] border-white/20 xl:h-[46rem]">
<img
src="/images/tailwind-bg-gradient.avif"
className="absolute top-0 right-0 opacity-100 z-2"
/>
<img
src="/images/tailwind-bg-gradient.avif"
className="absolute top-0 right-0 opacity-100 z-2"
/>
<div className="absolute top-0 left-0 w-full h-full md:w-3/5 xl:w-auto">
<img
className="object-cover w-full h-full md:object-right"
width={800}
alt="Smartest AI"
height={730}
src={"/images/service-1.png"}
/>
</div>
<div className="relative bg-page-gradient">
<div className="flex overflow-hidden relative items-stretch p-8 mb-5 rounded-3xl border lg:p-20 z-1 h-[55rem] md:h-[45rem] border-white/20 xl:h-[46rem]">
<img
src="/images/tailwind-bg-gradient.avif"
className="absolute top-0 right-0 opacity-100 z-2"
/>
<img
src="/images/tailwind-bg-gradient.avif"
className="absolute top-0 right-0 opacity-100 z-2"
/>
<div className="absolute top-0 left-0 w-full h-full md:w-3/5 xl:w-auto">
<img
className="object-cover w-full h-full md:object-right"
width={800}
alt="Smartest AI"
height={730}
src={"/images/service-1.png"}
/>
</div>
<div className="relative ml-auto z-1 max-w-[17rem]">
<h4 className="mb-4 text-3xl md:text-4xl">
We paid attention to details.
</h4>
<p className="body-2 mb-[3rem] text-n-3">
a small team of 4 student developers who have one mission.{" "}
<br />
Make the best second brain for everyone.
</p>
<ul className="text-lg">
{supermemoryPoints.map((item, index) => (
<li
key={index}
className="flex items-start py-4 border-t border-white/20"
>
<CheckIcon className="inline-flex justify-center items-center mt-2 ml-2 w-4 h-4 rounded-full text-slate-200 size-4" />
{/* <img width={24} height={24} src={check} /> */}
<p className="ml-4">{item}</p>
</li>
))}
</ul>
</div>
<div className="relative ml-auto z-1 max-w-[17rem]">
<h4 className="mb-4 text-3xl md:text-4xl">
We paid attention to details.
</h4>
<p className="body-2 mb-[3rem] text-n-3">
a small team of 4 student developers who have one mission.{" "}
<br />
Make the best second brain for everyone.
</p>
<ul className="text-lg">
{supermemoryPoints.map((item, index) => (
<li
key={index}
className="flex items-start py-4 border-t border-white/20"
>
<CheckIcon className="inline-flex justify-center items-center mt-2 ml-2 w-4 h-4 rounded-full text-slate-200 size-4" />
{/* <img width={24} height={24} src={check} /> */}
<p className="ml-4">{item}</p>
</li>
))}
</ul>
</div>
<Generating className="absolute right-4 bottom-4 left-4 border lg:bottom-8 lg-right-auto lg:left-1/2 lg:-translate-x-1/2 border-n-1/10" />
</div>
<Generating className="absolute right-4 bottom-4 left-4 border lg:bottom-8 lg-right-auto lg:left-1/2 lg:-translate-x-1/2 border-n-1/10" />
</div>
<div className="grid relative gap-5 lg:grid-cols-2 z-1">
<div className="overflow-hidden flex flex-col md:flex-row md:block relative rounded-3xl border min-h-[34rem] bg-hero-gradient bg-slate-950/10 border-white/10">
<div className="md:absolute inset-0">
<div className="absolute -z-1 inset-0 h-[600px] w-full bg-transparent opacity-5 bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
<div className="grid relative gap-5 lg:grid-cols-2 z-1">
<div className="overflow-hidden flex flex-col md:flex-row md:block relative rounded-3xl border min-h-[34rem] bg-hero-gradient bg-slate-950/10 border-white/10">
<div className="md:absolute inset-0">
<div className="absolute -z-1 inset-0 h-[600px] w-full bg-transparent opacity-5 bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
<Image
src="/images/landing_integrations.png"
className="object-contain w-full h-full"
width={630}
height={750}
alt="robot"
/>
</div>
<Image
src="/images/landing_integrations.png"
className="object-contain w-full h-full"
width={630}
height={750}
alt="robot"
/>
</div>
<div className="flex md:absolute md:mt-4 lg:-mt-20 inset-0 flex-col md:justify-end justify-center items-center md:items-start p-8 bg-glass-gradient">
<h4 className="text-3xl tracking-tight mb-2 text-center text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Supermemory works everywhere you are.
</h4>
<p className="max-w-lg text-lg font-normal tracking-tighter text-gray-400 mb-[3rem]">
We already have integrations for Telegram and Twitter (X),
with whatsapp and SMS coming soon. So you can add and query
data in a private manner, from anywhere.
</p>
<a
href="/signin"
className="inline-flex justify-center items-center py-4 px-10 w-full text-center bg-transparent bg-gradient-to-tr to-transparent rounded-xl transition-colors sm:w-auto mt-[-20px] bg-glass-gradient group from-zinc-300/5 via-gray-400/5 border-white/10 border-[1px] hover:bg-transparent/10"
>
Get started
<ChevronRight className="ml-2 w-4 h-4 duration-300 group-hover:translate-x-1" />
</a>
</div>
</div>
<div className="flex md:absolute md:mt-4 lg:-mt-20 inset-0 flex-col md:justify-end justify-center items-center md:items-start p-8 bg-glass-gradient">
<h4 className="text-3xl tracking-tight mb-2 text-center text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Supermemory works everywhere you are.
</h4>
<p className="max-w-lg text-lg font-normal tracking-tighter text-gray-400 mb-[3rem]">
We already have integrations for Telegram and Twitter (X),
with whatsapp and SMS coming soon. So you can add and query
data in a private manner, from anywhere.
</p>
<a
href="/signin"
className="inline-flex justify-center items-center py-4 px-10 w-full text-center bg-transparent bg-gradient-to-tr to-transparent rounded-xl transition-colors sm:w-auto mt-[-20px] bg-glass-gradient group from-zinc-300/5 via-gray-400/5 border-white/10 border-[1px] hover:bg-transparent/10"
>
Get started
<ChevronRight className="ml-2 w-4 h-4 duration-300 group-hover:translate-x-1" />
</a>
</div>
</div>
<div
style={{
background:
"linear-gradient(143.6deg, rgba(192, 132, 252, 0) 20.79%, rgba(140, 121, 249, 0.3) 60.92%, rgba(140, 121, 249, 0) 80.35%)",
}}
className="overflow-hidden relative py-4 rounded-3xl group bg-glass-gradient lg:min-h-[30rem]"
>
<div className="relative py-12 px-4 xl:px-8">
<h4 className="text-3xl tracking-tight mb-2 text-left text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Privacy First
</h4>
<p className="text-lg text-gray-400 body-2 mb-[2rem]">
We use state-of-the art technology and providers to make sure
that your data is completely safe and secure, and only store
what's absolutely needed.
</p>
</div>
<div
style={{
background:
"linear-gradient(143.6deg, rgba(192, 132, 252, 0) 20.79%, rgba(140, 121, 249, 0.3) 60.92%, rgba(140, 121, 249, 0) 80.35%)",
}}
className="overflow-hidden relative py-4 rounded-3xl group bg-glass-gradient lg:min-h-[30rem]"
>
<div className="relative py-12 px-4 xl:px-8">
<h4 className="text-3xl tracking-tight mb-2 text-left text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Privacy First
</h4>
<p className="text-lg text-gray-400 body-2 mb-[2rem]">
We use state-of-the art technology and providers to make sure
that your data is completely safe and secure, and only store
what's absolutely needed.
</p>
</div>
<div className="overflow-hidden relative rounded-xl h-[20rem] md:h-[25rem]">
<img
src={"/images/landing_vault.png"}
className="object-cover w-full h-full transition-all duration-500 ease-linear transform group-hover:rotate-3"
width={520}
height={400}
alt="vault image"
/>
</div>
<div className="overflow-hidden relative rounded-xl h-[20rem] md:h-[25rem]">
<img
src={"/images/landing_vault.png"}
className="object-cover w-full h-full transition-all duration-500 ease-linear transform group-hover:rotate-3"
width={520}
height={400}
alt="vault image"
/>
</div>
<Gradient opacity={5} />
</div>
</div>
<Gradient opacity={5} />
</div>
</div>
<div
style={{
background:
"linear-gradient(143.6deg, rgba(192, 132, 252, 0) 20.79%, rgba(140, 121, 249, 0.2) 40.92%, rgba(140, 121, 249, 0) 80.35%)",
}}
className="flex overflow-hidden relative items-center p-8 mt-5 mb-5 rounded-3xl border lg:p-20 bg-page-gradient z-1 h-[38rem] border-white/20 xl:h-[28rem] dark:[box-shadow:0_-20px_80px_-20px_#8686f01f_inset]"
>
<img
src="/images/tailwind-bg-gradient.avif"
className="absolute top-0 right-0 opacity-60 z-2"
/>
<div
style={{
background:
"linear-gradient(143.6deg, rgba(192, 132, 252, 0) 20.79%, rgba(140, 121, 249, 0.2) 40.92%, rgba(140, 121, 249, 0) 80.35%)",
}}
className="flex overflow-hidden relative items-center p-8 mt-5 mb-5 rounded-3xl border lg:p-20 bg-page-gradient z-1 h-[38rem] border-white/20 xl:h-[28rem] dark:[box-shadow:0_-20px_80px_-20px_#8686f01f_inset]"
>
<img
src="/images/tailwind-bg-gradient.avif"
className="absolute top-0 right-0 opacity-60 z-2"
/>
<div className="absolute top-0 right-0 left-0 mx-auto w-full h-full xl:w-auto">
<img
className="object-cover z-40 w-full h-full border-r-2 md:scale-110 border-r-white/5"
width={800}
alt="Github"
height={730}
src={"/images/github.webp"}
/>
</div>
<div className="absolute top-0 right-0 left-0 mx-auto w-full h-full xl:w-auto">
<img
className="object-cover z-40 w-full h-full border-r-2 md:scale-110 border-r-white/5"
width={800}
alt="Github"
height={730}
src={"/images/github.webp"}
/>
</div>
<div className="absolute right-0 left-0 bottom-5 mx-auto mt-20 text-center z-1 p-8">
<h4 className="mb-4 text-4xl tracking-tighter text-white lg:text-5xl">
Proudly <br /> Open Source
</h4>
<p className="text-lg body-2 mb-[3rem] ">
You dont even need to trust us. Just deploy it yourself and
enjoy the benefits.
</p>
<a
href="https://git.new/memory"
className="inline-flex gap-x-1 justify-center items-center py-4 px-10 text-center bg-transparent bg-gradient-to-tr to-transparent rounded-xl transition-colors sm:w-auto w-fit mt-[-20px] bg-glass-gradient group from-zinc-300/5 via-gray-400/5 border-white/10 border-[1px] hover:bg-transparent/10"
>
<GithubIcon className="inline-flex justify-center items-center w-5 h-5" />{" "}
Star us on Github
<ChevronRight className="ml-2 w-4 h-4 duration-300 group-hover:translate-x-1" />
</a>
</div>
</div>
<div className="absolute right-0 left-0 bottom-5 mx-auto mt-20 text-center z-1 p-8">
<h4 className="mb-4 text-4xl tracking-tighter text-white lg:text-5xl">
Proudly <br /> Open Source
</h4>
<p className="text-lg body-2 mb-[3rem] ">
You dont even need to trust us. Just deploy it yourself and
enjoy the benefits.
</p>
<a
href="https://git.new/memory"
className="inline-flex gap-x-1 justify-center items-center py-4 px-10 text-center bg-transparent bg-gradient-to-tr to-transparent rounded-xl transition-colors sm:w-auto w-fit mt-[-20px] bg-glass-gradient group from-zinc-300/5 via-gray-400/5 border-white/10 border-[1px] hover:bg-transparent/10"
>
<GithubIcon className="inline-flex justify-center items-center w-5 h-5" />{" "}
Star us on Github
<ChevronRight className="ml-2 w-4 h-4 duration-300 group-hover:translate-x-1" />
</a>
</div>
</div>
<div className="grid relative gap-5 lg:grid-cols-2 z-1">
<div className="overflow-hidden relative rounded-3xl border max-h-[20rem] min-h-[40rem] md:min-h-[33rem] bg-hero-gradient bg-slate-950/10 border-white/10">
<div className="absolute inset-0">
<AnimatedBeamShow />
</div>
<div className="grid relative gap-5 lg:grid-cols-2 z-1">
<div className="overflow-hidden relative rounded-3xl border max-h-[20rem] min-h-[40rem] md:min-h-[33rem] bg-hero-gradient bg-slate-950/10 border-white/10">
<div className="absolute inset-0">
<AnimatedBeamShow />
</div>
<div className="flex absolute inset-0 flex-col justify-end items-start p-8 pl-10 mt-4 lg:-mt-20 translate-y-10 md:translate-y-0 bg-glass-gradient">
<h4 className="text-3xl tracking-tight mb-2 text-center text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Bringing content in is easy.
</h4>
<p className="max-w-lg text-lg font-normal tracking-tighter text-gray-400 mb-[3rem]">
You can use our chrome extension, iOS shortcut, or our API to
send content to supermemory.
</p>
</div>
</div>
<div className="flex absolute inset-0 flex-col justify-end items-start p-8 pl-10 mt-4 lg:-mt-20 translate-y-10 md:translate-y-0 bg-glass-gradient">
<h4 className="text-3xl tracking-tight mb-2 text-center text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Bringing content in is easy.
</h4>
<p className="max-w-lg text-lg font-normal tracking-tighter text-gray-400 mb-[3rem]">
You can use our chrome extension, iOS shortcut, or our API to
send content to supermemory.
</p>
</div>
</div>
<div className="overflow-hidden bg-page-gradient relative py-4 rounded-3xl max-h-[33rem] group lg:min-h-[30rem]">
<div className="absolute -z-1 inset-0 h-[600px] w-full bg-transparent opacity-5 bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
<div className="overflow-hidden bg-page-gradient relative py-4 rounded-3xl max-h-[33rem] group lg:min-h-[30rem]">
<div className="absolute -z-1 inset-0 h-[600px] w-full bg-transparent opacity-5 bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:6rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
<div className="relative py-12 px-4 xl:px-8">
<h4 className="text-3xl tracking-tight mb-2 text-left text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Self hostable
</h4>
<p className="text-lg text-gray-400 body-2 mb-[2rem]">
All the code is open source and self hostable for
non-commercial use.
</p>
</div>
<div className="relative py-12 px-4 xl:px-8">
<h4 className="text-3xl tracking-tight mb-2 text-left text-transparent bg-clip-text bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)]">
Self hostable
</h4>
<p className="text-lg text-gray-400 body-2 mb-[2rem]">
All the code is open source and self hostable for
non-commercial use.
</p>
</div>
<div className="overflow-hidden relative mt-[-50px] mb-10 rounded-xl h-[20rem] md:h-[25rem]">
<img
src={
"https://www.koyeb.com/_next/image?url=%2Fimages%2Fillustrations%2Fhome-scale-mesh.webp&w=384&q=75"
}
className="object-cover w-full h-full transition-all duration-500 ease-linear transform group-hover:rotate-3"
width={1000}
height={1000}
alt="Scary robot"
/>
</div>
<div className="overflow-hidden relative mt-[-50px] mb-10 rounded-xl h-[20rem] md:h-[25rem]">
<img
src={
"https://www.koyeb.com/_next/image?url=%2Fimages%2Fillustrations%2Fhome-scale-mesh.webp&w=384&q=75"
}
className="object-cover w-full h-full transition-all duration-500 ease-linear transform group-hover:rotate-3"
width={1000}
height={1000}
alt="Scary robot"
/>
</div>
<Gradient opacity={5} />
</div>
</div>
<Gradient opacity={5} />
</div>
</div>
<Gradient />
</div>
</div>
</div>
);
<Gradient />
</div>
</div>
</div>
);
};
export default Services;

View file

@ -148,26 +148,26 @@ function Feature({
}
function FeaturesMobile() {
return (
<div className="-mx-4 mt-20 flex flex-col gap-y-10 overflow-hidden px-4 sm:-mx-6 sm:px-6 lg:hidden">
{features.map((feature) => (
<div key={feature.summary}>
<Feature feature={feature} className="mx-auto max-w-2xl" isActive />
<div className="relative mt-10 pb-10">
<div className="absolute -inset-x-4 bottom-0 top-8 bg-page-gradient sm:-inset-x-6" />
<div className="relative mx-auto lg:w-[52.75rem] md:w-[40rem] overflow-hidden rounded-xl bg-glass-gradient shadow-lg shadow-gray-200/5 ring-1 ring-slate-500/10">
<img
className="w-full"
src={`/images/${feature.image}`}
alt=""
sizes="52.75rem"
/>
</div>
</div>
</div>
))}
</div>
);
return (
<div className="-mx-4 mt-20 flex flex-col gap-y-10 overflow-hidden px-4 sm:-mx-6 sm:px-6 lg:hidden">
{features.map((feature) => (
<div key={feature.summary}>
<Feature feature={feature} className="mx-auto max-w-2xl" isActive />
<div className="relative mt-10 pb-10">
<div className="absolute -inset-x-4 bottom-0 top-8 bg-page-gradient sm:-inset-x-6" />
<div className="relative mx-auto lg:w-[52.75rem] md:w-[40rem] overflow-hidden rounded-xl bg-glass-gradient shadow-lg shadow-gray-200/5 ring-1 ring-slate-500/10">
<img
className="w-full"
src={`/images/${feature.image}`}
alt=""
sizes="52.75rem"
/>
</div>
</div>
</div>
))}
</div>
);
}
function FeaturesDesktop() {

View file

@ -345,13 +345,13 @@ export const createMemory = async (input: {
revalidatePath("/memories");
revalidatePath("/home");
if (!insertResponse[0]?.id) {
return {
success: false,
data: 0,
error: "Something went wrong while saving the document to the database",
};
}
if (!insertResponse[0]?.id) {
return {
success: false,
data: 0,
error: "Something went wrong while saving the document to the database",
};
}
contentId = insertResponse[0]?.id;
} catch (e) {

View file

@ -79,13 +79,13 @@ const createMemoryFromAPI = async (input: {
})
.returning({ id: storedContent.id });
if (!insertResponse[0]?.id) {
return {
success: false,
data: 0,
error: "Failed to save to database",
};
}
if (!insertResponse[0]?.id) {
return {
success: false,
data: 0,
error: "Failed to save to database",
};
}
contentId = insertResponse[0].id;
} catch (e) {

View file

@ -46,8 +46,8 @@ const ComboboxWithCreate: React.FC<ComboboxWithCreateProps> = ({
<Command className={cn("group", className)}>
<CommandInput
onChangeCapture={(e: React.ChangeEvent<HTMLInputElement>) =>
setInputValue(e.currentTarget.value)
}
setInputValue(e.currentTarget.value)
}
placeholder={placeholder}
value={inputValue}
/>

View file

@ -1,15 +1,15 @@
import { cn } from "@repo/ui/lib/utils"
import { cn } from "@repo/ui/lib/utils";
function Skeleton({
className,
...props
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
)
return (
<div
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
);
}
export { Skeleton }
export { Skeleton };

View file

@ -1,4 +1,4 @@
declare module "*.svg" {
const content: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
export default content;
}
const content: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
export default content;
}