Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slack-style tag plugin (Resolves #1962) #2038

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

Conversation

matthew-carroll
Copy link
Contributor

This PR adds a new plugin which brings Slack-style tagging to Super Editor. Slack-style tagging is very similar to our existing "stable tag" plugin. However, Slack tagging appears to consider everything between the trigger character and the caret as the search term. Additionally, Slack tokenizes the search term and then matches names token by token.

The following videos demonstrate the plugin in action. The colors in these demos are optional and controllable. We use colors in the video to show exactly where the composing and stable attributions are applied.

Screen.Recording.2024-05-25.at.2.50.00.PM.mov
Screen.Recording.2024-05-25.at.2.50.54.PM.mov

@matthew-carroll matthew-carroll changed the title Slack-style tag plugin Slack-style tag plugin (Resolves #1962) May 25, 2024
@matthew-carroll
Copy link
Contributor Author

CC @BazinC @josephrcox

@matthew-carroll
Copy link
Contributor Author

A couple change requests have been made:

  • Don't show the popover when there aren't any results
  • Cancel the composition if a space immediately follows the trigger

@matthew-carroll
Copy link
Contributor Author

Video of latest two modifications

Screen.Recording.2024-05-27.at.7.48.23.PM.mov

@BazinC
Copy link
Contributor

BazinC commented May 29, 2024

Thank you @matthew-carroll ! I'll try it in a bit :)

@BazinC
Copy link
Contributor

BazinC commented Jun 8, 2024

@matthew-carroll @josephrcox can we add to the specs:

Search should not happen if @ is in the middle of the word (i.e search should happen if @ predecessor is a whitespace)

Otherwise user typing a mail address would have the search popup opening after tappin @.

// FIXME: Use a transaction to bundle these changes so order doesn't matter.
if (removeComposingAttributionCommand != null) {
executor.executeCommand(removeComposingAttributionCommand);
print("Attributions immediately after removing composing attribution:");
Copy link
Contributor

Choose a reason for hiding this comment

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

There are a few print statements that need to be changed to editorSlackTagsLoga

// to reflect the deletions.
final composer = editContext.find<MutableDocumentComposer>(Editor.composerKey);

final baseBeforeDeletions = composer.selection!.base;
Copy link
Contributor

@BazinC BazinC Jul 22, 2024

Choose a reason for hiding this comment

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

Selection should be checked if null before reading base.
Otherwise a scenario like editor.execute([ClearSelectionRequest)]) will throw an exception, letting the editor stuck.

Comment on lines +1019 to +1023
case SelectionChangeType.expandSelection:
throw AssertionError(
"A collapsed selection reported a SelectionChangeType for an expanded selection: ${selectionChangeEvent.changeType}\n${selectionChangeEvent.newSelection}");
case SelectionChangeType.clearSelection:
throw AssertionError("Expected a collapsed selection but there was no selection.");
Copy link
Contributor

Choose a reason for hiding this comment

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

I would change these thrown errors with logs, at least for the beginning. For instance if you try the plugin on android with drag handles, moving the handle will throw here (SelectionChangeType.pushCaret). Editor is then stuck.

Comment on lines +752 to +756
if (composer.selection == null || !composer.selection!.isCollapsed) {
// We only tag when the selection is collapsed. Our selection is null or expanded. Return.
return null;
}
final selectionPosition = composer.selection!.extent;
Copy link
Contributor

Choose a reason for hiding this comment

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

same as above

Suggested change
if (composer.selection == null || !composer.selection!.isCollapsed) {
// We only tag when the selection is collapsed. Our selection is null or expanded. Return.
return null;
}
final selectionPosition = composer.selection!.extent;
final selection = composer.selection;
if (selection == null) {
return null;
}
if (!selection.isCollapsed) {
// We only tag when the selection is collapsed or expanded. Return.
return null;
}
final selectionPosition = selection.extent;

/// The key used to access the [SlackTagIndex] in an attached [Editor].
static const slackTagIndexKey = "slackTagIndex";

static const _trigger = "@";
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a way to provide another trigger if the user wants to

Comment on lines +37 to +43
_requestHandlers = <EditRequestHandler>[
(request) =>
request is FillInComposingSlackTagRequest ? FillInComposingSlackTagCommand(_trigger, request.tag) : null,
(request) => request is CancelComposingSlackTagRequest //
? const CancelComposingSlackTagCommand()
: null,
];
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we think of letting package user provide custom handlers? Let's say in the example the popover enable the end user to pick not only a username, but also different kind of entity. The package user would use the plugin to get the composing value from the tagIndex, and send custom request to commit not only user tags.

Comment on lines +1097 to +1103
case SelectionChangeType.placeCaret:
case SelectionChangeType.pushCaret:
case SelectionChangeType.collapseSelection:
throw AssertionError(
"An expanded selection reported a SelectionChangeType for a collapsed selection: ${selectionChangeEvent.changeType}\n${selectionChangeEvent.newSelection}");
case SelectionChangeType.clearSelection:
throw AssertionError("Expected a collapsed selection but there was no selection.");
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

Comment on lines +1480 to +1482
/// An attribution for a slack tag that was previously being composed, but was then
/// abandoned (not cancelled) without committing it.
const slackTagUnboundAttribution = NamedAttribution("slack-tag-unbound");
Copy link
Contributor

Choose a reason for hiding this comment

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

unused

@matthew-carroll
Copy link
Contributor Author

@BazinC - As mentioned on our recent call, what I'm looking to get from you is a list of UX requirements to consider this feature done. Doing a per-line code review isn't relevant until this code actually does what's needed.

Can you please provide the list of UX things this plugin needs to do, which it currently doesn't do?

@BazinC
Copy link
Contributor

BazinC commented Jul 23, 2024

Hello @matthew-carroll, I understand this PR is not finished but I tried it and noticed bugs not related to any specific UX requirements so I found relevant to report them now, with repro steps and point the involved lines of code.

Furthermore, I think the plugin could be more open to let Super Editor package users do more than it is possible in the current state.

Requirements:

  • Having the possibility to use a different trigger, not only @ (not possible in the current state. see Slack-style tag plugin (Resolves #1962) #2038 (comment))

  • Search should not happen in the middle of a word (see Slack-style tag plugin (Resolves #1962) #2038 (comment))

  • Fix Android bug (currently crashing. see Slack-style tag plugin (Resolves #1962) #2038 (comment))

  • Null bug fixed (currently crashing if editor executes clear selection. see Slack-style tag plugin (Resolves #1962) #2038 (comment))

  • Finally, the plugin in its current state can only handle request like "commit a username string" (FillInComposingSlackTagRequest/Command, which commits text with slackTagAttribution.) What if, like in slack, we would like to commit a "team" (a group of users). Or anything else? What if we want to give more info to the text attribution (like user id, avatar url..)?
    Do you see what I mean? There is a lot of possibilities. I cannot provide specific UX requirement for that.
    I think the plugin is great to find, manage and expose composing tag, but it should not be exclusively responsible of what can be committed. That is why I proposed to make the plugin to expose its SlackTagIndex and accept custom request handlers.

@matthew-carroll
Copy link
Contributor Author

Note: We want to support triggers of both arbitrary content and arbitrary character count.

We'll further discuss what team commitment means.

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.

2 participants