Skip to content

Commit

Permalink
fix: resource monitor not using CLI port, refactor: remove pipe runne…
Browse files Browse the repository at this point in the history
…r bin shit and use hard thread instead, feat: impl dev dialog for quick settings change in dev mode of app
  • Loading branch information
louis030195 committed Aug 27, 2024
1 parent 4982342 commit 79e58ba
Show file tree
Hide file tree
Showing 18 changed files with 346 additions and 347 deletions.
2 changes: 2 additions & 0 deletions examples/apps/screenpipe-app-tauri/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import UpdateNotification from "@/components/update-notification";
import { usePostHog } from "posthog-js/react";
import Link from "next/link";
import { useToast } from "@/components/ui/use-toast";
import { DevSettings } from "@/components/dev-dialog";

export default function Home() {
const { settings } = useSettings();
Expand All @@ -39,6 +40,7 @@ export default function Home() {

return (
<main className="flex min-h-screen flex-col items-center p-8">
{/* <DevSettings /> */}
<NotificationHandler />
{/* <UpdateNotification checkIntervalHours={3} /> */}
{/* <ScreenpipeInstanceChecker /> */}
Expand Down
130 changes: 130 additions & 0 deletions examples/apps/screenpipe-app-tauri/components/dev-dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import React, { useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { useSettings } from "@/lib/hooks/use-settings";
import { useToast } from "@/components/ui/use-toast";

export function DevSettings() {
const { settings, updateSettings } = useSettings();
const [localSettings, setLocalSettings] = React.useState(settings);
const [isSaving, setIsSaving] = useState(false);
const { toast } = useToast();

useEffect(() => {
setLocalSettings(settings);
}, [settings]);

const handleChange = (key: keyof typeof settings, value: any) => {
setLocalSettings((prev) => ({ ...prev, [key]: value }));
};

const handleSave = async () => {
setIsSaving(true);
toast({
title: "updating dev settings",
description: "this may take a few moments...",
});

try {
await updateSettings(localSettings);
await new Promise((resolve) => setTimeout(resolve, 1000));

toast({
title: "dev settings updated successfully",
description: "your changes have been saved.",
});
} catch (error) {
console.error("failed to update dev settings:", error);
toast({
title: "error updating dev settings",
description: "please try again or check the logs for more information.",
variant: "destructive",
});
} finally {
setIsSaving(false);
}
};

return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">dev settings</Button>
</DialogTrigger>
<DialogContent className="max-w-[80vw] w-full max-h-[80vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>dev settings</DialogTitle>
</DialogHeader>
<div className="space-y-4">
{Object.entries(localSettings).map(([key, value]) => (
<div key={key} className="flex flex-col space-y-2">
<Label htmlFor={key}>{key}</Label>
{typeof value === "boolean" ? (
<Switch
id={key}
checked={value}
onCheckedChange={(checked) =>
handleChange(key as any, checked)
}
/>
) : typeof value === "string" ? (
key === "customPrompt" ? (
<Textarea
id={key}
value={value}
onChange={(e) => handleChange(key as any, e.target.value)}
rows={4}
/>
) : (
<Input
id={key}
value={value}
onChange={(e) => handleChange(key as any, e.target.value)}
/>
)
) : typeof value === "number" ? (
<Input
id={key}
type="number"
value={value}
onChange={(e) =>
handleChange(key as any, Number(e.target.value))
}
/>
) : Array.isArray(value) ? (
<Textarea
id={key}
value={JSON.stringify(value)}
onChange={(e) =>
handleChange(key as any, JSON.parse(e.target.value))
}
rows={4}
/>
) : (
<Input
id={key}
value={JSON.stringify(value)}
onChange={(e) =>
handleChange(key as any, JSON.parse(e.target.value))
}
/>
)}
</div>
))}
</div>
<Button onClick={handleSave} className="mt-4" disabled={isSaving}>
{isSaving ? "saving..." : "save changes"}
</Button>
</DialogContent>
</Dialog>
);
}
16 changes: 6 additions & 10 deletions examples/apps/screenpipe-app-tauri/components/pipe-store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const PipeDialog: React.FC = () => {
});

// Update installed pipes in settings
const updatedInstalledPipes = [...settings.installedPipes, pipe.mainFile!];
const updatedInstalledPipes = [...settings.installedPipes, pipe];
await updateSettings({ installedPipes: updatedInstalledPipes });

// Kill existing screenpipe processes
Expand Down Expand Up @@ -124,7 +124,7 @@ const PipeDialog: React.FC = () => {

// Update installed pipes in settings
const updatedInstalledPipes = settings.installedPipes.filter(
(p) => p !== pipe.name
(p) => p.name !== pipe.name
);
await updateSettings({ installedPipes: updatedInstalledPipes });

Expand Down Expand Up @@ -158,14 +158,9 @@ const PipeDialog: React.FC = () => {
);
}

if (
selectedPipe.name === "Local First Meeting Summarizer" &&
settings.installedPipes.includes(selectedPipe.name)
) {
return <MeetingSummarizer pipe={selectedPipe} />;
}

const isInstalled = settings.installedPipes.includes(selectedPipe.name);
const isInstalled =
settings.installedPipes.find((p) => p.name === selectedPipe.name) !==
undefined;

return (
<>
Expand Down Expand Up @@ -268,6 +263,7 @@ const PipeDialog: React.FC = () => {
},
img({ src, alt }) {
return (
/* eslint-disable @next/next/no-img-element */
<img
src={src}
alt={alt}
Expand Down
40 changes: 30 additions & 10 deletions examples/apps/screenpipe-app-tauri/lib/hooks/use-pipes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,41 @@ export type Pipe = {
mainFile?: string;
};

const cache: { [key: string]: { data: any; timestamp: number } } = {};
const CACHE_DURATION = 60 * 60 * 1000; // 1 hour in milliseconds

const fetchWithCache = async (url: string) => {
if (cache[url] && Date.now() - cache[url].timestamp < CACHE_DURATION) {
return cache[url].data;
const cacheKey = `cache_${url}`;
const cachedData = localStorage.getItem(cacheKey);

if (cachedData) {
const { data, timestamp } = JSON.parse(cachedData);
if (Date.now() - timestamp < CACHE_DURATION) {
return data;
}
}

const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
try {
const response = await fetch(url);
if (response.status === 403) {
throw new Error("Rate limit exceeded");
}
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
localStorage.setItem(
cacheKey,
JSON.stringify({ data, timestamp: Date.now() })
);
return data;
} catch (error) {
console.error(`Error fetching ${url}:`, error);
if (cachedData) {
console.log("Returning stale cached data");
return JSON.parse(cachedData).data;
}
throw error;
}
const data = await response.json();
cache[url] = { data, timestamp: Date.now() };
return data;
};

const convertHtmlToMarkdown = (html: string) => {
Expand Down Expand Up @@ -156,7 +176,7 @@ export const usePipes = (repoUrls: string[]) => {
jsFiles[0];

const mainFileUrl = mainFile
? `https://github.com/${repoFullName}/blob/${branch}/${subDir}/${mainFile.name}`
? `https://raw.githubusercontent.com/${repoFullName}/${branch}/${subDir}/${mainFile.name}`
: undefined;

return {
Expand Down
14 changes: 11 additions & 3 deletions examples/apps/screenpipe-app-tauri/lib/hooks/use-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Store } from "@tauri-apps/plugin-store";
import { localDataDir } from "@tauri-apps/api/path";
import { join } from "@tauri-apps/api/path";
import { platform } from "@tauri-apps/plugin-os";
import { Pipe } from "./use-pipes";

const defaultSettings: Settings = {
openaiApiKey: "",
Expand Down Expand Up @@ -31,6 +32,8 @@ const defaultSettings: Settings = {
audioDevices: ["default"],
usePiiRemoval: false,
restartInterval: 0,
port: 3030,
dataDir: "default",
};

export interface Settings {
Expand All @@ -39,7 +42,7 @@ export interface Settings {
ollamaUrl: string;
isLoading: boolean;
aiModel: string;
installedPipes: string[];
installedPipes: Pipe[];
userId: string;
customPrompt: string;
devMode: boolean;
Expand All @@ -49,6 +52,8 @@ export interface Settings {
audioDevices: string[];
usePiiRemoval: boolean;
restartInterval: number;
port: number;
dataDir: string;
}

let store: Store | null = null;
Expand Down Expand Up @@ -96,7 +101,7 @@ export function useSettings() {
const savedAiModel =
((await store!.get("aiModel")) as string) || "gpt-4o";
const savedInstalledPipes =
((await store!.get("installedPipes")) as string[]) || [];
((await store!.get("installedPipes")) as Pipe[]) || [];
const savedUserId = ((await store!.get("userId")) as string) || "";
const savedCustomPrompt =
((await store!.get("customPrompt")) as string) || "";
Expand All @@ -117,7 +122,8 @@ export function useSettings() {
((await store!.get("usePiiRemoval")) as boolean) || false;
const savedRestartInterval =
((await store!.get("restartInterval")) as number) || 0;

const savedPort = ((await store!.get("port")) as number) || 3030;
const savedDataDir = ((await store!.get("dataDir")) as string) || "";
setSettings({
openaiApiKey: savedKey,
useOllama: savedUseOllama,
Expand All @@ -134,6 +140,8 @@ export function useSettings() {
audioDevices: savedAudioDevices,
usePiiRemoval: savedUsePiiRemoval,
restartInterval: savedRestartInterval,
port: savedPort,
dataDir: savedDataDir,
});
} catch (error) {
console.error("Failed to load settings:", error);
Expand Down
Loading

0 comments on commit 79e58ba

Please sign in to comment.