1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-06 22:30:57 +00:00
* Added: `Current Category` rule type for profile rules. (Ironically, does not currently apply when on the directory page for a category.)
* Fixed: Various chat input related features breaking, including Room Actions and tab-completion of emotes.
* Fixed: Alignment of certain chat settings menu elements.
* Maintenance: Update our copy of the `CHAT_TYPES` enum with new types from Twitch's client.
This commit is contained in:
SirStendec 2019-10-22 18:32:56 -04:00
parent bbaf96584c
commit 903b0b234c
9 changed files with 199 additions and 8 deletions

View file

@ -1,7 +1,7 @@
{
"name": "frankerfacez",
"author": "Dan Salvato LLC",
"version": "4.14.10",
"version": "4.14.11",
"description": "FrankerFaceZ is a Twitch enhancement suite.",
"license": "Apache-2.0",
"scripts": {

View file

@ -0,0 +1,138 @@
<template>
<section class="tw-flex-grow-1 tw-align-self-start">
<div class="tw-flex tw-align-items-center">
<label :for="'category$' + id">
{{ t(type.i18n, type.title) }}
</label>
<div class="ffz--search-avatar tw-mg-x-05 tw-card-img--size-2">
<aspect :ratio="1/1.33">
<img
v-if="current"
:alt="current.displayName || current.name"
:src="current.boxArtURL"
class="tw-avatar__img tw-image"
>
</aspect>
</div>
<autocomplete
v-slot="slot"
:input-id="'category$' + id"
:items="fetchCategories"
:value="search"
:suggest-on-focus="true"
:escape-to-clear="false"
class="tw-flex-grow-1"
@selected="onSelected"
>
<div class="tw-pd-x-1 tw-pd-y-05">
<div class="tw-card tw-relative">
<div class="tw-align-items-center tw-flex tw-flex-nowrap tw-flex-row">
<div class="tw-card-img tw-card-img--size-3 tw-flex-shrink-0 tw-overflow-hidden">
<aspect :ratio="1/1.33">
<img
:alt="slot.item.displayName"
:src="slot.item.boxArtURL"
class="tw-image"
>
</aspect>
</div>
<div class="tw-card-body tw-overflow-hidden tw-relative">
<p class="tw-pd-x-1">
{{ slot.item.displayName }}
</p>
</div>
</div>
</div>
</div>
</autocomplete>
</div>
</section>
</template>
<script>
import {debounce, deep_copy} from 'utilities/object';
let last_id = 0;
export default {
props: ['value', 'type', 'filters', 'context'],
data() {
return {
id: last_id++,
current: null,
loaded_id: null
}
},
computed: {
search() {
return this.current && this.current.displayName || this.value.data.name;
}
},
watch: {
value: {
handler() {
this.cacheCategory();
},
deep: true
}
},
created() {
const ffz = FrankerFaceZ.get();
this.loader = ffz.resolve('site.twitch_data');
this.cacheCategory = debounce(this.cacheCategory, 50);
},
beforeDestroy() {
this.cacheCategory = null;
},
mounted() {
this.cacheCategory();
},
methods: {
async cacheCategory() {
if ( ! this.loader || this.loaded_id === this.value.data.id )
return;
this.current = null;
this.loaded_id = this.value.data.id;
if ( ! this.loaded_id )
return;
const data = await this.loader.getCategory(this.loaded_id);
if ( data )
this.current = deep_copy(data);
else
this.current = null;
},
async fetchCategories(query) {
if ( ! this.loader )
return [];
const data = await this.loader.getMatchingCategories(query);
if ( ! data || ! data.items )
return [];
return deep_copy(data.items);
},
onSelected(item) {
this.current = item;
this.value.data.name = item?.name || null;
this.value.data.id = item?.id || null;
this.value.data.boxArtURL = item?.boxArtURL || null;
}
}
}
</script>

View file

@ -142,7 +142,6 @@ export const Time = {
editor: () => import(/* webpackChunkName: 'main-menu' */ './components/time.vue')
}
export const TheaterMode = {
createTest(config) {
return ctx => ctx.ui && ctx.ui.theatreModeEnabled === config;
@ -262,3 +261,25 @@ export const Channel = {
}),
editor: () => import(/* webpackChunkName: 'main-menu' */ './components/channel.vue')
};
export const Category = {
createTest(config = {}) {
const name = config.name,
id = config.id;
if ( ! id || ! name )
return () => false;
return ctx => ctx.categoryID === id || (ctx.categoryID == null && ctx.category === name);
},
title: 'Current Category',
i18n: 'settings.filter.category',
default: () => ({
name: null,
id: null
}),
editor: () => import(/* webpackChunkName: 'main-menu' */ './components/category.vue')
}

View file

@ -85,23 +85,36 @@ export default class Channel extends Module {
});
this.ChannelPage.on('mount', inst => {
const category = get('state.video.game', inst) || get('state.clip.game', inst) || get('state.channel.broadcastSettings.game', inst);
this.settings.updateContext({
channel: get('state.channel.login', inst),
channelID: get('state.channel.id', inst)
channelID: get('state.channel.id', inst),
channelColor: get('state.primaryColorHex', inst),
category: category?.name,
categoryID: category?.id
});
});
this.ChannelPage.on('unmount', () => {
this.settings.updateContext({
channel: null,
channelID: null
channelID: null,
channelColor: null,
category: null,
categoryID: null
});
});
this.ChannelPage.on('update', inst => {
const category = get('state.video.game', inst) || get('state.clip.game', inst) || get('state.channel.broadcastSettings.game', inst);
this.settings.updateContext({
channel: get('state.channel.login', inst),
channelID: get('state.channel.id', inst)
channelID: get('state.channel.id', inst),
channelColor: get('state.primaryColorHex', inst),
category: category?.name,
categoryID: category?.id
});
if ( this.settings.get('channel.hosting.enable') || has(inst.state, 'hostMode') || has(inst.state, 'hostedChannel') )

View file

@ -110,6 +110,8 @@ const CHAT_TYPES = make_enum(
'RewardGift',
'SubMysteryGift',
'AnonSubMysteryGift',
'StandardPayForward',
'CommunityPayForward',
'FirstCheerMessage',
'BitsBadgeTierMessage',
'InlinePrivateCallout',

View file

@ -85,7 +85,7 @@ export default class Input extends Module {
this.ChatInput = this.fine.define(
'chat-input',
n => n && n.setChatInputRef && n.setLocalAutocompleteInputRef,
n => n && n.setLocalChatInputRef && n.setLocalAutocompleteInputRef,
Twilight.CHAT_ROUTES
);

View file

@ -110,7 +110,7 @@ export default class SettingsMenu extends Module {
if ( ! this.ffzPauseClick )
this.ffzPauseClick = () => this.setState({ffzPauseMenu: ! this.state.ffzPauseMenu});
return (<div class="tw-absolute tw-balloon tw-balloon--auto tw-balloon--up tw-block" data-a-target="chat-settings-balloon">
return (<div class="tw-absolute tw-balloon tw-balloon--auto tw-balloon--right tw-balloon--up tw-block" data-a-target="chat-settings-balloon" style={{marginRight: '-5.3rem'}}>
<div class="tw-border-radius-large tw-c-background-base tw-c-text-inherit tw-elevation-2">
<div class="chat-settings__popover">
<div class="chat-settings__header tw-align-items-center tw-c-background-base tw-flex tw-pd-x-1 tw-relative">

View file

@ -0,0 +1,8 @@
query FFZ_GetGame($id: ID, $name: String) {
game(name: $name, id: $id) {
id
name
displayName
boxArtURL(width: 40, height: 56)
}
}

View file

@ -141,6 +141,15 @@ export default class TwitchData extends Module {
};
}
async getCategory(id, name) {
const data = await this.queryApollo(
require('./data/category-fetch.gql'),
{ id, name }
);
return get('data.game', data);
}
// ========================================================================
// Users