fix: fix the problem of local path not opening (#650)

* fix: fix the problem of local path not opening

* docs: update changelog

* chore: remove pizza-engine
This commit is contained in:
ayangweb
2025-06-10 17:26:19 +08:00
committed by GitHub
parent 7a2dde7448
commit 8ed808c591
13 changed files with 372 additions and 136 deletions

View File

@@ -35,6 +35,7 @@ Information about release notes of Coco Server is provided here.
- fix: arrow keys still navigated search when menu opened with Cmd+K #642
- fix: input lost when reopening dialog after search #644
- fix: web page unmount event #645
- fix: fix the problem of local path not opening #650
### ✈️ Improvements

View File

@@ -27,6 +27,7 @@
"@tauri-apps/plugin-global-shortcut": "~2.0.0",
"@tauri-apps/plugin-http": "~2.0.2",
"@tauri-apps/plugin-log": "~2.4.0",
"@tauri-apps/plugin-opener": "^2.2.7",
"@tauri-apps/plugin-os": "^2.2.1",
"@tauri-apps/plugin-process": "^2.2.1",
"@tauri-apps/plugin-shell": "^2.2.1",

10
pnpm-lock.yaml generated
View File

@@ -35,6 +35,9 @@ importers:
'@tauri-apps/plugin-log':
specifier: ~2.4.0
version: 2.4.0
'@tauri-apps/plugin-opener':
specifier: ^2.2.7
version: 2.2.7
'@tauri-apps/plugin-os':
specifier: ^2.2.1
version: 2.2.1
@@ -1265,6 +1268,9 @@ packages:
'@tauri-apps/plugin-log@2.4.0':
resolution: {integrity: sha512-j7yrDtLNmayCBOO2esl3aZv9jSXy2an8MDLry3Ys9ZXerwUg35n1Y2uD8HoCR+8Ng/EUgx215+qOUfJasjYrHw==}
'@tauri-apps/plugin-opener@2.2.7':
resolution: {integrity: sha512-uduEyvOdjpPOEeDRrhwlCspG/f9EQalHumWBtLBnp3fRp++fKGLqDOyUhSIn7PzX45b/rKep//ZQSAQoIxobLA==}
'@tauri-apps/plugin-os@2.2.1':
resolution: {integrity: sha512-cNYpNri2CCc6BaNeB6G/mOtLvg8dFyFQyCUdf2y0K8PIAKGEWdEcu8DECkydU2B+oj4OJihDPD2de5K6cbVl9A==}
@@ -4666,6 +4672,10 @@ snapshots:
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/plugin-opener@2.2.7':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/plugin-os@2.2.1':
dependencies:
'@tauri-apps/api': 2.5.0

23
src-tauri/Cargo.lock generated
View File

@@ -866,6 +866,7 @@ dependencies = [
"tauri-plugin-http",
"tauri-plugin-log",
"tauri-plugin-macos-permissions",
"tauri-plugin-opener",
"tauri-plugin-os",
"tauri-plugin-process",
"tauri-plugin-screenshots",
@@ -6279,6 +6280,28 @@ dependencies = [
"thiserror 2.0.12",
]
[[package]]
name = "tauri-plugin-opener"
version = "2.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66644b71a31ec1a8a52c4a16575edd28cf763c87cf4a7da24c884122b5c77097"
dependencies = [
"dunce",
"glob",
"objc2-app-kit 0.3.1",
"objc2-foundation 0.3.1",
"open",
"schemars",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.12",
"url",
"windows 0.61.1",
"zbus",
]
[[package]]
name = "tauri-plugin-os"
version = "2.2.1"

View File

@@ -98,6 +98,7 @@ derive_more = { version = "2.0.1", features = ["display"] }
anyhow = "1.0.98"
function_name = "0.3.0"
regex = "1.11.1"
tauri-plugin-opener = "2"
[target."cfg(target_os = \"macos\")".dependencies]
tauri-nspanel = { git = "https://github.com/ahkohd/tauri-nspanel", branch = "v2" }

View File

@@ -71,6 +71,7 @@
"process:default",
"updater:default",
"windows-version:default",
"log:default"
"log:default",
"opener:default"
]
}

View File

@@ -88,7 +88,8 @@ pub fn run() {
.plugin(tauri_plugin_screenshots::init())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_windows_version::init());
.plugin(tauri_plugin_windows_version::init())
.plugin(tauri_plugin_opener::init());
// Conditional compilation for macOS
#[cfg(target_os = "macos")]

View File

@@ -106,7 +106,7 @@ const Applications = () => {
<SquareArrowOutUpRight
className="size-4 cursor-pointer"
onClick={() => {
platformAdapter.openExternal(item);
platformAdapter.revealItemInDir(item);
}}
/>

View File

@@ -102,9 +102,10 @@ export interface SystemOperations {
checkUpdate: () => Promise<any>;
relaunchApp: () => Promise<void>;
isTauri: () => boolean;
openExternal: (url: string) => Promise<void>;
openUrl: (url: string) => Promise<void>;
commands: <T>(commandName: string, ...args: any[]) => Promise<T>;
isWindows10: () => Promise<boolean>;
revealItemInDir: (path: string) => Promise<void>;
}
// Base platform adapter interface

View File

@@ -72,7 +72,7 @@ export const OpenURLWithBrowser = async (url?: string) => {
if (!url) return;
if (IsTauri()) {
try {
await platformAdapter.openExternal(url);
await platformAdapter.openUrl(url);
await platformAdapter.commands("hide_coco");
console.log("URL opened in default browser");
} catch (error) {

View File

@@ -1,4 +1,3 @@
// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.
/** user-defined commands **/
@@ -51,8 +50,18 @@ export const commands = {
async getCurrentRecording(): Promise<JsonValue<RecordingInfo | null>> {
return await TAURI_INVOKE("get_current_recording");
},
async exportVideo(videoId: string, project: ProjectConfiguration, progress: TAURI_CHANNEL<RenderProgress>, force: boolean): Promise<string> {
return await TAURI_INVOKE("export_video", { videoId, project, progress, force });
async exportVideo(
videoId: string,
project: ProjectConfiguration,
progress: TAURI_CHANNEL<RenderProgress>,
force: boolean
): Promise<string> {
return await TAURI_INVOKE("export_video", {
videoId,
project,
progress,
force,
});
},
async copyFileToPath(src: string, dst: string): Promise<null> {
return await TAURI_INVOKE("copy_file_to_path", { src, dst });
@@ -66,10 +75,15 @@ export const commands = {
async openFilePath(path: string): Promise<null> {
return await TAURI_INVOKE("open_file_path", { path });
},
async getVideoMetadata(videoId: string, videoType: VideoType | null): Promise<VideoRecordingMetadata> {
async getVideoMetadata(
videoId: string,
videoType: VideoType | null
): Promise<VideoRecordingMetadata> {
return await TAURI_INVOKE("get_video_metadata", { videoId, videoType });
},
async createEditorInstance(videoId: string): Promise<SerializedEditorInstance> {
async createEditorInstance(
videoId: string
): Promise<SerializedEditorInstance> {
return await TAURI_INVOKE("create_editor_instance", { videoId });
},
async startPlayback(videoId: string): Promise<void> {
@@ -78,10 +92,16 @@ export const commands = {
async stopPlayback(videoId: string): Promise<void> {
await TAURI_INVOKE("stop_playback", { videoId });
},
async setPlayheadPosition(videoId: string, frameNumber: number): Promise<void> {
async setPlayheadPosition(
videoId: string,
frameNumber: number
): Promise<void> {
await TAURI_INVOKE("set_playhead_position", { videoId, frameNumber });
},
async setProjectConfig(videoId: string, config: ProjectConfiguration): Promise<void> {
async setProjectConfig(
videoId: string,
config: ProjectConfiguration
): Promise<void> {
await TAURI_INVOKE("set_project_config", { videoId, config });
},
async openEditor(id: string): Promise<void> {
@@ -99,7 +119,10 @@ export const commands = {
async requestPermission(permission: OSPermission): Promise<void> {
await TAURI_INVOKE("request_permission", { permission });
},
async uploadExportedVideo(videoId: string, mode: UploadMode): Promise<UploadResult> {
async uploadExportedVideo(
videoId: string,
mode: UploadMode
): Promise<UploadResult> {
return await TAURI_INVOKE("upload_exported_video", { videoId, mode });
},
async uploadScreenshot(screenshotPath: string): Promise<UploadResult> {
@@ -108,13 +131,16 @@ export const commands = {
async getRecordingMeta(id: string, fileType: string): Promise<RecordingMeta> {
return await TAURI_INVOKE("get_recording_meta", { id, fileType });
},
async saveFileDialog(fileName: string, fileType: string): Promise<string | null> {
async saveFileDialog(
fileName: string,
fileType: string
): Promise<string | null> {
return await TAURI_INVOKE("save_file_dialog", { fileName, fileType });
},
async listRecordings(): Promise<([string, string, RecordingMeta])[]> {
async listRecordings(): Promise<[string, string, RecordingMeta][]> {
return await TAURI_INVOKE("list_recordings");
},
async listScreenshots(): Promise<([string, string, RecordingMeta])[]> {
async listScreenshots(): Promise<[string, string, RecordingMeta][]> {
return await TAURI_INVOKE("list_screenshots");
},
async checkUpgradedAndUpdate(): Promise<boolean> {
@@ -144,7 +170,9 @@ export const commands = {
async sendFeedbackRequest(feedback: string): Promise<null> {
return await TAURI_INVOKE("send_feedback_request", { feedback });
},
async positionTrafficLights(controlsInset: [number, number] | null): Promise<void> {
async positionTrafficLights(
controlsInset: [number, number] | null
): Promise<void> {
await TAURI_INVOKE("position_traffic_lights", { controlsInset });
},
async setTheme(theme: AppTheme): Promise<void> {
@@ -158,31 +186,30 @@ export const commands = {
},
async writeClipboardString(text: string): Promise<null> {
return await TAURI_INVOKE("write_clipboard_string", { text });
}
}
},
};
/** user-defined events **/
export const events = __makeEvents__<{
audioInputLevelChange: AudioInputLevelChange,
authenticationInvalid: AuthenticationInvalid,
currentRecordingChanged: CurrentRecordingChanged,
editorStateChanged: EditorStateChanged,
newNotification: NewNotification,
newRecordingAdded: NewRecordingAdded,
newScreenshotAdded: NewScreenshotAdded,
recordingMetaChanged: RecordingMetaChanged,
recordingOptionsChanged: RecordingOptionsChanged,
recordingStarted: RecordingStarted,
recordingStopped: RecordingStopped,
renderFrameEvent: RenderFrameEvent,
requestNewScreenshot: RequestNewScreenshot,
requestOpenSettings: RequestOpenSettings,
requestRestartRecording: RequestRestartRecording,
requestStartRecording: RequestStartRecording,
requestStopRecording: RequestStopRecording,
uploadProgress: UploadProgress
audioInputLevelChange: AudioInputLevelChange;
authenticationInvalid: AuthenticationInvalid;
currentRecordingChanged: CurrentRecordingChanged;
editorStateChanged: EditorStateChanged;
newNotification: NewNotification;
newRecordingAdded: NewRecordingAdded;
newScreenshotAdded: NewScreenshotAdded;
recordingMetaChanged: RecordingMetaChanged;
recordingOptionsChanged: RecordingOptionsChanged;
recordingStarted: RecordingStarted;
recordingStopped: RecordingStopped;
renderFrameEvent: RenderFrameEvent;
requestNewScreenshot: RequestNewScreenshot;
requestOpenSettings: RequestOpenSettings;
requestRestartRecording: RequestRestartRecording;
requestStartRecording: RequestStartRecording;
requestStopRecording: RequestStopRecording;
uploadProgress: UploadProgress;
}>({
audioInputLevelChange: "audio-input-level-change",
authenticationInvalid: "authentication-invalid",
@@ -201,91 +228,247 @@ export const events = __makeEvents__<{
requestRestartRecording: "request-restart-recording",
requestStartRecording: "request-start-recording",
requestStopRecording: "request-stop-recording",
uploadProgress: "upload-progress"
})
uploadProgress: "upload-progress",
});
/** user-defined constants **/
/** user-defined types **/
export type AppEndpoint = string
export type AppTheme = "auto" | "light" | "dark"
export type WindowTheme = "light" | "dark"
export type AspectRatio = "wide" | "vertical" | "square" | "classic" | "tall"
export type Audio = { duration: number; sample_rate: number; channels: number }
export type AudioConfiguration = { mute: boolean; improve: boolean }
export type AudioInputLevelChange = number
export type AudioMeta = { path: string }
export type AuthStore = { token: string; user_id: string | null; expires: number; plan: Plan | null }
export type AuthenticationInvalid = null
export type BackgroundConfiguration = { source: BackgroundSource; blur: number; padding: number; rounding: number; inset: number; crop: Crop | null }
export type BackgroundSource = { type: "wallpaper"; id: number } | { type: "image"; path: string | null } | { type: "color"; value: [number, number, number] } | { type: "gradient"; from: [number, number, number]; to: [number, number, number]; angle?: number }
export type Bounds = { x: number; y: number; width: number; height: number }
export type Camera = { hide: boolean; mirror: boolean; position: CameraPosition; size: number; zoom_size: number | null; rounding: number; shadow: number }
export type CameraMeta = { path: string }
export type CameraPosition = { x: CameraXPosition; y: CameraYPosition }
export type CameraXPosition = "left" | "center" | "right"
export type CameraYPosition = "top" | "bottom"
export type CaptureScreen = { id: number; name: string }
export type CaptureWindow = { id: number; owner_name: string; name: string; bounds: Bounds }
export type Crop = { position: XY<number>; size: XY<number> }
export type CurrentRecordingChanged = null
export type CursorAnimationStyle = "regular" | "slow" | "fast"
export type CursorConfiguration = { hideWhenIdle: boolean; size: number; type: CursorType; animationStyle: CursorAnimationStyle }
export type CursorType = "pointer" | "circle"
export type Display = { path: string }
export type EditorStateChanged = { playhead_position: number }
export type Flags = { recordMouse: boolean; split: boolean; pauseResume: boolean; zoom: boolean; customS3: boolean }
export type GeneralSettingsStore = { uploadIndividualFiles?: boolean; openEditorAfterRecording?: boolean; hideDockIcon?: boolean; autoCreateShareableLink?: boolean; enableNotifications?: boolean; disableAutoOpenLinks?: boolean; hasCompletedStartup?: boolean; theme?: AppTheme }
export type Hotkey = { code: string; meta: boolean; ctrl: boolean; alt: boolean; shift: boolean }
export type HotkeyAction = "startRecording" | "stopRecording" | "restartRecording" | "takeScreenshot"
export type HotkeysConfiguration = { show: boolean }
export type HotkeysStore = { hotkeys: { [key in HotkeyAction]: Hotkey } }
export type JsonValue<T> = [T]
export type MultipleSegment = { display: Display; camera?: CameraMeta | null; audio?: AudioMeta | null; cursor?: string | null }
export type MultipleSegments = { segments: MultipleSegment[]; cursors: { [key in string]: string } }
export type NewNotification = { title: string; body: string; is_error: boolean }
export type NewRecordingAdded = { path: string }
export type NewScreenshotAdded = { path: string }
export type OSPermission = "screenRecording" | "camera" | "microphone" | "accessibility"
export type OSPermissionStatus = "notNeeded" | "empty" | "granted" | "denied"
export type OSPermissionsCheck = { screenRecording: OSPermissionStatus; microphone: OSPermissionStatus; camera: OSPermissionStatus; accessibility: OSPermissionStatus }
export type Plan = { upgraded: boolean; last_checked: number }
export type PreCreatedVideo = { id: string; link: string; config: S3UploadMeta }
export type ProjectConfiguration = { aspectRatio: AspectRatio | null; background: BackgroundConfiguration; camera: Camera; audio: AudioConfiguration; cursor: CursorConfiguration; hotkeys: HotkeysConfiguration; timeline?: TimelineConfiguration | null; motionBlur: number | null }
export type ProjectRecordings = { segments: SegmentRecordings[] }
export type RecordingInfo = { captureTarget: ScreenCaptureTarget }
export type RecordingMeta = ({ segment: SingleSegment } | { inner: MultipleSegments }) & { pretty_name: string; sharing?: SharingMeta | null }
export type RecordingMetaChanged = { id: string }
export type RecordingOptions = { captureTarget: ScreenCaptureTarget; cameraLabel: string | null; audioInputName: string | null }
export type RecordingOptionsChanged = null
export type RecordingStarted = null
export type RecordingStopped = { path: string }
export type RenderFrameEvent = { frame_number: number }
export type RenderProgress = { type: "Starting"; total_frames: number } | { type: "EstimatedTotalFrames"; total_frames: number } | { type: "FrameRendered"; current_frame: number }
export type RequestNewScreenshot = null
export type RequestOpenSettings = { page: string }
export type RequestRestartRecording = null
export type RequestStartRecording = null
export type RequestStopRecording = null
export type S3UploadMeta = { id: string; user_id: string; aws_region?: string; aws_bucket?: string }
export type ScreenCaptureTarget = ({ variant: "window" } & CaptureWindow) | ({ variant: "screen" } & CaptureScreen)
export type SegmentRecordings = { display: Video; camera: Video | null; audio: Audio | null }
export type SerializedEditorInstance = { framesSocketUrl: string; recordingDuration: number; savedProjectConfig: ProjectConfiguration; recordings: ProjectRecordings; path: string; prettyName: string }
export type SharingMeta = { id: string; link: string }
export type ShowCapWindow = "Setup" | "Main" | { Settings: { page: string | null } } | { Editor: { project_id: string } } | "PrevRecordings" | "WindowCaptureOccluder" | { Camera: { ws_port: number } } | { InProgressRecording: { position: [number, number] | null } } | "Upgrade"
export type SingleSegment = { display: Display; camera?: CameraMeta | null; audio?: AudioMeta | null; cursor?: string | null }
export type TimelineConfiguration = { segments: TimelineSegment[]; zoomSegments?: ZoomSegment[] }
export type TimelineSegment = { recordingSegment: number | null; timescale: number; start: number; end: number }
export type UploadMode = { Initial: { pre_created_video: PreCreatedVideo | null } } | "Reupload"
export type UploadProgress = { stage: string; progress: number; message: string }
export type UploadResult = { Success: string } | "NotAuthenticated" | "PlanCheckFailed" | "UpgradeRequired"
export type Video = { duration: number; width: number; height: number }
export type VideoRecordingMetadata = { duration: number; size: number }
export type VideoType = "screen" | "output"
export type XY<T> = { x: T; y: T }
export type ZoomSegment = { start: number; end: number; amount: number }
export type AppEndpoint = string;
export type AppTheme = "auto" | "light" | "dark";
export type WindowTheme = "light" | "dark";
export type AspectRatio = "wide" | "vertical" | "square" | "classic" | "tall";
export type Audio = { duration: number; sample_rate: number; channels: number };
export type AudioConfiguration = { mute: boolean; improve: boolean };
export type AudioInputLevelChange = number;
export type AudioMeta = { path: string };
export type AuthStore = {
token: string;
user_id: string | null;
expires: number;
plan: Plan | null;
};
export type AuthenticationInvalid = null;
export type BackgroundConfiguration = {
source: BackgroundSource;
blur: number;
padding: number;
rounding: number;
inset: number;
crop: Crop | null;
};
export type BackgroundSource =
| { type: "wallpaper"; id: number }
| { type: "image"; path: string | null }
| { type: "color"; value: [number, number, number] }
| {
type: "gradient";
from: [number, number, number];
to: [number, number, number];
angle?: number;
};
export type Bounds = { x: number; y: number; width: number; height: number };
export type Camera = {
hide: boolean;
mirror: boolean;
position: CameraPosition;
size: number;
zoom_size: number | null;
rounding: number;
shadow: number;
};
export type CameraMeta = { path: string };
export type CameraPosition = { x: CameraXPosition; y: CameraYPosition };
export type CameraXPosition = "left" | "center" | "right";
export type CameraYPosition = "top" | "bottom";
export type CaptureScreen = { id: number; name: string };
export type CaptureWindow = {
id: number;
owner_name: string;
name: string;
bounds: Bounds;
};
export type Crop = { position: XY<number>; size: XY<number> };
export type CurrentRecordingChanged = null;
export type CursorAnimationStyle = "regular" | "slow" | "fast";
export type CursorConfiguration = {
hideWhenIdle: boolean;
size: number;
type: CursorType;
animationStyle: CursorAnimationStyle;
};
export type CursorType = "pointer" | "circle";
export type Display = { path: string };
export type EditorStateChanged = { playhead_position: number };
export type Flags = {
recordMouse: boolean;
split: boolean;
pauseResume: boolean;
zoom: boolean;
customS3: boolean;
};
export type GeneralSettingsStore = {
uploadIndividualFiles?: boolean;
openEditorAfterRecording?: boolean;
hideDockIcon?: boolean;
autoCreateShareableLink?: boolean;
enableNotifications?: boolean;
disableAutoOpenLinks?: boolean;
hasCompletedStartup?: boolean;
theme?: AppTheme;
};
export type Hotkey = {
code: string;
meta: boolean;
ctrl: boolean;
alt: boolean;
shift: boolean;
};
export type HotkeyAction =
| "startRecording"
| "stopRecording"
| "restartRecording"
| "takeScreenshot";
export type HotkeysConfiguration = { show: boolean };
export type HotkeysStore = { hotkeys: { [key in HotkeyAction]: Hotkey } };
export type JsonValue<T> = [T];
export type MultipleSegment = {
display: Display;
camera?: CameraMeta | null;
audio?: AudioMeta | null;
cursor?: string | null;
};
export type MultipleSegments = {
segments: MultipleSegment[];
cursors: { [key in string]: string };
};
export type NewNotification = {
title: string;
body: string;
is_error: boolean;
};
export type NewRecordingAdded = { path: string };
export type NewScreenshotAdded = { path: string };
export type OSPermission =
| "screenRecording"
| "camera"
| "microphone"
| "accessibility";
export type OSPermissionStatus = "notNeeded" | "empty" | "granted" | "denied";
export type OSPermissionsCheck = {
screenRecording: OSPermissionStatus;
microphone: OSPermissionStatus;
camera: OSPermissionStatus;
accessibility: OSPermissionStatus;
};
export type Plan = { upgraded: boolean; last_checked: number };
export type PreCreatedVideo = {
id: string;
link: string;
config: S3UploadMeta;
};
export type ProjectConfiguration = {
aspectRatio: AspectRatio | null;
background: BackgroundConfiguration;
camera: Camera;
audio: AudioConfiguration;
cursor: CursorConfiguration;
hotkeys: HotkeysConfiguration;
timeline?: TimelineConfiguration | null;
motionBlur: number | null;
};
export type ProjectRecordings = { segments: SegmentRecordings[] };
export type RecordingInfo = { captureTarget: ScreenCaptureTarget };
export type RecordingMeta = (
| { segment: SingleSegment }
| { inner: MultipleSegments }
) & { pretty_name: string; sharing?: SharingMeta | null };
export type RecordingMetaChanged = { id: string };
export type RecordingOptions = {
captureTarget: ScreenCaptureTarget;
cameraLabel: string | null;
audioInputName: string | null;
};
export type RecordingOptionsChanged = null;
export type RecordingStarted = null;
export type RecordingStopped = { path: string };
export type RenderFrameEvent = { frame_number: number };
export type RenderProgress =
| { type: "Starting"; total_frames: number }
| { type: "EstimatedTotalFrames"; total_frames: number }
| { type: "FrameRendered"; current_frame: number };
export type RequestNewScreenshot = null;
export type RequestOpenSettings = { page: string };
export type RequestRestartRecording = null;
export type RequestStartRecording = null;
export type RequestStopRecording = null;
export type S3UploadMeta = {
id: string;
user_id: string;
aws_region?: string;
aws_bucket?: string;
};
export type ScreenCaptureTarget =
| ({ variant: "window" } & CaptureWindow)
| ({ variant: "screen" } & CaptureScreen);
export type SegmentRecordings = {
display: Video;
camera: Video | null;
audio: Audio | null;
};
export type SerializedEditorInstance = {
framesSocketUrl: string;
recordingDuration: number;
savedProjectConfig: ProjectConfiguration;
recordings: ProjectRecordings;
path: string;
prettyName: string;
};
export type SharingMeta = { id: string; link: string };
export type ShowCapWindow =
| "Setup"
| "Main"
| { Settings: { page: string | null } }
| { Editor: { project_id: string } }
| "PrevRecordings"
| "WindowCaptureOccluder"
| { Camera: { ws_port: number } }
| { InProgressRecording: { position: [number, number] | null } }
| "Upgrade";
export type SingleSegment = {
display: Display;
camera?: CameraMeta | null;
audio?: AudioMeta | null;
cursor?: string | null;
};
export type TimelineConfiguration = {
segments: TimelineSegment[];
zoomSegments?: ZoomSegment[];
};
export type TimelineSegment = {
recordingSegment: number | null;
timescale: number;
start: number;
end: number;
};
export type UploadMode =
| { Initial: { pre_created_video: PreCreatedVideo | null } }
| "Reupload";
export type UploadProgress = {
stage: string;
progress: number;
message: string;
};
export type UploadResult =
| { Success: string }
| "NotAuthenticated"
| "PlanCheckFailed"
| "UpgradeRequired";
export type Video = { duration: number; width: number; height: number };
export type VideoRecordingMetadata = { duration: number; size: number };
export type VideoType = "screen" | "output";
export type XY<T> = { x: T; y: T };
export type ZoomSegment = { start: number; end: number; amount: number };
/** tauri-specta globals **/
@@ -298,10 +481,10 @@ import { type WebviewWindow as __WebviewWindow__ } from "@tauri-apps/api/webview
type __EventObj__<T> = {
listen: (
cb: TAURI_API_EVENT.EventCallback<T>,
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
once: (
cb: TAURI_API_EVENT.EventCallback<T>,
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
emit: null extends T
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
@@ -313,7 +496,7 @@ export type Result<T, E> =
| { status: "error"; error: E };
function __makeEvents__<T extends Record<string, any>>(
mappings: Record<keyof T, string>,
mappings: Record<keyof T, string>
) {
return new Proxy(
{} as unknown as {
@@ -343,6 +526,6 @@ function __makeEvents__<T extends Record<string, any>>(
},
});
},
},
}
);
}

View File

@@ -206,10 +206,10 @@ export const createTauriAdapter = (): TauriPlatformAdapter => {
return true;
},
async openExternal(url) {
const { open } = await import("@tauri-apps/plugin-shell");
async openUrl(url) {
const { openUrl } = await import("@tauri-apps/plugin-opener");
open(url);
openUrl(url);
},
isWindows10,
@@ -223,5 +223,11 @@ export const createTauriAdapter = (): TauriPlatformAdapter => {
},
metadata,
async revealItemInDir(path) {
const { revealItemInDir } = await import("@tauri-apps/plugin-opener");
revealItemInDir(path);
},
};
};

View File

@@ -164,7 +164,7 @@ export const createWebAdapter = (): WebPlatformAdapter => {
return false;
},
async openExternal(url) {
async openUrl(url) {
console.log(`Web mode opening URL: ${url}`);
window.open(url, "_blank");
},
@@ -177,8 +177,16 @@ export const createWebAdapter = (): WebPlatformAdapter => {
},
async metadata(path, options = {}) {
console.log("metadata is not supported in web environment", path, options);
console.log(
"metadata is not supported in web environment",
path,
options
);
return Promise.resolve({ isAbsolute: false });
},
async revealItemInDir(path) {
console.log("revealItemInDir is not supported in web environment", path);
},
};
};