mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-05-12 05:51:45 +00:00
resolved conflicts
This commit is contained in:
commit
6f4792cab8
11 changed files with 137 additions and 52 deletions
|
|
@ -79,7 +79,7 @@ function SideBar({ jwt }: { jwt: string }) {
|
|||
const fetchSpaces = async () => {
|
||||
setLoading(true);
|
||||
chrome.runtime.sendMessage({ type: "fetchSpaces" }, (resp) => {
|
||||
console.log(resp);
|
||||
console.log("response", resp);
|
||||
setSpaces(resp);
|
||||
setLoading(false);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -52,12 +52,13 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|||
const spaces = request.spaces(
|
||||
// eslint-disable-next-line no-unexpected-multiline
|
||||
async () => {
|
||||
chrome.storage.local.get(["jwt"], async ({ jwt }) => {
|
||||
chrome.storage.local.get(["jwt"], ({ jwt }) => {
|
||||
if (!jwt) {
|
||||
console.error("No JWT found");
|
||||
return;
|
||||
}
|
||||
await fetch(`${backendUrl}/api/spaces`, {
|
||||
fetch(`${backendUrl}/api/store`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwt}`,
|
||||
},
|
||||
|
|
@ -67,29 +68,26 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|||
},
|
||||
)();
|
||||
} else if (request.type === "fetchSpaces") {
|
||||
const run = () =>
|
||||
chrome.storage.local.get(["jwt"], async ({ jwt }) => {
|
||||
if (!jwt) {
|
||||
console.error("No JWT found");
|
||||
return;
|
||||
}
|
||||
const resp = await fetch(`${backendUrl}/api/spaces`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwt}`,
|
||||
},
|
||||
});
|
||||
|
||||
const data: {
|
||||
message: "OK" | string;
|
||||
data: Space[] | undefined;
|
||||
} = await resp.json();
|
||||
|
||||
if (data.message === "OK" && data.data) {
|
||||
sendResponse(data.data);
|
||||
}
|
||||
chrome.storage.local.get(["jwt"], async ({ jwt }) => {
|
||||
if (!jwt) {
|
||||
console.error("No JWT found");
|
||||
return;
|
||||
}
|
||||
const resp = await fetch(`${backendUrl}/api/spaces`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${jwt}`,
|
||||
},
|
||||
});
|
||||
|
||||
run();
|
||||
const data: {
|
||||
message: "OK" | string;
|
||||
data: Space[] | undefined;
|
||||
} = await resp.json();
|
||||
|
||||
if (data.message === "OK" && data.data) {
|
||||
sendResponse(data.data);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
} else if (request.type === "queryApi") {
|
||||
|
|
|
|||
5
apps/web/public/note.svg
Normal file
5
apps/web/public/note.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#6F6F6F" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-text w-10 h-10">
|
||||
<path d="M17 6.1H3"></path>
|
||||
<path d="M21 12.1H3">
|
||||
</path><path d="M15.1 18H3"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 310 B |
|
|
@ -1,3 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
|
||||
</svg>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 676 B After Width: | Height: | Size: 677 B |
|
|
@ -41,7 +41,8 @@ export async function searchMemoriesAndSpaces(
|
|||
eq(storedContent.user, user.id),
|
||||
like(storedContent.title, `%${query}%`),
|
||||
),
|
||||
);
|
||||
)
|
||||
.orderBy(asc(storedContent.savedAt));
|
||||
|
||||
const searchSpacesQuery = db
|
||||
.select({
|
||||
|
|
@ -50,10 +51,13 @@ export async function searchMemoriesAndSpaces(
|
|||
memory: sql`NULL`,
|
||||
})
|
||||
.from(space)
|
||||
.where(and(eq(space.user, user.id), like(space.name, `%${query}%`)));
|
||||
.where(and(eq(space.user, user.id), like(space.name, `%${query}%`)))
|
||||
.orderBy(asc(space.name));
|
||||
|
||||
let queries = [];
|
||||
|
||||
console.log("adding");
|
||||
|
||||
[undefined, true].includes(opts?.filter?.memories) &&
|
||||
queries.push(searchMemoriesQuery);
|
||||
[undefined, true].includes(opts?.filter?.spaces) &&
|
||||
|
|
@ -69,6 +73,8 @@ export async function searchMemoriesAndSpaces(
|
|||
|
||||
const data = await Promise.all(queries);
|
||||
|
||||
console.log("resp", data);
|
||||
|
||||
return data.reduce((acc, i) => [...acc, ...i]) as SearchResult[];
|
||||
} catch {
|
||||
return [];
|
||||
|
|
@ -183,7 +189,7 @@ export async function fetchContentForSpace(
|
|||
),
|
||||
),
|
||||
)
|
||||
.orderBy(asc(storedContent.title));
|
||||
.orderBy(asc(storedContent.savedAt));
|
||||
|
||||
return range
|
||||
? await query.limit(range.limit).offset(range.offset)
|
||||
|
|
@ -214,7 +220,7 @@ export async function fetchFreeMemories(range?: {
|
|||
eq(storedContent.user, user.id),
|
||||
),
|
||||
)
|
||||
.orderBy(asc(storedContent.title));
|
||||
.orderBy(asc(storedContent.savedAt));
|
||||
|
||||
return range
|
||||
? await query.limit(range.limit).offset(range.offset)
|
||||
|
|
@ -257,3 +263,37 @@ export async function addMemory(
|
|||
addedToSpaces,
|
||||
};
|
||||
}
|
||||
|
||||
export async function deleteSpace(id: number) {
|
||||
const user = await getUser();
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await db.delete(contentToSpace).where(eq(contentToSpace.spaceId, id));
|
||||
|
||||
const [deleted] = await db
|
||||
.delete(space)
|
||||
.where(and(eq(space.user, user.id), eq(space.id, id)))
|
||||
.returning();
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
export async function deleteMemory(id: number) {
|
||||
const user = await getUser();
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await db.delete(contentToSpace).where(eq(contentToSpace.contentId, id));
|
||||
|
||||
const [deleted] = await db
|
||||
.delete(storedContent)
|
||||
.where(and(eq(storedContent.user, user.id), eq(storedContent.id, id)))
|
||||
.returning();
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ import {
|
|||
} from "../../types/memory";
|
||||
import { MemoryProvider } from "@/contexts/MemoryContext";
|
||||
import Content from "./content";
|
||||
import { searchMemoriesAndSpaces } from "@/actions/db";
|
||||
import { getMetaData } from "@/server/helpers";
|
||||
|
||||
export const runtime = "edge";
|
||||
|
||||
|
|
|
|||
|
|
@ -324,12 +324,18 @@ export function MemorySelectedItem({
|
|||
id,
|
||||
title,
|
||||
url,
|
||||
type,
|
||||
image,
|
||||
onRemove,
|
||||
}: StoredContent & { onRemove: () => void }) {
|
||||
return (
|
||||
<div className="hover:bg-rgray-4 focus-within-bg-rgray-4 flex w-full items-center justify-start gap-2 rounded-md p-1 px-2 text-sm [&:hover>[data-icon]]:block [&:hover>img]:hidden">
|
||||
<img src={image ?? "/icons/logo_without_bg.png"} className="h-5 w-5" />
|
||||
<img
|
||||
src={
|
||||
type === "note" ? "/note.svg" : image ?? "/icons/logo_without_bg.png"
|
||||
}
|
||||
className="h-5 w-5"
|
||||
/>
|
||||
<button
|
||||
onClick={onRemove}
|
||||
data-icon
|
||||
|
|
@ -338,7 +344,9 @@ export function MemorySelectedItem({
|
|||
<X className="h-5 w-5 scale-90" />
|
||||
</button>
|
||||
<span>{title}</span>
|
||||
<span className="ml-auto block opacity-50">{cleanUrl(url)}</span>
|
||||
<span className="ml-auto block opacity-50">
|
||||
{type === "note" ? "Note" : cleanUrl(url)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,7 +180,6 @@ export function FilterMemories({
|
|||
const [isSearching, setIsSearching] = React.useState(false);
|
||||
|
||||
const results = React.useMemo(() => {
|
||||
console.log("use memo");
|
||||
return searchResults.map((r) => r.memory);
|
||||
}, [searchResults]);
|
||||
|
||||
|
|
@ -266,7 +265,11 @@ export function FilterMemories({
|
|||
>
|
||||
<div className="text-rgray-11">
|
||||
<img
|
||||
src={m.image ?? "/icons/logo_without_bg.png"}
|
||||
src={
|
||||
m.type === "note"
|
||||
? "/note.svg"
|
||||
: m.image ?? "/icons/logo_without_bg.png"
|
||||
}
|
||||
className="mr-2 h-4 w-4"
|
||||
/>
|
||||
{m.title}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ import { ExpandedSpace } from "./ExpandedSpace";
|
|||
import { StoredContent, StoredSpace } from "@/server/db/schema";
|
||||
import Image from "next/image";
|
||||
import { useDebounce } from "@/hooks/useDebounce";
|
||||
import { searchMemoriesAndSpaces } from "@/actions/db";
|
||||
|
||||
export function MemoriesBar() {
|
||||
const [parent, enableAnimations] = useAutoAnimate();
|
||||
|
|
@ -169,7 +168,7 @@ export function MemoriesBar() {
|
|||
<>
|
||||
{spaces.map((space) => (
|
||||
<SpaceItem
|
||||
onDelete={() => {}}
|
||||
onDelete={() => deleteSpace(space.id)}
|
||||
key={space.id}
|
||||
//onClick={() => setExpandedSpace(space.id)}
|
||||
{...space}
|
||||
|
|
@ -255,7 +254,6 @@ export function SpaceItem({
|
|||
}, [cachedMemories]);
|
||||
|
||||
const _name = name.length > 10 ? name.slice(0, 10) + "..." : name;
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
ref={itemRef}
|
||||
|
|
@ -355,19 +353,31 @@ export function SpaceItem({
|
|||
<MemoryWithImages3
|
||||
className="h-24 w-24"
|
||||
id={id.toString()}
|
||||
images={spaceMemories.map((c) => c.image).reverse() as string[]}
|
||||
images={
|
||||
spaceMemories
|
||||
.map((c) => (c.type === "note" ? "/note.svg" : c.image))
|
||||
.reverse() as string[]
|
||||
}
|
||||
/>
|
||||
) : spaceMemories.length > 1 ? (
|
||||
<MemoryWithImages2
|
||||
className="h-24 w-24"
|
||||
id={id.toString()}
|
||||
images={spaceMemories.map((c) => c.image).reverse() as string[]}
|
||||
images={
|
||||
spaceMemories
|
||||
.map((c) => (c.type === "note" ? "/note.svg" : c.image))
|
||||
.reverse() as string[]
|
||||
}
|
||||
/>
|
||||
) : spaceMemories.length === 1 ? (
|
||||
<MemoryWithImage
|
||||
className="h-24 w-24"
|
||||
id={id.toString()}
|
||||
image={spaceMemories[0].image!}
|
||||
image={
|
||||
spaceMemories[0].type === "note"
|
||||
? "/note.svg"
|
||||
: spaceMemories[0].image!
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div className="bg-rgray-4 shadow- h-24 w-24 scale-50 rounded-full opacity-30"></div>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import {
|
|||
searchMemoriesAndSpaces,
|
||||
addSpace,
|
||||
fetchContentForSpace,
|
||||
deleteSpace,
|
||||
deleteMemory,
|
||||
} from "@/actions/db";
|
||||
import { User } from "next-auth";
|
||||
|
||||
|
|
@ -23,20 +25,22 @@ export type SearchResult = {
|
|||
// temperory (will change)
|
||||
export const MemoryContext = React.createContext<{
|
||||
spaces: StoredSpace[];
|
||||
deleteSpace: (id: number) => Promise<void>;
|
||||
freeMemories: StoredContent[];
|
||||
addSpace: typeof addSpace;
|
||||
addMemory: typeof addMemory;
|
||||
cachedMemories: ChachedSpaceContent[];
|
||||
search: typeof searchMemoriesAndSpaces;
|
||||
deleteSpace: typeof deleteSpace;
|
||||
deleteMemory: typeof deleteMemory;
|
||||
}>({
|
||||
spaces: [],
|
||||
freeMemories: [],
|
||||
addMemory: (() => {}) as unknown as typeof addMemory,
|
||||
addSpace: (async () => {}) as unknown as typeof addSpace,
|
||||
deleteSpace: async () => {},
|
||||
cachedMemories: [],
|
||||
search: async () => [],
|
||||
deleteMemory: (() => {}) as unknown as typeof deleteMemory,
|
||||
deleteSpace: (() => {}) as unknown as typeof deleteSpace,
|
||||
});
|
||||
|
||||
export const MemoryProvider: React.FC<
|
||||
|
|
@ -61,8 +65,22 @@ export const MemoryProvider: React.FC<
|
|||
ChachedSpaceContent[]
|
||||
>(initialCachedMemories);
|
||||
|
||||
const deleteSpace = async (id: number) => {
|
||||
setSpaces((prev) => prev.filter((s) => s.id !== id));
|
||||
const _deleteSpace: typeof deleteSpace = async (...params) => {
|
||||
const deleted = (await deleteSpace(...params))!;
|
||||
|
||||
setSpaces((prev) => prev.filter((i) => i.id !== deleted.id));
|
||||
setCachedMemories((prev) => prev.filter((i) => i.space !== deleted.id));
|
||||
|
||||
return deleted;
|
||||
};
|
||||
|
||||
const _deleteMemory: typeof deleteMemory = async (...params) => {
|
||||
const deleted = (await deleteMemory(...params))!;
|
||||
|
||||
setCachedMemories((prev) => prev.filter((i) => i.id !== deleted.id));
|
||||
setFreeMemories((prev) => prev.filter((i) => i.id !== deleted.id));
|
||||
|
||||
return deleted;
|
||||
};
|
||||
|
||||
// const fetchMemories = useCallback(async (query: string) => {
|
||||
|
|
@ -115,9 +133,10 @@ export const MemoryProvider: React.FC<
|
|||
search: searchMemoriesAndSpaces,
|
||||
spaces,
|
||||
addSpace: _addSpace,
|
||||
deleteSpace,
|
||||
deleteSpace: _deleteSpace,
|
||||
freeMemories,
|
||||
cachedMemories,
|
||||
deleteMemory: _deleteMemory,
|
||||
addMemory: _addMemory,
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export const accounts = createTable(
|
|||
id: integer("id").notNull().primaryKey({ autoIncrement: true }),
|
||||
userId: text("userId", { length: 255 })
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
.references(() => users.id, { onDelete: "cascade" }),
|
||||
type: text("type", { length: 255 }).notNull(),
|
||||
provider: text("provider", { length: 255 }).notNull(),
|
||||
providerAccountId: text("providerAccountId", { length: 255 }).notNull(),
|
||||
|
|
@ -60,7 +60,7 @@ export const sessions = createTable(
|
|||
sessionToken: text("sessionToken", { length: 255 }).notNull(),
|
||||
userId: text("userId", { length: 255 })
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
.references(() => users.id, { onDelete: "cascade" }),
|
||||
expires: int("expires", { mode: "timestamp" }).notNull(),
|
||||
},
|
||||
(session) => ({
|
||||
|
|
@ -94,7 +94,9 @@ export const storedContent = createTable(
|
|||
"page",
|
||||
),
|
||||
image: text("image", { length: 255 }),
|
||||
user: text("user", { length: 255 }).references(() => users.id),
|
||||
user: text("user", { length: 255 }).references(() => users.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
},
|
||||
(sc) => ({
|
||||
urlIdx: index("storedContent_url_idx").on(sc.url),
|
||||
|
|
@ -109,10 +111,10 @@ export const contentToSpace = createTable(
|
|||
{
|
||||
contentId: integer("contentId")
|
||||
.notNull()
|
||||
.references(() => storedContent.id),
|
||||
.references(() => storedContent.id, { onDelete: "cascade" }),
|
||||
spaceId: integer("spaceId")
|
||||
.notNull()
|
||||
.references(() => space.id),
|
||||
.references(() => space.id, { onDelete: "cascade" }),
|
||||
},
|
||||
(cts) => ({
|
||||
compoundKey: primaryKey({ columns: [cts.contentId, cts.spaceId] }),
|
||||
|
|
@ -124,7 +126,9 @@ export const space = createTable(
|
|||
{
|
||||
id: integer("id").notNull().primaryKey({ autoIncrement: true }),
|
||||
name: text("name").notNull().unique().default("none"),
|
||||
user: text("user", { length: 255 }).references(() => users.id),
|
||||
user: text("user", { length: 255 }).references(() => users.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
},
|
||||
(space) => ({
|
||||
nameIdx: index("spaces_name_idx").on(space.name),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue