mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-31 23:18:31 +00:00
4.20.38
* Fixed: Emotes not appearing in Chat on Videos. * Fixed: Extra, unnecessary `Pause Chat` section appearing in the Twitch chat settings menu. * Fixed: Hide the number of unread whispers when hiding the whispers button. * Fixed: The alternative live viewer display sometimes incorrectly displaying zero when loading the page. * Fixed: Precision issue when displaying localized numbers in some cases.
This commit is contained in:
parent
943e0fdc18
commit
472f9472ee
8 changed files with 93 additions and 14 deletions
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "frankerfacez",
|
||||
"author": "Dan Salvato LLC",
|
||||
"version": "4.20.37",
|
||||
"version": "4.20.38",
|
||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
|
|
|
@ -1388,9 +1388,15 @@ export default class Chat extends Module {
|
|||
ret = `${content.alt}${content.cheerAmount}`;
|
||||
|
||||
} else if ( content.images ) {
|
||||
const url = (content.images.themed ? content.images.dark : content.images.sources),
|
||||
match = url && /\/emoticons\/v1\/(\d+)\/[\d.]+$/.exec(url['1x']),
|
||||
const url = (content.images.themed ? content.images.dark : content.images.sources);
|
||||
let id = content.emoteID;
|
||||
if ( ! id ) {
|
||||
const match = url && (
|
||||
/\/emoticons\/v1\/(\d+)\/[\d.]+$/.exec(url['1x']) ||
|
||||
/\/emoticons\/v2\/(\d+)\//.exec(url['1x'])
|
||||
);
|
||||
id = match && match[1];
|
||||
}
|
||||
|
||||
ret = content.alt;
|
||||
|
||||
|
|
|
@ -369,6 +369,24 @@ export default class Channel extends Module {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: See if we can read this data directly from Apollo's cache.
|
||||
// Also, test how it works with videos and clips.
|
||||
/*const raw_game = el.querySelector('a[data-a-target="stream-game-link"]')?.textContent;
|
||||
if ( ! el._ffz_game_cache_updating && el._ffz_game_cache !== raw_game ) {
|
||||
el._ffz_game_cache_updating = true;
|
||||
el._ffz_game_cache = raw_game;
|
||||
|
||||
this.twitch_data.getUserGame(props.channelID, props.channelLogin).then(game => {
|
||||
el._ffz_game_cache_updating = false;
|
||||
this.settings.updateContext({
|
||||
category: game?.displayName,
|
||||
categoryID: game?.id
|
||||
})
|
||||
}).catch(() => {
|
||||
el._ffz_game_cache_updating = false;
|
||||
});
|
||||
}*/
|
||||
|
||||
const other_props = react.child.child?.child?.child?.child?.child?.child?.child?.child?.child?.memoizedProps,
|
||||
title = other_props?.title;
|
||||
|
||||
|
@ -438,8 +456,19 @@ export default class Channel extends Module {
|
|||
getViewerCount: () => {
|
||||
const thing = cont.querySelector('p[data-a-target="animated-channel-viewers-count"]'),
|
||||
r = thing && this.fine.getReactInstance(thing),
|
||||
p = r?.memoizedProps?.children?.props;
|
||||
c = r?.memoizedProps?.children;
|
||||
|
||||
// Sometimes, on early loads, the animated element
|
||||
// is actually a static string.
|
||||
if ( typeof c === 'string' && /^[0-9,.]+$/.test(c) ) {
|
||||
try {
|
||||
const val = parseInt(c.replace(/,/, ''), 10);
|
||||
if ( ! isNaN(val) && isFinite(val) && val > 0 )
|
||||
return val;
|
||||
} catch(err) { /* no-op */ }
|
||||
}
|
||||
|
||||
const p = c?.props;
|
||||
if ( p && p.value != null )
|
||||
return p.value;
|
||||
|
||||
|
|
|
@ -25,11 +25,11 @@ export default class SettingsMenu extends Module {
|
|||
Twilight.CHAT_ROUTES
|
||||
);
|
||||
|
||||
this.ModSettingsMenu = this.fine.define(
|
||||
/*this.ModSettingsMenu = this.fine.define(
|
||||
'chat-mod-settings',
|
||||
n => n.renderModerationSettingsLink && n.onChatClear,
|
||||
Twilight.CHAT_ROUTES
|
||||
);
|
||||
);*/
|
||||
}
|
||||
|
||||
async onEnable() {
|
||||
|
@ -71,7 +71,7 @@ export default class SettingsMenu extends Module {
|
|||
</div>}
|
||||
</div>);
|
||||
|
||||
const f = t.chat.context.get('chat.scroller.freeze'),
|
||||
/*const f = t.chat.context.get('chat.scroller.freeze'),
|
||||
reason = f === 2 ? t.i18n.t('key.ctrl', 'Ctrl Key') :
|
||||
f === 3 ? t.i18n.t('key.meta', 'Meta Key') :
|
||||
f === 4 ? t.i18n.t('key.alt', 'Alt Key') :
|
||||
|
@ -96,7 +96,7 @@ export default class SettingsMenu extends Module {
|
|||
<figure class="tw-svg ffz-i-right-dir" />
|
||||
</div>
|
||||
</button>
|
||||
</div>);
|
||||
</div>);*/
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ export default class SettingsMenu extends Module {
|
|||
this.SettingsMenu.forceUpdate();
|
||||
});
|
||||
|
||||
this.ModSettingsMenu.ready(cls => {
|
||||
/*this.ModSettingsMenu.ready(cls => {
|
||||
const old_render = cls.prototype.render;
|
||||
|
||||
cls.prototype.render = function() {
|
||||
|
@ -193,7 +193,7 @@ export default class SettingsMenu extends Module {
|
|||
}
|
||||
|
||||
this.ModSettingsMenu.forceUpdate();
|
||||
})
|
||||
})*/
|
||||
|
||||
this.SettingsMenu.on('unmount', inst => {
|
||||
inst.ffzSettingsClick = null;
|
||||
|
|
|
@ -33,7 +33,7 @@ const CLASSES = {
|
|||
'player-rerun-bar': '.channel-root__player-container div.tw-c-text-overlay:not([data-a-target="hosting-ui-header"])',
|
||||
|
||||
'pinned-cheer': '.pinned-cheer,.pinned-cheer-v2,.channel-leaderboard',
|
||||
'whispers': 'body .whispers-open-threads,.tw-core-button[data-a-target="whisper-box-button"]',
|
||||
'whispers': 'body .whispers-open-threads,.tw-core-button[data-a-target="whisper-box-button"],.whispers__pill',
|
||||
|
||||
'dir-live-ind': '.live-channel-card[data-ffz-type="live"] .tw-channel-status-text-indicator, article[data-ffz-type="live"] .tw-channel-status-text-indicator',
|
||||
'profile-hover': '.preview-card .tw-relative:hover .ffz-channel-avatar',
|
||||
|
|
12
src/utilities/data/user-game.gql
Normal file
12
src/utilities/data/user-game.gql
Normal file
|
@ -0,0 +1,12 @@
|
|||
query FFZ_UserGame($id: ID, $login: String) {
|
||||
user(id: $id, login: $login) {
|
||||
id
|
||||
broadcastSettings {
|
||||
id
|
||||
game {
|
||||
id
|
||||
displayName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,9 +51,9 @@ export const DEFAULT_TYPES = {
|
|||
|
||||
number(val, node) {
|
||||
if ( typeof val !== 'number' ) {
|
||||
let new_val = parseInt(val, 10);
|
||||
let new_val = parseFloat(val);
|
||||
if ( isNaN(new_val) || ! isFinite(new_val) )
|
||||
new_val = parseFloat(val);
|
||||
new_val = parseInt(val, 10);
|
||||
if ( isNaN(new_val) || ! isFinite(new_val) )
|
||||
return val;
|
||||
|
||||
|
@ -254,7 +254,16 @@ export default class TranslationCore {
|
|||
formatNumber(value, format) {
|
||||
let formatter = this.numberFormats.get(format);
|
||||
if ( ! formatter ) {
|
||||
formatter = new Intl.NumberFormat(this.locale, this.formats.number[format]);
|
||||
if ( this.formats.number[format] )
|
||||
formatter = new Intl.NumberFormat(this.locale, this.formats.number[format]);
|
||||
else if ( typeof format === 'number' )
|
||||
formatter = new Intl.NumberFormat(this.locale, {
|
||||
minimumFractionDigits: format,
|
||||
maximumFractionDigits: format
|
||||
});
|
||||
else
|
||||
formatter = new Intl.NumberFormat(this.locale);
|
||||
|
||||
this.numberFormats.set(format, formatter);
|
||||
}
|
||||
|
||||
|
|
|
@ -265,6 +265,29 @@ export default class TwitchData extends Module {
|
|||
return get('data.user', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries Apollo for the user's current game, details given the user id or name. One of (id, login) MUST be specified
|
||||
* @function getUserGame
|
||||
* @memberof TwitchData
|
||||
* @async
|
||||
*
|
||||
* @param {int|string|null|undefined} id - the user id number (can be an integer string)
|
||||
* @param {string|null|undefined} login - the username
|
||||
* @returns {Object} information about the requested user
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* console.log(this.twitch_data.getUserGame(19571641, null));
|
||||
*/
|
||||
async getUserGame(id, login) {
|
||||
const data = await this.queryApollo(
|
||||
await import(/* webpackChunkName: 'queries' */ './data/user-game.gql'),
|
||||
{ id, login }
|
||||
);
|
||||
|
||||
return get('data.user.broadcastSettings.game', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries Apollo for the logged in user's relationship to the channel with given the id or name. One of (id, login) MUST be specified
|
||||
* @function getUserSelf
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue