Mithril 2 Update (#52)

Update for Mithril 2

- Please note that PostQuoteButton and AutocompleteDropdown are not Fragments, not Components. Accordingly, they have been moved to the components folder.

Co-authored-by: Matthew Kilgore <tankerkiller125@gmail.com>
Co-authored-by: Franz Liedke <franz@develophp.org>
This commit is contained in:
Alexander Skvortsov 2020-09-23 22:53:46 -04:00 committed by GitHub
parent a48a84fcd0
commit ea56f39a53
11 changed files with 101 additions and 103 deletions

View File

@ -11,14 +11,12 @@ import highlight from 'flarum/helpers/highlight';
import KeyboardNavigatable from 'flarum/utils/KeyboardNavigatable';
import { truncate } from 'flarum/utils/string';
import AutocompleteDropdown from './components/AutocompleteDropdown';
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
export default function addComposerAutocomplete() {
extend(TextEditor.prototype, 'config', function(original, isInitialized) {
if (isInitialized) return;
extend(TextEditor.prototype, 'oncreate', function () {
const $container = $('<div class="ComposerBody-mentionsDropdownContainer"></div>');
const dropdown = new AutocompleteDropdown({items: []});
const dropdown = new AutocompleteDropdown();
const $textarea = this.$('textarea').wrap('<div class="ComposerBody-mentionsWrapper"></div>');
const searched = [];
let mentionStart;
@ -77,7 +75,8 @@ export default function addComposerAutocomplete() {
const makeSuggestion = function(user, replacement, content, className = '') {
const username = usernameHelper(user);
if (typed) {
username.children[0] = highlight(username.children[0], typed);
username.children = [highlight(username.text, typed)];
delete username.text;
}
return (
@ -150,7 +149,7 @@ export default function addComposerAutocomplete() {
}
if (suggestions.length) {
dropdown.props.items = suggestions;
dropdown.items = suggestions;
m.render($container[0], dropdown.render());
dropdown.show();

View File

@ -11,7 +11,7 @@ export default function addMentionedByList() {
Post.prototype.mentionedBy = Model.hasMany('mentionedBy');
extend(CommentPost.prototype, 'footerItems', function(items) {
const post = this.props.post;
const post = this.attrs.post;
const replies = post.mentionedBy();
if (replies && replies.length) {
@ -21,10 +21,8 @@ export default function addMentionedByList() {
.one('transitionend', function() { $(this).hide(); });
};
const config = function(element, isInitialized) {
if (isInitialized) return;
const $this = $(element);
const oncreate = function(vnode) {
const $this = $(vnode.dom);
let timeout;
const $preview = $('<ul class="Dropdown-menu Post-mentionedBy-preview fade"/>');
@ -86,8 +84,7 @@ export default function addMentionedByList() {
const user = reply.user();
return (
<a href={app.route.post(reply)}
config={m.route}
<a route={app.route.post(reply)}
onclick={hidePreview}
data-number={reply.number()}>
{app.session.user === user ? app.translator.trans('flarum-mentions.forum.post.you_text') : username(user)}
@ -107,7 +104,7 @@ export default function addMentionedByList() {
}
items.add('replies',
<div className="Post-mentionedBy" config={config}>
<div className="Post-mentionedBy" oncreate={oncreate}>
<span className="Post-mentionedBy-summary">
{icon('fas fa-reply')}
{app.translator.transChoice('flarum-mentions.forum.post.mentioned_by' + (repliers[0].user() === app.session.user ? '_self' : '') + '_text', names.length, {

View File

@ -4,18 +4,19 @@ import PostPreview from 'flarum/components/PostPreview';
import LoadingIndicator from 'flarum/components/LoadingIndicator';
export default function addPostMentionPreviews() {
extend(CommentPost.prototype, 'config', function() {
const contentHtml = this.props.post.contentHtml();
function addPreviews() {
const contentHtml = this.attrs.post.contentHtml();
if (contentHtml === this.oldPostContentHtml || this.isEditing()) return;
this.oldPostContentHtml = contentHtml;
const parentPost = this.props.post;
const parentPost = this.attrs.post;
const $parentPost = this.$();
this.$('.UserMention, .PostMention').each(function() {
m.route.call(this, this, false, {}, {attrs: {href: this.getAttribute('href')}});
this.$().on('click', '.UserMention, .PostMention', function (e) {
m.route.set(this.getAttribute('href'));
e.preventDefault();
});
this.$('.PostMention').each(function() {
@ -122,5 +123,8 @@ export default function addPostMentionPreviews() {
$(document).on('touchend', hidePreview);
});
});
}
extend(CommentPost.prototype, 'oncreate', addPreviews);
extend(CommentPost.prototype, 'onupdate', addPreviews);
}

View File

@ -1,14 +1,14 @@
import { extend } from 'flarum/extend';
import CommentPost from 'flarum/components/CommentPost';
import PostQuoteButton from './components/PostQuoteButton';
import PostQuoteButton from './fragments/PostQuoteButton';
import selectedText from './utils/selectedText';
export default function addPostQuoteButton() {
extend(CommentPost.prototype, 'config', function(original, isInitialized) {
const post = this.props.post;
extend(CommentPost.prototype, 'oncreate', function() {
const post = this.attrs.post;
if (isInitialized || post.isHidden() || (app.session.user && !post.discussion().canReply())) return;
if (post.isHidden() || (app.session.user && !post.discussion().canReply())) return;
const $postBody = this.$('.Post-body');
@ -16,11 +16,13 @@ export default function addPostQuoteButton() {
// button into it.
const $container = $('<div class="Post-quoteButtonContainer"></div>');
const button = new PostQuoteButton(post);
const handler = function(e) {
setTimeout(() => {
const content = selectedText($postBody);
if (content) {
const button = new PostQuoteButton({post, content});
button.content = content;
m.render($container[0], button.render());
const rects = window.getSelection().getRangeAt(0).getClientRects();

View File

@ -7,16 +7,14 @@ import reply from './utils/reply';
export default function () {
extend(CommentPost.prototype, 'actionItems', function (items) {
const post = this.props.post;
const post = this.attrs.post;
if (post.isHidden() || (app.session.user && !post.discussion().canReply())) return;
items.add('reply',
Button.component({
className: 'Button Button--link',
children: app.translator.trans('flarum-mentions.forum.post.reply_link'),
onclick: () => reply(post)
})
<Button className='Button Button--link' onclick={() => reply(post)}>
{app.translator.trans('flarum-mentions.forum.post.reply_link')}
</Button>
);
});
}

View File

@ -7,7 +7,7 @@ export default class PostMentionedNotification extends Notification {
}
href() {
const notification = this.props.notification;
const notification = this.attrs.notification;
const post = notification.subject();
const content = notification.content();
@ -15,13 +15,13 @@ export default class PostMentionedNotification extends Notification {
}
content() {
const notification = this.props.notification;
const notification = this.attrs.notification;
const user = notification.fromUser();
return app.translator.transChoice('flarum-mentions.forum.notifications.post_mentioned_text', 1, {user});
}
excerpt() {
return truncate(this.props.notification.subject().contentPlain(), 200);
return truncate(this.attrs.notification.subject().contentPlain(), 200);
}
}

View File

@ -1,53 +0,0 @@
import Button from 'flarum/components/Button';
import extract from 'flarum/utils/extract';
import reply from '../utils/reply';
export default class PostQuoteButton extends Button {
view() {
const post = extract(this.props, 'post');
const content = extract(this.props, 'content');
this.props.className = 'Button PostQuoteButton';
this.props.icon = 'fas fa-quote-left';
this.props.children = app.translator.trans('flarum-mentions.forum.post.quote_button');
this.props.onclick = () => {
this.hide();
reply(post, content);
};
this.props.onmousedown = (e) => e.stopPropagation();
return super.view();
}
config(isInitialized) {
if (isInitialized) return;
$(document).on('mousedown', this.hide.bind(this));
}
show(left, top) {
const $this = this.$().show();
const parentOffset = $this.offsetParent().offset();
$this
.css('left', left - parentOffset.left)
.css('top', top - parentOffset.top);
}
showStart(left, top) {
const $this = this.$();
this.show(left, $(window).scrollTop() + top - $this.outerHeight() - 5);
}
showEnd(right, bottom) {
const $this = this.$();
this.show(right - $this.outerWidth(), $(window).scrollTop() + bottom + 5);
}
hide() {
this.$().hide();
}
}

View File

@ -7,18 +7,18 @@ export default class UserMentionedNotification extends Notification {
}
href() {
const post = this.props.notification.subject();
const post = this.attrs.notification.subject();
return app.route.discussion(post.discussion(), post.number());
}
content() {
const user = this.props.notification.fromUser();
const user = this.attrs.notification.fromUser();
return app.translator.trans('flarum-mentions.forum.notifications.user_mentioned_text', {user});
}
excerpt() {
return truncate(this.props.notification.subject().contentPlain(), 200);
return truncate(this.attrs.notification.subject().contentPlain(), 200);
}
}

View File

@ -1,16 +1,15 @@
import Component from 'flarum/Component';
import Fragment from 'flarum/Fragment';
export default class AutocompleteDropdown extends Component {
init() {
this.active = false;
this.index = 0;
this.keyWasJustPressed = false;
}
export default class AutocompleteDropdown extends Fragment {
items = [];
active = false;
index = 0;
keyWasJustPressed = false;
view() {
return (
<ul className="Dropdown-menu MentionsDropdown">
{this.props.items.map(item => <li>{item}</li>)}
{this.items.map(item => <li>{item}</li>)}
</ul>
);
}
@ -71,7 +70,7 @@ export default class AutocompleteDropdown extends Component {
}
if (typeof scrollTop !== 'undefined') {
$dropdown.stop(true).animate({scrollTop}, 100);
$dropdown.stop(true).animate({ scrollTop }, 100);
}
}
}

View File

@ -0,0 +1,53 @@
import Fragment from 'flarum/Fragment';
import icon from 'flarum/helpers/icon';
import reply from '../utils/reply';
export default class PostQuoteButton extends Fragment {
constructor(post) {
super();
this.post = post;
}
view() {
return (
<button class="Button PostQuoteButton" onclick={() => {
reply(this.post, this.content);
}}>
{icon('fas fa-quote-left', { className: 'Button-icon' })}
{app.translator.trans('flarum-mentions.forum.post.quote_button')}
</button>
);
}
show(left, top) {
const $this = this.$().show();
const parentOffset = $this.offsetParent().offset();
$this
.css('left', left - parentOffset.left)
.css('top', top - parentOffset.top);
this.hideHandler = this.hide.bind(this);
$(document).on('mouseup', this.hideHandler);
}
showStart(left, top) {
const $this = this.$();
this.show(left, $(window).scrollTop() + top - $this.outerHeight() - 5);
}
showEnd(right, bottom) {
const $this = this.$();
this.show(right - $this.outerWidth(), $(window).scrollTop() + bottom + 5);
}
hide() {
this.$().hide();
$(document).off('mouseup', this.hideHandler);
}
}

View File

@ -53,16 +53,15 @@ app.initializers.add('flarum-mentions', function() {
});
// Add mentions tab in user profile
app.routes['user.mentions'] = {path: '/u/:username/mentions', component: MentionsUserPage.component()};
app.routes['user.mentions'] = {path: '/u/:username/mentions', component: MentionsUserPage};
extend(UserPage.prototype, 'navItems', function(items) {
const user = this.user;
items.add('mentions',
LinkButton.component({
href: app.route('user.mentions', {username: user.username()}),
name: 'mentions',
children: [app.translator.trans('flarum-mentions.forum.user.mentions_link')],
icon: 'fas fa-at'
}),
}, app.translator.trans('flarum-mentions.forum.user.mentions_link')),
80
);
});