|
|
@@ -69,93 +69,6 @@ export default class MentionUI extends Plugin {
|
|
|
this._mentionsConfigurations = new Map();
|
|
|
|
|
|
editor.config.define( 'mention', { feeds: [] } );
|
|
|
-
|
|
|
- this._handleSelectionDebounced = debounce( ( evt, data ) => {
|
|
|
- const matched = data.matched;
|
|
|
-
|
|
|
- const selection = editor.model.document.selection;
|
|
|
-
|
|
|
- const focus = selection.focus;
|
|
|
-
|
|
|
- // The text watcher listens only to changed range in selection - so the selection attributes are not yet available
|
|
|
- // and you cannot use selection.hasAttribute( 'mention' ) just yet.
|
|
|
- // See https://github.com/ckeditor/ckeditor5-engine/issues/1723.
|
|
|
- const hasMention = focus.textNode && focus.textNode.hasAttribute( 'mention' );
|
|
|
-
|
|
|
- const nodeBefore = focus.nodeBefore;
|
|
|
-
|
|
|
- if ( hasMention || nodeBefore && nodeBefore.is( 'text' ) && nodeBefore.hasAttribute( 'mention' ) ) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const { feedText, marker } = matched;
|
|
|
-
|
|
|
- const matchedTextLength = marker.length + feedText.length;
|
|
|
-
|
|
|
- // Create a marker range.
|
|
|
- const start = focus.getShiftedBy( -matchedTextLength );
|
|
|
- const end = focus.getShiftedBy( -feedText.length );
|
|
|
-
|
|
|
- const markerRange = editor.model.createRange( start, end );
|
|
|
-
|
|
|
- let mentionMarker;
|
|
|
-
|
|
|
- if ( editor.model.markers.has( 'mention' ) ) {
|
|
|
- mentionMarker = editor.model.markers.get( 'mention' );
|
|
|
- } else {
|
|
|
- mentionMarker = editor.model.change( writer => writer.addMarker( 'mention', {
|
|
|
- range: markerRange,
|
|
|
- usingOperation: false,
|
|
|
- affectsData: false
|
|
|
- } ) );
|
|
|
- }
|
|
|
-
|
|
|
- this._getFeed( marker, feedText )
|
|
|
- .catch( error => {
|
|
|
- if ( error.feedDiscarded ) {
|
|
|
- // Do nothing on discarded feeds as they might come after another one was requested.
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // At this point something bad happened - most likely unreachable host or some feed callback error.
|
|
|
- // So cleanup marker, remove the UI and...
|
|
|
- this._hideUIAndRemoveMarker();
|
|
|
-
|
|
|
- const notification = editor.plugins.get( Notification );
|
|
|
- const t = editor.locale.t;
|
|
|
-
|
|
|
- // ...show warning notification.
|
|
|
- notification.showWarning( t( 'Could not obtain mention autocomplete feed.' ), {
|
|
|
- title: t( 'Requesting feed failed' ),
|
|
|
- namespace: 'mention'
|
|
|
- } );
|
|
|
- } )
|
|
|
- .then( feed => {
|
|
|
- if ( !feed ) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if ( !this.editor.model.markers.has( 'mention' ) ) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Remove old entries.
|
|
|
- this._items.clear();
|
|
|
-
|
|
|
- for ( const feedItem of feed ) {
|
|
|
- const item = typeof feedItem != 'object' ? { id: feedItem, text: feedItem } : feedItem;
|
|
|
-
|
|
|
- this._items.add( { item, marker } );
|
|
|
- }
|
|
|
-
|
|
|
- if ( this._items.length ) {
|
|
|
- this._showUI( mentionMarker );
|
|
|
- } else {
|
|
|
- // Do not show empty mention UI.
|
|
|
- this._hideUIAndRemoveMarker();
|
|
|
- }
|
|
|
- } );
|
|
|
- }, 100 );
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -393,9 +306,89 @@ export default class MentionUI extends Plugin {
|
|
|
|
|
|
const watcher = new TextWatcher( editor, createTestCallback( marker, minimumCharacters ), createTextMatcher( marker ) );
|
|
|
|
|
|
- watcher.on( 'matched', ( evt, data ) => {
|
|
|
- this._handleSelectionDebounced( evt, data );
|
|
|
- } );
|
|
|
+ watcher.on( 'matched', debounce( ( evt, data ) => {
|
|
|
+ const selection = editor.model.document.selection;
|
|
|
+ const focus = selection.focus;
|
|
|
+
|
|
|
+ // The text watcher listens only to changed range in selection - so the selection attributes are not yet available
|
|
|
+ // and you cannot use selection.hasAttribute( 'mention' ) just yet.
|
|
|
+ // See https://github.com/ckeditor/ckeditor5-engine/issues/1723.
|
|
|
+ const hasMention = focus.textNode && focus.textNode.hasAttribute( 'mention' );
|
|
|
+
|
|
|
+ const nodeBefore = focus.nodeBefore;
|
|
|
+
|
|
|
+ if ( hasMention || nodeBefore && nodeBefore.is( 'text' ) && nodeBefore.hasAttribute( 'mention' ) ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { feedText, marker } = data.matched;
|
|
|
+
|
|
|
+ const matchedTextLength = marker.length + feedText.length;
|
|
|
+
|
|
|
+ // Create a marker range.
|
|
|
+ const start = focus.getShiftedBy( -matchedTextLength );
|
|
|
+ const end = focus.getShiftedBy( -feedText.length );
|
|
|
+
|
|
|
+ const markerRange = editor.model.createRange( start, end );
|
|
|
+
|
|
|
+ let mentionMarker;
|
|
|
+
|
|
|
+ if ( editor.model.markers.has( 'mention' ) ) {
|
|
|
+ mentionMarker = editor.model.markers.get( 'mention' );
|
|
|
+ } else {
|
|
|
+ mentionMarker = editor.model.change( writer => writer.addMarker( 'mention', {
|
|
|
+ range: markerRange,
|
|
|
+ usingOperation: false,
|
|
|
+ affectsData: false
|
|
|
+ } ) );
|
|
|
+ }
|
|
|
+
|
|
|
+ this._getFeed( marker, feedText )
|
|
|
+ .catch( error => {
|
|
|
+ if ( error.feedDiscarded ) {
|
|
|
+ // Do nothing on discarded feeds as they might come after another one was requested.
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // At this point something bad happened - most likely unreachable host or some feed callback error.
|
|
|
+ // So cleanup marker, remove the UI and...
|
|
|
+ this._hideUIAndRemoveMarker();
|
|
|
+
|
|
|
+ const notification = editor.plugins.get( Notification );
|
|
|
+ const t = editor.locale.t;
|
|
|
+
|
|
|
+ // ...show warning notification.
|
|
|
+ notification.showWarning( t( 'Could not obtain mention autocomplete feed.' ), {
|
|
|
+ title: t( 'Requesting feed failed' ),
|
|
|
+ namespace: 'mention'
|
|
|
+ } );
|
|
|
+ } )
|
|
|
+ .then( feed => {
|
|
|
+ if ( !feed ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( !this.editor.model.markers.has( 'mention' ) ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Remove old entries.
|
|
|
+ this._items.clear();
|
|
|
+
|
|
|
+ for ( const feedItem of feed ) {
|
|
|
+ const item = typeof feedItem != 'object' ? { id: feedItem, text: feedItem } : feedItem;
|
|
|
+
|
|
|
+ this._items.add( { item, marker } );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( this._items.length ) {
|
|
|
+ this._showUI( mentionMarker );
|
|
|
+ } else {
|
|
|
+ // Do not show empty mention UI.
|
|
|
+ this._hideUIAndRemoveMarker();
|
|
|
+ }
|
|
|
+ } );
|
|
|
+ }, 100 ) );
|
|
|
|
|
|
watcher.on( 'unmatched', () => {
|
|
|
this._hideUIAndRemoveMarker();
|