mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
Merge 1a5a57aa70 into 9652478093
This commit is contained in:
commit
243ca2dbf9
10 changed files with 68 additions and 51 deletions
|
|
@ -1612,11 +1612,11 @@ export function ChatSidebar({
|
|||
]
|
||||
for (const t of filtered) {
|
||||
const ts = new Date(t.updatedAt).getTime()
|
||||
if (ts >= startOfToday) buckets[0].items.push(t)
|
||||
else if (ts >= startOfToday - day) buckets[1].items.push(t)
|
||||
else if (ts >= startOfToday - 7 * day) buckets[2].items.push(t)
|
||||
else if (ts >= startOfToday - 30 * day) buckets[3].items.push(t)
|
||||
else buckets[4].items.push(t)
|
||||
if (ts >= startOfToday) buckets[0]?.items.push(t)
|
||||
else if (ts >= startOfToday - day) buckets[1]?.items.push(t)
|
||||
else if (ts >= startOfToday - 7 * day) buckets[2]?.items.push(t)
|
||||
else if (ts >= startOfToday - 30 * day) buckets[3]?.items.push(t)
|
||||
else buckets[4]?.items.push(t)
|
||||
}
|
||||
return buckets.filter((b) => b.items.length > 0)
|
||||
}, [threads, historySearch])
|
||||
|
|
|
|||
|
|
@ -67,15 +67,13 @@ export function StaticGraphPreview({
|
|||
const result: { x1: number; y1: number; x2: number; y2: number }[] = []
|
||||
const edgeCount = Math.min(nodes.length - 1, 20)
|
||||
for (let i = 0; i < edgeCount; i++) {
|
||||
const a = Math.floor(rand() * nodes.length)
|
||||
let b = Math.floor(rand() * nodes.length)
|
||||
if (b === a) b = (a + 1) % nodes.length
|
||||
result.push({
|
||||
x1: nodes[a]?.x,
|
||||
y1: nodes[a]?.y,
|
||||
x2: nodes[b]?.x,
|
||||
y2: nodes[b]?.y,
|
||||
})
|
||||
const aIdx = Math.floor(rand() * nodes.length)
|
||||
let bIdx = Math.floor(rand() * nodes.length)
|
||||
if (bIdx === aIdx) bIdx = (aIdx + 1) % nodes.length
|
||||
const a = nodes[aIdx]
|
||||
const b = nodes[bIdx]
|
||||
if (!a || !b) continue
|
||||
result.push({ x1: a.x, y1: a.y, x2: b.x, y2: b.y })
|
||||
}
|
||||
return result
|
||||
}, [nodes])
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ const INTEG: {
|
|||
key?: string
|
||||
label?: string
|
||||
sub?: string
|
||||
ring: number
|
||||
ring: 0 | 1
|
||||
ang: number
|
||||
size: number
|
||||
dim: boolean
|
||||
|
|
@ -76,8 +76,8 @@ const DW = 780
|
|||
const DH = 1024
|
||||
const CX = 390
|
||||
const CY = 512
|
||||
const RR = [200, 335]
|
||||
const SPEED = [1.0, 0.78]
|
||||
const RR: [number, number] = [200, 335]
|
||||
const SPEED: [number, number] = [1.0, 0.78]
|
||||
const DRAW: [number, number, number, string][] = [
|
||||
[125, 0.28, 1.7, "#74a8f6"],
|
||||
[200, 0.18, 1.9, "#4389ff"],
|
||||
|
|
@ -167,16 +167,15 @@ export default function OrbitMemory({
|
|||
track.setAttribute("stroke-opacity", "0")
|
||||
dtrack.setAttribute("stroke-opacity", "0")
|
||||
for (let k = 0; k < NC; k++) {
|
||||
cms[k].setAttribute("opacity", "0")
|
||||
cmgs[k].setAttribute("opacity", "0")
|
||||
oms[k].setAttribute("opacity", "0")
|
||||
omgs[k].setAttribute("opacity", "0")
|
||||
cms[k]?.setAttribute("opacity", "0")
|
||||
cmgs[k]?.setAttribute("opacity", "0")
|
||||
oms[k]?.setAttribute("opacity", "0")
|
||||
omgs[k]?.setAttribute("opacity", "0")
|
||||
}
|
||||
}
|
||||
let angle = 0
|
||||
const place = () => {
|
||||
for (let i = 0; i < INTEG.length; i++) {
|
||||
const it = INTEG[i]
|
||||
for (const [i, it] of INTEG.entries()) {
|
||||
const a = ((it.ang + angle * SPEED[it.ring]) * Math.PI) / 180
|
||||
const R = RR[it.ring]
|
||||
const ux = CX + R * Math.cos(a)
|
||||
|
|
@ -199,8 +198,8 @@ export default function OrbitMemory({
|
|||
const DISC = 700
|
||||
const INN: number[] = []
|
||||
const OUT: number[] = []
|
||||
for (let i = 0; i < INTEG.length; i++) {
|
||||
;(INTEG[i].ring === 0 ? INN : OUT).push(i)
|
||||
for (const [i, it] of INTEG.entries()) {
|
||||
;(it.ring === 0 ? INN : OUT).push(i)
|
||||
}
|
||||
let phase = "orbit"
|
||||
let pT0 = 0
|
||||
|
|
@ -259,12 +258,16 @@ export default function OrbitMemory({
|
|||
const ay = pyc - uy * HL
|
||||
const bx = pxc + ux * HL
|
||||
const by = pyc + uy * HL
|
||||
setLine(gr[k], ax, ay, bx, by)
|
||||
setLine(cr[k], ax, ay, bx, by)
|
||||
setLine(gl[k], ax, ay, bx, by)
|
||||
const grad = gr[k]
|
||||
const comet = cr[k]
|
||||
const glow = gl[k]
|
||||
if (!grad || !comet || !glow) continue
|
||||
setLine(grad, ax, ay, bx, by)
|
||||
setLine(comet, ax, ay, bx, by)
|
||||
setLine(glow, ax, ay, bx, by)
|
||||
const o = Math.sin(f * Math.PI) * P
|
||||
cr[k].setAttribute("opacity", o.toFixed(2))
|
||||
gl[k].setAttribute("opacity", (0.6 * o).toFixed(2))
|
||||
comet.setAttribute("opacity", o.toFixed(2))
|
||||
glow.setAttribute("opacity", (0.6 * o).toFixed(2))
|
||||
}
|
||||
}
|
||||
const frame = (now: number) => {
|
||||
|
|
@ -276,13 +279,13 @@ export default function OrbitMemory({
|
|||
if (phase === "orbit" && pt > ORBIT) {
|
||||
phase = "receive"
|
||||
pT0 = now
|
||||
src = INN[(ci * 5) % INN.length]
|
||||
dst = OUT[(ci * 7) % OUT.length]
|
||||
src = INN[(ci * 5) % INN.length] ?? 0
|
||||
dst = OUT[(ci * 7) % OUT.length] ?? 0
|
||||
ci++
|
||||
nodes[src]?.classList.add("sm-active")
|
||||
stage.style.setProperty(
|
||||
"--cm",
|
||||
`rgb(${ACCENT[INTEG[src].key!] || "91,157,255"})`,
|
||||
`rgb(${ACCENT[INTEG[src]?.key ?? ""] || "91,157,255"})`,
|
||||
)
|
||||
} else if (phase === "receive" && pt > RECV) {
|
||||
phase = "send"
|
||||
|
|
@ -318,8 +321,8 @@ export default function OrbitMemory({
|
|||
seg(
|
||||
now,
|
||||
track,
|
||||
INTEG[src]._x!,
|
||||
INTEG[src]._y!,
|
||||
INTEG[src]?._x ?? 0,
|
||||
INTEG[src]?._y ?? 0,
|
||||
ps,
|
||||
grads,
|
||||
cms,
|
||||
|
|
@ -330,8 +333,8 @@ export default function OrbitMemory({
|
|||
seg(
|
||||
now,
|
||||
dtrack,
|
||||
INTEG[dst]._x!,
|
||||
INTEG[dst]._y!,
|
||||
INTEG[dst]?._x ?? 0,
|
||||
INTEG[dst]?._y ?? 0,
|
||||
pd,
|
||||
ogrs,
|
||||
oms,
|
||||
|
|
@ -508,7 +511,9 @@ export default function OrbitMemory({
|
|||
<span
|
||||
className="sm-glyph"
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: static, vetted inline brand SVG markup
|
||||
dangerouslySetInnerHTML={{ __html: ICONS[it.key!] }}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: (it.key && ICONS[it.key]) || "",
|
||||
}}
|
||||
/>
|
||||
<span className="sm-gsub">{it.sub}</span>
|
||||
</span>
|
||||
|
|
@ -518,7 +523,9 @@ export default function OrbitMemory({
|
|||
<span
|
||||
className="sm-glyph"
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: static, vetted inline brand SVG markup
|
||||
dangerouslySetInnerHTML={{ __html: ICONS[it.key!] }}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: (it.key && ICONS[it.key]) || "",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -152,7 +152,10 @@ export default function Integrations() {
|
|||
name: `ios-${generateId().slice(0, 8)}`,
|
||||
prefix: `sm_${org?.id}_`,
|
||||
})
|
||||
return res.key
|
||||
if (res.error)
|
||||
throw new Error("Failed to create API key", { cause: res.error })
|
||||
if (!res.data?.key) throw new Error("API key missing from response")
|
||||
return res.data.key
|
||||
},
|
||||
onSuccess: (key) => {
|
||||
setApiKey(key)
|
||||
|
|
@ -182,7 +185,7 @@ export default function Integrations() {
|
|||
prefix: `sm_${org.id}_`,
|
||||
})
|
||||
if (res.error)
|
||||
throw new Error(res.error.message ?? "Failed to create API key")
|
||||
throw new Error("Failed to create API key", { cause: res.error })
|
||||
if (!res.data?.key) throw new Error("API key missing from response")
|
||||
return res.data.key
|
||||
},
|
||||
|
|
|
|||
|
|
@ -81,9 +81,11 @@ export function UserProfileMenu({
|
|||
const initials = (() => {
|
||||
if (user.name) {
|
||||
const parts = user.name.trim().split(/\s+/)
|
||||
const first = parts[0] ?? ""
|
||||
const last = parts[parts.length - 1] ?? ""
|
||||
return parts.length >= 2
|
||||
? `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase()
|
||||
: parts[0].slice(0, 2).toUpperCase()
|
||||
? `${first.slice(0, 1)}${last.slice(0, 1)}`.toUpperCase()
|
||||
: first.slice(0, 2).toUpperCase()
|
||||
}
|
||||
if (user.email) return user.email.slice(0, 2).toUpperCase()
|
||||
return "SM"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export function useResetOrganization() {
|
|||
mutationFn: async (body: { confirmation: string }) => {
|
||||
const res = await $fetch("@post/settings/reset", {
|
||||
body,
|
||||
retry: { attempts: 0 },
|
||||
retry: 0,
|
||||
})
|
||||
if (res.error) {
|
||||
const e = res.error as Record<string, unknown>
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ export function areUIMessageArraysEqual(
|
|||
return false
|
||||
}
|
||||
|
||||
if (msgA.content !== msgB.content) return false
|
||||
|
||||
if (JSON.stringify(msgA.parts) !== JSON.stringify(msgB.parts)) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -202,7 +200,8 @@ export function usePersistentChat() {
|
|||
)
|
||||
|
||||
const conversations: ConversationSummary[] = (() => {
|
||||
const convs = projectState?.conversations ?? {}
|
||||
const convs: Record<string, ConversationRecord> =
|
||||
projectState?.conversations ?? {}
|
||||
return Object.entries(convs).map(([id, rec]) => ({
|
||||
id,
|
||||
title: rec.title,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export function useProject() {
|
|||
const normalizedProjects =
|
||||
selectedProjects.length === 0 ? [defaultTag] : selectedProjects
|
||||
|
||||
const selectedProject = normalizedProjects[0]
|
||||
const selectedProject = normalizedProjects[0] ?? defaultTag
|
||||
|
||||
const effectiveContainerTags = normalizedProjects
|
||||
|
||||
|
|
|
|||
|
|
@ -507,8 +507,7 @@ export function useGraphData(
|
|||
// Golden angle (~137.5 deg) produces optimal packing in a spiral
|
||||
const goldenAngle = Math.PI * (3 - Math.sqrt(5))
|
||||
|
||||
for (let docIdx = 0; docIdx < docCount; docIdx++) {
|
||||
const doc = documents[docIdx]
|
||||
for (const [docIdx, doc] of documents.entries()) {
|
||||
const docCluster = getDocumentClusterAssignment(doc, clusterAssignments)
|
||||
const angle = docIdx * goldenAngle
|
||||
const radius = spiralScale * Math.sqrt((docIdx + 1) / docCount)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import type { CSSProperties } from "react"
|
||||
|
||||
export const OneDrive = ({ className }: { className?: string }) => (
|
||||
<svg
|
||||
className={className}
|
||||
|
|
@ -237,7 +239,13 @@ export const PDF = ({ className }: { className?: string }) => (
|
|||
</svg>
|
||||
)
|
||||
|
||||
export const SyncLogoIcon = ({ className }: { className?: string }) => {
|
||||
export const SyncLogoIcon = ({
|
||||
className,
|
||||
style,
|
||||
}: {
|
||||
className?: string
|
||||
style?: CSSProperties
|
||||
}) => {
|
||||
return (
|
||||
<svg
|
||||
width="11"
|
||||
|
|
@ -246,6 +254,7 @@ export const SyncLogoIcon = ({ className }: { className?: string }) => {
|
|||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<title>Sync Logo</title>
|
||||
<g clipPath="url(#clip0_344_4856)">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue