diff --git a/package.json b/package.json index 2a1f92e3..bd7ea275 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.20.41", + "version": "4.20.42", "description": "FrankerFaceZ is a Twitch enhancement suite.", "license": "Apache-2.0", "scripts": { diff --git a/src/modules/chat/emoji.js b/src/modules/chat/emoji.js index 6f4b8515..89888ec1 100644 --- a/src/modules/chat/emoji.js +++ b/src/modules/chat/emoji.js @@ -78,6 +78,11 @@ export default class Emoji extends Module { this.settings.add('chat.emoji.style', { default: 'twitter', + process(ctx, val) { + if ( val != 0 && ! IMAGE_PATHS[val] ) + return 'twitter'; + return val; + }, ui: { path: 'Chat > Appearance >> Emoji', title: 'Emoji Style', diff --git a/src/modules/chat/index.js b/src/modules/chat/index.js index 9be248eb..a3e81298 100644 --- a/src/modules/chat/index.js +++ b/src/modules/chat/index.js @@ -1665,12 +1665,12 @@ export default class Chat extends Module { if ( data.error ) data = { v: 5, - title: this.i18n.t('card.error', 'An error occured.'), + title: this.i18n.t('card.error', 'An error occurred.'), description: data.error, short: { type: 'header', image: {type: 'image', url: ERROR_IMAGE}, - title: {type: 'i18n', key: 'card.error', phrase: 'An error occured.'}, + title: {type: 'i18n', key: 'card.error', phrase: 'An error occurred.'}, subtitle: data.error } } diff --git a/src/modules/main_menu/components/async-text.vue b/src/modules/main_menu/components/async-text.vue index e9afaa81..94ede8fc 100644 --- a/src/modules/main_menu/components/async-text.vue +++ b/src/modules/main_menu/components/async-text.vue @@ -100,7 +100,7 @@ export default { if ( ! response.ok ) { this.uploading = false; - this.url = 'An error occured.'; + this.url = 'An error occurred.'; } this.url = await response.text(); diff --git a/src/modules/main_menu/components/changelog.vue b/src/modules/main_menu/components/changelog.vue index 1c171a4d..08014d6d 100644 --- a/src/modules/main_menu/components/changelog.vue +++ b/src/modules/main_menu/components/changelog.vue @@ -91,7 +91,7 @@
- {{ t('home.changelog.error', 'An error occured loading changes from GitHub.') }} + {{ t('home.changelog.error', 'An error occurred loading changes from GitHub.') }}

