Skip to content

Commit

Permalink
Move to TypeScript (wulkano#955)
Browse files Browse the repository at this point in the history
  • Loading branch information
karaggeorge authored Mar 13, 2021
1 parent a1aed0a commit 8bd89ce
Show file tree
Hide file tree
Showing 219 changed files with 12,951 additions and 8,167 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
/renderer/.next
/app/dist
/dist
/dist-js
133 changes: 57 additions & 76 deletions main/common/aperture.js → main/aperture.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,53 @@
'use strict';
import {windowManager} from './windows/manager';
import {setRecordingTray, 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';

const createAperture = require('aperture');

const {openEditorWindow} = require('../editor');
const {closePrefsWindow} = require('../preferences');
const {setRecordingTray, disableTray, resetTray} = require('../tray');
const {disableCroppers, setRecordingCroppers, closeAllCroppers} = require('../cropper');
const {setCropperShortcutAction} = require('../global-accelerators');

// eslint-disable-next-line no-unused-vars
const {convertToH264} = require('../utils/encoding');

const settings = require('./settings');
const {track} = require('./analytics');
const plugins = require('./plugins');
const {getAudioDevices} = require('../utils/devices');
const {showError} = require('../utils/errors');
const {RecordServiceContext} = require('../service-context');
const {setCurrentRecording, updatePluginState, stopCurrentRecording} = require('../recording-history');

const aperture = createAperture();
const {videoCodecs} = createAperture;

// eslint-disable-next-line no-unused-vars
const recordHevc = videoCodecs.has('hevc');

let lastUsedSettings;
let recordingPlugins = [];
const serviceState = new Map();
let apertureOptions;
let recordingName;
let past;
let recordingPlugins: Array<{plugin: InstalledPlugin; service: RecordService}> = [];
const serviceState = new Map<string, RecordServiceState>();
let apertureOptions: ApertureOptions;
let recordingName: string | undefined;
let past: number | undefined;

const setRecordingName = name => {
const setRecordingName = (name: string) => {
recordingName = name;
};

const serializeEditPluginState = () => {
const result = {};
const result: Record<string, Record<string, Record<string, unknown> | undefined>> = {};

for (const {plugin, service} of recordingPlugins) {
if (!result[plugin.name]) {
result[plugin.name] = {};
}

result[plugin.name][service.title] = serviceState.get(service.title).persistedState;
result[plugin.name][service.title] = serviceState.get(service.title)?.persistedState;
}

return result;
};

const callPlugins = async method => 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](
await service[method]?.(
new RecordServiceContext({
plugin,
apertureOptions,
state: serviceState.get(service.title),
config: plugin.config,
state: serviceState.get(service.title) ?? {},
setRecordingName
})
);
Expand All @@ -68,7 +58,7 @@ const callPlugins = async method => Promise.all(recordingPlugins.map(async ({plu
}));

const cleanup = async () => {
closeAllCroppers();
windowManager.cropper?.close();
resetTray();

await callPlugins('didStopRecording');
Expand All @@ -77,17 +67,17 @@ const cleanup = async () => {
setCropperShortcutAction();
};

const startRecording = async options => {
export const startRecording = async (options: StartRecordingOptions) => {
if (past) {
return;
}

past = Date.now();
recordingName = undefined;

closePrefsWindow();
windowManager.preferences?.close();
windowManager.cropper?.disable();
disableTray();
disableCroppers();

const {cropperBounds, screenBounds, displayId} = options;

Expand All @@ -108,19 +98,15 @@ const startRecording = async options => {
screenId: displayId
};

lastUsedSettings = {
recordedFps: apertureOptions.fps
};

if (recordAudio === true) {
if (recordAudio) {
// In case for some reason the default audio device is not set
// use the first available device for recording
const audioInputDeviceId = settings.getSelectedInputDeviceId();
const audioInputDeviceId = getSelectedInputDeviceId();
if (audioInputDeviceId) {
apertureOptions.audioDeviceId = audioInputDeviceId;
} else {
const [defaultAudioDevice] = await getAudioDevices();
apertureOptions.audioDeviceId = defaultAudioDevice && defaultAudioDevice.id;
apertureOptions.audioDeviceId = defaultAudioDevice?.id;
}
}

Expand All @@ -132,12 +118,15 @@ const startRecording = async options => {
console.log(`Collected settings after ${(Date.now() - past) / 1000}s`);

recordingPlugins = plugins
.getRecordingPlugins()
.recordingPlugins
.flatMap(
plugin => plugin.recordServicesWithStatus
// Make sure service is valid and enabled
.filter(({title, isEnabled}) => isEnabled && plugin.config.validServices.includes(title))
.map(service => ({plugin, service}))
plugin => {
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}));
}
);

for (const {service, plugin} of recordingPlugins) {
Expand All @@ -154,12 +143,12 @@ const startRecording = async options => {
filePath,
name: recordingName,
apertureOptions,
editPlugins: serializeEditPluginState()
plugins: serializeEditPluginState()
});
} catch (error) {
track('recording/stopped/error');
showError(error, {title: 'Recording error'});
past = null;
showError(error, {title: 'Recording error', plugin: undefined});
past = undefined;
cleanup();
return;
}
Expand All @@ -172,18 +161,18 @@ const startRecording = async options => {
}

console.log(`Started recording after ${startTime}s`);
setRecordingCroppers();
windowManager.cropper?.setRecording();
setRecordingTray(stopRecording);
setCropperShortcutAction(stopRecording);
past = Date.now();

// Track aperture errors after recording has started, to avoid kap freezing if something goes wrong
aperture.recorder.catch(error => {
aperture.recorder.catch((error: any) => {
// Make sure it doesn't catch the error of ending the recording
if (past) {
track('recording/stopped/error');
showError(error, {title: 'Recording error'});
past = null;
showError(error, {title: 'Recording error', plugin: undefined});
past = undefined;
cleanup();
}
});
Expand All @@ -192,46 +181,38 @@ const startRecording = async options => {
updatePluginState(serializeEditPluginState());
};

const stopRecording = async () => {
export const stopRecording = async () => {
// Ensure we only stop recording once
if (!past) {
return;
}

console.log(`Stopped recording after ${(Date.now() - past) / 1000}s`);
past = null;
past = undefined;

let filePath;

try {
filePath = await aperture.stopRecording();
} catch (error) {
track('recording/stopped/error');
showError(error, {title: 'Recording error'});
showError(error, {title: 'Recording error', plugin: undefined});
cleanup();
return;
}

const {recordedFps} = lastUsedSettings;

try {
cleanup();
} finally {
track('editor/opened/recording');

// TODO: bring this back when we figure out how to convert hevc files
// if (recordHevc) {
// openEditorWindow(await convertToH264(filePath), {recordedFps, isNewRecording: true, originalFilePath: filePath});
// } else {
await openEditorWindow(filePath, {recordedFps, isNewRecording: true, recordingName});
// }
const recording = new Recording({
filePath,
title: recordingName,
apertureOptions
});
await recording.openEditorWindow();

stopCurrentRecording(recordingName);
}
};

module.exports = {
startRecording,
stopRecording,
getAudioDevices
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

// The goal of this file is validating accelerator values we receive from the user
// to make sure that they are can be used with the electron api https://www.electronjs.org/docs/api/accelerator

Expand Down Expand Up @@ -46,9 +44,9 @@ const codes = [
'numsub',
'nummult',
'numdiv'
];
] as const;

const keyCodeRegex = new RegExp('^([\\dA-Z~`!@#$%^&*()_+=.,<>?;:\'"\\-\\/\\\\\\[\\]\\{\\}\\|]|F([1-9]|1[\\d]|2[0-4])|' + codes.join('|') + ')$');
const getKeyCodeRegex = () => new RegExp('^([\\dA-Z~`!@#$%^&*()_+=.,<>?;:\'"\\-\\/\\\\\\[\\]\\{\\}\\|]|F([1-9]|1[\\d]|2[0-4])|' + codes.join('|') + ')$');

const shiftKeyMap = new Map([
['~', '`'],
Expand Down Expand Up @@ -102,7 +100,7 @@ const namedKeyCodeMap = new Map([
['Clear', 'Numlock']
]);

const checkAccelerator = accelerator => {
export const checkAccelerator = (accelerator: string) => {
if (!accelerator) {
return true;
}
Expand All @@ -113,23 +111,18 @@ const checkAccelerator = accelerator => {
return false;
}

if (!keyCodeRegex.test(parts[parts.length - 1])) {
if (!getKeyCodeRegex().test(parts[parts.length - 1])) {
return false;
}

const metaKeys = parts.slice(0, -1);
return metaKeys.every(part => modifiers.includes(part)) && metaKeys.some(part => part !== 'Shift');
};

const eventKeyToAccelerator = (key, location) => {
export const eventKeyToAccelerator = (key: string, location: number) => {
if (location === 3) {
return numpadKeyMap.get(key);
}

return namedKeyCodeMap.get(key) || shiftKeyMap.get(key) || key.toUpperCase();
};

module.exports = {
checkAccelerator,
eventKeyToAccelerator
return namedKeyCodeMap.get(key) ?? shiftKeyMap.get(key) ?? key.toUpperCase();
};
20 changes: 8 additions & 12 deletions main/common/analytics.js → main/common/analytics.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
'use strict';

const util = require('electron-util');
import util from 'electron-util';
import {parse} from 'semver';
import {settings} from './settings';

const Insight = require('insight');
const {parse} = require('semver');
const pkg = require('../../package');
const settings = require('./settings');

const trackingCode = 'UA-84705099-2';
const insight = new Insight({trackingCode, pkg});
const version = parse(pkg.version);

const track = (...paths) => {
export const track = (...paths: string[]) => {
const allowAnalytics = settings.get('allowAnalytics');

if (allowAnalytics) {
console.log('Tracking', `v${version.major}.${version.minor}`, ...paths);
insight.track(`v${version.major}.${version.minor}`, ...paths);
console.log('Tracking', `v${version?.major}.${version?.minor}`, ...paths);
insight.track(`v${version?.major}.${version?.minor}`, ...paths);
}
};

const initializeAnalytics = () => {
export const initializeAnalytics = () => {
if (util.isFirstAppLaunch()) {
insight.track('install');
}
Expand All @@ -29,8 +30,3 @@ const initializeAnalytics = () => {
settings.set('version', pkg.version);
}
};

module.exports = {
initializeAnalytics,
track
};
15 changes: 0 additions & 15 deletions main/common/constants.js

This file was deleted.

14 changes: 14 additions & 0 deletions main/common/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {Format} from './types';

export const supportedVideoExtensions = ['mp4', 'mov', 'm4v'];

const formatExtensions = new Map([
['av1', 'mp4']
]);

export const formats = [Format.mp4, Format.av1, Format.gif, Format.apng, Format.webm];

export const getFormatExtension = (format: Format) => formatExtensions.get(format) ?? format;

export const defaultInputDeviceId = 'SYSTEM_DEFAULT';

Loading

0 comments on commit 8bd89ce

Please sign in to comment.