Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into windows
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsEeleeya committed Oct 21, 2024
2 parents 25b1889 + d85e535 commit 7c4c29d
Show file tree
Hide file tree
Showing 15 changed files with 226 additions and 331 deletions.
402 changes: 112 additions & 290 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions apps/desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "desktop"
version = "0.3.0-beta.5.7.1"
version = "0.3.0-beta.5.7.2"
description = "Beautiful, shareable screen recordings."
authors = ["you"]
edition = "2021"
Expand Down Expand Up @@ -84,7 +84,6 @@ rand = "0.8.5"
[target.'cfg(target_os = "macos")'.dependencies]
core-graphics = "0.24.0"
core-foundation = "0.10.0"
nokhwa-bindings-macos = { git = "https://github.com/CapSoftware/nokhwa", branch = "brendonovich-fork" }
objc2-app-kit = { version = "0.2.2", features = ["NSWindow", "NSResponder"] }
cocoa = "0.26.0"
objc = "0.2.7"
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"core:window:allow-set-focus",
"core:window:allow-start-dragging",
"core:window:allow-set-position",
"core:webview:default",
"core:webview:allow-create-webview-window",
"core:app:allow-version",
"shell:default",
Expand Down
9 changes: 8 additions & 1 deletion apps/desktop/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2247,6 +2247,12 @@ async fn reset_microphone_permissions(app: AppHandle) -> Result<(), ()> {
Ok(())
}

