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

refactor(client): create Typescript MethodChannel on all platforms #2298

Merged
merged 19 commits into from
Dec 4, 2024

Conversation

fortuna
Copy link
Collaborator

@fortuna fortuna commented Dec 3, 2024

With this change we can call native methods uniformly across Electron and Cordova, and we can easily add new methods by changing Go code only! No more touching all the platforms!
It also allows us to intercept a method at any layer.

I've replaced the fetchResource cordova plugin method with an InvokeMethod call instead to simplify the plugin and demonstrate the functionality.

@github-actions github-actions bot added the size/S label Dec 3, 2024
@github-actions github-actions bot added size/M and removed size/S labels Dec 3, 2024
@fortuna fortuna requested a review from jyyi1 December 3, 2024 20:37
@fortuna fortuna marked this pull request as ready for review December 3, 2024 20:39
@fortuna fortuna requested a review from a team as a code owner December 3, 2024 20:39
Copy link
Contributor

@jyyi1 jyyi1 left a comment

Choose a reason for hiding this comment

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

A large step towards unified native function call! This is awesome.

In addition to the comments, I think there are also some lint issues.

client/electron/index.ts Outdated Show resolved Hide resolved
// TODO(fortuna): wire generic calls in the Cordova plugin.
return pluginExecWithErrorCode<string>('fetchResource', params);
default:
return await pluginExecWithErrorCode(
Copy link
Contributor

Choose a reason for hiding this comment

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

[NOT THIS PR] I feel the name pluginExecWithErrorCode can be updated, instead of returning error codes, it throws a PlatformError now.

client/src/www/app/main.cordova.ts Outdated Show resolved Hide resolved
async invokeMethod(methodName: string, params: string): Promise<string> {
switch (methodName) {
default:
return await window.electron.methodChannel.invoke(
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe the await (and the async above) is not needed here? IIRC, methodChannel.invoke should already return a Promise<string>.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think it's clearer if we call await. Otherwise it reads as if we are returning a promise of a promise, even though Typescript auto-unwraps it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would not recommend return invoke(...) in an async function. Instead, I would maybe prefer return invoke(...) in a regular function, since we are not doing any multiple asynchronous steps here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done. But I also removed the switch to avoid mistakes. Previously I was implementing an interception there, and I needed the await.

client/src/www/app/method_channel.ts Show resolved Hide resolved
@fortuna fortuna requested a review from a team as a code owner December 3, 2024 21:05
@github-actions github-actions bot added size/L and removed size/M labels Dec 3, 2024
Copy link
Collaborator Author

@fortuna fortuna left a comment

Choose a reason for hiding this comment

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

Comments addressed. I also went one step further and wired all platforms!

async invokeMethod(methodName: string, params: string): Promise<string> {
switch (methodName) {
default:
return await window.electron.methodChannel.invoke(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think it's clearer if we call await. Otherwise it reads as if we are returning a promise of a promise, even though Typescript auto-unwraps it.

client/electron/index.ts Outdated Show resolved Hide resolved
client/src/www/app/main.cordova.ts Outdated Show resolved Hide resolved
client/src/www/app/method_channel.ts Show resolved Hide resolved
@fortuna fortuna requested a review from jyyi1 December 3, 2024 21:34
Copy link
Contributor

@jyyi1 jyyi1 left a comment

Choose a reason for hiding this comment

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

Cool, the code looks good, with some comments.

client/electron/go_plugin.ts Outdated Show resolved Hide resolved
client/electron/go_plugin.ts Outdated Show resolved Hide resolved
client/electron/index.ts Outdated Show resolved Hide resolved
client/go/outline/method_channel.go Outdated Show resolved Hide resolved
client/go/outline/method_channel.go Outdated Show resolved Hide resolved
client/go/outline/fetch.go Outdated Show resolved Hide resolved
}
DDLogInfo("Fetching resource from \(url)")
guard let input = command.argument(at: 1) as? String else {
return sendError("Missing method input", callbackId: command.callbackId)
Copy link
Contributor

Choose a reason for hiding this comment

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

What if the method doesn't accept any input? Passing "" or null?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'd say we should always pass an input, even if it's the empty string.

async invokeMethod(methodName: string, params: string): Promise<string> {
switch (methodName) {
default:
return await window.electron.methodChannel.invoke(
Copy link
Contributor

Choose a reason for hiding this comment

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

I would not recommend return invoke(...) in an async function. Instead, I would maybe prefer return invoke(...) in a regular function, since we are not doing any multiple asynchronous steps here.

@fortuna fortuna requested a review from jyyi1 December 3, 2024 23:24
@fortuna
Copy link
Collaborator Author

fortuna commented Dec 4, 2024

Tested on macOS, Android and Linux, so I'm quite confident it works on both Cordova and Electron.

@fortuna fortuna enabled auto-merge (squash) December 4, 2024 21:32
@fortuna fortuna merged commit 4aa6c2d into master Dec 4, 2024
16 of 17 checks passed
@fortuna fortuna deleted the fortuna-mc branch December 4, 2024 21:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants