Skip to content

[background-tips] Add service API for tip registration and redistribute tips#1417

Open
asiloisad wants to merge 7 commits into
pulsar-edit:masterfrom
asiloisad:upgrade-background-tips
Open

[background-tips] Add service API for tip registration and redistribute tips#1417
asiloisad wants to merge 7 commits into
pulsar-edit:masterfrom
asiloisad:upgrade-background-tips

Conversation

@asiloisad

@asiloisad asiloisad commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

The background-tips package previously had all tips hardcoded, including tips referencing commands from other package. This meant tips would still appear even when the referenced package was disabled or replaced — for example, a user who disables fuzzy-finder in favor of community package would still see tips about fuzzy-finder keybindings.

This PR adds a providedServices API to background-tips so that packages can register and unregister their own tips dynamically. When a package is disabled, its tips are automatically removed from the rotation. Community packages can also use this service to contribute their own tips.

@asiloisad

Copy link
Copy Markdown
Contributor Author

The "changes text in the message" test was failing because tips.js only had a single default tip, so cycling always produced the same text. Added two more core editor tips that don't depend on any specific package.

@savetheclocktower

Copy link
Copy Markdown
Contributor

This is a fantastic idea and we should look at it when we don't have fires to put out.

@confused-Techie confused-Techie left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Added a super quick review based on the consumption of the service in other packages, and will have to leave a more in depth review for later.

But overall, super love this idea and how the current implementation looks! Very rad idea to do this!

Comment thread packages/background-tips/lib/tips.js Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I know it might be somewhat antithetical to this PR, but we may want to leave the github package based tips in here until we are able to actually migrate that package into core, which we are still working towards and tracking in #512

this.backgroundTipsView = new BackgroundTipsView()
activate() {
this.defaultTips = require("./tips");
this.addedTips = new Set();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I can't test this at the moment. But with storing all acquired tips in a Set what are the chances we would retain tips after a package has been disabled in our current session? If this is still an issue, we could consider that still not even loading them after a reload is a huge improvement from previous behavior, but was just curious considering the goals of this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You are right, the service is too simple now. I will prepare new commits today that will handle lifecycle of tips better.

@asiloisad

Copy link
Copy Markdown
Contributor Author

Oh, I found that deferred packages (like command-palette and find-and-replace) don't register their consumed services until activation, sot their tips won't show on startup, Ironically, these are the tips most useful for new users who don't know the keybindings yet. A early-share mechanism would be useful that send tips before a delayed start.

@savetheclocktower

savetheclocktower commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Oh, I found that deferred packages (like command-palette and find-and-replace) don't register their consumed services until activation, sot their tips won't show on startup, Ironically, these are the tips most useful for new users who don't know the keybindings yet. A early-share mechanism would be useful that send tips before a delayed start.

Oof. That's a tough one to work around. Let me think about it.

EDIT: Maybe it could be part of the package.json? Less elegant, but would work for packages that are not yet activated.

EDIT 2: This would require that we be able to tell the difference between a not-yet-activated package (deferred activation for performance reasons) and an explicitly disabled package — the latter should not have tips shown. I'm not 100% certain that those are separate concepts, but I'll look into it.

@asiloisad

Copy link
Copy Markdown
Contributor Author

I have in mind that service may provide additional optional flag (next to version) like "onInitialize" that package manager will recognize and deal with service before activation (but after initialization) if package activation is deferred.

Consumed service of this topic is going like:

    "background-tips": {
      "versions": {
        "1.0.0": "consumeBackgroundTips"
      },
      "onInitialize": true
    }

A design of this package service need some updates then, because .disposables are not available yet, but It can be solved.

@savetheclocktower

Copy link
Copy Markdown
Contributor

In the short term, there won't be a good way to make this service work for packages that defer their activation. But the solution to that could just be to keep those packages' tips in the background-tips package until that can be addressed.

(As an aside: I've long felt that command-palette should not defer its own activation. The first time I type its shortcut, it takes a bit longer to appear because of its activation, and the first two characters I type actually go into the active text buffer instead of the palette because of the delay. I would've fixed this a long time ago — except that command-palette is written such that it automatically opens itself upon package activation. So it's not just a one-line fix. I could fix this just for myself by manually activating the package in my init.js — but then that causes the palette to appear!)

Another thing I thought of: I imagine the background-tips view is present pretty early in the window bootstrapping process, so we should make sure that the randomly picked tip is not chosen until after all packages have been activated (except for the deferred-activation packages, of course).

@savetheclocktower savetheclocktower added this to the 1.133.0 milestone May 2, 2026
@savetheclocktower

Copy link
Copy Markdown
Contributor

OK, giving this a 1.133.0 milestone so that it doesn't just languish because of decision paralysis.

Here are the possible ways forward:

  1. Tolerate the current limitations. Make it so that only the packages that do not defer activation are the ones that consume the new background-tips service. (This leaves some tips to be hard-coded and prevents deferred-activation community packages from being able to use this new service properly, but it's still an improvement over the status quo.)

  2. Expose background tips in package.json via some means other than a service. Could just be an arbitrary key at the top level like backgroundTips, much like activationCommands and activationHooks exist now. Would allow any package to add background tips without having to activate first. (And we certainly can tell the difference between disabled packages and not-yet-activated packages, so we can just ignore the background tips of all packages that the user has disabled. And if a package is disabled mid-session, we should be able to remove its background tips from the collection.)

  3. Add an early hook for a package that allows it to opt into consuming a service even before the package has technically been activated. This might be worth doing in its own right for other reasons… but it's risky, and would imply separate lifecycle methods. (When you consume a service, you'll likely create a Disposable that must be tracked… but if the package never activates, deactivate won't get called either.)

    I'm not going to rule this out as a possibility, but it feels like it needs a design document or an RFC or something. And there would need to be other plausible use cases for this.

My preference is for option 2, since we don't necessarily need all the flexibility that a service gives us. (We're just shoving static strings into an array, more or less.) And the problem with option 1 is that it strongly implies we'll revisit this and implement option 3 later… and that's a big undertaking. But I could theoretically be convinced otherwise!

@asiloisad

Copy link
Copy Markdown
Contributor Author

I like second option too. I will prepare new commits asap.

@asiloisad
asiloisad force-pushed the upgrade-background-tips branch from cf8968c to 9c38f46 Compare May 6, 2026 08:32
@asiloisad

Copy link
Copy Markdown
Contributor Author

I've reworked the implementation based on the discussion. Instead of a service/consumer pattern, packages declare tips directly in their package.json under a backgroundTips key, as an array of strings. This works for deferred packages too. If a placeholder command has no keybinding defined, the tip is skipped entirely rather than showing a raw command name (it was bug in my opinion). Tips are loaded/unloaded incrementally via onDidLoadPackage / onDidUnloadPackage, so enabling/disabling packages mid-session is handled. Tips from disabled packages are skipped at display time. A configs displayDuration and debug was used in production, but I keep them (both can be deleted if this is your preference).

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.

3 participants