Skip to content

Commit

Permalink
release: v0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
richiemcilroy committed Apr 17, 2024
1 parent 42cf3a3 commit 2b333d8
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 74 deletions.
2 changes: 1 addition & 1 deletion apps/desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"build": {
"beforeDevCommand": "next dev -p 3001",
"beforeDevCommand": "next dev -p 3001 --turbo",
"beforeBuildCommand": "next build",
"devPath": "http://localhost:3001",
"distDir": "../out",
Expand Down
4 changes: 3 additions & 1 deletion apps/desktop/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Recorder } from "@/components/windows/inner/Recorder";
import { WindowActions } from "@/components/WindowActions";
import { Permissions } from "@/components/windows/Permissions";
import { LogoSpinner } from "@cap/ui";
import { getPermissions, savePermissions } from "@/utils/helpers";
import { getPermissions } from "@/utils/helpers";
import { initializeCameraWindow } from "@/utils/recording/utils";
import { getVersion } from "@tauri-apps/api/app";
import { invoke } from "@tauri-apps/api/tauri";
Expand All @@ -19,6 +19,8 @@ export default function CameraPage() {
const [permissions, setPermissions] = useState(getPermissions());
const [permissionsLoaded, setPermissionsLoaded] = useState(false);

if (typeof window === "undefined") return null;

useEffect(() => {
const checkVersion = async () => {
const storedVersion = localStorage.getItem("cap_test_build_version");
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop/src/components/WindowActions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { exit } from "@tauri-apps/api/process";
import { Home } from "@/components/icons/Home";
// import { Settings } from "@/components/icons/Settings";
import { openLinkInBrowser } from "@/utils/helpers";

export const WindowActions = () => {
Expand Down
10 changes: 9 additions & 1 deletion apps/desktop/src/components/windows/Camera.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import React, { useEffect, useRef, useState } from "react";
import { useMediaDevices } from "@/utils/recording/MediaDeviceContext";
import { CloseX } from "@/components/icons/CloseX";
Expand All @@ -19,6 +21,8 @@ export const Camera = () => {
},
};

if (typeof navigator === "undefined") return;

navigator.mediaDevices
.getUserMedia(constraints)
.then((stream) => {
Expand All @@ -41,6 +45,8 @@ export const Camera = () => {
}, [selectedVideoDevice]);

const setWindowSize = async (type: "sm" | "lg") => {
if (typeof window === "undefined") return;

tauriWindowImport.then(
({ currentMonitor, appWindow, LogicalSize, LogicalPosition }) => {
currentMonitor().then((monitor) => {
Expand Down Expand Up @@ -70,7 +76,9 @@ export const Camera = () => {
};

const closeWindow = () => {
import("@tauri-apps/api/window").then(async ({ appWindow }) => {
if (typeof window === "undefined") return;

tauriWindowImport.then(async ({ appWindow }) => {
await emit("change-device", {
type: "video",
device: {
Expand Down
18 changes: 0 additions & 18 deletions apps/desktop/src/components/windows/Options.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
"use client";

// import { Recorder } from "@/components/windows/inner/Recorder";
import { SignIn } from "@/components/windows/inner/SignIn";
import { listen } from "@tauri-apps/api/event";
import { appWindow } from "@tauri-apps/api/window";
// import { useAuth } from "@/utils/database/AuthContext";

export const Options = () => {
// async function setupWindowReShow() {
// await listen("tauri://focus", () => {
// if (appWindow.isVisible) return;

// appWindow
// .show()
// .catch((err) => console.error("Error showing window:", err));
// });
// }

// setupWindowReShow();

return <SignIn />;
};
2 changes: 2 additions & 0 deletions apps/desktop/src/components/windows/Permissions.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import { Button, LogoBadge } from "@cap/ui";
import { useEffect, useState } from "react";
import { savePermissions, getPermissions } from "@/utils/helpers";
Expand Down
77 changes: 44 additions & 33 deletions apps/desktop/src/components/windows/inner/Recorder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ import { getLatestVideoId, saveLatestVideoId } from "@/utils/database/utils";
import { openLinkInBrowser } from "@/utils/helpers";
import toast, { Toaster } from "react-hot-toast";
import { authFetch } from "@/utils/auth/helpers";
import { appDataDir, join } from "@tauri-apps/api/path";
import { open } from "@tauri-apps/api/shell";
import * as Tauri from "@tauri-apps/api";

declare global {
interface Window {
Expand All @@ -42,6 +39,7 @@ export const Recorder = () => {
const [recordingTime, setRecordingTime] = useState("00:00");
const [canStopRecording, setCanStopRecording] = useState(false);
const [hasStartedRecording, setHasStartedRecording] = useState(false);
const tauriWindow = import("@tauri-apps/api/window");

const handleContextClick = async (option: "video" | "audio") => {
const { showMenu } = await import("tauri-plugin-context-menu");
Expand All @@ -52,37 +50,39 @@ export const Recorder = () => {
? selectedVideoDevice === null
: selectedAudioDevice === null;
}

return deviceKind === "videoinput"
? device.index === selectedVideoDevice?.index
: device.index === selectedAudioDevice?.index;
}
};
const select = async (device: Device | null) => {
// if (isSelected(device)) {
// return
// }
emit("change-device", { type: deviceKind, device: device }).catch((error) => {
console.log("Failed to emit change-device event:", error);
});
}
emit("change-device", { type: deviceKind, device: device }).catch(
(error) => {
console.log("Failed to emit change-device event:", error);
}
);
};

const devicesOfKind = devices.filter((device) => device.kind === deviceKind);
const devicesOfKind = devices.filter(
(device) => device.kind === deviceKind
);

const menuItems = [
{
label: "None",
checked: isSelected(null),
event: async() => select(null)
event: async () => select(null),
},
...devicesOfKind.map((device) => (
{
label: device.label,
checked: isSelected(device),
event: async() => select(device)
}
))
]

...devicesOfKind.map((device) => ({
label: device.label,
checked: isSelected(device),
event: async () => select(device),
})),
];

await showMenu({
items: [...menuItems],
...(devicesOfKind.length === 0 && {
Expand Down Expand Up @@ -137,18 +137,20 @@ export const Recorder = () => {

useEffect(() => {
let unlistenFn: UnlistenFn | null = null;

const setupListener = async () => {
unlistenFn = await listen("tray-on-left-click", (_) => {
if (isRecording) {
handleStopAllRecordings();
}

const currentWindow = Tauri.window.getCurrent();
if (!currentWindow.isVisible) {
currentWindow.show();
}
currentWindow.setFocus();
tauriWindow.then(({ getCurrent }) => {
const currentWindow = getCurrent();
if (!currentWindow.isVisible) {
currentWindow.show();
}
currentWindow.setFocus();
});
});
};

Expand Down Expand Up @@ -178,12 +180,13 @@ export const Recorder = () => {
if (window.fathom !== undefined) {
window.fathom.trackEvent("start_recording");
}
Tauri.window.getAll().forEach((window) => {
if (window.label !== "camera") {
window.hide();
}
tauriWindow.then(({ getAll }) => {
getAll().forEach((window) => {
if (window.label !== "camera") {
window.hide();
}
});
});

emit("toggle-recording", true);
await invoke("start_dual_recording", {
options: {
Expand Down Expand Up @@ -376,7 +379,11 @@ export const Recorder = () => {
width="full"
handler={() => handleContextClick("video")}
icon={<Video className="w-5 h-5" />}
label={devices.length === 0 ? "Video" : selectedVideoDevice?.label || "None"}
label={
devices.length === 0
? "Video"
: selectedVideoDevice?.label || "None"
}
active={selectedVideoDevice !== null}
recordingOption={true}
optionName="Video"
Expand All @@ -385,7 +392,11 @@ export const Recorder = () => {
width="full"
handler={() => handleContextClick("audio")}
icon={<Microphone className="w-5 h-5" />}
label={devices.length === 0 ? "Mic" : selectedAudioDevice?.label || "None"}
label={
devices.length === 0
? "Mic"
: selectedAudioDevice?.label || "None"
}
active={selectedAudioDevice !== null}
recordingOption={true}
optionName="Audio"
Expand Down
57 changes: 40 additions & 17 deletions apps/desktop/src/utils/recording/MediaDeviceContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,20 @@ export const MediaDeviceContext = createContext<
export const MediaDeviceProvider: React.FC<React.PropsWithChildren<{}>> = ({
children,
}) => {
const [selectedVideoDevice, setSelectedVideoDevice] =
useState<Device | null>(null);
const [selectedAudioDevice, setSelectedAudioDevice] =
useState<Device | null>(null);
const [selectedVideoDevice, setSelectedVideoDevice] = useState<Device | null>(
null
);
const [selectedAudioDevice, setSelectedAudioDevice] = useState<Device | null>(
null
);
const [selectedDisplayType, setSelectedDisplayType] = useState<
"screen" | "window" | "area"
>("screen");
const [devices, setDevices] = useState<Device[]>([]);
const [isRecording, setIsRecording] = useState(false);
const [startingRecording, setStartingRecording] = useState(false);
const getDevicesCalled = useRef(false);
const tauriWindowImport = import("@tauri-apps/api/window");

const getDevices = useCallback(async () => {
await enumerateAndStoreDevices();
Expand Down Expand Up @@ -111,48 +114,70 @@ export const MediaDeviceProvider: React.FC<React.PropsWithChildren<{}>> = ({
if (!type) {
return;
}

if (typeof window === "undefined") return;

if (window.fathom !== undefined) {
window.fathom.trackEvent(`${type === "videoinput" ? "video" : "audio"}_device_change`);
window.fathom.trackEvent(
`${type === "videoinput" ? "video" : "audio"}_device_change`
);
}
if (type === "videoinput") {
import("@tauri-apps/api/window").then(({ WebviewWindow }) => {
tauriWindowImport.then(({ WebviewWindow }) => {
if (WebviewWindow.getByLabel("camera")) {
WebviewWindow.getByLabel("camera").close();
} else if (type === "videoinput" && device) {
initializeCameraWindow();
}
});

if ((!device && selectedVideoDevice) || (selectedVideoDevice?.index !== device?.index)) {

if (
(!device && selectedVideoDevice) ||
selectedVideoDevice?.index !== device?.index
) {
setSelectedVideoDevice(device);
}
}

if (type === "audioinput") {
if ((!device && selectedAudioDevice) || (selectedAudioDevice?.index !== device?.index)) {
if (
(!device && selectedAudioDevice) ||
selectedAudioDevice?.index !== device?.index
) {
setSelectedAudioDevice(device);
}
}
}
};

useEffect(() => {
let unlistenFnChangeDevice: any;
let unlistenFnTraySetDevice: any;

const setupListeners = async () => {
try {
unlistenFnChangeDevice = await listen<{ type: string, device: Device | null }>("change-device", (event) => {
updateSelectedDevice(event.payload.type as DeviceKind, event.payload.device);
unlistenFnChangeDevice = await listen<{
type: string;
device: Device | null;
}>("change-device", (event) => {
updateSelectedDevice(
event.payload.type as DeviceKind,
event.payload.device
);
});
} catch (error) {
console.error("Error setting up change-device listener:", error);
}

try {
unlistenFnTraySetDevice = await listen<{ type: string, id: string | null }>("tray-set-device-id", (event) => {
unlistenFnTraySetDevice = await listen<{
type: string;
id: string | null;
}>("tray-set-device-id", (event) => {
const id = event.payload.id;
const kind = event.payload.type as DeviceKind;
const newDevice = id ? devices.find((device) => kind === device.kind && id === device.id) : null;
const newDevice = id
? devices.find((device) => kind === device.kind && id === device.id)
: null;
updateSelectedDevice(kind, newDevice);
});
} catch (error) {
Expand All @@ -164,9 +189,7 @@ export const MediaDeviceProvider: React.FC<React.PropsWithChildren<{}>> = ({

if (devices.length !== 0) {
emit("media-devices-set", {
mediaDevices: [
...(devices as Omit<Device, 'index'>[])
],
mediaDevices: [...(devices as Omit<Device, "index">[])],
selectedVideo: selectedVideoDevice,
selectedAudio: selectedAudioDevice,
});
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/utils/recording/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"use client";

import { emit } from "@tauri-apps/api/event";
import { invoke } from "@tauri-apps/api/tauri";

export const enumerateAndStoreDevices = async () => {
Expand Down Expand Up @@ -51,6 +50,7 @@ export const getSelectedVideoProperties = async () => {
};

export const initializeCameraWindow = async () => {
if (typeof window === "undefined") return;
import("@tauri-apps/api/window").then(({ currentMonitor, WebviewWindow }) => {
currentMonitor().then((monitor) => {
const windowWidth = 230;
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.2.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev --turbo",
"build": "next build",
"start": "next start",
"lint": "next lint"
Expand Down

0 comments on commit 2b333d8

Please sign in to comment.