-
Notifications
You must be signed in to change notification settings - Fork 833
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
Move to TypeScript #955
Conversation
|
||
const converters = new Map([ | ||
[Encoding.h264, h264Converters] | ||
]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we support recording in hevc, we can add converters for that here if they are different from h264 (same for ProRes etc)
constructor(name: string, services: Service[]) { | ||
const defaults = {}; | ||
|
||
const validators = services |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I noticed here, but hasn't come up as an issue yet, is that we allow each service exported by a plugin to have its own config
schema object, but we actually save all of them (and validate them) against the same object (electron-store instance). So the plugins need to make sure their different services don't have conflicting field schemas
main/plugins/service.ts
Outdated
didStopRecording?: () => {}; | ||
willEnable?: () => {}; | ||
cleanUp?: () => {}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should find a way (when this is done) to export this somehow as a package so plugins written in TS can leverage these types
if (this.encoding === 'h264') { | ||
this.previewPath = this.filePath; | ||
} else { | ||
this.previewPath = await convertToH264(this.filePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Written this like that (with a separate promise) as in the future when we have ProRes that takes a while to generate a preview, we can show the editor early with a spinner saying that the preview is being generated.
package.json
Outdated
"extends": "xo-react", | ||
"extends": [ | ||
"xo-react", | ||
"xo-typescript" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to remove this
main/common/settings.ts
Outdated
@@ -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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
main/plugins/plugin.ts
Outdated
} | ||
|
||
get shareServices() { | ||
return this.content.shareServices || []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return this.content.shareServices || []; | |
return this.content.shareServices ?? []; |
?
From your description, this sounds like a huge improvement on every level. I would recommend targeting just getting something working first, merge this PR, and then do follow-up PRs that perfect/abstract it and turn more things into TS.
👍 This would be much closer to how native apps work. |
.circleci/config.yml
Outdated
@@ -6,7 +6,7 @@ jobs: | |||
steps: | |||
- checkout | |||
- run: yarn | |||
- run: yarn test |
There was a problem hiding this comment.
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
The new export window looks hot 🙌
|
title: string; | ||
pluginName: string; | ||
pluginPath: string; | ||
apps?: App[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't lint this yet as the linting is buggy, but generally use readonly
whenever possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean add readonly to all fields? Maybe wrap the types with Readonly?
main/converters/index.ts
Outdated
croppedPath = options.inputPath; | ||
} | ||
|
||
let canceled = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let canceled = false; | |
let isCanceled = false; |
main/converters/utils.ts
Outdated
}; | ||
} | ||
|
||
export const makeEven = (n: number) => 2 * Math.round(n / 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export const makeEven = (n: number) => 2 * Math.round(n / 2); | |
export const makeEven = (number: number) => 2 * Math.round(number / 2); |
tsconfig.json
Outdated
"target": "es2019", | ||
"module": "commonjs", | ||
"esModuleInterop": true, | ||
"downlevelIteration": true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why enable this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allows stuff like [...someMap.values()]
without @ts-ignore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's only true when the target
is ES5. For modern targets, that should work without downlevelIteration
as it just uses it natively.
renderer/tsconfig.json
Outdated
@@ -0,0 +1,41 @@ | |||
{ | |||
"compilerOptions": { | |||
"target": "es5", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the target es5
? That will include a lot of polyfill bloat we don't need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, this is autogenerated by Next.js
What should the target be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as the main process tsconfig.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should get rid of the warning when navigating back from an ongoing conversion to the editor. I'll often realise I need to make further changes after starting a conversion, and the dialog slows me down unnecessarily, I only need to be warned if I'm about to lose the source file.
|
Keep in track of the ones I implemented above ^
The only thing we do async before opening the menu is getting the input devices. The only way around I can think is instead of checking them on every menu open, checking them every x seconds and using the last value. Surprisingly when running locally this is not delayed for me at all I'll investigate more
What would the icon be that would indicate that? Popover I think would also work, maybe make it a more abstract thing that we can re-use to introduce new or hidden features in general? But maybe different issue/PR?
Should this be a dialog (blocking), or close immediately, and just shoot a notification? Only thing about notification is the user might not see if it they have notifications off (or permission not granted) cc @skllcrn as well |
Why are we getting the input devices? They don't show in the menu. Could we not fetch those lazily?
Dialog, but we only need to show it once (ever).
Sure: #985 |
Yes, but not sure whether that's possible in Electron.
I forgot it was supposed to show there. It doesn't for me. I don't think I got a prompt either. And Kap doesn't show in the System Preferences for Microphone access. Here's the menu I see: |
Hmm maybe some kind of different permission thing for macos 11? I think we use the electron api for microphone permission. Did they make an update to it to handle macos 11 in a newer electron version? Electron 12 I think just released and it also has the share menu stuff, I can try to upgrade. If it's not the input devices, I don't know what would delay the menu. Let me reset my permission and try again see if there's something else going on |
It's not a big deal though. Don't let it block this PR. I can open an issue about it afterwards. |
@sindresorhus everything should be done, except for the one you opened an issue for, and then these:
Will try to figure out in a separate PR, probably need to upgrade Electron from 8.x
Right now it's the fastest it'll be, I think it's because of an ipc call every time? (I didn't change it at all) but since I'm about to rewrite Preferences window soon, I'd rather address in that PR So, let's test this a bit more, and if we don't have any other issues for a bit, we can merge |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's working great for me. I think we can merge this sooner than later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic work @karaggeorge! A couple of things I've noticed:
- We seem to have lost the file menu option to save the original
- File names in the conversion screen appear black when the system is in light mode
- Also in light mode, the window background turns light when transitioning back to the editor
- When navigating back to the editor, the trimming end is lost
- Hitting enter while editing the FPS does not validate the input
Have a lovely weekend ❤️
@skllcrn good catches, and although you forced me to go to light mode which throws me off so much, everything is fixed 😄 Forgot our editor is perma-dark styled, so was using the theme-dependent css vars |
This is such a nice improvement to the code quality 👌 |
Closes #984
Closes #895
This is a PR with a lot of changes. It started as rewriting the editor, in which I started writing the new code in TS (since next supports it pretty seamlessly), which then led to start turning the main process in TS as well. Since it was a big rewrite I also started making other big changes to re-organizing some things. I'll try to sum up the biggest things below since it's a lot of changes to review at once with no context:
Keep in mind that this is very much WIP, so there's a lot of duplicate files that I haven't fully transitioned, and a lot of debug code and console.logs, but I just wanted to get some eyes on it early.General
TS common types are duplicated for now as I haven't figured out a way to import them in both without transpiler breaking. But I've left comments on the types that should eventually only live in one placeRenderer
Main
window.constructor.name === 'BrowserWindow'
Tests/Linting
Remote States
Not sure if that's the best name, but the way I thought of this was firstly for export-options. So the options that populate the editor window (plugins/fps etc) need to be synced, since you can install/uninstall plugins as you have the editor open. This was done in a pretty ugly way, so I wanted something that'd work better with hooks on the renderer side. Then I saw that it could be used in general, so I made it abstract. The way it works, is on the main side, we need a function that takes an argument
sendState
which it can use to notify that state has changed, and returns an object with two properties. One isgetState
that a new subscription can use to receive the state at any given point, and an objectactions
who's properties are functions that can change the state. Then on the renderer side, via a hook, the page can subscribe to one of these states (by name) and they will receive a state automatically updating whenever needed, a method to manually refresh the state and all the actions exported by main as proxy functions, that when called will actually just call the main ones. This is all done in the background with the two remote-state implementations that communicate via ipc and handle subscriptions/state updates/actions. To write new states, we simply write the function explained above for main and call the hook in the renderer. TS should be able to auto generate types for renderer based on the main implementation, but since we don't have common types yet, I needed to replicate the main type to the renderer to get that to work.The only implementation for the above so far is the editor-options which handles, plugins (share/edit), and fps usage, but I'm planning on using one for conversions and keeping track (since now both editor windows and exports window will need to subscribe) and then for the cropper/action-bar to communicate with each other when I rewrite the cropper.
Any feedback/discussion is welcome. This is the first draft of all of this, and I'm trying to make sure I do it in a way that will help development in the future. Mostly trying to abstract things we do in every window, but slightly differently and it gets hard to manage/update.