Page MenuHomePhabricator

Provide an API to hook into new reply editor
Open, Needs TriagePublicFeature

Description

I love the new discussion tool and would love to hook into it. I'm using an autocorrect for the main VisualEditor. So adding dashes, arrows, Polish quotes etc. All this is still useful when replying.

So technically I need some activation hook similar to this:

	mw.hook('ve.activationComplete').add(function () {
		...
	});

And also need to have access to VE commandRegistry, VE Surface and VE sequenceRegistry.

		//create and register the command
		ve.ui.commandRegistry.register(...);
		//let the surface know that there is a new command that can be executed
		ve.init.target.getSurface().commands.push(name);
		//create and register the sequence
		ve.ui.sequenceRegistry.register(...);

Full code of the gadget can be found here:
https://github.com/Eccenux/veAutocorrect/blob/master/veAutocorrect.js

Requirements

Done

  • Volunteers are invited to share feedback about the API the Editing Team is considering implementing
  • Volunteers are offered a way to try out the API approach the Editing Team is considering implementing (e.g via patchdemo)

Event Timeline

The Russian Wikipedia also very often uses gadgets to correct the text (cyrillic link converter and markup fix). And we need to be able to add them to the toolbar.

Iniquity changed the subtype of this task from "Task" to "Feature Request".

It's current possible to add things to the toolbar, though there's not a great hook to hang this from.

e.g. this would add the special characters button to the discussiontools toolbar:

mw.loader.using( [ 'ext.discussionTools.ReplyWidgetVisual' ] ).then( function() {
	ve.init.mw.targetFactory.registry.discussionTools.static.toolbarGroups.push(
		{
			name: 'specialCharacter',
			include: [ 'specialCharacter' ]
		}
	);
});

(The flaw here is that as-is just dumping that into a gadget/script would forcibly load the DT modules on all pages regardless of whether they actually need to be loaded.)

I'd suggest a hook called something like dt.activationComplete at the end of controller.js's init function. Then maybe another in ReplyWidget.setup so someone can know when one is actually opened... or just expose the active widget somewhere so OOjs events can be used to similar effect.

This dt.activationComplete would be fine for me I think... Am I assuming correctly this would be valid?:

mw.hook( 'dt.activationComplete' ).add( function ( commentController ) {
	var editor = commentController.replyWidget.replyBodyWidget;
	// Check if this is the wikitext mode, rather than visual
	if ( editor instanceof OO.ui.TextInputWidget ) {
		console.log('ignore');
	} else {
		console.assert( typeof editor?.ui?.commandRegistry === 'object', { editor } );
		console.assert( typeof editor?.init?.target.getSurface === 'function', { editor } );
	}
} );

@Nux that's about how you'd use it. (Though what you're testing in your example wouldn't entirely tell you whether you were in visual or source mode -- just whether or not there was going to be a toolbar.)

Meta: while the Editing Team may eventually pick up work on this work, we are not considering that work to be a prerequisite for concluding work on Phase 1 of the Talk Pages Project (TPP-Phase1).

fi.wiki also wants this feature. When you start to work on it?

There are several hooks in VE. In approximate time order:

desktop+mobiledesktop onlywhenusers
ve.skinTabSetupCompleteThe edit tab(s) have been setup and handlers boundGuidedTour
ve.activationStartThe edit link was clicked and VE has started loadingHides sticky header in Vector2022
mw.libs.ve.addPluginNot a hook. Runs after VE is loaded, but before it is initialized.Anyone trying to register a tool.
ve.activateVE code has loaded, but not necessarily the documentPlanned for deprecation.
ve.wikitextInteractiveA wikitext editor is ready for use, either the full 2017WTE, or the temporary editor 2017WTE shows while loadingExtension:Linter, any wikitext gadget that wants to support 2017WTE
ve.activationCompleteA surface is ready for editing. (nb also fires when switching to/from 2017WTE)Many
ve.toolbarSaveButton.stateChangedThe main save button has been enabled/disabledGuidedTour
ve.saveDialog.stateChangedThe save dialog has been opened or changed panelEdit summary gadgets and TemplateSandbox
ve.deactivateVE has started to closePlanned for deprecation.
ve.deactivationCompleteVE has finished closingMany

