mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-01 16:48: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",
|
||||
"author": "Dan Salvato LLC",
|
||||
"version": "4.9.3",
|
||||
"version": "4.9.4",
|
||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
|
|
|
@ -219,7 +219,7 @@ export default class Actions extends Module {
|
|||
return `Error: The "${data.action}" action provider does not have tooltip support.`;
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -448,7 +448,9 @@ export default class Actions extends Module {
|
|||
(disp.staff != null && disp.staff !== (current_user ? !!current_user.staff : false)) ||
|
||||
(disp.emoteOnly != null && disp.emoteOnly !== current_room.emoteOnly) ||
|
||||
(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;
|
||||
|
||||
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);
|
||||
|
||||
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}
|
||||
>
|
||||
{actions}
|
||||
|
|
|
@ -159,7 +159,11 @@ export const ban = {
|
|||
},
|
||||
|
||||
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) {
|
||||
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>
|
||||
</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">
|
||||
<label for="vis_subs">
|
||||
{{ t('setting.actions.edit-visible.subs', 'Subs Mode') }}
|
||||
|
@ -206,6 +228,28 @@
|
|||
</select>
|
||||
</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">
|
||||
<label for="vis_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'));
|
||||
else if ( disp.subsMode === false )
|
||||
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 ) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
|
||||
<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:') }}
|
||||
|
||||
<div class="tw-pd-x-1 tw-checkbox">
|
||||
|
@ -102,6 +102,36 @@
|
|||
</label>
|
||||
</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">
|
||||
<input
|
||||
id="show_all"
|
||||
|
@ -291,6 +321,8 @@ export default {
|
|||
with_emote: false,
|
||||
with_subs: false,
|
||||
with_slow: false,
|
||||
with_followers: false,
|
||||
with_r9k: false,
|
||||
|
||||
is_staff: false,
|
||||
is_deleted: false,
|
||||
|
@ -543,6 +575,8 @@ export default {
|
|||
this.with_emote = this.has_mode && this.$refs.with_emote.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_followers = this.has_mode && this.$refs.with_followers.checked;
|
||||
this.with_r9k = this.has_mode && this.$refs.with_r9k.checked;
|
||||
},
|
||||
|
||||
displayAction(action) {
|
||||
|
@ -577,6 +611,12 @@ export default {
|
|||
|
||||
if ( disp.subsMode != null && disp.subsMode !== this.with_subs )
|
||||
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;
|
||||
|
|
|
@ -605,6 +605,21 @@ export default class ChatHook extends Module {
|
|||
if ( handler )
|
||||
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({
|
||||
addUpdateHandler: inst.addUpdateHandler,
|
||||
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;
|
||||
this.onResubscriptionEvent = function(e) {
|
||||
try {
|
||||
|
|
|
@ -157,6 +157,7 @@ export default class Input extends Module {
|
|||
const out = old_render.call(this);
|
||||
try {
|
||||
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');
|
||||
if ( ! container || ! container.props || ! container.props.children )
|
||||
return out;
|
||||
|
@ -179,7 +180,10 @@ export default class Input extends Module {
|
|||
emoteOnly: props.emoteOnlyMode,
|
||||
slowMode: props.slowMode,
|
||||
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);
|
||||
|
|
|
@ -741,7 +741,7 @@ other {# messages were deleted by a moderator.}
|
|||
|
||||
if ( ! this.props.installedExtensions.some(val => {
|
||||
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;
|
||||
|
||||
|
|
|
@ -245,6 +245,10 @@ textarea.tw-input {
|
|||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 2px 5px;
|
||||
border-radius: 2px;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue