From 79e6a70bbf10bd84bc6839dc14e9cd78bf5fd19e Mon Sep 17 00:00:00 2001 From: neo773 <62795688+neo773@users.noreply.github.com> Date: Sat, 25 Jan 2025 02:04:15 +0530 Subject: [PATCH] Plugin store new (#1169) * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * add docs * wip * wip * hide controls if not installed * fix conflict * fix * fix formatting * fix setting dev api key --- content/developer-account.png | Bin 0 -> 253167 bytes content/docs/pages/docs/plugins.mdx | 31 + screenpipe-app-tauri/app/page.tsx | 31 +- .../components/login-dialog.tsx | 56 + .../components/onboarding/login.tsx | 5 +- .../components/pipe-config-form.tsx | 23 +- .../components/pipe-store-markdown.tsx | 13 +- .../components/pipe-store.tsx | 1735 ++++------------- .../components/pipe-store/add-pipe-form.tsx | 71 + .../components/pipe-store/pipe-card.tsx | 162 ++ .../components/pipe-store/pipe-details.tsx | 265 +++ .../components/pipe-store/types.ts | 29 + .../components/publish-dialog.tsx | 4 +- .../components/recording-settings.tsx | 4 +- .../components/settings/account-section.tsx | 189 +- .../components/settings/ai-section.tsx | 9 +- .../store/credit-purchase-dialog.tsx | 12 +- screenpipe-app-tauri/lib/api/store/index.ts | 209 ++ .../lib/hooks/use-health-check.tsx | 2 +- .../lib/hooks/use-settings.tsx | 34 + screenpipe-app-tauri/lib/hooks/use-user.ts | 80 - screenpipe-app-tauri/src-tauri/src/main.rs | 6 + .../src-tauri/tauri.conf.json | 6 + .../src-tauri/ui_monitor-aarch64-apple-darwin | Bin 297920 -> 297920 bytes .../src-tauri/ui_monitor-x86_64-apple-darwin | Bin 279032 -> 279032 bytes screenpipe-core/Cargo.toml | 1 + screenpipe-core/src/pipes.rs | 92 + screenpipe-server/Cargo.toml | 1 + screenpipe-server/src/pipe_manager.rs | 45 +- screenpipe-server/src/server.rs | 34 + 30 files changed, 1640 insertions(+), 1509 deletions(-) create mode 100644 content/developer-account.png create mode 100644 screenpipe-app-tauri/components/login-dialog.tsx create mode 100644 screenpipe-app-tauri/components/pipe-store/add-pipe-form.tsx create mode 100644 screenpipe-app-tauri/components/pipe-store/pipe-card.tsx create mode 100644 screenpipe-app-tauri/components/pipe-store/pipe-details.tsx create mode 100644 screenpipe-app-tauri/components/pipe-store/types.ts create mode 100644 screenpipe-app-tauri/lib/api/store/index.ts delete mode 100644 screenpipe-app-tauri/lib/hooks/use-user.ts diff --git a/content/developer-account.png b/content/developer-account.png new file mode 100644 index 0000000000000000000000000000000000000000..733b18b4e4de611dd0181c486b2efae272c8a2d8 GIT binary patch literal 253167 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%0ASpLc2jP~2^|9r@ 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%0DPO;i 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 + +# create a new pipe +screenpipe create --name my-pipe [--paid --price 9.99] + +# publish your pipe to the store +screenpipe publish --name my-pipe + +# list all versions of your pipe +screenpipe list-versions --name my-pipe + +# end current session +screenpipe logout +``` + you can deploy your pipe to your screenpipe app through the UI or using `screenpipe install ` and `screenpipe enable `. when you're ready to deploy, send a PR to the [screenpipe repo](https://github.com/mediar-ai/screenpipe) to add your pipe to the store. diff --git a/screenpipe-app-tauri/app/page.tsx b/screenpipe-app-tauri/app/page.tsx index b69892a540..01b913da5c 100644 --- a/screenpipe-app-tauri/app/page.tsx +++ b/screenpipe-app-tauri/app/page.tsx @@ -13,16 +13,17 @@ import { ChangelogDialog } from "@/components/changelog-dialog"; import { BreakingChangesInstructionsDialog } from "@/components/breaking-changes-instructions-dialog"; import { platform } from "@tauri-apps/plugin-os"; -import PipeStore from "@/components/pipe-store"; +import {PipeStore} from "@/components/pipe-store"; import { invoke } from "@tauri-apps/api/core"; import { listen } from "@tauri-apps/api/event"; import { useProfiles } from "@/lib/hooks/use-profiles"; import { relaunch } from "@tauri-apps/plugin-process"; import { PipeApi } from "@/lib/api"; import localforage from "localforage"; +import { onOpenUrl } from "@tauri-apps/plugin-deep-link"; export default function Home() { - const { settings } = useSettings(); + const { settings, updateSettings } = useSettings(); const { setActiveProfile } = useProfiles(); const posthog = usePostHog(); const { toast } = useToast(); @@ -36,6 +37,31 @@ export default function Home() { return devices; }; + const setupDeepLink = async () => { + const unsubscribeDeepLink = await onOpenUrl(async (urls) => { + console.log("received deep link urls:", urls); + for (const url of urls) { + if (url.includes("api_key=")) { + const apiKey = new URL(url).searchParams.get("api_key"); + if (apiKey) { + updateSettings({ user: { token: apiKey } }); + toast({ + title: "logged in!", + description: "your api key has been set", + }); + } + } + } + }); + return unsubscribeDeepLink; + }; + + let deepLinkUnsubscribe: (() => void) | undefined; + + setupDeepLink().then((unsubscribe) => { + deepLinkUnsubscribe = unsubscribe; + }); + const unlisten = Promise.all([ listen("shortcut-start-recording", async () => { await invoke("spawn_screenpipe"); @@ -142,6 +168,7 @@ export default function Home() { unlisten.then((listeners) => { listeners.forEach((unlistenFn) => unlistenFn()); }); + if (deepLinkUnsubscribe) deepLinkUnsubscribe(); }; }, []); diff --git a/screenpipe-app-tauri/components/login-dialog.tsx b/screenpipe-app-tauri/components/login-dialog.tsx new file mode 100644 index 0000000000..bac3e9a459 --- /dev/null +++ b/screenpipe-app-tauri/components/login-dialog.tsx @@ -0,0 +1,56 @@ +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { ExternalLinkIcon } from 'lucide-react'; +import { open as openUrl } from '@tauri-apps/plugin-shell'; +import { useState } from 'react'; + +interface LoginDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export const LoginDialog: React.FC = ({ open, onOpenChange }) => { + return ( +

+ + + login required + + please login to continue. you will be redirected to screenpi.pe + + +
+ +
+
+
+ ); +}; + +export const useLoginCheck = () => { + const [showLoginDialog, setShowLoginDialog] = useState(false); + + const checkLogin = (user: any | null) => { + if (!user?.token) { + setShowLoginDialog(true); + return false; + } + return true; + }; + + return { showLoginDialog, setShowLoginDialog, checkLogin }; +}; \ No newline at end of file diff --git a/screenpipe-app-tauri/components/onboarding/login.tsx b/screenpipe-app-tauri/components/onboarding/login.tsx index bea305ae18..a2730f3ad9 100644 --- a/screenpipe-app-tauri/components/onboarding/login.tsx +++ b/screenpipe-app-tauri/components/onboarding/login.tsx @@ -6,7 +6,6 @@ import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { useSettings } from "@/lib/hooks/use-settings"; -import { useUser } from "@/lib/hooks/use-user"; import { toast } from "@/components/ui/use-toast"; import { onOpenUrl } from "@tauri-apps/plugin-deep-link"; import OnboardingNavigation from "./navigation"; @@ -22,7 +21,6 @@ const OnboardingLogin: React.FC = ({ handlePrevSlide, handleNextSlide, }) => { - const { user, loadUser } = useUser(); const { settings, updateSettings } = useSettings(); useEffect(() => { @@ -68,7 +66,7 @@ const OnboardingLogin: React.FC = ({

credits & usage

- {user?.credits?.amount || 0} available + {settings.user?.credits?.amount || 0} available @@ -91,7 +89,6 @@ const OnboardingLogin: React.FC = ({ variant="secondary" size="sm" onClick={async () => { - await loadUser(settings.user?.token || ""); toast({ title: "key verified" }); handleNextSlide(); }} diff --git a/screenpipe-app-tauri/components/pipe-config-form.tsx b/screenpipe-app-tauri/components/pipe-config-form.tsx index 8e896c4e7f..d4a9522c50 100644 --- a/screenpipe-app-tauri/components/pipe-config-form.tsx +++ b/screenpipe-app-tauri/components/pipe-config-form.tsx @@ -12,7 +12,7 @@ import { } from "./ui/tooltip"; import { Layers, Layout, RefreshCw } from "lucide-react"; import { toast } from "./ui/use-toast"; -import { Pipe } from "./pipe-store"; +import { InstalledPipe, PipeWithStatus } from "./pipe-store/types"; import { SqlAutocompleteInput } from "./sql-autocomplete-input"; import { Select, @@ -30,7 +30,7 @@ import { open } from "@tauri-apps/plugin-dialog"; import { FolderOpen } from "lucide-react"; type PipeConfigFormProps = { - pipe: Pipe; + pipe: PipeWithStatus; onConfigSave: (config: Record) => void; }; @@ -46,20 +46,23 @@ export const PipeConfigForm: React.FC = ({ pipe, onConfigSave, }) => { - const [config, setConfig] = useState(pipe.config); + const [config, setConfig] = useState(pipe.installed_config); useEffect(() => { - setConfig(pipe.config); + setConfig(pipe.installed_config); }, [pipe]); const handleInputChange = (name: string, value: any) => { if (!config) return; - setConfig((prevConfig) => ({ - ...prevConfig, - fields: prevConfig?.fields?.map((field: FieldConfig) => - field.name === name ? { ...field, value } : field - ), - })); + setConfig((prevConfig) => { + if (!prevConfig) return prevConfig; + return { + ...prevConfig, + fields: prevConfig.fields?.map((field: FieldConfig) => + field.name === name ? { ...field, value } : field + ), + }; + }); }; const renderConfigInput = (field: FieldConfig) => { diff --git a/screenpipe-app-tauri/components/pipe-store-markdown.tsx b/screenpipe-app-tauri/components/pipe-store-markdown.tsx index 308cd43022..2b04fa3966 100644 --- a/screenpipe-app-tauri/components/pipe-store-markdown.tsx +++ b/screenpipe-app-tauri/components/pipe-store-markdown.tsx @@ -6,6 +6,7 @@ import remarkMath from "remark-math"; import { useCopyToClipboard } from "@/lib/hooks/use-copy-to-clipboard"; import { Button } from "@/components/ui/button"; import { Copy, Check } from "lucide-react"; +import { convertHtmlToMarkdown } from "@/lib/utils"; interface MarkdownProps { content: string; @@ -19,6 +20,7 @@ export function PipeStoreMarkdown({ variant = "default", }: MarkdownProps) { const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 }); + const processedContent = convertHtmlToMarkdown(content); return (
@@ -97,9 +99,18 @@ export function PipeStoreMarkdown({ ); }, + img({ node, ...props }) { + return ( + + ); + }, }} > - {content.replace(/Â/g, "")} + {processedContent.replace(/Â/g, "")}
); diff --git a/screenpipe-app-tauri/components/pipe-store.tsx b/screenpipe-app-tauri/components/pipe-store.tsx index 2e6351acda..cfcb000e2c 100644 --- a/screenpipe-app-tauri/components/pipe-store.tsx +++ b/screenpipe-app-tauri/components/pipe-store.tsx @@ -1,467 +1,177 @@ import React, { useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; -import { Badge } from "@/components/ui/badge"; -import { toast } from "./ui/use-toast"; -import { Input } from "./ui/input"; -import { Switch } from "./ui/switch"; -import { - Download, - Plus, - Trash2, - ExternalLink, - FolderOpen, - RefreshCw, - Search, - Power, - Puzzle, - X, - Loader2, - BanknoteIcon, -} from "lucide-react"; -import { PipeConfigForm } from "./pipe-config-form"; +import { Input } from "@/components/ui/input"; +import { Switch } from "@/components/ui/switch"; +import { Loader2, Power, Search, Trash2 } from "lucide-react"; +import { toast } from "@/components/ui/use-toast"; import { useHealthCheck } from "@/lib/hooks/use-health-check"; -import posthog from "posthog-js"; -import { open } from "@tauri-apps/plugin-dialog"; -import { Command, open as openUrl } from "@tauri-apps/plugin-shell"; +import { Command } from "@tauri-apps/plugin-shell"; import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip"; -import { readFile } from "@tauri-apps/plugin-fs"; -import { join } from "@tauri-apps/api/path"; -import { convertHtmlToMarkdown } from "@/lib/utils"; -import { LogFileButton } from "./log-file-button"; + PipeApi, + PipeDownloadError, + PurchaseHistoryItem, +} from "@/lib/api/store"; +import { open as openUrl } from "@tauri-apps/plugin-shell"; +import { BrokenPipe, InstalledPipe, PipeWithStatus } from "./pipe-store/types"; +import { PipeDetails } from "./pipe-store/pipe-details"; +import { PipeCard } from "./pipe-store/pipe-card"; +import { AddPipeForm } from "./pipe-store/add-pipe-form"; import { useSettings } from "@/lib/hooks/use-settings"; -import { useUser } from "@/lib/hooks/use-user"; -import { PipeStoreMarkdown } from "@/components/pipe-store-markdown"; -import { PublishDialog } from "./publish-dialog"; -import { invoke } from "@tauri-apps/api/core"; -import { Progress } from "@/components/ui/progress"; -import supabase from "@/lib/supabase/client"; -import { CreditPurchaseDialog } from "./store/credit-purchase-dialog"; -import localforage from "localforage"; +import posthog from "posthog-js"; +import { Progress } from "./ui/progress"; +import { open } from "@tauri-apps/plugin-dialog"; +import { LoginDialog, useLoginCheck } from "./login-dialog"; +import { onOpenUrl } from "@tauri-apps/plugin-deep-link"; import { useStatusDialog } from "@/lib/hooks/use-status-dialog"; -export interface Pipe { - enabled: boolean; - id: string; - source: string; - fullDescription: string; - config?: Record; - author?: string; - port?: number; -} - -interface CorePipe { - id: string; - name: string; - description: string; - url: string; - credits: number; - paid: boolean; -} - -interface RunningPipe { - id: string; - port: number; - isRunning: boolean; -} - -const BROKEN_PIPES_KEY = "broken_pipes"; -interface BrokenPipe { - id: string; - lastAttempt: number; -} - -const fetchReadmeFromGithub = async (url: string): Promise => { - try { - // Convert github.com URL to raw.githubusercontent.com - const rawUrl = url - .replace("github.com", "raw.githubusercontent.com") - .replace("/tree/main", "/main"); - - const response = await fetch(`${rawUrl}/README.md`); - if (!response.ok) return "No description available."; - const text = await response.text(); - return convertHtmlToMarkdown(text); - } catch (error) { - console.error("failed to fetch readme:", error); - return "No description available."; - } -}; - -const corePipes: (CorePipe & { fullDescription?: string })[] = [ - { - id: "auto-pay", - name: "auto pay", - description: - "automatically trigger bank transfers based on screen activity. monitors your screen for payment-related information and initiates transfers through the Mercury API", - url: "https://github.com/different-ai/hypr-v0/tree/main/pipes/auto-pay", - credits: 15, - paid: true, - }, - { - id: "linkedin-ai-assistant", - name: "linkedin ai assistant", - description: "AI agent that automatically get new connections on linkedin", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/linkedin-ai-assistant", - credits: 20, - paid: true, - }, - { - id: "memories", - name: "memories gallery", - description: - "google-photo like gallery of your screen recordings memories, with AI-powered insights and timeline visualization", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/memories", - credits: 0, - paid: false, - }, - { - id: "data-table", - name: "data table", - description: - "explore your data in a powerful table view with filtering, sorting, and more", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/data-table", - credits: 0, - paid: false, - }, - { - id: "search", - name: "search", - description: - "search through your screen recordings and audio transcripts with AI", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/search", - credits: 0, - paid: false, - }, - { - id: "rewind", - name: "rewind", - description: - "rewind-like interface meet cursor-like AI chat interface", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/rewind", - credits: 20, - paid: true, - }, - { - id: "identify-speakers", - name: "speaker identification", - description: - "automatically identify and label different speakers in your recordings using AI voice recognition", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/identify-speakers", - credits: 0, - paid: false, - }, - { - id: "obsidian", - name: "obsidian v2", - description: - "write logs of your day in obsidian with local AI features, customization, and user friendly UI", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/obsidian", - credits: 20, - paid: true, - }, - { - id: "meeting", - name: "meeting assistant", - description: - "organize and summarize your meetings with AI - get transcripts, action items, and key insights, 100% local or using cloud models", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/meeting", - credits: 15, - paid: true, - }, - { - id: "pipe-for-loom", - name: "loom generator", - description: "generate looms from your screenpipe data", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/pipe-for-loom", - credits: 10, - paid: true, - }, - { - id: "pipe-simple-nextjs", - name: "keyword analytics", - description: "show most used keywords", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/pipe-simple-nextjs", - credits: 0, - paid: false, - }, - { - id: "reddit-auto-posts", - name: "reddit auto posts", - description: - "promote your content, grow your audience, or learn new things with this automated reddit post generator based on your screen recordings", - url: "https://github.com/mediar-ai/screenpipe/tree/main/pipes/reddit-auto-posts", - credits: 20, - paid: true, - }, -]; - -const getAuthorFromSource = (source: string): string => { - if (!source) return "Unknown"; - if (!source.startsWith("http")) return "Local"; - - try { - // Extract author from GitHub URL - // Format: https://github.com/author/repo/... - const match = source.match(/github\.com\/([^\/]+)/); - return match ? match[1] : "Unknown"; - } catch { - return "Unknown"; - } -}; - -const truncateDescription = (description: string, maxLines: number = 4) => { - if (!description) return ""; - const cleaned = description.replace(/Â/g, "").trim(); - - // Split into lines and track codeblock state - const lines = cleaned.split(/\r?\n/); - let inCodeBlock = false; - let visibleLines: string[] = []; - let lineCount = 0; - - for (const line of lines) { - // Check for codeblock markers - if (line.trim().startsWith("```")) { - inCodeBlock = !inCodeBlock; - visibleLines.push(line); - continue; - } - - // If we're in a codeblock, include the line - if (inCodeBlock) { - visibleLines.push(line); - continue; - } - - // For non-codeblock content, count lines normally - if (lineCount < maxLines) { - visibleLines.push(line); - if (line.trim()) lineCount++; - } - } - - // If we ended inside a codeblock, close it - if (inCodeBlock) { - visibleLines.push("```"); - } - - const result = visibleLines.join("\n"); - return lineCount >= maxLines ? result + "..." : result; -}; - -const getFriendlyName = (id: string, corePipes: CorePipe[]): string => { - const corePipe = corePipes.find((cp) => cp.id === id); - if (corePipe) return corePipe.name; - - // Convert pipe-name-format to Title Case if no match found - return id - .replace("pipe-", "") - .split("-") - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) - .join(" "); -}; - -const normalizeId = (id: string): string => { - // Remove 'pipe-' prefix if it exists and convert to lowercase - return id.replace(/^pipe-/, "").toLowerCase(); -}; - -const DEFAULT_PIPES = [ +const corePipes: string[] = [ + "auto-pay", + "linkedin-ai-assistant", "memories", "data-table", "search", "timeline", "identify-speakers", + "obsidian", + "meeting", + "pipe-for-loom", + "pipe-simple-nextjs", + "reddit-auto-posts", ]; -const PipeStore: React.FC = () => { - const [newRepoUrl, setNewRepoUrl] = useState(""); - const [selectedPipe, setSelectedPipe] = useState(null); - const [pipes, setPipes] = useState([]); +export const PipeStore: React.FC = () => { + const { health } = useHealthCheck(); + const [selectedPipe, setSelectedPipe] = useState(null); + const { settings } = useSettings(); + const [pipes, setPipes] = useState([]); + const [installedPipes, setInstalledPipes] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [showInstalledOnly, setShowInstalledOnly] = useState(false); - const { health } = useHealthCheck(); - const { getDataDir } = useSettings(); - const { user, refreshUser } = useUser(); - const [showCreditDialog, setShowCreditDialog] = useState(false); - const [isEnabling, setIsEnabling] = useState(false); - const [runningPipes, setRunningPipes] = useState>({}); - const [startupAttempts, setStartupAttempts] = useState< - Record - >({}); - const [brokenPipes, setBrokenPipes] = useState([]); - const MAX_STARTUP_ATTEMPTS = 20; // Will give up after ~20 seconds (20 attempts * 2 second interval) - const [coreReadmes, setCoreReadmes] = useState>({}); + const [purchaseHistory, setPurchaseHistory] = useState( + [] + ); + const { showLoginDialog, setShowLoginDialog, checkLogin } = useLoginCheck(); const { open: openStatusDialog } = useStatusDialog(); - useEffect(() => { - fetchInstalledPipes(); - }, [health?.status]); - - useEffect(() => { - localforage.getItem(BROKEN_PIPES_KEY).then((stored) => { - if (stored) setBrokenPipes(stored); - }); - }, []); - - useEffect(() => { - const loadReadmes = async () => { - const readmes: Record = {}; - - await Promise.all( - corePipes.map(async (pipe) => { - readmes[pipe.id] = await fetchReadmeFromGithub(pipe.url); - }) - ); - - setCoreReadmes(readmes); - }; - - loadReadmes(); - }, []); // Run once on component mount - - // Add this new effect to install default pipes - useEffect(() => { - const installDefaultPipes = async () => { - if (!health || health?.status === "error") return; - - // Get currently installed pipes - const response = await fetch("http://localhost:3030/pipes/list"); - const data = await response.json(); - const installedPipeIds = data.data.map((p: Pipe) => p.id); - - // Find which default pipes need to be installed - const pipesToInstall = DEFAULT_PIPES.filter( - (id) => !installedPipeIds.includes(id) - ); - - if (pipesToInstall.length === 0) return; - - // Create initial toast - const t = toast({ - title: "installing core pipes", - description: "setting up your workspace...", - duration: 100000, - }); - - // Install each missing pipe - for (const pipeId of pipesToInstall) { - const pipe = corePipes.find((p) => p.id === pipeId); - if (pipe?.url) { - try { - await handleDownloadPipe(pipe.url, pipe.id); - } catch (error) { - console.error(`Failed to install ${pipeId}:`, error); - } - } - } - - t.update({ - id: t.id, - title: "core pipes installed", - description: "your workspace is ready!", - duration: 2000, - }); - - await fetchInstalledPipes(); - }; - - installDefaultPipes(); - }, [health?.status]); + const filteredPipes = pipes + .filter( + (pipe) => + pipe.id.toLowerCase().includes(searchQuery.toLowerCase()) && + (!showInstalledOnly || pipe.is_installed) + ) + .sort((a, b) => Number(b.is_paid) - Number(a.is_paid)); - const handleResetAllPipes = async () => { + const fetchStorePlugins = async () => { try { - toast({ - title: "resetting pipes", - description: "this will delete all your pipes.", - }); - const cmd = Command.sidecar("screenpipe", ["pipe", "purge", "-y"]); - await cmd.execute(); - await new Promise((resolve) => setTimeout(resolve, 1000)); - toast({ - title: "all pipes deleted", - description: "the pipes folder has been reset.", - }); - // Refresh the pipe list and installed pipes - await fetchInstalledPipes(); + const pipeApi = await PipeApi.create(settings.user?.token!); + const plugins = await pipeApi.listStorePlugins(); + + // Create PipeWithStatus objects for store plugins + const storePluginsWithStatus = plugins.map((plugin) => ({ + ...plugin, + is_installed: installedPipes.some((p) => p.config?.id === plugin.id), + installed_config: installedPipes.find((p) => p.config?.id === plugin.id) + ?.config, + has_purchased: purchaseHistory.some((p) => p.plugins.id === plugin.id), + is_core_pipe: corePipes.includes(plugin.name), + })); + + const customPipes = installedPipes + .filter((p) => !plugins.some((plugin) => plugin.id === p.config?.id)) + .map((p) => { + console.log(p.config); + + const pluginName = p.config?.source?.split("/").pop(); + return { + id: p.config?.id || "", + name: pluginName || "", + description: "", + version: p.config?.version || "0.0.0", + is_paid: false, + price: 0, + status: "active", + created_at: new Date().toISOString(), + developer_accounts: { developer_name: "You" }, + plugin_analytics: { downloads_count: 0 }, + is_installed: true, + installed_config: p.config, + has_purchased: true, + is_core_pipe: false, + }; + }); + + setPipes([...storePluginsWithStatus, ...customPipes]); } catch (error) { - console.error("failed to reset pipes:", error); + console.error("Failed to fetch store plugins:", error); toast({ - title: "error resetting pipes", - description: "please try again or check the logs for more information.", + title: "error loading store", + description: "failed to fetch available pipes", variant: "destructive", }); - } finally { - setPipes([]); } }; - const fetchInstalledPipes = async () => { - if (!health || health?.status === "error") return; + const fetchPurchaseHistory = async () => { + if (!settings.user?.token) return; + const pipeApi = await PipeApi.create(settings.user!.token!); + const purchaseHistory = await pipeApi.getUserPurchaseHistory(); + setPurchaseHistory(purchaseHistory); + }; - const dataDir = await getDataDir(); - try { - const response = await fetch("http://localhost:3030/pipes/list"); - const data = await response.json(); + // TODO: replace with actual IDs once published on the new store + const installDefaultPipes = async () => { + const DEFAULT_PIPES = [ + "memories", + "data-table", + "search", + "timeline", + "identify-speakers", + ]; + }; - if (!data.success) throw new Error("Failed to fetch installed pipes"); + const handlePurchasePipe = async ( + pipe: PipeWithStatus, + onComplete?: () => void + ) => { + try { + if (!checkLogin(settings.user)) return; - const pipes = data.data; - for (const pipe of pipes) { - const pathToReadme = await join(dataDir, "pipes", pipe.id, "README.md"); - try { - const readme = await readFile(pathToReadme); - pipe.fullDescription = convertHtmlToMarkdown( - new TextDecoder().decode(readme) - ); - } catch (error) { - pipe.fullDescription = "no description available for this pipe."; - } - } - console.log("pipes", pipes); - setPipes(pipes); - return pipes; + const pipeApi = await PipeApi.create(settings.user!.token!); + const response = await pipeApi.purchasePipe(pipe.id); + openUrl(response.data.checkout_url); + onComplete?.(); } catch (error) { - console.error("Error fetching installed pipes:", error); + console.error("error purchasing pipe:", error); toast({ - title: "error fetching installed pipes", - description: "please try again or check the logs for more information.", + title: "error purchasing pipe", + description: "please try again or check the logs", variant: "destructive", }); } }; - const handleDownloadPipe = async (url: string, id: string) => { + const handleInstallSideload = async (url: string) => { + posthog.capture("add_own_pipe", { + newRepoUrl: url, + }); try { - posthog.capture("download_pipe", { - pipe_id: url, - }); - - // Create initial toast with progress bar const t = toast({ - title: "downloading pipe", + title: "adding custom pipe", description: (
-

starting download...

+

starting installation...

), - duration: 100000, // long duration + duration: 100000, }); - let value = 0; - // Update progress periodically const progressInterval = setInterval(() => { value += 3; t.update({ id: t.id, - title: "downloading pipe", + title: "adding custom pipe", description: (
@@ -477,8 +187,9 @@ const PipeStore: React.FC = () => { headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ url }), + body: JSON.stringify({ url: url }), }); + const data = await response.json(); clearInterval(progressInterval); @@ -489,7 +200,7 @@ const PipeStore: React.FC = () => { t.update({ id: t.id, - title: "pipe downloaded", + title: "pipe added", description: (
@@ -499,135 +210,153 @@ const PipeStore: React.FC = () => { duration: 2000, }); - // enable now - await fetch("http://localhost:3030/pipes/enable", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ pipe_id: id }), - }); - await fetchInstalledPipes(); - - const freshPipe = pipes.find( - (p) => normalizeId(p.id) === normalizeId(url) - ); - if (freshPipe) { - setSelectedPipe(freshPipe); - } t.dismiss(); } catch (error) { - console.error("Failed to download pipe:", error); + console.error("failed to add custom pipe:", error); toast({ - title: "error downloading pipe", - description: "please try again or check the logs for more information.", + title: "error adding custom pipe", + description: "please check the url and try again.", variant: "destructive", }); } }; - const checkExistingSubscription = async (pipeId: string) => { + const handleInstallPipe = async ( + pipe: PipeWithStatus, + onComplete?: () => void + ) => { try { - const { data, error } = await supabase - .from("subscriptions") - .select("*") - .eq("pipe_id", pipeId) - .eq("user_id", user?.id) - .single(); - - if (error) throw error; - return !!data; // returns true if subscription exists - } catch (error) { - console.error("failed to check subscription:", error); - return false; - } - }; + if (!checkLogin(settings.user)) return; - const handleToggleEnabled = async (pipe: Pipe) => { - try { - // Reset broken state when manually toggling - await updateBrokenPipes(pipe.id, false); - setStartupAttempts((prev) => { - const next = { ...prev }; - delete next[pipe.id]; - return next; + const t = toast({ + title: "downloading pipe", + description: ( +
+ +

downloading from server...

+
+ ), + duration: 100000, }); - // Set loading state when enabling - if (!pipe.enabled) { - setIsEnabling(true); - } + const pipeApi = await PipeApi.create(settings.user!.token!); + const response = await pipeApi.downloadPipe(pipe.id); - const corePipe = corePipes.find((cp) => cp.id === pipe.id); - console.log("attempting to toggle pipe:", { - pipeId: pipe.id, - isEnabled: pipe.enabled, - corePipe, - userToken: !!user?.token, - userCredits: user?.credits?.amount, + t.update({ + id: t.id, + title: "installing pipe", + description: ( +
+ +

installing dependencies...

+
+ ), + duration: 100000, }); - if (corePipe?.paid && !pipe.enabled) { - console.log("handling paid pipe enable flow"); - - if (!user?.token) { - console.log("user not authenticated, opening auth window"); - toast({ - title: "authentication required", - description: "please sign in in settings to use paid pipes", - variant: "destructive", - }); - return; + const downloadResponse = await fetch( + "http://localhost:3030/pipes/download-private", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + pipe_name: pipe.name, + pipe_id: pipe.id, + url: response.download_url, + }), } + ); + + const data = await downloadResponse.json(); + if (!data.success) { + throw new Error(data.error || "Failed to download pipe"); + } - const hasSubscription = await checkExistingSubscription(pipe.id); + await fetchInstalledPipes(); + + t.update({ + id: t.id, + title: "pipe installed", + description: ( +
+ +

completed successfully

+
+ ), + duration: 2000, + }); - console.log("subscription check:", { - hasSubscription, - pipeId: pipe.id, + onComplete?.(); + } catch (error) { + if ((error as Error).cause === PipeDownloadError.PURCHASE_REQUIRED) { + return toast({ + title: "paid pipe", + description: + "this pipe requires purchase. please visit screenpi.pe to buy credits.", + variant: "destructive", }); + } + toast({ + title: "error installing pipe", + description: (error as Error).message, + variant: "destructive", + }); + } + }; - if (!hasSubscription) { - const userCredits = user.credits?.amount || 0; - console.log("checking credits:", { - userCredits, - requiredCredits: corePipe.credits, - sufficient: userCredits >= corePipe.credits, - }); - - if (userCredits < corePipe.credits) { - console.log("insufficient credits, showing dialog"); - setShowCreditDialog(true); - return; - } + const fetchInstalledPipes = async () => { + if (!health || health?.status === "error") return; + try { + const response = await fetch("http://localhost:3030/pipes/list"); + const data = (await response.json()) as { + data: InstalledPipe[]; + success: boolean; + }; - console.log("attempting pipe purchase"); - const purchaseSuccess = await handlePipePurchase( - pipe, - corePipe.credits - ); - console.log("purchase result:", { purchaseSuccess }); + if (!data.success) throw new Error("Failed to fetch installed pipes"); - if (!purchaseSuccess) { - toast({ - title: "purchase failed", - description: "something went wrong, please try again", - variant: "destructive", - }); - return; - } + setInstalledPipes(data.data); + return data.data; + } catch (error) { + console.error("Error fetching installed pipes:", error); + toast({ + title: "error fetching installed pipes", + description: "please try again or check the logs", + variant: "destructive", + }); + } + }; - await refreshUser(); - console.log("user refreshed after purchase:", { - newCredits: user?.credits?.amount, - }); - } - } + const handleResetAllPipes = async () => { + try { + const cmd = Command.sidecar("screenpipe", ["pipe", "purge", "-y"]); + await cmd.execute(); + await fetchInstalledPipes(); + toast({ + title: "all pipes deleted", + description: "the pipes folder has been reset.", + }); + } catch (error) { + console.error("failed to reset pipes:", error); + toast({ + title: "error resetting pipes", + description: "please try again or check the logs", + variant: "destructive", + }); + } + }; + const handleTogglePipe = async ( + pipe: PipeWithStatus, + onComplete: () => void + ) => { + try { posthog.capture("toggle_pipe", { pipe_id: pipe.id, - enabled: !pipe.enabled, + enabled: !pipe.installed_config?.enabled, }); const t = toast({ @@ -641,40 +370,39 @@ const PipeStore: React.FC = () => { duration: 4000, }); - const endpoint = pipe.enabled ? "disable" : "enable"; - console.log(`calling ${endpoint} endpoint for pipe`); + const endpoint = pipe.installed_config?.enabled ? "disable" : "enable"; const response = await fetch(`http://localhost:3030/pipes/${endpoint}`, { method: "POST", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ pipe_id: pipe.id }), + body: JSON.stringify({ pipe_id: pipe.name }), }); const data = await response.json(); - console.log("toggle response:", data); if (!data.success) { throw new Error(data.error); } - // Wait for pipe to initialize - await new Promise((resolve) => setTimeout(resolve, 3000)); - const freshPipes = await fetchInstalledPipes(); - await new Promise((resolve) => setTimeout(resolve, 1000)); - - const freshPipe = freshPipes.find((p: Pipe) => p.id === pipe.id); - if (freshPipe) { - setSelectedPipe(freshPipe); - } - toast({ title: `pipe ${endpoint}d`, }); + setSelectedPipe((prev) => { + if (!prev) return prev; + return { + ...prev, + installed_config: { + ...prev.installed_config!, + enabled: !pipe.installed_config?.enabled, + }, + }; + }); + onComplete(); } catch (error) { console.error( - `Failed to ${pipe.enabled ? "disable" : "enable"} pipe:`, + `Failed to ${pipe.installed_config?.enabled ? "disable" : "enable"} pipe:`, error ); toast({ @@ -682,105 +410,12 @@ const PipeStore: React.FC = () => { description: "please try again or check the logs for more information.", variant: "destructive", }); - } finally { - // Reset loading state - setIsEnabling(false); - } - }; - - const reloadPipeConfig = async (pipe: Pipe) => { - await fetchInstalledPipes(); - - const freshPipe = pipes.find( - (p) => normalizeId(p.id) === normalizeId(pipe.id) - ); - if (freshPipe) { - console.log("freshPipe", freshPipe); - - setSelectedPipe(freshPipe); } }; - const handleAddOwnPipe = async () => { - if (newRepoUrl) { - try { - posthog.capture("add_own_pipe", { - newRepoUrl, - }); - - // Create initial toast with progress bar - const t = toast({ - title: "adding custom pipe", - description: ( -
- -

starting installation...

-
- ), - duration: 100000, // long duration - }); - - let value = 0; - - // Update progress periodically - const progressInterval = setInterval(() => { - value += 3; - t.update({ - id: t.id, - title: "adding custom pipe", - description: ( -
- -

installing dependencies...

-
- ), - duration: 100000, - }); - }, 500); - - const response = await fetch("http://localhost:3030/pipes/download", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ url: newRepoUrl }), - }); - - const data = await response.json(); - - clearInterval(progressInterval); - - if (!data.success) { - throw new Error(data.error || "Failed to download pipe"); - } - - t.update({ - id: t.id, - title: "pipe added", - description: ( -
- -

completed successfully

-
- ), - duration: 2000, - }); - - await fetchInstalledPipes(); - setNewRepoUrl(""); - t.dismiss(); - } catch (error) { - console.error("failed to add custom pipe:", error); - toast({ - title: "error adding custom pipe", - description: "please check the url and try again.", - variant: "destructive", - }); - } - } - }; - - const handleLoadFromLocalFolder = async () => { + const handleLoadFromLocalFolder = async ( + setNewRepoUrl: (url: string) => void + ) => { try { const selectedFolder = await open({ directory: true, @@ -788,6 +423,7 @@ const PipeStore: React.FC = () => { }); if (selectedFolder) { + console.log("loading from local folder", selectedFolder); // set in the bar setNewRepoUrl(selectedFolder); } @@ -800,17 +436,17 @@ const PipeStore: React.FC = () => { }); } }; + const handleConfigSave = async (config: Record) => { if (selectedPipe) { try { - setIsEnabling(true); const response = await fetch("http://localhost:3030/pipes/update", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - pipe_id: selectedPipe.id, + pipe_id: selectedPipe.name, config: config, }), }); @@ -825,8 +461,13 @@ const PipeStore: React.FC = () => { description: "The pipe configuration has been updated.", }); - await setSelectedPipe({ ...selectedPipe, config: config }); - setIsEnabling(false); + setSelectedPipe({ + ...selectedPipe, + installed_config: { + ...selectedPipe.installed_config!, + ...config, + }, + }); } catch (error) { console.error("Failed to save config:", error); toast({ @@ -835,13 +476,11 @@ const PipeStore: React.FC = () => { "please try again or check the logs for more information.", variant: "destructive", }); - setIsEnabling(false); } } }; - const handleDeletePipe = async (pipe: Pipe) => { + const handleDeletePipe = async (pipe: PipeWithStatus) => { try { - await updateBrokenPipes(pipe.id, false); posthog.capture("delete_pipe", { pipe_id: pipe.id, }); @@ -856,7 +495,7 @@ const PipeStore: React.FC = () => { headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ pipe_id: pipe.id }), + body: JSON.stringify({ pipe_id: pipe.name }), }); const data = await response.json(); @@ -871,6 +510,8 @@ const PipeStore: React.FC = () => { title: "pipe deleted", description: "the pipe has been successfully removed", }); + + setSelectedPipe(null); } catch (error) { console.error("failed to delete pipe:", error); toast({ @@ -881,43 +522,64 @@ const PipeStore: React.FC = () => { } }; - const allPipes = [ - ...pipes, - ...corePipes - .filter( - (cp) => !pipes.some((p) => normalizeId(p.id) === normalizeId(cp.id)) - ) - .map((cp) => ({ - id: cp.id, - fullDescription: coreReadmes[cp.id] || cp.description, // Fallback to short description - source: cp.url, - enabled: false, - })), - ]; - - const filteredPipes = allPipes - .filter( - (pipe) => - pipe.id.toLowerCase().includes(searchQuery.toLowerCase()) && - (!showInstalledOnly || pipe.enabled) - ) - .sort((a, b) => { - const aPaid = corePipes.find((cp) => cp.id === a.id)?.paid ? 1 : 0; - const bPaid = corePipes.find((cp) => cp.id === b.id)?.paid ? 1 : 0; - return bPaid - aPaid; // Sort paid pipes first - }); + const handleRefreshFromDisk = async (pipe: PipeWithStatus) => { + try { + posthog.capture("refresh_pipe_from_disk", { + pipe_id: pipe.name, + }); + + toast({ + title: "refreshing pipe", + description: "please wait...", + }); + + const response = await fetch(`http://localhost:3030/pipes/download`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ url: pipe.installed_config?.source }), + }); + if (!response.ok) { + throw new Error("failed to refresh pipe"); + } - const handleCloseDetails = async () => { - setSelectedPipe(null); - window.location.reload(); // dirty hack + await fetchInstalledPipes(); + toast({ + title: "pipe refreshed", + description: "the pipe has been successfully refreshed from disk.", + }); + } catch (error) { + console.error("failed to refresh pipe from disk:", error); + toast({ + title: "error refreshing pipe", + description: "please try again or check the logs for more information.", + variant: "destructive", + }); + } finally { + setSelectedPipe(null); + } }; - const handleUpdatePipe = async (pipe: Pipe) => { + const handleUpdatePipe = async (pipe: PipeWithStatus) => { try { + if (!checkLogin(settings.user)) return; + posthog.capture("update_pipe", { - pipe_id: pipe.id, + pipe_id: pipe.name, }); + const currentVersion = pipe.installed_config?.version!; + const storeApi = await PipeApi.create(settings.user!.token!); + const update = await storeApi.checkUpdate(pipe.id, currentVersion); + if (!update.has_update) { + toast({ + title: "no update available", + description: "the pipe is already up to date", + }); + return; + } + // Create initial toast with progress bar const t = toast({ title: "updating pipe", @@ -934,7 +596,7 @@ const PipeStore: React.FC = () => { await handleDeletePipe(pipe); // Then download the new version - if (pipe.source) { + if (pipe.installed_config?.source) { t.update({ id: t.id, title: "updating pipe", @@ -947,7 +609,7 @@ const PipeStore: React.FC = () => { duration: 100000, }); - await handleDownloadPipe(pipe.source, pipe.id); + await handleInstallPipe(pipe); } t.update({ @@ -976,492 +638,53 @@ const PipeStore: React.FC = () => { } }; - const checkPipeRunning = async (port: number): Promise => { - try { - // Use Tauri's http client instead of fetch to avoid CORS - const response = await fetch(`http://localhost:${port}`, { - mode: "no-cors", // Add no-cors mode to avoid CORS errors - }); - return true; // If we get here, the port is responding - } catch { - return false; - } - }; - - const checkRunningPipes = async () => { - const runningStates: Record = {}; - - // First check all pipes - for (const pipe of pipes) { - if (pipe.enabled && pipe.config?.port) { - runningStates[pipe.id] = await checkPipeRunning(pipe.config.port); - } - } - - // Then update states based on results - setRunningPipes((prevRunning) => { - setStartupAttempts((prevAttempts) => { - const updatedAttempts = { ...prevAttempts }; - - for (const pipe of pipes) { - if (pipe.enabled && pipe.config?.port) { - const isRunning = runningStates[pipe.id]; - - if (!isRunning) { - updatedAttempts[pipe.id] = (prevAttempts[pipe.id] || 0) + 1; - console.log( - `Attempt ${updatedAttempts[pipe.id]} for pipe ${pipe.id}` - ); - - if (updatedAttempts[pipe.id] >= MAX_STARTUP_ATTEMPTS) { - handleDisablePipe(pipe.id); - delete updatedAttempts[pipe.id]; - updateBrokenPipes(pipe.id, true); - } - } else { - delete updatedAttempts[pipe.id]; - updateBrokenPipes(pipe.id, false); - } - } - } - return updatedAttempts; - }); - return runningStates; - }); - }; - - // Separate function to handle pipe disabling - const handleDisablePipe = async (pipeId: string) => { - try { - await fetch(`http://localhost:3030/pipes/disable`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ pipe_id: pipeId }), - }); - - toast({ - title: "pipe startup failed", - description: - "the pipe has been disabled. please check the logs for more information.", - variant: "destructive", - }); - - // unselect the pipe - setSelectedPipe(null); - - await fetchInstalledPipes(); - } catch (error) { - console.error("failed to disable pipe:", error); - } - }; - - // Add this effect to periodically check running pipes useEffect(() => { - checkRunningPipes(); - }, [pipes]); - - const updateBrokenPipes = async (pipeId: string, isBroken: boolean) => { - const updated = isBroken - ? [...brokenPipes, { id: pipeId, lastAttempt: Date.now() }] - : brokenPipes.filter((p) => p.id !== pipeId); - - setBrokenPipes(updated); - await localforage.setItem(BROKEN_PIPES_KEY, updated); - }; - - const renderPipeDetails = () => { - if (!selectedPipe) return null; - - const isPipeRunning = runningPipes[selectedPipe.id]; - - return ( -
- cp.id === selectedPipe.id)?.credits || 0 - : 0 - } - currentCredits={user?.credits?.amount || 0} - onCreditsUpdated={refreshUser} - /> -
-
- -

- {getFriendlyName(selectedPipe.id, corePipes)} -

- - by {getAuthorFromSource(selectedPipe.source)} - -
-
- -
-
-
-
-
-
- - - - - - -

- {selectedPipe.enabled ? "disable" : "enable"} pipe -

-
-
-
- - - - {selectedPipe.source?.startsWith("http") && ( - - - - - - -

update pipe

-
-
-
- )} - - {selectedPipe.source?.startsWith("http") && ( - - - - - - -

view source code

-
-
-
- )} - - {!selectedPipe.source?.startsWith("https://") && ( - - - - - - -

refresh the code from your local disk

-
-
-
- )} -
- {/* Only show delete button for non-core pipes */} - {/* {!corePipes.some((cp) => cp.id === selectedPipe.id) && ( */} - - - - - - -

delete pipe

-
-
-
- {/* )} */} -
-
- - {corePipes.find((cp) => cp.id === selectedPipe.id)?.paid && ( -
- requires{" "} - { - corePipes.find((cp) => cp.id === selectedPipe.id) - ?.credits - }{" "} - credits{" "} - {user?.credits ? `(you have ${user.credits.amount})` : ""} -
- )} -
-
- - {selectedPipe.enabled && ( -
- -
- )} -
-
+ fetchStorePlugins(); + }, [installedPipes, purchaseHistory]); -
-
- {selectedPipe.enabled && selectedPipe?.config?.port && ( -
-
-
- - -
-
-
- )} - - {selectedPipe.fullDescription && ( -
-

about this pipe

-
- -
-
- )} -
-
-
-
- ); - }; - - const handleRefreshFromDisk = async (pipe: Pipe) => { - try { - posthog.capture("refresh_pipe_from_disk", { - pipe_id: pipe.id, - }); - - toast({ - title: "refreshing pipe", - description: "please wait...", - }); - - const response = await fetch(`http://localhost:3030/pipes/download`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ url: pipe.source }), - }); - if (!response.ok) { - throw new Error("failed to refresh pipe"); - } + useEffect(() => { + fetchPurchaseHistory(); + }, [settings.user]); - await fetchInstalledPipes(); - toast({ - title: "pipe refreshed", - description: "the pipe has been successfully refreshed from disk.", - }); - } catch (error) { - console.error("failed to refresh pipe from disk:", error); - toast({ - title: "error refreshing pipe", - description: "please try again or check the logs for more information.", - variant: "destructive", - }); - } finally { - setSelectedPipe(null); - } - }; + useEffect(() => { + fetchInstalledPipes(); + }, [health]); - const handleCardClick = async (pipe: Pipe) => { - // Rest of the existing logic - const isInstalled = pipes.some((p) => p.id === pipe.id); - if (!isInstalled && pipe.source) { - try { - await handleDownloadPipe(pipe.source, pipe.id); - // Fetch the updated pipe data and wait for it - const response = await fetch("http://localhost:3030/pipes/list"); - const data = await response.json(); + useEffect(() => { + const interval = setInterval(() => { + fetchInstalledPipes(); + }, 1000); + return () => clearInterval(interval); + }, []); - if (!data.success) throw new Error("Failed to fetch installed pipes"); - - // Get the data dir and fetch README for the new pipe - const dataDir = await getDataDir(); - const updatedPipe = data.data.find((p: Pipe) => p.id === pipe.id); - - if (updatedPipe) { - const pathToReadme = await join( - dataDir, - "pipes", - pipe.id, - "README.md" - ); - try { - const readme = await readFile(pathToReadme); - updatedPipe.fullDescription = convertHtmlToMarkdown( - new TextDecoder().decode(readme) - ); - } catch (error) { - updatedPipe.fullDescription = - "no description available for this pipe."; + useEffect(() => { + const setupDeepLink = async () => { + const unsubscribeDeepLink = await onOpenUrl(async (urls) => { + console.log("received deep link urls:", urls); + for (const url of urls) { + if (url.includes("purchase-successful")) { + fetchPurchaseHistory(); + toast({ + title: "purchase successful", + description: "your purchase has been successful", + }); } - // Update pipes state and set selected pipe - setPipes(data.data); - setSelectedPipe(updatedPipe); } - } catch (error) { - console.error("Failed to download and show pipe:", error); - toast({ - title: "error showing pipe details", - description: - "please try again or check the logs for more information.", - variant: "destructive", - }); - } - } else { - const installedPipe = pipes.find((p) => p.id === pipe.id); - setSelectedPipe(installedPipe || pipe); - } - }; - - const handlePipePurchase = async (pipe: Pipe, requiredCredits: number) => { - try { - const { data, error } = await supabase.rpc("purchase_pipe", { - v_user_id: user?.id, - p_pipe_id: pipe.id, - p_credits_spent: requiredCredits, }); + return unsubscribeDeepLink; + }; - if (error) { - console.error("purchase error:", error); - toast({ - title: "purchase failed", - description: error.message, - variant: "destructive", - }); - return false; - } - - if (!data) { - toast({ - title: "purchase failed", - description: "unknown error occurred", - variant: "destructive", - }); - return false; - } - - // Update local user credits state - if (user?.credits) { - user.credits.amount -= requiredCredits; - } + let deepLinkUnsubscribe: (() => void) | undefined; - toast({ - title: "pipe purchased", - description: `${requiredCredits} credits deducted`, - }); - - return true; - } catch (error) { - console.error("purchase failed:", error); - toast({ - title: "purchase failed", - description: "please try again or contact support", - variant: "destructive", - }); - return false; - } - }; + setupDeepLink().then((unsubscribe) => { + deepLinkUnsubscribe = unsubscribe; + }); + return () => { + if (deepLinkUnsubscribe) deepLinkUnsubscribe(); + }; + }, []); - // Add this empty state render function - const renderEmptyState = () => { + if (health?.status === "error") { return (
@@ -1480,22 +703,27 @@ const PipeStore: React.FC = () => {
); - }; - - // Add this check at the start of the component render - if (health?.status === "error") { - return renderEmptyState(); } if (selectedPipe) { - return renderPipeDetails(); + return ( + setSelectedPipe(null)} + onToggle={handleTogglePipe} + onConfigSave={handleConfigSave} + onDelete={handleDeletePipe} + onRefreshFromDisk={handleRefreshFromDisk} + onUpdate={handleUpdatePipe} + /> + ); } return (
-
+
{ checked={showInstalledOnly} onCheckedChange={setShowInstalledOnly} /> - - - - - - -

remove all pipes and start fresh

-
-
-
+
-
-
-
- {filteredPipes.map((pipe) => ( -
handleCardClick(pipe)} - > -
-
-
-

- {getFriendlyName(pipe.id, corePipes)} -

-
- - by {getAuthorFromSource(pipe.source)} - - {pipe.source?.startsWith("http") ? ( - { - e.stopPropagation(); - openUrl(pipe.source); - }} - /> - ) : ( - - )} -
-
-
- {pipes.some((p) => p.id === pipe.id) ? ( - <> - {pipes.find((p) => p.id === pipe.id)?.config - ?.port && - pipes.find((p) => p.id === pipe.id)?.enabled ? ( - - ) : null} - - ) : ( - - )} -
-
-
- -
-
- Updated recently -
- {corePipes.find((cp) => cp.id === pipe.id)?.paid && ( -
- requires{" "} - {corePipes.find((cp) => cp.id === pipe.id)?.credits}{" "} - credits{" "} - {user?.credits - ? `(you have ${user.credits.amount})` - : ""} -
- )} -
-
- ))} -
- -
-
-