For non-article VE integrations, such as DiscussionTools (and also Content Translation, Flow), we should decide if we want to come up with a naming scheme for equivalent hooks where applicable. Ideally we could reuse the hooks and make it up to the user to work out which VE integration fired it (as with the desktop+mobile hooks), however in practice this would required fixing hundreds of gadgets.

Alternatively we could deprecated all of the above hooks, and come up with new platform-agnostic ones that could be migrated to over time.

@Esanders That is helpful for other stuff... but none of that works for discussion tools.

Tested to be sure:
https://pl.wikipedia.org/w/index.php?title=Wikipedysta:Nux/common.js&oldid=70560334#L-14

Results after opening few discussions on my Talk page (also tried switching editors and also no events):

18:14:01.490 Niektóre ciasteczka niewłaściwie wykorzystują zalecany atrybut „SameSite” 51
18:14:01.504 Układ został wymuszony przed pełnym wczytaniem strony. Jeśli arkusze stylów nie są jeszcze wczytane, może spowodować to miganie treści bez nałożonych stylów. TableWrapper.js:54
18:14:02.069 [nuxHookTest] init hooks Dyskusja_wikipedysty:Nux line 10 > injectedScript:1:168
18:14:02.076 This page is using the deprecated ResourceLoader module "jquery.cookie".
Merged into "mediawiki.cookie", use that module instead (T271995) Dyskusja_wikipedysty:Nux line 10 > injectedScript:396:641
18:14:02.120 This page is using the deprecated ResourceLoader module "jquery.ui".
Please use OOUI instead. load.php:730:998
18:14:02.302 Ta strona używa niestandardowej właściwości „zoom”. Rozważ użycie calc() w odpowiednich wartościach właściwości lub użycie „transform” wraz z „transform-origin: 0 0”. Dyskusja_wikipedysty:Nux
18:14:02.589 [table filter] no long and sortable tables found index.php:41:12
18:14:02.650 ext.popups was loaded but everything is disabled Dyskusja_wikipedysty:Nux line 10 > injectedScript:47:454

Notice how [nuxHookTest] init hooks is in the console, but none of the hooks.

Editing an article with VE shows hooks:

...
18:13:33.919 [nuxHookTest] init hooks Oktawa_(interwał) line 10 > injectedScript:1:168
...
18:13:38.147 [nuxHookTest] ve.activationStart Object { arglen: 0 } {} Oktawa_(interwał) line 10 > injectedScript:1:73
18:13:38.629 [nuxHookTest] ve.skinTabSetupComplete Object { arglen: 0 } {} Oktawa_(interwał) line 10 > injectedScript:1:73
18:13:38.655 [nuxHookTest] ve.activate Object { arglen: 0 } {} Oktawa_(interwał) line 10 > injectedScript:1:73
18:13:39.119 [nuxHookTest] ve.activationComplete Object { arglen: 0 }

As I understand below would work, but AFAIK was not merged:

PS: I guess that hook might need some prefix so that simplified toolbars are not modified by gadgets unwillingly.

@Esanders That is helpful for other stuff... but none of that works for discussion tools.

Indeed, which is why I said:

For non-article VE integrations, such as DiscussionTools (and also Content Translation, Flow), we should decide if we want to come up with a naming scheme for equivalent hooks where applicable. ...

My point is we need to be mindful about adding new hooks or changing our existing hooks, as the system in place is already quite messy and confusing, and we don't want to add to that confusion.

The WMDE-TechWish team is currently watching this as part of T341211. Since the last activity here was not that long ago we wonder if there is anything we can help with to make this happen?

Another example an issue with knowing which target is available: knowing if NWE is enabled, as seen in this fix:

https://en.wikipedia.org/w/index.php?title=User%3AMatma_Rex%2Fnwe-nowiki.js&diff=1170527210&oldid=1167396811

Hi. Is there a sane way to wait for the initialization of ve.init.mw.targetFactory? I did do an insane ;) way of waiting for the object in intervals. It works, but would prefer to use something else.

This seems to kind of work after waiting for the targetFactory in small intervals:

	ve.init.mw.targetFactory.on('register', (name) => {
	 	console.log('[discussionToolsExtend]', 'registered: ' + name);
	});

I can then add some tools to the toolbar at least, but it's possible I would miss the emission of the register event. So it seem to be better to wait for ve.init.mw.targetFactory.registry.discussionTools... Unless there is a hook for targetFactory initialization? The mw.hook('ve.loadModules') doesn't seem to fire on talk pages.