Skip to content

Commit fe7dd1d

Browse files
committed
Improve camera overlay resizing and editor captions state
1 parent 10e22e5 commit fe7dd1d

File tree

8 files changed

+120
-29
lines changed

8 files changed

+120
-29
lines changed

apps/desktop/src-tauri/src/camera.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ impl CameraPreviewManager {
116116
self.preview.is_some()
117117
}
118118

119+
pub fn notify_window_resized(&self, width: u32, height: u32) {
120+
if let Some(preview) = &self.preview {
121+
preview
122+
.reconfigure
123+
.send(ReconfigureEvent::WindowResized { width, height })
124+
.map_err(|err| error!("Error notifying camera preview of resize: {err}"))
125+
.ok();
126+
}
127+
}
128+
119129
/// Initialize the camera preview for a specific Tauri window
120130
pub async fn init_window(
121131
&mut self,
@@ -169,6 +179,7 @@ impl CameraPreviewManager {
169179
#[derive(Clone)]
170180
enum ReconfigureEvent {
171181
State(CameraPreviewState),
182+
WindowResized { width: u32, height: u32 },
172183
Shutdown,
173184
}
174185

@@ -604,6 +615,10 @@ impl Renderer {
604615
self.reconfigure_gpu_surface(width, height);
605616
}
606617
}
618+
Err(ReconfigureEvent::WindowResized { width, height }) => {
619+
trace!("CameraPreview/ReconfigureEvent.WindowResized({width}x{height})");
620+
self.reconfigure_gpu_surface(width, height);
621+
}
607622
Err(ReconfigureEvent::Shutdown) => return,
608623
}
609624
}

apps/desktop/src-tauri/src/target_select_overlay.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use base64::prelude::*;
99
use cap_recording::screen_capture::ScreenCaptureTarget;
1010

1111
use crate::{
12-
general_settings,
12+
App, ArcLock, general_settings,
1313
window_exclusion::WindowExclusion,
1414
windows::{CapWindowId, ShowCapWindow},
1515
};
@@ -163,10 +163,13 @@ pub async fn update_camera_overlay_bounds(
163163
.get_webview_window("camera")
164164
.ok_or("Camera window not found")?;
165165

166+
let width_u32 = width as u32;
167+
let height_u32 = height as u32;
168+
166169
window
167170
.set_size(tauri::Size::Physical(tauri::PhysicalSize {
168-
width: width as u32,
169-
height: height as u32,
171+
width: width_u32,
172+
height: height_u32,
170173
}))
171174
.map_err(|e| e.to_string())?;
172175
window
@@ -176,6 +179,16 @@ pub async fn update_camera_overlay_bounds(
176179
}))
177180
.map_err(|e| e.to_string())?;
178181

182+
let scale_factor = window.scale_factor().unwrap_or(1.0);
183+
let logical_width = (width / scale_factor) as u32;
184+
let logical_height = (height / scale_factor) as u32;
185+
186+
let state = app.state::<ArcLock<App>>();
187+
let app_state = state.read().await;
188+
app_state
189+
.camera_preview
190+
.notify_window_resized(logical_width, logical_height);
191+
179192
Ok(())
180193
}
181194

