mirror of
https://github.com/flarum/core.git
synced 2025-08-10 18:35:56 +02:00
New mentions format, decouple usernames from mentions (#65)
* Convert user mentions to new `@"Display Name"#ID` format * Handle deleted user's mentions * Convert post mentions to `@"Display Name"#pID` format * Handle deleted user's post mentions and deleted posts mentions * Clean display name of `"#{letters}{numbers}` (replace with underscore _) * Adapt integration tests to new mention formats * Use a deleted attribute for user mentions * Introduce cleanDisplayName util * Detect new format with autocomplete * Slug needed on rendering only * Invalidate user mention tag when ID is invalid This used to be implicitly done, when there was a username attribute configured, formatter would check that all attributes are available and if not invalidate. since we now only have `displayname` and `id` attributes which are both available from the regex matching, formatter doesn't implicitly invalidate anymore and therefore validates ANY matches. So we explicitly invalidate the tag when the ID does not match a user. * Allow username mention format with a setting * Add tests for turning setting on/off * Move setting check to tag filter Because the configurator caches, changing the setting only takes effect after the cache is cleared. * fix: showing autocomplete at the right moment * Add dockblocks to explain unparsing process
This commit is contained in:
1
extensions/mentions/js/admin.js
Normal file
1
extensions/mentions/js/admin.js
Normal file
@@ -0,0 +1 @@
|
||||
export * from './src/admin';
|
10
extensions/mentions/js/src/admin/index.js
Normal file
10
extensions/mentions/js/src/admin/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
app.initializers.add('flarum-mentions', function() {
|
||||
app.extensionData
|
||||
.for('flarum-mentions')
|
||||
.registerSetting({
|
||||
setting: 'flarum-mentions.allow_username_format',
|
||||
type: 'boolean',
|
||||
label: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_label'),
|
||||
help: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_text')
|
||||
});
|
||||
});
|
@@ -10,6 +10,7 @@ import KeyboardNavigatable from 'flarum/utils/KeyboardNavigatable';
|
||||
import { truncate } from 'flarum/utils/string';
|
||||
|
||||
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
||||
import cleanDisplayName from './utils/cleanDisplayName';
|
||||
|
||||
export default function addComposerAutocomplete() {
|
||||
const $container = $('<div class="ComposerBody-mentionsDropdownContainer"></div>');
|
||||
@@ -35,6 +36,7 @@ export default function addComposerAutocomplete() {
|
||||
let relMentionStart;
|
||||
let absMentionStart;
|
||||
let typed;
|
||||
let matchTyped;
|
||||
let searchTimeout;
|
||||
|
||||
// We store users returned from an API here to preserve order in which they are returned
|
||||
@@ -74,6 +76,8 @@ export default function addComposerAutocomplete() {
|
||||
|
||||
if (absMentionStart) {
|
||||
typed = lastChunk.substring(relMentionStart).toLowerCase();
|
||||
matchTyped = typed.match(/^"((?:(?!"#).)+)$/);
|
||||
typed = (matchTyped && matchTyped[1]) || typed;
|
||||
|
||||
const makeSuggestion = function(user, replacement, content, className = '') {
|
||||
const username = usernameHelper(user);
|
||||
@@ -116,7 +120,7 @@ export default function addComposerAutocomplete() {
|
||||
if (!userMatches(user)) return;
|
||||
|
||||
suggestions.push(
|
||||
makeSuggestion(user, '@' + user.username(), '', 'MentionsDropdown-user')
|
||||
makeSuggestion(user, `@"${cleanDisplayName(user)}"#${user.id()}`, '', 'MentionsDropdown-user')
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -142,7 +146,7 @@ export default function addComposerAutocomplete() {
|
||||
.forEach(post => {
|
||||
const user = post.user();
|
||||
suggestions.push(
|
||||
makeSuggestion(user, '@' + user.username() + '#' + post.id(), [
|
||||
makeSuggestion(user, `@"${cleanDisplayName(user)}"#p${post.id()}`, [
|
||||
app.translator.trans('flarum-mentions.forum.composer.reply_to_post_text', {number: post.number()}), ' — ',
|
||||
truncate(post.contentPlain(), 200)
|
||||
], 'MentionsDropdown-post')
|
||||
|
@@ -14,12 +14,12 @@ export default function addPostMentionPreviews() {
|
||||
const parentPost = this.attrs.post;
|
||||
const $parentPost = this.$();
|
||||
|
||||
this.$().on('click', '.UserMention, .PostMention', function (e) {
|
||||
this.$().on('click', '.UserMention:not(.UserMention--deleted), .PostMention:not(.PostMention--deleted)', function (e) {
|
||||
m.route.set(this.getAttribute('href'));
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
this.$('.PostMention').each(function() {
|
||||
this.$('.PostMention:not(.PostMention--deleted)').each(function() {
|
||||
const $this = $(this);
|
||||
const id = $this.data('id');
|
||||
let timeout;
|
||||
|
@@ -0,0 +1,3 @@
|
||||
export default function cleanDisplayName(user) {
|
||||
return user.displayName().replace(/"#[a-z]{0,3}[0-9]+/, '_');
|
||||
};
|
@@ -1,9 +1,10 @@
|
||||
import DiscussionControls from 'flarum/utils/DiscussionControls';
|
||||
import EditPostComposer from 'flarum/components/EditPostComposer';
|
||||
import cleanDisplayName from './cleanDisplayName';
|
||||
|
||||
function insertMention(post, composer, quote) {
|
||||
const user = post.user();
|
||||
const mention = '@' + (user ? user.username() : post.number()) + '#' + post.id() + ' ';
|
||||
const mention = `@"${(user && cleanDisplayName(user)) || app.translator.trans('core.lib.username.deleted_text')}"#p${post.id()}`;
|
||||
|
||||
// If the composer is empty, then assume we're starting a new reply.
|
||||
// In which case we don't want the user to have to confirm if they
|
||||
|
@@ -2,14 +2,22 @@ import username from 'flarum/helpers/username';
|
||||
import extractText from 'flarum/utils/extractText';
|
||||
|
||||
export function filterUserMentions(tag) {
|
||||
const user = app.store.getBy('users', 'username', tag.getAttribute('username'));
|
||||
let user;
|
||||
|
||||
if (app.forum.attribute('allowUsernameMentionFormat') && tag.hasAttribute('username'))
|
||||
user = app.store.getBy('users', 'username', tag.getAttribute('username'));
|
||||
else if (tag.hasAttribute('id'))
|
||||
user = app.store.getById('users', tag.getAttribute('id'));
|
||||
|
||||
if (user) {
|
||||
tag.setAttribute('id', user.id());
|
||||
tag.setAttribute('slug', user.slug());
|
||||
tag.setAttribute('displayname', extractText(username(user)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
tag.invalidate();
|
||||
}
|
||||
|
||||
export function filterPostMentions(tag) {
|
||||
|
Reference in New Issue
Block a user