#[tauri::command]
#[specta::specta]
async fn is_camera_window_open(app: AppHandle) -> bool {
CapWindow::Camera { ws_port: 0 }.get(&app).is_some()
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub async fn run() {
let specta_builder = tauri_specta::Builder::new()
Expand Down Expand Up @@ -2301,7 +2307,8 @@ pub async fn run() {
set_general_settings,
delete_auth_open_signin,
reset_camera_permissions,
reset_microphone_permissions
reset_microphone_permissions,
is_camera_window_open
])
.events(tauri_specta::collect_events![
RecordingOptionsChanged,
Expand Down
3 changes: 1 addition & 2 deletions apps/desktop/src-tauri/src/permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ use serde::{Deserialize, Serialize};
use tauri::AppHandle;

#[cfg(target_os = "macos")]
use cap_media::platform::{AVAuthorizationStatus, AVMediaType};
use core_foundation::boolean::CFBoolean;
#[cfg(target_os = "macos")]
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; // Import CFDictionaryRef
#[cfg(target_os = "macos")]
use core_foundation::string::CFString;
#[cfg(target_os = "macos")]
use nokhwa_bindings_macos::{AVAuthorizationStatus, AVMediaType};

use crate::windows::CapWindow;

Expand Down
8 changes: 4 additions & 4 deletions apps/desktop/src/routes/(window-chrome)/changelog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ export default function Page() {
<For each={changelog()}>
{(entry, i) => (
<li class="border-b-2 border-gray-200 pb-8">
<div class="flex items-center gap-2 mb-2">
<div class="flex mb-2">
<Show when={i() === 0}>
<div class="bg-blue-400 text-white px-2 py-1 rounded-md uppercase font-bold">
<span style="color: #fff" class="text-xs">
New
</span>
</div>
</Show>
<h3 class="text-xl font-semibold text-gray-800">
{entry.title}
</h3>
</div>
<h3 class="text-xl font-semibold text-gray-800 mb-2">
{entry.title}
</h3>
<div class="text-gray-500 text-sm mb-4">
Version {entry.version} -{" "}
{new Date(entry.publishedAt).toLocaleDateString()}
Expand Down
47 changes: 32 additions & 15 deletions apps/desktop/src/routes/(window-chrome)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { createEventListener } from "@solid-primitives/event-listener";
import { cache, createAsync, redirect, useNavigate } from "@solidjs/router";
import { createMutation, createQuery } from "@tanstack/solid-query";
import { getVersion } from "@tauri-apps/api/app";
import { Window } from "@tauri-apps/api/window";
import { cx } from "cva";
import {
Show,
Expand Down Expand Up @@ -47,7 +46,7 @@ export const route = {
};

export default function () {
const options = createOptionsQuery();
const { options, setOptions } = createOptionsQuery();
const windows = createQuery(() => listWindows);
const videoDevices = createVideoDevicesQuery();
const audioDevices = createQuery(() => listAudioDevices);
Expand Down Expand Up @@ -87,7 +86,6 @@ export default function () {
}
});

// important for sign in redirect, trust me
createAsync(() => getAuth());

createUpdateCheck();
Expand Down Expand Up @@ -179,12 +177,25 @@ export default function () {

if (!item || !options.data) return;

commands.setRecordingOptions({
setOptions({
...options.data,
audioInputName: item.name !== "No Audio" ? item.name : null,
});
};

onMount(async () => {
if (options.data?.cameraLabel && options.data.cameraLabel !== "No Camera") {
const cameraWindowActive = await commands.isCameraWindowOpen();

if (!cameraWindowActive) {
console.log("cameraWindow not found");
setOptions({
...options.data,
});
}
}
});

return (
<div class="flex justify-center flex-col p-[1rem] gap-[0.75rem] text-[0.875rem] font-[400] bg-gray-50 h-full">
<div class="absolute top-3 right-3">
Expand Down Expand Up @@ -247,7 +258,7 @@ export default function () {
value={selectedWindow() ?? null}
onChange={(d: CaptureWindow | null) => {
if (!d || !options.data) return;
commands.setRecordingOptions({
setOptions({
...options.data,
captureTarget: { variant: "window", ...d },
});
Expand All @@ -265,7 +276,7 @@ export default function () {
return;
}
if (s === "screen") {
commands.setRecordingOptions({
setOptions({
...options.data,
captureTarget: { variant: "screen" },
});
Expand Down Expand Up @@ -330,12 +341,12 @@ export default function () {
if (!options.data) return;

if (!item || !item.isCamera) {
await commands.setRecordingOptions({
await setOptions({
...options.data,
cameraLabel: null,
});
} else {
await commands.setRecordingOptions({
await setOptions({
...options.data,
cameraLabel: item.name,
});
Expand Down Expand Up @@ -401,15 +412,17 @@ export default function () {
return requestPermission("camera");
}
if (!options.data?.cameraLabel) return;
commands.setRecordingOptions({
setOptions({
...options.data,
cameraLabel: null,
});
}}
>
{
isPermitted(permissions?.data?.camera) ? (options.data?.cameraLabel ? "On" : "Off") : "Request Permission"
}
{isPermitted(permissions?.data?.camera)
? options.data?.cameraLabel
? "On"
: "Off"
: "Request Permission"}
</button>
</KSelect.Trigger>
<KSelect.Portal>
Expand Down Expand Up @@ -490,21 +503,25 @@ export default function () {
if (permissions?.data?.microphone !== "granted") {
await requestPermission("microphone");
if (isPermitted(permissions?.data?.microphone)) {
commands.setRecordingOptions({
setOptions({
...options.data!,
audioInputName: audioDevice().name,
});
}
} else {
if (!options.data?.audioInputName) return;
commands.setRecordingOptions({
setOptions({
...options.data,
audioInputName: null,
});
}
}}
>
{isPermitted(permissions?.data?.microphone) ? (options.data?.audioInputName ? "On" : "Off") : "Request Permission"}
{isPermitted(permissions?.data?.microphone)
? options.data?.audioInputName
? "On"
: "Off"
: "Request Permission"}
</button>
</KSelect.Trigger>
<KSelect.Portal>
Expand Down
13 changes: 7 additions & 6 deletions apps/desktop/src/routes/(window-chrome)/update.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,13 @@ export default function () {
<div>
<Switch fallback={<IconCapLogo class="animate-spin size-4" />}>
<Match when={updateStatus()?.type === "done"}>
Update has been installed. Restart Cap to finish updating.
<div class="flex flex-row gap-4">
<Button variant="secondary" onClick={() => navigate("/")}>
Restart Later
</Button>
<Button onClick={() => relaunch()}>Restart Now</Button>
<div class="flex flex-col gap-4">
<p>
Update has been installed. Restart Cap to finish updating.
</p>
<div class="flex flex-row">
<Button onClick={() => relaunch()}>Restart Now</Button>
</div>
</div>
</Match>
<Match
Expand Down
5 changes: 2 additions & 3 deletions apps/desktop/src/routes/camera.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { ToggleButton as KToggleButton } from "@kobalte/core/toggle-button";
import { cx } from "cva";

import { createOptionsQuery } from "~/utils/queries";
import { commands } from "~/utils/tauri";
import { createImageDataWS, createLazySignal } from "~/utils/socket";

namespace CameraWindow {
Expand All @@ -37,7 +36,7 @@ const BAR_HEIGHT = 56;
const { cameraWsPort } = (window as any).__CAP__;

export default function () {
const options = createOptionsQuery();
const { options, setOptions } = createOptionsQuery();

const [state, setState] = makePersisted(
createStore<CameraWindow.State>({
Expand Down Expand Up @@ -133,7 +132,7 @@ export default function () {
<div class="flex flex-row gap-[0.25rem] p-[0.25rem] opacity-0 group-hover:opacity-100 translate-y-2 group-hover:translate-y-0 rounded-xl transition-[opacity,transform] bg-gray-500 border border-white-transparent-20 text-gray-400">
<ControlButton
onClick={() => {
commands.setRecordingOptions({
setOptions({
...options(),
cameraLabel: null,
});
Expand Down
43 changes: 38 additions & 5 deletions apps/desktop/src/utils/queries.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { createQuery, queryOptions } from "@tanstack/solid-query";
import { createTimer } from "@solid-primitives/timer";

import { commands } from "./tauri";
import { commands, RecordingOptions } from "./tauri";
import { createQueryInvalidate } from "./events";
import { createStore, reconcile } from "solid-js/store";
import { createMemo } from "solid-js";
import { createEffect, createMemo } from "solid-js";
import { makePersisted } from "@solid-primitives/storage";

export const listWindows = queryOptions({
queryKey: ["capture", "windows"] as const,
Expand Down Expand Up @@ -64,15 +64,48 @@ export const getPermissions = queryOptions({
refetchInterval: 1000,
});

type PartialRecordingOptions = Omit<RecordingOptions, "captureTarget">;
export function createOptionsQuery() {
const options = createQuery(() => getOptions);
const KEY = "recordingOptionsQuery";
const localState = localStorage.getItem(KEY);
const [state, setState, _init] = makePersisted(
createStore<PartialRecordingOptions>(
localState
? JSON.parse(localState)
: {
cameraLabel: null,
audioInputName: null,
}
)
);

const setOptions = (newOptions: RecordingOptions) => {
commands.setRecordingOptions(newOptions);
const { captureTarget: _, ...partialOptions } = newOptions;
setState(partialOptions);
};

createEffect(() => {
localStorage.setItem(KEY, JSON.stringify(state));
});

const options = createQuery(() => ({
...getOptions,
select: (data) => {
if (data && state) {
return { ...data, ...state };
}
},
}));

createQueryInvalidate(options, "recordingOptionsChanged");

return options;
return { options, setOptions };
}

export function createCurrentRecordingQuery() {
const currentRecording = createQuery(() => getCurrentRecording);

createQueryInvalidate(currentRecording, "currentRecordingChanged");

return currentRecording;
Expand Down
3 changes: 3 additions & 0 deletions apps/desktop/src/utils/tauri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ async resetMicrophonePermissions() : Promise<Result<null, null>> {
if(e instanceof Error) throw e;
else return { status: "error", error: e as any };
}
},
async isCameraWindowOpen() : Promise<boolean> {
return await TAURI_INVOKE("is_camera_window_open");
}
}

Expand Down
11 changes: 11 additions & 0 deletions apps/web/content/changelog/10.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: Auto shareable links + Remember previous camera/audio devices
app: Cap Desktop
publishedAt: "2024-10-19"
version: 0.3.0-beta.5.7.2
image:
---

- New "Auto create shareable link" option in settings
- New retry mechanism for shareable link uploads, if upload error is encountered
- Previously selected camera/audio devices will now be selected on startup
7 changes: 4 additions & 3 deletions crates/media/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ffmpeg.workspace = true
ffmpeg-sys-next.workspace = true
flume = "0.11.0"
indexmap = "2.5.0"
nokhwa = { git = "https://github.com/Brendonovich/nokhwa", rev = "2de5a760d5f1", features = [
nokhwa = { git = "https://github.com/filleduchaos/nokhwa", rev = "408354f6bcdd", features = [
"input-native",
"serialize",
] }
Expand All @@ -25,14 +25,15 @@ thiserror = "1.0"
tracing = "0.1"

[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.26.0"
core-graphics = "0.24.0"
core-foundation = "0.10.0"
nokhwa-bindings-macos = { git = "https://github.com/Brendonovich/nokhwa", rev = "2de5a760d5f1" }
nokhwa-bindings-macos = { git = "https://github.com/filleduchaos/nokhwa", rev = "408354f6bcdd" }

[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "0.52.0", features = [
"Win32_Foundation",
"Win32_System",
"Win32_UI_WindowsAndMessaging",
"Win32_Graphics_Dwm"
"Win32_Graphics_Dwm",
] }
1 change: 1 addition & 0 deletions crates/media/src/feeds/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ impl FrameConverter {
FrameFormat::NV12 => RawVideoFormat::Nv12,
FrameFormat::GRAY => RawVideoFormat::Gray,
FrameFormat::RAWRGB => RawVideoFormat::RawRgb,
FrameFormat::BGRA => RawVideoFormat::Bgra,
};

let video_info = VideoInfo::from_raw(
Expand Down
1 change: 1 addition & 0 deletions crates/media/src/platform/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use core_graphics::{
kCGWindowOwnerPID, CGWindowListCopyWindowInfo,
},
};
pub use nokhwa_bindings_macos::{AVAuthorizationStatus, AVMediaType};
use std::ffi::c_void;

use crate::platform::{Bounds, Window};
Expand Down

0 comments on commit 7c4c29d

Please sign in to comment.