mirror of
https://github.com/flarum/core.git
synced 2025-08-14 04:14:06 +02:00
update: forum/components/DiscussionListItem
This commit is contained in:
committed by
Franz Liedke
parent
9793c10610
commit
60c3f23667
@@ -8,7 +8,6 @@ import ItemList from '../../common/utils/ItemList';
|
|||||||
import abbreviateNumber from '../../common/utils/abbreviateNumber';
|
import abbreviateNumber from '../../common/utils/abbreviateNumber';
|
||||||
import Dropdown from '../../common/components/Dropdown';
|
import Dropdown from '../../common/components/Dropdown';
|
||||||
import TerminalPost from './TerminalPost';
|
import TerminalPost from './TerminalPost';
|
||||||
import PostPreview from './PostPreview';
|
|
||||||
import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
|
import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
|
||||||
import DiscussionControls from '../utils/DiscussionControls';
|
import DiscussionControls from '../utils/DiscussionControls';
|
||||||
import slidable from '../utils/slidable';
|
import slidable from '../utils/slidable';
|
||||||
@@ -26,7 +25,9 @@ import { escapeRegExp } from 'lodash-es';
|
|||||||
* - `params`
|
* - `params`
|
||||||
*/
|
*/
|
||||||
export default class DiscussionListItem extends Component {
|
export default class DiscussionListItem extends Component {
|
||||||
init() {
|
oninit(vnode) {
|
||||||
|
super.oninit(vnode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up a subtree retainer so that the discussion will not be redrawn
|
* Set up a subtree retainer so that the discussion will not be redrawn
|
||||||
* unless new data comes in.
|
* unless new data comes in.
|
||||||
@@ -34,7 +35,7 @@ export default class DiscussionListItem extends Component {
|
|||||||
* @type {SubtreeRetainer}
|
* @type {SubtreeRetainer}
|
||||||
*/
|
*/
|
||||||
this.subtree = new SubtreeRetainer(
|
this.subtree = new SubtreeRetainer(
|
||||||
() => this.props.discussion.freshness,
|
() => this.attrs.discussion.freshness,
|
||||||
() => {
|
() => {
|
||||||
const time = app.session.user && app.session.user.markedAllAsReadAt();
|
const time = app.session.user && app.session.user.markedAllAsReadAt();
|
||||||
return time && time.getTime();
|
return time && time.getTime();
|
||||||
@@ -43,37 +44,33 @@ export default class DiscussionListItem extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs() {
|
elementAttrs() {
|
||||||
return {
|
return {
|
||||||
className: classList([
|
className: classList([
|
||||||
'DiscussionListItem',
|
'DiscussionListItem',
|
||||||
this.active() ? 'active' : '',
|
this.active() ? 'active' : '',
|
||||||
this.props.discussion.isHidden() ? 'DiscussionListItem--hidden' : '',
|
this.attrs.discussion.isHidden() ? 'DiscussionListItem--hidden' : '',
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view(vnode) {
|
||||||
const retain = this.subtree.retain();
|
const discussion = this.attrs.discussion;
|
||||||
|
|
||||||
if (retain) return retain;
|
|
||||||
|
|
||||||
const discussion = this.props.discussion;
|
|
||||||
const user = discussion.user();
|
const user = discussion.user();
|
||||||
const isUnread = discussion.isUnread();
|
const isUnread = discussion.isUnread();
|
||||||
const isRead = discussion.isRead();
|
const isRead = discussion.isRead();
|
||||||
const showUnread = !this.showRepliesCount() && isUnread;
|
const showUnread = !this.showRepliesCount() && isUnread;
|
||||||
let jumpTo = 0;
|
let jumpTo = 0;
|
||||||
const controls = DiscussionControls.controls(discussion, this).toArray();
|
const controls = DiscussionControls.controls(discussion, this).toArray();
|
||||||
const attrs = this.attrs();
|
const attrs = this.elementAttrs();
|
||||||
|
|
||||||
if (this.props.params.q) {
|
if (this.attrs.params.q) {
|
||||||
const post = discussion.mostRelevantPost();
|
const post = discussion.mostRelevantPost();
|
||||||
if (post) {
|
if (post) {
|
||||||
jumpTo = post.number();
|
jumpTo = post.number();
|
||||||
}
|
}
|
||||||
|
|
||||||
const phrase = escapeRegExp(this.props.params.q);
|
const phrase = escapeRegExp(this.attrs.params.q);
|
||||||
this.highlightRegExp = new RegExp(phrase + '|' + phrase.trim().replace(/\s+/g, '|'), 'gi');
|
this.highlightRegExp = new RegExp(phrase + '|' + phrase.trim().replace(/\s+/g, '|'), 'gi');
|
||||||
} else {
|
} else {
|
||||||
jumpTo = Math.min(discussion.lastPostNumber(), (discussion.lastReadPostNumber() || 0) + 1);
|
jumpTo = Math.min(discussion.lastPostNumber(), (discussion.lastReadPostNumber() || 0) + 1);
|
||||||
@@ -82,12 +79,14 @@ export default class DiscussionListItem extends Component {
|
|||||||
return (
|
return (
|
||||||
<div {...attrs}>
|
<div {...attrs}>
|
||||||
{controls.length
|
{controls.length
|
||||||
? Dropdown.component({
|
? Dropdown.component(
|
||||||
icon: 'fas fa-ellipsis-v',
|
{
|
||||||
children: controls,
|
icon: 'fas fa-ellipsis-v',
|
||||||
className: 'DiscussionListItem-controls',
|
className: 'DiscussionListItem-controls',
|
||||||
buttonClassName: 'Button Button--icon Button--flat Slidable-underneath Slidable-underneath--right',
|
buttonClassName: 'Button Button--icon Button--flat Slidable-underneath Slidable-underneath--right',
|
||||||
})
|
},
|
||||||
|
controls
|
||||||
|
)
|
||||||
: ''}
|
: ''}
|
||||||
|
|
||||||
<a
|
<a
|
||||||
@@ -131,8 +130,8 @@ export default class DiscussionListItem extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
config(isInitialized) {
|
oncreate(vnode) {
|
||||||
if (isInitialized) return;
|
super.oncreate(vnode);
|
||||||
|
|
||||||
// If we're on a touch device, set up the discussion row to be slidable.
|
// If we're on a touch device, set up the discussion row to be slidable.
|
||||||
// This allows the user to drag the row to either side of the screen to
|
// This allows the user to drag the row to either side of the screen to
|
||||||
@@ -144,6 +143,12 @@ export default class DiscussionListItem extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onbeforeupdate(vnode, old) {
|
||||||
|
super.onbeforeupdate(vnode, old);
|
||||||
|
|
||||||
|
return this.subtree.needsRebuild();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether or not the discussion is currently being viewed.
|
* Determine whether or not the discussion is currently being viewed.
|
||||||
*
|
*
|
||||||
@@ -152,7 +157,7 @@ export default class DiscussionListItem extends Component {
|
|||||||
active() {
|
active() {
|
||||||
const idParam = m.route.param('id');
|
const idParam = m.route.param('id');
|
||||||
|
|
||||||
return idParam && idParam.split('-')[0] === this.props.discussion.id();
|
return idParam && idParam.split('-')[0] === this.attrs.discussion.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,7 +168,7 @@ export default class DiscussionListItem extends Component {
|
|||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
*/
|
*/
|
||||||
showFirstPost() {
|
showFirstPost() {
|
||||||
return ['newest', 'oldest'].indexOf(this.props.params.sort) !== -1;
|
return ['newest', 'oldest'].indexOf(this.attrs.params.sort) !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -173,14 +178,14 @@ export default class DiscussionListItem extends Component {
|
|||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
*/
|
*/
|
||||||
showRepliesCount() {
|
showRepliesCount() {
|
||||||
return this.props.params.sort === 'replies';
|
return this.attrs.params.sort === 'replies';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark the discussion as read.
|
* Mark the discussion as read.
|
||||||
*/
|
*/
|
||||||
markAsRead() {
|
markAsRead() {
|
||||||
const discussion = this.props.discussion;
|
const discussion = this.attrs.discussion;
|
||||||
|
|
||||||
if (discussion.isUnread()) {
|
if (discussion.isUnread()) {
|
||||||
discussion.save({ lastReadPostNumber: discussion.lastPostNumber() });
|
discussion.save({ lastReadPostNumber: discussion.lastPostNumber() });
|
||||||
@@ -197,8 +202,8 @@ export default class DiscussionListItem extends Component {
|
|||||||
infoItems() {
|
infoItems() {
|
||||||
const items = new ItemList();
|
const items = new ItemList();
|
||||||
|
|
||||||
if (this.props.params.q) {
|
if (this.attrs.params.q) {
|
||||||
const post = this.props.discussion.mostRelevantPost() || this.props.discussion.firstPost();
|
const post = this.attrs.discussion.mostRelevantPost() || this.attrs.discussion.firstPost();
|
||||||
|
|
||||||
if (post && post.contentType() === 'comment') {
|
if (post && post.contentType() === 'comment') {
|
||||||
const excerpt = highlight(post.contentPlain(), this.highlightRegExp, 175);
|
const excerpt = highlight(post.contentPlain(), this.highlightRegExp, 175);
|
||||||
@@ -208,7 +213,7 @@ export default class DiscussionListItem extends Component {
|
|||||||
items.add(
|
items.add(
|
||||||
'terminalPost',
|
'terminalPost',
|
||||||
TerminalPost.component({
|
TerminalPost.component({
|
||||||
discussion: this.props.discussion,
|
discussion: this.attrs.discussion,
|
||||||
lastPost: !this.showFirstPost(),
|
lastPost: !this.showFirstPost(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user