1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-07-31 23:18:31 +00:00
* 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:
SirStendec 2020-09-15 19:17:29 -04:00
parent 943e0fdc18
commit 472f9472ee
8 changed files with 93 additions and 14 deletions

View file

@ -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": {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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',

View file

@ -0,0 +1,12 @@
query FFZ_UserGame($id: ID, $login: String) {
user(id: $id, login: $login) {
id
broadcastSettings {
id
game {
id
displayName
}
}
}
}

View file

@ -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);
}

View file

@ -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