mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-08 23:30:53 +00:00
4.20.30
* Added: Support for Twitch's native chat replies style. * Added: Option to display in-line actions on hover. * Added: Option for changing the current replies style, including a choice to disable replies. * Fixed: Hover styling for elements including rich chat embeds due to a removed CSS class.
This commit is contained in:
parent
c48423a7b2
commit
8fb51dc06b
17 changed files with 160 additions and 48 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"author": "Dan Salvato LLC",
|
"author": "Dan Salvato LLC",
|
||||||
"version": "4.20.29",
|
"version": "4.20.30",
|
||||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -484,11 +484,16 @@ export default class Actions extends Module {
|
||||||
const u = site.getUser(),
|
const u = site.getUser(),
|
||||||
r = {id: line.props.channelID, login: room};
|
r = {id: line.props.channelID, login: room};
|
||||||
|
|
||||||
|
const has_replies = line.chatRepliesTreatment ? line.chatRepliesTreatment !== 'control' : false,
|
||||||
|
can_replies = has_replies && ! msg.deleted && ! line.props.disableReplyClick,
|
||||||
|
can_reply = can_replies && u.login !== msg.user?.login && ! msg.reply;
|
||||||
|
|
||||||
msg.roomId = r.id;
|
msg.roomId = r.id;
|
||||||
|
|
||||||
if ( u ) {
|
if ( u ) {
|
||||||
u.moderator = line.props.isCurrentUserModerator;
|
u.moderator = line.props.isCurrentUserModerator;
|
||||||
u.staff = line.props.isCurrentUserStaff;
|
u.staff = line.props.isCurrentUserStaff;
|
||||||
|
u.can_reply = this.parent.context.get('chat.replies.style') === 2 && can_reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
const current_level = this.getUserLevel(r, u),
|
const current_level = this.getUserLevel(r, u),
|
||||||
|
@ -629,6 +634,7 @@ export default class Actions extends Module {
|
||||||
let ap = data.appearance || {};
|
let ap = data.appearance || {};
|
||||||
const disp = data.display || {},
|
const disp = data.display || {},
|
||||||
keys = disp.keys,
|
keys = disp.keys,
|
||||||
|
hover = disp.hover,
|
||||||
act = this.actions[data.action];
|
act = this.actions[data.action];
|
||||||
|
|
||||||
if ( ! act || disp.disabled ||
|
if ( ! act || disp.disabled ||
|
||||||
|
@ -661,12 +667,12 @@ export default class Actions extends Module {
|
||||||
|
|
||||||
let list = actions;
|
let list = actions;
|
||||||
|
|
||||||
if ( keys )
|
if ( keys || hover )
|
||||||
list = modified;
|
list = modified;
|
||||||
|
|
||||||
had_action = true;
|
had_action = true;
|
||||||
list.push(<button
|
list.push(<button
|
||||||
class={`ffz-tooltip ffz-mod-icon mod-icon tw-c-text-alt-2${disabled ? ' disabled' : ''}${has_color ? ' colored' : ''}${keys ? ` ffz-modifier-${keys}` : ''}`}
|
class={`ffz-tooltip ffz-mod-icon mod-icon tw-c-text-alt-2${disabled ? ' disabled' : ''}${has_color ? ' colored' : ''}${keys ? ` ffz-modifier-${keys}` : ''}${hover ? ' ffz-hover' : ''}`}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
data-tooltip-type="action"
|
data-tooltip-type="action"
|
||||||
data-action={data.action}
|
data-action={data.action}
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const reply = {
|
||||||
required_context: ['message'],
|
required_context: ['message'],
|
||||||
|
|
||||||
title: 'Reply to Message',
|
title: 'Reply to Message',
|
||||||
description: 'Allows you to directly reply to another user\'s message.',
|
description: 'Allows you to directly reply to another user\'s message. Only functions when the Chat Replies Style is "FrankerFaceZ".',
|
||||||
|
|
||||||
can_self: true,
|
can_self: true,
|
||||||
|
|
||||||
|
|
|
@ -282,7 +282,7 @@ export default {
|
||||||
tooltip && 'ffz-tooltip',
|
tooltip && 'ffz-tooltip',
|
||||||
this.accent && 'ffz-accent-card',
|
this.accent && 'ffz-accent-card',
|
||||||
!this.error && 'tw-interactable--hover-enabled',
|
!this.error && 'tw-interactable--hover-enabled',
|
||||||
'tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--alpha tw-interactive'
|
'tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--default tw-interactive'
|
||||||
],
|
],
|
||||||
attrs: {
|
attrs: {
|
||||||
'data-tooltip-type': 'link',
|
'data-tooltip-type': 'link',
|
||||||
|
|
|
@ -1514,8 +1514,6 @@ export default class Chat extends Module {
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
let tokens = [{type: 'text', text: msg.message}];
|
let tokens = [{type: 'text', text: msg.message}];
|
||||||
if ( ! tokens[0].text )
|
|
||||||
return tokens;
|
|
||||||
|
|
||||||
for(const tokenizer of this.__tokenizers)
|
for(const tokenizer of this.__tokenizers)
|
||||||
tokens = tokenizer.process.call(this, tokens, msg, user);
|
tokens = tokenizer.process.call(this, tokens, msg, user);
|
||||||
|
|
|
@ -250,7 +250,7 @@ export const Replies = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<strong
|
return (<strong
|
||||||
class={`chat-line__message-mention ffz-tooltip ffz--reply-mention ffz-i-reply${token.me ? ' ffz--mention-me' : ''}`}
|
class={`chat-line__message-mention ffz--pointer-events ffz-tooltip ffz--reply-mention ffz-i-reply${token.me ? ' ffz--mention-me' : ''}`}
|
||||||
style={{color}}
|
style={{color}}
|
||||||
data-tooltip-type="reply"
|
data-tooltip-type="reply"
|
||||||
data-login={token.recipient}
|
data-login={token.recipient}
|
||||||
|
@ -311,7 +311,7 @@ export const Mentions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<strong
|
return (<strong
|
||||||
class={`chat-line__message-mention${token.me ? ' ffz--mention-me' : ''}`}
|
class={`chat-line__message-mention${token.me ? ' ffz--mention-me' : ''} ffz--pointer-events`}
|
||||||
style={{color}}
|
style={{color}}
|
||||||
data-login={token.recipient}
|
data-login={token.recipient}
|
||||||
onClick={this.handleMentionClick}
|
onClick={this.handleMentionClick}
|
||||||
|
@ -637,7 +637,7 @@ export const BlockedTerms = {
|
||||||
return (<strong
|
return (<strong
|
||||||
data-text={token.text}
|
data-text={token.text}
|
||||||
data-tooltip-type="blocked"
|
data-tooltip-type="blocked"
|
||||||
class="ffz-tooltip ffz--blocked"
|
class="ffz-tooltip ffz--blocked ffz--pointer-events"
|
||||||
onClick={this.clickToReveal}
|
onClick={this.clickToReveal}
|
||||||
>
|
>
|
||||||
×××
|
×××
|
||||||
|
@ -698,7 +698,7 @@ export const AutomoddedTerms = {
|
||||||
data-text={token.text}
|
data-text={token.text}
|
||||||
data-categories={JSON.stringify(token.categories)}
|
data-categories={JSON.stringify(token.categories)}
|
||||||
data-tooltip-type="amterm"
|
data-tooltip-type="amterm"
|
||||||
class="ffz-tooltip ffz--blocked"
|
class="ffz-tooltip ffz--blocked ffz--pointer-events"
|
||||||
onClick={this.clickToReveal}
|
onClick={this.clickToReveal}
|
||||||
>
|
>
|
||||||
×××
|
×××
|
||||||
|
@ -866,7 +866,7 @@ export const CheerEmotes = {
|
||||||
|
|
||||||
render(token, createElement) {
|
render(token, createElement) {
|
||||||
return (<span
|
return (<span
|
||||||
class="ffz-cheer ffz-tooltip"
|
class="ffz-cheer ffz-tooltip ffz--pointer-events"
|
||||||
data-tooltip-type="cheer"
|
data-tooltip-type="cheer"
|
||||||
data-prefix={token.prefix}
|
data-prefix={token.prefix}
|
||||||
data-amount={this.i18n.formatNumber(token.amount)}
|
data-amount={this.i18n.formatNumber(token.amount)}
|
||||||
|
@ -1087,7 +1087,7 @@ export const AddonEmotes = {
|
||||||
render(token, createElement, wrapped) {
|
render(token, createElement, wrapped) {
|
||||||
const mods = token.modifiers || [], ml = mods.length,
|
const mods = token.modifiers || [], ml = mods.length,
|
||||||
emote = (<img
|
emote = (<img
|
||||||
class={`${EMOTE_CLASS} ffz-tooltip${token.provider === 'ffz' ? ' ffz-emote' : token.provider === 'emoji' ? ' ffz-emoji' : ''}`}
|
class={`${EMOTE_CLASS} ffz--pointer-events ffz-tooltip${token.provider === 'ffz' ? ' ffz-emote' : token.provider === 'emoji' ? ' ffz-emoji' : ''}`}
|
||||||
src={token.src}
|
src={token.src}
|
||||||
srcSet={token.srcSet}
|
srcSet={token.srcSet}
|
||||||
alt={token.text}
|
alt={token.text}
|
||||||
|
@ -1110,7 +1110,7 @@ export const AddonEmotes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<div
|
return (<div
|
||||||
class="ffz--inline modified-emote"
|
class="ffz--inline ffz--pointer-events modified-emote"
|
||||||
data-test-selector="emote-button"
|
data-test-selector="emote-button"
|
||||||
data-provider={token.provider}
|
data-provider={token.provider}
|
||||||
data-id={token.id}
|
data-id={token.id}
|
||||||
|
|
|
@ -329,6 +329,22 @@
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tw-pd-r-1 tw-checkbox">
|
||||||
|
<input
|
||||||
|
:id="'key_hover$' + id"
|
||||||
|
ref="key_hover"
|
||||||
|
:checked="edit_data.display.hover"
|
||||||
|
type="checkbox"
|
||||||
|
class="tw-checkbox__input"
|
||||||
|
@change="onChangeKeys"
|
||||||
|
>
|
||||||
|
<label :for="'key_hover$' + id" class="tw-checkbox__label">
|
||||||
|
<span class="tw-mg-l-1">
|
||||||
|
{{ t('setting.key.hover', 'Hover') }}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -660,6 +676,9 @@ export default {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( disp.hover )
|
||||||
|
out.push(this.t('setting.actions.visible.hover', 'when hovering'));
|
||||||
|
|
||||||
if ( ! out.length )
|
if ( ! out.length )
|
||||||
return this.t('setting.actions.visible.always', 'always');
|
return this.t('setting.actions.visible.always', 'always');
|
||||||
|
|
||||||
|
@ -693,6 +712,7 @@ export default {
|
||||||
if ( this.$refs.key_meta.checked )
|
if ( this.$refs.key_meta.checked )
|
||||||
i |= 8;
|
i |= 8;
|
||||||
|
|
||||||
|
this.edit_data.display.hover = this.$refs.key_hover.checked;
|
||||||
this.edit_data.display.keys = i;
|
this.edit_data.display.keys = i;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -404,7 +404,7 @@ export default class SettingsContext extends EventEmitter {
|
||||||
if ( ! type )
|
if ( ! type )
|
||||||
throw new Error(`non-existent type for ${key}`)
|
throw new Error(`non-existent type for ${key}`)
|
||||||
|
|
||||||
return type.get(key, this.profiles(), this.manager.definitions.get(key), this.manager.log);
|
return type.get(key, this.profiles(), this.manager.definitions.get(key), this.manager.log, this);
|
||||||
}
|
}
|
||||||
/* for(const profile of this.__profiles)
|
/* for(const profile of this.__profiles)
|
||||||
if ( profile.has(key) )
|
if ( profile.has(key) )
|
||||||
|
|
|
@ -250,6 +250,21 @@ export default class ChatHook extends Module {
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
|
|
||||||
|
this.settings.add('chat.replies.style', {
|
||||||
|
default: 2,
|
||||||
|
ui: {
|
||||||
|
path: 'Chat > Appearance >> Replies',
|
||||||
|
title: 'Style',
|
||||||
|
description: `Twitch's default style makes entire messages clickable and adds a button to the right. FrankerFaceZ uses an In-Line Chat Action and does not make messages clickable.`,
|
||||||
|
component: 'setting-select-box',
|
||||||
|
data: [
|
||||||
|
{value: 0, title: 'Disabled'},
|
||||||
|
{value: 1, title: 'Vanilla Twitch'},
|
||||||
|
{value: 2, title: 'FrankerFaceZ'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.settings.add('channel.raids.no-autojoin', {
|
this.settings.add('channel.raids.no-autojoin', {
|
||||||
default: false,
|
default: false,
|
||||||
ui: {
|
ui: {
|
||||||
|
@ -698,6 +713,7 @@ export default class ChatHook extends Module {
|
||||||
this.chat.context.on('changed:chat.points.allow-highlight', this.updateChatLines, this);
|
this.chat.context.on('changed:chat.points.allow-highlight', this.updateChatLines, this);
|
||||||
this.chat.context.on('changed:chat.filtering.display-deleted', this.updateChatLines, this);
|
this.chat.context.on('changed:chat.filtering.display-deleted', this.updateChatLines, this);
|
||||||
this.chat.context.on('changed:chat.filtering.display-mod-action', this.updateChatLines, this);
|
this.chat.context.on('changed:chat.filtering.display-mod-action', this.updateChatLines, this);
|
||||||
|
this.chat.context.on('changed:chat.replies.style', this.updateChatLines, this);
|
||||||
this.chat.context.on('changed:chat.filtering.clickable-mentions', val => this.css_tweaks.toggle('clickable-mentions', val));
|
this.chat.context.on('changed:chat.filtering.clickable-mentions', val => this.css_tweaks.toggle('clickable-mentions', val));
|
||||||
this.chat.context.on('changed:chat.filtering.bold-mentions', val => this.css_tweaks.toggle('chat-mention-no-bold', ! val));
|
this.chat.context.on('changed:chat.filtering.bold-mentions', val => this.css_tweaks.toggle('chat-mention-no-bold', ! val));
|
||||||
this.chat.context.on('changed:chat.pin-resubs', val => {
|
this.chat.context.on('changed:chat.pin-resubs', val => {
|
||||||
|
|
|
@ -241,6 +241,11 @@ export default class ChatLine extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
cls.prototype.ffzOpenReply = function() {
|
cls.prototype.ffzOpenReply = function() {
|
||||||
|
if ( this.props.reply ) {
|
||||||
|
this.setOPCardTray(this.props.reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const old_render_author = this.renderMessageAuthor;
|
const old_render_author = this.renderMessageAuthor;
|
||||||
this.renderMessageAuthor = () => this.ffzReplyAuthor();
|
this.renderMessageAuthor = () => this.ffzReplyAuthor();
|
||||||
|
|
||||||
|
@ -317,10 +322,11 @@ export default class ChatLine extends Module {
|
||||||
|
|
||||||
const types = t.parent.message_types || {},
|
const types = t.parent.message_types || {},
|
||||||
deleted_count = this.props.deletedCount,
|
deleted_count = this.props.deletedCount,
|
||||||
|
reply_mode = t.chat.context.get('chat.replies.style'),
|
||||||
override_mode = t.chat.context.get('chat.filtering.display-deleted'),
|
override_mode = t.chat.context.get('chat.filtering.display-deleted'),
|
||||||
|
|
||||||
msg = t.chat.standardizeMessage(this.props.message),
|
msg = t.chat.standardizeMessage(this.props.message),
|
||||||
reply_tokens = msg.ffz_reply = msg.ffz_reply || t.chat.tokenizeReply(this.props.reply),
|
reply_tokens = reply_mode === 2 ? ( msg.ffz_reply = msg.ffz_reply || t.chat.tokenizeReply(this.props.reply) ) : null,
|
||||||
is_action = msg.messageType === types.Action,
|
is_action = msg.messageType === types.Action,
|
||||||
|
|
||||||
user = msg.user,
|
user = msg.user,
|
||||||
|
@ -411,21 +417,27 @@ other {# messages were deleted by a moderator.}
|
||||||
//if ( ! msg.message && msg.messageParts )
|
//if ( ! msg.message && msg.messageParts )
|
||||||
// t.chat.detokenizeMessage(msg);
|
// t.chat.detokenizeMessage(msg);
|
||||||
|
|
||||||
const has_replies = this.chatRepliesTreatment ? this.chatRepliesTreatment !== 'control' : false;
|
|
||||||
|
|
||||||
const u = t.site.getUser(),
|
const u = t.site.getUser(),
|
||||||
r = {id: room_id, login: room};
|
r = {id: room_id, login: room};
|
||||||
|
|
||||||
|
const has_replies = this.chatRepliesTreatment ? this.chatRepliesTreatment !== 'control' : false,
|
||||||
|
can_replies = has_replies && msg.message && ! msg.deleted && ! this.props.disableReplyClick,
|
||||||
|
can_reply = can_replies && u.login !== msg.user?.login && ! msg.reply,
|
||||||
|
twitch_clickable = reply_mode === 1 && can_replies && (!!msg.reply || can_reply);
|
||||||
|
|
||||||
if ( u ) {
|
if ( u ) {
|
||||||
u.moderator = this.props.isCurrentUserModerator;
|
u.moderator = this.props.isCurrentUserModerator;
|
||||||
u.staff = this.props.isCurrentUserStaff;
|
u.staff = this.props.isCurrentUserStaff;
|
||||||
u.can_reply = has_replies && u.login !== msg.user?.login && ! msg.deleted && ! this.props.disableReplyClick
|
u.can_reply = reply_mode === 2 && can_reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokens = msg.ffz_tokens = msg.ffz_tokens || t.chat.tokenizeMessage(msg, u, r),
|
const tokens = msg.ffz_tokens = msg.ffz_tokens || t.chat.tokenizeMessage(msg, u, r),
|
||||||
rich_content = FFZRichContent && t.chat.pluckRichContent(tokens, msg),
|
rich_content = FFZRichContent && t.chat.pluckRichContent(tokens, msg),
|
||||||
bg_css = msg.mentioned && msg.mention_color ? t.parent.inverse_colors.process(msg.mention_color) : null;
|
bg_css = msg.mentioned && msg.mention_color ? t.parent.inverse_colors.process(msg.mention_color) : null;
|
||||||
|
|
||||||
|
if ( ! this.ffz_open_reply )
|
||||||
|
this.ffz_open_reply = this.ffzOpenReply.bind(this);
|
||||||
|
|
||||||
if ( ! this.ffz_user_click_handler ) {
|
if ( ! this.ffz_user_click_handler ) {
|
||||||
if ( this.props.onUsernameClick )
|
if ( this.props.onUsernameClick )
|
||||||
this.ffz_user_click_handler = event => {
|
this.ffz_user_click_handler = event => {
|
||||||
|
@ -473,30 +485,36 @@ other {# messages were deleted by a moderator.}
|
||||||
|
|
||||||
const override_name = t.overrides.getName(user.id);
|
const override_name = t.overrides.getName(user.id);
|
||||||
|
|
||||||
let cls = `chat-line__message${show_class ? ' ffz--deleted-message' : ''}`,
|
const user_bits = [
|
||||||
|
t.actions.renderInline(msg, this.props.showModerationIcons, u, r, e),
|
||||||
|
e('span', {
|
||||||
|
className: 'chat-line__message--badges'
|
||||||
|
}, t.chat.badges.render(msg, e)),
|
||||||
|
e('span', {
|
||||||
|
className: `chat-line__username notranslate${override_name ? ' ffz--name-override tw-relative tw-tooltip-wrapper' : ''}`,
|
||||||
|
role: 'button',
|
||||||
|
style: { color },
|
||||||
|
onClick: this.ffz_user_click_handler,
|
||||||
|
onContextMenu: t.actions.handleUserContext
|
||||||
|
}, override_name ? [
|
||||||
|
e('span', {
|
||||||
|
className: 'chat-author__display-name'
|
||||||
|
}, override_name),
|
||||||
|
e('div', {
|
||||||
|
className: 'tw-tooltip tw-tooltip--down tw-tooltip--align-center'
|
||||||
|
}, user_block)
|
||||||
|
] : user_block)
|
||||||
|
];
|
||||||
|
|
||||||
|
let cls = `chat-line__message${show_class ? ' ffz--deleted-message' : ''}${twitch_clickable ? ' tw-relative' : ''}${twitch_clickable && can_reply ? ' tw-pd-r-3' : ''}`,
|
||||||
out = (tokens.length || ! msg.ffz_type) ? [
|
out = (tokens.length || ! msg.ffz_type) ? [
|
||||||
this.props.showTimestamps && e('span', {
|
this.props.showTimestamps && e('span', {
|
||||||
className: 'chat-line__timestamp'
|
className: 'chat-line__timestamp'
|
||||||
}, t.chat.formatTime(msg.timestamp)),
|
}, t.chat.formatTime(msg.timestamp)),
|
||||||
t.actions.renderInline(msg, this.props.showModerationIcons, u, r, e),
|
twitch_clickable ?
|
||||||
e('span', {
|
e('div', {className: 'chat-line__username-container tw-inline-block'}, user_bits)
|
||||||
className: 'chat-line__message--badges'
|
: user_bits,
|
||||||
}, t.chat.badges.render(msg, e)),
|
e('span', {'aria-hidden': true}, is_action ? ' ' : ': '),
|
||||||
e('span', {
|
|
||||||
className: `chat-line__username notranslate${override_name ? ' ffz--name-override tw-relative tw-tooltip-wrapper' : ''}`,
|
|
||||||
role: 'button',
|
|
||||||
style: { color },
|
|
||||||
onClick: this.ffz_user_click_handler,
|
|
||||||
onContextMenu: t.actions.handleUserContext
|
|
||||||
}, override_name ? [
|
|
||||||
e('span', {
|
|
||||||
className: 'chat-author__display-name'
|
|
||||||
}, override_name),
|
|
||||||
e('div', {
|
|
||||||
className: 'tw-tooltip tw-tooltip--down tw-tooltip--align-center'
|
|
||||||
}, user_block)
|
|
||||||
] : user_block),
|
|
||||||
e('span', null, is_action ? ' ' : ': '),
|
|
||||||
show && has_replies && reply_tokens ?
|
show && has_replies && reply_tokens ?
|
||||||
t.chat.renderTokens(reply_tokens, e)
|
t.chat.renderTokens(reply_tokens, e)
|
||||||
: null,
|
: null,
|
||||||
|
@ -504,7 +522,7 @@ other {# messages were deleted by a moderator.}
|
||||||
e('span', {
|
e('span', {
|
||||||
className:'message',
|
className:'message',
|
||||||
style: is_action ? { color } : null
|
style: is_action ? { color } : null
|
||||||
}, t.chat.renderTokens(tokens, e, has_replies ? this.props.reply : null))
|
}, t.chat.renderTokens(tokens, e, (reply_mode !== 0 && has_replies) ? this.props.reply : null))
|
||||||
:
|
:
|
||||||
e('span', {
|
e('span', {
|
||||||
className: 'chat-line__message--deleted',
|
className: 'chat-line__message--deleted',
|
||||||
|
@ -531,6 +549,33 @@ other {# messages were deleted by a moderator.}
|
||||||
}, JSON.stringify([tokens, msg.emotes], null, 2))*/
|
}, JSON.stringify([tokens, msg.emotes], null, 2))*/
|
||||||
] : null;
|
] : null;
|
||||||
|
|
||||||
|
if ( twitch_clickable ) {
|
||||||
|
let btn = null;
|
||||||
|
if ( can_reply )
|
||||||
|
btn = e('div', {
|
||||||
|
className: 'chat-line__reply-icon tw-absolute tw-c-text-alt-2 tw-right-0 tw-top-0 ffz-tooltip ffz-tooltip--no-mouse',
|
||||||
|
'data-title': t.i18n.t('chat.actions.reply', 'Reply to Message')
|
||||||
|
}, [
|
||||||
|
e('div', {
|
||||||
|
className: 'chat-line__reply-icon-background tw-border-bottom-left-radius-medium tw-border-top-right-radius-medium tw-c-background-alt-2'
|
||||||
|
}),
|
||||||
|
e('figure', {className: 'ffz-i-reply'})
|
||||||
|
]);
|
||||||
|
|
||||||
|
out = [
|
||||||
|
e('button', {
|
||||||
|
className: 'ffz--reply-container chat-line__reply-button-container tw-interactive tw-link tw-link--button',
|
||||||
|
'data-test-selector': 'chat-reply-button',
|
||||||
|
onClick: this.ffz_open_reply
|
||||||
|
}, e('div', {className: 'chat-line__reply-button'}, btn)),
|
||||||
|
|
||||||
|
e('div', {className: 'chat-line__message-container tw-relative'}, [
|
||||||
|
this.renderReplyLine(),
|
||||||
|
out
|
||||||
|
])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
if ( msg.ffz_type === 'sub_mystery' ) {
|
if ( msg.ffz_type === 'sub_mystery' ) {
|
||||||
const mystery = msg.mystery;
|
const mystery = msg.mystery;
|
||||||
if ( mystery )
|
if ( mystery )
|
||||||
|
|
|
@ -227,7 +227,7 @@ export default class RichContent extends Module {
|
||||||
const tooltip = this.props.card_tooltip && this.state.full && ! this.props.force_full;
|
const tooltip = this.props.card_tooltip && this.state.full && ! this.props.force_full;
|
||||||
if ( this.state.url ) {
|
if ( this.state.url ) {
|
||||||
content = (<a
|
content = (<a
|
||||||
class={`${tooltip ? 'ffz-tooltip ' : ''}${this.state.accent ? 'ffz-accent-card ' : ''}${this.state.error ? 'tw-interactable--hover-enabled ': ''} tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--alpha tw-interactive`}
|
class={`${tooltip ? 'ffz-tooltip ' : ''}${this.state.accent ? 'ffz-accent-card ' : ''}${this.state.error ? '': 'tw-interactable--hover-enabled '}tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--default tw-interactive`}
|
||||||
data-tooltip-type="link"
|
data-tooltip-type="link"
|
||||||
data-url={this.state.url}
|
data-url={this.state.url}
|
||||||
data-is-mail={false}
|
data-is-mail={false}
|
||||||
|
|
|
@ -57,7 +57,7 @@ export default class SettingsMenu extends Module {
|
||||||
this.ffzPauseClick = () => this.setState({ffzPauseMenu: ! this.state.ffzPauseMenu});
|
this.ffzPauseClick = () => this.setState({ffzPauseMenu: ! this.state.ffzPauseMenu});
|
||||||
|
|
||||||
val.props.children.push(<div class="tw-full-width tw-relative">
|
val.props.children.push(<div class="tw-full-width tw-relative">
|
||||||
<button class="tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--alpha tw-interactive" onClick={this.ffzSettingsClick}>
|
<button class="tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--default tw-interactive" onClick={this.ffzSettingsClick}>
|
||||||
<div class="tw-align-items-center tw-flex tw-pd-05 tw-relative">
|
<div class="tw-align-items-center tw-flex tw-pd-05 tw-relative">
|
||||||
<div class="tw-flex-grow-1">
|
<div class="tw-flex-grow-1">
|
||||||
{t.i18n.t('site.menu_button', 'FrankerFaceZ Control Center')}
|
{t.i18n.t('site.menu_button', 'FrankerFaceZ Control Center')}
|
||||||
|
@ -85,7 +85,7 @@ export default class SettingsMenu extends Module {
|
||||||
|
|
||||||
val.props.children.push(<div class="tw-full-width tw-relative">
|
val.props.children.push(<div class="tw-full-width tw-relative">
|
||||||
<button
|
<button
|
||||||
class="tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--alpha tw-interactive"
|
class="tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--default tw-interactive"
|
||||||
onClick={this.ffzPauseClick}
|
onClick={this.ffzPauseClick}
|
||||||
>
|
>
|
||||||
<div class="tw-align-items-center tw-flex tw-pd-05 tw-relative">
|
<div class="tw-align-items-center tw-flex tw-pd-05 tw-relative">
|
||||||
|
@ -143,7 +143,7 @@ export default class SettingsMenu extends Module {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--alpha tw-interactive"
|
class="tw-block tw-border-radius-medium tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--default tw-interactive"
|
||||||
data-page="chat.behavior"
|
data-page="chat.behavior"
|
||||||
onClick={this.ffzSettingsClick}
|
onClick={this.ffzSettingsClick}
|
||||||
>
|
>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
.chat-line__moderation,
|
.chat-line__moderation,
|
||||||
.chat-line__status,
|
.chat-line__status,
|
||||||
.chat-line__raid {
|
.chat-line__raid {
|
||||||
padding: .5rem 1rem !important;
|
padding: .5rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ffz--points-line,
|
.ffz--points-line,
|
||||||
|
|
|
@ -160,7 +160,7 @@ export default class Following extends SiteModule {
|
||||||
|
|
||||||
// Hosted Channel Content
|
// Hosted Channel Content
|
||||||
simplebarContentChildren.push(<a
|
simplebarContentChildren.push(<a
|
||||||
class="tw-block tw-border-radius-small tw-full-width tw-interactable tw-interactable--alpha tw-interactive"
|
class="tw-block tw-border-radius-small tw-full-width tw-interactable tw-interactable--default tw-interactable--hover-enabled tw-interactive"
|
||||||
href={`/${inst.props.channelLogin}`}
|
href={`/${inst.props.channelLogin}`}
|
||||||
onClick={e => this.parent.hijackUserClick(e, inst.props.channelLogin, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind
|
onClick={e => this.parent.hijackUserClick(e, inst.props.channelLogin, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind
|
||||||
>
|
>
|
||||||
|
@ -182,7 +182,7 @@ export default class Following extends SiteModule {
|
||||||
// Hosting Channels Content
|
// Hosting Channels Content
|
||||||
for (const channel of channels) {
|
for (const channel of channels) {
|
||||||
simplebarContentChildren.push(<a
|
simplebarContentChildren.push(<a
|
||||||
class="tw-block tw-border-radius-small tw-full-width tw-interactable tw-interactable--alpha tw-interactive"
|
class="tw-block tw-border-radius-small tw-full-width tw-interactable tw-interactable--default tw-interactable--hover-enabled tw-interactive"
|
||||||
href={`/${channel.login}`}
|
href={`/${channel.login}`}
|
||||||
onClick={e => this.parent.hijackUserClick(e, channel.login, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind
|
onClick={e => this.parent.hijackUserClick(e, channel.login, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind
|
||||||
>
|
>
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz--pointer-events {
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
.ffz--freeze-indicator {
|
.ffz--freeze-indicator {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +59,24 @@
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz--reply-container {
|
||||||
|
height: 100% !important;
|
||||||
|
width: 100% !important;
|
||||||
|
left: 0 !important;
|
||||||
|
right: 0 !important;
|
||||||
|
|
||||||
|
.chat-line__reply-icon {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
figure {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 0.25rem;
|
||||||
|
right: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ffz--reply-mention {
|
.ffz--reply-mention {
|
||||||
padding: 0.25rem 0.5rem;
|
padding: 0.25rem 0.5rem;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
|
|
|
@ -816,7 +816,7 @@ TOKEN_TYPES.link = function(token, createElement, ctx) {
|
||||||
|
|
||||||
const klass = [];
|
const klass = [];
|
||||||
if ( token.interactive )
|
if ( token.interactive )
|
||||||
klass.push(`tw-interactable tw-interactable--hover-enabled tw-interactable--alpha tw-interactive`);
|
klass.push(`tw-interactable tw-interactable--hover-enabled tw-interactable--default tw-interactive`);
|
||||||
|
|
||||||
if ( token.tooltip !== false )
|
if ( token.tooltip !== false )
|
||||||
klass.push('ffz-tooltip');
|
klass.push('ffz-tooltip');
|
||||||
|
|
|
@ -334,6 +334,11 @@
|
||||||
margin: 0 .5rem;
|
margin: 0 .5rem;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.chat-line__message:hover & .ffz-hover {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ffz--keys {
|
.ffz--keys {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue