Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to TypeScript #955

Merged
merged 15 commits into from
Mar 13, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
steps:
- checkout
- run: yarn
- run: yarn test
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabling this so I can still get PR builds until I go back and clean up linting and tests

# - run: yarn test
- run: yarn run dist
- run: mv dist/*.dmg dist/Kap.dmg
- store_artifacts:
Expand Down
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
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
};
4 changes: 2 additions & 2 deletions main/common/aperture.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const {setCropperShortcutAction} = require('../global-accelerators');
// eslint-disable-next-line no-unused-vars
const {convertToH264} = require('../utils/encoding');

const settings = require('./settings');
const {default: settings, getSelectedInputDeviceId} = require('./settings');
const {track} = require('./analytics');
const plugins = require('./plugins');
const {getAudioDevices} = require('../utils/devices');
Expand Down Expand Up @@ -115,7 +115,7 @@ const startRecording = async options => {
if (recordAudio === true) {
// 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 {
Expand Down
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';

17 changes: 11 additions & 6 deletions main/common/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ const {notify} = require('./notifications');
const {track} = require('./analytics');
const {InstalledPlugin, NpmPlugin, recordPluginServiceState} = require('../plugin');
const {showError} = require('../utils/errors');
const {EventEmitter} = require('events');

// Need to persist the notification, otherwise it is garbage collected and the actions don't trigger
// https://github.com/electron/electron/issues/12690
let pluginNotification;

class Plugins {
class Plugins extends EventEmitter {
constructor() {
super();
this.yarnBin = path.join(__dirname, '../../node_modules/yarn/bin/yarn.js');
this._makePluginsDir();
this.appVersion = app.getVersion();
Expand Down Expand Up @@ -55,7 +57,7 @@ class Plugins {
}
} catch (error) {
showError(error, {title: `Something went wrong while enabling “${service.title}”`});
const Sentry = require('./utils/sentry');
const Sentry = require('./utils/sentry').default;
Sentry.captureException(error);
}

Expand Down Expand Up @@ -179,6 +181,7 @@ class Plugins {
pluginNotification.show();
this.updateExportOptions();
this.refreshRecordPluginServices();
this.emit('installed', plugin);

return plugin;
} catch (error) {
Expand Down Expand Up @@ -210,6 +213,7 @@ class Plugins {
}

plugin.config.clear();
this.emit('uninstalled', name);
this.updateExportOptions();
return new NpmPlugin(plugin.json, {
// Keeping for backwards compatibility
Expand All @@ -236,7 +240,7 @@ class Plugins {
return this._pluginNames().map(name => new InstalledPlugin(name));
} catch (error) {
showError(error);
const Sentry = require('../utils/sentry');
const Sentry = require('../utils/sentry').default;
Sentry.captureException(error);
return [];
}
Expand All @@ -256,15 +260,15 @@ class Plugins {

getBuiltIn() {
return [{
pluginPath: './plugins/copy-to-clipboard-plugin',
pluginPath: path.resolve(__dirname, '..', 'plugins', 'copy-to-clipboard-plugin'),
isCompatible: true,
name: '_copyToClipboard'
}, {
pluginPath: './plugins/save-file-plugin',
pluginPath: path.resolve(__dirname, '..', 'plugins', 'save-file-plugin'),
isCompatible: true,
name: '_saveToDisk'
}, {
pluginPath: './plugins/open-with-plugin',
pluginPath: path.resolve(__dirname, '..', 'plugins', 'open-with-plugin'),
isCompatible: true,
name: '_openWith'
}];
Expand Down Expand Up @@ -296,6 +300,7 @@ class Plugins {
async openPluginConfig(name) {
await openConfigWindow(name);
const plugin = new InstalledPlugin(name);
this.emit('config-changed', plugin);
return plugin.isValid;
}
}
Expand Down
49 changes: 37 additions & 12 deletions main/common/settings.js → main/common/settings.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,48 @@
'use strict';

const {homedir} = require('os');
const Store = require('electron-store');
import {homedir} from 'os';
import Store from 'electron-store';

const {defaultInputDeviceId} = require('./constants');
const {hasMicrophoneAccess} = require('./system-permissions');
const {getAudioDevices, getDefaultInputDevice} = require('../utils/devices');
const shortcutToAccelerator = require('../utils/shortcut-to-accelerator');

const shortcuts = {
triggerCropper: 'Toggle Kap'
export const shortcuts = {
triggerCropper: 'Toggle Kap',
};

const shortcutSchema = {
type: 'string',
default: ''
};

const store = new Store({
interface Settings {
kapturesDir: string;
allowAnalytics: boolean;
showCursor: boolean;
highlightClicks: boolean;
record60fps: boolean;
loopExports: boolean;
recordKeyboardShortcut: boolean;
recordAudio: boolean;
audioInputDeviceId?: string;
cropperShortcut: {
metaKey: boolean,
altKey: boolean,
ctrlKey: boolean,
shiftKey: boolean,
character: string
};
lossyCompression: boolean;
enableShortcuts: boolean;
shortcuts: {
[key in keyof typeof shortcuts]: string
},
version: string;
}

const store = new Store<Settings>({
schema: {
kapturesDir: {
type: 'string',
Expand Down Expand Up @@ -103,8 +128,7 @@ const store = new Store({
}
});

module.exports = store;
module.exports.shortcuts = shortcuts;
export default store;

// TODO: Remove this when we feel like everyone has migrated
if (store.has('recordKeyboardShortcut')) {
Expand All @@ -114,26 +138,27 @@ if (store.has('recordKeyboardShortcut')) {

// TODO: Remove this when we feel like everyone has migrated
if (store.has('cropperShortcut')) {
store.set('shortcuts.triggerCropper', shortcutToAccelerator(store.get('cropperShortcut')));
// TODO: Investigate type for dot notation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not yet possible, AFAIK.

sindresorhus/type-fest#134 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I saw something like this on Twitter a few months ago. It might have been something that hadn't landed in a stable version yet. It's not a big deal for us, but figured we could look into it

store.set('shortcuts.triggerCropper' as any, shortcutToAccelerator(store.get('cropperShortcut')));
store.delete('cropperShortcut');
}

store.set('cropper', {});
store.set('actionBar', {});
store.set('cropper' as any, {});
store.set('actionBar' as any, {});

const audioInputDeviceId = store.get('audioInputDeviceId');

if (hasMicrophoneAccess()) {
(async () => {
const devices = await getAudioDevices();

if (!devices.some(device => device.id === audioInputDeviceId)) {
if (!devices.some((device: any) => device.id === audioInputDeviceId)) {
store.set('audioInputDeviceId', defaultInputDeviceId);
}
})();
}

module.exports.getSelectedInputDeviceId = () => {
export const getSelectedInputDeviceId = () => {
const audioInputDeviceId = store.get('audioInputDeviceId', defaultInputDeviceId);

if (audioInputDeviceId === defaultInputDeviceId) {
Expand Down
21 changes: 21 additions & 0 deletions main/common/types/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export enum Format {
gif = 'gif',
mp4 = 'mp4',
webm = 'webm',
apng = 'apng',
av1 = 'av1'
}

export enum Encoding {
h264 = 'h264',
hevc = 'hevc',
proRes422 = 'proRes422',
proRes4444 = 'proRes4444'
}

export type App = {
url: string;
isDefault: boolean;
icon: string;
name: string;
}
38 changes: 38 additions & 0 deletions main/common/types/conversion-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {App, Format} from './base'

export type CreateConversionOptions = {
filePath: string;
options: ConversionOptions;
format: Format;
plugins: {
share: {
pluginName: string;
serviceTitle: string;
app?: App
}
}
}

export type EditServiceInfo = {
pluginName: string;
serviceTitle: string;
}

export type ConversionOptions = {
startTime: number;
endTime: number;
width: number;
height: number;
fps: number;
shouldCrop: boolean;
shouldMute: boolean;
editService?: EditServiceInfo;
}

export enum ConversionStatus {
idle = 'idle',
inProgress = 'inProgress',
failed = 'failed',
canceled = 'canceled',
completed = 'completed'
}
3 changes: 3 additions & 0 deletions main/common/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './base';
export * from './remote-states';
export * from './conversion-options';
Loading