Page MenuHomePhabricator

Gadget support: Evaluate alternatives to util.addPortletLink hook
Open, MediumPublicBUG REPORT

Description

Since we deployed Vector 2022 to English Wikipedia it seems our gadget support is not as a good as might be expected. See T327369 for example.

A mw.hook is expected to be run once but in the case of addPortletLink is run multiple times. This means users must run additional code to handle race conditions where hook handlers are registered late.

It's currently used in Minerva and Vector to add icons to certain menu items.

Possible alternatives are

  • using mw.trackSubscribe
  • removing it and upstreaming Vector/Minerva behavior to core. Both Minerva and Vector use this hook to add an icon element. Options could be added to the existing skin flag to handle this case. This would require some cleanup in Minerva to drop the Minerva specific classes.

Event Timeline

Tgr renamed this task from Evaluate alternatives to mw.util.addPortletLink hook to Evaluate alternatives to util.addPortletLink hook.Jul 23 2022, 8:13 PM

Not sure if this is related, but one specific situation where addPortletLink doesn't work is with the sticky header in Vector 2022. That menu is created via JS after pageload, and calls to addPortletLink don't get registered after that menu is created.

The menu in the sticky header should be a copy of the user menu in the Vector 2022 header. The user menu in the header gets server loaded and works with addPortletLink, so the user expectation is that when adding links to that user menu, those links are also added to the menu in the sticky header, but that's not currently possible using the addPortletLink method.

Screen Shot 2022-12-12 at 10.45.53 AM.png (762×1 px, 364 KB)

@Jdrewniak I think in this case, this is a problem with Vector not triggering an event for when the sticky header is initialized. I suggest we add mw.hook.fire('vector.stickyheader.init') after the sticky header is initialized so gadgets can subscribe to it and then use sticky header safely. The addPortletLink method currently assumes the elements are in the DOM when run.

Change 878211 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/core@master] [POC] Allow skins to implement mediawiki.util methods

https://gerrit.wikimedia.org/r/878211

Jdlrobson renamed this task from Evaluate alternatives to util.addPortletLink hook to Gadget support: Evaluate alternatives to util.addPortletLink hook.Jan 31 2023, 12:44 AM
Jdlrobson updated the task description. (Show Details)

Could the sticky header elements in question be present from the first HTML parse? Portlets are generally not expected to pop in and out of existence, as indicated by the current expectation mismatch between Vector 22 and general MW/gadget consumers.

Portlets can be hidden or empty when needed, but the parent element is generally assumed to either exist or not exist on a given pageload (title/user/skin combo). Even if calls are handled asynchronously, you might still be missing calls that will never take place due to missed checks. E.g. it seems reasonable for a gadget to check whether $('#p-foobar').length > 0 portlet exists and then decide between something it does optimised and catered for Vector 22 vs other skins. If the check fails, then the method is never called and the hook call never queued. Something to consider :)

There's some challenges for us to add the sticky header relating to serving valid HTML (avoiding portlet links with the same ID) that we're working towards (since it duplicates element in the user menu dropdown) but yes we're working towards that.

That aside, I think the main motivation for the approach in https://gerrit.wikimedia.org/r/878211 is that there is no one-fits-all generic way of adding portlets / links across skins, and skins really should have the final say on any HTML modifications. The methods in mediawiki.util currently mix generic utility methods, and skin UI modification. It should be possible for a skin to reimplement these methods to match the specification if it sees fit.

Jdlrobson triaged this task as Medium priority.Feb 6 2023, 11:40 PM

Change 878211 abandoned by Jdlrobson:

[mediawiki/core@master] Allow skins to implement mediawiki.util methods

Reason:

Shifting focus elsewhere for now until priorities align.

https://gerrit.wikimedia.org/r/878211

@Jdrewniak and I explored several options here, but I forgot to update. We settled on using option 1 which we would likely use on T303488 first before updating the existing addPortletLink function. Leaving this open a bit longer (and publicising) in case anyone has any further ideas or concerns.

Option 1) Use mw.track instead of mw.hook

PROS:
*unlike mw.hook this is guaranteed to run regardless of ordering.

  • simple change

CONS:

diff --git a/resources/src/mediawiki.util/util.js b/resources/src/mediawiki.util/util.js
index bad9216f821..6081b471690 100644
--- a/resources/src/mediawiki.util/util.js
+++ b/resources/src/mediawiki.util/util.js
@@ -637,9 +637,9 @@ util = {
 			$( link ).updateTooltipAccessKeys();
 		}
 
-		mw.hook( 'util.addPortletLink' ).fire( item, {
+		mw.track( 'util.addPortletLink',[ item, {
 			id: id
-		} );
+		} ] );
 		return item;
 	},

Option 2) Allow skins to supply mediawiki.util skin functions.
POC: https://gerrit.wikimedia.org/r/c/mediawiki/core/+/878211

Pros:

  • Skins have full control over how content is added to UI
  • Util methods can be non-existent by default allowing us to add mw.util.addPortlet.
  • Can drop skin option link with data text-wrapper etc.. as skins no longer need to care about how the rendering happens.

Cons:

  • Relatively unintuitive to developers
  • Complex
  1. Keep the status quo.

Change 878211 restored by Jdlrobson:

[mediawiki/core@master] Allow skins to implement mediawiki.util methods

https://gerrit.wikimedia.org/r/878211

Change 878211 abandoned by Jdlrobson:

[mediawiki/core@master] Allow skins to implement mediawiki.util methods

Reason:

Abandoning for now (to be revisited another day)

https://gerrit.wikimedia.org/r/878211