Skip to content

Commit

Permalink
Plugin store new (#1169)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
neo773 authored Jan 24, 2025
1 parent b4487f7 commit da4f356
Show file tree
Hide file tree
Showing 30 changed files with 1,640 additions and 1,509 deletions.
Binary file added content/developer-account.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions content/docs/pages/docs/plugins.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,37 @@ follow installation instructions & test your pipe locally
bun dev
```

### developer CLI

for developers wanting to publish pipes to the store, we provide a dedicated CLI tool:

![developer account](https://raw.githubusercontent.com/mediar-ai/screenpipe/main/content/developer-account.png)

```bash copy
npm install -g @screenpipe/dev
```

prerequisite: connect your Stripe account in settings/account to obtain your developer API key.

available commands:

```bash copy
# authenticate with your API key
screenpipe login --apiKey <your-key>

# 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 <path>` and `screenpipe enable <id/folder of your pipe>`.

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.
Expand Down
31 changes: 29 additions & 2 deletions screenpipe-app-tauri/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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");
Expand Down Expand Up @@ -142,6 +168,7 @@ export default function Home() {
unlisten.then((listeners) => {
listeners.forEach((unlistenFn) => unlistenFn());
});
if (deepLinkUnsubscribe) deepLinkUnsubscribe();
};
}, []);

Expand Down
56 changes: 56 additions & 0 deletions screenpipe-app-tauri/components/login-dialog.tsx
Original file line number Diff line number Diff line change
@@ -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<LoginDialogProps> = ({ open, onOpenChange }) => {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent>
<DialogHeader>
<DialogTitle>login required</DialogTitle>
<DialogDescription>
please login to continue. you will be redirected to screenpi.pe
</DialogDescription>
</DialogHeader>
<div className='flex justify-end'>
<Button
variant='default'
onClick={() => {
openUrl('https://screenpi.pe/login');
onOpenChange(false);
}}
>
login <ExternalLinkIcon className='w-4 h-4 ml-2' />
</Button>
</div>
</DialogContent>
</Dialog>
);
};

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 };
};
5 changes: 1 addition & 4 deletions screenpipe-app-tauri/components/onboarding/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -22,7 +21,6 @@ const OnboardingLogin: React.FC<OnboardingLoginProps> = ({
handlePrevSlide,
handleNextSlide,
}) => {
const { user, loadUser } = useUser();
const { settings, updateSettings } = useSettings();

useEffect(() => {
Expand Down Expand Up @@ -68,7 +66,7 @@ const OnboardingLogin: React.FC<OnboardingLoginProps> = ({
<Coins className="w-4 h-4 text-muted-foreground" />
<h4 className="text-sm font-medium">credits & usage</h4>
<Badge variant="secondary" className="rounded-full px-2.5 py-0.5">
{user?.credits?.amount || 0} available
{settings.user?.credits?.amount || 0} available
</Badge>
</div>

Expand All @@ -91,7 +89,6 @@ const OnboardingLogin: React.FC<OnboardingLoginProps> = ({
variant="secondary"
size="sm"
onClick={async () => {
await loadUser(settings.user?.token || "");
toast({ title: "key verified" });
handleNextSlide();
}}
Expand Down
23 changes: 13 additions & 10 deletions screenpipe-app-tauri/components/pipe-config-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<string, any>) => void;
};

Expand All @@ -46,20 +46,23 @@ export const PipeConfigForm: React.FC<PipeConfigFormProps> = ({
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) => {
Expand Down
13 changes: 12 additions & 1 deletion screenpipe-app-tauri/components/pipe-store-markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -19,6 +20,7 @@ export function PipeStoreMarkdown({
variant = "default",
}: MarkdownProps) {
const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 });
const processedContent = convertHtmlToMarkdown(content);

return (
<div className={`prose prose-sm dark:prose-invert max-w-none ${className}`}>
Expand Down Expand Up @@ -97,9 +99,18 @@ export function PipeStoreMarkdown({
</a>
);
},
img({ node, ...props }) {
return (
<img
{...props}
className="max-w-full h-auto rounded-lg"
style={{ maxHeight: '600px' }}
/>
);
},
}}
>
{content.replace(/Â/g, "")}
{processedContent.replace(/Â/g, "")}
</MemoizedReactMarkdown>
</div>
);
Expand Down
Loading

0 comments on commit da4f356

Please sign in to comment.