add your own pipe

- -
-
-
- setNewRepoUrl(e.target.value)} - autoCorrect="off" - autoComplete="off" - disabled={health?.status === "error"} - /> -
- - -
- -
+
+
+ {filteredPipes.map((pipe) => ( + + ))}
+ +
+
); }; - -export default PipeStore; diff --git a/screenpipe-app-tauri/components/pipe-store/add-pipe-form.tsx b/screenpipe-app-tauri/components/pipe-store/add-pipe-form.tsx new file mode 100644 index 0000000000..80b4d04c32 --- /dev/null +++ b/screenpipe-app-tauri/components/pipe-store/add-pipe-form.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Plus, FolderOpen, Puzzle } from 'lucide-react'; +import { open } from '@tauri-apps/plugin-dialog'; +import { PublishDialog } from '../publish-dialog'; +import { PipeStorePlugin } from '@/lib/api/store'; + +interface AddPipeFormProps { + onAddPipe: (url: string) => Promise; + onLoadFromLocalFolder: (setNewRepoUrl: (url: string) => void) => Promise; + isHealthy: boolean; +} + +export const AddPipeForm: React.FC = ({ + onAddPipe, + onLoadFromLocalFolder, + isHealthy, +}) => { + const [newRepoUrl, setNewRepoUrl] = useState(''); + + return ( +
+
+
+ setNewRepoUrl(e.target.value)} + autoCorrect="off" + autoComplete="off" + disabled={!isHealthy} + /> +
+ + +
+ +
+ ); +}; \ No newline at end of file diff --git a/screenpipe-app-tauri/components/pipe-store/pipe-card.tsx b/screenpipe-app-tauri/components/pipe-store/pipe-card.tsx new file mode 100644 index 0000000000..505252e5a1 --- /dev/null +++ b/screenpipe-app-tauri/components/pipe-store/pipe-card.tsx @@ -0,0 +1,162 @@ +import React, { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Download, Puzzle, UserIcon } from "lucide-react"; +import { PipeStoreMarkdown } from "@/components/pipe-store-markdown"; +import { PipeWithStatus } from "./types"; +import { invoke } from "@tauri-apps/api/core"; +import { toast } from "@/components/ui/use-toast"; + +interface PipeCardProps { + pipe: PipeWithStatus; + onInstall: (pipe: PipeWithStatus, onComplete: () => void) => Promise; + onPurchase: (pipe: PipeWithStatus, onComplete: () => void) => Promise; + onClick: (pipe: PipeWithStatus) => void; +} + +const truncateDescription = (description: string, maxLines: number = 4) => { + if (!description) return ""; + const cleaned = description.replace(/Â/g, "").trim(); + + // Split into lines and track codeblock state + const lines = cleaned.split(/\r?\n/); + let inCodeBlock = false; + let visibleLines: string[] = []; + let lineCount = 0; + + for (const line of lines) { + // Check for codeblock markers + if (line.trim().startsWith("```")) { + inCodeBlock = !inCodeBlock; + visibleLines.push(line); + continue; + } + + // If we're in a codeblock, include the line + if (inCodeBlock) { + visibleLines.push(line); + continue; + } + + // For non-codeblock content, count lines normally + if (lineCount < maxLines) { + visibleLines.push(line); + if (line.trim()) lineCount++; + } + } + + // If we ended inside a codeblock, close it + if (inCodeBlock) { + visibleLines.push("```"); + } + + const result = visibleLines.join("\n"); + return lineCount >= maxLines ? result + "..." : result; +}; + +export const PipeCard: React.FC = ({ + pipe, + onInstall, + onPurchase, + onClick, +}) => { + const [isLoading, setIsLoading] = useState(false); + const handleOpenWindow = async (e: React.MouseEvent) => { + e.stopPropagation(); + try { + if (pipe.installed_config?.port) { + await invoke("open_pipe_window", { + port: pipe.installed_config.port, + title: pipe.id, + }); + } + } catch (err) { + console.error("failed to open pipe window:", err); + toast({ + title: "error opening pipe window", + description: "please try again or check the logs", + variant: "destructive", + }); + } + }; + + return ( +
onClick(pipe)} + > +
+
+
+
+ +
+
+

+ {pipe.name} +

+

+ +

+
+
+
+ {pipe.is_installed ? ( + + ) : ( + + )} +
+
+ {pipe.installed_config?.source === 'store' && ( +
+
+
+ +
+ {pipe.developer_accounts.developer_name} +
+ {pipe.plugin_analytics.downloads_count != null && ( + + + {pipe.plugin_analytics.downloads_count} + + )} +
+ )} +
+
+ ); +}; diff --git a/screenpipe-app-tauri/components/pipe-store/pipe-details.tsx b/screenpipe-app-tauri/components/pipe-store/pipe-details.tsx new file mode 100644 index 0000000000..67c17a940f --- /dev/null +++ b/screenpipe-app-tauri/components/pipe-store/pipe-details.tsx @@ -0,0 +1,265 @@ +import React, { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { + ExternalLink, + Power, + Puzzle, + RefreshCw, + Trash2, + X, +} from "lucide-react"; +import { PipeStoreMarkdown } from "@/components/pipe-store-markdown"; +import { PipeWithStatus } from "./types"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "../ui/tooltip"; +import { LogFileButton } from "../log-file-button"; +import { toast } from "../ui/use-toast"; +import { invoke } from "@tauri-apps/api/core"; +import { PipeConfigForm } from "../pipe-config-form"; +import { open as openUrl } from "@tauri-apps/plugin-shell"; +import { Badge } from "../ui/badge"; + +interface PipeDetailsProps { + pipe: PipeWithStatus; + onClose: () => void; + onToggle: (pipe: PipeWithStatus, onComplete: () => void) => void; + onConfigSave: (config: Record, onComplete: () => void) => void; + onUpdate: (pipe: PipeWithStatus, onComplete: () => void) => void; + onDelete: (pipe: PipeWithStatus, onComplete: () => void) => void; + onRefreshFromDisk: (pipe: PipeWithStatus, onComplete: () => void) => void; +} + +const isValidSource = (source?: string): boolean => { + if (!source) return false; + + // github url pattern + const githubPattern = /^https?:\/\/(?:www\.)?github\.com\/.+\/.+/i; + + // filesystem path patterns (unix and windows) + const unixPattern = /^(?:\/|~\/)/; + const windowsPattern = /^[a-zA-Z]:\\|^\\\\/; + + return ( + githubPattern.test(source) || + unixPattern.test(source) || + windowsPattern.test(source) + ); +}; + +export const PipeDetails: React.FC = ({ + pipe, + onClose, + onToggle, + onConfigSave, + onUpdate, + onDelete, + onRefreshFromDisk, +}) => { + const [isLoading, setIsLoading] = useState(false); + return ( +
+
+
+ +

{pipe.name}

+ + by {pipe.developer_accounts.developer_name} + +
+
+ +
+ {pipe.is_installed && ( +
+
+
+
+
+ + + + + + +

+ {pipe.installed_config?.enabled + ? "disable" + : "enable"}{" "} + pipe +

+
+
+
+ + + + {pipe.installed_config?.source && + isValidSource(pipe.installed_config.source) ? ( + + + + + + +

refresh the code from your local disk

+
+
+
+ ) : ( + + + + + + +

update pipe

+
+
+
+ )} + +
+ {/* Only show delete button for non-core pipes */} + {!pipe.is_core_pipe && ( + + + + + + +

delete pipe

+
+
+
+ )} +
+
+
+
+ + {pipe.installed_config?.enabled && ( +
+ { + onConfigSave(config, () => setIsLoading(false)); + }} + /> +
+ )} +
+
+ )} + +
+
+ {pipe.installed_config?.enabled && pipe.installed_config?.port && ( +
+
+
+ + +
+
+
+ )} + + {pipe.description && ( +
+

about this pipe

+
+ +
+
+ )} +
+
+
+
+ ); +}; diff --git a/screenpipe-app-tauri/components/pipe-store/types.ts b/screenpipe-app-tauri/components/pipe-store/types.ts new file mode 100644 index 0000000000..5b23260495 --- /dev/null +++ b/screenpipe-app-tauri/components/pipe-store/types.ts @@ -0,0 +1,29 @@ +import { PipeStorePlugin } from "@/lib/api/store"; + +export interface InstalledPipe { + config: { + id?: string; + enabled?: boolean; + is_nextjs: boolean; + port?: number; + source: string; + crons?: { + path: string; + schedule: string; + }[]; + fields?: Record; + version?: string; + }; +} + +export interface PipeWithStatus extends PipeStorePlugin { + is_installed: boolean; + installed_config?: InstalledPipe['config']; + has_purchased: boolean; + is_core_pipe: boolean; +} + +export interface BrokenPipe { + id: string; + lastAttempt: number; +} \ No newline at end of file diff --git a/screenpipe-app-tauri/components/publish-dialog.tsx b/screenpipe-app-tauri/components/publish-dialog.tsx index 216b40647a..cee1ab8622 100644 --- a/screenpipe-app-tauri/components/publish-dialog.tsx +++ b/screenpipe-app-tauri/components/publish-dialog.tsx @@ -20,10 +20,10 @@ import { TooltipTrigger, } from "@/components/ui/tooltip"; import { open as openUrl } from "@tauri-apps/plugin-shell"; -import { Pipe } from "./pipe-store"; +import { PipeWithStatus } from "./pipe-store/types"; interface PublishDialogProps { - app: Pipe | null; + app: PipeWithStatus | null; } export const PublishDialog: React.FC = ({ app }) => { diff --git a/screenpipe-app-tauri/components/recording-settings.tsx b/screenpipe-app-tauri/components/recording-settings.tsx index 1daae5af82..6bcb5acd0f 100644 --- a/screenpipe-app-tauri/components/recording-settings.tsx +++ b/screenpipe-app-tauri/components/recording-settings.tsx @@ -63,7 +63,6 @@ import { open } from "@tauri-apps/plugin-dialog"; import { exists } from "@tauri-apps/plugin-fs"; import { Command as ShellCommand } from "@tauri-apps/plugin-shell"; import { ToastAction } from "@/components/ui/toast"; -import { useUser } from "@/lib/hooks/use-user"; import { open as openUrl } from "@tauri-apps/plugin-shell"; import { Separator } from "./ui/separator"; import { MultiSelect } from "@/components/ui/multi-select"; @@ -142,8 +141,7 @@ export function RecordingSettings() { const [isMacOS, setIsMacOS] = useState(false); const [isSetupRunning, setIsSetupRunning] = useState(false); const [showApiKey, setShowApiKey] = useState(false); - const { user } = useUser(); - const { credits } = user || {}; + const { credits } = settings.user || {}; // Add new state to track if settings have changed const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); diff --git a/screenpipe-app-tauri/components/settings/account-section.tsx b/screenpipe-app-tauri/components/settings/account-section.tsx index d90d34377a..cf05a75723 100644 --- a/screenpipe-app-tauri/components/settings/account-section.tsx +++ b/screenpipe-app-tauri/components/settings/account-section.tsx @@ -21,6 +21,11 @@ import { Coins, UserCog, ExternalLinkIcon, + Key, + EyeOff, + Eye, + ArrowUpRight, + BookOpen, EyeIcon, EyeOffIcon, CopyIcon, @@ -28,10 +33,10 @@ import { import { toast } from "@/components/ui/use-toast"; -import { useUser } from "@/lib/hooks/use-user"; import { open as openUrl } from "@tauri-apps/plugin-shell"; import { Card } from "../ui/card"; import { onOpenUrl } from "@tauri-apps/plugin-deep-link"; +import { invoke } from "@tauri-apps/api/core"; function PlanCard({ title, @@ -83,8 +88,7 @@ function PlanCard({ } export function AccountSection() { - const { user, loadUser } = useUser(); - const { settings, updateSettings } = useSettings(); + const { settings, updateSettings, loadUser } = useSettings(); const [isRefreshing, setIsRefreshing] = useState(false); const [selectedPlan, setSelectedPlan] = useState(null); const [isConnectingStripe, setIsConnectingStripe] = useState(false); @@ -99,7 +103,6 @@ export function AccountSection() { const apiKey = new URL(url).searchParams.get("api_key"); if (apiKey) { updateSettings({ user: { token: apiKey } }); - loadUser(apiKey); toast({ title: "logged in!", description: "your api key has been set", @@ -109,9 +112,15 @@ export function AccountSection() { if (url.includes("return") || url.includes("refresh")) { console.log("stripe connect url:", url); if (url.includes("/return")) { - if (user) { - const updatedUser = { ...user, stripe_connected: true }; - updateSettings({ user: updatedUser }); + const apiKey = new URL(url).searchParams.get("api_key")!; + if (settings.user) { + updateSettings({ + user: { + ...settings.user, + api_key: apiKey, + stripe_connected: true, + }, + }); } toast({ title: "stripe connected!", @@ -137,14 +146,13 @@ export function AccountSection() { return () => { if (deepLinkUnsubscribe) deepLinkUnsubscribe(); }; - }, [settings.user?.token, loadUser, updateSettings]); + }, [settings.user?.token, updateSettings]); const handleRefreshCredits = async () => { if (!settings.user?.token) return; setIsRefreshing(true); try { - await loadUser(settings.user.token); toast({ title: "credits refreshed", description: "your credit balance has been updated", @@ -160,8 +168,8 @@ export function AccountSection() { } }; - const clientRefId = `${user?.id}&customer_email=${encodeURIComponent( - user?.email ?? "" + const clientRefId = `${settings.user?.id}&customer_email=${encodeURIComponent( + settings.user?.email ?? "" )}`; const plans = [ @@ -197,14 +205,17 @@ export function AccountSection() { const handleConnectStripe = async () => { setIsConnectingStripe(true); try { - const host = "https://screenpi.pe/api/dev-stripe"; + const BASE_URL = + (await invoke("get_env", { name: "BASE_URL_PRIVATE" })) ?? + "https://screenpi.pe"; + const host = `${BASE_URL}/api/dev-stripe`; const response = await fetch(host, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - user_id: user?.id, + user_id: settings.user?.id, }), }); @@ -231,6 +242,13 @@ export function AccountSection() { } }; + useEffect(() => { + console.log("document visibility state:", document.visibilityState); + + const updatedUser = { ...settings.user, stripe_connected: true }; + updateSettings({ user: updatedUser }); + }, []); + return (
@@ -264,7 +282,7 @@ export function AccountSection() {

credits & usage

- {user?.credits?.amount || 0} available + {settings.user?.credits?.amount || 0} available
- + {settings.user?.stripe_connected ? ( + + ) : ( + + )}
- -
-
-
- - estimated earnings - - $1,385.00 -
-
- {[40, 35, 55, 45, 60, 75, 65].map((height, i) => ( -
- ))} -
-
- pending payout - coming soon + {settings.user?.api_key && ( +
+
+
+
+ +
+
+
+
api key
+ +
+

+ {showApiKey + ? settings.user?.api_key + : settings.user?.api_key?.replace(/./g, "*")} +

+
+
+
- -
- -
- $ screenpipe publish my-awesome-pipe + )} +
+
+
+
+
+ +
+
+
documentation
+

+ learn how to build and publish custom pipes +

+
+
+ + read docs + +
diff --git a/screenpipe-app-tauri/components/settings/ai-section.tsx b/screenpipe-app-tauri/components/settings/ai-section.tsx index cf3f7e6d08..8379e4a394 100644 --- a/screenpipe-app-tauri/components/settings/ai-section.tsx +++ b/screenpipe-app-tauri/components/settings/ai-section.tsx @@ -30,7 +30,6 @@ import { Textarea } from "../ui/textarea"; import { toast } from "../ui/use-toast"; import { invoke } from "@tauri-apps/api/core"; import { open as openUrl } from "@tauri-apps/plugin-shell"; -import { useUser } from "@/lib/hooks/use-user"; import { Button } from "../ui/button"; import { cn } from "@/lib/utils"; import { Card, CardContent } from "../ui/card"; @@ -124,9 +123,7 @@ const AISection = () => { >("idle"); const [showApiKey, setShowApiKey] = React.useState(false); - const { user } = useUser(); - const { credits } = user || {}; const handleApiKeyChange = (e: React.ChangeEvent) => { updateSettings({ openaiApiKey: e.target.value }); }; @@ -350,11 +347,11 @@ const AISection = () => { imageSrc="/images/screenpipe.png" selected={settings.aiProviderType === "screenpipe-cloud"} onClick={() => handleAiProviderChange("screenpipe-cloud")} - disabled={!user} + disabled={!settings.user} warningText={ - !user + !settings.user ? "login required" - : !credits?.amount + : !settings.user?.credits?.amount ? "requires credits" : undefined } diff --git a/screenpipe-app-tauri/components/store/credit-purchase-dialog.tsx b/screenpipe-app-tauri/components/store/credit-purchase-dialog.tsx index 4d56dbeb6d..e9a30789ab 100644 --- a/screenpipe-app-tauri/components/store/credit-purchase-dialog.tsx +++ b/screenpipe-app-tauri/components/store/credit-purchase-dialog.tsx @@ -8,8 +8,8 @@ import { import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { open as openUrl } from "@tauri-apps/plugin-shell"; -import { useUser } from "@/lib/hooks/use-user"; import { Loader2 } from "lucide-react"; +import { useSettings } from "@/lib/hooks/use-settings"; interface CreditPurchaseDialogProps { open: boolean; @@ -26,17 +26,17 @@ export function CreditPurchaseDialog({ currentCredits, onCreditsUpdated, }: CreditPurchaseDialogProps) { - const { refreshUser, user } = useUser(); + const { settings, loadUser } = useSettings(); const [showRefreshHint, setShowRefreshHint] = useState(false); const [isLoading, setIsLoading] = useState(false); const handlePurchase = async (url: string) => { setIsLoading(true); await openUrl( - `${url}?client_reference_id=${user?.id}&metadata[user_id]=${user?.id}` + `${url}?client_reference_id=${settings.user?.id}&metadata[user_id]=${settings.user?.id}` ); setTimeout(async () => { - await refreshUser(); + await loadUser(settings.user?.token!); onCreditsUpdated?.(); setShowRefreshHint(true); setIsLoading(false); @@ -71,7 +71,7 @@ export function CreditPurchaseDialog({ variant="outline" onClick={() => handlePurchase( - `https://buy.stripe.com/5kA6p79qefweacg5kJ?client_reference_id=${user?.id}&customer_email=${encodeURIComponent(user?.email ?? '')}` + `https://buy.stripe.com/5kA6p79qefweacg5kJ?client_reference_id=${settings.user?.id}&customer_email=${encodeURIComponent(settings.user?.email ?? '')}` ) } disabled={isLoading} @@ -99,7 +99,7 @@ export function CreditPurchaseDialog({ variant="outline" onClick={() => handlePurchase( - `https://buy.stripe.com/eVaeVD45UbfYeswcNd?client_reference_id=${user?.id}&customer_email=${encodeURIComponent(user?.email ?? '')}` + `https://buy.stripe.com/eVaeVD45UbfYeswcNd?client_reference_id=${settings.user?.id}&customer_email=${encodeURIComponent(settings.user?.email ?? '')}` ) } disabled={isLoading} diff --git a/screenpipe-app-tauri/lib/api/store/index.ts b/screenpipe-app-tauri/lib/api/store/index.ts new file mode 100644 index 0000000000..47ad9ead04 --- /dev/null +++ b/screenpipe-app-tauri/lib/api/store/index.ts @@ -0,0 +1,209 @@ +import { invoke } from "@tauri-apps/api/core"; + +export interface PipeStorePlugin { + id: string; + name: string; + description: string | null; + is_paid: boolean | null; + price: number | null; + status: string | null; + created_at: string | null; + developer_accounts: { + developer_name: string; + }; + plugin_analytics: { + downloads_count: number | null; + }; +} + +export interface PipeDownloadResponse { + download_url: string; + file_hash: string; + file_size: number; +} + +export enum PipeDownloadError { + PURCHASE_REQUIRED = "purchase required", + DOWNLOAD_FAILED = "failed to download pipe", +} + +type PurchaseHistoryResponse = PurchaseHistoryItem[]; + +export interface PurchaseHistoryItem { + id: string; + amount_paid: number; + currency: string; + stripe_payment_status: string; + created_at: string; + refunded_at: null; + plugins: Plugins; +} +interface Plugins { + id: string; + name: string; + description: string; + developer_accounts: Developer_accounts; +} +interface Developer_accounts { + developer_name: string; +} + +interface PurchaseUrlResponse { + data: { + checkout_url: string; + }; +} + +export interface CheckUpdateResponse { + has_update: boolean; + current_version: string; + latest_version: string; + latest_file_hash: string; + latest_file_size: number; +} + +export class PipeApi { + private baseUrl: string; + private authToken: string; + + private constructor(authToken: string) { + this.baseUrl = "https://screenpi.pe"; + this.authToken = authToken; + } + + static async create(authToken: string): Promise { + const api = new PipeApi(authToken); + await api.init(authToken); + return api; + } + + private async init(authToken: string) { + try { + const BASE_URL = await invoke("get_env", { name: "BASE_URL_PRIVATE" }); + if (BASE_URL) { + this.baseUrl = BASE_URL as string; + } + this.authToken = authToken; + } catch (error) { + console.error("error initializing base url:", error); + } + } + + async getUserPurchaseHistory(): Promise { + try { + const response = await fetch( + `${this.baseUrl}/api/plugins/user-purchase-history`, + { + headers: { + Authorization: `Bearer ${this.authToken}`, + }, + } + ); + if (!response.ok) { + const { error } = (await response.json()) as { error: string }; + throw new Error(`failed to fetch purchase history: ${error}`); + } + const data = (await response.json()) as PurchaseHistoryResponse; + return data; + } catch (error) { + console.error("error getting purchase history:", error); + throw error; + } + } + + async listStorePlugins(): Promise { + try { + const response = await fetch(`${this.baseUrl}/api/plugins/registry`, { + headers: { + Authorization: `Bearer ${this.authToken}`, + }, + }); + if (!response.ok) { + const { error } = await response.json(); + throw new Error(`failed to fetch plugins: ${error}`); + } + const data: PipeStorePlugin[] = await response.json(); + return data; + } catch (error) { + console.error("error listing pipes:", error); + throw error; + } + } + + async purchasePipe(pipeId: string): Promise { + try { + const response = await fetch(`${this.baseUrl}/api/plugins/purchase`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${this.authToken}`, + }, + body: JSON.stringify({ pipe_id: pipeId }), + }); + if (!response.ok) { + const { error } = await response.json(); + throw new Error(`failed to purchase pipe: ${error}`); + } + const data = (await response.json()) as PurchaseUrlResponse; + return data; + } catch (error) { + console.error("error purchasing pipe:", error); + throw error; + } + } + + async downloadPipe(pipeId: string): Promise { + try { + const response = await fetch(`${this.baseUrl}/api/plugins/download`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${this.authToken}`, + }, + body: JSON.stringify({ pipe_id: pipeId }), + }); + + if (!response.ok) { + const { error } = (await response.json()) as { error: string }; + throw new Error(error!, { + cause: + response.status === 403 + ? PipeDownloadError.PURCHASE_REQUIRED + : PipeDownloadError.DOWNLOAD_FAILED, + }); + } + const data = (await response.json()) as PipeDownloadResponse; + return data; + } catch (error) { + console.error("error downloading pipe:", error); + throw error; + } + } + + async checkUpdate( + pipeId: string, + version: string + ): Promise { + try { + const response = await fetch(`${this.baseUrl}/api/plugins/check-update`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${this.authToken}`, + }, + body: JSON.stringify({ pipe_id: pipeId, version }), + }); + + if (!response.ok) { + const { error } = await response.json(); + throw new Error(`failed to check for updates: ${error}`); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error("error checking for updates:", error); + throw error; + } + } +} diff --git a/screenpipe-app-tauri/lib/hooks/use-health-check.tsx b/screenpipe-app-tauri/lib/hooks/use-health-check.tsx index a9c1af981b..8a9fb49a51 100644 --- a/screenpipe-app-tauri/lib/hooks/use-health-check.tsx +++ b/screenpipe-app-tauri/lib/hooks/use-health-check.tsx @@ -117,7 +117,7 @@ export function useHealthCheck() { } }, [isServerDown, setIsLoading]); - const debouncedFetchHealth = useCallback(debounce(fetchHealth, 200), [ + const debouncedFetchHealth = useCallback(debounce(fetchHealth, 1000), [ fetchHealth, ]); diff --git a/screenpipe-app-tauri/lib/hooks/use-settings.tsx b/screenpipe-app-tauri/lib/hooks/use-settings.tsx index 2c8122c2d3..7fb7547de0 100644 --- a/screenpipe-app-tauri/lib/hooks/use-settings.tsx +++ b/screenpipe-app-tauri/lib/hooks/use-settings.tsx @@ -12,6 +12,7 @@ import { import { LazyStore, LazyStore as TauriStore } from "@tauri-apps/plugin-store"; import { localDataDir } from "@tauri-apps/api/path"; import { flattenObject, unflattenObject } from "../utils"; +import { invoke } from "@tauri-apps/api/core"; export type VadSensitivity = "low" | "medium" | "high"; @@ -41,6 +42,7 @@ export type User = { image?: string; token?: string; clerk_id?: string; + api_key?: string; credits?: { amount: number; }; @@ -341,10 +343,42 @@ export function useSettings() { : `${homeDirPath}\\.screenpipe`; }; + const loadUser = async (token: string) => { + try { + const BASE_URL = await invoke("get_env", { name: "BASE_URL_PRIVATE" }) ?? "https://screenpi.pe"; + + const response = await fetch(`${BASE_URL}/api/tauri`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ token }), + }); + + if (!response.ok) { + throw new Error("failed to verify token"); + } + + const data = await response.json(); + const userData = { + ...data.user, + stripe_connected: data.user.stripe_connected ?? false, + } as User; + + setSettings({ + user: userData + }); + + } catch (err) { + console.error("failed to load user:", err); + } + }; + return { settings, updateSettings: setSettings, resetSettings, + loadUser, resetSetting, getDataDir, }; diff --git a/screenpipe-app-tauri/lib/hooks/use-user.ts b/screenpipe-app-tauri/lib/hooks/use-user.ts deleted file mode 100644 index 538fccb79d..0000000000 --- a/screenpipe-app-tauri/lib/hooks/use-user.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { useEffect, useState } from "react"; -import { User, useSettings } from "./use-settings"; -import { useInterval } from "./use-interval"; -import { fetch } from "@tauri-apps/plugin-http"; - -async function verifyUserToken(token: string): Promise { - const response = await fetch("https://screenpi.pe/api/tauri", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ token }), - }); - - if (!response.ok) { - throw new Error("failed to verify token"); - } - - const data = await response.json(); - return { - ...data.user, - stripe_connected: data.user.stripe_connected ?? false, - } as User; -} - -export function useUser() { - const [user, setUser] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); - const { settings, updateSettings } = useSettings(); - - // poll credits every 3 seconds if the settings dialog is open - useInterval(() => { - if (settings.user?.token) { - loadUser(settings.user.token); - } - }, 3000); - - const loadUser = async (token: string) => { - try { - const userData = await verifyUserToken(token); - // skip if user data did not change - if ( - userData.id === user?.id && - userData.credits?.amount === user?.credits?.amount - ) - return; - setUser(userData); - updateSettings({ user: userData }); - } catch (err) { - console.error("failed to load user:", err); - setError(err instanceof Error ? err.message : "failed to load user"); - } finally { - setIsLoading(false); - } - }; - - // explicit refresh function - const refreshUser = async () => { - if (settings.user?.token) { - await loadUser(settings.user.token); - } - }; - - // load from settings - useEffect(() => { - if (settings.user?.token) { - setUser(settings.user); - } - }, [settings.user?.token]); - - return { - user, - isSignedIn: !!user, - isLoading, - error, - loadUser, - refreshUser, // expose the refresh function - }; -} diff --git a/screenpipe-app-tauri/src-tauri/src/main.rs b/screenpipe-app-tauri/src-tauri/src/main.rs index c9468d3ed8..977f3bc15f 100755 --- a/screenpipe-app-tauri/src-tauri/src/main.rs +++ b/screenpipe-app-tauri/src-tauri/src/main.rs @@ -334,6 +334,11 @@ async fn apply_shortcuts(app: &AppHandle, config: &ShortcutConfig) -> Result<(), Ok(()) } +#[tauri::command] +fn get_env(name: &str) -> String { + std::env::var(String::from(name)).unwrap_or(String::from("")) +} + async fn get_pipe_port(pipe_id: &str) -> anyhow::Result { // Fetch pipe config from API let client = reqwest::Client::new(); @@ -672,6 +677,7 @@ async fn main() { commands::open_pipe_window, get_log_files, update_global_shortcuts, + get_env ]) .setup(|app| { // Logging setup diff --git a/screenpipe-app-tauri/src-tauri/tauri.conf.json b/screenpipe-app-tauri/src-tauri/tauri.conf.json index 2bcf4f5ef2..80a2a86eb2 100644 --- a/screenpipe-app-tauri/src-tauri/tauri.conf.json +++ b/screenpipe-app-tauri/src-tauri/tauri.conf.json @@ -63,6 +63,12 @@ "pathPrefix": [ "/stripe-connect" ] + }, + { + "host": "screenpi.pe", + "pathPrefix": [ + "/purchase-successful" + ] } ] } diff --git a/screenpipe-app-tauri/src-tauri/ui_monitor-aarch64-apple-darwin b/screenpipe-app-tauri/src-tauri/ui_monitor-aarch64-apple-darwin index 9aba920f6c708afde99c6a56d61c87a5961de5e5..509c1cea2bdcfb05407a91bfc2f3756db55b3fe5 100755 GIT binary patch delta 587 zcmX>wUFg7cp$$K{1rC3nt5JO4D5*U}QeWDI=i_D$9+NOerp>lV>xF^T+tT|IK6-X6$_kGGpVT>8wD?^Mx=Ekc#~x%>|?? z|5bz3ef|HKk!kBqMs{9CruK)tj6e*cnYTaWW!YV#kn%H$DcFT6x3B4&DB~U!wKVeO%kIXFw!VS~ zrK(@9X8ry5Sk#Brz1#nq_kJkR?VDNCEp;I1ZP~d6&oj1PDY-l8{Jga-S_fn}->M;~mgUb%hp*=je1L*=MbwpL9x MW776LEi5eT0O_0vj{pDw delta 587 zcmX>wUFg7cp$$K{1-?2=zihI~_TRcwiMns~|0Hha;4ukfRN8Etv|boUy)C^j0i@3M z$+LiXlj0eHl<$;k4j^@M&UI!+rO68y{0ET>KLdrPE;X9H4q@7)IqPTuaEhS8k-B|+hwL5|2D;8`kp411@)^Mey$NL-M4$o{!h&pS9V=*yH=x_`M!3-5ihBG z&NsC~qo-!FbX2Elq-#FisU$1rmGE`{N|!tQCZFf8uw7Pc$18qlU5|o8PlabU^Q%AG zbI->ukDI3<<@!cr@>c6!*TUGQ#Kr~p9=@v6@xAoObn(jN2iCc)U#O80c92y_JTuL} z@$Z8vJpCUXZtdw`6ynVu%nCdFd=^5siP`{k8j(HRKqNYxVV{vCoX_7Vsm=Tei0z0UbsyPNZsq6 z!~&!WC(K|3Qe2aMvjZu%S=y{X%4oh2NYHfwABYNB=*^>UdLja%@}H`LjMyH^ m#5f5kIsFAQ;};}ec8NUFzcUc(c@G(ZVR|zu$F%u9oZ?6(&snY`h1=>*~ diff --git a/screenpipe-core/Cargo.toml b/screenpipe-core/Cargo.toml index 9a9b1316b4..c6ae00a8e4 100644 --- a/screenpipe-core/Cargo.toml +++ b/screenpipe-core/Cargo.toml @@ -49,6 +49,7 @@ once_cell = "1.19.0" cron = "0.13.0" chrono = "0.4.38" sentry = { workspace = true } +zip = "0.6.2" [features] default = ["pipes", "security"] diff --git a/screenpipe-core/src/pipes.rs b/screenpipe-core/src/pipes.rs index 2fc652674b..174e8e182e 100644 --- a/screenpipe-core/src/pipes.rs +++ b/screenpipe-core/src/pipes.rs @@ -1167,6 +1167,98 @@ mod pipes { use std::net::TcpListener; TcpListener::bind(("127.0.0.1", port)).is_ok() } + + pub async fn download_pipe_private(pipe_name: &str, source: &str, screenpipe_dir: PathBuf) -> anyhow::Result { + info!("processing private pipe from zip: {}", source); + + let dest_dir = screenpipe_dir.join("pipes").join(&pipe_name); + debug!("destination directory: {:?}", dest_dir); + + // Create temp directory for download + let temp_dir = dest_dir.with_extension("_temp"); + tokio::fs::create_dir_all(&temp_dir).await?; + + // Download zip file + debug!("downloading zip file from: {}", source); + let client = Client::new(); + let response = client.get(source).send().await?; + let zip_content = response.bytes().await?; + + // Create temporary zip file + let temp_zip = temp_dir.join("temp.zip"); + tokio::fs::write(&temp_zip, &zip_content).await?; + + // Unzip the file using tokio spawn_blocking to handle sync operations + debug!("unzipping file to temp directory"); + let temp_zip_path = temp_zip.clone(); + let temp_dir_path = temp_dir.clone(); + + tokio::task::spawn_blocking(move || -> anyhow::Result<()> { + let zip_file = std::fs::File::open(&temp_zip_path)?; + let mut archive = zip::ZipArchive::new(zip_file)?; + + for i in 0..archive.len() { + let mut file = archive.by_index(i)?; + let name = file.name().to_string(); + let outpath = temp_dir_path.join(&name); + let ends_with_slash = name.ends_with('/'); + if ends_with_slash { + std::fs::create_dir_all(&outpath)?; + } else { + if let Some(p) = outpath.parent() { + if !p.exists() { + std::fs::create_dir_all(p)?; + } + } + let mut outfile = std::fs::File::create(&outpath)?; + std::io::copy(&mut file, &mut outfile)?; + } + } + Ok(()) + }).await??; + + // Remove the temporary zip file + tokio::fs::remove_file(&temp_zip).await?; + + // Move temp dir to final location + if dest_dir.exists() { + tokio::fs::remove_dir_all(&dest_dir).await?; + } + tokio::fs::rename(&temp_dir, &dest_dir).await?; + + // Check if it's a Next.js project + let package_json_path = dest_dir.join("package.json"); + let is_nextjs = if package_json_path.exists() { + let package_json = tokio::fs::read_to_string(&package_json_path).await?; + let package_data: Value = serde_json::from_str(&package_json)?; + package_data["dependencies"].get("next").is_some() + } else { + false + }; + + // Find bun path + let bun_path = find_bun_path().ok_or_else(|| anyhow::anyhow!("bun not found"))?; + + // Run bun install + info!("installing dependencies"); + retry_install(&bun_path, &dest_dir, 3).await?; + + if is_nextjs { + info!("detected next.js project, starting in production mode"); + // Update pipe.json to indicate it's a Next.js project + let pipe_json_path = dest_dir.join("pipe.json"); + if pipe_json_path.exists() { + let pipe_json = tokio::fs::read_to_string(&pipe_json_path).await?; + let mut pipe_config: Value = serde_json::from_str(&pipe_json)?; + pipe_config["is_nextjs"] = json!(true); + let updated_pipe_json = serde_json::to_string_pretty(&pipe_config)?; + tokio::fs::write(&pipe_json_path, updated_pipe_json).await?; + } + } + + info!("pipe downloaded and set up successfully at: {:?}", dest_dir); + Ok(dest_dir) + } } #[cfg(feature = "pipes")] diff --git a/screenpipe-server/Cargo.toml b/screenpipe-server/Cargo.toml index 1c878af541..d9fd3ab1c4 100644 --- a/screenpipe-server/Cargo.toml +++ b/screenpipe-server/Cargo.toml @@ -63,6 +63,7 @@ opentelemetry-semantic-conventions = "0.13" # Server axum = { version = "0.7.5", features = ["ws"] } +axum-macros = "0.5.0" async-stream = "0.3" tokio = { version = "1.15", features = ["full", "tracing"] } tower-http = { version = "0.5.2", features = ["cors", "trace"] } diff --git a/screenpipe-server/src/pipe_manager.rs b/screenpipe-server/src/pipe_manager.rs index 95681d93d7..86d12e03b6 100644 --- a/screenpipe-server/src/pipe_manager.rs +++ b/screenpipe-server/src/pipe_manager.rs @@ -2,7 +2,7 @@ use anyhow::Result; use killport::cli::Mode; use killport::killport::{Killport, KillportOperations}; use killport::signal::KillportSignal; -use screenpipe_core::{download_pipe, PipeState}; +use screenpipe_core::{download_pipe, download_pipe_private, PipeState}; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; @@ -85,11 +85,12 @@ impl PipeManager { if let Value::Object(updates) = new_config { // Update top-level properties for (key, value) in updates.iter() { - if key != "fields" { // Handle non-fields properties directly + if key != "fields" { + // Handle non-fields properties directly existing_config.insert(key.clone(), value.clone()); } } - + // Handle fields separately if they exist if let Some(Value::Array(new_fields)) = updates.get("fields") { existing_config.insert("fields".to_string(), Value::Array(new_fields.clone())); @@ -215,6 +216,37 @@ impl PipeManager { Ok(pipe_dir.file_name().unwrap().to_string_lossy().into_owned()) } + pub async fn download_pipe_private(&self, url: &str, pipe_name: &str, pipe_id: &str) -> Result { + let pipe_dir = download_pipe_private(&pipe_name, &url, self.screenpipe_dir.clone()).await?; + + let package_json_path = pipe_dir.join("package.json"); + let version = if package_json_path.exists() { + let package_json = tokio::fs::read_to_string(&package_json_path).await?; + let package_data: Value = serde_json::from_str(&package_json)?; + package_data["version"].as_str().unwrap_or("1.0.0").to_string() + } else { + "1.0.0".to_string() + }; + + // update the config with the source url and version + self.update_config( + &pipe_dir.file_name().unwrap().to_string_lossy(), + serde_json::json!({ + "source": "store", + "version": version, + "id": pipe_id, + }), + ) + .await?; + + info!( + "pipe {} downloaded", + pipe_dir.file_name().unwrap().to_string_lossy() + ); + + Ok(pipe_dir.file_name().unwrap().to_string_lossy().into_owned()) + } + pub async fn purge_pipes(&self) -> Result<()> { let pipe_dir = self.screenpipe_dir.join("pipes"); tokio::fs::remove_dir_all(pipe_dir).await?; @@ -256,7 +288,8 @@ impl PipeManager { let killport = Killport; let signal: KillportSignal = "SIGKILL".parse().unwrap(); - match killport.kill_service_by_port(port, signal.clone(), Mode::Auto, false) { + match killport.kill_service_by_port(port, signal.clone(), Mode::Auto, false) + { Ok(killed_services) => { if killed_services.is_empty() { debug!("no services found using port {}", port); @@ -273,7 +306,9 @@ impl PipeManager { warn!("error killing port {}: {}", port, e); } } - }).await.map_err(|e| anyhow::anyhow!("Failed to kill port: {}", e))?; + }) + .await + .map_err(|e| anyhow::anyhow!("Failed to kill port: {}", e))?; } PipeState::Pid(pid) => { // Force kill the process if it's still running diff --git a/screenpipe-server/src/server.rs b/screenpipe-server/src/server.rs index 2ef2bd6be4..c7e8fc0996 100644 --- a/screenpipe-server/src/server.rs +++ b/screenpipe-server/src/server.rs @@ -8,6 +8,7 @@ use axum::{ routing::{get, post}, serve, Router, }; +use axum_macros::debug_handler; use futures::{ future::{try_join, try_join_all}, SinkExt, Stream, StreamExt, @@ -647,6 +648,13 @@ struct DownloadPipeRequest { url: String, } +#[derive(Deserialize)] +struct DownloadPipePrivateRequest { + url: String, + pipe_name: String, + pipe_id: String, +} + #[derive(Deserialize)] struct RunPipeRequest { pipe_id: String, @@ -685,6 +693,31 @@ async fn download_pipe_handler( } } +async fn download_pipe_private_handler( + State(state): State>, + JsonResponse(payload): JsonResponse, +) -> Result, (StatusCode, JsonResponse)> { + match state.pipe_manager.download_pipe_private(&payload.url, &payload.pipe_name, &payload.pipe_id).await { + Ok(pipe_dir) => Ok(JsonResponse(json!({ + "data": { + "pipe_id": pipe_dir, + "message": "pipe downloaded successfully" + }, + "success": true + }))), + Err(e) => { + error!("Failed to download pipe: {}", e); + Err(( + StatusCode::INTERNAL_SERVER_ERROR, + JsonResponse(json!({ + "error": format!("failed to download pipe: {}", e), + "success": false + })), + )) + } + } +} + async fn run_pipe_handler( State(state): State>, JsonResponse(payload): JsonResponse, @@ -1813,6 +1846,7 @@ pub fn create_router() -> Router> { .route("/pipes/info/:pipe_id", get(get_pipe_info_handler)) .route("/pipes/list", get(list_pipes_handler)) .route("/pipes/download", post(download_pipe_handler)) + .route("/pipes/download-private", post(download_pipe_private_handler)) .route("/pipes/enable", post(run_pipe_handler)) .route("/pipes/disable", post(stop_pipe_handler)) .route("/pipes/update", post(update_pipe_config_handler))