diff --git a/package.json b/package.json index 153672e6..ef2699c0 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.20.28", + "version": "4.20.29", "description": "FrankerFaceZ is a Twitch enhancement suite.", "license": "Apache-2.0", "scripts": { diff --git a/src/modules/chat/actions/index.jsx b/src/modules/chat/actions/index.jsx index 935b7393..42affe17 100644 --- a/src/modules/chat/actions/index.jsx +++ b/src/modules/chat/actions/index.jsx @@ -65,11 +65,11 @@ export default class Actions extends Module { ), default: [ - {v: {action: 'reply', appearance: {type: 'icon', icon: 'ffz-i-reply'}, options: {}, display: {}}}, {v: {action: 'ban', appearance: {type: 'icon', icon: 'ffz-i-block'}, options: {}, display: {mod: true, mod_icons: true, deleted: false}}}, {v: {action: 'unban', appearance: {type: 'icon', icon: 'ffz-i-ok'}, options: {}, display: {mod: true, mod_icons: true, deleted: true}}}, {v: {action: 'timeout', appearance: {type: 'icon', icon: 'ffz-i-clock'}, display: {mod: true, mod_icons: true}}}, - {v: {action: 'msg_delete', appearance: {type: 'icon', icon: 'ffz-i-trash'}, options: {}, display: {mod: true, mod_icons: true}}} + {v: {action: 'msg_delete', appearance: {type: 'icon', icon: 'ffz-i-trash'}, options: {}, display: {mod: true, mod_icons: true}}}, + {v: {action: 'reply', appearance: {type: 'icon', icon: 'ffz-i-reply'}, options: {}, display: {}}} ], type: 'array_merge', @@ -498,12 +498,14 @@ export default class Actions extends Module { if ( current_level < 3 ) mod_icons = false; + const chat_line = line; + return this.renderPopup(target, (t, tip) => { const lines = []; let line = null; const handle_click = event => { - this.handleClick(event); + this.handleClick(event, line); tip.hide(); }; @@ -599,6 +601,7 @@ export default class Actions extends Module { ); out.ffz_message = msg; + out.ffz_line = chat_line; return out; }); } @@ -723,11 +726,12 @@ export default class Actions extends Module { if ( ! definition ) return null; - let user, room, message, loaded = false; + let user, room, message, loaded = false, line; if ( pds ) { if ( pds.source === 'msg' && parent.ffz_message ) { const msg = parent.ffz_message; + line = parent.ffz_line; loaded = true; user = msg.user ? { @@ -749,8 +753,8 @@ export default class Actions extends Module { }; } else if ( pds.source === 'line' ) { - const fine = this.resolve('site.fine'), - line = fine && fine.searchParent(parent, n => n.props && n.props.message); + const fine = this.resolve('site.fine'); + line = fine && fine.searchParent(parent, n => n.props && n.props.message); if ( line && line.props && line.props.message ) { loaded = true; @@ -792,7 +796,8 @@ export default class Actions extends Module { user, room, message, - message_id: message ? message.id : null + message_id: message ? message.id : null, + line }; if ( definition.defaults ) diff --git a/src/modules/chat/actions/types.jsx b/src/modules/chat/actions/types.jsx index 6e94145a..c8de86b6 100644 --- a/src/modules/chat/actions/types.jsx +++ b/src/modules/chat/actions/types.jsx @@ -36,15 +36,17 @@ export const reply = { return true; }, - click(event) { - const fine = this.resolve('site.fine'), + click(event, data) { + let line = data.line; + if ( ! line ) { + const fine = this.resolve('site.fine'); line = fine ? fine.searchParent(event.target, n => n.setMessageTray && n.props && n.props.message) : null; + } if ( ! line ) return; line.ffzOpenReply(); - //line.setMessageTray(line.props.message, line.props.message.message); } } diff --git a/src/modules/chat/index.js b/src/modules/chat/index.js index 81e965b2..61baecfa 100644 --- a/src/modules/chat/index.js +++ b/src/modules/chat/index.js @@ -1279,6 +1279,10 @@ export default class Chat extends Module { const emotes = {}, chars = split_chars(msg.message); + let offset = 0; + if ( msg.message && msg.messageBody && msg.message !== msg.messageBody ) + offset = chars.length - split_chars(msg.messageBody).length; + for(const key in msg.emotes) if ( has(msg.emotes, key) ) { const raw_emote = msg.emotes[key]; @@ -1286,7 +1290,7 @@ export default class Chat extends Module { return msg.ffz_emotes = msg.emotes; const em = emotes[raw_emote.id] = emotes[raw_emote.id] || []; - let idx = raw_emote.startIndex + 1; + let idx = raw_emote.startIndex + 1 + offset; while(idx < chars.length) { if ( EMOTE_CHARS.test(chars[idx]) ) break; @@ -1295,7 +1299,7 @@ export default class Chat extends Module { } em.push({ - startIndex: raw_emote.startIndex, + startIndex: raw_emote.startIndex + offset, endIndex: idx - 1 }); } diff --git a/src/settings/types.js b/src/settings/types.js index cd847f6e..a115456b 100644 --- a/src/settings/types.js +++ b/src/settings/types.js @@ -4,6 +4,8 @@ // Settings Types // ============================================================================ +const DEFAULT = Symbol('default'); + export const basic = { get(key, profiles) { for(const profile of profiles) @@ -52,41 +54,55 @@ export const array_merge = { return values; }, - get(key, profiles, definition, log) { + get(key, profiles, definition, log, ctx) { const values = [], sources = []; let trailing = []; let had_value = false; - for(const profile of profiles) - if ( profile.has(key) ) { - const value = profile.get(key), - trail = []; + const profs = [...profiles, DEFAULT]; - if ( ! Array.isArray(value) ) { + for(const profile of profs) { + let value; + if ( profile === DEFAULT ) { + value = definition.default; + if ( typeof value === 'function' ) + value = value(ctx); + + } else if ( profile.has(key) ) + value = profile.get(key); + else + continue; + + if ( ! Array.isArray(value) ) { + if ( profile !== DEFAULT ) log.warn(`Profile #${profile.id} has an invalid value for "${key}" of type ${typeof value}. Skipping.`); - continue; - } - - sources.push(profile.id); - let is_trailing = false; - for(const val of value) { - had_value = true; - if ( val.t === 'inherit' ) - is_trailing = true; - else if ( is_trailing ) - trail.push(val.v); - else - values.push(val.v); - } - - trailing = trail.concat(trailing); - - // If we didn't run into an inherit, don't inherit. - if ( ! is_trailing && ! definition.always_inherit ) - break; + continue; } + const trail = []; + + if ( profile !== DEFAULT ) + sources.push(profile.id); + + let is_trailing = false; + for(const val of value) { + had_value = true; + if ( val.t === 'inherit' ) + is_trailing = true; + else if ( is_trailing ) + trail.push(val.v); + else + values.push(val.v); + } + + trailing = trail.concat(trailing); + + // If we didn't run into an inherit, don't inherit. + if ( ! is_trailing && ! definition.always_inherit ) + break; + } + if ( had_value ) return [ values.concat(trailing), diff --git a/src/sites/twitch-twilight/styles/chat.scss b/src/sites/twitch-twilight/styles/chat.scss index 3e9094dd..e764d882 100644 --- a/src/sites/twitch-twilight/styles/chat.scss +++ b/src/sites/twitch-twilight/styles/chat.scss @@ -58,6 +58,7 @@ .ffz--reply-mention { padding: 0.25rem 0.5rem; border-radius: 1rem; + white-space: nowrap; &:before { font-size: 0.8em;