Skip to content
This repository has been archived by the owner on Aug 29, 2023. It is now read-only.

Migrate plugin to be dynamic #24

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

Migrate plugin to be dynamic #24

wants to merge 2 commits into from

Conversation

nazmulidris
Copy link

JetBrains has deprecated components to make IDE startup more performant.
The commit migrates the DarkModeSync component into a service and post
startup activity. Here are some links from JetBrains docs about dynamic
plugin migrations.

JetBrains has deprecated components to make IDE startup more performant.
The commit migrates the DarkModeSync component into a service and post
startup activity. Here are some links from JetBrains docs about dynamic
plugin migrations.

- https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/dynamic_plugins.html
- https://jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_components.html
@gilday gilday self-assigned this Sep 10, 2020
Copy link
Owner

@gilday gilday left a comment

Choose a reason for hiding this comment

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

This is awesome! I was unaware of the new APIs like Service before reading the links you shared.

One thing I learned is that the postStartupActivity listener pertains to the project lifecycle, but Dark Mode Sync operates at the application level. If I understand this correctly, this change creates a new DarkModeSync service each time a new project is opened. Instead, we want one DarkModeSync service singleton at the Application level.

Before we merge this improvement, let's figure out how to listen for the right AppLifecycleListener events to initialize the service as an Application level singleton.

}

public static DarkModeSync getInstance(@NotNull Project project) {
return project.getService(DarkModeSync.class);
Copy link
Owner

Choose a reason for hiding this comment

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

This creates a new DarkModeSync service for each Project, right? We want one DarkModeSync singleton at the application level

Copy link
Author

Choose a reason for hiding this comment

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

You are right, this will end up creating a service instance for each project. Good catch!

</application-components>
<extensions defaultExtensionNs="com.intellij">
<postStartupActivity implementation="com.github.gilday.darkmode.DarkModeSync$MyStartupActivity"/>
Copy link
Owner

Choose a reason for hiding this comment

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

postStartupActivity pertains to the Project lifecycle. Can we use an AppLifecycleListener instead? I'm thinking we may need to initialize the singleton in both the welcomeScreenDisplayed and appStarting callbacks. Thoughts?

Copy link
Author

Choose a reason for hiding this comment

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

I've migrated MyStartupActivity into a MyLifecycleListener which implements AppLifecycleListener.

Also DarkModeSync no longer implements Disposable. Instead it is all handled in the following lifecycle methods.

  1. appStarting() -> calls onStartup()
  2. appWillBeClosed() -> calls onClose()

And there's no longer a need to pass a project to getInstance(), which just returns a singleton.


/** @param lafManager IDEA look-and-feel manager for getting and setting the current theme */
public DarkModeSync(final LafManager lafManager) {
private static final class MyStartupActivity implements StartupActivity.DumbAware {
Copy link
Owner

Choose a reason for hiding this comment

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

Can we make this listener public? I assume private works because the platform is using setAccessible before using reflection to create a new instance of this listener, but I would rather not rely on that behavior.

Copy link
Author

@nazmulidris nazmulidris Sep 10, 2020

Choose a reason for hiding this comment

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

Done!

Instead of using StartupActivity, use AppLifecycleListener and make the
DarkModeSync class a singleton.
@nazmulidris
Copy link
Author

Hi Jonathan

I'm glad that you found this PR useful 😄 . JetBrains does make a lot of changes to their platform APIs and it is really difficult to figure out what they are and how that will impact things 😦 .

I've made the changes you requested. I totally missed that a new service instance would be created for every project opened! Great catch 👏 . Please let me know what you think on this commit that should address these changes: https://github.com/nazmulidris/dark-mode-sync-plugin/commit/47323eb5c35c934e702e1e3180e96b9b38377491

Thanks
Nazmul

@ChrisCarini
Copy link
Contributor

FWIW, I would love to see this PR land! The UX of dynamically loading / unloading plugins is really nice as a user! :)

@gilday
Copy link
Owner

gilday commented Sep 21, 2020

Thanks for making those changes! I tested it out tonight and it's not working as expected. I ran ./gradlew runIde to test manually as I normally do, and the themes didn't update as expected.

I'll dig in and see if I can figure out why

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

Successfully merging this pull request may close these issues.

3 participants