From e494c0566d661c52354ba130fad0321a401d0893 Mon Sep 17 00:00:00 2001 From: Side Quest Studios Date: Tue, 16 Jun 2026 14:04:26 -0400 Subject: [PATCH 01/32] Fix Windows helper prebundled path resolution --- electron/ipc/paths/binaries.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/electron/ipc/paths/binaries.ts b/electron/ipc/paths/binaries.ts index 739f7df84..2a4bf83fd 100644 --- a/electron/ipc/paths/binaries.ts +++ b/electron/ipc/paths/binaries.ts @@ -49,6 +49,14 @@ export function getPrebundledNativeHelperPath(binaryName: string): string { return resolveUnpackedAppPath("electron", "native", "bin", getNativeArchTag(), binaryName); } +function getWindowsNativeArchTag(): string { + return process.arch === "arm64" ? "win32-arm64" : "win32-x64"; +} + +function getPrebundledWindowsNativeHelperPath(binaryName: string): string { + return resolveUnpackedAppPath("electron", "native", "bin", getWindowsNativeArchTag(), binaryName); +} + export function resolvePreferredWindowsNativeHelperPath( helperDirectory: string, binaryName: string, @@ -61,7 +69,7 @@ export function resolvePreferredWindowsNativeHelperPath( "Release", binaryName, ); - const prebundledPath = getPrebundledNativeHelperPath(binaryName); + const prebundledPath = getPrebundledWindowsNativeHelperPath(binaryName); if (app.isPackaged && existsSync(prebundledPath)) { return prebundledPath; From 89e2c14814817fcd8c4030189a2ca217deae59e7 Mon Sep 17 00:00:00 2001 From: Side Quest Studios Date: Tue, 16 Jun 2026 14:36:48 -0400 Subject: [PATCH 02/32] Rebrand app to VybeClip --- electron-builder.json5 | 16 ++-- electron/appPaths.ts | 2 +- electron/ipc/captions/generate.ts | 2 +- electron/ipc/register/project.ts | 8 +- electron/ipc/register/recording.ts | 12 +-- electron/ipc/register/sources.ts | 1 + electron/main.ts | 16 ++-- electron/updater.ts | 22 +++--- electron/windows.ts | 2 +- package-lock.json | 83 +++++++++----------- package.json | 14 ++-- src/App.tsx | 8 +- src/components/launch/UpdateToastWindow.tsx | 8 +- src/components/video-editor/TutorialHelp.tsx | 2 +- src/components/video-editor/VideoEditor.tsx | 2 +- src/hooks/useScreenRecorder.ts | 8 +- src/i18n/locales/en/common.json | 4 +- src/i18n/locales/en/editor.json | 2 +- src/i18n/locales/en/launch.json | 12 +-- src/i18n/locales/en/settings.json | 2 +- src/i18n/locales/es/common.json | 4 +- src/i18n/locales/es/editor.json | 2 +- src/i18n/locales/es/launch.json | 12 +-- src/i18n/locales/es/settings.json | 2 +- src/i18n/locales/fr/common.json | 4 +- src/i18n/locales/fr/editor.json | 2 +- src/i18n/locales/fr/launch.json | 12 +-- src/i18n/locales/fr/settings.json | 2 +- src/i18n/locales/it/common.json | 4 +- src/i18n/locales/it/editor.json | 2 +- src/i18n/locales/it/launch.json | 12 +-- src/i18n/locales/it/settings.json | 2 +- src/i18n/locales/ko/common.json | 4 +- src/i18n/locales/ko/editor.json | 2 +- src/i18n/locales/ko/launch.json | 12 +-- src/i18n/locales/ko/settings.json | 2 +- src/i18n/locales/nl/common.json | 4 +- src/i18n/locales/nl/editor.json | 2 +- src/i18n/locales/nl/launch.json | 12 +-- src/i18n/locales/nl/settings.json | 2 +- src/i18n/locales/pt-BR/common.json | 4 +- src/i18n/locales/pt-BR/editor.json | 2 +- src/i18n/locales/pt-BR/launch.json | 12 +-- src/i18n/locales/pt-BR/settings.json | 2 +- src/i18n/locales/ru/common.json | 4 +- src/i18n/locales/ru/launch.json | 12 +-- src/i18n/locales/ru/settings.json | 4 +- src/i18n/locales/zh-CN/common.json | 4 +- src/i18n/locales/zh-CN/editor.json | 2 +- src/i18n/locales/zh-CN/launch.json | 12 +-- src/i18n/locales/zh-CN/settings.json | 2 +- src/i18n/locales/zh-TW/common.json | 4 +- src/i18n/locales/zh-TW/editor.json | 2 +- src/i18n/locales/zh-TW/launch.json | 12 +-- src/i18n/locales/zh-TW/settings.json | 2 +- src/lib/exporter/exportSavePolicy.ts | 4 +- 56 files changed, 203 insertions(+), 207 deletions(-) diff --git a/electron-builder.json5 b/electron-builder.json5 index 1aaa56af1..1bc13d82a 100644 --- a/electron-builder.json5 +++ b/electron-builder.json5 @@ -1,7 +1,7 @@ // @see - https://www.electron.build/configuration/configuration { "$schema": "https://raw.githubusercontent.com/electron-userland/electron-builder/master/packages/app-builder-lib/scheme.json", - "appId": "dev.recordly.app", + "appId": "studio.boxcreative.vybeclip", "electronUpdaterCompatibility": ">=2.16", "asar": true, "asarUnpack": [ @@ -10,7 +10,7 @@ "node_modules/uiohook-napi/**", "electron/native/**" ], - "productName": "Recordly", + "productName": "VybeClip", "npmRebuild": true, "buildDependenciesFromSource": true, "compression": "normal", @@ -41,8 +41,8 @@ "publish": [ { "provider": "github", - "owner": "webadderall", - "repo": "Recordly", + "owner": "Alfredoalv13", + "repo": "Recordly", "tagNamePrefix": "v", "publishAutoUpdate": true } @@ -65,9 +65,9 @@ "icon": "icons/icons/mac/icon.icns", "artifactName": "${productName}-${arch}.${ext}", "extendInfo": { - "NSAudioCaptureUsageDescription": "Recordly needs audio capture permission to record system audio.", - "NSCameraUsageDescription": "Recordly needs camera access to record webcam video.", - "NSMicrophoneUsageDescription": "Recordly needs microphone access to record voice audio.", + "NSAudioCaptureUsageDescription": "VybeClip needs audio capture permission to record system audio.", + "NSCameraUsageDescription": "VybeClip needs camera access to record webcam video.", + "NSMicrophoneUsageDescription": "VybeClip needs microphone access to record voice audio.", "NSCameraUseContinuityCameraDeviceType": true, "com.apple.security.device.audio-input": true } @@ -86,7 +86,7 @@ ], "icon": "icons/icons/win/icon.ico" , - "executableName": "Recordly", + "executableName": "VybeClip", "artifactName": "${productName}-windows-${arch}.${ext}" } } diff --git a/electron/appPaths.ts b/electron/appPaths.ts index 68d6cfc39..834c269f4 100644 --- a/electron/appPaths.ts +++ b/electron/appPaths.ts @@ -2,7 +2,7 @@ import path from "node:path"; import { app } from "electron"; if (process.env["VITE_DEV_SERVER_URL"]) { - const devUserDataPath = path.join(app.getPath("appData"), "Recordly-dev"); + const devUserDataPath = path.join(app.getPath("appData"), "VybeClip-dev"); app.setPath("userData", devUserDataPath); app.setPath("sessionData", path.join(devUserDataPath, "session")); } diff --git a/electron/ipc/captions/generate.ts b/electron/ipc/captions/generate.ts index 33c345848..95342a7f3 100644 --- a/electron/ipc/captions/generate.ts +++ b/electron/ipc/captions/generate.ts @@ -71,7 +71,7 @@ export async function resolveWhisperExecutablePath(preferredPath?: string | null } throw new Error( - "No Whisper runtime was found. Recordly looked for a bundled binary first, then checked common system install locations.", + "No Whisper runtime was found. VybeClip looked for a bundled binary first, then checked common system install locations.", ); } diff --git a/electron/ipc/register/project.ts b/electron/ipc/register/project.ts index a65fd9070..96e315e37 100644 --- a/electron/ipc/register/project.ts +++ b/electron/ipc/register/project.ts @@ -313,10 +313,10 @@ export function registerProjectHandlers() { const defaultName = `${safeName}.${PROJECT_FILE_EXTENSION}` const result = await dialog.showSaveDialog({ - title: 'Save Recordly Project', + title: 'Save VybeClip Project', defaultPath: path.join(projectsDir, defaultName), filters: [ - { name: 'Recordly Project', extensions: [PROJECT_FILE_EXTENSION] }, + { name: 'VybeClip Project', extensions: [PROJECT_FILE_EXTENSION] }, { name: 'JSON', extensions: ['json'] } ], properties: ['createDirectory', 'showOverwriteConfirmation'] @@ -432,10 +432,10 @@ export function registerProjectHandlers() { try { const projectsDir = await getProjectsDir() const result = await dialog.showOpenDialog({ - title: 'Open Recordly Project', + title: 'Open VybeClip Project', defaultPath: projectsDir, filters: [ - { name: 'Recordly Project', extensions: [PROJECT_FILE_EXTENSION, ...LEGACY_PROJECT_FILE_EXTENSIONS] }, + { name: 'VybeClip Project', extensions: [PROJECT_FILE_EXTENSION, ...LEGACY_PROJECT_FILE_EXTENSIONS] }, { name: 'JSON', extensions: ['json'] }, { name: 'All Files', extensions: ['*'] } ], diff --git a/electron/ipc/register/recording.ts b/electron/ipc/register/recording.ts index b13453c74..1d73a9da2 100644 --- a/electron/ipc/register/recording.ts +++ b/electron/ipc/register/recording.ts @@ -691,12 +691,12 @@ export function registerRecordingHandlers( !ALLOW_RECORDLY_WINDOW_CAPTURE && source?.id?.startsWith("window:") && appName && - (appName === ownAppName || appName === "recordly") + (appName === ownAppName || appName === "vybeclip" || appName === "recordly") ) { return { success: false, message: - "Cannot record Recordly windows. Please select another app window.", + "Cannot record VybeClip windows. Please select another app window.", }; } @@ -805,8 +805,8 @@ export function registerRecordingHandlers( type: "warning", title: "Screen Recording Permission Required", message: - "Recordly needs screen recording permission to capture your screen.", - detail: "Please open System Settings > Privacy & Security > Screen Recording, make sure Recordly is toggled ON, then try recording again.", + "VybeClip needs screen recording permission to capture your screen.", + detail: "Please open System Settings > Privacy & Security > Screen Recording, make sure VybeClip is toggled ON, then try recording again.", buttons: ["Open System Settings", "Cancel"], defaultId: 0, cancelId: 1, @@ -838,8 +838,8 @@ export function registerRecordingHandlers( const { response } = await dialog.showMessageBox({ type: "warning", title: "Microphone Permission Required", - message: "Recordly needs microphone permission to record audio.", - detail: "Please open System Settings > Privacy & Security > Microphone, make sure Recordly is toggled ON, then try recording again.", + message: "VybeClip needs microphone permission to record audio.", + detail: "Please open System Settings > Privacy & Security > Microphone, make sure VybeClip is toggled ON, then try recording again.", buttons: ["Open System Settings", "Cancel"], defaultId: 0, cancelId: 1, diff --git a/electron/ipc/register/sources.ts b/electron/ipc/register/sources.ts index 33c9ee74c..cf20b7a5e 100644 --- a/electron/ipc/register/sources.ts +++ b/electron/ipc/register/sources.ts @@ -82,6 +82,7 @@ export function registerSourceHandlers({ const ownWindowNames = new Set( [ app.getName(), + "VybeClip", "Recordly", ...BrowserWindow.getAllWindows().flatMap((win) => { const title = win.getTitle().trim(); diff --git a/electron/main.ts b/electron/main.ts index ed05ffeb6..54ab928f0 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -519,22 +519,22 @@ function syncDockIcon() { function getUpdateNotificationTitle(payload: UpdateToastPayload) { switch (payload.phase) { case "available": - return `Recordly ${payload.version} is available`; + return `VybeClip ${payload.version} is available`; case "downloading": - return `Downloading Recordly ${payload.version}`; + return `Downloading VybeClip ${payload.version}`; case "ready": - return `Recordly ${payload.version} is ready`; + return `VybeClip ${payload.version} is ready`; case "error": - return `Recordly ${payload.version} needs attention`; + return `VybeClip ${payload.version} needs attention`; } } function getUpdateNotificationBody(payload: UpdateToastPayload) { switch (payload.phase) { case "available": - return "Click to install the update and restart Recordly."; + return "Click to install the update and restart VybeClip."; case "downloading": - return "Recordly is downloading the update and will restart when it is ready."; + return "VybeClip is downloading the update and will restart when it is ready."; case "ready": return "Click to install the downloaded update and restart."; case "error": @@ -709,7 +709,7 @@ ipcMain.handle("check-for-app-updates", async () => { function updateTrayMenu(recording: boolean = false) { if (!tray) return; const trayIcon = recording ? getRecordingTrayIcon() : getDefaultTrayIcon(); - const trayToolTip = recording ? `Recording: ${selectedSourceName}` : "Recordly"; + const trayToolTip = recording ? `Recording: ${selectedSourceName}` : "VybeClip"; const menuTemplate = recording ? [ { @@ -876,7 +876,7 @@ app.on("second-instance", () => { // Register all IPC handlers when app is ready app.whenReady().then(async () => { if (process.platform === "win32") { - app.setAppUserModelId("dev.recordly.app"); + app.setAppUserModelId("studio.boxcreative.vybeclip"); } session.defaultSession.setPermissionCheckHandler((_webContents, permission) => { diff --git a/electron/updater.ts b/electron/updater.ts index 86a02aecf..31d96b91a 100644 --- a/electron/updater.ts +++ b/electron/updater.ts @@ -212,10 +212,10 @@ function createDownloadingUpdateToastPayload( phase: "downloading", detail: normalizedProgress >= 100 - ? "Finishing the update download. Recordly will restart as soon as the installer is ready." + ? "Finishing the update download. VybeClip will restart as soon as the installer is ready." : remainingMb !== null - ? `${remainingMb.toFixed(1)} MB left before Recordly restarts.` - : "Downloading the update now. Recordly will restart when it finishes.", + ? `${remainingMb.toFixed(1)} MB left before VybeClip restarts.` + : "Downloading the update now. VybeClip will restart when it finishes.", delayMs: UPDATE_REMINDER_DELAY_MS, progressPercent: normalizedProgress, transferredBytes, @@ -412,7 +412,7 @@ export async function downloadAvailableUpdate( setUpdateStatusSummary({ status: "downloading", availableVersion, - detail: `Downloading Recordly ${availableVersion}`, + detail: `Downloading VybeClip ${availableVersion}`, }); emitUpdateToastState( sendToRenderer, @@ -524,7 +524,7 @@ async function showAvailableUpdateDialog( const result = await showMessageBox(getMainWindow, { type: "info", title: "Update Available", - message: `Recordly ${version} is available.`, + message: `VybeClip ${version} is available.`, detail: "Install and restart now, or remind me later.", buttons: ["Install & Restart", "Later"], defaultId: 0, @@ -550,8 +550,8 @@ async function showDownloadedUpdateDialog( type: "info", title: "Update Ready", message: isPreview - ? `Recordly ${version} is ready to install.` - : `Recordly ${version} has been downloaded.`, + ? `VybeClip ${version} is ready to install.` + : `VybeClip ${version} has been downloaded.`, detail: isPreview ? "Development preview of the native update prompt. No real update will be installed." : "Install and restart now, or remind me later.", @@ -674,7 +674,7 @@ export function setupAutoUpdates( setUpdateStatusSummary({ status: "available", availableVersion: info.version, - detail: `Recordly ${info.version} is available.`, + detail: `VybeClip ${info.version} is available.`, }); if (skippedVersion === info.version) { manualCheckRequested = false; @@ -704,7 +704,7 @@ export function setupAutoUpdates( setUpdateStatusSummary({ status: "up-to-date", availableVersion: null, - detail: `Recordly ${app.getVersion()} is up to date.`, + detail: `VybeClip ${app.getVersion()} is up to date.`, }); clearVisibleUpdateToast(sendToRenderer); manualCheckRequested = false; @@ -719,7 +719,7 @@ export function setupAutoUpdates( setUpdateStatusSummary({ status: "downloading", availableVersion, - detail: `Downloading Recordly ${availableVersion}`, + detail: `Downloading VybeClip ${availableVersion}`, }); writeUpdaterLog( `Download progress for ${availableVersion}: ${progress.percent.toFixed(1)}%`, @@ -775,7 +775,7 @@ export function setupAutoUpdates( setUpdateStatusSummary({ status: "ready", availableVersion: info.version, - detail: `Recordly ${info.version} is ready to install.`, + detail: `VybeClip ${info.version} is ready to install.`, }); clearDeferredReminderTimer(); diff --git a/electron/windows.ts b/electron/windows.ts index 478584b55..274557551 100644 --- a/electron/windows.ts +++ b/electron/windows.ts @@ -852,7 +852,7 @@ export function createEditorWindow(): BrowserWindow { resizable: true, alwaysOnTop: false, skipTaskbar: false, - title: "Recordly", + title: "VybeClip", show: false, backgroundColor: "#000000", webPreferences: { diff --git a/package-lock.json b/package-lock.json index a255b232f..1d6ae851b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "recordly", + "name": "vybeclip", "version": "1.3.4", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "recordly", + "name": "vybeclip", "version": "1.3.4", "hasInstallScript": true, "dependencies": { @@ -122,6 +122,7 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -351,6 +352,7 @@ "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.9.0" } @@ -1358,7 +1360,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", @@ -1380,7 +1381,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -1397,7 +1397,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -1412,7 +1411,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">= 10.0.0" } @@ -2102,6 +2100,7 @@ "integrity": "sha512-LTATglVUPGkPf15zX1wTMlZ0+AU7cGEGF6ekVF1crA8eHUWsGjrYTB+Ht4E3HTrCok8weQG+K01rJndCp/l4XA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/core": "^0.16.13" @@ -2144,6 +2143,7 @@ "integrity": "sha512-8Z1k96ZFxlhK2bgrY1JNWNwvaBeI/bciLM0yDOni2+aZwfIIiC7Y6PeWHTAvjHNjphz+XCt01WQmOYWCn0ML6g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13" @@ -2158,6 +2158,7 @@ "integrity": "sha512-PvLrfa8vkej3qinlebyhLpksJgCF5aiysDMSVhOZqwH5nQLLtDE9WYbnsofGw4r0VVpyw3H/ANCIzYTyCtP9Cg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13" @@ -2186,6 +2187,7 @@ "integrity": "sha512-xW+9BtEvoIkkH/Wde9ql4nAFbYLkVINhpgAE7VcBUsuuB34WUbcBl/taOuUYQrPEFQJ4jfXiAJZ2H/rvKjCVnQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13", @@ -2235,6 +2237,7 @@ "integrity": "sha512-WEl2tPVYwzYL8OKme6Go2xqiWgKsgxlMwyHabdAU4tXaRwOCnOI7v4021gCcBb9zn/oWwguHuKHmK30Fw2Z/PA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13" @@ -2378,6 +2381,7 @@ "integrity": "sha512-qoqtN8LDknm3fJm9nuPygJv30O3vGhSBD2TxrsCnhtOsxKAqVPJtFVdGd/qVuZ8nqQANQmTlfqTiK9mVWQ7MiQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13" @@ -2392,6 +2396,7 @@ "integrity": "sha512-Ev+Jjmj1nHYw897z9C3R9dYsPv7S2/nxdgfFb/h8hOwK0Ovd1k/+yYS46A0uj/JCKK0pQk8wOslYBkPwdnLorw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13" @@ -2409,6 +2414,7 @@ "integrity": "sha512-05POQaEJVucjTiSGMoH68ZiELc7QqpIpuQlZ2JBbhCV+WCbPFUBcGSmE7w4Jd0E2GvCho/NoMODLwgcVGQA97A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13" @@ -2827,7 +2833,6 @@ "integrity": "sha512-a6R+bXKeXMDcRmjYQoBIK+v2EYqxSX49wcjAY579EYM/WrFKS98nSees6lqVUcLKrcQh2DT9srJHX7XMny3voQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@pixi/colord": "^2.9.6" } @@ -2844,8 +2849,7 @@ "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-7.4.3.tgz", "integrity": "sha512-QGmwJUNQy/vVEHzL6VGQvnwawLZ1wceZMI8HwJAT4/I2uAzbBeFDdmCS8WsTpSWLZjF/DszDc1D8BFp4pVJ5UQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@pixi/core": { "version": "7.4.3", @@ -2874,8 +2878,7 @@ "resolved": "https://registry.npmjs.org/@pixi/extensions/-/extensions-7.4.3.tgz", "integrity": "sha512-FhoiYkHQEDYHUE7wXhqfsTRz6KxLXjuMbSiAwnLb9uG1vAgp6q6qd6HEsf4X30YaZbLFY8a4KY6hFZWjF+4Fdw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@pixi/filter-drop-shadow": { "version": "5.2.0", @@ -2915,16 +2918,14 @@ "resolved": "https://registry.npmjs.org/@pixi/math/-/math-7.4.3.tgz", "integrity": "sha512-/uJOVhR2DOZ+zgdI6Bs/CwcXT4bNRKsS+TqX3ekRIxPCwaLra+Qdm7aDxT5cTToDzdxbKL5+rwiLu3Y1egILDw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@pixi/runner": { "version": "7.4.3", "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-7.4.3.tgz", "integrity": "sha512-TJyfp7y23u5vvRAyYhVSa7ytq0PdKSvPLXu4G3meoFh1oxTLHH6g/RIzLuxUAThPG2z7ftthuW3qWq6dRV+dhw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@pixi/settings": { "version": "7.4.3", @@ -2932,7 +2933,6 @@ "integrity": "sha512-SmGK8smc0PxRB9nr0UJioEtE9hl4gvj9OedCvZx3bxBwA3omA5BmP3CyhQfN8XJ29+o2OUL01r3zAPVol4l4lA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@pixi/constants": "7.4.3", "@types/css-font-loading-module": "^0.0.12", @@ -2945,7 +2945,6 @@ "integrity": "sha512-tHsAD0iOUb6QSGGw+c8cyRBvxsq/NlfzIFBZLEHhWZ+Bx4a0MmXup6I/yJDGmyPCYE+ctCcAfY13wKAzdiVFgQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@pixi/extensions": "7.4.3", "@pixi/settings": "7.4.3", @@ -2958,7 +2957,6 @@ "integrity": "sha512-NO3Y9HAn2UKS1YdxffqsPp+kDpVm8XWvkZcS/E+rBzY9VTLnNOI7cawSRm+dacdET3a8Jad3aDKEDZ0HmAqAFA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@pixi/color": "7.4.3", "@pixi/constants": "7.4.3", @@ -2974,24 +2972,21 @@ "resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-2.1.4.tgz", "integrity": "sha512-qp3m9PPz4gULB9MhjGID7wpo3gJ4bTGXm7ltNDsmOvsPduTeHp8wSW9YckBj3mljeOh4F0m2z/0JKAALRKbmLQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@pixi/utils/node_modules/earcut": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/@pixi/utils/node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", @@ -4515,6 +4510,7 @@ "integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -4526,6 +4522,7 @@ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -4819,6 +4816,7 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5610,6 +5608,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -5828,7 +5827,6 @@ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" @@ -6262,8 +6260,7 @@ "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -6555,6 +6552,7 @@ "integrity": "sha512-uOOBA3f+kW3o4KpSoMQ6SNpdXU7WtxlJRb9vCZgOvqhTz4b3GjcoWKstdisizNZLsylhTMv8TLHFPFW0Uxsj/g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "app-builder-lib": "26.7.0", "builder-util": "26.4.1", @@ -6968,7 +6966,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", @@ -6989,7 +6986,6 @@ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -8653,6 +8649,7 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -9567,7 +9564,6 @@ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 0.4" }, @@ -10115,6 +10111,7 @@ "integrity": "sha512-ituDiEBb1Oqx56RYwTtC6MjPUhPfF/i15fpUv5oEqmzC/ce3SaSumulJcOjKG7+y0J0Ekl9Rl4XTxaUw+MVFZw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@pixi/colord": "^2.9.6", "@types/css-font-loading-module": "^0.0.12", @@ -10185,6 +10182,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -10335,7 +10333,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "commander": "^9.4.0" }, @@ -10353,7 +10350,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": "^12.20.0 || >=14" } @@ -10496,7 +10492,6 @@ "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "side-channel": "^1.1.0" }, @@ -10557,6 +10552,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -10569,6 +10565,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -11365,7 +11362,6 @@ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -11386,7 +11382,6 @@ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -11404,7 +11399,6 @@ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -11424,7 +11418,6 @@ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -12036,6 +12029,7 @@ "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -12084,7 +12078,6 @@ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -12148,7 +12141,6 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -12163,7 +12155,6 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -12177,6 +12168,7 @@ "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -12338,6 +12330,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -12561,7 +12554,6 @@ "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "punycode": "^1.4.1", "qs": "^6.12.3" @@ -12575,8 +12567,7 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/use-callback-ref": { "version": "1.3.3", @@ -12693,6 +12684,7 @@ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -12767,7 +12759,8 @@ "resolved": "https://registry.npmjs.org/vite-plugin-electron-renderer/-/vite-plugin-electron-renderer-0.14.6.tgz", "integrity": "sha512-oqkWFa7kQIkvHXG7+Mnl1RTroA4sP0yesKatmAy0gjZC4VwUqlvF9IvOpHd1fpLWsqYX/eZlVxlhULNtaQ78Jw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/vitest": { "version": "4.0.16", @@ -13331,6 +13324,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -13344,6 +13338,7 @@ "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", diff --git a/package.json b/package.json index 6357c6667..2275f2f80 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { - "name": "recordly", - "productName": "Recordly", - "description": "A free, creator-focused screen recorder with auto-zoom, cursor effects, backgrounds, annotations, and more - built for polished videos out of the box.", - "author": "webadderall", - "homepage": "https://github.com/webadderallorg/Recordly", + "name": "vybeclip", + "productName": "VybeClip", + "description": "A creator-focused screen recorder and demo video studio for polished walkthroughs, product videos, and branded clips.", + "author": "Box Creative Studio", + "homepage": "https://github.com/Alfredoalv13/Recordly", "repository": { "type": "git", - "url": "https://github.com/webadderallorg/Recordly.git" + "url": "https://github.com/Alfredoalv13/Recordly.git" }, "bugs": { - "url": "https://github.com/webadderallorg/Recordly/issues" + "url": "https://github.com/Alfredoalv13/Recordly/issues" }, "private": true, "version": "1.3.4", diff --git a/src/App.tsx b/src/App.tsx index 9e1f4e4c5..2a80102b0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -52,8 +52,8 @@ export default function App() { useEffect(() => { document.title = windowType === "editor" - ? t("app.editorTitle", "Recordly Editor") - : t("app.name", "Recordly"); + ? t("app.editorTitle", "VybeClip Editor") + : t("app.name", "VybeClip"); }, [windowType, t]); switch (windowType) { @@ -83,12 +83,12 @@ export default function App() {
{t("app.name",

- {t("app.name", "Recordly")} + {t("app.name", "VybeClip")}

{t("app.subtitle", "Screen recording and editing")} diff --git a/src/components/launch/UpdateToastWindow.tsx b/src/components/launch/UpdateToastWindow.tsx index e872a25cc..89d5a83bf 100644 --- a/src/components/launch/UpdateToastWindow.tsx +++ b/src/components/launch/UpdateToastWindow.tsx @@ -48,15 +48,15 @@ function getToastTitle(payload: UpdateToastPayload) { switch (payload.phase) { case "available": - return `Recordly ${payload.version} is available`; + return `VybeClip ${payload.version} is available`; case "downloading": - return `Installing Recordly ${payload.version}`; + return `Installing VybeClip ${payload.version}`; case "ready": - return `Recordly ${payload.version} is ready`; + return `VybeClip ${payload.version} is ready`; case "error": return payload.primaryAction === "retry-check" ? "Could not check for updates" - : `Recordly ${payload.version} needs attention`; + : `VybeClip ${payload.version} needs attention`; } } diff --git a/src/components/video-editor/TutorialHelp.tsx b/src/components/video-editor/TutorialHelp.tsx index a09e5c888..a5b842fbf 100644 --- a/src/components/video-editor/TutorialHelp.tsx +++ b/src/components/video-editor/TutorialHelp.tsx @@ -15,7 +15,7 @@ import { formatBinding, SHORTCUT_ACTIONS, SHORTCUT_LABELS } from "@/lib/shortcut import { formatShortcut } from "@/utils/platformUtils"; import { toast } from "sonner"; -export const RECORDLY_ISSUES_URL = "https://github.com/webadderallorg/Recordly/issues"; +export const RECORDLY_ISSUES_URL = "https://github.com/Alfredoalv13/Recordly/issues"; const RECORDLY_DISCORD_URL = "https://discord.gg/sdv2FBVNgE"; const RECORDLY_X_URL = "https://x.com/webadderall"; const CONTACT_EMAIL = "youngchen3442@gmail.com"; diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index f18b931f7..102b79791 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -5251,7 +5251,7 @@ export default function VideoEditor() { {t( "editor.nativeCaptureUnavailable.description", - "Your device does not support native capture. This could be for a variety of reasons we haven’t figured out yet. This doesn’t break Recordly, but it does make cursor smoothing impossible.", + "Your device does not support native capture. This could be for a variety of reasons we haven’t figured out yet. This doesn’t break VybeClip, but it does make cursor smoothing impossible.", )} diff --git a/src/hooks/useScreenRecorder.ts b/src/hooks/useScreenRecorder.ts index c5cd70056..fcaedb440 100644 --- a/src/hooks/useScreenRecorder.ts +++ b/src/hooks/useScreenRecorder.ts @@ -499,8 +499,8 @@ export function useScreenRecorder(): UseScreenRecorderReturn { await window.electronAPI.openScreenRecordingPreferences(); alert( options.startup - ? "Recordly needs Screen Recording permission before you start. System Settings has been opened. After enabling it, quit and reopen Recordly." - : "Screen Recording permission is still missing. System Settings has been opened again. Enable it, then quit and reopen Recordly before recording.", + ? "VybeClip needs Screen Recording permission before you start. System Settings has been opened. After enabling it, quit and reopen VybeClip." + : "Screen Recording permission is still missing. System Settings has been opened again. Enable it, then quit and reopen VybeClip before recording.", ); return false; } @@ -522,8 +522,8 @@ export function useScreenRecorder(): UseScreenRecorderReturn { await window.electronAPI.openAccessibilityPreferences(); alert( options.startup - ? "Recordly also needs Accessibility permission for cursor tracking. System Settings has been opened. After enabling it, quit and reopen Recordly." - : "Accessibility permission is still missing. System Settings has been opened again. Enable it, then quit and reopen Recordly before recording.", + ? "VybeClip also needs Accessibility permission for cursor tracking. System Settings has been opened. After enabling it, quit and reopen VybeClip." + : "Accessibility permission is still missing. System Settings has been opened again. Enable it, then quit and reopen VybeClip before recording.", ); return false; diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 98bb2c7aa..125afee1f 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Recordly Editor", + "name": "VybeClip", + "editorTitle": "VybeClip Editor", "subtitle": "Screen recording and editing", "language": "Language", "manageRecordings": "Open recordings folder" diff --git a/src/i18n/locales/en/editor.json b/src/i18n/locales/en/editor.json index 902522306..79c0067cb 100644 --- a/src/i18n/locales/en/editor.json +++ b/src/i18n/locales/en/editor.json @@ -115,7 +115,7 @@ }, "nativeCaptureUnavailable": { "title": "Nothing’s broken, but we won’t be able to render an animated cursor overlay.", - "description": "Your device does not support native capture. This could be for a variety of reasons we haven’t figured out yet. This doesn’t break Recordly, but it does make cursor smoothing impossible.", + "description": "Your device does not support native capture. This could be for a variety of reasons we haven’t figured out yet. This doesn’t break VybeClip, but it does make cursor smoothing impossible.", "confirm": "Okay" }, "exportStatus": { diff --git a/src/i18n/locales/en/launch.json b/src/i18n/locales/en/launch.json index 9dfcbe038..27468c7ed 100644 --- a/src/i18n/locales/en/launch.json +++ b/src/i18n/locales/en/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "Checking for updates...", "downloadingTitle": "Downloading update...", "errorTitle": "Update check failed. Click to retry.", - "upToDateTitle": "Recordly {{version}} is up to date.", - "availableTitle": "Recordly {{version}} is available.", + "upToDateTitle": "VybeClip {{version}} is up to date.", + "availableTitle": "VybeClip {{version}} is available.", "availableGenericTitle": "An update is available." } }, @@ -67,10 +67,10 @@ "share": "Share" }, "permissions": { - "screenRecordingNeeded": "Recordly needs Screen Recording permission before you start. System Settings has been opened. After enabling it, quit and reopen Recordly.", - "screenRecordingMissing": "Screen Recording permission is still missing. System Settings has been opened again. Enable it, then quit and reopen Recordly before recording.", - "accessibilityNeeded": "Recordly also needs Accessibility permission for cursor tracking. System Settings has been opened. After enabling it, quit and reopen Recordly.", - "accessibilityMissing": "Accessibility permission is still missing. System Settings has been opened again. Enable it, then quit and reopen Recordly before recording.", + "screenRecordingNeeded": "VybeClip needs Screen Recording permission before you start. System Settings has been opened. After enabling it, quit and reopen VybeClip.", + "screenRecordingMissing": "Screen Recording permission is still missing. System Settings has been opened again. Enable it, then quit and reopen VybeClip before recording.", + "accessibilityNeeded": "VybeClip also needs Accessibility permission for cursor tracking. System Settings has been opened. After enabling it, quit and reopen VybeClip.", + "accessibilityMissing": "Accessibility permission is still missing. System Settings has been opened again. Enable it, then quit and reopen VybeClip before recording.", "selectSource": "Please select a source to record", "systemAudioUnavailable": "System audio is not available for this source. Recording will continue without system audio.", "microphoneDenied": "Microphone access was denied. Recording will continue without microphone audio.", diff --git a/src/i18n/locales/en/settings.json b/src/i18n/locales/en/settings.json index dc24cd97a..a67253403 100644 --- a/src/i18n/locales/en/settings.json +++ b/src/i18n/locales/en/settings.json @@ -85,7 +85,7 @@ "connectedZoomDuration": "Connected Zoom Duration", "connectedZoomEasing": "Connected Pan Curve", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "Glide", "smooth": "Smooth", "snappy": "Snappy", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index f74c23773..6bcb7d04a 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Editor de Recordly", + "name": "VybeClip", + "editorTitle": "Editor de VybeClip", "subtitle": "Grabación de pantalla y edición", "language": "Idioma", "manageRecordings": "Abrir carpeta de grabaciones" diff --git a/src/i18n/locales/es/editor.json b/src/i18n/locales/es/editor.json index 40373f1a6..ef204f93f 100644 --- a/src/i18n/locales/es/editor.json +++ b/src/i18n/locales/es/editor.json @@ -115,7 +115,7 @@ }, "nativeCaptureUnavailable": { "title": "Nada está roto, pero no podremos renderizar una superposición de cursor animada.", - "description": "Tu dispositivo no es compatible con la captura nativa. Esto puede deberse a varias razones que todavía no hemos identificado. Recordly seguirá funcionando, pero hará imposible el suavizado del cursor.", + "description": "Tu dispositivo no es compatible con la captura nativa. Esto puede deberse a varias razones que todavía no hemos identificado. VybeClip seguirá funcionando, pero hará imposible el suavizado del cursor.", "confirm": "Entendido" }, "exportStatus": { diff --git a/src/i18n/locales/es/launch.json b/src/i18n/locales/es/launch.json index a458844a2..5502c7433 100644 --- a/src/i18n/locales/es/launch.json +++ b/src/i18n/locales/es/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "Buscando actualizaciones...", "downloadingTitle": "Descargando actualización...", "errorTitle": "La comprobación de actualizaciones falló. Haz clic para reintentar.", - "upToDateTitle": "Recordly {{version}} está actualizado.", - "availableTitle": "Recordly {{version}} está disponible.", + "upToDateTitle": "VybeClip {{version}} está actualizado.", + "availableTitle": "VybeClip {{version}} está disponible.", "availableGenericTitle": "Hay una actualización disponible." } }, @@ -67,10 +67,10 @@ "share": "Compartir" }, "permissions": { - "screenRecordingNeeded": "Recordly necesita permiso de grabación de pantalla antes de comenzar. Se ha abierto Configuración del sistema. Después de habilitarlo, cierra y vuelve a abrir Recordly.", - "screenRecordingMissing": "El permiso de grabación de pantalla aún falta. Se ha abierto Configuración del sistema nuevamente. Habilítalo, luego cierra y vuelve a abrir Recordly antes de grabar.", - "accessibilityNeeded": "Recordly también necesita permiso de accesibilidad para el seguimiento del cursor. Se ha abierto Configuración del sistema. Después de habilitarlo, cierra y vuelve a abrir Recordly.", - "accessibilityMissing": "El permiso de accesibilidad aún falta. Se ha abierto Configuración del sistema nuevamente. Habilítalo, luego cierra y vuelve a abrir Recordly antes de grabar.", + "screenRecordingNeeded": "VybeClip necesita permiso de grabación de pantalla antes de comenzar. Se ha abierto Configuración del sistema. Después de habilitarlo, cierra y vuelve a abrir VybeClip.", + "screenRecordingMissing": "El permiso de grabación de pantalla aún falta. Se ha abierto Configuración del sistema nuevamente. Habilítalo, luego cierra y vuelve a abrir VybeClip antes de grabar.", + "accessibilityNeeded": "VybeClip también necesita permiso de accesibilidad para el seguimiento del cursor. Se ha abierto Configuración del sistema. Después de habilitarlo, cierra y vuelve a abrir VybeClip.", + "accessibilityMissing": "El permiso de accesibilidad aún falta. Se ha abierto Configuración del sistema nuevamente. Habilítalo, luego cierra y vuelve a abrir VybeClip antes de grabar.", "selectSource": "Por favor selecciona una fuente para grabar", "systemAudioUnavailable": "El audio del sistema no está disponible para esta fuente. La grabación continuará sin audio del sistema.", "microphoneDenied": "Se denegó el acceso al micrófono. La grabación continuará sin audio del micrófono.", diff --git a/src/i18n/locales/es/settings.json b/src/i18n/locales/es/settings.json index 66a05e89c..1d3d36d01 100644 --- a/src/i18n/locales/es/settings.json +++ b/src/i18n/locales/es/settings.json @@ -66,7 +66,7 @@ "connectedZoomDuration": "Duración entre zooms conectados", "connectedZoomEasing": "Curva del paneo conectado", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "Glide", "smooth": "Suave", "snappy": "Rápida", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index 38daaa826..37af554cf 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Recordly Editor", + "name": "VybeClip", + "editorTitle": "VybeClip Editor", "subtitle": "Enregistrement et édition d’écran", "language": "Langue", "manageRecordings": "Ouvrir le dossier des enregistrements" diff --git a/src/i18n/locales/fr/editor.json b/src/i18n/locales/fr/editor.json index cb4b4d13f..58cb4c746 100644 --- a/src/i18n/locales/fr/editor.json +++ b/src/i18n/locales/fr/editor.json @@ -115,7 +115,7 @@ }, "nativeCaptureUnavailable": { "title": "Rien n'est cassé, mais nous ne pourrons pas afficher une superposition animée du curseur.", - "description": "Votre appareil ne prend pas en charge la capture native. Cela peut arriver pour plusieurs raisons que nous n'avons pas encore identifiées. Recordly continuera de fonctionner, mais le lissage du curseur sera impossible.", + "description": "Votre appareil ne prend pas en charge la capture native. Cela peut arriver pour plusieurs raisons que nous n'avons pas encore identifiées. VybeClip continuera de fonctionner, mais le lissage du curseur sera impossible.", "confirm": "D'accord" }, "exportStatus": { diff --git a/src/i18n/locales/fr/launch.json b/src/i18n/locales/fr/launch.json index df2e43b2b..b20ffe021 100644 --- a/src/i18n/locales/fr/launch.json +++ b/src/i18n/locales/fr/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "Vérification des mises à jour...", "downloadingTitle": "Téléchargement de la mise à jour...", "errorTitle": "Échec de la vérification des mises à jour. Cliquez pour réessayer.", - "upToDateTitle": "Recordly {{version}} est à jour.", - "availableTitle": "Recordly {{version}} est disponible.", + "upToDateTitle": "VybeClip {{version}} est à jour.", + "availableTitle": "VybeClip {{version}} est disponible.", "availableGenericTitle": "Une mise à jour est disponible." } }, @@ -67,10 +67,10 @@ "share": "Partager" }, "permissions": { - "screenRecordingNeeded": "Recordly nécessite l’autorisation d’enregistrement d’écran avant de commencer. Les paramètres système ont été ouverts. Après l’avoir activée, quittez et relancez Recordly.", - "screenRecordingMissing": "L’autorisation d’enregistrement d’écran est toujours manquante. Les paramètres système ont été ouverts à nouveau. Activez-la, puis quittez et relancez Recordly avant d’enregistrer.", - "accessibilityNeeded": "Recordly nécessite également l’autorisation d’accessibilité pour le suivi du curseur. Les paramètres système ont été ouverts. Après l’avoir activée, quittez et relancez Recordly.", - "accessibilityMissing": "L’autorisation d’accessibilité est toujours manquante. Les paramètres système ont été ouverts à nouveau. Activez-la, puis quittez et relancez Recordly avant d’enregistrer.", + "screenRecordingNeeded": "VybeClip nécessite l’autorisation d’enregistrement d’écran avant de commencer. Les paramètres système ont été ouverts. Après l’avoir activée, quittez et relancez VybeClip.", + "screenRecordingMissing": "L’autorisation d’enregistrement d’écran est toujours manquante. Les paramètres système ont été ouverts à nouveau. Activez-la, puis quittez et relancez VybeClip avant d’enregistrer.", + "accessibilityNeeded": "VybeClip nécessite également l’autorisation d’accessibilité pour le suivi du curseur. Les paramètres système ont été ouverts. Après l’avoir activée, quittez et relancez VybeClip.", + "accessibilityMissing": "L’autorisation d’accessibilité est toujours manquante. Les paramètres système ont été ouverts à nouveau. Activez-la, puis quittez et relancez VybeClip avant d’enregistrer.", "selectSource": "Veuillez sélectionner une source à enregistrer", "systemAudioUnavailable": "L’audio système n’est pas disponible pour cette source. L’enregistrement continuera sans audio système.", "microphoneDenied": "L’accès au microphone a été refusé. L’enregistrement continuera sans audio du microphone.", diff --git a/src/i18n/locales/fr/settings.json b/src/i18n/locales/fr/settings.json index 200ecaa02..4f4369106 100644 --- a/src/i18n/locales/fr/settings.json +++ b/src/i18n/locales/fr/settings.json @@ -66,7 +66,7 @@ "connectedZoomDuration": "Durée du zoom connecté", "connectedZoomEasing": "Courbe du pan connecté", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "Glide", "smooth": "Lisse", "snappy": "Rapide", diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index 9c270d7e8..a09c6ea01 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Editor Recordly", + "name": "VybeClip", + "editorTitle": "Editor VybeClip", "subtitle": "Registrazione e modifica dello schermo", "language": "Lingua", "manageRecordings": "Apri cartella registrazioni" diff --git a/src/i18n/locales/it/editor.json b/src/i18n/locales/it/editor.json index b23d247da..44c5a785e 100644 --- a/src/i18n/locales/it/editor.json +++ b/src/i18n/locales/it/editor.json @@ -115,7 +115,7 @@ }, "nativeCaptureUnavailable": { "title": "Niente è rotto, ma non sarà possibile renderizzare un overlay del cursore animato.", - "description": "Il tuo dispositivo non supporta la cattura nativa. Le cause possono essere varie e non ancora identificate. Recordly funziona comunque, ma non è possibile applicare lo smoothing del cursore.", + "description": "Il tuo dispositivo non supporta la cattura nativa. Le cause possono essere varie e non ancora identificate. VybeClip funziona comunque, ma non è possibile applicare lo smoothing del cursore.", "confirm": "Ok" }, "exportStatus": { diff --git a/src/i18n/locales/it/launch.json b/src/i18n/locales/it/launch.json index c27abc3ad..2fe3165f3 100644 --- a/src/i18n/locales/it/launch.json +++ b/src/i18n/locales/it/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "Verifica aggiornamenti in corso...", "downloadingTitle": "Download dell'aggiornamento in corso...", "errorTitle": "Verifica aggiornamenti non riuscita. Clicca per riprovare.", - "upToDateTitle": "Recordly {{version}} è aggiornato.", - "availableTitle": "Recordly {{version}} è disponibile.", + "upToDateTitle": "VybeClip {{version}} è aggiornato.", + "availableTitle": "VybeClip {{version}} è disponibile.", "availableGenericTitle": "È disponibile un aggiornamento." } }, @@ -67,10 +67,10 @@ "share": "Condividi" }, "permissions": { - "screenRecordingNeeded": "Recordly necessita del permesso di Registrazione schermo prima di iniziare. Sono state aperte le Impostazioni di sistema. Dopo averlo abilitato, esci e riapri Recordly.", - "screenRecordingMissing": "Manca ancora il permesso di Registrazione schermo. Le Impostazioni di sistema sono state riaperte. Abilitalo, poi esci e riapri Recordly prima di registrare.", - "accessibilityNeeded": "Recordly necessita anche del permesso di Accessibilità per il tracciamento del cursore. Sono state aperte le Impostazioni di sistema. Dopo averlo abilitato, esci e riapri Recordly.", - "accessibilityMissing": "Manca ancora il permesso di Accessibilità. Le Impostazioni di sistema sono state riaperte. Abilitalo, poi esci e riapri Recordly prima di registrare.", + "screenRecordingNeeded": "VybeClip necessita del permesso di Registrazione schermo prima di iniziare. Sono state aperte le Impostazioni di sistema. Dopo averlo abilitato, esci e riapri VybeClip.", + "screenRecordingMissing": "Manca ancora il permesso di Registrazione schermo. Le Impostazioni di sistema sono state riaperte. Abilitalo, poi esci e riapri VybeClip prima di registrare.", + "accessibilityNeeded": "VybeClip necessita anche del permesso di Accessibilità per il tracciamento del cursore. Sono state aperte le Impostazioni di sistema. Dopo averlo abilitato, esci e riapri VybeClip.", + "accessibilityMissing": "Manca ancora il permesso di Accessibilità. Le Impostazioni di sistema sono state riaperte. Abilitalo, poi esci e riapri VybeClip prima di registrare.", "selectSource": "Seleziona una sorgente da registrare", "systemAudioUnavailable": "L'audio di sistema non è disponibile per questa sorgente. La registrazione continuerà senza audio di sistema.", "microphoneDenied": "L'accesso al microfono è stato negato. La registrazione continuerà senza audio del microfono.", diff --git a/src/i18n/locales/it/settings.json b/src/i18n/locales/it/settings.json index d9b9a1a18..0263a93ce 100644 --- a/src/i18n/locales/it/settings.json +++ b/src/i18n/locales/it/settings.json @@ -85,7 +85,7 @@ "connectedZoomDuration": "Durata zoom connessi", "connectedZoomEasing": "Curva pan connesso", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "Glide", "smooth": "Fluido", "snappy": "Rapido", diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index f036318e0..f6644e136 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Recordly 편집기", + "name": "VybeClip", + "editorTitle": "VybeClip 편집기", "subtitle": "화면 녹화 및 편집", "language": "언어", "manageRecordings": "녹화 폴더 열기" diff --git a/src/i18n/locales/ko/editor.json b/src/i18n/locales/ko/editor.json index 49678dee1..affcc6e63 100644 --- a/src/i18n/locales/ko/editor.json +++ b/src/i18n/locales/ko/editor.json @@ -116,7 +116,7 @@ }, "nativeCaptureUnavailable": { "title": "문제가 생긴 것은 아니지만, 애니메이션 커서 오버레이를 렌더링할 수 없습니다.", - "description": "이 장치는 네이티브 캡처를 지원하지 않습니다. 아직 확인하지 못한 여러 이유가 있을 수 있습니다. Recordly는 계속 작동하지만 커서 스무딩은 사용할 수 없습니다.", + "description": "이 장치는 네이티브 캡처를 지원하지 않습니다. 아직 확인하지 못한 여러 이유가 있을 수 있습니다. VybeClip는 계속 작동하지만 커서 스무딩은 사용할 수 없습니다.", "confirm": "확인" }, "exportStatus": { diff --git a/src/i18n/locales/ko/launch.json b/src/i18n/locales/ko/launch.json index 345000399..2c47bb0a0 100644 --- a/src/i18n/locales/ko/launch.json +++ b/src/i18n/locales/ko/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "업데이트를 확인하는 중...", "downloadingTitle": "업데이트를 다운로드하는 중...", "errorTitle": "업데이트 확인에 실패했습니다. 클릭하여 다시 시도하세요.", - "upToDateTitle": "Recordly {{version}}은(는) 최신 버전입니다.", - "availableTitle": "Recordly {{version}}을(를) 사용할 수 있습니다.", + "upToDateTitle": "VybeClip {{version}}은(는) 최신 버전입니다.", + "availableTitle": "VybeClip {{version}}을(를) 사용할 수 있습니다.", "availableGenericTitle": "업데이트를 사용할 수 있습니다." } }, @@ -67,10 +67,10 @@ "share": "공유" }, "permissions": { - "screenRecordingNeeded": "녹화를 시작하기 전에 Recordly에 화면 녹화 권한이 필요합니다. 시스템 설정을 열었습니다. 권한을 허용한 뒤 Recordly를 종료하고 다시 실행해 주세요.", - "screenRecordingMissing": "화면 녹화 권한이 아직 없습니다. 시스템 설정을 다시 열었습니다. 권한을 허용한 뒤 Recordly를 종료하고 다시 실행한 후 녹화를 시작해 주세요.", - "accessibilityNeeded": "커서 추적을 위해 Recordly에 손쉬운 사용 권한도 필요합니다. 시스템 설정을 열었습니다. 권한을 허용한 뒤 Recordly를 종료하고 다시 실행해 주세요.", - "accessibilityMissing": "손쉬운 사용 권한이 아직 없습니다. 시스템 설정을 다시 열었습니다. 권한을 허용한 뒤 Recordly를 종료하고 다시 실행한 후 녹화를 시작해 주세요.", + "screenRecordingNeeded": "녹화를 시작하기 전에 VybeClip에 화면 녹화 권한이 필요합니다. 시스템 설정을 열었습니다. 권한을 허용한 뒤 VybeClip를 종료하고 다시 실행해 주세요.", + "screenRecordingMissing": "화면 녹화 권한이 아직 없습니다. 시스템 설정을 다시 열었습니다. 권한을 허용한 뒤 VybeClip를 종료하고 다시 실행한 후 녹화를 시작해 주세요.", + "accessibilityNeeded": "커서 추적을 위해 VybeClip에 손쉬운 사용 권한도 필요합니다. 시스템 설정을 열었습니다. 권한을 허용한 뒤 VybeClip를 종료하고 다시 실행해 주세요.", + "accessibilityMissing": "손쉬운 사용 권한이 아직 없습니다. 시스템 설정을 다시 열었습니다. 권한을 허용한 뒤 VybeClip를 종료하고 다시 실행한 후 녹화를 시작해 주세요.", "selectSource": "녹화할 소스를 선택해 주세요", "systemAudioUnavailable": "이 소스에서는 시스템 오디오를 사용할 수 없습니다. 시스템 오디오 없이 녹화를 계속합니다.", "microphoneDenied": "마이크 접근이 거부되었습니다. 마이크 오디오 없이 녹화를 계속합니다.", diff --git a/src/i18n/locales/ko/settings.json b/src/i18n/locales/ko/settings.json index c528a98fb..326fcba90 100644 --- a/src/i18n/locales/ko/settings.json +++ b/src/i18n/locales/ko/settings.json @@ -66,7 +66,7 @@ "connectedZoomDuration": "연결 확대 시간", "connectedZoomEasing": "연결 이동 커브", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "Glide", "smooth": "Smooth", "snappy": "Snappy", diff --git a/src/i18n/locales/nl/common.json b/src/i18n/locales/nl/common.json index 0e7c2f33f..2bcb133c5 100644 --- a/src/i18n/locales/nl/common.json +++ b/src/i18n/locales/nl/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Recordly Editor", + "name": "VybeClip", + "editorTitle": "VybeClip Editor", "subtitle": "Schermopname en bewerking", "language": "Taal", "manageRecordings": "Opnamemap openen" diff --git a/src/i18n/locales/nl/editor.json b/src/i18n/locales/nl/editor.json index d58b9e525..8a638dc5f 100644 --- a/src/i18n/locales/nl/editor.json +++ b/src/i18n/locales/nl/editor.json @@ -116,7 +116,7 @@ }, "nativeCaptureUnavailable": { "title": "Er is niets kapot, maar we kunnen geen geanimeerde cursor-overlay renderen.", - "description": "Je apparaat ondersteunt geen native capture. Dit kan verschillende oorzaken hebben die we nog niet hebben achterhaald. Recordly blijft werken, maar cursor smoothing is dan niet mogelijk.", + "description": "Je apparaat ondersteunt geen native capture. Dit kan verschillende oorzaken hebben die we nog niet hebben achterhaald. VybeClip blijft werken, maar cursor smoothing is dan niet mogelijk.", "confirm": "Oké" }, "exportStatus": { diff --git a/src/i18n/locales/nl/launch.json b/src/i18n/locales/nl/launch.json index d3d5870c9..867a46116 100644 --- a/src/i18n/locales/nl/launch.json +++ b/src/i18n/locales/nl/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "Controleren op updates...", "downloadingTitle": "Update downloaden...", "errorTitle": "Updatecontrole mislukt. Klik om opnieuw te proberen.", - "upToDateTitle": "Recordly {{version}} is up-to-date.", - "availableTitle": "Recordly {{version}} is beschikbaar.", + "upToDateTitle": "VybeClip {{version}} is up-to-date.", + "availableTitle": "VybeClip {{version}} is beschikbaar.", "availableGenericTitle": "Er is een update beschikbaar." } }, @@ -67,10 +67,10 @@ "share": "Delen" }, "permissions": { - "screenRecordingNeeded": "Recordly heeft toestemming voor schermopname nodig voordat je begint. Systeeminstellingen zijn geopend. Schakel het in, sluit Recordly en open het opnieuw.", - "screenRecordingMissing": "Toestemming voor schermopname ontbreekt nog. Systeeminstellingen zijn opnieuw geopend. Schakel het in, sluit Recordly en open het opnieuw voordat je opneemt.", - "accessibilityNeeded": "Recordly heeft ook toegankelijkheidstoestemming nodig voor cursortracking. Systeeminstellingen zijn geopend. Schakel het in, sluit Recordly en open het opnieuw.", - "accessibilityMissing": "Toegankelijkheidstoestemming ontbreekt nog. Systeeminstellingen zijn opnieuw geopend. Schakel het in, sluit Recordly en open het opnieuw voordat je opneemt.", + "screenRecordingNeeded": "VybeClip heeft toestemming voor schermopname nodig voordat je begint. Systeeminstellingen zijn geopend. Schakel het in, sluit VybeClip en open het opnieuw.", + "screenRecordingMissing": "Toestemming voor schermopname ontbreekt nog. Systeeminstellingen zijn opnieuw geopend. Schakel het in, sluit VybeClip en open het opnieuw voordat je opneemt.", + "accessibilityNeeded": "VybeClip heeft ook toegankelijkheidstoestemming nodig voor cursortracking. Systeeminstellingen zijn geopend. Schakel het in, sluit VybeClip en open het opnieuw.", + "accessibilityMissing": "Toegankelijkheidstoestemming ontbreekt nog. Systeeminstellingen zijn opnieuw geopend. Schakel het in, sluit VybeClip en open het opnieuw voordat je opneemt.", "selectSource": "Selecteer een bron om op te nemen", "systemAudioUnavailable": "Systeemaudio is niet beschikbaar voor deze bron. De opname gaat verder zonder systeemaudio.", "microphoneDenied": "Microfoontoegang is geweigerd. De opname gaat verder zonder microfoonaudio.", diff --git a/src/i18n/locales/nl/settings.json b/src/i18n/locales/nl/settings.json index d88e4278c..977c73ce8 100644 --- a/src/i18n/locales/nl/settings.json +++ b/src/i18n/locales/nl/settings.json @@ -66,7 +66,7 @@ "connectedZoomDuration": "Verbonden zoomduur", "connectedZoomEasing": "Verbonden pancurve", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "Glijden", "smooth": "Vloeiend", "snappy": "Pittig", diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index 97a2ea1d9..40e2862dd 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Editor do Recordly", + "name": "VybeClip", + "editorTitle": "Editor do VybeClip", "subtitle": "Gravação e edição de tela", "language": "Idioma", "manageRecordings": "Abrir pasta de gravações" diff --git a/src/i18n/locales/pt-BR/editor.json b/src/i18n/locales/pt-BR/editor.json index 702939fd1..9eb2c1b23 100644 --- a/src/i18n/locales/pt-BR/editor.json +++ b/src/i18n/locales/pt-BR/editor.json @@ -115,7 +115,7 @@ }, "nativeCaptureUnavailable": { "title": "Nada está quebrado, mas não poderemos renderizar uma sobreposição animada do cursor.", - "description": "Seu dispositivo não oferece suporte à captura nativa. Isso pode acontecer por vários motivos que ainda não identificamos. O Recordly continuará funcionando, mas a suavização do cursor ficará indisponível.", + "description": "Seu dispositivo não oferece suporte à captura nativa. Isso pode acontecer por vários motivos que ainda não identificamos. O VybeClip continuará funcionando, mas a suavização do cursor ficará indisponível.", "confirm": "Entendi" }, "exportStatus": { diff --git a/src/i18n/locales/pt-BR/launch.json b/src/i18n/locales/pt-BR/launch.json index 8d19ac7db..0734dd83b 100644 --- a/src/i18n/locales/pt-BR/launch.json +++ b/src/i18n/locales/pt-BR/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "Verificando atualizações...", "downloadingTitle": "Baixando atualização...", "errorTitle": "Falha ao verificar atualizações. Clique para tentar novamente.", - "upToDateTitle": "Recordly {{version}} está atualizado.", - "availableTitle": "Recordly {{version}} está disponível.", + "upToDateTitle": "VybeClip {{version}} está atualizado.", + "availableTitle": "VybeClip {{version}} está disponível.", "availableGenericTitle": "Há uma atualização disponível." } }, @@ -67,10 +67,10 @@ "share": "Compartilhar" }, "permissions": { - "screenRecordingNeeded": "O Recordly precisa da permissão de Gravação de Tela antes de iniciar. Ajustes do Sistema foram abertos. Depois de ativar, feche e reabra o Recordly.", - "screenRecordingMissing": "A permissão de Gravação de Tela ainda está ausente. Ajustes do Sistema foram abertos novamente. Ative e depois feche e reabra o Recordly antes de gravar.", - "accessibilityNeeded": "O Recordly também precisa da permissão de Acessibilidade para rastrear o cursor. Ajustes do Sistema foram abertos. Depois de ativar, feche e reabra o Recordly.", - "accessibilityMissing": "A permissão de Acessibilidade ainda está ausente. Ajustes do Sistema foram abertos novamente. Ative e depois feche e reabra o Recordly antes de gravar.", + "screenRecordingNeeded": "O VybeClip precisa da permissão de Gravação de Tela antes de iniciar. Ajustes do Sistema foram abertos. Depois de ativar, feche e reabra o VybeClip.", + "screenRecordingMissing": "A permissão de Gravação de Tela ainda está ausente. Ajustes do Sistema foram abertos novamente. Ative e depois feche e reabra o VybeClip antes de gravar.", + "accessibilityNeeded": "O VybeClip também precisa da permissão de Acessibilidade para rastrear o cursor. Ajustes do Sistema foram abertos. Depois de ativar, feche e reabra o VybeClip.", + "accessibilityMissing": "A permissão de Acessibilidade ainda está ausente. Ajustes do Sistema foram abertos novamente. Ative e depois feche e reabra o VybeClip antes de gravar.", "selectSource": "Selecione uma fonte para gravar", "systemAudioUnavailable": "O áudio do sistema não está disponível para esta fonte. A gravação continuará sem áudio do sistema.", "microphoneDenied": "O acesso ao microfone foi negado. A gravação continuará sem áudio do microfone.", diff --git a/src/i18n/locales/pt-BR/settings.json b/src/i18n/locales/pt-BR/settings.json index a34e6e4d2..594ae0e9c 100644 --- a/src/i18n/locales/pt-BR/settings.json +++ b/src/i18n/locales/pt-BR/settings.json @@ -66,7 +66,7 @@ "connectedZoomDuration": "Duração do zoom conectado", "connectedZoomEasing": "Curva de pan conectado", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "Glide", "smooth": "Smooth", "snappy": "Snappy", diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index 3946d72b9..aa24faf84 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Recordly Editor", + "name": "VybeClip", + "editorTitle": "VybeClip Editor", "subtitle": "Запись экрана и редактирование видео", "language": "Язык", "manageRecordings": "Открыть папку с записями" diff --git a/src/i18n/locales/ru/launch.json b/src/i18n/locales/ru/launch.json index 65bd57b8c..452ada2f9 100644 --- a/src/i18n/locales/ru/launch.json +++ b/src/i18n/locales/ru/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "Поиск обновлений...", "downloadingTitle": "Загрузка обновления...", "errorTitle": "Ошибка при проверке обновления. Нажмите, чтобы повторить", - "upToDateTitle": "У вас актуальная версия Recordly {{version}}.", - "availableTitle": "Доступна новая версия Recordly {{version}}.", + "upToDateTitle": "У вас актуальная версия VybeClip {{version}}.", + "availableTitle": "Доступна новая версия VybeClip {{version}}.", "availableGenericTitle": "Доступно обновление." } }, @@ -67,10 +67,10 @@ "share": "Поделиться" }, "permissions": { - "screenRecordingNeeded": "Recordly нужно разрешение на запись экрана. Мы открыли настройки – включите доступ и перезапустите приложение.", - "screenRecordingMissing": "Доступа к записи экрана всё ещё нет. Мы снова открыли настройки. Разрешите доступ и перезапустите Recordly.", - "accessibilityNeeded": "Разрешите Recordly использовать универсальный доступ, чтобы отслеживать курсор. Мы открыли настройки – включите его и перезапустите приложение.", - "accessibilityMissing": "Разрешения для универсального доступа всё ещё нет. Включите его в настройках и перезапустите Recordly.", + "screenRecordingNeeded": "VybeClip нужно разрешение на запись экрана. Мы открыли настройки – включите доступ и перезапустите приложение.", + "screenRecordingMissing": "Доступа к записи экрана всё ещё нет. Мы снова открыли настройки. Разрешите доступ и перезапустите VybeClip.", + "accessibilityNeeded": "Разрешите VybeClip использовать универсальный доступ, чтобы отслеживать курсор. Мы открыли настройки – включите его и перезапустите приложение.", + "accessibilityMissing": "Разрешения для универсального доступа всё ещё нет. Включите его в настройках и перезапустите VybeClip.", "selectSource": "Выберите источник записи", "systemAudioUnavailable": "Системные звуки недоступны для этого источника. Запись продолжится без их захвата.", "microphoneDenied": "Нет доступа к микрофону. Запись продолжится без вашего голоса.", diff --git a/src/i18n/locales/ru/settings.json b/src/i18n/locales/ru/settings.json index 687f8383b..76579ec3b 100644 --- a/src/i18n/locales/ru/settings.json +++ b/src/i18n/locales/ru/settings.json @@ -85,7 +85,7 @@ "connectedZoomDuration": "Длительность интервала", "connectedZoomEasing": "Кривая панорамирования", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "Плавно", "smooth": "Мягко", "snappy": "Резко", @@ -216,4 +216,4 @@ "mixedLabel": "Источник", "deleteRegion": "Удалить аудио" } -} \ No newline at end of file +} diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index b35ca3d8c..9cec83f09 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Recordly 编辑器", + "name": "VybeClip", + "editorTitle": "VybeClip 编辑器", "subtitle": "屏幕录制与编辑", "language": "语言", "manageRecordings": "打开录制文件夹" diff --git a/src/i18n/locales/zh-CN/editor.json b/src/i18n/locales/zh-CN/editor.json index 1bf3a6084..309ee044b 100644 --- a/src/i18n/locales/zh-CN/editor.json +++ b/src/i18n/locales/zh-CN/editor.json @@ -115,7 +115,7 @@ }, "nativeCaptureUnavailable": { "title": "没有出错,但我们无法渲染动画光标叠加层。", - "description": "你的设备不支持原生捕获。这可能是由我们尚未确定的多种原因造成的。Recordly 仍可继续运行,但无法进行光标平滑处理。", + "description": "你的设备不支持原生捕获。这可能是由我们尚未确定的多种原因造成的。VybeClip 仍可继续运行,但无法进行光标平滑处理。", "confirm": "好的" }, "exportStatus": { diff --git a/src/i18n/locales/zh-CN/launch.json b/src/i18n/locales/zh-CN/launch.json index 164c02afe..7ebc5a2f8 100644 --- a/src/i18n/locales/zh-CN/launch.json +++ b/src/i18n/locales/zh-CN/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "正在检查更新...", "downloadingTitle": "正在下载更新...", "errorTitle": "检查更新失败。点击重试。", - "upToDateTitle": "Recordly {{version}} 已是最新版本。", - "availableTitle": "Recordly {{version}} 可更新。", + "upToDateTitle": "VybeClip {{version}} 已是最新版本。", + "availableTitle": "VybeClip {{version}} 可更新。", "availableGenericTitle": "有可用更新。" } }, @@ -67,10 +67,10 @@ "share": "共享" }, "permissions": { - "screenRecordingNeeded": "Recordly 需要屏幕录制权限才能开始。系统设置已打开。启用后请退出并重新打开 Recordly。", - "screenRecordingMissing": "屏幕录制权限仍然缺失。系统设置已再次打开。请启用权限,然后退出并重新打开 Recordly。", - "accessibilityNeeded": "Recordly 还需要辅助功能权限以跟踪光标。系统设置已打开。启用后请退出并重新打开 Recordly。", - "accessibilityMissing": "辅助功能权限仍然缺失。系统设置已再次打开。请启用权限,然后退出并重新打开 Recordly。", + "screenRecordingNeeded": "VybeClip 需要屏幕录制权限才能开始。系统设置已打开。启用后请退出并重新打开 VybeClip。", + "screenRecordingMissing": "屏幕录制权限仍然缺失。系统设置已再次打开。请启用权限,然后退出并重新打开 VybeClip。", + "accessibilityNeeded": "VybeClip 还需要辅助功能权限以跟踪光标。系统设置已打开。启用后请退出并重新打开 VybeClip。", + "accessibilityMissing": "辅助功能权限仍然缺失。系统设置已再次打开。请启用权限,然后退出并重新打开 VybeClip。", "selectSource": "请选择要录制的源", "systemAudioUnavailable": "此源不支持系统音频。将继续录制但不包含系统音频。", "microphoneDenied": "麦克风访问被拒绝。将继续录制但不包含麦克风音频。", diff --git a/src/i18n/locales/zh-CN/settings.json b/src/i18n/locales/zh-CN/settings.json index a68d2a04f..0cc5d3ab6 100644 --- a/src/i18n/locales/zh-CN/settings.json +++ b/src/i18n/locales/zh-CN/settings.json @@ -80,7 +80,7 @@ "connectedZoomDuration": "连接缩放时长", "connectedZoomEasing": "连接平移曲线", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "滑行", "smooth": "平滑", "snappy": "利落", diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index c5fa86d10..db5080bc8 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -1,7 +1,7 @@ { "app": { - "name": "Recordly", - "editorTitle": "Recordly 編輯器", + "name": "VybeClip", + "editorTitle": "VybeClip 編輯器", "subtitle": "螢幕錄製與編輯", "language": "語言", "manageRecordings": "打開錄製影像文件夾" diff --git a/src/i18n/locales/zh-TW/editor.json b/src/i18n/locales/zh-TW/editor.json index 6f2b0f823..049768c5a 100644 --- a/src/i18n/locales/zh-TW/editor.json +++ b/src/i18n/locales/zh-TW/editor.json @@ -115,7 +115,7 @@ }, "nativeCaptureUnavailable": { "title": "沒有出錯,但我們無法轉譯動畫游標覆蓋層。", - "description": "你的裝置不支援原生擷取。這可能是由我們尚未釐清的多種原因造成的。Recordly 仍可繼續運作,但無法進行游標平滑處理。", + "description": "你的裝置不支援原生擷取。這可能是由我們尚未釐清的多種原因造成的。VybeClip 仍可繼續運作,但無法進行游標平滑處理。", "confirm": "好的" }, "exportStatus": { diff --git a/src/i18n/locales/zh-TW/launch.json b/src/i18n/locales/zh-TW/launch.json index 12ec494d0..4baaff259 100644 --- a/src/i18n/locales/zh-TW/launch.json +++ b/src/i18n/locales/zh-TW/launch.json @@ -50,8 +50,8 @@ "checkingTitle": "正在檢查更新...", "downloadingTitle": "正在下載更新...", "errorTitle": "檢查更新失敗,點一下重試。", - "upToDateTitle": "Recordly {{version}} 已是最新版本。", - "availableTitle": "Recordly {{version}} 已推出新版本。", + "upToDateTitle": "VybeClip {{version}} 已是最新版本。", + "availableTitle": "VybeClip {{version}} 已推出新版本。", "availableGenericTitle": "有可用更新。" } }, @@ -67,10 +67,10 @@ "share": "分享" }, "permissions": { - "screenRecordingNeeded": "Recordly 需要「螢幕錄製」權限才能開始。已開啟系統設定。啟用後,請結束並重新開啟 Recordly。", - "screenRecordingMissing": "仍未取得「螢幕錄製」權限。已再次開啟系統設定。請先啟用,再結束並重新開啟 Recordly 後再錄製。", - "accessibilityNeeded": "Recordly 也需要「輔助使用」權限以追蹤游標。已開啟系統設定。啟用後,請結束並重新開啟 Recordly。", - "accessibilityMissing": "仍未取得「輔助使用」權限。已再次開啟系統設定。請先啟用,再結束並重新開啟 Recordly 後再錄製。", + "screenRecordingNeeded": "VybeClip 需要「螢幕錄製」權限才能開始。已開啟系統設定。啟用後,請結束並重新開啟 VybeClip。", + "screenRecordingMissing": "仍未取得「螢幕錄製」權限。已再次開啟系統設定。請先啟用,再結束並重新開啟 VybeClip 後再錄製。", + "accessibilityNeeded": "VybeClip 也需要「輔助使用」權限以追蹤游標。已開啟系統設定。啟用後,請結束並重新開啟 VybeClip。", + "accessibilityMissing": "仍未取得「輔助使用」權限。已再次開啟系統設定。請先啟用,再結束並重新開啟 VybeClip 後再錄製。", "selectSource": "請選擇要錄製的來源", "systemAudioUnavailable": "此來源不支援系統音訊,將在沒有系統音訊的情況下繼續錄製。", "microphoneDenied": "麥克風存取遭拒,將在沒有麥克風音訊的情況下繼續錄製。", diff --git a/src/i18n/locales/zh-TW/settings.json b/src/i18n/locales/zh-TW/settings.json index db0ea7e04..c156b3178 100644 --- a/src/i18n/locales/zh-TW/settings.json +++ b/src/i18n/locales/zh-TW/settings.json @@ -66,7 +66,7 @@ "connectedZoomDuration": "連接縮放時間", "connectedZoomEasing": "連接平移曲線", "zoomEasingOptions": { - "recordly": "Recordly", + "recordly": "VybeClip", "glide": "滑行", "smooth": "平滑", "snappy": "俐落", diff --git a/src/lib/exporter/exportSavePolicy.ts b/src/lib/exporter/exportSavePolicy.ts index c48516ed3..9c9a7ce45 100644 --- a/src/lib/exporter/exportSavePolicy.ts +++ b/src/lib/exporter/exportSavePolicy.ts @@ -39,8 +39,8 @@ export function describeBlockedInMemoryExportSave({ }): string { const normalizedExtension = normalizeExportExtension(extension) || "export"; if (isExportTooLargeForInMemorySave(blobSize)) { - return `The ${normalizedExtension.toUpperCase()} export is too large to save through the legacy in-memory path. Please retry the export so Recordly can save it through the temp-file streaming path.`; + return `The ${normalizedExtension.toUpperCase()} export is too large to save through the legacy in-memory path. Please retry the export so VybeClip can save it through the temp-file streaming path.`; } - return `The ${normalizedExtension.toUpperCase()} export could not be saved through the temp-file streaming path, and Recordly will not fall back to the legacy in-memory path for MP4 exports. Please retry the export.`; + return `The ${normalizedExtension.toUpperCase()} export could not be saved through the temp-file streaming path, and VybeClip will not fall back to the legacy in-memory path for MP4 exports. Please retry the export.`; } From fae3771dccc351cddcea6007e40d120eb099c7e2 Mon Sep 17 00:00:00 2001 From: Side Quest Studios Date: Wed, 1 Jul 2026 17:40:07 -0400 Subject: [PATCH 03/32] Add VybeClip studio UI baseline --- _documentation/vybeclip_studio_mockup.html | 105 ++++++++ src/App.tsx | 22 +- src/components/brand/VybeClipLogo.tsx | 33 +++ src/components/launch/LaunchWindow.module.css | 20 +- src/components/launch/RecordingControls.tsx | 6 +- .../launch/SourceSelector.module.css | 12 +- src/components/launch/launchTheme.css | 30 +-- .../videoPlayback/zoomRegionUtils.ts | 7 +- src/components/vybe/VybeStudioPreview.tsx | 233 ++++++++++++++++++ src/index.css | 104 ++++---- 10 files changed, 464 insertions(+), 108 deletions(-) create mode 100644 _documentation/vybeclip_studio_mockup.html create mode 100644 src/components/brand/VybeClipLogo.tsx create mode 100644 src/components/vybe/VybeStudioPreview.tsx diff --git a/_documentation/vybeclip_studio_mockup.html b/_documentation/vybeclip_studio_mockup.html new file mode 100644 index 000000000..2ec3e00da --- /dev/null +++ b/_documentation/vybeclip_studio_mockup.html @@ -0,0 +1,105 @@ + + + + + + VybeClip | Studio Interface + + + + + + + +

+
+ + + + + + + VybeClip_Studio_v01 +
+ +
+ + + +
+
+ +
+ + + + + +
+
+
+
Canvas Stage
+
+
+ + +
+
+ Timeline +
+
+
Source_Clip_01.mp4
+
+
+
+
+
+
+ + + +
+ + + + diff --git a/src/App.tsx b/src/App.tsx index 2a80102b0..20520ae46 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import { UpdateToastWindow } from "./components/launch/UpdateToastWindow"; import { Toaster } from "./components/ui/sonner"; import { ShortcutsConfigDialog } from "./components/video-editor/ShortcutsConfigDialog"; import VideoEditor from "./components/video-editor/VideoEditor"; +import { VybeStudioPreview } from "./components/vybe/VybeStudioPreview"; import { useI18n } from "./contexts/I18nContext"; import { ShortcutsProvider } from "./contexts/ShortcutsContext"; import { loadAllCustomFonts } from "./lib/customFonts"; @@ -14,7 +15,6 @@ export default function App() { const [windowType, setWindowType] = useState(""); const { t } = useI18n(); const isMacOS = /mac/i.test(navigator.platform); - const appIconSrc = "/app-icons/recordly-128.png"; useEffect(() => { const params = new URLSearchParams(window.location.search); @@ -78,24 +78,6 @@ export default function App() { ); default: - return ( -
-
- {t("app.name", -
-

- {t("app.name", "VybeClip")} -

-

- {t("app.subtitle", "Screen recording and editing")} -

-
-
-
- ); + return ; } } diff --git a/src/components/brand/VybeClipLogo.tsx b/src/components/brand/VybeClipLogo.tsx new file mode 100644 index 000000000..ea7de3189 --- /dev/null +++ b/src/components/brand/VybeClipLogo.tsx @@ -0,0 +1,33 @@ +interface VybeClipLogoProps { + className?: string; + title?: string; +} + +export function VybeClipLogo({ className = "h-9 w-9", title }: VybeClipLogoProps) { + return ( + + + + + + + ); +} diff --git a/src/components/launch/LaunchWindow.module.css b/src/components/launch/LaunchWindow.module.css index 3638e7563..6fac762b6 100644 --- a/src/components/launch/LaunchWindow.module.css +++ b/src/components/launch/LaunchWindow.module.css @@ -72,19 +72,19 @@ } .ibActive { - color: #3d8bff; + color: var(--launch-accent); } .ibActive:hover { - color: #62a4ff; + color: #d59d80; } .ibRed { - color: #f43f5e; + color: #b6410f; } .ibRed:hover { - color: #ff5a75; + color: #d59d80; } .ibGreen { @@ -184,7 +184,7 @@ } .finalizingSpin { - color: #3d8bff; + color: var(--launch-accent); animation: finalizingSpin 0.9s linear infinite; } @@ -218,7 +218,7 @@ height: 46px; border-radius: 50%; border: none; - background: #f43f5e; + background: #b6410f; color: #fff; cursor: pointer; display: inline-flex; @@ -226,12 +226,12 @@ justify-content: center; transition: all 0.2s ease; flex-shrink: 0; - box-shadow: 0 0 0 0 rgba(244, 63, 94, 0.3); + box-shadow: 0 0 0 0 rgba(182, 65, 15, 0.3); } .recBtn:hover { - background: #ff5a75; - box-shadow: 0 0 0 6px rgba(244, 63, 94, 0.15); + background: #c0754d; + box-shadow: 0 0 0 6px rgba(182, 65, 15, 0.15); } .recBtn:disabled { @@ -240,7 +240,7 @@ } .recBtn:disabled:hover { - background: #f43f5e; + background: #b6410f; box-shadow: none; } diff --git a/src/components/launch/RecordingControls.tsx b/src/components/launch/RecordingControls.tsx index 4e24f943a..a68c1ead2 100644 --- a/src/components/launch/RecordingControls.tsx +++ b/src/components/launch/RecordingControls.tsx @@ -36,12 +36,12 @@ export const RecordingControls = ({
{paused ? t("recording.paused") : t("recording.rec")} @@ -50,7 +50,7 @@ export const RecordingControls = ({ {formatTime(elapsed)} diff --git a/src/components/launch/SourceSelector.module.css b/src/components/launch/SourceSelector.module.css index 79cf78532..0b56282c9 100644 --- a/src/components/launch/SourceSelector.module.css +++ b/src/components/launch/SourceSelector.module.css @@ -21,9 +21,9 @@ } .selected { - border: 2px solid #2563eb; - background: linear-gradient(120deg, rgba(91, 33, 182, 0.18) 0%, rgba(38, 38, 48, 0.98) 100%); - box-shadow: 0 0 0 2px #2563eb33; + border: 2px solid #b6410f; + background: linear-gradient(120deg, rgba(16, 76, 100, 0.24) 0%, rgba(38, 38, 48, 0.98) 100%); + box-shadow: 0 0 0 2px rgba(182, 65, 15, 0.2); } .icon { @@ -47,7 +47,7 @@ /* scrollbar */ .sourceGridScroll { scrollbar-width: thin; - scrollbar-color: rgba(37, 99, 235, 0.5) rgba(40, 40, 50, 0.6); + scrollbar-color: rgba(192, 117, 77, 0.5) rgba(40, 40, 50, 0.6); } .sourceGridScroll::-webkit-scrollbar { @@ -66,9 +66,9 @@ } .sourceGridScroll::-webkit-scrollbar-thumb:hover { - background: rgba(37, 99, 235, 0.6); + background: rgba(192, 117, 77, 0.6); } .sourceGridScroll::-webkit-scrollbar-thumb:active { - background: rgba(37, 99, 235, 0.8); + background: rgba(182, 65, 15, 0.8); } diff --git a/src/components/launch/launchTheme.css b/src/components/launch/launchTheme.css index 4adca96dd..20381cb05 100644 --- a/src/components/launch/launchTheme.css +++ b/src/components/launch/launchTheme.css @@ -4,13 +4,13 @@ --launch-panel: #f8fafc; --launch-border: rgba(0, 0, 0, 0.08); --launch-border-strong: rgba(0, 0, 0, 0.16); - --launch-text: #020617; /* Deepest Navy/Black */ - --launch-text-muted: #475569; /* Slate 600 */ - --launch-label: #64748b; /* Slate 500 - increased contrast */ + --launch-text: #0d1d25; + --launch-text-muted: #4b5f64; + --launch-label: #6b756f; --launch-hover: rgba(0, 0, 0, 0.045); - --launch-selected: rgba(37, 99, 235, 0.12); /* Blue 600 at 12% */ - --launch-accent: #2563eb; /* Blue 600 */ - --launch-accent-soft: #f1f5f9; /* Slate 100 */ + --launch-selected: rgba(16, 76, 100, 0.13); + --launch-accent: #b6410f; + --launch-accent-soft: #f6e3d8; --launch-popover-blur: 40px; --launch-popover-saturate: 200%; --launch-bar-bg: rgba(255, 255, 255, 0.98); @@ -23,18 +23,18 @@ .dark .launch-theme, .launch-theme.dark { /* Dark Mode values */ - --launch-surface: rgba(18, 18, 24, 0.97); - --launch-panel: rgba(18, 18, 24, 0.82); + --launch-surface: rgba(10, 17, 21, 0.97); + --launch-panel: rgba(13, 29, 37, 0.82); --launch-border: rgba(255, 255, 255, 0.07); --launch-border-strong: rgba(255, 255, 255, 0.12); - --launch-text: #f3f6ff; - --launch-text-muted: #aab3c7; - --launch-label: #8f99b1; + --launch-text: #f3e7de; + --launch-text-muted: #c6c6d0; + --launch-label: rgba(198, 198, 208, 0.62); --launch-hover: rgba(255, 255, 255, 0.1); - --launch-selected: rgba(92, 153, 255, 0.22); - --launch-accent: #3d8bff; - --launch-accent-soft: #dbeafe; - --launch-bar-bg: rgba(18, 18, 24, 0.97); + --launch-selected: rgba(16, 76, 100, 0.34); + --launch-accent: #d59d80; + --launch-accent-soft: #0d1d25; + --launch-bar-bg: rgba(10, 17, 21, 0.97); --launch-bar-border: rgba(255, 255, 255, 0.07); --launch-bar-shadow: 0 10px 30px rgba(0, 0, 0, 0.24), 0 2px 10px rgba(0, 0, 0, 0.12); } diff --git a/src/components/video-editor/videoPlayback/zoomRegionUtils.ts b/src/components/video-editor/videoPlayback/zoomRegionUtils.ts index 8e1cc6bf5..b167fc66b 100644 --- a/src/components/video-editor/videoPlayback/zoomRegionUtils.ts +++ b/src/components/video-editor/videoPlayback/zoomRegionUtils.ts @@ -203,7 +203,7 @@ function getConnectedRegionTransition(connectedPairs: ConnectedRegionPair[], tim for (const pair of connectedPairs) { const { currentRegion, nextRegion, transitionStart, transitionEnd } = pair; - if (timeMs < transitionStart || timeMs > transitionEnd) { + if (timeMs <= transitionStart || timeMs >= transitionEnd) { continue; } @@ -250,6 +250,11 @@ export function findDominantRegion( const connectedPairs = options.connectZooms ? getConnectedRegionPairs(regions) : []; if (options.connectZooms) { + const connectedTransition = getConnectedRegionTransition(connectedPairs, timeMs); + if (connectedTransition) { + return connectedTransition; + } + const connectedHold = getConnectedRegionHold(timeMs, connectedPairs); if (connectedHold) { return { ...connectedHold, transition: null }; diff --git a/src/components/vybe/VybeStudioPreview.tsx b/src/components/vybe/VybeStudioPreview.tsx new file mode 100644 index 000000000..6346638da --- /dev/null +++ b/src/components/vybe/VybeStudioPreview.tsx @@ -0,0 +1,233 @@ +import { + ArrowSquareOutIcon, + CameraIcon, + CaretDownIcon, + ExportIcon, + FilmSlateIcon, + FolderOpenIcon, + MicrophoneIcon, + MonitorIcon, + PlayIcon, + PlusIcon, + RecordIcon, + SlidersHorizontalIcon, + SparkleIcon, + UploadSimpleIcon, + WaveformIcon, +} from "@phosphor-icons/react"; +import { VybeClipLogo } from "../brand/VybeClipLogo"; + +const workspaceItems = [ + { label: "Current Recording", meta: "Ready to capture", active: true }, + { label: "Project Assets", meta: "Clips, overlays, audio" }, + { label: "Brand Kit", meta: "VybeClip presets" }, +]; + +const inspectorRows = [ + ["Format", "16:9 Desktop"], + ["Canvas Style", "Clean Demo"], + ["Pointer", "Soft Highlight"], + ["Captions", "Smart Draft"], +]; + +export function VybeStudioPreview() { + return ( +
+
+
+ +
+

+ VybeClip Studio +

+

+ Capture, polish, publish +

+
+
+ +
+ + + +
+
+ +
+ + +
+
+
+
+
+
+
+ +
+
+

Canvas Stage

+

+ Your screen recording preview will live here. +

+
+
+
+
+
+ +
+
+
+ + Timeline +
+
+ 00:00 + + Draft clip +
+
+
+
+
+ + Video +
+
+
+
+
+
+
+ + Audio +
+
+
+
+
+
+
+
+ + +
+
+ ); +} diff --git a/src/index.css b/src/index.css index a5ae2368b..3af85c588 100644 --- a/src/index.css +++ b/src/index.css @@ -30,27 +30,27 @@ :root { --app-font-sans: "SF Pro Display", "SF Pro Text", Helvetica, sans-serif; - --brand-accent: #2563eb; - --brand-accent-rgb: 37, 99, 235; + --brand-accent: #b6410f; + --brand-accent-rgb: 182, 65, 15; --background: 0 0% 100%; --foreground: 20 14.3% 4.1%; --card: 0 0% 100%; --card-foreground: 20 14.3% 4.1%; --popover: 0 0% 100%; --popover-foreground: 20 14.3% 4.1%; - --primary: 221 83% 53%; + --primary: 19 85% 39%; --primary-foreground: 210 40% 98%; --secondary: 60 4.8% 95.9%; --secondary-foreground: 24 9.8% 10%; --muted: 60 4.8% 95.9%; --muted-foreground: 25 5.3% 44.7%; - --accent: 214 100% 97%; - --accent-foreground: 221 83% 40%; + --accent: 21 51% 91%; + --accent-foreground: 19 85% 31%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 60 9.1% 97.8%; --border: 20 5.9% 90%; --input: 20 5.9% 90%; - --ring: 221 83% 53%; + --ring: 19 85% 39%; --chart-1: 12 76% 61%; --chart-2: 173 58% 39%; --chart-3: 197 37% 24%; @@ -59,11 +59,11 @@ --radius: 0.5rem; /* Editor surface colors — light mode */ - --editor-bg: 0 0% 100%; - --editor-header: 0 0% 97%; - --editor-panel: 0 0% 98%; - --editor-surface: 0 0% 97%; - --editor-surface-alt: 0 0% 95%; + --editor-bg: 32 28% 97%; + --editor-header: 21 39% 94%; + --editor-panel: 21 34% 96%; + --editor-surface: 21 28% 94%; + --editor-surface-alt: 21 22% 91%; --editor-dialog: 0 0% 100%; --editor-dialog-alt: 0 0% 98%; --editor-timeline: 220 13% 91%; @@ -72,53 +72,53 @@ /* Slider track colors — light mode */ --slider-track: 0 0% 0% / 0.12; - --slider-thumb: 0 0% 10%; + --slider-thumb: 19 85% 39%; --slider-thumb-shadow: 0 0% 0% / 0.22; --slider-glow: 0 0% 0% / 0.35; } .dark { - --background: 20 14.3% 4.1%; - --foreground: 60 9.1% 97.8%; - --card: 20 14.3% 4.1%; - --card-foreground: 60 9.1% 97.8%; - --popover: 20 14.3% 4.1%; - --popover-foreground: 60 9.1% 97.8%; - --primary: 221 83% 53%; + --background: 200 33% 3%; + --foreground: 240 10% 80%; + --card: 202 35% 6%; + --card-foreground: 240 10% 80%; + --popover: 202 35% 6%; + --popover-foreground: 240 10% 80%; + --primary: 19 85% 39%; --primary-foreground: 210 40% 98%; - --secondary: 12 6.5% 15.1%; - --secondary-foreground: 60 9.1% 97.8%; - --muted: 12 6.5% 15.1%; - --muted-foreground: 24 5.4% 63.9%; - --accent: 217 33% 17%; - --accent-foreground: 210 40% 98%; + --secondary: 202 48% 10%; + --secondary-foreground: 240 10% 80%; + --muted: 202 35% 12%; + --muted-foreground: 240 7% 62%; + --accent: 197 72% 23%; + --accent-foreground: 21 51% 88%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 60 9.1% 97.8%; - --border: 12 6.5% 15.1%; - --input: 12 6.5% 15.1%; - --ring: 221 83% 53%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; + --border: 202 35% 16%; + --input: 202 35% 16%; + --ring: 19 85% 39%; + --chart-1: 19 85% 39%; + --chart-2: 197 72% 23%; + --chart-3: 21 51% 67%; + --chart-4: 21 48% 53%; + --chart-5: 240 10% 80%; /* Editor surface colors — dark mode */ - --editor-bg: 240 6% 7%; - --editor-header: 240 5% 8.5%; - --editor-panel: 240 5% 9%; - --editor-surface: 240 4% 10%; - --editor-surface-alt: 240 5% 11%; - --editor-dialog: 240 10% 3%; - --editor-dialog-alt: 237 9% 5%; - --editor-timeline: 240 6% 7%; - --editor-row: 240 4% 10%; - --editor-subrow: 240 7% 15%; + --editor-bg: 200 33% 3%; + --editor-header: 202 35% 6%; + --editor-panel: 202 35% 6%; + --editor-surface: 202 48% 10%; + --editor-surface-alt: 197 55% 13%; + --editor-dialog: 200 33% 3%; + --editor-dialog-alt: 202 35% 6%; + --editor-timeline: 202 35% 6%; + --editor-row: 202 48% 10%; + --editor-subrow: 197 45% 16%; /* Slider track colors — dark mode */ --slider-track: 0 0% 100% / 0.12; - --slider-thumb: 0 0% 100%; - --slider-thumb-shadow: 0 0% 100% / 0.32; - --slider-glow: 0 0% 100% / 0.5; + --slider-thumb: 21 51% 67%; + --slider-thumb-shadow: 21 51% 67% / 0.32; + --slider-glow: 19 85% 39% / 0.5; } } @@ -171,11 +171,11 @@ border-radius: inherit; background: linear-gradient( 90deg, - rgba(37, 99, 235, 0) 0%, - rgba(37, 99, 235, 0.35) 18%, - rgba(96, 165, 250, 0.92) 52%, - rgba(37, 99, 235, 0.3) 82%, - rgba(37, 99, 235, 0) 100% + rgba(182, 65, 15, 0) 0%, + rgba(192, 117, 77, 0.28) 18%, + rgba(213, 157, 128, 0.92) 52%, + rgba(182, 65, 15, 0.3) 82%, + rgba(182, 65, 15, 0) 100% ); animation: indeterminate-progress 1.15s cubic-bezier(0.4, 0, 0.2, 1) infinite; } @@ -269,5 +269,3 @@ } } - - From 106a1ff97bf2628c39393f16d1167ebd5da302cf Mon Sep 17 00:00:00 2001 From: Side Quest Studios Date: Wed, 1 Jul 2026 17:51:08 -0400 Subject: [PATCH 04/32] Make VybeClip Studio the main app window --- electron/electron-env.d.ts | 1 + electron/main.ts | 105 ++++---- electron/preload.ts | 3 + electron/windows.ts | 71 +++++ src/App.tsx | 16 +- src/components/vybe/VybeStudioPreview.tsx | 304 ++++++++++++++++++---- src/components/vybe/studioActions.test.ts | 68 +++++ src/components/vybe/studioActions.ts | 53 ++++ src/index.css | 13 +- 9 files changed, 514 insertions(+), 120 deletions(-) create mode 100644 src/components/vybe/studioActions.test.ts create mode 100644 src/components/vybe/studioActions.ts diff --git a/electron/electron-env.d.ts b/electron/electron-env.d.ts index 6dc7d3966..f776bf962 100644 --- a/electron/electron-env.d.ts +++ b/electron/electron-env.d.ts @@ -221,6 +221,7 @@ interface Window { getSources: (opts: Electron.SourcesOptions) => Promise; switchToEditor: () => Promise; openSourceSelector: () => Promise; + showRecordingControls: () => Promise<{ success: boolean }>; selectSource: (source: ProcessedDesktopSource) => Promise; showSourceHighlight: (source: ProcessedDesktopSource) => Promise<{ success: boolean }>; getSelectedSource: () => Promise; diff --git a/electron/main.ts b/electron/main.ts index 54ab928f0..de9ce6ec7 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -45,6 +45,7 @@ import { createEditorWindow, createHudOverlayWindow, createSourceSelectorWindow, + createStudioWindow, getHudOverlayWindow, getUpdateToastWindow, hideUpdateToastWindow, @@ -134,6 +135,7 @@ process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL // Window references let mainWindow: BrowserWindow | null = null; +let studioWindow: BrowserWindow | null = null; let sourceSelectorWindow: BrowserWindow | null = null; let tray: Tray | null = null; let trayContextMenu: Menu | null = null; @@ -142,6 +144,7 @@ let editorHasUnsavedChanges = false; let isForceClosing = false; let isCreatingMainWindow = false; let isCreatingEditorWindow = false; +let isAppQuitting = false; let activeUpdateNotification: Notification | null = null; let activeUpdateNotificationKey: string | null = null; const shouldEnforceSingleInstanceLock = !IS_DEV; @@ -170,7 +173,7 @@ function restoreWindowSafely(window: BrowserWindow | null) { return; } - if (!isEditorWindow(window) && process.platform === "win32") { + if (window === getHudOverlayWindow() && process.platform === "win32") { showHudOverlayFromTray(); return; } @@ -241,6 +244,16 @@ function showHudOverlayFromTray() { return true; } +function showOrCreateRecordingControls() { + const existingHud = getHudOverlayWindow(); + if (existingHud) { + showHudOverlayFromTray(); + return existingHud; + } + + return createHudOverlayWindow(); +} + ipcMain.on("set-has-unsaved-changes", (_event, hasChanges: boolean) => { editorHasUnsavedChanges = hasChanges; }); @@ -259,23 +272,21 @@ function createWindow() { return; } - if (mainWindow && !mainWindow.isDestroyed()) { - restoreWindowSafely(mainWindow); - return; - } - - const existingHudWindow = getHudOverlayWindow(); - if (existingHudWindow) { - mainWindow = existingHudWindow; - restoreWindowSafely(existingHudWindow); + if (studioWindow && !studioWindow.isDestroyed()) { + mainWindow = studioWindow; + restoreWindowSafely(studioWindow); return; } isCreatingMainWindow = true; - const createdHudWindow = createHudOverlayWindow(); - mainWindow = createdHudWindow; - createdHudWindow.once("closed", () => { - if (mainWindow === createdHudWindow) { + const createdStudioWindow = createStudioWindow(); + studioWindow = createdStudioWindow; + mainWindow = createdStudioWindow; + createdStudioWindow.once("closed", () => { + if (studioWindow === createdStudioWindow) { + studioWindow = null; + } + if (mainWindow === createdStudioWindow) { mainWindow = null; } }); @@ -291,47 +302,11 @@ function focusOrCreateMainWindow() { } if (!mainWindow || mainWindow.isDestroyed()) { - const existingHud = getHudOverlayWindow(); - if (existingHud && !existingHud.isDestroyed()) { - mainWindow = existingHud; - } else { - createWindow(); - return; - } + createWindow(); + return; } if (mainWindow && !mainWindow.isDestroyed()) { - // On Linux/Wayland, focus() often doesn't take effect (compositor ignores it). Apps like Telegram - // work because they receive an XDG activation token via StatusNotifierItem.ProvideXdgActivationToken; - // Electron's tray doesn't handle that yet. Workaround: destroy and recreate the HUD so the new - // window gets focus (creation path works). Only for HUD, not editor. - if ( - process.platform === "linux" && - !mainWindow.isFocused() && - !isEditorWindow(mainWindow) - ) { - const win = mainWindow; - mainWindow = null; - win.once("closed", () => createWindow()); - win.destroy(); - return; - } - - // On Win32 with mouse passthrough enabled (Win11+), calling - // show/moveTop/focus on the transparent HUD overlay permanently corrupts - // setIgnoreMouseEvents forwarding, making it click-through. Only focus - // the editor window; the HUD is alwaysOnTop so it doesn't need explicit - // focus. On Win10 (passthrough disabled), the HUD is always interactive - // and can be safely shown/restored. - if ( - process.platform === "win32" && - !isEditorWindow(mainWindow) && - isHudOverlayMousePassthroughSupported() - ) { - showHudOverlayFromTray(); - return; - } - mainWindow.show(); if (mainWindow.isMinimized()) mainWindow.restore(); mainWindow.moveTop(); @@ -715,16 +690,15 @@ function updateTrayMenu(recording: boolean = false) { { label: "Show Controls", click: () => { - if (!showHudOverlayFromTray()) { - focusOrCreateMainWindow(); - } + showOrCreateRecordingControls(); }, }, { label: "Stop Recording", click: () => { - if (mainWindow && !mainWindow.isDestroyed()) { - mainWindow.webContents.send("stop-recording-from-tray"); + const hud = getHudOverlayWindow(); + if (hud && !hud.isDestroyed()) { + hud.webContents.send("stop-recording-from-tray"); } }, }, @@ -733,9 +707,7 @@ function updateTrayMenu(recording: boolean = false) { { label: "Open", click: () => { - if (!showHudOverlayFromTray()) { - focusOrCreateMainWindow(); - } + focusOrCreateMainWindow(); }, }, { @@ -798,6 +770,10 @@ function createEditorWindowWrapper() { const editorWindow = createEditorWindow(); mainWindow = editorWindow; editorHasUnsavedChanges = false; + const hudWindow = getHudOverlayWindow(); + if (hudWindow && !hudWindow.isDestroyed()) { + hudWindow.hide(); + } editorWindow.on("closed", () => { if (mainWindow === editorWindow) { @@ -806,6 +782,9 @@ function createEditorWindowWrapper() { isCreatingEditorWindow = false; isForceClosing = false; editorHasUnsavedChanges = false; + if (!isAppQuitting && !IS_SMOKE_EXPORT) { + createWindow(); + } }); editorWindow.on("close", (event) => { @@ -851,6 +830,7 @@ function createSourceSelectorWindowWrapper() { // On macOS, applications and their menu bar stay active until the user quits // explicitly with Cmd + Q. app.on("before-quit", () => { + isAppQuitting = true; killWindowsCaptureProcess(); showCursor(); cleanupNativeVideoExportSessions(); @@ -975,6 +955,11 @@ app.whenReady().then(async () => { registerExtensionIpcHandlers(); + ipcMain.handle("show-recording-controls", () => { + showOrCreateRecordingControls(); + return { success: true }; + }); + if (IS_SMOKE_EXPORT || process.env.RECORDLY_DEV_OPEN_RECORDING_INPUT) { await logSmokeExportGpuDiagnostics(); if (IS_SMOKE_EXPORT) { diff --git a/electron/preload.ts b/electron/preload.ts index 6f941e802..0912992c0 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -482,6 +482,9 @@ contextBridge.exposeInMainWorld("electronAPI", { openSourceSelector: () => { return ipcRenderer.invoke("open-source-selector"); }, + showRecordingControls: () => { + return ipcRenderer.invoke("show-recording-controls"); + }, selectSource: (source: ProcessedDesktopSource) => { return ipcRenderer.invoke("select-source", source); }, diff --git a/electron/windows.ts b/electron/windows.ts index 274557551..10a446843 100644 --- a/electron/windows.ts +++ b/electron/windows.ts @@ -823,6 +823,77 @@ function loadPackagedEditorWindow(win: BrowserWindow) { }); } +function loadStudioWindow(win: BrowserWindow) { + const query = { windowType: "studio" }; + if (VITE_DEV_SERVER_URL) { + void win.loadURL(`${VITE_DEV_SERVER_URL}?windowType=studio`); + return; + } + + const packagedRendererBaseUrl = getPackagedRendererBaseUrl(); + if (packagedRendererBaseUrl) { + void win.loadURL(`${packagedRendererBaseUrl}/?windowType=studio`).catch((error) => { + console.warn("[studio-window] packaged renderer URL failed, falling back to file", { + error: error instanceof Error ? error.message : String(error), + }); + if (!win.isDestroyed()) { + void win.loadFile(path.join(RENDERER_DIST, "index.html"), { query }); + } + }); + return; + } + + void win.loadFile(path.join(RENDERER_DIST, "index.html"), { query }); +} + +export function createStudioWindow(): BrowserWindow { + const isMac = process.platform === "darwin"; + const { workAreaSize } = getScreen().getPrimaryDisplay(); + const width = Math.min(1360, Math.max(960, Math.round(workAreaSize.width * 0.82))); + const height = Math.min(900, Math.max(680, Math.round(workAreaSize.height * 0.82))); + + const win = new BrowserWindow({ + width, + height, + minWidth: 900, + minHeight: 640, + ...(process.platform !== "darwin" && { + icon: WINDOW_ICON_PATH, + }), + ...(isMac && { + titleBarStyle: "hiddenInset", + trafficLightPosition: { x: 14, y: 18 }, + }), + autoHideMenuBar: !isMac, + resizable: true, + title: "VybeClip Studio", + show: false, + backgroundColor: "#05080A", + webPreferences: { + preload: path.join(electronWindowsDir, "preload.mjs"), + nodeIntegration: false, + contextIsolation: true, + webSecurity: false, + backgroundThrottling: false, + }, + }); + + win.once("ready-to-show", () => { + if (!win.isDestroyed()) { + win.show(); + } + }); + + win.webContents.on("did-finish-load", () => { + if (!win.isDestroyed() && !win.isVisible()) { + win.show(); + } + }); + + loadStudioWindow(win); + return win; +} + export function createEditorWindow(): BrowserWindow { const perfStart = Date.now(); console.log("[PERF:MAIN] createEditorWindow: STARTED"); diff --git a/src/App.tsx b/src/App.tsx index 20520ae46..24bafdbeb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -47,7 +47,7 @@ export default function App() { loadAllCustomFonts().catch((error) => { console.error("Failed to load custom fonts:", error); }); - }, []); + }, [isMacOS]); useEffect(() => { document.title = @@ -70,6 +70,13 @@ export default function App() { return ; case "update-toast": return ; + case "studio": + return ( + <> + + + + ); case "editor": return ( @@ -78,6 +85,11 @@ export default function App() { ); default: - return ; + return ( + <> + + + + ); } } diff --git a/src/components/vybe/VybeStudioPreview.tsx b/src/components/vybe/VybeStudioPreview.tsx index 6346638da..d5c64c593 100644 --- a/src/components/vybe/VybeStudioPreview.tsx +++ b/src/components/vybe/VybeStudioPreview.tsx @@ -2,12 +2,12 @@ import { ArrowSquareOutIcon, CameraIcon, CaretDownIcon, + CircleNotchIcon, ExportIcon, FilmSlateIcon, FolderOpenIcon, MicrophoneIcon, MonitorIcon, - PlayIcon, PlusIcon, RecordIcon, SlidersHorizontalIcon, @@ -15,13 +15,17 @@ import { UploadSimpleIcon, WaveformIcon, } from "@phosphor-icons/react"; +import { useCallback, useEffect, useState } from "react"; +import { toast } from "sonner"; import { VybeClipLogo } from "../brand/VybeClipLogo"; - -const workspaceItems = [ - { label: "Current Recording", meta: "Ready to capture", active: true }, - { label: "Project Assets", meta: "Clips, overlays, audio" }, - { label: "Brand Kit", meta: "VybeClip presets" }, -]; +import type { ProjectLibraryEntry } from "../video-editor/ProjectBrowserDialog"; +import { toFileUrl } from "../video-editor/projectPersistence"; +import { + importStudioVideo, + openRecentStudioProject, + openStudioProject, + startStudioRecording, +} from "./studioActions"; const inspectorRows = [ ["Format", "16:9 Desktop"], @@ -30,10 +34,103 @@ const inspectorRows = [ ["Captions", "Smart Draft"], ]; +function formatProjectDate(updatedAt: number) { + return new Intl.DateTimeFormat(undefined, { + month: "short", + day: "numeric", + year: + new Date(updatedAt).getFullYear() === new Date().getFullYear() ? undefined : "numeric", + }).format(updatedAt); +} + export function VybeStudioPreview() { + const isDesktop = Boolean(window.electronAPI); + const [projects, setProjects] = useState([]); + const [projectsLoading, setProjectsLoading] = useState(isDesktop); + const [pendingAction, setPendingAction] = useState(null); + + const refreshProjects = useCallback(async () => { + if (!window.electronAPI) return; + + setProjectsLoading(true); + try { + const result = await window.electronAPI.listProjectFiles(); + if (!result.success) { + throw new Error(result.error || "Unable to load projects"); + } + setProjects(result.entries); + } catch (error) { + console.error("Failed to load VybeClip projects:", error); + toast.error("Could not load your projects"); + } finally { + setProjectsLoading(false); + } + }, []); + + useEffect(() => { + void refreshProjects(); + }, [refreshProjects]); + + const runAction = useCallback( + async (actionName: string, action: () => Promise) => { + if (!window.electronAPI || pendingAction) return; + setPendingAction(actionName); + try { + await action(); + } catch (error) { + console.error(`VybeClip ${actionName} action failed:`, error); + toast.error( + error instanceof Error ? error.message : "The action could not be completed", + ); + } finally { + setPendingAction(null); + } + }, + [pendingAction], + ); + + const handleRecord = useCallback(() => { + void runAction("record", async () => { + await startStudioRecording(window.electronAPI); + }); + }, [runAction]); + + const handleImport = useCallback(() => { + void runAction("import", async () => { + await importStudioVideo(window.electronAPI); + }); + }, [runAction]); + + const handleOpenProject = useCallback(() => { + void runAction("open-project", async () => { + await openStudioProject(window.electronAPI); + }); + }, [runAction]); + + const handleOpenRecentProject = useCallback( + (projectPath: string) => { + void runAction("open-project", async () => { + await openRecentStudioProject(window.electronAPI, projectPath); + }); + }, + [runAction], + ); + + const handleOpenProjectsFolder = useCallback(() => { + void runAction("projects-folder", async () => { + const result = await window.electronAPI.openProjectsDirectory(); + if (!result.success) { + throw new Error(result.message || "Could not open the projects folder"); + } + }); + }, [runAction]); + + const recentProjects = projects.slice(0, 5); + const actionsDisabled = !isDesktop || pendingAction !== null; + return (
-
+
@@ -46,87 +143,164 @@ export function VybeStudioPreview() {
-
+
-
+ {permissionIssue && ( +
+
+ +
+

+ {permissionIssue === "screen" + ? "Screen Recording permission is required" + : "Accessibility permission is required for cursor tracking"} +

+

+ Enable VybeClip in macOS Privacy & Security, then reopen the app. +

+
+
+
+ + +
+
+ )}