Skip to content

Commit

Permalink
refactor: onboarding, fix: issue with mp4 files on macos being associ…
Browse files Browse the repository at this point in the history
…ated with screenpipe
  • Loading branch information
louis030195 committed Jan 14, 2025
1 parent 7a65244 commit a86cb53
Show file tree
Hide file tree
Showing 12 changed files with 705 additions and 220 deletions.
17 changes: 13 additions & 4 deletions .github/workflows/build-core-pipes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,19 @@ jobs:
bun install
bun run build
# create zip of dist folder
cd dist
zip -r ../../$pipe.zip .
cd ../..
# create zip only if build succeeded and dist exists
if [ -d "dist" ]; then
cd dist
zip -r ../../$pipe.zip .
cd ../..
else
echo "warning: no dist directory found for $pipe"
fi
# go back to root for next iteration
cd ../../
else
echo "warning: pipe directory $pipe not found"
fi
done
Expand Down
59 changes: 35 additions & 24 deletions screenpipe-app-tauri/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
"use client";

import { Settings } from "@/components/settings";
import { getStore, useSettings } from "@/lib/hooks/use-settings";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";

import React, { useEffect } from "react";
import NotificationHandler from "@/components/notification-handler";
Expand All @@ -18,19 +9,17 @@ import { usePostHog } from "posthog-js/react";
import { useToast } from "@/components/ui/use-toast";
import Onboarding from "@/components/onboarding";
import { useOnboarding } from "@/lib/hooks/use-onboarding";
import { registerShortcuts } from "@/lib/shortcuts";
import { ChangelogDialog } from "@/components/changelog-dialog";
import { BreakingChangesInstructionsDialog } from "@/components/breaking-changes-instructions-dialog";

import { Button } from "@/components/ui/button";
import { Plus } from "lucide-react";
import { platform } from "@tauri-apps/plugin-os";
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";

export default function Home() {
const { settings } = useSettings();
Expand Down Expand Up @@ -106,7 +95,9 @@ export default function Home() {
const devices = await getAudioDevices();
const pipeApi = new PipeApi();
console.log("audio-devices", devices);
await Promise.all(devices.map(device => pipeApi.startAudio(device)));
await Promise.all(
devices.map((device) => pipeApi.startAudio(device))
);
toast({
title: "audio started",
description: "audio has been started",
Expand All @@ -115,7 +106,8 @@ export default function Home() {
console.error("error starting audio:", error);
toast({
title: "error starting audio",
description: error instanceof Error ? error.message : "unknown error occurred",
description:
error instanceof Error ? error.message : "unknown error occurred",
variant: "destructive",
});
} finally {
Expand All @@ -137,8 +129,9 @@ export default function Home() {
} catch (error) {
console.error("error stopping audio:", error);
toast({
title: "error stopping audio",
description: error instanceof Error ? error.message : "unknown error occurred",
title: "error stopping audio",
description:
error instanceof Error ? error.message : "unknown error occurred",
variant: "destructive",
});
}
Expand All @@ -160,17 +153,35 @@ export default function Home() {
}
}, [settings.userId, posthog]);

useEffect(() => {
const checkScreenPermissionRestart = async () => {
const restartPending = await localforage.getItem(
"screenPermissionRestartPending"
);
if (restartPending) {
setShowOnboarding(true);
}
};

checkScreenPermissionRestart();
}, [setShowOnboarding]);

return (
<div className="flex flex-col items-center flex-1">
<NotificationHandler />
{showOnboarding && <Onboarding />}
<ChangelogDialog />
<BreakingChangesInstructionsDialog />
<Header />
<div className="h-[32px]" />
<div className=" w-[90%]">
<PipeStore />
</div>
{showOnboarding ? (
<Onboarding />
) : (
<>
<ChangelogDialog />
<BreakingChangesInstructionsDialog />
<Header />
<div className="h-[32px]" />
<div className=" w-[90%]">
<PipeStore />
</div>
</>
)}
</div>
);
}
77 changes: 66 additions & 11 deletions screenpipe-app-tauri/components/onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import OnboardingSelection from "@/components/onboarding/usecases-selection";
import OnboardingInstructions from "@/components/onboarding/explain-instructions";
import { useOnboarding } from "@/lib/hooks/use-onboarding";
import { useSettings } from "@/lib/hooks/use-settings";
import OnboardingLogin from "./onboarding/login";
import OnboardingPipeStore from "./onboarding/pipe-store";
import posthog from "posthog-js";

const setFirstTimeUserFlag = async () => {
await localforage.setItem("isFirstTimeUser", false);
Expand All @@ -21,12 +24,14 @@ const setFirstTimeUserFlag = async () => {
type SlideKey =
| "intro"
| "status"
| "login"
| "selection"
| "personalize"
| "apiSetup"
| "devOrNonDev"
| "devConfig"
| "pipes"
| "pipeStore"
| "instructions";

const slideFlow: Record<
Expand All @@ -51,9 +56,14 @@ const slideFlow: Record<
},
status: {
// status of screenpipe (blockage or not)
next: () => "selection",
next: () => "login",
prev: () => "intro",
},
login: {
// login
next: () => "apiSetup",
prev: () => "status",
},
selection: {
// selection (four options)
next: (selectedOptions) => {
Expand All @@ -78,16 +88,13 @@ const slideFlow: Record<
},
apiSetup: {
// api setup & validation
next: () => "instructions",
prev: (selectedOptions) => {
if (
selectedOptions?.length === 1 &&
selectedOptions?.includes("professionalUse")
) {
return "selection";
}
return "personalize";
},
next: () => "pipeStore",
prev: () => "login",
},
pipeStore: {
// pipe store
next: () => null,
prev: () => "apiSetup",
},
devOrNonDev: {
// dev or no dev
Expand Down Expand Up @@ -127,6 +134,16 @@ const slideFlow: Record<
},
};

const trackOnboardingStep = (
step: SlideKey | "completed",
properties?: Record<string, any>
) => {
posthog.capture("onboarding_step", {
step,
...properties,
});
};

const Onboarding: React.FC = () => {
const { toast } = useToast();
const [currentSlide, setCurrentSlide] = useState<SlideKey>("intro");
Expand Down Expand Up @@ -174,6 +191,14 @@ const Onboarding: React.FC = () => {
selectedPreference,
selectedPersonalization
);

trackOnboardingStep(currentSlide, {
selectedOptions,
selectedPreference,
selectedPersonalization,
direction: "next",
});

if (
currentSlide === "selection" &&
(!selectedOptions || selectedOptions.length === 0)
Expand Down Expand Up @@ -202,6 +227,14 @@ const Onboarding: React.FC = () => {

const handlePrevSlide = () => {
setIsVisible(false);

trackOnboardingStep(currentSlide, {
selectedOptions,
selectedPreference,
selectedPersonalization,
direction: "back",
});

setTimeout(() => {
const prevSlide = slideFlow[currentSlide].prev(
selectedOptions,
Expand Down Expand Up @@ -231,6 +264,12 @@ const Onboarding: React.FC = () => {
};

const handleEnd = async () => {
trackOnboardingStep("completed", {
finalOptions: selectedOptions,
finalPreference: selectedPreference,
finalPersonalization: selectedPersonalization,
});

setShowOnboarding(false);
await setFirstTimeUserFlag();
updateSettings({
Expand All @@ -257,6 +296,14 @@ const Onboarding: React.FC = () => {
handleNextSlide={handleNextSlide}
/>
)}
{currentSlide === "login" && (
<OnboardingLogin
className={`transition-opacity duration-300
${isVisible ? "opacity-100 ease-out" : "opacity-0 ease-in"}`}
handleNextSlide={handleNextSlide}
handlePrevSlide={handlePrevSlide}
/>
)}
{currentSlide === "selection" && (
<OnboardingSelection
className={`transition-opacity duration-300 ease-in-out
Expand Down Expand Up @@ -285,6 +332,14 @@ const Onboarding: React.FC = () => {
handlePrevSlide={handlePrevSlide}
/>
)}
{currentSlide === "pipeStore" && (
<OnboardingPipeStore
className={`transition-opacity duration-300 ease-in-out
${isVisible ? "opacity-100 ease-out" : "opacity-0 ease-in"}`}
handleNextSlide={handleEnd}
handlePrevSlide={handlePrevSlide}
/>
)}
{currentSlide === "devOrNonDev" && (
<OnboardingDevOrNonDev
className={`transition-opacity duration-300 ease-in-out
Expand Down
39 changes: 26 additions & 13 deletions screenpipe-app-tauri/components/onboarding/api-setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import AISection from "../settings/ai-section";

interface OnboardingAPISetupProps {
className?: string;
Expand Down Expand Up @@ -54,19 +55,26 @@ const OnboardingAPISetup: React.FC<OnboardingAPISetupProps> = ({

useEffect(() => {
const { aiUrl, openaiApiKey, aiModel } = localSettings;
const isApiKeyRequired = aiUrl !== "https://ai-proxy.i-f9f.workers.dev/v1" && aiUrl !== "http://localhost:11434/v1";

const isApiKeyRequired =
aiUrl !== "https://ai-proxy.i-f9f.workers.dev/v1" &&
aiUrl !== "http://localhost:11434/v1";

setAreAllInputsFilled(
aiUrl.trim() !== "" &&
aiModel.trim() !== "" &&
(!isApiKeyRequired || openaiApiKey.trim() !== "")
aiUrl.trim() !== "" &&
aiModel.trim() !== "" &&
(!isApiKeyRequired || openaiApiKey.trim() !== "")
);
}, [localSettings]);

const validateInputs = async () => {
const { aiUrl, openaiApiKey, aiModel } = localSettings;
const newErrors: { [key: string]: string } = {};
try {
const t = toast({
title: "validating AI provider",
description: "please wait...",
duration: 10000,
});
const response = await fetch(`${aiUrl}/chat/completions`, {
method: "POST",
headers: {
Expand All @@ -83,7 +91,7 @@ const OnboardingAPISetup: React.FC<OnboardingAPISetupProps> = ({
{
role: "user",
content:
"Tell me a short joke (1-2 sentences) about screen recording, answer in lower case only.",
"Tell me a very short joke (1-2 sentences) about screen recording, AI, and screenpipe, answer in lower case only.",
},
],
max_tokens: 60,
Expand All @@ -96,7 +104,8 @@ const OnboardingAPISetup: React.FC<OnboardingAPISetupProps> = ({
const joke = data.choices[0].message.content.trim();

console.log("ai is ready!", joke);
toast({
t.update({
id: t.id,
title: "ai is ready!",
description: `here's a joke: ${joke}`,
duration: 5000,
Expand Down Expand Up @@ -288,11 +297,15 @@ const OnboardingAPISetup: React.FC<OnboardingAPISetupProps> = ({
</DialogTitle>
</DialogHeader>
<Card className="mt-4">
<CardHeader>
<CardTitle className="text-center">setup api key</CardTitle>
</CardHeader>
<CardContent className="flex flex-col items-center space-y-4">
<div className="w-full max-w-md">
<CardContent className="flex flex-col items-center space-y-4 max-h-[60vh] overflow-y-auto ">
<AISection />
<div className="mb-16" />
<div className="mb-16" />
<div className="mb-16" />
<div className="mb-16" />
<div className="mb-16" />
<div className="mb-16" />
{/* <div className="w-full max-w-md">
<div className="flex items-center gap-2 mb-2">
<Label htmlFor="aiUrl" className="min-w-[100px] text-right">
ai provider
Expand Down Expand Up @@ -421,7 +434,7 @@ const OnboardingAPISetup: React.FC<OnboardingAPISetupProps> = ({
</Tooltip>
</TooltipProvider>
</div>
</div>
</div> */}
</CardContent>
</Card>
<a
Expand Down
Loading

0 comments on commit a86cb53

Please sign in to comment.