apps/desktop/src/routes/camera.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,15 +700,18 @@ function Canvas(props: {
700700
latestFrame: Accessor<{ width: number; data: ImageData } | null | undefined>;
701701
state: CameraWindowState;
702702
ref: HTMLCanvasElement | undefined;
703+
containerSize?: { width: number; height: number };
703704
}) {
704705
const style = () => {
705706
const frame = props.latestFrame();
706707
if (!frame) return {};
707708

708709
const aspectRatio = frame.data.width / frame.data.height;
709710

710-
// Use state.size directly for immediate feedback
711-
const base = props.state.size;
711+
// Use container size if available (for external resize), otherwise use state.size
712+
const base = props.containerSize
713+
? Math.min(props.containerSize.width, props.containerSize.height)
714+
: props.state.size;
712715

713716
// Replicate window size logic synchronously for the canvas
714717
const winWidth =
@@ -741,7 +744,7 @@ function Canvas(props: {
741744
else
742745
return {
743746
width: base,
744-
height: base * aspectRatio,
747+
height: base / aspectRatio,
745748
};
746749
})();
747750

apps/desktop/src/routes/editor/CaptionsTab.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ function RgbInput(props: { value: string; onChange: (value: string) => void }) {
150150
}
151151

152152
export function CaptionsTab() {
153-
const { project, setProject, editorInstance, editorState } =
153+
const { project, setProject, editorInstance, editorState, setEditorState } =
154154
useEditorContext();
155155

156156
const getSetting = <K extends keyof CaptionSettings>(
@@ -172,12 +172,18 @@ export function CaptionsTab() {
172172
const [selectedLanguage, setSelectedLanguage] = createSignal("auto");
173173
const [downloadedModels, setDownloadedModels] = createSignal<string[]>([]);
174174

175-
const [isDownloading, setIsDownloading] = createSignal(false);
176-
const [downloadProgress, setDownloadProgress] = createSignal(0);
177-
const [downloadingModel, setDownloadingModel] = createSignal<string | null>(
178-
null,
179-
);
180-
const [isGenerating, setIsGenerating] = createSignal(false);
175+
const isDownloading = () => editorState.captions.isDownloading;
176+
const setIsDownloading = (value: boolean) =>
177+
setEditorState("captions", "isDownloading", value);
178+
const downloadProgress = () => editorState.captions.downloadProgress;
179+
const setDownloadProgress = (value: number) =>
180+
setEditorState("captions", "downloadProgress", value);
181+
const downloadingModel = () => editorState.captions.downloadingModel;
182+
const setDownloadingModel = (value: string | null) =>
183+
setEditorState("captions", "downloadingModel", value);
184+
const isGenerating = () => editorState.captions.isGenerating;
185+
const setIsGenerating = (value: boolean) =>
186+
setEditorState("captions", "isGenerating", value);
181187
const [hasAudio, setHasAudio] = createSignal(false);
182188

183189
createEffect(

apps/desktop/src/routes/editor/context.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,12 @@ export const [EditorContextProvider, useEditorContext] = createContextProvider(
612612
previewTime: null as number | null,
613613
playbackTime: 0,
614614
playing: false,
615+
captions: {
616+
isGenerating: false,
617+
isDownloading: false,
618+
downloadProgress: 0,
619+
downloadingModel: null as string | null,
620+
},
615621
timeline: {
616622
interactMode: "seek" as "seek" | "split",
617623
selection: null as

apps/desktop/src/routes/target-select-overlay.tsx

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -536,23 +536,34 @@ function Inner() {
536536
const originalLogicalSize = original.size.toLogical(scaleFactor);
537537

538538
const padding = 16;
539+
const TOOLBAR_HEIGHT = 56;
540+
const originalContentWidth = originalLogicalSize.width;
541+
const originalContentHeight = Math.max(
542+
0,
543+
originalLogicalSize.height - TOOLBAR_HEIGHT,
544+
);
545+
539546
const selectionMinDim = Math.min(bounds.width, bounds.height);
540-
const targetMaxDim = Math.max(
541-
150,
547+
const targetContentMaxDim = Math.max(
548+
100,
542549
Math.min(
543-
Math.max(originalLogicalSize.width, originalLogicalSize.height),
544-
selectionMinDim * 0.5,
550+
Math.max(originalContentWidth, originalContentHeight),
551+
selectionMinDim * 0.5 - TOOLBAR_HEIGHT,
545552
),
546553
);
547554

548-
const originalMaxDim = Math.max(
549-
originalLogicalSize.width,
550-
originalLogicalSize.height,
555+
const originalContentMaxDim = Math.max(
556+
originalContentWidth,
557+
originalContentHeight,
551558
);
552-
const scale = targetMaxDim / originalMaxDim;
559+
const scale =
560+
originalContentMaxDim > 0
561+
? targetContentMaxDim / originalContentMaxDim
562+
: 1;
553563

554-
const newWidth = Math.round(originalLogicalSize.width * scale);
555-
const newHeight = Math.round(originalLogicalSize.height * scale);
564+
const newWidth = Math.round(originalContentWidth * scale);
565+
const newHeight =
566+
Math.round(originalContentHeight * scale) + TOOLBAR_HEIGHT;
556567

557568
if (
558569
bounds.width > newWidth + padding * 2 &&
@@ -580,6 +591,12 @@ function Inner() {
580591
if (original && win) {
581592
await win.setPosition(original.position);
582593
await win.setSize(original.size);
594+
await commands.updateCameraOverlayBounds(
595+
original.position.x,
596+
original.position.y,
597+
original.size.width,
598+
original.size.height,
599+
);
583600
setOriginalCameraBounds(null);
584601
setTargetState(null);
585602
lastApplied = null;

bash.exe.stackdump

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Stack trace:
2+
Frame Function Args
3+
0007FFFFB360 00021005FE8E (000210285F68, 00021026AB6E, 000000000000, 0007FFFFA260) msys-2.0.dll+0x1FE8E
4+
0007FFFFB360 0002100467F9 (000000000000, 000000000000, 000000000000, 0007FFFFB638) msys-2.0.dll+0x67F9
5+
0007FFFFB360 000210046832 (000210286019, 0007FFFFB218, 000000000000, 000000000000) msys-2.0.dll+0x6832
6+
0007FFFFB360 000210068CF6 (000000000000, 000000000000, 000000000000, 000000000000) msys-2.0.dll+0x28CF6
7+
0007FFFFB360 000210068E24 (0007FFFFB370, 000000000000, 000000000000, 000000000000) msys-2.0.dll+0x28E24
8+
0007FFFFB640 00021006A225 (0007FFFFB370, 000000000000, 000000000000, 000000000000) msys-2.0.dll+0x2A225
9+
End of stack trace
10+
Loaded modules:
11+
000100400000 bash.exe
12+
7FFE664C0000 ntdll.dll
13+
7FFE65400000 KERNEL32.DLL
14+
7FFE63610000 KERNELBASE.dll
15+
7FFE64260000 USER32.dll
16+
000210040000 msys-2.0.dll
17+
7FFE64180000 win32u.dll
18+
7FFE64EE0000 GDI32.dll
19+
7FFE63B60000 gdi32full.dll
20+
7FFE641B0000 msvcp_win.dll
21+
7FFE63A10000 ucrtbase.dll
22+
7FFE657E0000 advapi32.dll
23+
7FFE648D0000 msvcrt.dll
24+
7FFE65A90000 sechost.dll
25+
7FFE64DC0000 RPCRT4.dll
26+
7FFE62C40000 CRYPTBASE.DLL
27+
7FFE64040000 bcryptPrimitives.dll
28+
7FFE65600000 IMM32.DLL

crates/rendering/src/lib.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,12 +1368,15 @@ impl ProjectUniforms {
13681368

13691369
let crop_bounds = match project.camera.shape {
13701370
CameraShape::Source => [0.0, 0.0, frame_size[0], frame_size[1]],
1371-
CameraShape::Square => [
1372-
(frame_size[0] - frame_size[1]) / 2.0,
1373-
0.0,
1374-
frame_size[0] - (frame_size[0] - frame_size[1]) / 2.0,
1375-
frame_size[1],
1376-
],
1371+
CameraShape::Square => {
1372+
if frame_size[0] > frame_size[1] {
1373+
let offset = (frame_size[0] - frame_size[1]) / 2.0;
1374+
[offset, 0.0, frame_size[0] - offset, frame_size[1]]
1375+
} else {
1376+
let offset = (frame_size[1] - frame_size[0]) / 2.0;
1377+
[0.0, offset, frame_size[0], frame_size[1] - offset]
1378+
}
1379+
}
13771380
};
13781381

13791382
CompositeVideoFrameUniforms {

0 commit comments

Comments
 (0)