Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified pipes/rewind/bun.lockb
Binary file not shown.
17 changes: 10 additions & 7 deletions pipes/rewind/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
},
"dependencies": {
"@radix-ui/react-accordion": "^1.2.2",
"@radix-ui/react-checkbox": "^1.1.3",
"@radix-ui/react-dialog": "^1.1.3",
"@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-popover": "^1.1.3",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-progress": "^1.1.1",
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-select": "^2.1.3",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slider": "^1.2.2",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-toast": "^1.2.3",
"@radix-ui/react-tooltip": "^1.1.5",
Expand All @@ -33,17 +33,18 @@
"ai": "^4.0.18",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "1.0.0",
"cmdk": "^1.0.4",
"date-fns": "^4.1.0",
"framer-motion": "^11.14.4",
"install": "^0.13.0",
"js-levenshtein": "^1.1.6",
"localforage": "^1.10.0",
"lodash": "^4.17.21",
"lucide-react": "^0.468.0",
"lucide-react": "^0.475.0",
"magic-ui": "^0.1.0",
"next": "15.1.0",
"npm": "^10.9.2",
"nuqs": "^2.3.2",
"openai": "^4.76.3",
"react": "^19.0.0",
"react-day-picker": "8.10.1",
Expand All @@ -52,6 +53,7 @@
"react-syntax-highlighter": "^15.6.1",
"remark-gfm": "^4.0.0",
"remark-math": "^6.0.0",
"stopword": "^3.1.4",
"tailwind-merge": "^2.5.5",
"tailwindcss-animate": "^1.0.7",
"zustand": "^5.0.3"
Expand All @@ -61,6 +63,7 @@
"@types/node": "^22.10.2",
"@types/react": "^19",
"@types/react-dom": "^19",
"@types/stopword": "^2.0.3",
"autoprefixer": "^10.4.20",
"eslint": "^9.19.0",
"postcss": "^8.4.49",
Expand Down
85 changes: 42 additions & 43 deletions pipes/rewind/src/app/api/settings/route.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,59 @@
// app/api/settings/route.ts
import { pipe } from "@screenpipe/js";
import { NextResponse } from "next/server";
import type { Settings } from "@screenpipe/js";
import { getDefaultSettings } from "@screenpipe/browser";
// Force Node.js runtime
export const runtime = "nodejs"; // Add this line
export const dynamic = "force-dynamic";

export async function GET() {
const defaultSettings = getDefaultSettings();
try {
const settingsManager = pipe.settings;
if (!settingsManager) {
throw new Error("settingsManager not found");
}
const rawSettings = await settingsManager.getAll();
return NextResponse.json(rawSettings);
} catch (error) {
console.error("failed to get settings:", error);
return NextResponse.json(defaultSettings);
}
const defaultSettings = getDefaultSettings();
try {
const settingsManager = pipe.settings;
if (!settingsManager) {
throw new Error("settingsManager not found");
}
const rawSettings = await settingsManager.getAll();
return NextResponse.json(rawSettings);
} catch (error) {
console.error("failed to get settings:", error);
return NextResponse.json(defaultSettings);
}
}

export async function PUT(request: Request) {
try {
const settingsManager = pipe.settings;
if (!settingsManager) {
throw new Error("settingsManager not found");
}
try {
const settingsManager = pipe.settings;
if (!settingsManager) {
throw new Error("settingsManager not found");
}

const body = await request.json();
const { key, value, isPartialUpdate, reset } = body;
const body = await request.json();
const { key, value, isPartialUpdate, reset } = body;

if (reset) {
if (key) {
await settingsManager.resetKey(key);
} else {
await settingsManager.reset();
}
return NextResponse.json({ success: true });
}
if (reset) {
if (key) {
await settingsManager.resetKey(key);
} else {
await settingsManager.reset();
}
return NextResponse.json({ success: true });
}

if (isPartialUpdate) {
const serializedSettings = JSON.parse(JSON.stringify(value));
await settingsManager.update(serializedSettings);
} else {
const serializedValue = JSON.parse(JSON.stringify(value));
await settingsManager.set(key, serializedValue);
}
if (isPartialUpdate) {
const serializedSettings = JSON.parse(JSON.stringify(value));
await settingsManager.update(serializedSettings);
} else {
const serializedValue = JSON.parse(JSON.stringify(value));
await settingsManager.set(key, serializedValue);
}

return NextResponse.json({ success: true });
} catch (error) {
console.error("failed to update settings:", error);
return NextResponse.json(
{ error: "failed to update settings" },
{ status: 500 }
);
}
return NextResponse.json({ success: true });
} catch (error) {
console.error("failed to update settings:", error);
return NextResponse.json(
{ error: "failed to update settings" },
{ status: 500 },
);
}
}
39 changes: 24 additions & 15 deletions pipes/rewind/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { SearchCommand } from "@/components/search-command";
import { NuqsAdapter } from "nuqs/adapters/next/app";
import { getScreenpipeAppSettings } from "@/lib/actions/get-screenpipe-app-settings";
import { SettingsProvider } from "@/components/settings-provider";

const geistSans = Geist({
variable: "--font-geist-sans",
Expand All @@ -26,9 +30,7 @@ export default async function RootLayout({
}>) {
const checkSettings = async () => {
try {
const port = process.env.PORT || 3000;
const response = await fetch(`http://localhost:${port}/api/settings`);
const settings = await response.json();
const settings = await getScreenpipeAppSettings();

return settings.enableFrameCache;
} catch (error) {
Expand All @@ -44,19 +46,26 @@ export default async function RootLayout({
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{!enabled ? (
<div className="flex items-center justify-center h-screen">
<div className="text-center space-y-4">
<h2 className="text-xl font-medium">Frame Cache Disabled</h2>
<p className="text-muted-foreground">
Please enable frame cache in settings to use the timeline
feature.
</p>
<SettingsProvider>
{!enabled ? (
<div className="flex items-center justify-center h-screen">
<div className="text-center space-y-4">
<h2 className="text-xl font-medium">Frame Cache Disabled</h2>
<p className="text-muted-foreground">
Please enable frame cache in settings to use the timeline
feature.
</p>
</div>
</div>
</div>
) : (
<>{children}</>
)}
) : (
<>
<NuqsAdapter>
<SearchCommand />
{children}
</NuqsAdapter>
</>
)}
</SettingsProvider>
</body>
</html>
);
Expand Down
19 changes: 12 additions & 7 deletions pipes/rewind/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
"use client";
import { useEffect, useState, useRef, useMemo, useCallback } from "react";
import { Loader2, RotateCcw, AlertCircle } from "lucide-react";
import { TimelineIconsSection } from "@/components/timeline/timeline-dock-section";
import { AudioTranscript } from "@/components/timeline/audio-transcript";
import { AIPanel } from "@/components/timeline/ai-panel";
import { TimelineProvider } from "@/lib/hooks/use-timeline-selection";
import { throttle } from "lodash";
import { AGENTS } from "@/components/timeline/agents";
import { TimelineSelection } from "@/components/timeline/timeline-selection";
import { TimelineControls } from "@/components/timeline/timeline-controls";
import { TimelineSearch } from "@/components/timeline/timeline-search";
import { TimelineSearch2 } from "@/components/timeline/timeline-search-v2";
import { addDays, isAfter, isSameDay, subDays } from "date-fns";
import { getStartDate } from "@/lib/actions/get-start-date";
import { useTimelineData } from "@/lib/hooks/use-timeline-data";
import { useCurrentFrame } from "@/lib/hooks/use-current-frame";
import { TimelineSlider } from "@/components/timeline/timeline";
import { useTimelineStore } from "@/lib/hooks/use-timeline-store";
import { hasFramesForDate } from "@/lib/actions/has-frames-date";
import { CommandShortcut } from "@/components/ui/command";

export interface StreamTimeSeriesResponse {
timestamp: string;
Expand Down Expand Up @@ -265,11 +262,16 @@ export default function Timeline() {
if (!hasDateBeenFetched(newDate)) {
setCurrentFrame(null);
const frameTimeStamp = new Date(newDate);
if (frameTimeStamp.getDate() === new Date(currentDate).getDate()) {
console.log(
frameTimeStamp.getDate() === new Date(currentDate).getDate(),
startAndEndDates.start.getDate(),
newDate.getDate(),
);
if (isSameDay(frameTimeStamp, new Date(currentDate))) {
return;
}

if (isAfter(startAndEndDates.start.getDate(), newDate.getDate())) {
if (isAfter(startAndEndDates.start, newDate)) {
return;
}

Expand Down Expand Up @@ -342,6 +344,10 @@ export default function Timeline() {
onResultSelect={animateToIndex}
onSearchResults={setSearchResults}
/> */}
<div>
<CommandShortcut>⌘K</CommandShortcut>{" "}
<span className="text-xs text-muted-foreground">to search</span>
</div>
</div>
</div>

Expand Down Expand Up @@ -393,7 +399,6 @@ export default function Timeline() {
)}
{currentFrame && (
<img
//src={`data:image/png;base64,${imageFrame}`}
src={`http://localhost:3030/frames/${currentFrame.devices[0].frame_id}`}
className="absolute inset-0 w-4/5 h-auto max-h-[75vh] object-contain mx-auto border rounded-xl p-2 mt-20"
alt="Current frame"
Expand Down
Loading
Loading