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

Add demo add-on for adding a custom exporter #21

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

RumovZ
Copy link

@RumovZ RumovZ commented Apr 28, 2024

No description provided.

Copy link
Member

@dae dae left a comment

Choose a reason for hiding this comment

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

Thanks Rumo, this example is a good way of sparking discussion on this. It highlights some of the issues we'll need to think about to come close to the flexibility of Qt add-ons, such as:

  • the ability of add-ons to extend the UI
  • a lack of static typechecking support - add-on authors currently would not be able to catch breakages if our JS API changes

@@ -0,0 +1,27 @@
function updateExporters(exporters) {
for (const exporter of exporters) {
exporter.isDefault = false;
Copy link
Member

Choose a reason for hiding this comment

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

That feels like something every add-on author will try to do? What happens when multiple add-ons try to become the default?

Copy link
Author

Choose a reason for hiding this comment

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

If they do it like this the last one will win; if there are multiple defaults the first one due to how findIndex() works.

Copy link
Member

Choose a reason for hiding this comment

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

I just wonder if it's useful to expose this - presumably all add-ons will want to do it, and then we might as well make it the default, or leave the defaults alone so things are consistent.

Copy link
Author

Choose a reason for hiding this comment

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

I hadn't assumed users would have multiple add-ons adding custom exporters enabled at once very often.
How about we leave isDefault customisable, but remove it from the example?
That said, it doesn't really matter to me if we expose this, it's just a bit simpler this way.

Copy link
Member

Choose a reason for hiding this comment

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

Colud we perhaps make it simpler by making it a wantDefault instead? The standard importers could leave it off, and we could then select the first wantDefault, and fall back on the first importer if none have it set.

But that's assuming we want to expose this. One counterpoint for example: the 'special fields' add-on breaks the import of recent .apkg files. Allowing the defaults to be changed could make it harder for the user to realise that problems are caused by an add-on.

Copy link
Author

Choose a reason for hiding this comment

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

Ok, no problem, I'll remove the default flag on the next occasion.

demos/add_exporter/init.js Show resolved Hide resolved
demos/add_exporter/init.js Outdated Show resolved Hide resolved
@RumovZ
Copy link
Author

RumovZ commented May 3, 2024

I guess there's also a race condition, at least hypothetically. The event could already have fired when the add-on code runs. One way to solve it would be to additionally set a global variable. The add-on would have to check the variable and only setup the listener if it's not set, yet. Feels hacky ...

If you don't know how to make injected code run after Anki's code, either (and I'm getting the feeling it might in fact be impossible due to SvelteKit's event-driven page loading), it seems we need a new Python hook for that.
How about we use the existing registerPackage() utility, and extend it to call a Python hook with the name of the now importable package?

@dae
Copy link
Member

dae commented May 6, 2024

Feels hacky

Agreed.

How about we use the existing registerPackage() utility, and extend it to call a Python hook with the name of the now importable package?

That could work. I wonder if we could cut Python out of the equation though? We may eventually get to the point where we want to run JS add-ons on mobile platforms as well, and avoiding a Python intermediary would make that a little easier in the future.

We have control over ts/src/app.html, so we can insert inline scripts or non-async script references there, which would be guaranteed to load before any injected JS. We could use that to expose some global promise(s), which injected code could await. It would be nice if we could do it in a way that doesn't require us touching the small synchronous code each time we want to expose a new hook.

WDYT?

@RumovZ
Copy link
Author

RumovZ commented May 8, 2024

Sounds good! I will start looking into it next week.
Would it still make sense to reuse the existing mechanism in runtime-require.ts? I have something like a requireAsync() in mind that returns a Promise that resolves once the requested package is available instead of throwing.

@dae
Copy link
Member

dae commented May 15, 2024

Sorry for the delay here Rumo.

While part of me wonders whether there might be a better way than runtime-require to provide typed exports, I don't currently have a better idea, so following the existing pattern of using runtime-require seems like a safe bet unless anyone else like @abdnh @glutanimate and so on wish to chime in.

@dae
Copy link
Member

dae commented May 15, 2024

(are you planning to have requireAsync similarly-typed to require so that if we end up providing a d.ts file to add-on authors in the future, they'll be able to get the correct types from the required namespace?)

@RumovZ
Copy link
Author

RumovZ commented May 18, 2024

Sorry for the delay here Rumo.

No worries, I hope for the same lenience. 😉

are you planning to have requireAsync similarly-typed to require

Yes, just pushed it.

@dae
Copy link
Member

dae commented Jun 28, 2024

Sorry, this fell off my radar. I'm happy to merge it in as-is if you feel it's ready. A quick question first: how do you imagine doExport to be implemented by an add-on author? Presumably they would need to add a new endpoint to mediasrv, and invoke it in doExport()? A minimal example of this might make things easier for people using this demo as a reference.

@RumovZ
Copy link
Author

RumovZ commented Jun 30, 2024

I was under the impression you wanted to sort out ankitects/anki#3187 first. If you think it makes sense, I will try to add support for bundled Svelte components to ankitects/anki#3145 and this demo.

A minimal example of this might make things easier for people using this demo as a reference.

I'll look into it.

@dae
Copy link
Member

dae commented Jul 22, 2024

Sorry for the delay; I just replied on ankitects/anki#3187

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants