1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-10-22 10:52:02 +00:00

A ton of stuff. Initial migration to React 16. Initial changes for Rooms support. Add support for clip champ badge. Start using .gql source files that are compiled during import so we don't need to include GraphQL-tag in builds.

This commit is contained in:
SirStendec 2018-02-22 18:23:44 -05:00
parent f0bcf7f53e
commit 0ae6e5021d
29 changed files with 536 additions and 263 deletions

View file

@ -38,10 +38,8 @@ export default class Twilight extends BaseSite {
}
onEnable() {
const root = this.fine.getParent(this.fine.react),
ctx = this.context = root && root._context,
store = this.store = ctx && ctx.store;
const thing = this.fine.searchTree(null, n => n.props && n.props.store),
store = this.store = thing && thing.props && thing.props.store;
if ( ! store )
return new Promise(r => setTimeout(r, 50)).then(() => this.onEnable());
@ -64,10 +62,10 @@ export default class Twilight extends BaseSite {
updateContext() {
try {
const state = this.store.getState(),
route = this.context.router && this.context.router.route;
history = this.router && this.router.history;
this.settings.updateContext({
location: route && route.location,
location: history && history.location,
ui: state && state.ui,
session: state && state.session
});

View file

@ -7,6 +7,9 @@
import Module from 'utilities/module';
import {deep_copy} from 'utilities/object';
import CHANNEL_QUERY from './channel_bar_query.gql';
export default class ChannelBar extends Module {
constructor(...args) {
super(...args);
@ -17,17 +20,9 @@ export default class ChannelBar extends Module {
this.inject('site.apollo');
this.inject('metadata');
this.apollo.registerModifier('ChannelPage_ChannelInfoBar_User', this.apollo.gql`query {
user {
stream {
createdAt
type
}
}
}`);
this.apollo.registerModifier('ChannelPage_ChannelInfoBar_User', CHANNEL_QUERY);
this.apollo.registerModifier('ChannelPage_ChannelInfoBar_User', data => {
console.log('BOOP BOOP A DOOP', data);
const u = data && data.data && data.data.user;
if ( u ) {
const o = u.profileViewCount = new Number(u.profileViewCount || 0);

View file

@ -0,0 +1,8 @@
query {
user {
stream {
createdAt
type
}
}
}

View file

@ -61,25 +61,30 @@ const EVENTS = [
'onJoinedEvent',
'onDisconnectedEvent',
'onReconnectingEvent',
'onChatMessageEvent',
'onChatNoticeEvent',
'onChatActionEvent',
'onBadgesUpdatedEvent',
'onHostingEvent',
'onUnhostEvent',
'onChatMessageEvent',
'onChatActionEvent',
'onChatNoticeEvent',
'onTimeoutEvent',
'onBanEvent',
'onModerationEvent',
'onPurchaseEvent',
'onCrateEvent',
//'onRitualEvent',
'onSubscriptionEvent',
//'onResubscriptionEvent',
'onSubscriptionGiftEvent',
'onRoomStateEvent',
'onSlowModeEvent',
'onFollowerOnlyModeEvent',
'onSubscriberOnlyModeEvent',
'onTimeoutEvent',
'onBanEvent',
'onClearChatEvent',
'onRaidEvent',
'onUnraidEvent',
'onBadgesUpdatedEvent'
'onRoomModsEvent',
'onRoomStateEvent',
'onFollowerOnlyModeEvent',
'onSlowModeEvent',
'onSubscriberOnlyModeEvent',
'onEmoteOnlyModeEvent',
'onBitsCharityEvent'
];
@ -408,7 +413,7 @@ export default class ChatHook extends Module {
const i = this,
pm = this.postMessage;
for(const key of EVENTS) { // eslint-disable-line guard-for-in
for(const key of EVENTS) {
const original = this[key];
if ( original )
this[key] = function(e, t) {

View file

@ -25,7 +25,12 @@ export default class ChatLine extends Module {
this.ChatLine = this.fine.define(
'chat-line',
n => n.renderMessageBody
n => n.renderMessageBody && ! n.getMessageParts
);
this.ChatRoomLine = this.fine.define(
'chat-room-line',
n => n.renderMessageBody && n.getMessageParts
);
}
@ -64,8 +69,23 @@ export default class ChatLine extends Module {
const types = t.parent.chat_types || {},
msg = this.props.message,
is_action = msg.type === types.Action,
user = msg.user,
is_action = msg.type === types.Action;
if ( msg.content && ! msg.message )
msg.message = msg.content.text;
if ( msg.sender && ! msg.user ) {
msg.user = msg.sender;
msg.user.color = msg.user.color || msg.user.chatColor;
}
if ( ! msg.badges && msg.user.displayBadges ) {
const b = msg.badges = {};
for(const item of msg.user.displayBadges)
b[item.setID] = item.version;
}
const user = msg.user,
color = t.parent.colors.process(user.color),
/*bg_rgb = Color.RGBA.fromHex(user.color),
bg_color = bg_rgb.luminance() < .005 ? bg_rgb : bg_rgb.toHSLA().targetLuminance(0.005).toRGBA(),

View file

@ -0,0 +1,72 @@
'use strict';
// ============================================================================
// Compatibility Layer
// Emote Menu for Twitch (BTTV Emote Menu)
// ============================================================================
import Module from 'utilities/module';
import {has} from 'utilities/object';
export default class CompatEmoteMenu extends Module {
constructor(...args) {
super(...args);
this.should_enable = true;
this.inject('site.chat');
this.inject('chat.emotes');
}
async onEnable() {
const em = await this.findEmoteMenu();
if ( ! em )
return this.log.info('Emote Menu for Twitch was not found after 60 seconds.');
em.registerEmoteGetter('FrankerFaceZ', () => {
// We get literally no information about the current context,
// so we need to look up everything.
const cont = this.chat.ChatContainer.first,
props = cont && cont.props;
if ( ! props )
return;
const sets = this.emotes.getSets(props.userID, props.currentUserLogin, props.channelID, props.channelLogin),
emotes = [];
for(const set of sets) {
if ( ! set || ! set.emotes )
continue;
for(const emote_id in set.emotes)
if ( has(set.emotes, emote_id) ) {
const emote = set.emotes[emote_id];
if ( emote.hidden )
continue;
emotes.push({
text: emote.name,
url: emote.urls[1],
channel: `${set.source || 'FrankerFaceZ'} ${set.title}`,
badge: set.icon || '//cdn.frankerfacez.com/script/devicon.png'
});
}
}
return emotes;
});
}
async findEmoteMenu(delay = 0) {
if ( window.emoteMenu && emoteMenu.registerEmoteGetter )
return emoteMenu;
if ( delay >= 60000 )
return null;
return new Promise(s => {
setTimeout(() => this.findEmoteMenu(delay + 100).then(s), 100)
});
}
}

View file

@ -0,0 +1,12 @@
query {
streams {
edges {
node {
createdAt
broadcaster {
profileImageURL(width: 70)
}
}
}
}
}

View file

@ -7,6 +7,8 @@
import {SiteModule} from 'utilities/module';
import {get} from 'utilities/object';
import BROWSE_POPULAR from './browse_popular.gql';
export default class BrowsePopular extends SiteModule {
constructor(...args) {
super(...args);
@ -15,18 +17,7 @@ export default class BrowsePopular extends SiteModule {
this.inject('site.fine');
this.inject('settings');
this.apollo.registerModifier('BrowsePage_Popular', this.apollo.gql`query {
streams {
edges {
node {
createdAt
broadcaster {
profileImageURL(width: 70)
}
}
}
}
}`);
this.apollo.registerModifier('BrowsePage_Popular', BROWSE_POPULAR);
this.ChannelCard = this.fine.define(
'browse-all-channel-card',

View file

@ -1,33 +0,0 @@
'use strict';
// ============================================================================
// Directory (Following, for now)
// ============================================================================
import {SiteModule} from 'utilities/module';
export default class Community extends SiteModule {
constructor(...args) {
super(...args);
this.inject('site.apollo');
this.apollo.registerModifier('GamePage_Game', this.apollo.gql`query {
directory {
... on Community {
streams {
edges {
node {
createdAt
type
broadcaster {
profileImageURL(width: 70)
}
}
}
}
}
}
}`);
}
}

View file

@ -0,0 +1,13 @@
query {
currentUser {
followedLiveUsers {
nodes {
profileImageURL(width: 70)
stream {
type
createdAt
}
}
}
}
}

View file

@ -0,0 +1,15 @@
query {
currentUser {
followedHosts {
nodes {
profileImageURL(width: 70)
hosting {
profileImageURL(width: 70)
stream {
createdAt
}
}
}
}
}
}

View file

@ -0,0 +1,24 @@
query {
currentUser {
followedLiveUsers {
nodes {
profileImageURL(width: 70)
stream {
createdAt
}
}
}
followedHosts {
nodes {
profileImageURL(width: 70)
hosting {
profileImageURL(width: 70)
stream {
createdAt
type
}
}
}
}
}
}

View file

@ -0,0 +1,14 @@
query {
currentUser {
followedLiveUsers {
edges {
node {
profileImageURL(width: 70)
stream {
createdAt
}
}
}
}
}
}

View file

@ -10,6 +10,11 @@ import {get} from 'utilities/object';
import Popper from 'popper.js';
import FOLLOWED_INDEX from './followed_index.gql';
import FOLLOWED_HOSTS from './followed_hosts.gql';
import FOLLOWED_CHANNELS from './followed_channels.gql';
import FOLLOWED_LIVE from './followed_live.gql';
export default class Following extends SiteModule {
constructor(...args) {
super(...args);
@ -58,75 +63,10 @@ export default class Following extends SiteModule {
changed: () => this.ChannelCard.forceUpdate()
});
this.apollo.registerModifier('FollowedIndex_CurrentUser', this.apollo.gql`query {
currentUser {
followedLiveUsers {
nodes {
profileImageURL(width: 70)
stream {
createdAt
}
}
}
followedHosts {
nodes {
profileImageURL(width: 70)
hosting {
profileImageURL(width: 70)
stream {
createdAt
type
}
}
}
}
}
}`);
this.apollo.registerModifier('FollowingLive_CurrentUser', this.apollo.gql`query {
currentUser {
followedLiveUsers {
edges {
node {
profileImageURL(width: 70)
stream {
createdAt
}
}
}
}
}
}`);
this.apollo.registerModifier('FollowingHosts_CurrentUser', this.apollo.gql`query {
currentUser {
followedHosts {
nodes {
profileImageURL(width: 70)
hosting {
profileImageURL(width: 70)
stream {
createdAt
}
}
}
}
}
}`);
this.apollo.registerModifier('FollowedChannels', this.apollo.gql`query {
currentUser {
followedLiveUsers {
nodes {
profileImageURL(width: 70)
stream {
type
createdAt
}
}
}
}
}`);
this.apollo.registerModifier('FollowedIndex_CurrentUser', FOLLOWED_INDEX);
this.apollo.registerModifier('FollowingLive_CurrentUser', FOLLOWED_LIVE);
this.apollo.registerModifier('FollowingHosts_CurrentUser', FOLLOWED_HOSTS);
this.apollo.registerModifier('FollowedChannels', FOLLOWED_CHANNELS);
this.ChannelCard = this.fine.define(
'following-channel-card',

View file

@ -0,0 +1,30 @@
query {
directory {
... on Game {
streams {
edges {
node {
createdAt
type
broadcaster {
profileImageURL(width: 70)
}
}
}
}
}
... on Community {
streams {
edges {
node {
createdAt
type
broadcaster {
profileImageURL(width: 70)
}
}
}
}
}
}
}

View file

@ -7,6 +7,8 @@
import {SiteModule} from 'utilities/module';
import {createElement as e} from 'utilities/dom';
import GAME_QUERY from './game.gql';
export default class Game extends SiteModule {
constructor(...args) {
super(...args);
@ -22,23 +24,7 @@ export default class Game extends SiteModule {
n => n.renderFollowButton && n.renderGameDetailsTab
);
this.apollo.registerModifier('GamePage_Game', this.apollo.gql`query {
directory {
... on Game {
streams {
edges {
node {
createdAt
type
broadcaster {
profileImageURL(width: 70)
}
}
}
}
}
}
}`);
this.apollo.registerModifier('GamePage_Game', GAME_QUERY);
}
onEnable() {

View file

@ -11,7 +11,6 @@ import {get} from 'utilities/object';
import Following from './following';
import Game from './game';
import Community from './community';
import BrowsePopular from './browse_popular';
export default class Directory extends SiteModule {
@ -30,7 +29,6 @@ export default class Directory extends SiteModule {
this.inject(Following);
this.inject(Game);
this.inject(Community);
this.inject(BrowsePopular);
this.apollo.registerModifier('GamePage_Game', res => this.modifyStreams(res), false);

View file

@ -47,7 +47,7 @@ export default class HostButton extends Module {
if (userLogin)
this.joinChannel(userLogin);
this.metadata.updateMetadata('host');
}
});
@ -57,9 +57,9 @@ export default class HostButton extends Module {
button: true,
disabled: () => {
return this._host_updating || this._host_error;
return this._host_updating || this._host_error;
},
click: data => {
if (data.channel) this.sendHostUnhostCommand(data.channel.login);
},
@ -69,7 +69,7 @@ export default class HostButton extends Module {
_host_options_vue = import(/* webpackChunkName: "host-options" */ './host-options.vue'),
_autoHosts = this.fetchAutoHosts(),
_autoHostSettings = this.fetchAutoHostSettings();
const [, host_options_vue, autoHosts, autoHostSettings] = await Promise.all([vue.enable(), _host_options_vue, _autoHosts, _autoHostSettings]);
this._auto_host_tip = tip;
@ -86,7 +86,7 @@ export default class HostButton extends Module {
const ffz_user = this.site.getUser(),
userLogin = ffz_user && ffz_user.login;
if (data.channel && data.channel.login === userLogin) {
return '';
}
@ -168,22 +168,22 @@ export default class HostButton extends Module {
this.on('tmi:host', e => {
if (e.channel.substring(1) !== userLogin) return;
clearTimeout(this._host_feedback);
this._host_error = false;
this._last_hosted_channel = e.target;
this._host_updating = false;
this.metadata.updateMetadata('host');
});
this.on('tmi:unhost', e => {
if (e.channel.substring(1) !== userLogin) return;
clearTimeout(this._host_feedback);
this._host_error = false;
this._last_hosted_channel = null;
this._host_updating = false;
this.metadata.updateMetadata('host');
});
@ -232,12 +232,12 @@ export default class HostButton extends Module {
const t = e.target,
setting = t.dataset.setting;
let state = t.checked;
if ( setting === 'strategy' )
state = state ? 'random' : 'ordered';
else if ( setting === 'deprioritize_vodcast' )
state = ! state;
this.updateAutoHostSetting(setting, state);
}
})
@ -302,20 +302,20 @@ export default class HostButton extends Module {
queueHostUpdate() {
if (this._host_update_timer) clearTimeout(this._host_update_timer);
this._host_update_timer = setTimeout(() => {
this._host_update_timer = undefined;
this.updateAutoHosts(this.autoHosts);
}, 1000);
}
rearrangeHosts(oldIndex, newIndex) {
const host = this.autoHosts.splice(oldIndex, 1)[0];
this.autoHosts.splice(newIndex, 0, host);
this.queueHostUpdate();
}
currentRoomInHosts() {
return this.getAutoHostIDs(this.autoHosts).includes(parseInt(this._current_channel_id, 10));
}
@ -329,7 +329,7 @@ export default class HostButton extends Module {
removeUserFromHosts(event) {
const id = event.target.closest('.ffz--host-user').dataset.id;
const newHosts = [];
for (let i = 0; i < this.autoHosts.length; i++) {
if (this.autoHosts[i]._id != id) newHosts.push(this.autoHosts[i]);

View file

@ -192,12 +192,12 @@ export default class Player extends Module {
disableAutoplay(inst) {
if ( ! inst.player ) {
this.log.warn("disableAutoplay() called but Player was not ready");
this.log.warn('disableAutoplay() called but Player was not ready');
return;
}
if ( ! inst.ffzAutoplay ) {
var playListener = () => {
const playListener = () => {
this.log.info('Auto-paused player');
inst.ffzAutoplay = null;
inst.player.pause();
@ -209,6 +209,7 @@ export default class Player extends Module {
inst.player.removeEventListener('contentShowing', playListener);
}, 1000);
}
inst.ffzAutoplay = playListener;
inst.player.addEventListener('play', inst.ffzAutoplay);
inst.player.addEventListener('playing', inst.ffzAutoplay);