mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-09-17 02:16:54 +00:00
4.0.0-rc14
* Added: New settings in Chat > Appearance for controlling Subscription notices in chat. * Changed: Display an icon next to new subscription notices, like vanilla Twitch is doing now. * Changed: Display in-line moderation actions on subscription notices without associated messages. You can now merge mass gift subs, as well as completely hide subscription notices if you so choose. Please note that you will still see the messages people send with their gift regardless of these new settings.
This commit is contained in:
parent
a8886167a3
commit
24a5cd512f
5 changed files with 453 additions and 44 deletions
|
@ -8,7 +8,8 @@ import Twilight from 'site';
|
|||
import Module from 'utilities/module';
|
||||
|
||||
import RichContent from './rich_content';
|
||||
import { has } from 'src/utilities/object';
|
||||
import { has } from 'utilities/object';
|
||||
import { KEYS } from 'utilities/constants';
|
||||
|
||||
const SUB_TIERS = {
|
||||
1000: 1,
|
||||
|
@ -63,6 +64,8 @@ export default class ChatLine extends Module {
|
|||
this.chat.context.on('changed:chat.badges.hidden', this.updateLines, this);
|
||||
this.chat.context.on('changed:chat.badges.custom-mod', this.updateLines, this);
|
||||
this.chat.context.on('changed:chat.rituals.show', this.updateLines, this);
|
||||
this.chat.context.on('changed:chat.subs.show', this.updateLines, this);
|
||||
this.chat.context.on('changed:chat.subs.compact', this.updateLines, this);
|
||||
this.chat.context.on('changed:chat.rich.enabled', this.updateLines, this);
|
||||
this.chat.context.on('changed:chat.rich.hide-tokens', this.updateLines, this);
|
||||
this.chat.context.on('changed:chat.rich.all-links', this.updateLines, this);
|
||||
|
@ -251,6 +254,7 @@ export default class ChatLine extends Module {
|
|||
this._ffz_show = show;
|
||||
|
||||
return show !== old_show ||
|
||||
state.ffz_expanded !== this.state.ffz_expanded ||
|
||||
//state.renderDebug !== this.state.renderDebug ||
|
||||
props.message !== this.props.message ||
|
||||
props.isCurrentUserModerator !== this.props.isCurrentUserModerator ||
|
||||
|
@ -302,8 +306,30 @@ export default class ChatLine extends Module {
|
|||
rich_content = FFZRichContent && t.chat.pluckRichContent(tokens, msg),
|
||||
bg_css = msg.mentioned && msg.mention_color ? t.parent.inverse_colors.process(msg.mention_color) : null;
|
||||
|
||||
if ( ! this.ffz_user_click_handler )
|
||||
this.ffz_user_click_handler = this.openViewerCard || this.usernameClickHandler; //event => event.ctrlKey ? this.usernameClickHandler(event) : t.viewer_cards.openCard(r, user, event);
|
||||
if ( ! this.ffz_user_click_handler ) {
|
||||
if ( this.props.onUsernameClick )
|
||||
this.ffz_user_click_handler = event => {
|
||||
if ( this.isKeyboardEvent(event) && event.keyCode !== KEYS.Space && event.keyCode !== KEYS.Enter )
|
||||
return;
|
||||
|
||||
const target = event.currentTarget,
|
||||
ds = target && target.dataset;
|
||||
let target_user = user;
|
||||
|
||||
if ( ds && ds.user ) {
|
||||
try {
|
||||
target_user = JSON.parse(ds.user);
|
||||
} catch(err) { /* nothing~! */ }
|
||||
}
|
||||
|
||||
/*if ( event.ctrlKey )
|
||||
t.viewer_cards.openCard(r, target_user, event);
|
||||
else*/
|
||||
this.props.onUsernameClick(target_user.login, 'chat_message', msg.id, target.getBoundingClientRect().bottom);
|
||||
}
|
||||
else
|
||||
this.ffz_user_click_handler = this.openViewerCard || this.usernameClickHandler; //event => event.ctrlKey ? this.usernameClickHandler(event) : t.viewer_cards.openCard(r, user, event);
|
||||
}
|
||||
|
||||
let cls = `chat-line__message${show_class ? ' ffz--deleted-message' : ''}`,
|
||||
out = (tokens.length || ! msg.ffz_type) ? [
|
||||
|
@ -356,47 +382,83 @@ export default class ChatLine extends Module {
|
|||
}, JSON.stringify([tokens, msg.emotes], null, 2))*/
|
||||
] : null;
|
||||
|
||||
if ( msg.ffz_type === 'resub' ) {
|
||||
const plan = msg.sub_plan || {},
|
||||
months = msg.sub_cumulative || msg.sub_months,
|
||||
tier = SUB_TIERS[plan.plan] || 1;
|
||||
if ( msg.ffz_type === 'sub_mystery' ) {
|
||||
const mystery = msg.mystery;
|
||||
if ( mystery )
|
||||
msg.mystery.line = this;
|
||||
|
||||
const sub_msg = t.i18n.tList('chat.sub.main', '%{user} subscribed %{plan}.', {
|
||||
user: e('button', {
|
||||
className: 'chatter-name',
|
||||
onClick: this.ffz_user_click_handler
|
||||
}, e('span', {
|
||||
className: 'tw-c-text-base tw-strong'
|
||||
}, user.userDisplayName)),
|
||||
plan: plan.prime ?
|
||||
t.i18n.t('chat.sub.twitch-prime', 'with Twitch Prime') :
|
||||
t.i18n.t('chat.sub.plan', 'at Tier %{tier}', {tier})
|
||||
const sub_msg = t.i18n.tList('chat.sub.gift', "%{user} is gifting %{count} Tier %{tier} Sub%{count|en_plural} to %{channel}'s community! ", {
|
||||
user: (msg.sub_anon || user.username === 'ananonymousgifter') ?
|
||||
t.i18n.t('chat.sub.anonymous-gifter', 'An anonymous gifter') :
|
||||
e('span', {
|
||||
role: 'button',
|
||||
className: 'chatter-name',
|
||||
onClick: this.ffz_user_click_handler
|
||||
}, e('span', {
|
||||
className: 'tw-c-text-base tw-strong'
|
||||
}, user.userDisplayName)),
|
||||
count: msg.sub_count,
|
||||
tier: SUB_TIERS[msg.sub_plan] || 1,
|
||||
channel: msg.roomLogin
|
||||
});
|
||||
|
||||
if ( msg.sub_share_streak && msg.sub_streak ) {
|
||||
sub_msg.push(t.i18n.t(
|
||||
'chat.sub.cumulative-months',
|
||||
"They've subscribed for %{cumulative} months, currently on a %{streak} month streak!",
|
||||
{
|
||||
cumulative: msg.sub_cumulative,
|
||||
streak: msg.sub_streak
|
||||
}
|
||||
));
|
||||
if ( msg.sub_total === 1 )
|
||||
sub_msg.push(t.i18n.t('chat.sub.gift-first', "It's their first time gifting a Sub in the channel!"));
|
||||
else if ( msg.sub_total > 1 )
|
||||
sub_msg.push(t.i18n.t('chat.sub.gift-total', "They've gifted %{count} Subs in the channel!", {
|
||||
count: msg.sub_total
|
||||
}));
|
||||
|
||||
} else if ( months ) {
|
||||
sub_msg.push(t.i18n.t(
|
||||
'chat.sub.months',
|
||||
"They've subscribed for %{count} months!",
|
||||
{
|
||||
count: months
|
||||
}
|
||||
));
|
||||
if ( ! this.ffz_click_expand )
|
||||
this.ffz_click_expand = () => {
|
||||
this.setState({
|
||||
ffz_expanded: ! this.state.ffz_expanded
|
||||
});
|
||||
}
|
||||
|
||||
let sub_list = null;
|
||||
if( this.state.ffz_expanded && mystery && mystery.recipients && mystery.recipients.length > 0 ) {
|
||||
const the_list = [];
|
||||
for(const x of mystery.recipients) {
|
||||
if ( the_list.length )
|
||||
the_list.push(', ');
|
||||
|
||||
the_list.push(e('span', {
|
||||
role: 'button',
|
||||
className: 'chatter-name',
|
||||
onClick: this.ffz_user_click_handler,
|
||||
'data-user': JSON.stringify(x)
|
||||
}, e('span', {
|
||||
className: 'tw-c-text-base tw-strong'
|
||||
}, x.displayName)));
|
||||
}
|
||||
|
||||
sub_list = e('div', {
|
||||
className: 'tw-mg-t-05 tw-border-t tw-pd-t-05 tw-c-text-alt-2'
|
||||
}, the_list);
|
||||
}
|
||||
|
||||
|
||||
cls = 'user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--subscribe-line';
|
||||
cls = 'user-notice-line tw-pd-y-05 ffz--subscribe-line';
|
||||
out = [
|
||||
e('div', {className: 'tw-c-text-alt-2'}, sub_msg),
|
||||
e('div', {
|
||||
className: 'tw-flex tw-c-text-alt-2',
|
||||
onClick: this.ffz_click_expand
|
||||
}, [
|
||||
t.chat.context.get('chat.subs.compact') ? null :
|
||||
e('figure', {
|
||||
className: `ffz-i-star${msg.sub_anon ? '-empty' : ''} tw-mg-r-05`
|
||||
}),
|
||||
e('div', null, [
|
||||
(out || msg.sub_anon) ? null : t.actions.renderInline(msg, this.props.showModerationIcons, u, r, e),
|
||||
sub_msg
|
||||
]),
|
||||
mystery ? e('div', {
|
||||
className: 'tw-mg-l-05 tw-border-l tw-pd-l-05 ffz--sub-expando'
|
||||
}, e('figure', {
|
||||
className: `ffz-i-${this.state.ffz_expanded ? 'down' : 'right'}-dir tw-pd-y-1`
|
||||
})) : null
|
||||
]),
|
||||
sub_list,
|
||||
out && e('div', {
|
||||
className: 'chat-line--inline chat-line__message',
|
||||
'data-room-id': this.props.channelID,
|
||||
|
@ -406,12 +468,130 @@ export default class ChatLine extends Module {
|
|||
}, out)
|
||||
];
|
||||
|
||||
} else if ( msg.ffz_type === 'sub_gift' ) {
|
||||
const plan = msg.sub_plan || {},
|
||||
tier = SUB_TIERS[plan.plan] || 1;
|
||||
|
||||
const sub_msg = t.i18n.tList('chat.sub.mystery', '%{user} gifted a %{plan} Sub to %{recipient}!', {
|
||||
user: (msg.sub_anon || user.username === 'ananonymousgifter') ?
|
||||
t.i18n.t('chat.sub.anonymous-gifter', 'An anonymous gifter') :
|
||||
e('span', {
|
||||
role: 'button',
|
||||
className: 'chatter-name',
|
||||
onClick: this.ffz_user_click_handler
|
||||
}, e('span', {
|
||||
className: 'tw-c-text-base tw-strong'
|
||||
}, user.userDisplayName)),
|
||||
plan: plan.plan === 'custom' ? '' :
|
||||
t.i18n.t('chat.sub.gift-plan', 'Tier %{tier}', {tier}),
|
||||
recipient: e('span', {
|
||||
role: 'button',
|
||||
className: 'chatter-name',
|
||||
onClick: this.ffz_user_click_handler,
|
||||
'data-user': JSON.stringify(msg.sub_recipient)
|
||||
}, e('span', {
|
||||
className: 'tw-c-text-base tw-strong'
|
||||
}, msg.sub_recipient.displayName))
|
||||
});
|
||||
|
||||
if ( msg.sub_total === 1 )
|
||||
sub_msg.push(t.i18n.t('chat.sub.gift-first', "It's their first time gifting a Sub in the channel!"));
|
||||
else if ( msg.sub_total > 1 )
|
||||
sub_msg.push(t.i18n.t('chat.sub.gift-total', "They've gifted %{count} Subs in the channel!", {
|
||||
count: msg.sub_total
|
||||
}));
|
||||
|
||||
cls = 'user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--subscribe-line';
|
||||
out = [
|
||||
e('div', {className: 'tw-flex tw-c-text-alt-2'}, [
|
||||
t.chat.context.get('chat.subs.compact') ? null :
|
||||
e('figure', {
|
||||
className: 'ffz-i-star tw-mg-r-05'
|
||||
}),
|
||||
e('div', null, [
|
||||
(out || msg.sub_anon) ? null : t.actions.renderInline(msg, this.props.showModerationIcons, u, r, e),
|
||||
sub_msg
|
||||
])
|
||||
]),
|
||||
out && e('div', {
|
||||
className: 'chat-line--inline chat-line__message',
|
||||
'data-room-id': this.props.channelID,
|
||||
'data-room': room,
|
||||
'data-user-id': user.userID,
|
||||
'data-user': user.userLogin && user.userLogin.toLowerCase(),
|
||||
}, out)
|
||||
];
|
||||
|
||||
} else if ( msg.ffz_type === 'resub' ) {
|
||||
const months = msg.sub_cumulative || msg.sub_months,
|
||||
setting = t.chat.context.get('chat.subs.show');
|
||||
|
||||
if ( setting === 3 || (setting === 1 && out && months > 1) || (setting === 2 && months > 1) ) {
|
||||
const plan = msg.sub_plan || {},
|
||||
tier = SUB_TIERS[plan.plan] || 1;
|
||||
|
||||
const sub_msg = t.i18n.tList('chat.sub.main', '%{user} subscribed %{plan}. ', {
|
||||
user: e('span', {
|
||||
role: 'button',
|
||||
className: 'chatter-name',
|
||||
onClick: this.ffz_user_click_handler
|
||||
}, e('span', {
|
||||
className: 'tw-c-text-base tw-strong'
|
||||
}, user.userDisplayName)),
|
||||
plan: plan.prime ?
|
||||
t.i18n.t('chat.sub.twitch-prime', 'with Twitch Prime') :
|
||||
t.i18n.t('chat.sub.plan', 'at Tier %{tier}', {tier})
|
||||
});
|
||||
|
||||
if ( msg.sub_share_streak && msg.sub_streak > 1 ) {
|
||||
sub_msg.push(t.i18n.t(
|
||||
'chat.sub.cumulative-months',
|
||||
"They've subscribed for %{cumulative} months, currently on a %{streak} month streak!",
|
||||
{
|
||||
cumulative: msg.sub_cumulative,
|
||||
streak: msg.sub_streak
|
||||
}
|
||||
));
|
||||
|
||||
} else if ( months > 1 ) {
|
||||
sub_msg.push(t.i18n.t(
|
||||
'chat.sub.months',
|
||||
"They've subscribed for %{count} months!",
|
||||
{
|
||||
count: months
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
cls = 'user-notice-line tw-pd-y-05 tw-pd-r-2 ffz--subscribe-line';
|
||||
out = [
|
||||
e('div', {className: 'tw-flex tw-c-text-alt-2'}, [
|
||||
t.chat.context.get('chat.subs.compact') ? null :
|
||||
e('figure', {
|
||||
className: `ffz-i-${plan.prime ? 'crown' : 'star'} tw-mg-r-05`
|
||||
}),
|
||||
e('div', null, [
|
||||
out ? null : t.actions.renderInline(msg, this.props.showModerationIcons, u, r, e),
|
||||
sub_msg
|
||||
])
|
||||
]),
|
||||
out && e('div', {
|
||||
className: 'chat-line--inline chat-line__message',
|
||||
'data-room-id': this.props.channelID,
|
||||
'data-room': room,
|
||||
'data-user-id': user.userID,
|
||||
'data-user': user.userLogin && user.userLogin.toLowerCase(),
|
||||
}, out)
|
||||
];
|
||||
}
|
||||
|
||||
} else if ( msg.ffz_type === 'ritual' && t.chat.context.get('chat.rituals.show') ) {
|
||||
let system_msg;
|
||||
if ( msg.ritual === 'new_chatter' )
|
||||
system_msg = e('div', {className: 'tw-c-text-alt-2'}, [
|
||||
t.i18n.tList('chat.ritual', '%{user} is new here. Say hello!', {
|
||||
user: e('button', {
|
||||
user: e('span', {
|
||||
role: 'button',
|
||||
className: 'chatter-name',
|
||||
onClick: this.ffz_user_click_handler
|
||||
}, e('span', {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue