diff --git a/src/main.js b/src/main.js index 2fc617f0..753e68ed 100644 --- a/src/main.js +++ b/src/main.js @@ -100,7 +100,7 @@ class FrankerFaceZ extends Module { FrankerFaceZ.Logger = Logger; const VER = FrankerFaceZ.version_info = { - major: 4, minor: 0, revision: 0, extra: '-rc12.20', + major: 4, minor: 0, revision: 0, extra: '-rc12.21', commit: __git_commit__, build: __webpack_hash__, toString: () => diff --git a/src/modules/chat/index.js b/src/modules/chat/index.js index 350b1336..67b77280 100644 --- a/src/modules/chat/index.js +++ b/src/modules/chat/index.js @@ -586,13 +586,14 @@ export default class Chat extends Module { if ( login ) { const other = this.users[login]; if ( other ) { - if ( other !== this && ! no_login ) { + if ( other !== user && ! no_login ) { // If the other has an ID, something weird happened. Screw it // and just take over. if ( other.id ) this.users[login] = user; else { - // TODO: Merge Logic~~ + user.merge(other); + other.destroy(true); } } } else @@ -645,13 +646,14 @@ export default class Chat extends Module { if ( login ) { const other = this.rooms[login]; if ( other ) { - if ( other !== this && ! no_login ) { + if ( other !== room && ! no_login ) { // If the other has an ID, something weird happened. Screw it // and just take over. if ( other.id ) this.rooms[login] = room; else { - // TODO: Merge Logic~~ + room.merge(other); + other.destroy(true); } } diff --git a/src/modules/chat/room.js b/src/modules/chat/room.js index 818bae5f..8946ba56 100644 --- a/src/modules/chat/room.js +++ b/src/modules/chat/room.js @@ -56,6 +56,7 @@ export default class Room { user.destroy(); } + this.refs = null; this.users = null; this.user_ids = null; @@ -83,6 +84,63 @@ export default class Room { } + merge(other) { + if ( ! this.login && other.login ) + this.login = other.login; + + // We skip a lot of data, assuming that we got valid information from FFZ's API. + + if ( other.refs ) + for(const ref of other.refs) + this.ref(ref); + + if ( other.emote_sets && other.emote_sets._sources ) { + for(const [provider, sets] of other.emote_sets._sources.entries()) { + for(const set_id of sets) + this.addSet(provider, set_id); + } + } + + if ( other.data && ! this.data ) { + this.data = other.data; + if ( this.data.css ) + this.style.set('css', this.data.css); + else + this.style.delete('css'); + + this.buildModBadgeCSS(); + } + + if ( other.badges && ! this.badges ) { + this.badges = other.badges; + this.buildBadgeCSS(); + } + + if ( other.bitsConfig && ! this.bitsConfig ) { + this.bitsConfig = other.bitsConfig; + this.buildBitsCSS(); + } + + const handled_users = new Set; + + if ( other.users ) + for(const user of Object.values(other.users)) { + if ( ! user.destroyed && ! handled_users.has(user) ) { + this.getUser(user.id, user.login).merge(user); + handled_users.add(user); + } + } + + if ( other.user_ids ) + for(const user of Object.values(other.user_ids)) { + if ( ! user.destroyed && ! handled_users.has(user) ) { + this.getUser(user.id, user.login).merge(user); + handled_users.add(user); + } + } + } + + get id() { return this._id; } @@ -111,6 +169,8 @@ export default class Room { if ( old_room && old_room !== this ) old_room.login = null; + // Make sure we didn't have a funky loop thing happen. + this._login = val; this.manager.rooms[val] = this; this.manager.socket.subscribe(this, `room.${val}`); this.manager.emit(':room-update-login', this, val); @@ -162,13 +222,14 @@ export default class Room { if ( login ) { const other = this.users[login]; if ( other ) { - if ( other !== this && ! no_login ) { + if ( other !== user && ! no_login ) { // If the other has an ID, something weird happened. Screw it // and just take over. if ( other.id ) this.users[login] = user; else { - // TODO: Merge Logic~~ + user.merge(other); + other.destroy(); } } } else diff --git a/src/modules/chat/user.js b/src/modules/chat/user.js index 9f7b9508..ba4318ac 100644 --- a/src/modules/chat/user.js +++ b/src/modules/chat/user.js @@ -42,6 +42,25 @@ export default class User { } } + merge(other) { + if ( ! this.login && other.login ) + this.login = other.login; + + if ( other.emote_sets && other.emote_sets._sources ) { + for(const [provider, sets] of other.emote_sets._sources.entries()) { + for(const set_id of sets) + this.addSet(provider, set_id); + } + } + + if ( other.badges && other.badges._sources ) { + for(const [provider, badges] of other.badges._sources.entries()) { + for(const badge of badges) + this.addBadge(provider, badge.id, badge); + } + } + } + get id() { return this._id; } @@ -70,6 +89,8 @@ export default class User { if ( old_user && old_user !== this ) old_user.login = null; + // Make sure we didn't have a funky loop thing happen. + this._login = val; obj.users[val] = this; } diff --git a/src/modules/main_menu/components/main-menu.vue b/src/modules/main_menu/components/main-menu.vue index ba5b9ecb..8666e991 100644 --- a/src/modules/main_menu/components/main-menu.vue +++ b/src/modules/main_menu/components/main-menu.vue @@ -3,7 +3,7 @@ :class="{ maximized: maximized || exclusive, exclusive, faded }" class="ffz-dialog ffz-main-menu tw-elevation-3 tw-c-background-alt tw-c-text tw-border tw-flex tw-flex-nowrap tw-flex-column" > -
+

FrankerFaceZ

@@ -150,6 +150,13 @@ export default { }, methods: { + maybeResize(event) { + if ( event.target !== this.$refs.header ) + return; + + this.resize(event); + }, + changeProfile() { const new_id = this.$refs.profiles.value, new_profile = this.context.profiles[new_id]; diff --git a/src/modules/main_menu/index.js b/src/modules/main_menu/index.js index 3f88af4c..ff194e1b 100644 --- a/src/modules/main_menu/index.js +++ b/src/modules/main_menu/index.js @@ -58,6 +58,11 @@ export default class MainMenu extends Module { component: 'changelog' }); + this.on('settings:added-definition', (key, definition) => { + this._addDefinitionToTree(key, definition); + this.scheduleUpdate(); + }) + this.on('socket:command:new_version', version => { if ( version === window.FrankerFaceZ.version_info.commit ) return; @@ -136,6 +141,35 @@ export default class MainMenu extends Module { } + scheduleUpdate() { + if ( this._update_timer ) + return; + + this._update_timer = setTimeout(() => this.updateLiveMenu(), 250); + } + + + updateLiveMenu() { + clearTimeout(this._update_timer); + this._update_timer = null; + + if ( ! this._vue || ! this._vue.$children || ! this._vue.$children[0] ) + return; + + const root = this._vue.$children[0], + item = root.currentItem, + key = item && item.full_key, + + tree = this.getSettingsTree(); + + root.nav = tree; + root.nav_keys = tree.keys; + root.currentItem = tree.keys[key] || (this.has_update ? + tree.keys['home.changelog'] : + tree.keys['home']); + } + + rebuildSettingsTree() { this._settings_tree = {}; this._settings_count = 0; diff --git a/src/modules/metadata.jsx b/src/modules/metadata.jsx index 05761831..c3cfcb77 100644 --- a/src/modules/metadata.jsx +++ b/src/modules/metadata.jsx @@ -647,8 +647,11 @@ export default class Metadata extends Module { if ( ! el ) { let icon = maybe_call(def.icon, this, data); + let button = false; + + if ( def.button !== false && (def.popup || def.click) ) { + button = true; - if ( def.popup || def.click ) { let btn, popup; let cls = maybe_call(def.button, this, data); if ( typeof cls !== 'string' ) @@ -691,7 +694,7 @@ export default class Metadata extends Module { if ( def.click ) btn.addEventListener('click', e => { - if ( btn.disabled || btn.classList.contains('disabled') || el.disabled || el.classList.contains('disabled') ) + if ( el._ffz_fading || btn.disabled || btn.classList.contains('disabled') || el.disabled || el.classList.contains('disabled') ) return false; def.click.call(this, el._ffz_data, e, () => refresh_fn(key)); @@ -779,7 +782,15 @@ export default class Metadata extends Module { > {icon} {stat = } -
) +
); + + if ( def.click ) + el.addEventListener('click', e => { + if ( el._ffz_fading || el.disabled || el.classList.contains('disabled') ) + return false; + + def.click.call(this, el._ffz_data, e, () => refresh_fn(key)); + }); } el._ffz_order = order; @@ -787,11 +798,18 @@ export default class Metadata extends Module { if ( order != null ) el.style.order = order; - container.appendChild(el); + let subcontainer; + + if ( button ) + subcontainer = container.querySelector('.tw-flex:last-child') || container; + else + subcontainer = container.querySelector('.tw-flex:first-child') || container; + + subcontainer.appendChild(el); if ( def.tooltip ) { const parent = document.body.querySelector('.twilight-root') || document.body; - el.tooltip = new Tooltip(container, el, { + el.tooltip = new Tooltip(parent, el, { logger: this.log, live: false, html: true, diff --git a/src/sites/twitch-twilight/modules/channel_bar.js b/src/sites/twitch-twilight/modules/channel_bar.js index 23b2bc3d..406fd3b6 100644 --- a/src/sites/twitch-twilight/modules/channel_bar.js +++ b/src/sites/twitch-twilight/modules/channel_bar.js @@ -33,7 +33,7 @@ export default class ChannelBar extends Module { this.ChannelBar = this.fine.define( 'channel-bar', n => n.renderChannelMetadata && n.renderTitleInfo, - ['user', 'user-video', 'user-clip', 'video', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following'] + ['disabled'], //['user', 'user-video', 'user-clip', 'video', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following'] ) } diff --git a/src/sites/twitch-twilight/styles/channel.scss b/src/sites/twitch-twilight/styles/channel.scss index 0c05af41..5dbc299e 100644 --- a/src/sites/twitch-twilight/styles/channel.scss +++ b/src/sites/twitch-twilight/styles/channel.scss @@ -1,4 +1,8 @@ -.channel-info-bar__action-container { +.channel-info-bar__action-container > .tw-flex { + .channel-info-bar__viewers-wrapper > div:first-child { + margin-right: 0; + } + & > .tw-flex { & > * { margin-left: 0 !important; diff --git a/styles/widgets.scss b/styles/widgets.scss index 68773937..9d57612c 100644 --- a/styles/widgets.scss +++ b/styles/widgets.scss @@ -1,5 +1,6 @@ @import "./widgets/container.scss"; +@import "./widgets/main-menu.scss"; @import "./widgets/menu-container.scss"; @import "./widgets/tab-container.scss"; diff --git a/styles/widgets/main-menu.scss b/styles/widgets/main-menu.scss new file mode 100644 index 00000000..784614e2 --- /dev/null +++ b/styles/widgets/main-menu.scss @@ -0,0 +1,11 @@ +.ffz-main-menu { + & > header { + * { + pointer-events: none; + } + + input, button { + pointer-events: all; + } + } +} \ No newline at end of file