mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-27 21:05:53 +00:00
4.36.0
* Added: Setting to hide specific chat token types from rendering in chat, in case you for some reason don't want to see cheers / emotes / whatever. * Added: Support for the Artist, No Audio, and No Video badges in different badge styles. * API Added: The `site.player` module now exports CSS rules for the player control containers, so that FS Chat (and maybe other add-ons) won't need updates in the future if the CSS rule changes slightly.
This commit is contained in:
parent
168db52e2b
commit
dd248838ad
9 changed files with 125 additions and 13 deletions
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "frankerfacez",
|
||||
"author": "Dan Salvato LLC",
|
||||
"version": "4.35.2",
|
||||
"version": "4.36.0",
|
||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
|
|
|
@ -44,7 +44,10 @@ const CSS_BADGES = {
|
|||
turbo: { 1: { color: '#59399A' } },
|
||||
premium: { 1: { color: '#00A0D6' } },
|
||||
'anonymous-cheerer': { 1: { color: '#4B367C' } },
|
||||
'clip-champ': { 1: { color: '#9146FF' } }
|
||||
'clip-champ': { 1: { color: '#9146FF' } },
|
||||
'artist-badge': { 1: { color: '#1e69ff' } },
|
||||
'no_audio': { 1: { color: '#323239' } },
|
||||
'no_video': { 1: { color: '#323239' } }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,10 @@ function sortPriorityColorTerms(list) {
|
|||
|
||||
const TERM_FLAGS = ['g', 'gi'];
|
||||
|
||||
const UNBLOCKABLE_TOKENS = [
|
||||
'filter_test'
|
||||
];
|
||||
|
||||
function formatTerms(data) {
|
||||
const out = [];
|
||||
|
||||
|
@ -441,6 +445,29 @@ export default class Chat extends Module {
|
|||
}
|
||||
});
|
||||
|
||||
this.settings.add('chat.filtering.hidden-tokens', {
|
||||
default: [],
|
||||
type: 'array_merge',
|
||||
always_inherit: true,
|
||||
process(ctx, val) {
|
||||
const out = new Set;
|
||||
for(const v of val)
|
||||
if ( v?.v || ! UNBLOCKABLE_TOKENS.includes(v.v) )
|
||||
out.add(v.v);
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
ui: {
|
||||
path: 'Chat > Appearance >> Hidden Token Types @{"description":"This filter allows you to prevent specific content token types from appearing chat messages, such as hiding all cheers or emotes."}',
|
||||
component: 'blocked-types',
|
||||
data: () => Object
|
||||
.keys(this.tokenizers)
|
||||
.filter(key => ! UNBLOCKABLE_TOKENS.includes(key) && this.tokenizers[key]?.render)
|
||||
.sort()
|
||||
}
|
||||
});
|
||||
|
||||
this.settings.add('chat.filtering.highlight-basic-users', {
|
||||
default: [],
|
||||
type: 'array_merge',
|
||||
|
@ -1978,12 +2005,14 @@ export default class Chat extends Module {
|
|||
tokenizers = this.tokenizers,
|
||||
l = tokens.length;
|
||||
|
||||
const hidden = this.context.get('chat.filtering.hidden-tokens');
|
||||
|
||||
for(let i=0; i < l; i++) {
|
||||
const token = tokens[i],
|
||||
type = token.type,
|
||||
tk = tokenizers[type];
|
||||
|
||||
if ( token.hidden )
|
||||
if ( token.hidden || hidden.has(type) )
|
||||
continue;
|
||||
|
||||
let res;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
:key="rule.id"
|
||||
:value="rule"
|
||||
:filters="filters"
|
||||
:preview="preview"
|
||||
:context="context"
|
||||
:data-id="rule.id"
|
||||
@input="updateRule(rule.id, $event)"
|
||||
|
@ -61,10 +62,15 @@ export default {
|
|||
value: Array,
|
||||
filters: Object,
|
||||
maxRules: {
|
||||
tpye: Number,
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0
|
||||
},
|
||||
preview: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
context: {
|
||||
type: Object,
|
||||
required: false
|
||||
|
|
|
@ -10,10 +10,11 @@
|
|||
:type="type"
|
||||
:filters="filters"
|
||||
:context="context"
|
||||
:preview="preview"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="isShort"
|
||||
v-if="isShort && preview"
|
||||
class="tw-mg-l-1 tw-pd-x-1 tw-border-l tw-flex tw-align-items-center ffz--profile__icon tw-relative ffz-il-tooltip__container"
|
||||
>
|
||||
<figure :class="[passes ? 'ffz-i-ok' : 'ffz-i-cancel']" />
|
||||
|
@ -31,7 +32,7 @@
|
|||
:class="[isShort ? '' : 'tw-mg-l-1']"
|
||||
class="tw-border-l tw-pd-l-1 tw-flex tw-flex-column tw-flex-wrap tw-justify-content-start tw-align-items-start"
|
||||
>
|
||||
<div v-if="! isShort" class="tw-mg-b-1 tw-border-b tw-pd-b-1 tw-full-width tw-flex tw-justify-content-center ffz--profile__icon tw-relative ffz-il-tooltip__container">
|
||||
<div v-if="! isShort && preview" class="tw-mg-b-1 tw-border-b tw-pd-b-1 tw-full-width tw-flex tw-justify-content-center ffz--profile__icon tw-relative ffz-il-tooltip__container">
|
||||
<figure :class="[passes ? 'ffz-i-ok' : 'ffz-i-cancel']" />
|
||||
<div class="ffz-il-tooltip ffz-il-tooltip--up ffz-il-tooltip--align-right">
|
||||
<span v-if="passes">
|
||||
|
@ -80,6 +81,11 @@ export default {
|
|||
context: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
preview: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -93,7 +99,7 @@ export default {
|
|||
|
||||
computed: {
|
||||
passes() {
|
||||
return this.tester && this.tester(this.context);
|
||||
return this.preview && this.tester && this.tester(this.context);
|
||||
},
|
||||
|
||||
type() {
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
v-model="rules"
|
||||
:filters="filters"
|
||||
:context="test_context"
|
||||
:preview="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
60
src/modules/main_menu/components/setting-filter-editor.vue
Normal file
60
src/modules/main_menu/components/setting-filter-editor.vue
Normal file
|
@ -0,0 +1,60 @@
|
|||
<template lang="html">
|
||||
<div class="ffz--widget ffz--filter-editor tw-border-t tw-pd-y-1">
|
||||
<div
|
||||
v-if="source && source !== profile"
|
||||
class="tw-c-background-accent tw-c-text-overlay tw-pd-1 tw-mg-b-1"
|
||||
>
|
||||
<span class="ffz-i-info" />
|
||||
{{ t('setting.warn-inheritence', 'These values are being overridden by another profile and may not take effect.') }}
|
||||
</div>
|
||||
|
||||
<filter-editor
|
||||
:value="rules"
|
||||
:filters="filters"
|
||||
:context="test_context"
|
||||
:preview="preview"
|
||||
@input="onInput"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {deep_copy} from 'utilities/object';
|
||||
|
||||
import SettingMixin from '../setting-mixin';
|
||||
|
||||
export default {
|
||||
mixins: [SettingMixin],
|
||||
props: ['item', 'context'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
filters: this.item.data(),
|
||||
test_context: this.item.test_context ? this.item.test_context() : {},
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
preview() {
|
||||
return this.item.preview || false
|
||||
},
|
||||
|
||||
rules() {
|
||||
if ( ! Array.isArray(this.value) || this.value.length <= 0 )
|
||||
return [];
|
||||
|
||||
return this.value.filter(x => x.v).map(x => x.v);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onInput(data) {
|
||||
const val = deep_copy(data);
|
||||
this.set(val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
|
@ -13,6 +13,9 @@ import { getFontsList, useFont } from 'utilities/fonts';
|
|||
|
||||
const STYLE_VALIDATOR = createElement('span');
|
||||
|
||||
const LEFT_CONTROLS = '.video-player__default-player .player-controls__left-control-group';
|
||||
const RIGHT_CONTROLS = '.video-player__default-player .player-controls__right-control-group';
|
||||
|
||||
const HAS_COMPRESSOR = window.AudioContext && window.DynamicsCompressorNode != null,
|
||||
HAS_GAIN = HAS_COMPRESSOR && window.GainNode != null;
|
||||
|
||||
|
@ -75,6 +78,9 @@ export default class PlayerBase extends Module {
|
|||
|
||||
this.onShortcut = this.onShortcut.bind(this);
|
||||
|
||||
this.LEFT_CONTROLS = LEFT_CONTROLS;
|
||||
this.RIGHT_CONTROLS = RIGHT_CONTROLS;
|
||||
|
||||
this.registerSettings();
|
||||
}
|
||||
|
||||
|
@ -1171,7 +1177,7 @@ export default class PlayerBase extends Module {
|
|||
addGainSlider(inst, visible_only, tries = 0) {
|
||||
const outer = inst.props.containerRef || this.fine.getChildNode(inst),
|
||||
video = inst.props.mediaPlayerInstance?.mediaSinkManager?.video || inst.props.mediaPlayerInstance?.core?.mediaSinkManager?.video,
|
||||
container = outer && outer.querySelector('.video-player__default-player .player-controls__left-control-group');
|
||||
container = outer && outer.querySelector(LEFT_CONTROLS);
|
||||
let gain = video != null && video._ffz_compressed && video._ffz_gain;
|
||||
|
||||
if ( this.areControlsDisabled(inst) )
|
||||
|
@ -1302,7 +1308,7 @@ export default class PlayerBase extends Module {
|
|||
addCompressorButton(inst, visible_only, tries = 0) {
|
||||
const outer = inst.props.containerRef || this.fine.getChildNode(inst),
|
||||
video = inst.props.mediaPlayerInstance?.mediaSinkManager?.video || inst.props.mediaPlayerInstance?.core?.mediaSinkManager?.video,
|
||||
container = outer && outer.querySelector('.video-player__default-player .player-controls__left-control-group'),
|
||||
container = outer && outer.querySelector(LEFT_CONTROLS),
|
||||
has_comp = HAS_COMPRESSOR && video != null && this.settings.get('player.compressor.enable');
|
||||
|
||||
if ( ! container ) {
|
||||
|
@ -1730,7 +1736,7 @@ export default class PlayerBase extends Module {
|
|||
const outer = inst.props.containerRef || this.fine.getChildNode(inst),
|
||||
video = inst.props.mediaPlayerInstance?.mediaSinkManager?.video || inst.props.mediaPlayerInstance?.core?.mediaSinkManager?.video,
|
||||
is_fs = video && document.fullscreenElement && document.fullscreenElement.contains(video),
|
||||
container = outer && outer.querySelector('.video-player__default-player .player-controls__right-control-group'),
|
||||
container = outer && outer.querySelector(RIGHT_CONTROLS),
|
||||
has_pip = document.pictureInPictureEnabled && this.settings.get('player.button.pip');
|
||||
|
||||
if ( ! container ) {
|
||||
|
@ -1833,7 +1839,7 @@ export default class PlayerBase extends Module {
|
|||
|
||||
addResetButton(inst, tries = 0) {
|
||||
const outer = inst.props.containerRef || this.fine.getChildNode(inst),
|
||||
container = outer && outer.querySelector('.video-player__default-player .player-controls__right-control-group'),
|
||||
container = outer && outer.querySelector(RIGHT_CONTROLS),
|
||||
has_reset = this.settings.get('player.button.reset');
|
||||
|
||||
if ( ! container ) {
|
||||
|
@ -2055,7 +2061,7 @@ export default class PlayerBase extends Module {
|
|||
return;
|
||||
|
||||
const outer = inst.props.containerRef || this.fine.getChildNode(inst),
|
||||
container = outer && outer.querySelector('.video-player__default-player .player-controls__right-control-group');
|
||||
container = outer && outer.querySelector(RIGHT_CONTROLS);
|
||||
|
||||
if ( ! container )
|
||||
return;
|
||||
|
|
|
@ -45,7 +45,8 @@ export const RERENDER_SETTINGS = [
|
|||
'chat.filtering.display-deleted',
|
||||
'chat.filtering.display-mod-action',
|
||||
'chat.replies.style',
|
||||
'chat.bits.cheer-notice'
|
||||
'chat.bits.cheer-notice',
|
||||
'chat.filtering.hidden-tokens'
|
||||
];
|
||||
|
||||
export const UPDATE_BADGE_SETTINGS = [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue