diff --git a/.circleci/config.yml b/.circleci/config.yml index 974b6b54..f87363e2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: build: macos: - xcode: '13.0.0' + xcode: '13.4.1' steps: - checkout - run: yarn diff --git a/.gitignore b/.gitignore index d82b0f3a..4af8b308 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node_modules /app/dist /dist /dist-js +.DS_Store \ No newline at end of file diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz new file mode 100644 index 00000000..0b2fa099 Binary files /dev/null and b/.yarn/install-state.gz differ diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 00000000..d9df8550 --- /dev/null +++ b/.yarnrc @@ -0,0 +1,5 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +yarn-path ".yarn/releases/yarn-1.22.21.cjs" diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 00000000..3186f3f0 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/main/aperture.ts b/main/aperture.ts index 5fca024c..a5685190 100644 --- a/main/aperture.ts +++ b/main/aperture.ts @@ -1,23 +1,23 @@ -import {windowManager} from './windows/manager'; -import {setRecordingTray, setPausedTray, disableTray, resetTray} from './tray'; -import {setCropperShortcutAction} from './global-accelerators'; -import {settings} from './common/settings'; -import {track} from './common/analytics'; -import {plugins} from './plugins'; -import {getAudioDevices, getSelectedInputDeviceId} from './utils/devices'; -import {showError} from './utils/errors'; -import {RecordServiceContext, RecordServiceState} from './plugins/service-context'; -import {setCurrentRecording, updatePluginState, stopCurrentRecording} from './recording-history'; -import {Recording} from './video'; -import {ApertureOptions, StartRecordingOptions} from './common/types'; -import {InstalledPlugin} from './plugins/plugin'; -import {RecordService, RecordServiceHook} from './plugins/service'; -import {getCurrentDurationStart, getOverallDuration, setCurrentDurationStart, setOverallDuration} from './utils/track-duration'; +import { windowManager } from './windows/manager'; +import { setRecordingTray, setPausedTray, disableTray, resetTray } from './tray'; +import { setCropperShortcutAction } from './global-accelerators'; +import { settings } from './common/settings'; +import { track } from './common/analytics'; +import { plugins } from './plugins'; +import { getAudioDevices, getSelectedInputDeviceId } from './utils/devices'; +import { showError } from './utils/errors'; +import { RecordServiceContext, RecordServiceState } from './plugins/service-context'; +import { setCurrentRecording, updatePluginState, stopCurrentRecording } from './recording-history'; +import { Recording } from './video'; +import { ApertureOptions, StartRecordingOptions } from './common/types'; +import { InstalledPlugin } from './plugins/plugin'; +import { RecordService, RecordServiceHook } from './plugins/service'; +import { getCurrentDurationStart, getOverallDuration, setCurrentDurationStart, setOverallDuration } from './utils/track-duration'; const createAperture = require('aperture'); const aperture = createAperture(); -let recordingPlugins: Array<{plugin: InstalledPlugin; service: RecordService}> = []; +let recordingPlugins: Array<{ plugin: InstalledPlugin; service: RecordService }> = []; const serviceState = new Map(); let apertureOptions: ApertureOptions; let recordingName: string | undefined; @@ -30,7 +30,7 @@ const setRecordingName = (name: string) => { const serializeEditPluginState = () => { const result: Record | undefined>> = {}; - for (const {plugin, service} of recordingPlugins) { + for (const { plugin, service } of recordingPlugins) { if (!result[plugin.name]) { result[plugin.name] = {}; } @@ -41,7 +41,7 @@ const serializeEditPluginState = () => { return result; }; -const callPlugins = async (method: RecordServiceHook) => Promise.all(recordingPlugins.map(async ({plugin, service}) => { +const callPlugins = async (method: RecordServiceHook) => Promise.all(recordingPlugins.map(async ({ plugin, service }) => { if (service[method] && typeof service[method] === 'function') { try { await service[method]?.( @@ -53,7 +53,7 @@ const callPlugins = async (method: RecordServiceHook) => Promise.all(recordingPl }) ); } catch (error) { - showError(error as any, {title: `Something went wrong while using the plugin “${plugin.prettyName}”`, plugin}); + showError(error as any, { title: `Something went wrong while using the plugin “${plugin.prettyName}”`, plugin }); } } })); @@ -74,13 +74,14 @@ export const startRecording = async (options: StartRecordingOptions) => { } past = Date.now(); + console.log(`Starting recording ${(Date.now() - past) / 1000}s`); recordingName = undefined; windowManager.preferences?.close(); windowManager.cropper?.disable(); disableTray(); - const {cropperBounds, screenBounds, displayId} = options; + const { cropperBounds, screenBounds, displayId } = options; cropperBounds.y = screenBounds.height - (cropperBounds.y + cropperBounds.height); @@ -98,14 +99,20 @@ export const startRecording = async (options: StartRecordingOptions) => { highlightClicks, screenId: displayId }; + console.log(`before recordaudio ${(Date.now() - past) / 1000}s`); if (recordAudio) { // In case for some reason the default audio device is not set // use the first available device for recording + console.log(`getting audio ${(Date.now() - past) / 1000}s`); const audioInputDeviceId = getSelectedInputDeviceId(); + console.log(`getSelectedInputDeviceId ${(Date.now() - past) / 1000}s`); + if (audioInputDeviceId) { apertureOptions.audioDeviceId = audioInputDeviceId; } else { + console.log(`getting defaultaudio ${(Date.now() - past) / 1000}s`); + const [defaultAudioDevice] = await getAudioDevices(); apertureOptions.audioDeviceId = defaultAudioDevice?.id; } @@ -125,20 +132,25 @@ export const startRecording = async (options: StartRecordingOptions) => { const validServices = plugin.config.validServices; return plugin.recordServicesWithStatus // Make sure service is valid and enabled - .filter(({title, isEnabled}) => isEnabled && validServices.includes(title)) - .map(service => ({plugin, service})); + .filter(({ title, isEnabled }) => isEnabled && validServices.includes(title)) + .map(service => ({ plugin, service })); } ); - for (const {service, plugin} of recordingPlugins) { - serviceState.set(service.title, {persistedState: {}}); + for (const { service, plugin } of recordingPlugins) { + serviceState.set(service.title, { persistedState: {} }); track(`plugins/used/record/${plugin.name}`); } + console.log(`callplugins b4 ${(Date.now() - past) / 1000}s`); await callPlugins('willStartRecording'); + console.log(`callplugins after ${(Date.now() - past) / 1000}s`); + try { const filePath = await aperture.startRecording(apertureOptions); + console.log(`aperture startrecording ${(Date.now() - past) / 1000}s`); + setOverallDuration(0); setCurrentDurationStart(Date.now()); @@ -150,7 +162,7 @@ export const startRecording = async (options: StartRecordingOptions) => { }); } catch (error) { track('recording/stopped/error'); - showError(error as any, {title: 'Recording error', plugin: undefined}); + showError(error as any, { title: 'Recording error', plugin: undefined }); past = undefined; cleanup(); return; @@ -174,7 +186,7 @@ export const startRecording = async (options: StartRecordingOptions) => { // Make sure it doesn't catch the error of ending the recording if (past) { track('recording/stopped/error'); - showError(error, {title: 'Recording error', plugin: undefined}); + showError(error, { title: 'Recording error', plugin: undefined }); past = undefined; cleanup(); } @@ -201,7 +213,7 @@ export const stopRecording = async () => { setCurrentDurationStart(0); } catch (error) { track('recording/stopped/error'); - showError(error as any, {title: 'Recording error', plugin: undefined}); + showError(error as any, { title: 'Recording error', plugin: undefined }); cleanup(); return; } @@ -237,7 +249,7 @@ export const stopRecordingWithNoEdit = async () => { setCurrentDurationStart(0); } catch (error) { track('recording/quit/error'); - showError(error as any, {title: 'Recording error', plugin: undefined}); + showError(error as any, { title: 'Recording error', plugin: undefined }); cleanup(); return; } @@ -266,7 +278,7 @@ export const pauseRecording = async () => { console.log(`Paused recording after ${(Date.now() - past) / 1000}s`); } catch (error) { track('recording/paused/error'); - showError(error as any, {title: 'Recording error', plugin: undefined}); + showError(error as any, { title: 'Recording error', plugin: undefined }); cleanup(); } }; @@ -286,7 +298,7 @@ export const resumeRecording = async () => { console.log(`Resume recording after ${(Date.now() - past) / 1000}s`); } catch (error) { track('recording/resumed/error'); - showError(error as any, {title: 'Recording error', plugin: undefined}); + showError(error as any, { title: 'Recording error', plugin: undefined }); cleanup(); } }; diff --git a/main/global-accelerators.ts b/main/global-accelerators.ts index d7970beb..ec57f328 100644 --- a/main/global-accelerators.ts +++ b/main/global-accelerators.ts @@ -1,11 +1,16 @@ -import {globalShortcut} from 'electron'; -import {ipcMain as ipc} from 'electron-better-ipc'; -import {settings} from './common/settings'; -import {windowManager} from './windows/manager'; +import { globalShortcut } from 'electron'; +import { ipcMain as ipc } from 'electron-better-ipc'; +import { settings } from './common/settings'; +import { windowManager } from './windows/manager'; const openCropper = () => { - if (!windowManager.cropper?.isOpen()) { + let cropperwindow = windowManager.cropper?.isOpen() + if (!cropperwindow) { windowManager.cropper?.open(); + } else { + if (cropperwindow.isVisible()) + cropperwindow?.hide() + else cropperwindow?.show() } }; @@ -31,6 +36,7 @@ export const setCropperShortcutAction = (action = openCropper) => { const registerShortcut = (shortcut: string, action: () => void) => { try { globalShortcut.register(shortcut, action); + console.log('Registered shortcut successfully', shortcut, action); } catch (error) { console.error('Error registering shortcut', shortcut, action, error); } @@ -50,31 +56,36 @@ const registerFromStore = () => { }; export const initializeGlobalAccelerators = () => { - ipc.answerRenderer('update-shortcut', ({setting, shortcut}) => { + ipc.answerRenderer('update-shortcut', ({ setting, shortcut }) => { const oldShortcut = settings.get(`shortcuts.${setting}`); try { if (oldShortcut && oldShortcut !== shortcut && globalShortcut.isRegistered(oldShortcut)) { + console.log('Unregistering old shortcut', oldShortcut); globalShortcut.unregister(oldShortcut); } } catch (error) { console.error('Error unregistering old shortcutAccelerator', error); } finally { if (shortcut && shortcut !== oldShortcut) { + console.log('Registering new shortcut', shortcut); settings.set(`shortcuts.${setting}`, shortcut); const handler = handlers.get(setting); - + console.log(handler) if (settings.get('enableShortcuts') && handler) { + console.log('Registering new shortcut2', shortcut); registerShortcut(shortcut, handler); } } else if (!shortcut) { // @ts-expect-error settings.delete(`shortcuts.${setting}`); + console.log('No shortcut, unregistering shortcut', oldShortcut); } } }); - ipc.answerRenderer('toggle-shortcuts', ({enabled}) => { + ipc.answerRenderer('toggle-shortcuts', ({ enabled }) => { + console.log('Toggling shortcuts', enabled); if (enabled) { registerFromStore(); } else { diff --git a/main/menus/common.ts b/main/menus/common.ts index 495dd126..8924295f 100644 --- a/main/menus/common.ts +++ b/main/menus/common.ts @@ -1,24 +1,26 @@ import delay from 'delay'; -import {app, dialog} from 'electron'; -import {openNewGitHubIssue} from 'electron-util'; +import { app, dialog } from 'electron'; +import { openNewGitHubIssue } from 'electron-util'; import macosRelease from '../utils/macos-release'; -import {supportedVideoExtensions} from '../common/constants'; -import {getCurrentMenuItem, MenuItemId} from './utils'; -import {openFiles} from '../utils/open-files'; -import {windowManager} from '../windows/manager'; +import { supportedVideoExtensions } from '../common/constants'; +import { getCurrentMenuItem, MenuItemId } from './utils'; +import { openFiles } from '../utils/open-files'; +import { windowManager } from '../windows/manager'; export const getPreferencesMenuItem = () => ({ id: MenuItemId.preferences, label: 'Preferences…', accelerator: 'Command+,', - click: () => windowManager.preferences?.open() + click: () => + windowManager.preferences?.open() + }); export const getAboutMenuItem = () => ({ id: MenuItemId.about, label: `About ${app.name}`, click: () => { - windowManager.cropper?.close(); + // windowManager.cropper?.close(); app.focus(); app.showAboutPanel(); } @@ -34,8 +36,8 @@ export const getOpenFileMenuItem = () => ({ await delay(200); app.focus(); - const {canceled, filePaths} = await dialog.showOpenDialog({ - filters: [{name: 'Videos', extensions: supportedVideoExtensions}], + const { canceled, filePaths } = await dialog.showOpenDialog({ + filters: [{ name: 'Videos', extensions: supportedVideoExtensions }], properties: ['openFile', 'multiSelections'] }); diff --git a/main/tray.ts b/main/tray.ts index 535df1d7..5f98c75d 100644 --- a/main/tray.ts +++ b/main/tray.ts @@ -1,28 +1,31 @@ 'use strict'; -import {Tray} from 'electron'; -import {KeyboardEvent} from 'electron/main'; +import { Tray } from 'electron'; +import { KeyboardEvent } from 'electron/main'; import path from 'path'; -import {getCogMenu} from './menus/cog'; -import {getRecordMenu} from './menus/record'; -import {track} from './common/analytics'; -import {openFiles} from './utils/open-files'; -import {windowManager} from './windows/manager'; -import {pauseRecording, resumeRecording, stopRecording} from './aperture'; +import { getCogMenu } from './menus/cog'; +import { getRecordMenu } from './menus/record'; +import { track } from './common/analytics'; +import { openFiles } from './utils/open-files'; +import { windowManager } from './windows/manager'; +import { pauseRecording, resumeRecording, stopRecording } from './aperture'; let tray: Tray; let trayAnimation: NodeJS.Timeout | undefined; +let cogMenu = getCogMenu() const openContextMenu = async () => { - tray.popUpContextMenu(await getCogMenu()); + tray.popUpContextMenu(await cogMenu); }; +let recordMenu = getRecordMenu(false) const openRecordingContextMenu = async () => { - tray.popUpContextMenu(await getRecordMenu(false)); + tray.popUpContextMenu(await recordMenu); }; +let pausedMenu = getRecordMenu(true) const openPausedContextMenu = async () => { - tray.popUpContextMenu(await getRecordMenu(true)); + tray.popUpContextMenu(await pausedMenu); }; const openCropperWindow = () => windowManager.cropper?.open(); @@ -58,13 +61,13 @@ export const resetTray = () => { }; export const setRecordingTray = () => { - animateIcon(); tray.removeAllListeners('right-click'); // TODO: figure out why this is marked as missing. It's defined properly in the electron.d.ts file tray.once('click', onRecordingTrayClick); tray.on('right-click', openRecordingContextMenu); + animateIcon(); }; export const setPausedTray = () => { @@ -89,7 +92,7 @@ const onRecordingTrayClick = (event: KeyboardEvent) => { }; const animateIcon = async () => new Promise(resolve => { - const interval = 20; + const interval = 50; let i = 0; const next = () => { diff --git a/main/utils/devices.ts b/main/utils/devices.ts index 667ced43..f74c19d8 100644 --- a/main/utils/devices.ts +++ b/main/utils/devices.ts @@ -1,11 +1,11 @@ -import {hasMicrophoneAccess} from '../common/system-permissions'; +import { hasMicrophoneAccess } from '../common/system-permissions'; import * as audioDevices from 'macos-audio-devices'; -import {settings} from '../common/settings'; -import {defaultInputDeviceId} from '../common/constants'; +import { settings } from '../common/settings'; +import { defaultInputDeviceId } from '../common/constants'; import Sentry from './sentry'; const aperture = require('aperture'); -const {showError} = require('./errors'); +const { showError } = require('./errors'); export const getAudioDevices = async () => { if (!hasMicrophoneAccess()) { @@ -29,7 +29,7 @@ export const getAudioDevices = async () => { } return 0; - }).map(device => ({id: device.uid, name: device.name})); + }).map(device => ({ id: device.uid, name: device.name })); } catch (error) { try { const devices = await aperture.audioDevices(); @@ -47,10 +47,10 @@ export const getAudioDevices = async () => { } } }; - +let defaultDevice = audioDevices.getDefaultInputDevice.sync(); export const getDefaultInputDevice = () => { try { - const device = audioDevices.getDefaultInputDevice.sync(); + const device = defaultDevice || audioDevices.getDefaultInputDevice.sync(); return { id: device.uid, name: device.name @@ -62,10 +62,13 @@ export const getDefaultInputDevice = () => { }; export const getSelectedInputDeviceId = () => { + let start = Date.now() const audioInputDeviceId = settings.get('audioInputDeviceId', defaultInputDeviceId); - + console.log('getSelectedInputDeviceId', Date.now() - start) if (audioInputDeviceId === defaultInputDeviceId) { + console.log('getting default audio device', Date.now() - start) const device = getDefaultInputDevice(); + console.log('got default audio device', Date.now() - start) return device?.id; } diff --git a/main/windows/cropper.ts b/main/windows/cropper.ts index 895293a8..a27ab281 100644 --- a/main/windows/cropper.ts +++ b/main/windows/cropper.ts @@ -1,24 +1,32 @@ -import {windowManager} from './manager'; -import {BrowserWindow, systemPreferences, dialog, screen, Display, app} from 'electron'; +import { windowManager } from './manager'; +import { BrowserWindow, systemPreferences, dialog, screen, Display, app } from 'electron'; import delay from 'delay'; -import {settings} from '../common/settings'; -import {hasMicrophoneAccess, ensureMicrophonePermissions, openSystemPreferences, ensureScreenCapturePermissions} from '../common/system-permissions'; -import {loadRoute} from '../utils/routes'; -import {MacWindow} from '../utils/windows'; +import { settings } from '../common/settings'; +import { hasMicrophoneAccess, ensureMicrophonePermissions, openSystemPreferences, ensureScreenCapturePermissions } from '../common/system-permissions'; +import { loadRoute } from '../utils/routes'; +import { MacWindow } from '../utils/windows'; const croppers = new Map(); let notificationId: number | undefined; let isOpen = false; const closeAllCroppers = () => { + console.log("closeAllCroppers") screen.removeAllListeners('display-removed'); screen.removeAllListeners('display-added'); - + let i = 0 for (const [id, cropper] of croppers) { - cropper.destroy(); - croppers.delete(id); + if (cropper.isDestroyed()) { + croppers.delete(id); + } else if (!i) { + cropper.hide() + } else { + + cropper.destroy(); + croppers.delete(id); + } } isOpen = false; @@ -30,10 +38,20 @@ const closeAllCroppers = () => { }; const openCropper = (display: Display, activeDisplayId?: number) => { - const {id, bounds} = display; - const {x, y, width, height} = bounds; - - const cropper = new BrowserWindow({ + const { id, bounds } = display; + const { x, y, width, height } = bounds; + let availableCroppers = [] + for (const [id, cropper] of croppers) { + console.log("cropper exists with id: " + id) + if (cropper.isDestroyed()) { + croppers.delete(id); + } else { + availableCroppers.push(cropper) + } + } + if (!availableCroppers[0]) { console.log("no cropper available???") } + // console.log(availableCroppers) + const cropper = availableCroppers[0] || new BrowserWindow({ x, y, width, @@ -44,15 +62,29 @@ const openCropper = (display: Display, activeDisplayId?: number) => { movable: false, frame: false, transparent: true, - show: false, + show: true, webPreferences: { nodeIntegration: true, enableRemoteModule: true, contextIsolation: false } }); - - loadRoute(cropper, 'cropper'); + cropper.on('close', () => console.log("cropper closed? idk why")) + if (!availableCroppers[0]) + loadRoute(cropper, 'cropper'); + else { + availableCroppers[0].setBounds({ x, y, width, height }) + const isActive = activeDisplayId === id; + const displayInfo = { + isActive, + id, + x, + y, + width, + height + }; + cropper.webContents.send('display', displayInfo); + } cropper.setAlwaysOnTop(true, 'screen-saver', 1); @@ -85,7 +117,7 @@ const openCropper = (display: Display, activeDisplayId?: number) => { }; const openCropperWindow = async () => { - closeAllCroppers(); + // closeAllCroppers(); if (windowManager.editor?.areAnyBlocking()) { return; } @@ -98,7 +130,7 @@ const openCropperWindow = async () => { if (recordAudio && !hasMicrophoneAccess()) { const granted = await ensureMicrophonePermissions(async () => { - const {response} = await dialog.showMessageBox({ + const { response } = await dialog.showMessageBox({ type: 'warning', buttons: ['Open System Preferences', 'Continue'], defaultId: 1, @@ -142,11 +174,11 @@ const openCropperWindow = async () => { // Electron typing issue, this should be marked as returning a number notificationId = (systemPreferences as any).subscribeWorkspaceNotification('NSWorkspaceActiveSpaceDidChangeNotification', () => { - closeAllCroppers(); + // closeAllCroppers(); }); screen.on('display-removed', (_, oldDisplay) => { - const {id} = oldDisplay; + const { id } = oldDisplay; const cropper = croppers.get(id); if (!cropper) { @@ -182,10 +214,10 @@ const selectApp = async (window: MacWindow, activateWindow: (ownerName: string) await activateWindow(window.ownerName); - const {x, y, width, height, ownerName} = window; + const { x, y, width, height, ownerName } = window; - const display = screen.getDisplayMatching({x, y, width, height}); - const {id, bounds: {x: screenX, y: screenY}} = display; + const display = screen.getDisplayMatching({ x, y, width, height }); + const { id, bounds: { x: screenX, y: screenY } } = display; // For some reason this happened a bit too early without the timeout await delay(300); @@ -225,7 +257,17 @@ const setRecordingCroppers = () => { } }; -const isCropperOpen = () => isOpen; +const isCropperOpen = () => { + let focusedWindow = BrowserWindow.getFocusedWindow(); + if (focusedWindow?.isVisible()) { + return focusedWindow + } else { + if (isOpen) return BrowserWindow.getAllWindows().find(window => + window.webContents.getURL().includes("cropper")) || false; + else return false + } + +}; app.on('before-quit', closeAllCroppers); diff --git a/main/windows/editor.ts b/main/windows/editor.ts index 77ad4238..54d64820 100644 --- a/main/windows/editor.ts +++ b/main/windows/editor.ts @@ -1,12 +1,12 @@ -import {EditorWindowState} from '../common/types'; -import type {Video} from '../video'; +import { EditorWindowState } from '../common/types'; +import type { Video } from '../video'; import KapWindow from './kap-window'; -import {MenuItemId} from '../menus/utils'; -import {BrowserWindow, dialog} from 'electron'; -import {is} from 'electron-util'; +import { MenuItemId } from '../menus/utils'; +import { BrowserWindow, dialog } from 'electron'; +import { is } from 'electron-util'; import fs from 'fs'; -import {saveSnapshot} from '../utils/image-preview'; -import {windowManager} from './manager'; +import { saveSnapshot } from '../utils/image-preview'; +import { windowManager } from './manager'; const pify = require('pify'); @@ -20,6 +20,7 @@ const editors = new Map(); const editorsWithNotSavedDialogs = new Map(); const open = async (video: Video) => { + windowManager.cropper?.close(); if (editors.has(video.filePath)) { editors.get(video.filePath).show(); return; @@ -124,7 +125,7 @@ const open = async (video: Video) => { }; const saveOriginal = async (video: Video) => { - const {filePath} = await dialog.showSaveDialog(BrowserWindow.getFocusedWindow()!, { + const { filePath } = await dialog.showSaveDialog(BrowserWindow.getFocusedWindow()!, { defaultPath: `${video.title}.mp4` }); diff --git a/main/windows/manager.ts b/main/windows/manager.ts index cfabcf7d..3e12dbd1 100644 --- a/main/windows/manager.ts +++ b/main/windows/manager.ts @@ -1,8 +1,8 @@ -import type {BrowserWindow} from 'electron'; -import {MacWindow} from '../utils/windows'; -import type {Video} from '../video'; -import type {DialogOptions} from './dialog'; -import type {PreferencesWindowOptions} from './preferences'; +import type { BrowserWindow } from 'electron'; +import { MacWindow } from '../utils/windows'; +import type { Video } from '../video'; +import type { DialogOptions } from './dialog'; +import type { PreferencesWindowOptions } from './preferences'; export interface EditorManager { open: (video: Video) => Promise; @@ -14,7 +14,7 @@ export interface CropperManager { close: () => void; disable: () => void; setRecording: () => void; - isOpen: () => boolean; + isOpen: () => BrowserWindow | false; selectApp: (window: MacWindow, activateWindow: (ownerName: string) => Promise) => void; } diff --git a/main/windows/preferences.ts b/main/windows/preferences.ts index b6dd366d..b7b91b44 100644 --- a/main/windows/preferences.ts +++ b/main/windows/preferences.ts @@ -1,11 +1,11 @@ -import {BrowserWindow} from 'electron'; -import {promisify} from 'util'; +import { BrowserWindow } from 'electron'; +import { promisify } from 'util'; import pEvent from 'p-event'; -import {ipcMain as ipc} from 'electron-better-ipc'; -import {loadRoute} from '../utils/routes'; -import {track} from '../common/analytics'; -import {windowManager} from './manager'; +import { ipcMain as ipc } from 'electron-better-ipc'; +import { loadRoute } from '../utils/routes'; +import { track } from '../common/analytics'; +import { windowManager } from './manager'; let prefsWindow: BrowserWindow | undefined; @@ -13,7 +13,9 @@ export type PreferencesWindowOptions = any; const openPrefsWindow = async (options?: PreferencesWindowOptions) => { track('preferences/opened'); - windowManager.cropper?.close(); + let window = windowManager.cropper?.isOpen() + if (window) window?.hide?.() + if (prefsWindow) { if (options) { diff --git a/package.json b/package.json index ee5148b8..cafdda0c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "test": "yarn lint && yarn test:main", "start": "tsc && run-electron .", "build-main": "tsc", - "build-renderer": "next build renderer && next export renderer", + "build-renderer": "NODE_OPTIONS='--openssl-legacy-provider' && next build renderer && next export renderer", "build": "yarn build-main && yarn build-renderer", "dist": "npm run build && electron-builder", "pack": "npm run build && electron-builder --dir", @@ -89,8 +89,7 @@ "tildify": "^2.0.0", "tmp": "^0.2.0", "unstated": "^1.2.0", - "unstated-next": "^1.1.0", - "yarn": "^1.22.10" + "unstated-next": "^1.1.0" }, "devDependencies": { "@babel/core": "^7.12.16", @@ -303,5 +302,6 @@ } ] } - } -} + }, + "packageManager": "yarn@4.1.0" +} \ No newline at end of file diff --git a/renderer/components/action-bar/controls/main.js b/renderer/components/action-bar/controls/main.js index 79284921..1bb9ccf3 100644 --- a/renderer/components/action-bar/controls/main.js +++ b/renderer/components/action-bar/controls/main.js @@ -11,7 +11,7 @@ import { FullscreenIcon, ExitFullscreenIcon } from '../../../vectors'; -import {connect, ActionBarContainer, CropperContainer} from '../../../containers'; +import { connect, ActionBarContainer, CropperContainer } from '../../../containers'; const mainStyle = css` .main { @@ -27,8 +27,8 @@ const MainControls = {}; const remote = electron.remote || false; let menu; -const buildMenu = async ({selectedApp}) => { - const {buildWindowsMenu} = remote.require('./utils/windows'); +const buildMenu = async ({ selectedApp }) => { + const { buildWindowsMenu } = remote.require('./utils/windows'); menu = await buildWindowsMenu(selectedApp); }; @@ -36,25 +36,25 @@ class Left extends React.Component { state = {}; static getDerivedStateFromProps(nextProps, previousState) { - const {selectedApp} = nextProps; + const { selectedApp } = nextProps; if (selectedApp !== previousState.selectedApp) { - buildMenu({selectedApp}); - return {selectedApp}; + buildMenu({ selectedApp }); + return { selectedApp }; } return null; } render() { - const {toggleAdvanced, selectedApp, advanced} = this.props; + const { toggleAdvanced, selectedApp, advanced } = this.props; return (
- +
- +