diff --git a/src/modules/main_menu/components/game-list-editor.vue b/src/modules/main_menu/components/game-list-editor.vue new file mode 100644 index 00000000..1742b75a --- /dev/null +++ b/src/modules/main_menu/components/game-list-editor.vue @@ -0,0 +1,157 @@ + + + \ No newline at end of file diff --git a/src/modules/main_menu/index.js b/src/modules/main_menu/index.js index 87050eee..6988a9cf 100644 --- a/src/modules/main_menu/index.js +++ b/src/modules/main_menu/index.js @@ -10,7 +10,8 @@ import {get, has, deep_copy} from 'utilities/object'; import Dialog from 'utilities/dialog'; -import Mixin from './setting-mixin'; +import SettingMixin from './setting-mixin'; +import ProviderMixin from './provider-mixin'; import {parse_path} from 'src/settings'; @@ -32,7 +33,8 @@ export default class MainMenu extends Module { this.load_requires = ['vue']; - this.Mixin = Mixin; + this.Mixin = this.SettingMixin = SettingMixin; + this.ProviderMixin = ProviderMixin; //this.should_enable = true; @@ -134,9 +136,9 @@ export default class MainMenu extends Module { this.scheduleUpdate(); } - openPopout() { + openPopout(item) { const win = window.open( - 'https://twitch.tv/popout/frankerfacez/chat?ffz-settings', + `https://twitch.tv/popout/frankerfacez/chat?ffz-settings${item ? `=${encodeURIComponent(item)}` : ''}`, '_blank', 'resizable=yes,scrollbars=yes,width=850,height=600' ); @@ -633,6 +635,7 @@ export default class MainMenu extends Module { const t = this, Vue = this.vue.Vue, settings = this.settings, + provider = settings.provider, context = settings.main_context, [profiles, profile_keys] = this.getProfiles(); @@ -665,6 +668,16 @@ export default class MainMenu extends Module { getFFZ: () => t.resolve('core'), + provider: { + unwrap: () => provider, + get: (...args) => provider.get(...args), + set: (...args) => provider.set(...args), + delete: (...args) => provider.delete(...args), + has: (...args) => provider.has(...args), + on: (...args) => provider.on(...args), + off: (...args) => provider.off(...args) + }, + context: { _users: 0, @@ -924,18 +937,18 @@ export default class MainMenu extends Module { close: e => ! this.dialog.exclusive && this.dialog.toggleVisible(e), - popout: e => { - if ( this.dialog.exclusive ) - return; - - this.dialog.toggleVisible(e); - if ( ! this.openPopout() ) - alert(this.i18n.t('popup.error', 'We tried opening a pop-up window and could not. Make sure to allow pop-ups from Twitch.')); // eslint-disable-line no-alert - }, - version: window.FrankerFaceZ.version_info, }; + out.popout = e => { + if ( this.dialog.exclusive ) + return; + + this.dialog.toggleVisible(e); + if ( ! this.openPopout(out.currentItem?.full_key) ) + alert(this.i18n.t('popup.error', 'We tried opening a pop-up window and could not. Make sure to allow pop-ups from Twitch.')); // eslint-disable-line no-alert + } + return out; } } \ No newline at end of file diff --git a/src/modules/main_menu/provider-mixin.js b/src/modules/main_menu/provider-mixin.js new file mode 100644 index 00000000..3b6e0107 --- /dev/null +++ b/src/modules/main_menu/provider-mixin.js @@ -0,0 +1,108 @@ +'use strict'; + +import {deep_copy} from 'utilities/object'; + +export default { + data() { + return { + value: undefined, + has_value: false, + + _unseen: false + } + }, + + created() { + const provider = this.context.provider, + setting = this.item.setting; + + provider.on('changed', this._providerChange, this); + + this.has_value = provider.has(setting); + if ( this.has_value ) + this.value = deep_copy(provider.get(setting)); + else + this.value = this.default_value; + + if ( this.item.unseen ) { + this._unseen = true; + this.item.unseen = 0; + } + }, + + destroyed() { + const provider = this.context.provider; + + provider.off('changed', this._providerChange, this); + + this.value = undefined; + this.has_value = false; + }, + + computed: { + data() { + const data = this.item.data; + if ( typeof data === 'function' ) + return data(this.value); + + return data; + }, + + unseen() { + return this._unseen || this.item.unseen > 0; + }, + + default_value() { + if ( typeof this.item.default === 'function' ) + return this.item.default(this.context); + + return deep_copy(this.item.default); + }, + + isDefault() { + return ! this.has_value + } + }, + + methods: { + _providerChange(key, val, deleted) { + if ( key !== this.item.setting ) + return; + + if ( deleted ) { + this.has_value = false; + this.value = this.default_value; + } else { + this.has_value = true; + this.value = deep_copy(val); + } + }, + + set(value) { + if ( this.item.process ) + value = this.item.process(value); + + const provider = this.context.provider, + setting = this.item.setting; + + provider.set(setting, value); + this.has_value = true; + this.value = deep_copy(value); + + if ( this.item.onUIChange ) + this.item.onUIChange(this.value); + }, + + clear() { + const provider = this.context.provider, + setting = this.item.setting; + + provider.delete(setting); + this.value = this.default_value; + this.has_value = false; + + if ( this.item.onUIChange ) + this.item.onUIChange(this.value); + } + } +} \ No newline at end of file diff --git a/src/settings/index.js b/src/settings/index.js index f257f3d3..3302afa6 100644 --- a/src/settings/index.js +++ b/src/settings/index.js @@ -565,7 +565,8 @@ export default class SettingsManager extends Module { if ( ! ui.key && ui.title ) ui.key = ui.title.toSnakeCase(); - if ( (ui.component === 'setting-select-box' || ui.component === 'setting-combo-box') && Array.isArray(ui.data) ) { + if ( (ui.component === 'setting-select-box' || ui.component === 'setting-combo-box') && Array.isArray(ui.data) && ! ui.no_i18n + && key !== 'ffzap.core.highlight_sound' ) { // TODO: Remove workaround. const i18n_base = `${ui.i18n_key || `setting.entry.${key}`}.values`; for(const value of ui.data) { if ( value.i18n_key === undefined && value.value !== undefined ) diff --git a/src/sites/twitch-twilight/modules/chat/rich_content.jsx b/src/sites/twitch-twilight/modules/chat/rich_content.jsx index 363083ac..b50f0148 100644 --- a/src/sites/twitch-twilight/modules/chat/rich_content.jsx +++ b/src/sites/twitch-twilight/modules/chat/rich_content.jsx @@ -196,7 +196,7 @@ export default class RichContent extends Module { renderBasic() { let title, description; if ( this.state.error ) { - title = t.i18n.t('card.error', 'An error occured.'); + title = t.i18n.t('card.error', 'An error occurred.'); description = this.state.error; } else if ( this.state.loaded && this.state.has_tokenizer ) { diff --git a/src/sites/twitch-twilight/modules/chat/viewer_card.jsx b/src/sites/twitch-twilight/modules/chat/viewer_card.jsx index c632fb54..840fe6e7 100644 --- a/src/sites/twitch-twilight/modules/chat/viewer_card.jsx +++ b/src/sites/twitch-twilight/modules/chat/viewer_card.jsx @@ -78,7 +78,7 @@ export default class ViewerCards extends Module { else color = 'rgba(128,170,255,0.2)'; - this.css_tweaks.set('viewer-card-highlight', `body .chat-list .chat-line__message:not(.chat-line--inline):nth-child(1n+0)[data-user="${login}"] { + this.css_tweaks.set('viewer-card-highlight', `body .chat-room .chat-line__message:not(.chat-line--inline):nth-child(1n+0)[data-user="${login}"] { background-color: ${color} !important; }`); } else diff --git a/src/sites/twitch-twilight/modules/css_tweaks/index.js b/src/sites/twitch-twilight/modules/css_tweaks/index.js index 31f7c9cd..c4b426bf 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/index.js +++ b/src/sites/twitch-twilight/modules/css_tweaks/index.js @@ -241,9 +241,12 @@ export default class CSSTweaks extends Module { }); this.settings.add('layout.minimal-navigation', { - requires: ['layout.theatre-navigation'], + requires: ['layout.theatre-navigation', 'context.isWatchParty'], default: false, process(ctx, val) { + if ( ctx.get('context.isWatchParty') ) + return false; + return ctx.get('layout.theatre-navigation') ? true : val; }, @@ -288,7 +291,7 @@ export default class CSSTweaks extends Module { default: true, ui: { path: 'Appearance > Layout >> Top Navigation', - title: 'Show Twitch Prime offers.', + title: 'Show Prime Gaming Loot.', component: 'setting-check-box' }, changed: val => this.toggleHide('prime-offers', !val) diff --git a/src/sites/twitch-twilight/modules/css_tweaks/styles/theatre-metadata.scss b/src/sites/twitch-twilight/modules/css_tweaks/styles/theatre-metadata.scss index 90ae1b9f..1b8a7213 100644 --- a/src/sites/twitch-twilight/modules/css_tweaks/styles/theatre-metadata.scss +++ b/src/sites/twitch-twilight/modules/css_tweaks/styles/theatre-metadata.scss @@ -2,7 +2,7 @@ .channel-info-content > div:first-child, .channel-info-bar { position: fixed; - bottom: 10rem; + bottom: 17rem; left: 5rem; right: calc(var(--ffz-chat-width) + 40rem); z-index: 3500; diff --git a/src/sites/twitch-twilight/modules/directory/game.jsx b/src/sites/twitch-twilight/modules/directory/game.jsx index b9dbfd42..c93ed242 100644 --- a/src/sites/twitch-twilight/modules/directory/game.jsx +++ b/src/sites/twitch-twilight/modules/directory/game.jsx @@ -21,9 +21,23 @@ export default class Game extends SiteModule { this.GameHeader = this.fine.define( 'game-header', - n => n.props && n.props.data && n.getBannerImage && n.getFollowButton, + n => n.props && n.props.data && n.getBannerImage && n.getDirectoryCountAndTags, ['dir-game-index', 'dir-community', 'dir-game-videos', 'dir-game-clips', 'dir-game-details'] ); + + this.settings.addUI('directory.game.blocked-games', { + path: 'Directory > Categories @{"description": "Please note that due to limitations in Twitch\'s website, names here must be formatted exactly as displayed in your client. For best results, you can block or unblock categories directly from directory pages."} >> Blocked', + component: 'game-list-editor', + default: [], + onUIChange: () => this.parent.updateCards() + }); + + this.settings.addUI('directory.game.hidden-thumbnails', { + path: 'Directory > Categories >> Hidden Thumbnails', + component: 'game-list-editor', + default: [], + onUIChange: () => this.parent.updateCards() + }); } onEnable() { @@ -36,6 +50,15 @@ export default class Game extends SiteModule { }) }); + this.settings.provider.on('changed', key => { + if ( key === 'directory.game.blocked-games' || key === 'directory.game.hidden-thumbnails' ) { + this.parent.updateCards(); + + for(const inst of this.GameHeader.instances) + this.updateGameHeader(inst); + } + }); + this.GameHeader.ready((cls, instances) => { for(const inst of instances) this.updateGameHeader(inst); diff --git a/src/sites/twitch-twilight/modules/directory/index.jsx b/src/sites/twitch-twilight/modules/directory/index.jsx index 00965c54..c3ec8f15 100644 --- a/src/sites/twitch-twilight/modules/directory/index.jsx +++ b/src/sites/twitch-twilight/modules/directory/index.jsx @@ -57,9 +57,10 @@ export default class Directory extends SiteModule { default: 2, ui: { - path: 'Directory > Channels >> Blocked and Hidden Categories', + path: 'Directory > Categories >> Hidden Thumbnail Style @{"sort": 100}', title: 'Hidden Style', component: 'setting-select-box', + sort: 100, data: [ {value: 0, title: 'Replace Image'}, @@ -79,9 +80,10 @@ export default class Directory extends SiteModule { default: false, ui: { - path: 'Directory > Channels >> Blocked and Hidden Categories', + path: 'Directory > Categories >> Hidden Thumbnail Style', title: 'Reveal hidden entries on mouse hover.', - component: 'setting-check-box' + component: 'setting-check-box', + sort: 101 }, changed: val => this.css_tweaks.toggle('dir-reveal', val) @@ -329,7 +331,7 @@ export default class Directory extends SiteModule { if ( ! props?.channelLogin ) return; - const game = props.gameTitle || props.trackingProps?.categoryName; + const game = props.gameTitle || props.trackingProps?.categoryName || props.trackingProps?.category; el.classList.toggle('ffz-hide-thumbnail', this.settings.provider.get('directory.game.hidden-thumbnails', []).includes(game)); el.dataset.ffzType = props.streamType; diff --git a/src/sites/twitch-twilight/modules/featured-follow.vue b/src/sites/twitch-twilight/modules/featured-follow.vue index 880b862b..61036167 100644 --- a/src/sites/twitch-twilight/modules/featured-follow.vue +++ b/src/sites/twitch-twilight/modules/featured-follow.vue @@ -30,7 +30,7 @@
- {{ t('featured-follow.error', 'An error occured.') }} + {{ t('featured-follow.error', 'An error occurred.') }}