mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-01 08:38:32 +00:00
4.9.4
* Added: Room Actions can now be filtered based on the chat being in Followers-Only Mode or R9K Mode. * Changed: Custom tool-tips for actions now support variables. Time-out and ban reasons do as well. Text labels do not. * Fixed: Chat messages from Twitch Extensions not displaying.
This commit is contained in:
parent
d150b9720d
commit
6cb585d7d4
9 changed files with 154 additions and 9 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"author": "Dan Salvato LLC",
|
"author": "Dan Salvato LLC",
|
||||||
"version": "4.9.3",
|
"version": "4.9.4",
|
||||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -219,7 +219,7 @@ export default class Actions extends Module {
|
||||||
return `Error: The "${data.action}" action provider does not have tooltip support.`;
|
return `Error: The "${data.action}" action provider does not have tooltip support.`;
|
||||||
|
|
||||||
if ( data.tip && data.tip.length )
|
if ( data.tip && data.tip.length )
|
||||||
return data.tip;
|
return this.replaceVariables(data.tip, data);
|
||||||
|
|
||||||
return maybe_call(data.definition.tooltip, this, data, target, tip);
|
return maybe_call(data.definition.tooltip, this, data, target, tip);
|
||||||
}
|
}
|
||||||
|
@ -448,7 +448,9 @@ export default class Actions extends Module {
|
||||||
(disp.staff != null && disp.staff !== (current_user ? !!current_user.staff : false)) ||
|
(disp.staff != null && disp.staff !== (current_user ? !!current_user.staff : false)) ||
|
||||||
(disp.emoteOnly != null && disp.emoteOnly !== current_room.emoteOnly) ||
|
(disp.emoteOnly != null && disp.emoteOnly !== current_room.emoteOnly) ||
|
||||||
(disp.slowMode != null && disp.slowMode !== current_room.slowMode) ||
|
(disp.slowMode != null && disp.slowMode !== current_room.slowMode) ||
|
||||||
(disp.subsMode != null && disp.subsMode !== current_room.subsMode) )
|
(disp.subsMode != null && disp.subsMode !== current_room.subsMode) ||
|
||||||
|
(disp.r9kMode != null && disp.r9kMode !== current_room.r9kMode) ||
|
||||||
|
(disp.followersOnly != null && disp.followersOnly !== current_room.followersOnly) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const has_color = def.colored && ap.color,
|
const has_color = def.colored && ap.color,
|
||||||
|
@ -474,7 +476,7 @@ export default class Actions extends Module {
|
||||||
const room = current_room && JSON.stringify(current_room);
|
const room = current_room && JSON.stringify(current_room);
|
||||||
|
|
||||||
return (<div
|
return (<div
|
||||||
class={`ffz--room-actions ffz-action-data tw-flex tw-flex-grow-1 tw-align-items-center ${is_above ? 'tw-pd-y-05 tw-border-t' : 'tw-mg-x-05'}`}
|
class={`ffz--room-actions ffz-action-data tw-flex tw-flex-grow-1 tw-flex-wrap tw-align-items-center ${is_above ? 'tw-pd-y-05 tw-border-t' : 'tw-mg-x-05'}`}
|
||||||
data-room={room}
|
data-room={room}
|
||||||
>
|
>
|
||||||
{actions}
|
{actions}
|
||||||
|
|
|
@ -159,7 +159,11 @@ export const ban = {
|
||||||
},
|
},
|
||||||
|
|
||||||
click(event, data) {
|
click(event, data) {
|
||||||
this.sendMessage(data.room.login, `/ban ${data.user.login} ${data.reason||data.options.reason||''}`);
|
let reason = data.reason || data.options.reason || '';
|
||||||
|
if ( reason.length )
|
||||||
|
reason = this.replaceVariables(reason, data);
|
||||||
|
|
||||||
|
this.sendMessage(data.room.login, `/ban ${data.user.login} ${reason}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +215,11 @@ export const timeout = {
|
||||||
},
|
},
|
||||||
|
|
||||||
click(event, data) {
|
click(event, data) {
|
||||||
this.sendMessage(data.room.login, `/timeout ${data.user.login} ${data.options.duration} ${data.reason||data.options.reason||''}`);
|
let reason = data.reason || data.options.reason || '';
|
||||||
|
if ( reason.length )
|
||||||
|
reason = this.replaceVariables(reason, data);
|
||||||
|
|
||||||
|
this.sendMessage(data.room.login, `/timeout ${data.user.login} ${data.options.duration} ${reason}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,28 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="has_mode" class="tw-flex tw-align-items-center">
|
||||||
|
<label for="vis_follows">
|
||||||
|
{{ t('setting.actions.edit-visible.follows', 'Follower-Only Mode') }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<select
|
||||||
|
id="vis_subs"
|
||||||
|
v-model="edit_data.display.followersOnly"
|
||||||
|
class="tw-border-radius-medium tw-font-size-6 tw-full-width tw-select tw-pd-l-1 tw-pd-r-3 tw-pd-y-05 tw-mg-y-05"
|
||||||
|
>
|
||||||
|
<option :value="undefined" selected>
|
||||||
|
{{ t('setting.unset', 'Unset') }}
|
||||||
|
</option>
|
||||||
|
<option :value="true">
|
||||||
|
{{ t('setting.true', 'True') }}
|
||||||
|
</option>
|
||||||
|
<option :value="false">
|
||||||
|
{{ t('setting.false', 'False') }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="has_mode" class="tw-flex tw-align-items-center">
|
<div v-if="has_mode" class="tw-flex tw-align-items-center">
|
||||||
<label for="vis_subs">
|
<label for="vis_subs">
|
||||||
{{ t('setting.actions.edit-visible.subs', 'Subs Mode') }}
|
{{ t('setting.actions.edit-visible.subs', 'Subs Mode') }}
|
||||||
|
@ -206,6 +228,28 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="has_mode" class="tw-flex tw-align-items-center">
|
||||||
|
<label for="vis_r9k">
|
||||||
|
{{ t('setting.actions.edit-visible.r9k', 'R9k Mode') }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<select
|
||||||
|
id="vis_r9k"
|
||||||
|
v-model="edit_data.display.r9kMode"
|
||||||
|
class="tw-border-radius-medium tw-font-size-6 tw-full-width tw-select tw-pd-l-1 tw-pd-r-3 tw-pd-y-05 tw-mg-y-05"
|
||||||
|
>
|
||||||
|
<option :value="undefined" selected>
|
||||||
|
{{ t('setting.unset', 'Unset') }}
|
||||||
|
</option>
|
||||||
|
<option :value="true">
|
||||||
|
{{ t('setting.true', 'True') }}
|
||||||
|
</option>
|
||||||
|
<option :value="false">
|
||||||
|
{{ t('setting.false', 'False') }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="has_modifiers" class="tw-flex tw-align-items-start">
|
<div v-if="has_modifiers" class="tw-flex tw-align-items-start">
|
||||||
<label for="vis_modifiers">
|
<label for="vis_modifiers">
|
||||||
{{ t('setting.actions.edit-visible.modifier', 'Modifiers') }}
|
{{ t('setting.actions.edit-visible.modifier', 'Modifiers') }}
|
||||||
|
@ -552,6 +596,16 @@ export default {
|
||||||
out.push(this.t('setting.actions.visible.subs', 'when subs mode'));
|
out.push(this.t('setting.actions.visible.subs', 'when subs mode'));
|
||||||
else if ( disp.subsMode === false )
|
else if ( disp.subsMode === false )
|
||||||
out.push(this.t('setting.actions.visible.no-subs', 'when not subs mode'));
|
out.push(this.t('setting.actions.visible.no-subs', 'when not subs mode'));
|
||||||
|
|
||||||
|
if ( disp.r9kMode === true )
|
||||||
|
out.push(this.t('setting.actions.visible.r9k', 'when r9k mode'));
|
||||||
|
else if ( disp.r9kMode === false )
|
||||||
|
out.push(this.t('setting.actions.visible.no-r9k', 'when not r9k mode'));
|
||||||
|
|
||||||
|
if ( disp.followersOnly === true )
|
||||||
|
out.push(this.t('setting.actions.visible.followers', 'when followers-only mode'));
|
||||||
|
else if ( disp.followersOnly === false )
|
||||||
|
out.push(this.t('setting.actions.visible.no-followers', 'when not followers-only mode'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( disp.keys ) {
|
if ( disp.keys ) {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tw-pd-b-1 tw-border-b tw-mg-b-1">
|
<div class="tw-pd-b-1 tw-border-b tw-mg-b-1">
|
||||||
<div class="tw-flex tw-align-items-center ffz--inline">
|
<div class="tw-flex tw-flex-wrap tw-align-items-center ffz--inline">
|
||||||
{{ t('setting.actions.preview', 'Preview:') }}
|
{{ t('setting.actions.preview', 'Preview:') }}
|
||||||
|
|
||||||
<div class="tw-pd-x-1 tw-checkbox">
|
<div class="tw-pd-x-1 tw-checkbox">
|
||||||
|
@ -102,6 +102,36 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="has_mode" class="tw-pd-x-1 tw-checkbox">
|
||||||
|
<input
|
||||||
|
id="with_followers"
|
||||||
|
ref="with_followers"
|
||||||
|
:checked="with_followers"
|
||||||
|
type="checkbox"
|
||||||
|
class="tw-checkbox__input"
|
||||||
|
@change="onPreview"
|
||||||
|
>
|
||||||
|
|
||||||
|
<label for="with_followers" class="tw-checkbox__label">
|
||||||
|
{{ t('setting.actions.preview.followers', 'Followers-Only') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="has_mode" class="tw-pd-x-1 tw-checkbox">
|
||||||
|
<input
|
||||||
|
id="with_r9k"
|
||||||
|
ref="with_r9k"
|
||||||
|
:checked="with_r9k"
|
||||||
|
type="checkbox"
|
||||||
|
class="tw-checkbox__input"
|
||||||
|
@change="onPreview"
|
||||||
|
>
|
||||||
|
|
||||||
|
<label for="with_r9k" class="tw-checkbox__label">
|
||||||
|
{{ t('setting.actions.preview.r9k', 'R9k Mode') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tw-pd-x-1 tw-checkbox">
|
<div class="tw-pd-x-1 tw-checkbox">
|
||||||
<input
|
<input
|
||||||
id="show_all"
|
id="show_all"
|
||||||
|
@ -291,6 +321,8 @@ export default {
|
||||||
with_emote: false,
|
with_emote: false,
|
||||||
with_subs: false,
|
with_subs: false,
|
||||||
with_slow: false,
|
with_slow: false,
|
||||||
|
with_followers: false,
|
||||||
|
with_r9k: false,
|
||||||
|
|
||||||
is_staff: false,
|
is_staff: false,
|
||||||
is_deleted: false,
|
is_deleted: false,
|
||||||
|
@ -543,6 +575,8 @@ export default {
|
||||||
this.with_emote = this.has_mode && this.$refs.with_emote.checked;
|
this.with_emote = this.has_mode && this.$refs.with_emote.checked;
|
||||||
this.with_subs = this.has_mode && this.$refs.with_subs.checked;
|
this.with_subs = this.has_mode && this.$refs.with_subs.checked;
|
||||||
this.with_slow = this.has_mode && this.$refs.with_slow.checked;
|
this.with_slow = this.has_mode && this.$refs.with_slow.checked;
|
||||||
|
this.with_followers = this.has_mode && this.$refs.with_followers.checked;
|
||||||
|
this.with_r9k = this.has_mode && this.$refs.with_r9k.checked;
|
||||||
},
|
},
|
||||||
|
|
||||||
displayAction(action) {
|
displayAction(action) {
|
||||||
|
@ -577,6 +611,12 @@ export default {
|
||||||
|
|
||||||
if ( disp.subsMode != null && disp.subsMode !== this.with_subs )
|
if ( disp.subsMode != null && disp.subsMode !== this.with_subs )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if ( disp.r9kMode != null && disp.r9kMode !== this.with_r9k )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( disp.followersOnly != null && disp.followersOnly !== this.with_followers )
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -605,6 +605,21 @@ export default class ChatHook extends Module {
|
||||||
if ( handler )
|
if ( handler )
|
||||||
handler.addMessageHandler(inst.handleMessage);
|
handler.addMessageHandler(inst.handleMessage);
|
||||||
|
|
||||||
|
if ( Array.isArray(inst.buffer) ) {
|
||||||
|
let i = inst.buffer.length;
|
||||||
|
const ct = this.chat_types || CHAT_TYPES;
|
||||||
|
|
||||||
|
while(i--) {
|
||||||
|
const msg = inst.buffer[i];
|
||||||
|
if ( msg && msg.type === ct.RoomState && msg.state ) {
|
||||||
|
this.chat.context.updateContext({
|
||||||
|
chat_state: msg.state
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inst.props.setMessageBufferAPI({
|
inst.props.setMessageBufferAPI({
|
||||||
addUpdateHandler: inst.addUpdateHandler,
|
addUpdateHandler: inst.addUpdateHandler,
|
||||||
removeUpdateHandler: inst.removeUpdateHandler,
|
removeUpdateHandler: inst.removeUpdateHandler,
|
||||||
|
@ -1313,6 +1328,24 @@ export default class ChatHook extends Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const old_state = this.onRoomStateEvent;
|
||||||
|
this.onRoomStateEvent = function(e) {
|
||||||
|
try {
|
||||||
|
const channel = e.channel,
|
||||||
|
current = t.chat.context.get('context.channel');
|
||||||
|
|
||||||
|
if ( channel && (channel === current || channel === `#${current}`) )
|
||||||
|
t.chat.context.updateContext({
|
||||||
|
chat_state: e.state
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch(err) {
|
||||||
|
t.log.capture(err, {extra: e});
|
||||||
|
}
|
||||||
|
|
||||||
|
return old_state.call(i, e);
|
||||||
|
}
|
||||||
|
|
||||||
const old_resub = this.onResubscriptionEvent;
|
const old_resub = this.onResubscriptionEvent;
|
||||||
this.onResubscriptionEvent = function(e) {
|
this.onResubscriptionEvent = function(e) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -157,6 +157,7 @@ export default class Input extends Module {
|
||||||
const out = old_render.call(this);
|
const out = old_render.call(this);
|
||||||
try {
|
try {
|
||||||
const above = t.chat.context.get('chat.actions.room-above'),
|
const above = t.chat.context.get('chat.actions.room-above'),
|
||||||
|
state = t.chat.context.get('context.chat_state') || {},
|
||||||
container = above ? out : findReactFragment(out, n => n.props && n.props.className === 'chat-input__buttons-container');
|
container = above ? out : findReactFragment(out, n => n.props && n.props.className === 'chat-input__buttons-container');
|
||||||
if ( ! container || ! container.props || ! container.props.children )
|
if ( ! container || ! container.props || ! container.props.children )
|
||||||
return out;
|
return out;
|
||||||
|
@ -179,7 +180,10 @@ export default class Input extends Module {
|
||||||
emoteOnly: props.emoteOnlyMode,
|
emoteOnly: props.emoteOnlyMode,
|
||||||
slowMode: props.slowMode,
|
slowMode: props.slowMode,
|
||||||
slowDuration: props.slowModeDuration,
|
slowDuration: props.slowModeDuration,
|
||||||
subsMode: props.subsOnlyMode
|
subsMode: props.subsOnlyMode,
|
||||||
|
r9kMode: state.r9k,
|
||||||
|
followersOnly: state.followersOnly,
|
||||||
|
followersDuration: state.followersOnlyRequirement
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = t.actions.renderRoom(t.chat.context.get('context.chat.showModIcons'), u, r, above, createElement);
|
const actions = t.actions.renderRoom(t.chat.context.get('context.chat.showModIcons'), u, r, above, createElement);
|
||||||
|
|
|
@ -741,7 +741,7 @@ other {# messages were deleted by a moderator.}
|
||||||
|
|
||||||
if ( ! this.props.installedExtensions.some(val => {
|
if ( ! this.props.installedExtensions.some(val => {
|
||||||
const e = val.extension;
|
const e = val.extension;
|
||||||
return e && e.clientID === ext.clientID && e.version === ext.version;
|
return e && (e.clientId || e.clientID) === (ext.clientId || ext.clientID) && e.version === ext.version;
|
||||||
}) )
|
}) )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
|
@ -245,6 +245,10 @@ textarea.tw-input {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue