mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-02 16:08:31 +00:00
Merge 52ca7ecf42
into d089002698
This commit is contained in:
commit
ca30a3414f
69 changed files with 1646 additions and 1313 deletions
|
@ -2,6 +2,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'env': {
|
'env': {
|
||||||
'browser': true,
|
'browser': true,
|
||||||
|
'es2020': true,
|
||||||
'es6': true
|
'es6': true
|
||||||
},
|
},
|
||||||
'extends': [
|
'extends': [
|
||||||
|
@ -33,6 +34,7 @@ module.exports = {
|
||||||
'__version_major__': false,
|
'__version_major__': false,
|
||||||
'__version_minor__': false,
|
'__version_minor__': false,
|
||||||
'__version_patch__': false,
|
'__version_patch__': false,
|
||||||
|
'__version_build__': false,
|
||||||
'__version_prerelease__': false,
|
'__version_prerelease__': false,
|
||||||
'__extension__': false,
|
'__extension__': false,
|
||||||
'FrankerFaceZ': false
|
'FrankerFaceZ': false
|
||||||
|
@ -70,7 +72,6 @@ module.exports = {
|
||||||
'no-useless-concat': ['warn'],
|
'no-useless-concat': ['warn'],
|
||||||
'no-useless-return': ['warn'],
|
'no-useless-return': ['warn'],
|
||||||
'no-void': ['error'],
|
'no-void': ['error'],
|
||||||
'no-warning-comments': ['warn'],
|
|
||||||
'no-with': ['error'],
|
'no-with': ['error'],
|
||||||
'radix': ['error'],
|
'radix': ['error'],
|
||||||
'require-await': ['warn'],
|
'require-await': ['warn'],
|
||||||
|
@ -121,9 +122,12 @@ module.exports = {
|
||||||
'tab'
|
'tab'
|
||||||
],
|
],
|
||||||
'vue/valid-template-root': 'off',
|
'vue/valid-template-root': 'off',
|
||||||
|
'vue/multi-word-component-names': 'off',
|
||||||
'vue/max-attributes-per-line': 'off',
|
'vue/max-attributes-per-line': 'off',
|
||||||
'vue/require-prop-types': 'off',
|
'vue/require-prop-types': 'off',
|
||||||
'vue/require-default-prop': 'off',
|
'vue/require-default-prop': 'off',
|
||||||
|
'vue/no-mutating-props': 'off', // TODO: all these
|
||||||
|
'vue/prop-name-casing': 'off', // TODO: do we need this?
|
||||||
'vue/html-closing-bracket-newline': [
|
'vue/html-closing-bracket-newline': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
|
@ -157,4 +161,4 @@ module.exports = {
|
||||||
'react/jsx-uses-react': 'error',
|
'react/jsx-uses-react': 'error',
|
||||||
'react/jsx-wrap-multilines': 'error'
|
'react/jsx-wrap-multilines': 'error'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMessage(id, payload) {
|
function handleMessage(id, payload) {
|
||||||
const port = connection.get(id);
|
const port = connections.get(id);
|
||||||
if ( port ) {
|
if ( port ) {
|
||||||
port.postMessage(payload);
|
port.postMessage(payload);
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
|
|
||||||
|
|
||||||
// Let the extension send messages to the page directly.
|
// Let the extension send messages to the page directly.
|
||||||
browser.runtime.onMessage.addListener((msg, sender) => {
|
browser.runtime.onMessage.addListener(msg => {
|
||||||
if (msg?.type === 'ffz_to_page')
|
if (msg?.type === 'ffz_to_page')
|
||||||
window.postMessage(msg.data, '*');
|
window.postMessage(msg.data, '*');
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
|
|
||||||
// Now, inject our script into the page context.
|
// Now, inject our script into the page context.
|
||||||
const HOST = location.hostname,
|
const HOST = location.hostname,
|
||||||
SERVER = browser.runtime.getURL("web"),
|
SERVER = browser.runtime.getURL('web'),
|
||||||
script = document.createElement('script');
|
script = document.createElement('script');
|
||||||
|
|
||||||
let FLAVOR =
|
let FLAVOR =
|
||||||
|
|
|
@ -32,7 +32,7 @@ class FFZESBridge {
|
||||||
|
|
||||||
window.addEventListener('message', this.onWindowMessage);
|
window.addEventListener('message', this.onWindowMessage);
|
||||||
|
|
||||||
document.addEventListener('readystatechange', event => {
|
document.addEventListener('readystatechange', () => {
|
||||||
if ( document.documentElement )
|
if ( document.documentElement )
|
||||||
document.documentElement.dataset.ffzEsbridge = true;
|
document.documentElement.dataset.ffzEsbridge = true;
|
||||||
});
|
});
|
||||||
|
@ -55,7 +55,7 @@ class FFZESBridge {
|
||||||
msg,
|
msg,
|
||||||
location.origin,
|
location.origin,
|
||||||
transfer ? (Array.isArray(transfer) ? transfer : [transfer]) : undefined
|
transfer ? (Array.isArray(transfer) ? transfer : [transfer]) : undefined
|
||||||
);
|
);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
this.log.error('Error sending message to window.', err, msg, transfer);
|
this.log.error('Error sending message to window.', err, msg, transfer);
|
||||||
}
|
}
|
||||||
|
@ -63,21 +63,21 @@ class FFZESBridge {
|
||||||
|
|
||||||
onWindowMessage(event) {
|
onWindowMessage(event) {
|
||||||
if ( event.origin !== location.origin )
|
if ( event.origin !== location.origin )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const msg = event.data,
|
const msg = event.data,
|
||||||
id = msg?.id,
|
id = msg?.id,
|
||||||
type = msg?.ffz_esb_type;
|
type = msg?.ffz_esb_type;
|
||||||
|
|
||||||
if ( ! type )
|
if ( ! type )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.log.info('Received Message from Page', type, id, msg);
|
this.log.info('Received Message from Page', type, id, msg);
|
||||||
|
|
||||||
if ( type === 'init' ) {
|
if ( type === 'init' ) {
|
||||||
this.received_init = true;
|
this.received_init = true;
|
||||||
if ( this.active )
|
if ( this.active )
|
||||||
this.runtimeHeartbeat();
|
this.runtimeHeartbeat();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.runtimeSend(msg);
|
this.runtimeSend(msg);
|
||||||
|
@ -89,7 +89,7 @@ class FFZESBridge {
|
||||||
|
|
||||||
runtimeOpen() {
|
runtimeOpen() {
|
||||||
if ( this.active )
|
if ( this.active )
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
|
||||||
this.log.info('Connecting to worker.');
|
this.log.info('Connecting to worker.');
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class FFZESBridge {
|
||||||
this.port.onDisconnect.addListener(this.onRuntimeDisconnect);
|
this.port.onDisconnect.addListener(this.onRuntimeDisconnect);
|
||||||
|
|
||||||
if ( this.received_init )
|
if ( this.received_init )
|
||||||
this.runtimeHeartbeat();
|
this.runtimeHeartbeat();
|
||||||
}
|
}
|
||||||
|
|
||||||
onRuntimeMessage(msg) {
|
onRuntimeMessage(msg) {
|
||||||
|
@ -118,27 +118,27 @@ class FFZESBridge {
|
||||||
|
|
||||||
runtimeHeartbeat() {
|
runtimeHeartbeat() {
|
||||||
if ( this._heartbeat )
|
if ( this._heartbeat )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._heartbeat = setInterval(() => {
|
this._heartbeat = setInterval(() => {
|
||||||
if ( this.active )
|
if ( this.active )
|
||||||
this.runtimeSend('heartbeat');
|
this.runtimeSend('heartbeat');
|
||||||
}, 30000);
|
}, 30000);
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeSend(msg) {
|
runtimeSend(msg) {
|
||||||
if ( typeof msg === 'string' )
|
if ( typeof msg === 'string' )
|
||||||
msg = {ffz_esb_type: msg};
|
msg = {ffz_esb_type: msg};
|
||||||
|
|
||||||
if ( ! this.active )
|
if ( ! this.active )
|
||||||
// We need to create our port.
|
// We need to create our port.
|
||||||
this.runtimeOpen();
|
this.runtimeOpen();
|
||||||
|
|
||||||
// Send the message, knowing we have an open port.
|
// Send the message, knowing we have an open port.
|
||||||
this.port.postMessage(msg);
|
this.port.postMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
FFZESBridge.Logger = Logger;
|
FFZESBridge.Logger = Logger;
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ const VER = FFZESBridge.version_info = Object.freeze({
|
||||||
build: __version_build__,
|
build: __version_build__,
|
||||||
hash: __webpack_hash__,
|
hash: __webpack_hash__,
|
||||||
toString: () =>
|
toString: () =>
|
||||||
`${VER.major}.${VER.minor}.${VER.revision}${VER.extra || ''}${VER.build ? `+${VER.build}` : ''}`
|
`${VER.major}.${VER.minor}.${VER.revision}${VER.extra || ''}${VER.build ? `+${VER.build}` : ''}`
|
||||||
});
|
});
|
||||||
|
|
||||||
window.FFZESBridge = FFZESBridge;
|
window.FFZESBridge = FFZESBridge;
|
||||||
|
|
|
@ -187,7 +187,7 @@ export default class TranslationManager extends Module {
|
||||||
},
|
},
|
||||||
data: () => {
|
data: () => {
|
||||||
const out = [], now = new Date;
|
const out = [], now = new Date;
|
||||||
for (const [key, fmt] of Object.entries(this._.formats.date)) {
|
for (const [key] of Object.entries(this._.formats.date)) {
|
||||||
out.push({
|
out.push({
|
||||||
value: key, title: `${this.formatDate(now, key)} (${key})`
|
value: key, title: `${this.formatDate(now, key)} (${key})`
|
||||||
})
|
})
|
||||||
|
@ -217,7 +217,7 @@ export default class TranslationManager extends Module {
|
||||||
},
|
},
|
||||||
data: () => {
|
data: () => {
|
||||||
const out = [], now = new Date;
|
const out = [], now = new Date;
|
||||||
for (const [key,fmt] of Object.entries(this._.formats.time)) {
|
for (const [key] of Object.entries(this._.formats.time)) {
|
||||||
out.push({
|
out.push({
|
||||||
value: key, title: `${this.formatTime(now, key)} (${key})`
|
value: key, title: `${this.formatTime(now, key)} (${key})`
|
||||||
})
|
})
|
||||||
|
@ -247,7 +247,7 @@ export default class TranslationManager extends Module {
|
||||||
},
|
},
|
||||||
data: () => {
|
data: () => {
|
||||||
const out = [], now = new Date;
|
const out = [], now = new Date;
|
||||||
for (const [key,fmt] of Object.entries(this._.formats.datetime)) {
|
for (const [key] of Object.entries(this._.formats.datetime)) {
|
||||||
out.push({
|
out.push({
|
||||||
value: key, title: `${this.formatDateTime(now, key)} (${key})`
|
value: key, title: `${this.formatDateTime(now, key)} (${key})`
|
||||||
})
|
})
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default class Actions extends Module {
|
||||||
this.actions = {};
|
this.actions = {};
|
||||||
this.renderers = {};
|
this.renderers = {};
|
||||||
|
|
||||||
this.filterAction = (x) => x.appearance &&
|
this.filterAction = x => x.appearance &&
|
||||||
this.renderers[x.appearance.type] &&
|
this.renderers[x.appearance.type] &&
|
||||||
(! this.renderers[x.appearance.type].load || this.renderers[x.appearance.type].load(x.appearance)) &&
|
(! this.renderers[x.appearance.type].load || this.renderers[x.appearance.type].load(x.appearance)) &&
|
||||||
(! x.action || this.actions[x.action]);
|
(! x.action || this.actions[x.action]);
|
||||||
|
@ -802,7 +802,7 @@ export default class Actions extends Module {
|
||||||
if ( u ) {
|
if ( u ) {
|
||||||
u.moderator = line.props.isCurrentUserModerator;
|
u.moderator = line.props.isCurrentUserModerator;
|
||||||
u.staff = line.props.isCurrentUserStaff;
|
u.staff = line.props.isCurrentUserStaff;
|
||||||
u.reply_mode = this.parent.context.get('chat.replies.style'),
|
u.reply_mode = this.parent.context.get('chat.replies.style');
|
||||||
u.can_reply = can_reply;
|
u.can_reply = can_reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,6 @@
|
||||||
{{ t('setting.actions.chat.target-incompatible', 'Note: This is not compatible with pasting a message into chat, and will not function if that is enabled.') }}
|
{{ t('setting.actions.chat.target-incompatible', 'Note: This is not compatible with pasting a message into chat, and will not function if that is enabled.') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
v-for="profile in profiles"
|
v-for="profile in profiles"
|
||||||
:key="profile.value"
|
:key="profile.value"
|
||||||
:value="profile.value"
|
:value="profile.value"
|
||||||
>{{ profile.i18n_key ? t(profile.i18n_key, profile.name) : profile.name }}</option>
|
>
|
||||||
|
{{ profile.i18n_key ? t(profile.i18n_key, profile.name) : profile.name }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -40,7 +40,7 @@ export const pin = {
|
||||||
},
|
},
|
||||||
|
|
||||||
hidden(data, message, current_room, current_user, mod_icons, instance) {
|
hidden(data, message, current_room, current_user, mod_icons, instance) {
|
||||||
let line = instance;
|
const line = instance;
|
||||||
|
|
||||||
if ( ! line )
|
if ( ! line )
|
||||||
return true;
|
return true;
|
||||||
|
@ -549,7 +549,8 @@ export const mod = {
|
||||||
return this.i18n.t('chat.actions.mod.tooltip', 'Mod {user.login}', {user: data.user});
|
return this.i18n.t('chat.actions.mod.tooltip', 'Mod {user.login}', {user: data.user});
|
||||||
},
|
},
|
||||||
|
|
||||||
hidden(data, message, current_room, current_user, mod_icons, instance) {
|
// can accept (data, message, current_room, current_user, mod_icons, instance)
|
||||||
|
hidden(data, message, current_room, current_user) {
|
||||||
// You cannot mod mods.
|
// You cannot mod mods.
|
||||||
if ( message.user.type === 'mod' )
|
if ( message.user.type === 'mod' )
|
||||||
return true;
|
return true;
|
||||||
|
@ -584,7 +585,8 @@ export const unmod = {
|
||||||
return this.i18n.t('chat.actions.unmod.tooltip', 'Un-Mod {user.login}', {user: data.user});
|
return this.i18n.t('chat.actions.unmod.tooltip', 'Un-Mod {user.login}', {user: data.user});
|
||||||
},
|
},
|
||||||
|
|
||||||
hidden(data, message, current_room, current_user, mod_icons, instance) {
|
// can accept (data, message, current_room, current_user, mod_icons, instance)
|
||||||
|
hidden(data, message, current_room, current_user) {
|
||||||
// You can only un-mod mods.
|
// You can only un-mod mods.
|
||||||
if ( message.user.type !== 'mod' )
|
if ( message.user.type !== 'mod' )
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -657,7 +657,7 @@ export default class Badges extends Module {
|
||||||
|
|
||||||
const existing = this.badges[badge_id];
|
const existing = this.badges[badge_id];
|
||||||
if ( existing && existing.addon !== addon_id )
|
if ( existing && existing.addon !== addon_id )
|
||||||
module.log.warn('[DEV-CHECK] Removed un-owned badge with chat.badges.removeBadge():', key, ' owner:', existing.addon ?? 'ffz');
|
module.log.warn('[DEV-CHECK] Removed un-owned badge with chat.badges.removeBadge():', badge_id, ' owner:', existing.addon ?? 'ffz');
|
||||||
|
|
||||||
return this.removeBadge(badge_id, ...args);
|
return this.removeBadge(badge_id, ...args);
|
||||||
};
|
};
|
||||||
|
@ -739,10 +739,10 @@ export default class Badges extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
room_id: room_id,
|
room_id,
|
||||||
room_login: room_login,
|
room_login,
|
||||||
user_id: user_id,
|
user_id,
|
||||||
user_login: user_login,
|
user_login,
|
||||||
data
|
data
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1279,11 +1279,11 @@ export default class Badges extends Module {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( d.lifetime )
|
if ( d.lifetime )
|
||||||
return '\n' + this.i18n.t('badges.subwoofer.lifetime', 'Lifetime Subwoofer');
|
return `\n${ this.i18n.t('badges.subwoofer.lifetime', 'Lifetime Subwoofer')}`;
|
||||||
|
|
||||||
return '\n' + this.i18n.t('badges.subwoofer.months', '({count, plural, one {# Month} other {# Months}})', {
|
return `\n${ this.i18n.t('badges.subwoofer.months', '({count, plural, one {# Month} other {# Months}})', {
|
||||||
count: d.months
|
count: d.months
|
||||||
});
|
})}`;
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -81,10 +81,9 @@ function appearLeaveToKeyframes(source, multi = 1, offset = 0, has_var = false)
|
||||||
|
|
||||||
for(const line of source) {
|
for(const line of source) {
|
||||||
const pct = (line[0] * multi) + offset;
|
const pct = (line[0] * multi) + offset;
|
||||||
|
const vr = has_var ? `var(--ffz-effect-transforms) ` : '';
|
||||||
let vr, tx, scale, ty;
|
const tx = line[1] === 0 ? '' : `translateX(${line[1]}px) `;
|
||||||
vr = has_var ? `var(--ffz-effect-transforms) ` : '';
|
let scale, ty;
|
||||||
tx = line[1] === 0 ? '' : `translateX(${line[1]}px) `;
|
|
||||||
|
|
||||||
if ( line.length === 4 ) {
|
if ( line.length === 4 ) {
|
||||||
scale = `scale(${line[2]})`;
|
scale = `scale(${line[2]})`;
|
||||||
|
@ -639,7 +638,7 @@ export default class Emotes extends Module {
|
||||||
const overrides = {},
|
const overrides = {},
|
||||||
warnings = {};
|
warnings = {};
|
||||||
|
|
||||||
overrides.addFilter = (filter) => {
|
overrides.addFilter = filter => {
|
||||||
if ( filter )
|
if ( filter )
|
||||||
filter.__source = addon_id;
|
filter.__source = addon_id;
|
||||||
|
|
||||||
|
@ -648,7 +647,7 @@ export default class Emotes extends Module {
|
||||||
|
|
||||||
overrides.setProvider = (provider, data) => {
|
overrides.setProvider = (provider, data) => {
|
||||||
if ( is_dev && ! id_checker.test(provider) )
|
if ( is_dev && ! id_checker.test(provider) )
|
||||||
module.log.warn('[DEV-CHECK] Call to emotes.setProvider did not include addon ID in provider:', provider);
|
module.log.warn('[DEV-CHECK] Call to emotes.setProvider did not include addon ID in provider:', provider);
|
||||||
|
|
||||||
if ( data )
|
if ( data )
|
||||||
data.__source = addon_id;
|
data.__source = addon_id;
|
||||||
|
@ -707,7 +706,7 @@ export default class Emotes extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( is_dev ) {
|
if ( is_dev ) {
|
||||||
overrides.removeFilter = (filter) => {
|
overrides.removeFilter = filter => {
|
||||||
let type;
|
let type;
|
||||||
if ( typeof filter === 'string' ) type = filter;
|
if ( typeof filter === 'string' ) type = filter;
|
||||||
else type = filter.type;
|
else type = filter.type;
|
||||||
|
@ -1073,7 +1072,7 @@ export default class Emotes extends Module {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get the current channel.
|
// Get the current channel.
|
||||||
let room_id = this.parent.context.get('context.channelID'),
|
const room_id = this.parent.context.get('context.channelID'),
|
||||||
room_login = this.parent.context.get('context.channel');
|
room_login = this.parent.context.get('context.channel');
|
||||||
|
|
||||||
// And now get the current user's available emote sets.
|
// And now get the current user's available emote sets.
|
||||||
|
@ -1168,7 +1167,8 @@ export default class Emotes extends Module {
|
||||||
if ( ! this.parent.context.get('chat.effects.enable') )
|
if ( ! this.parent.context.get('chat.effects.enable') )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
let filter, transformOrigin, transform, animation, animations = [];
|
const animations = [];
|
||||||
|
let filter, transformOrigin, transform, animation;
|
||||||
|
|
||||||
for(const input of this.activeEffectStyles) {
|
for(const input of this.activeEffectStyles) {
|
||||||
if ( (flags & input.flags) !== input.flags )
|
if ( (flags & input.flags) !== input.flags )
|
||||||
|
@ -2184,7 +2184,7 @@ export default class Emotes extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
processEmote(emote, set_id) {
|
static processEmote(emote, set_id) {
|
||||||
if ( ! emote.id || ! emote.name || ! emote.urls )
|
if ( ! emote.id || ! emote.name || ! emote.urls )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -2269,9 +2269,9 @@ export default class Emotes extends Module {
|
||||||
if ( ! set )
|
if ( ! set )
|
||||||
throw new Error(`Invalid emote set "${set_id}"`);
|
throw new Error(`Invalid emote set "${set_id}"`);
|
||||||
|
|
||||||
let processed = this.processEmote(emote, set_id);
|
const processed = this.constructor.processEmote(emote, set_id);
|
||||||
if ( ! processed )
|
if ( ! processed )
|
||||||
throw new Error("Invalid emote data object.");
|
throw new Error('Invalid emote data object.');
|
||||||
|
|
||||||
const is_disabled = this.shouldFilterEmote(processed, set, set_id);
|
const is_disabled = this.shouldFilterEmote(processed, set, set_id);
|
||||||
|
|
||||||
|
@ -2284,7 +2284,7 @@ export default class Emotes extends Module {
|
||||||
// 6. Old emote disabled. New emote disabled.
|
// 6. Old emote disabled. New emote disabled.
|
||||||
|
|
||||||
// Are we removing a disabled emote?
|
// Are we removing a disabled emote?
|
||||||
let removed = set.disabled_emotes[processed.id];
|
const removed = set.disabled_emotes[processed.id];
|
||||||
if ( removed ) {
|
if ( removed ) {
|
||||||
delete set.disabled_emotes[processed.id];
|
delete set.disabled_emotes[processed.id];
|
||||||
set.disabled_count--;
|
set.disabled_count--;
|
||||||
|
@ -2456,7 +2456,7 @@ export default class Emotes extends Module {
|
||||||
const bad_emotes = [];
|
const bad_emotes = [];
|
||||||
|
|
||||||
for(const emote of ems) {
|
for(const emote of ems) {
|
||||||
let processed = this.processEmote(emote, set_id);
|
const processed = this.constructor.processEmote(emote, set_id);
|
||||||
if ( ! processed ) {
|
if ( ! processed ) {
|
||||||
bad_emotes.push(emote);
|
bad_emotes.push(emote);
|
||||||
continue;
|
continue;
|
||||||
|
@ -2554,7 +2554,7 @@ export default class Emotes extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( emote.modifier && emote.mask?.[1] ) {
|
if ( emote.modifier && emote.mask?.[1] ) {
|
||||||
output = (output || '') + `.modified-emote[data-modifiers~="${emote.id}"] > .chat-line__message--emote {
|
output = `${output || '' }.modified-emote[data-modifiers~="${emote.id}"] > .chat-line__message--emote {
|
||||||
-webkit-mask-image: url("${emote.mask[1]}");
|
-webkit-mask-image: url("${emote.mask[1]}");
|
||||||
-webkit-mask-position: center center;
|
-webkit-mask-position: center center;
|
||||||
}`
|
}`
|
||||||
|
|
|
@ -134,9 +134,7 @@ export default class Chat extends Module {
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
this.settings.add('debug.link-resolver.source', {
|
this.settings.add('debug.link-resolver.source', {
|
||||||
process: (ctx, val) => {
|
process: (ctx, val) => LINK_DATA_HOSTS[val] ?? LINK_DATA_HOSTS.Production,
|
||||||
return LINK_DATA_HOSTS[val] ?? LINK_DATA_HOSTS.Production;
|
|
||||||
},
|
|
||||||
|
|
||||||
default: null,
|
default: null,
|
||||||
ui: {
|
ui: {
|
||||||
|
@ -1404,17 +1402,17 @@ export default class Chat extends Module {
|
||||||
user_ids: 'Please use getUser()'
|
user_ids: 'Please use getUser()'
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
overrides.iterateUsers = function*() {
|
overrides.iterateUsers = function *() {
|
||||||
for(const user of this.iterateUsers())
|
for(const user of this.iterateUsers())
|
||||||
yield new Proxy(user, user_proxy);
|
yield new Proxy(user, user_proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
overrides.iterateRooms = function*() {
|
overrides.iterateRooms = function *() {
|
||||||
for(const room of this.iterateRooms())
|
for(const room of this.iterateRooms())
|
||||||
yield new Proxy(room, room_proxy);
|
yield new Proxy(room, room_proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
overrides.iterateAllRoomsAndUsers = function*() {
|
overrides.iterateAllRoomsAndUsers = function *() {
|
||||||
for(const thing of this.iterateAllRoomsAndUsers())
|
for(const thing of this.iterateAllRoomsAndUsers())
|
||||||
yield new Proxy(thing, (thing instanceof Room)
|
yield new Proxy(thing, (thing instanceof Room)
|
||||||
? room_proxy
|
? room_proxy
|
||||||
|
@ -1463,13 +1461,13 @@ export default class Chat extends Module {
|
||||||
|
|
||||||
if ( is_dev ) {
|
if ( is_dev ) {
|
||||||
overrides.getUser = (...args) => {
|
overrides.getUser = (...args) => {
|
||||||
let result = this.getUser(...args);
|
const result = this.getUser(...args);
|
||||||
if ( result )
|
if ( result )
|
||||||
return new Proxy(result, user_proxy);
|
return new Proxy(result, user_proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
overrides.getRoom = (...args) => {
|
overrides.getRoom = (...args) => {
|
||||||
let result = this.getRoom(...args);
|
const result = this.getRoom(...args);
|
||||||
if ( result )
|
if ( result )
|
||||||
return new Proxy(result, room_proxy);
|
return new Proxy(result, room_proxy);
|
||||||
}
|
}
|
||||||
|
@ -1551,7 +1549,7 @@ export default class Chat extends Module {
|
||||||
if ( has(LINK_PROVIDERS, key) )
|
if ( has(LINK_PROVIDERS, key) )
|
||||||
this.addLinkProvider(LINK_PROVIDERS[key]);
|
this.addLinkProvider(LINK_PROVIDERS[key]);
|
||||||
|
|
||||||
this.on('chat:reload-data', flags => {
|
this.on('chat:reload-data', () => {
|
||||||
for(const room of this.iterateRooms())
|
for(const room of this.iterateRooms())
|
||||||
room.load_data();
|
room.load_data();
|
||||||
});
|
});
|
||||||
|
@ -1567,7 +1565,7 @@ export default class Chat extends Module {
|
||||||
|
|
||||||
this.triggered_reload = false;
|
this.triggered_reload = false;
|
||||||
|
|
||||||
this.on('chat:ffz-command:reload', event => {
|
this.on('chat:ffz-command:reload', () => {
|
||||||
if ( this.triggered_reload )
|
if ( this.triggered_reload )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1579,7 +1577,7 @@ export default class Chat extends Module {
|
||||||
this.emit('chat:reload-data');
|
this.emit('chat:reload-data');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('load_tracker:complete:chat-data', (list) => {
|
this.on('load_tracker:complete:chat-data', list => {
|
||||||
if ( this.triggered_reload ) {
|
if ( this.triggered_reload ) {
|
||||||
const sc = this.resolve('site.chat');
|
const sc = this.resolve('site.chat');
|
||||||
if ( sc?.addNotice )
|
if ( sc?.addNotice )
|
||||||
|
@ -1649,7 +1647,7 @@ export default class Chat extends Module {
|
||||||
|
|
||||||
result.then(value => {
|
result.then(value => {
|
||||||
// If something is already running, don't override it.
|
// If something is already running, don't override it.
|
||||||
let info = this._link_info[url];
|
const info = this._link_info[url];
|
||||||
if ( info )
|
if ( info )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2599,7 +2597,7 @@ export default class Chat extends Module {
|
||||||
emote = emote_set?.emotes?.[token.id];
|
emote = emote_set?.emotes?.[token.id];
|
||||||
|
|
||||||
if ( emote ) {
|
if ( emote ) {
|
||||||
let urls = (animated ? emote.animated : null) ?? emote.urls;
|
const urls = (animated ? emote.animated : null) ?? emote.urls;
|
||||||
let pair = getBiggestImage(urls);
|
let pair = getBiggestImage(urls);
|
||||||
if (! pair )
|
if (! pair )
|
||||||
return null;
|
return null;
|
||||||
|
@ -2873,7 +2871,7 @@ export default class Chat extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onProviderChange(key, value) {
|
onProviderChange(key) {
|
||||||
if ( key !== 'agreed-tos' && key !== 'declined-tos' )
|
if ( key !== 'agreed-tos' && key !== 'declined-tos' )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ export const Clip = {
|
||||||
if ( ! clip || ! clip.broadcaster )
|
if ( ! clip || ! clip.broadcaster )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const game = clip.game,
|
const game = clip.game,
|
||||||
game_display = game && game.displayName;
|
game_display = game && game.displayName;
|
||||||
|
|
||||||
let user = {
|
let user = {
|
||||||
|
@ -359,9 +359,7 @@ export const Video = {
|
||||||
if ( ! result || ! result.data || ! result.data.video || ! result.data.video.owner )
|
if ( ! result || ! result.data || ! result.data.video || ! result.data.video.owner )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const video = result.data.video,
|
const video = result.data.video;
|
||||||
game = video.game,
|
|
||||||
game_display = game && game.displayName;
|
|
||||||
|
|
||||||
const fragments = {
|
const fragments = {
|
||||||
title: video.title,
|
title: video.title,
|
||||||
|
@ -406,7 +404,7 @@ export const Video = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let length = video.lengthSeconds;
|
const length = video.lengthSeconds;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
v: 5,
|
v: 5,
|
||||||
|
@ -483,7 +481,7 @@ export const Video = {
|
||||||
type: 'icon',
|
type: 'icon',
|
||||||
name: 'twitch'
|
name: 'twitch'
|
||||||
},
|
},
|
||||||
" Twitch • ",
|
' Twitch • ',
|
||||||
{
|
{
|
||||||
type: 'format',
|
type: 'format',
|
||||||
format: 'datetime',
|
format: 'datetime',
|
||||||
|
|
|
@ -93,7 +93,7 @@ export default class Room {
|
||||||
this.manager.room_ids[this._id] = null;
|
this.manager.room_ids[this._id] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
0
|
0
|
||||||
merge(other) {
|
merge(other) {
|
||||||
if ( ! this.login && other.login )
|
if ( ! this.login && other.login )
|
||||||
this.login = other.login;
|
this.login = other.login;
|
||||||
|
@ -176,10 +176,11 @@ export default class Room {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: This
|
||||||
_unloadAddon(addon_id) {
|
_unloadAddon(addon_id) {
|
||||||
// TODO: This
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
get id() {
|
get id() {
|
||||||
|
|
|
@ -23,7 +23,7 @@ const SHRINK_X = MODIFIER_FLAGS.ShrinkX,
|
||||||
const EMOTE_CLASS = 'chat-image chat-line__message--emote',
|
const EMOTE_CLASS = 'chat-image chat-line__message--emote',
|
||||||
//WHITESPACE = /^\s*$/,
|
//WHITESPACE = /^\s*$/,
|
||||||
//LINK_REGEX = /([^\w@#%\-+=:~])?((?:(https?:\/\/)?(?:[\w@#%\-+=:~]+\.)+[a-z]{2,6}(?:\/[\w./@#%&()\-+=:?~]*)?))([^\w./@#%&()\-+=:?~]|\s|$)/g,
|
//LINK_REGEX = /([^\w@#%\-+=:~])?((?:(https?:\/\/)?(?:[\w@#%\-+=:~]+\.)+[a-z]{2,6}(?:\/[\w./@#%&()\-+=:?~]*)?))([^\w./@#%&()\-+=:?~]|\s|$)/g,
|
||||||
NEW_LINK_REGEX = /(?:(https?:\/\/)?((?:[\w#%\-+=:~]+\.)+[a-z]{2,10}(?:\/[\w./#%&@()\-+=:?~]*[^\s\.!,?])?))/g,
|
NEW_LINK_REGEX = /(?:(https?:\/\/)?((?:[\w#%\-+=:~]+\.)+[a-z]{2,10}(?:\/[\w./#%&@()\-+=:?~]*[^\s.!,?])?))/g,
|
||||||
//OLD_NEW_LINK_REGEX = /(?:(https?:\/\/)?((?:[\w#%\-+=:~]+\.)+[a-z]{2,10}(?:\/[\w./#%&@()\-+=:?~]*)?))/g,
|
//OLD_NEW_LINK_REGEX = /(?:(https?:\/\/)?((?:[\w#%\-+=:~]+\.)+[a-z]{2,10}(?:\/[\w./#%&@()\-+=:?~]*)?))/g,
|
||||||
//MENTION_REGEX = /([^\w@#%\-+=:~])?(@([^\u0000-\u007F]+|\w+)+)([^\w./@#%&()\-+=:?~]|\s|$)/g; // eslint-disable-line no-control-regex
|
//MENTION_REGEX = /([^\w@#%\-+=:~])?(@([^\u0000-\u007F]+|\w+)+)([^\w./@#%&()\-+=:?~]|\s|$)/g; // eslint-disable-line no-control-regex
|
||||||
MENTION_REGEX = /^(['"*([{<\\/]*)(@)((?:[^\u0000-\u007F]|[\w-])+)(?:\b|$)/; // eslint-disable-line no-control-regex
|
MENTION_REGEX = /^(['"*([{<\\/]*)(@)((?:[^\u0000-\u007F]|[\w-])+)(?:\b|$)/; // eslint-disable-line no-control-regex
|
||||||
|
@ -322,81 +322,6 @@ export const Replies = {
|
||||||
// Mentions
|
// Mentions
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
function mention_processAll(tokens, msg, user, color_mentions) {
|
|
||||||
const can_highlight_user = user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own'),
|
|
||||||
priority = this.context.get('chat.filtering.mention-priority');
|
|
||||||
|
|
||||||
let login, display, mentionable = false;
|
|
||||||
if ( user && user.login && ! can_highlight_user ) {
|
|
||||||
login = user.login.toLowerCase();
|
|
||||||
display = user.displayName && user.displayName.toLowerCase();
|
|
||||||
if ( display === login )
|
|
||||||
display = null;
|
|
||||||
|
|
||||||
mentionable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const out = [];
|
|
||||||
for(const token of tokens) {
|
|
||||||
if ( token.type !== 'text' ) {
|
|
||||||
out.push(token);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let text = [];
|
|
||||||
|
|
||||||
for(const segment of token.text.split(/ +/)) {
|
|
||||||
const match = /^(@?)(\S+?)(?:\b|$)/.exec(segment);
|
|
||||||
if ( match ) {
|
|
||||||
let recipient = match[2],
|
|
||||||
has_at = match[1] === '@',
|
|
||||||
mentioned = false;
|
|
||||||
|
|
||||||
const rlower = recipient ? recipient.toLowerCase() : '',
|
|
||||||
color = this.color_cache ? this.color_cache.get(rlower) : null;
|
|
||||||
|
|
||||||
if ( rlower === login || rlower === display )
|
|
||||||
mentioned = true;
|
|
||||||
|
|
||||||
if ( ! has_at && ! color && ! mentioned ) {
|
|
||||||
text.push(segment);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// If we have pending text, join it together.
|
|
||||||
if ( text.length ) {
|
|
||||||
out.push({
|
|
||||||
type: 'text',
|
|
||||||
text: `${text.join(' ')} `
|
|
||||||
});
|
|
||||||
text = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
out.push({
|
|
||||||
type: 'mention',
|
|
||||||
text: match[0],
|
|
||||||
me: mentioned,
|
|
||||||
color: color_mentions ? color : null,
|
|
||||||
recipient: rlower
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( mentioned )
|
|
||||||
this.applyHighlight(msg, priority, null, 'mention', true);
|
|
||||||
|
|
||||||
// Push the remaining text from the token.
|
|
||||||
text.push(segment.substr(match[0].length));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
|
||||||
text.push(segment);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( text.length > 1 || (text.length === 1 && text[0] !== '') )
|
|
||||||
out.push({type: 'text', text: text.join(' ')})
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Mentions = {
|
export const Mentions = {
|
||||||
type: 'mention',
|
type: 'mention',
|
||||||
priority: 0,
|
priority: 0,
|
||||||
|
@ -434,7 +359,7 @@ export const Mentions = {
|
||||||
color_mentions = this.context.get('chat.filtering.color-mentions');
|
color_mentions = this.context.get('chat.filtering.color-mentions');
|
||||||
|
|
||||||
if ( all_mentions )
|
if ( all_mentions )
|
||||||
return mention_processAll.call(this, tokens, msg, user, color_mentions);
|
return this.processAll(tokens, msg, user, color_mentions);
|
||||||
|
|
||||||
const can_highlight_user = user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own'),
|
const can_highlight_user = user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own'),
|
||||||
priority = this.context.get('chat.filtering.mention-priority');
|
priority = this.context.get('chat.filtering.mention-priority');
|
||||||
|
@ -510,6 +435,79 @@ export const Mentions = {
|
||||||
out.push({type: 'text', text: text.join(' ')})
|
out.push({type: 'text', text: text.join(' ')})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
},
|
||||||
|
|
||||||
|
processAll(tokens, msg, user, color_mentions) {
|
||||||
|
const can_highlight_user = user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own'),
|
||||||
|
priority = this.context.get('chat.filtering.mention-priority');
|
||||||
|
|
||||||
|
let login, display = false;
|
||||||
|
if ( user && user.login && ! can_highlight_user ) {
|
||||||
|
login = user.login.toLowerCase();
|
||||||
|
display = user.displayName && user.displayName.toLowerCase();
|
||||||
|
if ( display === login )
|
||||||
|
display = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const out = [];
|
||||||
|
for(const token of tokens) {
|
||||||
|
if ( token.type !== 'text' ) {
|
||||||
|
out.push(token);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = [];
|
||||||
|
|
||||||
|
for(const segment of token.text.split(/ +/)) {
|
||||||
|
const match = /^(@?)(\S+?)(?:\b|$)/.exec(segment);
|
||||||
|
if ( match ) {
|
||||||
|
const recipient = match[2],
|
||||||
|
has_at = match[1] === '@';
|
||||||
|
let mentioned = false;
|
||||||
|
|
||||||
|
const rlower = recipient ? recipient.toLowerCase() : '',
|
||||||
|
color = this.color_cache ? this.color_cache.get(rlower) : null;
|
||||||
|
|
||||||
|
if ( rlower === login || rlower === display )
|
||||||
|
mentioned = true;
|
||||||
|
|
||||||
|
if ( ! has_at && ! color && ! mentioned ) {
|
||||||
|
text.push(segment);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If we have pending text, join it together.
|
||||||
|
if ( text.length ) {
|
||||||
|
out.push({
|
||||||
|
type: 'text',
|
||||||
|
text: `${text.join(' ')} `
|
||||||
|
});
|
||||||
|
text = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push({
|
||||||
|
type: 'mention',
|
||||||
|
text: match[0],
|
||||||
|
me: mentioned,
|
||||||
|
color: color_mentions ? color : null,
|
||||||
|
recipient: rlower
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( mentioned )
|
||||||
|
this.applyHighlight(msg, priority, null, 'mention', true);
|
||||||
|
|
||||||
|
// Push the remaining text from the token.
|
||||||
|
text.push(segment.substr(match[0].length));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
text.push(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( text.length > 1 || (text.length === 1 && text[0] !== '') )
|
||||||
|
out.push({type: 'text', text: text.join(' ')})
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1312,13 +1310,13 @@ export const AddonEmotes = {
|
||||||
hoverSrcSet = big ? token.animSrcSet2 : token.animSrcSet;
|
hoverSrcSet = big ? token.animSrcSet2 : token.animSrcSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
let style = undefined, outerStyle = undefined;
|
let style, outerStyle;
|
||||||
const mods = token.modifiers || [], ml = mods.length,
|
const mods = token.modifiers || [], ml = mods.length,
|
||||||
effects = token.modifier_flags,
|
effects = token.modifier_flags,
|
||||||
is_big = (token.big && ! token.can_big && token.height);
|
is_big = (token.big && ! token.can_big && token.height);
|
||||||
|
|
||||||
let as_bg = (this.emotes.activeAsBackgroundMask & effects) !== 0;
|
let as_bg = (this.emotes.activeAsBackgroundMask & effects) !== 0;
|
||||||
let no_wide = (this.emotes.activeNoWideMask & effects) !== 0;
|
const no_wide = (this.emotes.activeNoWideMask & effects) !== 0;
|
||||||
|
|
||||||
if ( no_wide || effects || ml ) {
|
if ( no_wide || effects || ml ) {
|
||||||
// We need to calculate the size of the emote and the biggest
|
// We need to calculate the size of the emote and the biggest
|
||||||
|
@ -1620,19 +1618,19 @@ export const AddonEmotes = {
|
||||||
|
|
||||||
const target = this.emotes.getTargetEmote();
|
const target = this.emotes.getTargetEmote();
|
||||||
|
|
||||||
let style = {
|
const style = {
|
||||||
width: (target.width ?? 28) * 2,
|
width: (target.width ?? 28) * 2,
|
||||||
height: (target.height ?? 28) * 2
|
height: (target.height ?? 28) * 2
|
||||||
};
|
};
|
||||||
|
|
||||||
let outerStyle = {
|
const outerStyle = {
|
||||||
width: style.width,
|
width: style.width,
|
||||||
height: style.height
|
height: style.height
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let as_bg = (this.emotes.activeAsBackgroundMask & effects) !== 0;
|
const as_bg = (this.emotes.activeAsBackgroundMask & effects) !== 0;
|
||||||
let no_wide = (this.emotes.activeNoWideMask & effects) !== 0;
|
const no_wide = (this.emotes.activeNoWideMask & effects) !== 0;
|
||||||
|
|
||||||
let changed = false;
|
let changed = false;
|
||||||
|
|
||||||
|
@ -1696,6 +1694,7 @@ export const AddonEmotes = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whip up a special preview.
|
// Whip up a special preview.
|
||||||
|
/* eslint-disable indent -- disagrees with react/jsx-indent-props */
|
||||||
preview = (<div class="ffz-effect-tip">
|
preview = (<div class="ffz-effect-tip">
|
||||||
<img
|
<img
|
||||||
src={target.src}
|
src={target.src}
|
||||||
|
@ -1713,20 +1712,21 @@ export const AddonEmotes = {
|
||||||
>
|
>
|
||||||
{as_bg
|
{as_bg
|
||||||
? <div
|
? <div
|
||||||
class={`${EMOTE_CLASS} ffz--pointer-events ffz-tooltip ffz-emote`}
|
class={`${EMOTE_CLASS} ffz--pointer-events ffz-tooltip ffz-emote`}
|
||||||
style={style}
|
style={style}
|
||||||
/>
|
/>
|
||||||
: <img
|
: <img
|
||||||
class={`${EMOTE_CLASS} ffz--pointer-events ffz-tooltip ffz-emote`}
|
class={`${EMOTE_CLASS} ffz--pointer-events ffz-tooltip ffz-emote`}
|
||||||
src={target.src}
|
src={target.src}
|
||||||
srcSet={target.srcSet}
|
srcSet={target.srcSet}
|
||||||
style={style}
|
style={style}
|
||||||
height={style ? undefined : `${target.height * 2}px`}
|
height={style ? undefined : `${target.height * 2}px`}
|
||||||
onLoad={tip.update}
|
onLoad={tip.update}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>);
|
</div>);
|
||||||
|
/* eslint-enable indent */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1861,10 +1861,10 @@ export const AddonEmotes = {
|
||||||
|
|
||||||
last_token.modifiers.push(
|
last_token.modifiers.push(
|
||||||
Object.assign({
|
Object.assign({
|
||||||
big,
|
big,
|
||||||
anim
|
anim
|
||||||
},
|
},
|
||||||
emote.token
|
emote.token
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2010,7 +2010,7 @@ export const Emoji = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const text = replace ?
|
const text = replace ?
|
||||||
token.text.replace(JOINER_REPLACEMENT, "\u200d") :
|
token.text.replace(JOINER_REPLACEMENT, '\u200d') :
|
||||||
token.text;
|
token.text;
|
||||||
|
|
||||||
splitter.lastIndex = 0;
|
splitter.lastIndex = 0;
|
||||||
|
|
|
@ -94,10 +94,12 @@
|
||||||
@click="toggleFavorite"
|
@click="toggleFavorite"
|
||||||
>
|
>
|
||||||
<span class="tw-button-icon__icon">
|
<span class="tw-button-icon__icon">
|
||||||
<figure :class="{
|
<figure
|
||||||
'ffz-i-star': isFavorite,
|
:class="{
|
||||||
'ffz-i-star-empty': ! isFavorite
|
'ffz-i-star': isFavorite,
|
||||||
}" />
|
'ffz-i-star-empty': ! isFavorite
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<div class="tw-flex tw-flex-column tw-align-self-start">
|
<div class="tw-flex tw-flex-column tw-align-self-start">
|
||||||
|
@ -175,20 +177,20 @@
|
||||||
<ReportForm
|
<ReportForm
|
||||||
v-if="reporting"
|
v-if="reporting"
|
||||||
:emote="emote"
|
:emote="emote"
|
||||||
:getFFZ="getFFZ"
|
:get-f-f-z="getFFZ"
|
||||||
@close="close"
|
@close="close"
|
||||||
/>
|
/>
|
||||||
<component
|
<component
|
||||||
v-if="! reporting && loaded && hasBody"
|
|
||||||
:is="bodyComponent"
|
:is="bodyComponent"
|
||||||
|
v-if="! reporting && loaded && hasBody"
|
||||||
:emote="emote"
|
:emote="emote"
|
||||||
:getFFZ="getFFZ"
|
:get-f-f-z="getFFZ"
|
||||||
@close="close"
|
@close="close"
|
||||||
/>
|
/>
|
||||||
<Modifiers
|
<Modifiers
|
||||||
v-if="! reporting && raw_modifiers && raw_modifiers.length"
|
v-if="! reporting && raw_modifiers && raw_modifiers.length"
|
||||||
:raw_modifiers="raw_modifiers"
|
:raw_modifiers="raw_modifiers"
|
||||||
:getFFZ="getFFZ"
|
:get-f-f-z="getFFZ"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -352,13 +354,13 @@ export default {
|
||||||
|
|
||||||
if ( entry.type === 'report-ffz' )
|
if ( entry.type === 'report-ffz' )
|
||||||
this.reporting = true;
|
this.reporting = true;
|
||||||
this.$nextTick(() => this.handleResize());
|
this.$nextTick(() => this.handleResize());
|
||||||
|
|
||||||
if ( entry.type === 'report-twitch' ) {
|
if ( entry.type === 'report-twitch' ) {
|
||||||
if ( this.reportTwitchEmote(this.emote.id, this.emote.channel_id) )
|
if ( this.reportTwitchEmote(this.emote.id, this.emote.channel_id) )
|
||||||
this.close();
|
this.close();
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -371,7 +373,7 @@ export default {
|
||||||
parent = document.body;
|
parent = document.body;
|
||||||
|
|
||||||
const box = el.getBoundingClientRect();
|
const box = el.getBoundingClientRect();
|
||||||
let pbox = parent.getBoundingClientRect();
|
const pbox = parent.getBoundingClientRect();
|
||||||
|
|
||||||
if ( box.top < pbox.top ) {
|
if ( box.top < pbox.top ) {
|
||||||
el.style.top = `${el.offsetTop + (pbox.top - box.top)}px`;
|
el.style.top = `${el.offsetTop + (pbox.top - box.top)}px`;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<img
|
<img
|
||||||
class="tw-block tw-image tw-image-avatar"
|
class="tw-block tw-image tw-image-avatar"
|
||||||
:src="image"
|
:src="image"
|
||||||
/>
|
>
|
||||||
</figure>
|
</figure>
|
||||||
<div class="tw-flex-grow-1">
|
<div class="tw-flex-grow-1">
|
||||||
{{ collection.title }}
|
{{ collection.title }}
|
||||||
|
@ -161,11 +161,11 @@ export default {
|
||||||
throw new Error('collection at limit');
|
throw new Error('collection at limit');
|
||||||
|
|
||||||
const resp = await fetch(url, {
|
const resp = await fetch(url, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`
|
Authorization: `Bearer ${token}`
|
||||||
}
|
}
|
||||||
}).then(r => r.ok ? r.json() : null);
|
}).then(r => r.ok ? r.json() : null);
|
||||||
|
|
||||||
this.isInCollection = true;
|
this.isInCollection = true;
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,12 @@
|
||||||
{{ t('emote-card.error', 'There was an error loading data.') }}
|
{{ t('emote-card.error', 'There was an error loading data.') }}
|
||||||
</div>
|
</div>
|
||||||
<CollectionEntry
|
<CollectionEntry
|
||||||
v-else
|
|
||||||
v-for="collection in collections"
|
v-for="collection in collections"
|
||||||
|
v-else
|
||||||
:key="collection.id"
|
:key="collection.id"
|
||||||
:collection="collection"
|
:collection="collection"
|
||||||
:emote="emote"
|
:emote="emote"
|
||||||
:getFFZ="getFFZ"
|
:get-f-f-z="getFFZ"
|
||||||
:initial="presence.includes(collection.id)"
|
:initial="presence.includes(collection.id)"
|
||||||
/>
|
/>
|
||||||
</simplebar>
|
</simplebar>
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="expanded"
|
|
||||||
v-for="(mod, idx) in modifiers"
|
v-for="(mod, idx) in modifiers"
|
||||||
|
v-if="expanded"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
class="tw-pd-05 tw-flex tw-align-items-center tw-border-t"
|
class="tw-pd-05 tw-flex tw-align-items-center tw-border-t"
|
||||||
>
|
>
|
||||||
|
@ -48,7 +48,9 @@
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
<div class="tw-align-left tw-flex-grow-1 tw-ellipsis tw-mg-x-1">
|
<div class="tw-align-left tw-flex-grow-1 tw-ellipsis tw-mg-x-1">
|
||||||
<h4 class="tw-inline" :title="mod.name">{{ mod.name }}</h4>
|
<h4 class="tw-inline" :title="mod.name">
|
||||||
|
{{ mod.name }}
|
||||||
|
</h4>
|
||||||
<p
|
<p
|
||||||
v-if="mod.source"
|
v-if="mod.source"
|
||||||
class="tw-c-text-alt-2 tw-font-size-6"
|
class="tw-c-text-alt-2 tw-font-size-6"
|
||||||
|
|
|
@ -48,7 +48,9 @@
|
||||||
phrase="emote-card.report-details"
|
phrase="emote-card.report-details"
|
||||||
default="You are reporting this emote for {reason}. Please enter any additional details below:"
|
default="You are reporting this emote for {reason}. Please enter any additional details below:"
|
||||||
>
|
>
|
||||||
<template #reason><code>{{ category.i18n ? t(category.i18n, category.title, category) : category.title }}</code></template>
|
<template #reason>
|
||||||
|
<code>{{ category.i18n ? t(category.i18n, category.title, category) : category.title }}</code>
|
||||||
|
</template>
|
||||||
</t-list>
|
</t-list>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -88,12 +90,12 @@
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
:id="'report$' + id + '$reason$' + idx"
|
:id="'report$' + id + '$reason$' + idx"
|
||||||
:name="'report-reasons$' + id"
|
|
||||||
v-model="pendingCategory"
|
v-model="pendingCategory"
|
||||||
|
:name="'report-reasons$' + id"
|
||||||
:value="reason"
|
:value="reason"
|
||||||
type="radio"
|
type="radio"
|
||||||
class="ffz-radio__input"
|
class="ffz-radio__input"
|
||||||
/>
|
>
|
||||||
<label
|
<label
|
||||||
:for="'report$' + id + '$reason$' + idx"
|
:for="'report$' + id + '$reason$' + idx"
|
||||||
class="tw-block ffz-radio__label tw-pd-r-1 tw-pd-y-1"
|
class="tw-block ffz-radio__label tw-pd-r-1 tw-pd-y-1"
|
||||||
|
@ -117,7 +119,6 @@
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
@ -155,7 +156,7 @@ export default {
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
REASONS: REASONS,
|
REASONS,
|
||||||
id: id++,
|
id: id++,
|
||||||
message: '',
|
message: '',
|
||||||
pendingCategory: null,
|
pendingCategory: null,
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
<figure class="ffz-emote-card__live-indicator tw-mg-r-05" />
|
<figure class="ffz-emote-card__live-indicator tw-mg-r-05" />
|
||||||
{{ t('emote-card.live', 'LIVE') }}
|
{{ t('emote-card.live', 'LIVE') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<template v-if="isSubscriptionEmote">
|
<template v-if="isSubscriptionEmote">
|
||||||
<p v-if="emote.unlocked">
|
<p v-if="emote.unlocked">
|
||||||
|
@ -75,7 +74,7 @@
|
||||||
:data-title="extra.name"
|
:data-title="extra.name"
|
||||||
class="ffz-tooltip"
|
class="ffz-tooltip"
|
||||||
>
|
>
|
||||||
<img :src="extra.src" :srcset="extra.srcSet" :alt="extra.name" />
|
<img :src="extra.src" :srcset="extra.srcSet" :alt="extra.name">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="emote.channel_id" class="tw-mg-t-1 tw-flex">
|
<div v-if="emote.channel_id" class="tw-mg-t-1 tw-flex">
|
||||||
|
|
|
@ -213,7 +213,7 @@ export default class EmoteCard extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
source = this.i18n.t('emote-card.sub', 'Tier {tier} Sub Emote ({source})', {
|
source = this.i18n.t('emote-card.sub', 'Tier {tier} Sub Emote ({source})', {
|
||||||
tier: tier,
|
tier,
|
||||||
source: data.owner?.displayName || data.owner?.login
|
source: data.owner?.displayName || data.owner?.login
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -287,12 +287,12 @@ export default class EmoteCard extends Module {
|
||||||
|
|
||||||
// Check if we can actually submit a report.
|
// Check if we can actually submit a report.
|
||||||
if ( this.canReportTwitch() )
|
if ( this.canReportTwitch() )
|
||||||
out.more.push({
|
out.more.push({
|
||||||
type: 'report-twitch',
|
type: 'report-twitch',
|
||||||
title_i18n: 'emote-card.report',
|
title_i18n: 'emote-card.report',
|
||||||
title: 'Report Emote',
|
title: 'Report Emote',
|
||||||
icon: 'ffz-i-flag'
|
icon: 'ffz-i-flag'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( data.bitsBadgeTierSummary?.threshold ) {
|
if ( data.bitsBadgeTierSummary?.threshold ) {
|
||||||
|
@ -511,7 +511,7 @@ export default class EmoteCard extends Module {
|
||||||
props: {
|
props: {
|
||||||
raw_emote: deep_copy(emote),
|
raw_emote: deep_copy(emote),
|
||||||
raw_modifiers: modifiers,
|
raw_modifiers: modifiers,
|
||||||
data: data,
|
data,
|
||||||
|
|
||||||
getFFZ: () => this,
|
getFFZ: () => this,
|
||||||
reportTwitchEmote: (...args) => this.reportTwitchEmote(...args),
|
reportTwitchEmote: (...args) => this.reportTwitchEmote(...args),
|
||||||
|
|
|
@ -145,13 +145,13 @@
|
||||||
<ManageFFZ
|
<ManageFFZ
|
||||||
v-if="active_tab === 'manage' && ffzEmote"
|
v-if="active_tab === 'manage' && ffzEmote"
|
||||||
:emote="ffzEmote"
|
:emote="ffzEmote"
|
||||||
:getFFZ="getFFZ"
|
:get-f-f-z="getFFZ"
|
||||||
:no-header="true"
|
:no-header="true"
|
||||||
/>
|
/>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
<div
|
<div
|
||||||
class="tw-c-background-base tw-pd-05"
|
|
||||||
v-if="active_tab === 'urls'"
|
v-if="active_tab === 'urls'"
|
||||||
|
class="tw-c-background-base tw-pd-05"
|
||||||
>
|
>
|
||||||
<table v-if="embed && embed.urls && embed.urls.length">
|
<table v-if="embed && embed.urls && embed.urls.length">
|
||||||
<tbody
|
<tbody
|
||||||
|
@ -159,7 +159,9 @@
|
||||||
:key="idx"
|
:key="idx"
|
||||||
>
|
>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tw-c-text-alt-2">{{ tNumber(idx + 1) }}.</td>
|
<td class="tw-c-text-alt-2">
|
||||||
|
{{ tNumber(idx + 1) }}.
|
||||||
|
</td>
|
||||||
<td class="tw-pd-x-05 tw-word-break-all">
|
<td class="tw-pd-x-05 tw-word-break-all">
|
||||||
<a
|
<a
|
||||||
:data-url="url.url"
|
:data-url="url.url"
|
||||||
|
@ -180,8 +182,8 @@
|
||||||
class="ffz-pill"
|
class="ffz-pill"
|
||||||
>{{ t('link-card.shortened', 'shortened') }}</span>
|
>{{ t('link-card.shortened', 'shortened') }}</span>
|
||||||
<span
|
<span
|
||||||
v-if="url.flags"
|
|
||||||
v-for="flag in url.flags"
|
v-for="flag in url.flags"
|
||||||
|
v-if="url.flags"
|
||||||
class="ffz-pill ffz-pill--live"
|
class="ffz-pill ffz-pill--live"
|
||||||
>{{ flag }}</span>
|
>{{ flag }}</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
import { createElement } from 'utilities/dom';
|
import { createElement } from 'utilities/dom';
|
||||||
import { getDialogNextZ } from 'utilities/dialog';
|
import { getDialogNextZ } from 'utilities/dialog';
|
||||||
import { deep_copy } from 'utilities/object';
|
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
|
||||||
|
@ -88,7 +87,7 @@ export default class LinkCard extends Module {
|
||||||
|
|
||||||
out.push(createElement('span', url.host));
|
out.push(createElement('span', url.host));
|
||||||
|
|
||||||
let suffix = url.toString().slice(url.origin.length);
|
const suffix = url.toString().slice(url.origin.length);
|
||||||
|
|
||||||
if ( suffix.length && suffix !== '/' )
|
if ( suffix.length && suffix !== '/' )
|
||||||
out.push(createElement('span', {
|
out.push(createElement('span', {
|
||||||
|
@ -112,7 +111,7 @@ export default class LinkCard extends Module {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos_x = event ? event.clientX : window.innerWidth / 2,
|
const pos_x = event ? event.clientX : window.innerWidth / 2,
|
||||||
pos_y = event ? event.clientY + 15 : window.innerHeight / 2;
|
pos_y = event ? event.clientY + 15 : window.innerHeight / 2;
|
||||||
|
|
||||||
/*if ( this.last_card ) {
|
/*if ( this.last_card ) {
|
||||||
|
@ -150,7 +149,7 @@ export default class LinkCard extends Module {
|
||||||
render: h => h('link-card', {
|
render: h => h('link-card', {
|
||||||
props: {
|
props: {
|
||||||
url: link,
|
url: link,
|
||||||
data: data,
|
data,
|
||||||
|
|
||||||
use_dest: this.settings.get('link-cards.use-destination'),
|
use_dest: this.settings.get('link-cards.use-destination'),
|
||||||
|
|
||||||
|
@ -197,4 +196,4 @@ export default class LinkCard extends Module {
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -827,7 +827,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
maybeDynamic(data) {
|
maybeDynamic(data) {
|
||||||
let ap = data.appearance;
|
const ap = data.appearance;
|
||||||
if (ap?.type === 'dynamic') {
|
if (ap?.type === 'dynamic') {
|
||||||
const act = this.action_def,
|
const act = this.action_def,
|
||||||
ffz = this.vuectx.getFFZ(),
|
ffz = this.vuectx.getFFZ(),
|
||||||
|
|
|
@ -149,20 +149,16 @@
|
||||||
|
|
||||||
import {get} from 'utilities/object';
|
import {get} from 'utilities/object';
|
||||||
|
|
||||||
const TITLE_MATCH = /^(.+?)?\s*v?(\d+\.\d+\.\d+(?:\-[a-z0-9-]+)?)$/i,
|
const TITLE_MATCH = /^(.+?)?\s*v?(\d+\.\d+\.\d+(?:-[a-z0-9-]+)?)$/i,
|
||||||
SETTING_REGEX = /\]\(~([^)]+)\)/g,
|
SETTING_REGEX = /\]\(~([^)]+)\)/g,
|
||||||
CHANGE_REGEX = /^\*\s*([^:]+?):\s*(.+)$/i,
|
CHANGE_REGEX = /^\*\s*([^:]+?):\s*(.+)$/i,
|
||||||
ISSUE_REGEX = /(^|\s)#(\d+)\b/g;
|
ISSUE_REGEX = /(^|\s)#(\d+)\b/g;
|
||||||
|
|
||||||
|
|
||||||
function linkify(text, repo) {
|
function linkify(text, repo) {
|
||||||
text = text.replace(SETTING_REGEX, (_, link) => {
|
text = text.replace(SETTING_REGEX, (_, link) => `](~${link})`);
|
||||||
return `](~${link})`
|
|
||||||
});
|
|
||||||
|
|
||||||
return text.replace(ISSUE_REGEX, (_, space, number) => {
|
return text.replace(ISSUE_REGEX, (_, space, number) => `${space}[#${number}](https://github.com/FrankerFaceZ/${repo}/issues/${number})`);
|
||||||
return `${space}[#${number}](https://github.com/FrankerFaceZ/${repo}/issues/${number})`;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,13 +186,13 @@ export default {
|
||||||
old_commit = this.t('home.changelog.nonversioned', 'Non-Versioned Commit');
|
old_commit = this.t('home.changelog.nonversioned', 'Non-Versioned Commit');
|
||||||
|
|
||||||
for(const commit of this.commits) {
|
for(const commit of this.commits) {
|
||||||
const input = commit.commit.message;
|
const input = commit.commit.message,
|
||||||
|
sections = {};
|
||||||
let title = old_commit,
|
let title = old_commit,
|
||||||
title_nav = null,
|
title_nav = null,
|
||||||
icon = null,
|
icon = null,
|
||||||
version = null,
|
version = null,
|
||||||
author = null,
|
author = null,
|
||||||
sections = {},
|
|
||||||
description = [];
|
description = [];
|
||||||
|
|
||||||
if ( /\bskiplog\b/i.test(input) && ! this.nonversion )
|
if ( /\bskiplog\b/i.test(input) && ! this.nonversion )
|
||||||
|
@ -248,7 +244,7 @@ export default {
|
||||||
description = lines;
|
description = lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = description.join('\n').trim();
|
const message = description.join('\n').trim();
|
||||||
|
|
||||||
const segments = [];
|
const segments = [];
|
||||||
|
|
||||||
|
@ -388,4 +384,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -296,7 +296,7 @@
|
||||||
:act="maybeDynamic(preset)"
|
:act="maybeDynamic(preset)"
|
||||||
:process-color="color"
|
:process-color="color"
|
||||||
:renderers="data.renderers"
|
:renderers="data.renderers"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -794,7 +794,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
maybeDynamic(data) {
|
maybeDynamic(data) {
|
||||||
let ap = data.appearance;
|
const ap = data.appearance;
|
||||||
if (ap?.type === 'dynamic') {
|
if (ap?.type === 'dynamic') {
|
||||||
const act = this.data.actions[data.action],
|
const act = this.data.actions[data.action],
|
||||||
ffz = this.context.getFFZ(),
|
ffz = this.context.getFFZ(),
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
class="tw-block tw-font-size-6 tw-full-width ffz-textarea ffz-mg-t-1p"
|
class="tw-block tw-font-size-6 tw-full-width ffz-textarea ffz-mg-t-1p"
|
||||||
@blur="updateMessage"
|
@blur="updateMessage"
|
||||||
@input="onMessageChange"
|
@input="onMessageChange"
|
||||||
/>
|
>
|
||||||
<textarea
|
<textarea
|
||||||
ref="message"
|
ref="message"
|
||||||
class="tw-block tw-font-size-6 tw-full-width ffz-textarea ffz-mg-t-1p tw-border-bottom-left-radius-medium tw-border-bottom-right-radius-medium"
|
class="tw-block tw-font-size-6 tw-full-width ffz-textarea ffz-mg-t-1p tw-border-bottom-left-radius-medium tw-border-bottom-right-radius-medium"
|
||||||
|
@ -151,17 +151,25 @@
|
||||||
{{ tTime(item.timestamp, 'HH:mm:ss') }}
|
{{ tTime(item.timestamp, 'HH:mm:ss') }}
|
||||||
</time>
|
</time>
|
||||||
<div v-if="item.pubsub" class="tw-flex-grow-1">
|
<div v-if="item.pubsub" class="tw-flex-grow-1">
|
||||||
<div class="tw-mg-b-05 tw-border-b tw-pd-b-05">{{ item.topic }}</div>
|
<div class="tw-mg-b-05 tw-border-b tw-pd-b-05">
|
||||||
|
{{ item.topic }}
|
||||||
|
</div>
|
||||||
<div v-html="highlightJson(item.data)" />
|
<div v-html="highlightJson(item.data)" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.chat" class="tw-flex-grow-1">
|
<div v-else-if="item.chat" class="tw-flex-grow-1">
|
||||||
<div v-if="item.tags" class="ffz-ct--tags">
|
<div v-if="item.tags" class="ffz-ct--tags">
|
||||||
@<template v-for="(tag, key) in item.tags"><span class="ffz-ct--tag">{{ key }}</span>=<span class="ffz-ct--tag-value">{{ tag }}</span>;</template>
|
@<template v-for="(tag, key) in item.tags">
|
||||||
|
<span class="ffz-ct--tag">{{ key }}</span>=<span class="ffz-ct--tag-value">{{ tag }}</span>;
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="ffz-ct--prefix">
|
<div class="ffz-ct--prefix">
|
||||||
<template v-if="item.prefix">:<span v-if="item.user" class="ffz-ct--user">{{ item.user }}</span><span class="ffz-ct--prefix">{{ item.prefix }}</span></template>
|
<template v-if="item.prefix">
|
||||||
|
:<span v-if="item.user" class="ffz-ct--user">{{ item.user }}</span><span class="ffz-ct--prefix">{{ item.prefix }}</span>
|
||||||
|
</template>
|
||||||
<span class="ffz-ct--command">{{ item.command }}</span>
|
<span class="ffz-ct--command">{{ item.command }}</span>
|
||||||
<template v-if="item.channel">#<span class="ffz-ct--channel">{{ item.channel }}</span></template>
|
<template v-if="item.channel">
|
||||||
|
#<span class="ffz-ct--channel">{{ item.channel }}</span>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="item.last_param" class="ffz-ct--params">
|
<div v-if="item.last_param" class="ffz-ct--params">
|
||||||
<span v-for="para in item.params" class="ffz-ct--param">{{ para }}</span>
|
<span v-for="para in item.params" class="ffz-ct--param">{{ para }}</span>
|
||||||
|
@ -212,8 +220,8 @@ const IGNORE_COMMANDS = [
|
||||||
|
|
||||||
let LOADED_SAMPLES = [
|
let LOADED_SAMPLES = [
|
||||||
{
|
{
|
||||||
"name": "Ping",
|
'name': 'Ping',
|
||||||
"data": "PING :tmi.twitch.tv"
|
'data': 'PING :tmi.twitch.tv'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -228,7 +236,7 @@ export default {
|
||||||
const message = state?.ffz_ct_message ?? samples[0].data;
|
const message = state?.ffz_ct_message ?? samples[0].data;
|
||||||
const topic = state?.ffz_ct_topic ?? samples[0].topic ?? '';
|
const topic = state?.ffz_ct_topic ?? samples[0].topic ?? '';
|
||||||
|
|
||||||
let is_custom = true;
|
const is_custom = true;
|
||||||
/*for(const item of samples) {
|
/*for(const item of samples) {
|
||||||
if ( ! item.topic )
|
if ( ! item.topic )
|
||||||
item.topic = '';
|
item.topic = '';
|
||||||
|
@ -384,7 +392,7 @@ export default {
|
||||||
if ( conn.ws )
|
if ( conn.ws )
|
||||||
conn.ws.onmessage = conn.onSocketMessage;
|
conn.ws.onmessage = conn.onSocketMessage;
|
||||||
|
|
||||||
this.addLog("Started capturing chat.");
|
this.addLog('Started capturing chat.');
|
||||||
|
|
||||||
this.listening_chat = true;
|
this.listening_chat = true;
|
||||||
},
|
},
|
||||||
|
@ -400,7 +408,7 @@ export default {
|
||||||
if ( conn.ws )
|
if ( conn.ws )
|
||||||
conn.ws.onmessage = conn.onSocketMessage;
|
conn.ws.onmessage = conn.onSocketMessage;
|
||||||
|
|
||||||
this.addLog("Stopped capturing chat.");
|
this.addLog('Stopped capturing chat.');
|
||||||
|
|
||||||
this.listening_chat = false;
|
this.listening_chat = false;
|
||||||
},
|
},
|
||||||
|
@ -451,7 +459,7 @@ export default {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.chat.on('site.subpump:pubsub-message', this.handlePubsub, this);
|
this.chat.on('site.subpump:pubsub-message', this.handlePubsub, this);
|
||||||
this.addLog("Started capturing PubSub.");
|
this.addLog('Started capturing PubSub.');
|
||||||
|
|
||||||
this.listening_pubsub = true;
|
this.listening_pubsub = true;
|
||||||
},
|
},
|
||||||
|
@ -461,7 +469,7 @@ export default {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.chat.off('site.subpump:pubsub-message', this.handlePubsub, this);
|
this.chat.off('site.subpump:pubsub-message', this.handlePubsub, this);
|
||||||
this.addLog("Stopped capturing PubSub.");
|
this.addLog('Stopped capturing PubSub.');
|
||||||
|
|
||||||
this.listening_pubsub = false;
|
this.listening_pubsub = false;
|
||||||
},
|
},
|
||||||
|
@ -589,7 +597,7 @@ export default {
|
||||||
data = JSON.parse(this.message);
|
data = JSON.parse(this.message);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
alert("Unable to parse message.");
|
alert('Unable to parse message.'); // eslint-disable-line no-alert -- this is a dev tool
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,7 +620,7 @@ export default {
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
alert("Unable to parse message.");
|
alert('Unable to parse message.'); // eslint-disable-line no-alert -- this is a dev tool
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,17 +56,19 @@
|
||||||
<img
|
<img
|
||||||
:src="provider.icon"
|
:src="provider.icon"
|
||||||
class="tw-image"
|
class="tw-image"
|
||||||
/>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 v-if="! provider.name">
|
<h4 v-if="! provider.name">
|
||||||
{{ t('emote-source.unknown', 'Unknown ({id})', provider) }}
|
{{ t('emote-source.unknown', 'Unknown ({id})', provider) }}
|
||||||
</h4>
|
</h4>
|
||||||
<h4 v-else>{{
|
<h4 v-else>
|
||||||
provider.i18n_key
|
{{
|
||||||
? t(provider.i18n_key, provider.name, provider)
|
provider.i18n_key
|
||||||
: provider.name
|
? t(provider.i18n_key, provider.name, provider)
|
||||||
}}</h4>
|
: provider.name
|
||||||
|
}}
|
||||||
|
</h4>
|
||||||
<div v-if="provider.description">
|
<div v-if="provider.description">
|
||||||
{{ provider.desc_i18n_key ? t(provider.desc_i18n_key, provider.description, provider) : provider.description }}
|
{{ provider.desc_i18n_key ? t(provider.desc_i18n_key, provider.description, provider) : provider.description }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -81,9 +83,6 @@
|
||||||
|
|
||||||
import settingMixin from '../setting-mixin';
|
import settingMixin from '../setting-mixin';
|
||||||
import Sortable from 'sortablejs';
|
import Sortable from 'sortablejs';
|
||||||
import { deep_copy } from 'utilities/object';
|
|
||||||
|
|
||||||
let last_id = 0;
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [settingMixin],
|
mixins: [settingMixin],
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
{{ t('setting.filters.missing', 'This rule of type "{type}" cannot be loaded. It may be from an add-on that is not loaded.', {type: editing && editing.type}) }}
|
{{ t('setting.filters.missing', 'This rule of type "{type}" cannot be loaded. It may be from an add-on that is not loaded.', {type: editing && editing.type}) }}
|
||||||
</div>
|
</div>
|
||||||
<component
|
<component
|
||||||
v-else
|
|
||||||
:is="component"
|
:is="component"
|
||||||
|
v-else
|
||||||
v-model="editing"
|
v-model="editing"
|
||||||
:type="type"
|
:type="type"
|
||||||
:filters="filters"
|
:filters="filters"
|
||||||
|
|
|
@ -213,9 +213,6 @@
|
||||||
|
|
||||||
import HOME_MD from '../home.md';
|
import HOME_MD from '../home.md';
|
||||||
|
|
||||||
import {createElement as e} from 'utilities/dom';
|
|
||||||
import { EXTENSION } from 'utilities/constants';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['item', 'context'],
|
props: ['item', 'context'],
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@
|
||||||
<h1 class="tw-mg-5 ffz-i-zreknarf loading" />
|
<h1 class="tw-mg-5 ffz-i-zreknarf loading" />
|
||||||
</div>
|
</div>
|
||||||
<code v-else-if="typeof raw_data === 'string'">{{ raw_data }}</code>
|
<code v-else-if="typeof raw_data === 'string'">{{ raw_data }}</code>
|
||||||
<code v-else v-html="highlightJson(raw_data, true)"></code>
|
<code v-else v-html="highlightJson(raw_data, true)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -147,7 +147,7 @@ export default {
|
||||||
let query = this.query.toLowerCase();
|
let query = this.query.toLowerCase();
|
||||||
|
|
||||||
let flags = new Set;
|
let flags = new Set;
|
||||||
query = query.replace(/(?<=^|\s)@(\S+)(?:\s+|$)/g, (match, flag, index) => {
|
query = query.replace(/(?<=^|\s)@(\S+)(?:\s+|$)/g, (match, flag) => {
|
||||||
if ( VALID_FLAGS.includes(flag) ) {
|
if ( VALID_FLAGS.includes(flag) ) {
|
||||||
flags.add(flag);
|
flags.add(flag);
|
||||||
return '';
|
return '';
|
||||||
|
@ -349,4 +349,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -100,8 +100,8 @@
|
||||||
<input
|
<input
|
||||||
id="ffz:editor:name"
|
id="ffz:editor:name"
|
||||||
ref="name"
|
ref="name"
|
||||||
:disabled="isEphemeral"
|
|
||||||
v-model="name"
|
v-model="name"
|
||||||
|
:disabled="isEphemeral"
|
||||||
class="tw-full-width tw-border-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 ffz-input"
|
class="tw-full-width tw-border-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 ffz-input"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
@ -114,8 +114,8 @@
|
||||||
<textarea
|
<textarea
|
||||||
id="ffz:editor:description"
|
id="ffz:editor:description"
|
||||||
ref="desc"
|
ref="desc"
|
||||||
:disabled="isEphemeral"
|
|
||||||
v-model="desc"
|
v-model="desc"
|
||||||
|
:disabled="isEphemeral"
|
||||||
class="tw-full-width tw-border-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 ffz-input"
|
class="tw-full-width tw-border-radius-medium tw-font-size-6 tw-pd-x-1 tw-pd-y-05 ffz-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -129,8 +129,8 @@
|
||||||
<key-picker
|
<key-picker
|
||||||
id="ffz:editor:hotkey"
|
id="ffz:editor:hotkey"
|
||||||
ref="hotkey"
|
ref="hotkey"
|
||||||
:disabled="isEphemeral"
|
|
||||||
v-model="hotkey"
|
v-model="hotkey"
|
||||||
|
:disabled="isEphemeral"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -541,7 +541,7 @@ export default {
|
||||||
prof.update({
|
prof.update({
|
||||||
i18n_key: undefined,
|
i18n_key: undefined,
|
||||||
desc_i18n_key: undefined,
|
desc_i18n_key: undefined,
|
||||||
description: `${prof.description ? prof.description + '\n' : ''}${this.t('setting.backup-restore.imported-at', 'Imported at {now,datetime}.', {now: new Date})}`
|
description: `${prof.description ? `${prof.description }\n` : ''}${this.t('setting.backup-restore.imported-at', 'Imported at {now,datetime}.', {now: new Date})}`
|
||||||
});
|
});
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
|
@ -132,7 +132,7 @@ export default {
|
||||||
if (!scroller || ! window.ffzSimplebar || scroller.SimpleBar)
|
if (!scroller || ! window.ffzSimplebar || scroller.SimpleBar)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new ffzSimplebar(scroller, ffzSimplebar.getElOptions(scroller));
|
new window.ffzSimplebar(scroller, window.ffzSimplebar.getElOptions(scroller));
|
||||||
},
|
},
|
||||||
|
|
||||||
openConfigure() {
|
openConfigure() {
|
||||||
|
@ -268,4 +268,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { maybe_call } from 'utilities/object';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
'chat-rich': async () => {
|
'chat-rich': async () => {
|
||||||
|
|
|
@ -58,7 +58,6 @@
|
||||||
{{ t('setting.filter.add-default-tip', 'Add all of the default values to this profile.') }}
|
{{ t('setting.filter.add-default-tip', 'Add all of the default values to this profile.') }}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<filter-editor
|
<filter-editor
|
||||||
|
@ -68,7 +67,6 @@
|
||||||
:preview="preview"
|
:preview="preview"
|
||||||
@input="onInput"
|
@input="onInput"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -42,12 +42,16 @@
|
||||||
<div v-if="page == 'versions'">
|
<div v-if="page == 'versions'">
|
||||||
<table>
|
<table>
|
||||||
<thead class="tw-border-b tw-pd-b-05 tw-mg-b-05 tw-strong">
|
<thead class="tw-border-b tw-pd-b-05 tw-mg-b-05 tw-strong">
|
||||||
<th class="tw-pd-r-1">{{ t('socket.info.version', 'Version') }}</th>
|
<th class="tw-pd-r-1">
|
||||||
|
{{ t('socket.info.version', 'Version') }}
|
||||||
|
</th>
|
||||||
<th>{{ t('socket.info.count', 'Count') }}</th>
|
<th>{{ t('socket.info.count', 'Count') }}</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="entry in version_list" :key="entry[0]">
|
<tr v-for="entry in version_list" :key="entry[0]">
|
||||||
<td class="tw-pd-r-1">{{ entry[0] }}</td>
|
<td class="tw-pd-r-1">
|
||||||
|
{{ entry[0] }}
|
||||||
|
</td>
|
||||||
<td>{{ tNumber(entry[1]) }}</td>
|
<td>{{ tNumber(entry[1]) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -56,12 +60,16 @@
|
||||||
<div v-if="page == 'commands'">
|
<div v-if="page == 'commands'">
|
||||||
<table>
|
<table>
|
||||||
<thead class="tw-border-b tw-pd-b-05 tw-mg-b-05 tw-strong">
|
<thead class="tw-border-b tw-pd-b-05 tw-mg-b-05 tw-strong">
|
||||||
<th class="tw-pd-r-1">{{ t('socket.info.command', 'Command') }}</th>
|
<th class="tw-pd-r-1">
|
||||||
|
{{ t('socket.info.command', 'Command') }}
|
||||||
|
</th>
|
||||||
<th>{{ t('socket.info.count', 'Count') }}</th>
|
<th>{{ t('socket.info.count', 'Count') }}</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="entry in command_list" :key="entry[0]">
|
<tr v-for="entry in command_list" :key="entry[0]">
|
||||||
<td class="tw-pd-r-1">{{ entry[0] }}</td>
|
<td class="tw-pd-r-1">
|
||||||
|
{{ entry[0] }}
|
||||||
|
</td>
|
||||||
<td>{{ tNumber(entry[1]) }}</td>
|
<td>{{ tNumber(entry[1]) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -59,7 +59,6 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import SettingMixin from '../setting-mixin';
|
import SettingMixin from '../setting-mixin';
|
||||||
import {deep_copy} from 'utilities/object';
|
|
||||||
|
|
||||||
let last_id = 0;
|
let last_id = 0;
|
||||||
|
|
||||||
|
@ -114,7 +113,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleLink(i) {
|
handleLink(i) { // eslint-disable-line no-unused-vars
|
||||||
//this.router.navigate('dir-game-index', {gameName: i});
|
//this.router.navigate('dir-game-index', {gameName: i});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -131,4 +130,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<button
|
<button
|
||||||
@click="accept"
|
|
||||||
class="tw-button tw-mg-b-05"
|
class="tw-button tw-mg-b-05"
|
||||||
|
@click="accept"
|
||||||
>
|
>
|
||||||
<span class="tw-button__text">
|
<span class="tw-button__text">
|
||||||
{{ acceptText }}
|
{{ acceptText }}
|
||||||
|
@ -16,8 +16,8 @@
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="! declined"
|
v-if="! declined"
|
||||||
@click="reject"
|
|
||||||
class="tw-button tw-button--text tw-block"
|
class="tw-button tw-button--text tw-block"
|
||||||
|
@click="reject"
|
||||||
>
|
>
|
||||||
<span class="tw-button__text">
|
<span class="tw-button__text">
|
||||||
{{ t('tooltip.decline-tos', 'I do not accept.') }}
|
{{ t('tooltip.decline-tos', 'I do not accept.') }}
|
||||||
|
@ -33,7 +33,6 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import ProviderMixin from '../provider-mixin';
|
import ProviderMixin from '../provider-mixin';
|
||||||
import { deep_copy } from 'utilities/object';
|
|
||||||
|
|
||||||
let last_id = 0;
|
let last_id = 0;
|
||||||
|
|
||||||
|
|
|
@ -1186,7 +1186,9 @@ export default class MainMenu extends Module {
|
||||||
key = params?.get('ffz-settings');
|
key = params?.get('ffz-settings');
|
||||||
current = key && settings.keys[key];
|
current = key && settings.keys[key];
|
||||||
if ( ! current )
|
if ( ! current )
|
||||||
restored = false;
|
restored = false; // eslint-disable-line no-unused-vars
|
||||||
|
// TODO: `restored` isn't used after this, but we go through
|
||||||
|
// a lot of effort to set it; do we need to?
|
||||||
}
|
}
|
||||||
if ( ! current )
|
if ( ! current )
|
||||||
current = this.has_update ?
|
current = this.has_update ?
|
||||||
|
|
|
@ -30,11 +30,15 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ffz--i18n-sub-entry tw-mg-l-05 tw-flex-grow-1">
|
<div class="ffz--i18n-sub-entry tw-mg-l-05 tw-flex-grow-1">
|
||||||
<div v-if="error && ! open">
|
<div v-if="error && ! open">
|
||||||
<div class="tw-strong">{{ t('i18n.ui.error', 'Error') }}</div>
|
<div class="tw-strong">
|
||||||
|
{{ t('i18n.ui.error', 'Error') }}
|
||||||
|
</div>
|
||||||
<code class="tw-font-size-7 tw-c-text-alt-2">{{ error }}</code>
|
<code class="tw-font-size-7 tw-c-text-alt-2">{{ error }}</code>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="source">
|
<div v-if="source">
|
||||||
<div class="tw-strong">{{ t('i18n.ui.source', 'Source') }}</div>
|
<div class="tw-strong">
|
||||||
|
{{ t('i18n.ui.source', 'Source') }}
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="(line, idx) in source"
|
v-for="(line, idx) in source"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
|
@ -50,7 +54,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="context_str && ! open">
|
<div v-if="context_str && ! open">
|
||||||
<div class="tw-strong">{{ t('i18n.ui.context', 'Context') }}</div>
|
<div class="tw-strong">
|
||||||
|
{{ t('i18n.ui.context', 'Context') }}
|
||||||
|
</div>
|
||||||
<code class="tw-font-size-7 tw-c-text-alt-2">{{ context_str }}</code>
|
<code class="tw-font-size-7 tw-c-text-alt-2">{{ context_str }}</code>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -196,7 +202,7 @@ export default {
|
||||||
out = [];
|
out = [];
|
||||||
|
|
||||||
for(const line of lines) {
|
for(const line of lines) {
|
||||||
const match = /^(?:(.*?) \()?(\/[^:\)]+):(\d+):(\d+)\)?$/.exec(line);
|
const match = /^(?:(.*?) \()?(\/[^:)]+):(\d+):(\d+)\)?$/.exec(line);
|
||||||
if ( match )
|
if ( match )
|
||||||
out.push([
|
out.push([
|
||||||
match[1] || '???',
|
match[1] || '???',
|
||||||
|
@ -328,4 +334,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
class="ffz-dialog tw-elevation-3 tw-c-background-alt tw-c-text-base tw-border tw-flex tw-flex-nowrap tw-flex-column"
|
class="ffz-dialog tw-elevation-3 tw-c-background-alt tw-c-text-base tw-border tw-flex tw-flex-nowrap tw-flex-column"
|
||||||
>
|
>
|
||||||
<header class="tw-c-background-base tw-full-width tw-align-items-center tw-flex tw-flex-nowrap" @dblclick="resize">
|
<header class="tw-c-background-base tw-full-width tw-align-items-center tw-flex tw-flex-nowrap" @dblclick="resize">
|
||||||
<h3 class="ffz-i-zreknarf ffz-i-pd-1">{{ t('i18n.ui.title', 'Translation Tester') }}</h3>
|
<h3 class="ffz-i-zreknarf ffz-i-pd-1">
|
||||||
|
{{ t('i18n.ui.title', 'Translation Tester') }}
|
||||||
|
</h3>
|
||||||
<div class="tw-flex-grow-1 tw-pd-x-2">
|
<div class="tw-flex-grow-1 tw-pd-x-2">
|
||||||
<div class="tw-search-input">
|
<div class="tw-search-input">
|
||||||
<label for="ffz-main-menu.search" class="tw-hide-accessible">{{ t('i18n.ui.search', 'Search Strings') }}</label>
|
<label for="ffz-main-menu.search" class="tw-hide-accessible">{{ t('i18n.ui.search', 'Search Strings') }}</label>
|
||||||
|
@ -230,7 +232,7 @@ import displace from 'displacejs';
|
||||||
import Parser from '@ffz/icu-msgparser';
|
import Parser from '@ffz/icu-msgparser';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
|
|
||||||
import { deep_equals, deep_copy, sleep } from 'utilities/object';
|
import { deep_equals, deep_copy } from 'utilities/object';
|
||||||
|
|
||||||
const parser = new Parser();
|
const parser = new Parser();
|
||||||
const PER_PAGE = 20;
|
const PER_PAGE = 20;
|
||||||
|
@ -549,4 +551,4 @@ export default {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
:channel="channel"
|
:channel="channel"
|
||||||
:user="user"
|
:user="user"
|
||||||
:self="self"
|
:self="self"
|
||||||
:getFFZ="getFFZ"
|
:get-f-f-z="getFFZ"
|
||||||
@close="close"
|
@close="close"
|
||||||
/>
|
/>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div />
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* global FrankerFaceZ: false */
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Raven Logging
|
// Raven Logging
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
|
@ -42,10 +42,6 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
|
||||||
this.detectMonitors();
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
selected() {
|
selected() {
|
||||||
if ( ! this.ready || ! this.selected )
|
if ( ! this.ready || ! this.selected )
|
||||||
|
@ -62,6 +58,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.detectMonitors();
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async detectMonitors() {
|
async detectMonitors() {
|
||||||
let data;
|
let data;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import Module, { GenericModule } from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
|
||||||
let last_site = 0;
|
let last_site = 0;
|
||||||
let last_call = 0;
|
let last_call = 0;
|
||||||
|
@ -42,7 +42,7 @@ export default class BaseSite extends Module {
|
||||||
if ( this._reactDom )
|
if ( this._reactDom )
|
||||||
return this._reactDom;
|
return this._reactDom;
|
||||||
|
|
||||||
let reactDom = this.resolve('site.web_munch')?.getModule?.('react-dom');
|
const reactDom = this.resolve('site.web_munch')?.getModule?.('react-dom');
|
||||||
if ( reactDom?.createPortal )
|
if ( reactDom?.createPortal )
|
||||||
return this._reactDom = reactDom;
|
return this._reactDom = reactDom;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import {createElement} from 'utilities/dom';
|
|
||||||
import {Color} from 'utilities/color';
|
import {Color} from 'utilities/color';
|
||||||
|
|
||||||
//import THEME_CSS from 'site/styles/theme.scss';
|
//import THEME_CSS from 'site/styles/theme.scss';
|
||||||
|
@ -412,7 +411,7 @@ export default class ThemeEngine extends Module {
|
||||||
this.css_tweaks.delete('accent-normal');
|
this.css_tweaks.delete('accent-normal');
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleNormalizer(enable) { // eslint-disable-line class-methods-use-this
|
toggleNormalizer(enable) { // eslint-disable-line class-methods-use-this, no-unused-vars
|
||||||
// Intentionally disabled~
|
// Intentionally disabled~
|
||||||
/*if ( ! this._normalizer ) {
|
/*if ( ! this._normalizer ) {
|
||||||
if ( ! enable )
|
if ( ! enable )
|
||||||
|
@ -461,4 +460,4 @@ export default class ThemeEngine extends Module {
|
||||||
this.updateCSS();
|
this.updateCSS();
|
||||||
this.updateFont();
|
this.updateFont();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -644,7 +644,7 @@ export default class Metadata extends Module {
|
||||||
if ( order != null )
|
if ( order != null )
|
||||||
el.style.order = order;
|
el.style.order = order;
|
||||||
|
|
||||||
let subcontainer = container;
|
const subcontainer = container;
|
||||||
|
|
||||||
/*if ( button )
|
/*if ( button )
|
||||||
subcontainer = container.querySelector('.tw-flex:last-child') || container;
|
subcontainer = container.querySelector('.tw-flex:last-child') || container;
|
||||||
|
|
|
@ -633,7 +633,7 @@ export default class PlayerBase extends Module {
|
||||||
default: false,
|
default: false,
|
||||||
ui: {
|
ui: {
|
||||||
path: 'Player > General >> Playback',
|
path: 'Player > General >> Playback',
|
||||||
title: "Pause/Unpause the player by clicking.",
|
title: 'Pause/Unpause the player by clicking.',
|
||||||
component: 'setting-check-box'
|
component: 'setting-check-box'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1418,7 +1418,6 @@ export default class PlayerBase extends Module {
|
||||||
else {
|
else {
|
||||||
input = cont.querySelector('input');
|
input = cont.querySelector('input');
|
||||||
fill = cont.querySelector('.ffz--gain-value');
|
fill = cont.querySelector('.ffz--gain-value');
|
||||||
tipcont = cont.querySelector('.ffz-il-tooltip');
|
|
||||||
tip = cont.querySelector('.ffz-il-tooltip .ffz--p-tip');
|
tip = cont.querySelector('.ffz-il-tooltip .ffz--p-tip');
|
||||||
extra = cont.querySelector('.ffz-il-tooltip .ffz--p-value');
|
extra = cont.querySelector('.ffz-il-tooltip .ffz--p-value');
|
||||||
}
|
}
|
||||||
|
@ -1550,7 +1549,7 @@ export default class PlayerBase extends Module {
|
||||||
this.replaceVideoElement(player, video);
|
this.replaceVideoElement(player, video);
|
||||||
}
|
}
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
t.log.error('Error while handling player load.', err);
|
this.log.error('Error while handling player load.', err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return player._ffz_load(...args);
|
return player._ffz_load(...args);
|
||||||
|
@ -1769,7 +1768,7 @@ export default class PlayerBase extends Module {
|
||||||
try {
|
try {
|
||||||
ctx.addEventListener('statechange', evt);
|
ctx.addEventListener('statechange', evt);
|
||||||
ctx.resume();
|
ctx.resume();
|
||||||
} catch(err) { }
|
} catch(err) { null }
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2058,7 +2057,7 @@ export default class PlayerBase extends Module {
|
||||||
|
|
||||||
if ( ! cont ) {
|
if ( ! cont ) {
|
||||||
// We need the native clip button, so we can dispatch a click.
|
// We need the native clip button, so we can dispatch a click.
|
||||||
const on_click = e => {
|
const on_click = () => {
|
||||||
const native = getNativeClipButton(container);
|
const native = getNativeClipButton(container);
|
||||||
if (native)
|
if (native)
|
||||||
native.click();
|
native.click();
|
||||||
|
@ -2188,7 +2187,8 @@ export default class PlayerBase extends Module {
|
||||||
addErrorResetButton(inst, tries = 0) {
|
addErrorResetButton(inst, tries = 0) {
|
||||||
const outer = inst.props.containerRef || this.fine.getChildNode(inst),
|
const outer = inst.props.containerRef || this.fine.getChildNode(inst),
|
||||||
container = outer && outer.querySelector('.content-overlay-gate'),
|
container = outer && outer.querySelector('.content-overlay-gate'),
|
||||||
has_reset = this.settings.get('player.button.reset');
|
has_reset = this.settings.get('player.button.reset'),
|
||||||
|
t = this;
|
||||||
|
|
||||||
if ( ! container ) {
|
if ( ! container ) {
|
||||||
if ( ! has_reset )
|
if ( ! has_reset )
|
||||||
|
@ -2384,7 +2384,7 @@ export default class PlayerBase extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getUptime(inst) {
|
getUptime() {
|
||||||
// TODO: Support multiple instances.
|
// TODO: Support multiple instances.
|
||||||
const source = this.getData(),
|
const source = this.getData(),
|
||||||
user = source?.props?.data?.user;
|
user = source?.props?.data?.user;
|
||||||
|
|
|
@ -521,7 +521,7 @@ export default class Channel extends Module {
|
||||||
// is actually a static string.
|
// is actually a static string.
|
||||||
if ( typeof c === 'string' && /^[0-9,.]+$/.test(c) ) {
|
if ( typeof c === 'string' && /^[0-9,.]+$/.test(c) ) {
|
||||||
try {
|
try {
|
||||||
const val = parseInt(c.replace(/[\.,]+/, ''), 10);
|
const val = parseInt(c.replace(/[.,]+/, ''), 10);
|
||||||
if ( ! isNaN(val) && isFinite(val) && val > 0 )
|
if ( ! isNaN(val) && isFinite(val) && val > 0 )
|
||||||
return val;
|
return val;
|
||||||
} catch(err) { /* no-op */ }
|
} catch(err) { /* no-op */ }
|
||||||
|
|
|
@ -462,9 +462,9 @@ export default class EmoteMenu extends Module {
|
||||||
this._ffz_no_scan = false;
|
this._ffz_no_scan = false;
|
||||||
|
|
||||||
if ( ! this.props ||
|
if ( ! this.props ||
|
||||||
this.props.emotePickerSource === 'bits-rewards' ||
|
this.props.emotePickerSource === 'bits-rewards' ||
|
||||||
! has(this.props, 'channelID') ||
|
! has(this.props, 'channelID') ||
|
||||||
! t.chat.context.get('chat.emote-menu.enabled')
|
! t.chat.context.get('chat.emote-menu.enabled')
|
||||||
) {
|
) {
|
||||||
return old_render.call(this);
|
return old_render.call(this);
|
||||||
}
|
}
|
||||||
|
@ -980,8 +980,8 @@ export default class EmoteMenu extends Module {
|
||||||
if ( ! data.all_locked || ! data.locks )
|
if ( ! data.all_locked || ! data.locks )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
let lock = data.locks[this.state.unlocked],
|
let lock = data.locks[this.state.unlocked];
|
||||||
locks = Object.values(data.locks).filter(x => x.id !== 'cheer'),
|
const locks = Object.values(data.locks).filter(x => x.id !== 'cheer'),
|
||||||
has_ffz = locks.filter(x => x.is_ffz).length > 0;
|
has_ffz = locks.filter(x => x.is_ffz).length > 0;
|
||||||
|
|
||||||
if ( ! lock && data.locks.length === 1 )
|
if ( ! lock && data.locks.length === 1 )
|
||||||
|
@ -1792,11 +1792,11 @@ export default class EmoteMenu extends Module {
|
||||||
const state = Object.assign({}, old_state),
|
const state = Object.assign({}, old_state),
|
||||||
|
|
||||||
data = state.set_data || {},
|
data = state.set_data || {},
|
||||||
modifiers = state.emote_modifiers = {},
|
|
||||||
channel = state.channel_sets = [],
|
channel = state.channel_sets = [],
|
||||||
all = state.all_sets = [],
|
all = state.all_sets = [],
|
||||||
effects = state.effect_sets = [],
|
effects = state.effect_sets = [],
|
||||||
favorites = state.favorites = [];
|
favorites = state.favorites = [];
|
||||||
|
state.emote_modifiers = {};
|
||||||
|
|
||||||
// If we're still loading, don't set any data.
|
// If we're still loading, don't set any data.
|
||||||
if ( props.loading || props.error || state.loading )
|
if ( props.loading || props.error || state.loading )
|
||||||
|
@ -2344,8 +2344,8 @@ export default class EmoteMenu extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
let wants_resub_info = false,
|
let wants_resub_info = false,
|
||||||
wants_plan_info = false,
|
|
||||||
has_new_effects = false;
|
has_new_effects = false;
|
||||||
|
const wants_plan_info = false;
|
||||||
|
|
||||||
const unlocked_effects = [...t.settings.provider.get('unlocked-effects', [])];
|
const unlocked_effects = [...t.settings.provider.get('unlocked-effects', [])];
|
||||||
|
|
||||||
|
@ -2395,7 +2395,7 @@ export default class EmoteMenu extends Module {
|
||||||
section.emotes.sort(sort_emotes);
|
section.emotes.sort(sort_emotes);
|
||||||
|
|
||||||
if ( use_effect_tab && ! effects.includes(section) && section.has_effects ) {
|
if ( use_effect_tab && ! effects.includes(section) && section.has_effects ) {
|
||||||
has_new_effects = this.checkNewEffects(section.emotes, unlocked_effects) || has_new_effects;
|
has_new_effects = this.constructor.checkNewEffects(section.emotes, unlocked_effects) || has_new_effects;
|
||||||
effects.push(section);
|
effects.push(section);
|
||||||
} else if ( ! all.includes(section) )
|
} else if ( ! all.includes(section) )
|
||||||
all.push(section);
|
all.push(section);
|
||||||
|
@ -2414,7 +2414,7 @@ export default class EmoteMenu extends Module {
|
||||||
section.emotes.sort(sort_emotes);
|
section.emotes.sort(sort_emotes);
|
||||||
|
|
||||||
if ( use_effect_tab && ! effects.includes(section) && section.has_effects ) {
|
if ( use_effect_tab && ! effects.includes(section) && section.has_effects ) {
|
||||||
has_new_effects = this.checkNewEffects(section.emotes, unlocked_effects) || has_new_effects;
|
has_new_effects = this.constructor.checkNewEffects(section.emotes, unlocked_effects) || has_new_effects;
|
||||||
effects.push(section);
|
effects.push(section);
|
||||||
|
|
||||||
} else if ( ! all.includes(section) )
|
} else if ( ! all.includes(section) )
|
||||||
|
@ -2454,7 +2454,7 @@ export default class EmoteMenu extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
checkNewEffects(emotes, unlocked) {
|
static checkNewEffects(emotes, unlocked) {
|
||||||
let added = false;
|
let added = false;
|
||||||
for(const emote of emotes) {
|
for(const emote of emotes) {
|
||||||
if ( emote && ! emote.locked && emote.id && emote.provider === 'ffz' && ! unlocked.includes(emote.id) ) {
|
if ( emote && ! emote.locked && emote.id && emote.provider === 'ffz' && ! unlocked.includes(emote.id) ) {
|
||||||
|
@ -2491,8 +2491,8 @@ export default class EmoteMenu extends Module {
|
||||||
|
|
||||||
title = (provider === 'ffz-main' || emote_set.title_is_channel)
|
title = (provider === 'ffz-main' || emote_set.title_is_channel)
|
||||||
? source_name
|
? source_name
|
||||||
? t.i18n.t('emote-menu.source-set', '{channel}\'s Emotes', {channel: source_name})
|
? t.i18n.t('emote-menu.source-set', '{channel}\'s Emotes', {channel: source_name})
|
||||||
: t.i18n.t('emote-menu.main-set', 'Channel Emotes')
|
: t.i18n.t('emote-menu.main-set', 'Channel Emotes')
|
||||||
: (emote_set.title || t.i18n.t('emote-menu.unknown-set', `Set #{set_id}`, {set_id: emote_set.id}));
|
: (emote_set.title || t.i18n.t('emote-menu.unknown-set', `Set #{set_id}`, {set_id: emote_set.id}));
|
||||||
|
|
||||||
let sort_key = pdata && pdata.sort_key || emote_set.sort;
|
let sort_key = pdata && pdata.sort_key || emote_set.sort;
|
||||||
|
@ -2572,7 +2572,7 @@ export default class EmoteMenu extends Module {
|
||||||
effect_prefix: emote.modifier ? emote.modifier_prefix : false,
|
effect_prefix: emote.modifier ? emote.modifier_prefix : false,
|
||||||
name: emote.name,
|
name: emote.name,
|
||||||
favorite: is_fav,
|
favorite: is_fav,
|
||||||
locked: locked,
|
locked,
|
||||||
hidden: known_hidden.includes(emote.id),
|
hidden: known_hidden.includes(emote.id),
|
||||||
height: emote.height,
|
height: emote.height,
|
||||||
width: emote.width
|
width: emote.width
|
||||||
|
@ -2696,7 +2696,7 @@ export default class EmoteMenu extends Module {
|
||||||
if ( ! loading )
|
if ( ! loading )
|
||||||
this.loadedOnce = true;
|
this.loadedOnce = true;
|
||||||
|
|
||||||
let tab, sets, is_emoji, is_favs, is_effect;
|
let tab, sets, is_emoji, is_favs;
|
||||||
|
|
||||||
if ( no_tabs ) {
|
if ( no_tabs ) {
|
||||||
sets = [
|
sets = [
|
||||||
|
@ -2714,7 +2714,6 @@ export default class EmoteMenu extends Module {
|
||||||
|
|
||||||
is_emoji = tab === 'emoji';
|
is_emoji = tab === 'emoji';
|
||||||
is_favs = tab === 'fav';
|
is_favs = tab === 'fav';
|
||||||
is_effect = tab === 'effect';
|
|
||||||
|
|
||||||
switch(tab) {
|
switch(tab) {
|
||||||
case 'fav':
|
case 'fav':
|
||||||
|
|
|
@ -163,31 +163,31 @@ const INLINE_CALLOUT_TYPES = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const CALLOUT_TYPES = {
|
const CALLOUT_TYPES = {
|
||||||
"AppointedModerator": "appointed-moderator",
|
'AppointedModerator': 'appointed-moderator',
|
||||||
"BitsBadgeTier": "bits-badge-tier",
|
'BitsBadgeTier': 'bits-badge-tier',
|
||||||
"BitsPowerUps": "bits-power-ups",
|
'BitsPowerUps': 'bits-power-ups',
|
||||||
"ClipLiveNudge": "clip-live-nudge",
|
'ClipLiveNudge': 'clip-live-nudge',
|
||||||
"CommunityMoment": "community-moment",
|
'CommunityMoment': 'community-moment',
|
||||||
"CommunityPointsRewards": "community-points-rewards",
|
'CommunityPointsRewards': 'community-points-rewards',
|
||||||
"CosmicAbyss": "cosmic-abyss",
|
'CosmicAbyss': 'cosmic-abyss',
|
||||||
"CreatorAnniversaries": "creator-anniversaries",
|
'CreatorAnniversaries': 'creator-anniversaries',
|
||||||
"Drop": "drop",
|
'Drop': 'drop',
|
||||||
"EarnedSubBadge": "earned-sub-badge",
|
'EarnedSubBadge': 'earned-sub-badge',
|
||||||
"FavoritedGuestCollab": "favorited-guest-collab",
|
'FavoritedGuestCollab': 'favorited-guest-collab',
|
||||||
"GiftBadgeExpiration": "gift-badge-expiration",
|
'GiftBadgeExpiration': 'gift-badge-expiration',
|
||||||
"GiftBadgeRestored": "gift-badge-restored",
|
'GiftBadgeRestored': 'gift-badge-restored',
|
||||||
"GiftBundleUpSell": "gift-bundle-up-sell",
|
'GiftBundleUpSell': 'gift-bundle-up-sell',
|
||||||
"HypeTrainRewards": "hype-train-rewards",
|
'HypeTrainRewards': 'hype-train-rewards',
|
||||||
"LapsedBitsUser": "lapsed-bits-user",
|
'LapsedBitsUser': 'lapsed-bits-user',
|
||||||
"PartnerPlusUpSellNudge": "partner-plus-up-sell-nudge",
|
'PartnerPlusUpSellNudge': 'partner-plus-up-sell-nudge',
|
||||||
"ReplyByKeyboard": "reply-by-keyboard",
|
'ReplyByKeyboard': 'reply-by-keyboard',
|
||||||
"RequestToJoinAccepted": "request-to-join-accepted",
|
'RequestToJoinAccepted': 'request-to-join-accepted',
|
||||||
"STPromo": "st-promo",
|
'STPromo': 'st-promo',
|
||||||
"ShareResub": "share-resub",
|
'ShareResub': 'share-resub',
|
||||||
"SubtemberPromoBits": "subtember-promo-bits",
|
'SubtemberPromoBits': 'subtember-promo-bits',
|
||||||
"ThankSubGifter": "thank-sub-gifter",
|
'ThankSubGifter': 'thank-sub-gifter',
|
||||||
"TurnOffAnimatedEmotes": "turn-off-animated-emotes",
|
'TurnOffAnimatedEmotes': 'turn-off-animated-emotes',
|
||||||
"WalletDrop": "wallet-drop"
|
'WalletDrop': 'wallet-drop'
|
||||||
};
|
};
|
||||||
|
|
||||||
const UNBLOCKABLE_CALLOUTS = [];
|
const UNBLOCKABLE_CALLOUTS = [];
|
||||||
|
@ -628,7 +628,7 @@ export default class ChatHook extends Module {
|
||||||
default: true,
|
default: true,
|
||||||
ui: {
|
ui: {
|
||||||
path: 'Chat > Appearance >> Community',
|
path: 'Chat > Appearance >> Community',
|
||||||
title: 'Allow the \"Chat seems active.\" clip suggestion to be displayed in chat.',
|
title: 'Allow the "Chat seems active." clip suggestion to be displayed in chat.',
|
||||||
component: 'setting-check-box'
|
component: 'setting-check-box'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1372,7 +1372,8 @@ export default class ChatHook extends Module {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('chat:pre-send-message', e => {
|
this.on('chat:pre-send-message', e => {
|
||||||
const msg = e.message,
|
const t = this,
|
||||||
|
msg = e.message,
|
||||||
inst = e._inst;
|
inst = e._inst;
|
||||||
|
|
||||||
if ( ! /^\/reconnect ?/i.test(msg) )
|
if ( ! /^\/reconnect ?/i.test(msg) )
|
||||||
|
@ -1641,7 +1642,7 @@ export default class ChatHook extends Module {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
t.insertChannelPointMessage(msg);
|
t.insertChannelPointMessage(msg);
|
||||||
return;
|
|
||||||
|
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
t.log.error('Error handling reward event:', err);
|
t.log.error('Error handling reward event:', err);
|
||||||
|
@ -1849,7 +1850,7 @@ export default class ChatHook extends Module {
|
||||||
|
|
||||||
let rewardID;
|
let rewardID;
|
||||||
if (isAutomaticReward)
|
if (isAutomaticReward)
|
||||||
rewardID = `${inst.props.channelID}:${data.reward.reward_type}`;
|
rewardID = `${service.props.channelID}:${data.reward.reward_type}`;
|
||||||
else
|
else
|
||||||
rewardID = data.reward.id;
|
rewardID = data.reward.id;
|
||||||
|
|
||||||
|
@ -1910,7 +1911,7 @@ export default class ChatHook extends Module {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ( type === 'megacheer_emote_recipient' &&
|
if ( type === 'megacheer_emote_recipient' &&
|
||||||
! t.chat.context.get('chat.bits.show-rewards')
|
! this.chat.context.get('chat.bits.show-rewards')
|
||||||
)
|
)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -2001,7 +2002,7 @@ export default class ChatHook extends Module {
|
||||||
const event = inst.props?.event?.callout?.contextMenuProps?.event ?? inst.props?.event,
|
const event = inst.props?.event?.callout?.contextMenuProps?.event ?? inst.props?.event,
|
||||||
type = event?.type;
|
type = event?.type;
|
||||||
|
|
||||||
if ( type !== 'drop' || inst._ffz_clicking || ! this.chat.context.get("chat.drops.auto-rewards") )
|
if ( type !== 'drop' || inst._ffz_clicking || ! this.chat.context.get('chat.drops.auto-rewards') )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//console.warn('autoClickDrop', event, inst);
|
//console.warn('autoClickDrop', event, inst);
|
||||||
|
@ -2021,7 +2022,7 @@ export default class ChatHook extends Module {
|
||||||
const event = inst.props?.event?.callout?.contextMenuProps?.event ?? inst.props?.event,
|
const event = inst.props?.event?.callout?.contextMenuProps?.event ?? inst.props?.event,
|
||||||
type = event?.type;
|
type = event?.type;
|
||||||
|
|
||||||
if ( type !== 'drop' || ! this.chat.context.get("chat.drops.auto-rewards") )
|
if ( type !== 'drop' || ! this.chat.context.get('chat.drops.auto-rewards') )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
btn.click();
|
btn.click();
|
||||||
|
@ -3317,7 +3318,7 @@ export default class ChatHook extends Module {
|
||||||
id: out.id,
|
id: out.id,
|
||||||
displayName: out.user.userDisplayName,
|
displayName: out.user.userDisplayName,
|
||||||
login: out.user.userLogin,
|
login: out.user.userLogin,
|
||||||
reward: reward,
|
reward,
|
||||||
message: out,
|
message: out,
|
||||||
userID: out.user.userID,
|
userID: out.user.userID,
|
||||||
animationID: e.animationID,
|
animationID: e.animationID,
|
||||||
|
@ -3662,7 +3663,7 @@ export default class ChatHook extends Module {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
if (bd) {
|
if (bd) {
|
||||||
for(const entry of bd.values()) {
|
for(const entry of bd.values()) {
|
||||||
for(const _ of entry.values()) {
|
for(const _ of entry.values()) { // eslint-disable-line no-unused-vars
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import { findReactFragment } from 'utilities/dom';
|
import { findReactFragment } from 'utilities/dom';
|
||||||
|
|
||||||
import { SourcedSet, getTwitchEmoteSrcSet } from 'utilities/object';
|
import { getTwitchEmoteSrcSet } from 'utilities/object';
|
||||||
import { TWITCH_POINTS_SETS, TWITCH_GLOBAL_SETS, TWITCH_PRIME_SETS, KNOWN_CODES, REPLACEMENTS, REPLACEMENT_BASE, KEYS } from 'utilities/constants';
|
import { TWITCH_POINTS_SETS, TWITCH_GLOBAL_SETS, TWITCH_PRIME_SETS, KNOWN_CODES, REPLACEMENTS, REPLACEMENT_BASE, KEYS } from 'utilities/constants';
|
||||||
|
|
||||||
import Twilight from 'site';
|
import Twilight from 'site';
|
||||||
|
@ -355,7 +355,7 @@ export default class Input extends Module {
|
||||||
this.ChatInput.on('mount', this.overrideChatInput, this);
|
this.ChatInput.on('mount', this.overrideChatInput, this);
|
||||||
|
|
||||||
this.ChatInput.on('mount', this.installPreviewObserver, this);
|
this.ChatInput.on('mount', this.installPreviewObserver, this);
|
||||||
this.ChatInput.on('unmount', this.removePreviewObserver, this);
|
this.ChatInput.on('unmount', this.constructor.removePreviewObserver, this);
|
||||||
|
|
||||||
this.EmoteSuggestions.on('mount', this.overrideEmoteMatcher, this);
|
this.EmoteSuggestions.on('mount', this.overrideEmoteMatcher, this);
|
||||||
this.MentionSuggestions.on('mount', this.overrideMentionMatcher, this);
|
this.MentionSuggestions.on('mount', this.overrideMentionMatcher, this);
|
||||||
|
@ -461,9 +461,12 @@ export default class Input extends Module {
|
||||||
this.updatePreview(inst, target);
|
this.updatePreview(inst, target);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
for(const target of node.querySelectorAll?.('img.chat-line__message--emote')) {
|
const img = node.querySelectorAll?.('img.chat-line__message--emote');
|
||||||
if ( target && (target.dataset.ffzId || target.src.startsWith('https://static-cdn.jtvnw.net/emoticons/v2/__FFZ__')) )
|
if ( img !== undefined ) {
|
||||||
this.updatePreview(inst, target);
|
for(const target of img) {
|
||||||
|
if ( target && (target.dataset.ffzId || target.src.startsWith('https://static-cdn.jtvnw.net/emoticons/v2/__FFZ__')) )
|
||||||
|
this.updatePreview(inst, target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +542,7 @@ export default class Input extends Module {
|
||||||
evt.stopImmediatePropagation();
|
evt.stopImmediatePropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
removePreviewObserver(inst) {
|
static removePreviewObserver(inst) {
|
||||||
if ( inst._ffz_preview_observer ) {
|
if ( inst._ffz_preview_observer ) {
|
||||||
inst._ffz_preview_observer.disconnect();
|
inst._ffz_preview_observer.disconnect();
|
||||||
inst._ffz_preview_observer = null;
|
inst._ffz_preview_observer = null;
|
||||||
|
@ -580,8 +583,8 @@ export default class Input extends Module {
|
||||||
this.props.emotes.splice(idx, 1, data);
|
this.props.emotes.splice(idx, 1, data);
|
||||||
else if ( idx !== -1 && ! data )
|
else if ( idx !== -1 && ! data )
|
||||||
this.props.emotes.splice(idx, 1);
|
this.props.emotes.splice(idx, 1);
|
||||||
else
|
// else
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
// TODO: Somehow update other React state to deal with our
|
// TODO: Somehow update other React state to deal with our
|
||||||
// injected changes. Making a shallow copy of the array
|
// injected changes. Making a shallow copy of the array
|
||||||
|
@ -864,7 +867,7 @@ export default class Input extends Module {
|
||||||
createElement = React?.createElement;
|
createElement = React?.createElement;
|
||||||
|
|
||||||
if ( createElement )
|
if ( createElement )
|
||||||
inst.renderCommandSuggestion = function(cmd, input) {
|
inst.renderCommandSuggestion = function(cmd) {
|
||||||
const args = Array.isArray(cmd?.commandArgs)
|
const args = Array.isArray(cmd?.commandArgs)
|
||||||
? cmd.commandArgs.map(arg => (<div class={`tw-mg-r-05${arg.isRequired ? '' : ' tw-c-text-alt'}`}>[{arg.name}]</div>))
|
? cmd.commandArgs.map(arg => (<div class={`tw-mg-r-05${arg.isRequired ? '' : ' tw-c-text-alt'}`}>[{arg.name}]</div>))
|
||||||
: null;
|
: null;
|
||||||
|
@ -911,8 +914,6 @@ export default class Input extends Module {
|
||||||
if ( ! set || ! set.emotes )
|
if ( ! set || ! set.emotes )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const source = set.source || 'ffz';
|
|
||||||
|
|
||||||
for(const emote of Object.values(set.emotes)) {
|
for(const emote of Object.values(set.emotes)) {
|
||||||
if ( ! emote || ! emote.id || ! emote.name || added_emotes.has(emote.name) )
|
if ( ! emote || ! emote.id || ! emote.name || added_emotes.has(emote.name) )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1184,7 +1185,7 @@ export default class Input extends Module {
|
||||||
for(const emote of emotes) {
|
for(const emote of emotes) {
|
||||||
const match_type = inst.doesEmoteMatchTerm(emote, search);
|
const match_type = inst.doesEmoteMatchTerm(emote, search);
|
||||||
if (match_type < emoteMatchingType)
|
if (match_type < emoteMatchingType)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const element = {
|
const element = {
|
||||||
current: input,
|
current: input,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { has } from 'utilities/object';
|
||||||
import { KEYS, RERENDER_SETTINGS, UPDATE_BADGE_SETTINGS, UPDATE_TOKEN_SETTINGS } from 'utilities/constants';
|
import { KEYS, RERENDER_SETTINGS, UPDATE_BADGE_SETTINGS, UPDATE_TOKEN_SETTINGS } from 'utilities/constants';
|
||||||
import { print_duration } from 'utilities/time';
|
import { print_duration } from 'utilities/time';
|
||||||
|
|
||||||
import { getRewardTitle, getRewardCost, isGiantEmoteReward, doesRewardCostBits, isMessageEffect } from './points';
|
import { getRewardTitle, getRewardCost, isGiantEmoteReward, doesRewardCostBits } from './points';
|
||||||
import awaitMD, {getMD} from 'utilities/markdown';
|
import awaitMD, {getMD} from 'utilities/markdown';
|
||||||
|
|
||||||
const SUB_TIERS = {
|
const SUB_TIERS = {
|
||||||
|
@ -41,9 +41,7 @@ export default class ChatLine extends Module {
|
||||||
this.line_types = {};
|
this.line_types = {};
|
||||||
|
|
||||||
this.line_types.unknown = {
|
this.line_types.unknown = {
|
||||||
renderNotice: (msg, current_user, room, inst, e) => {
|
renderNotice: msg => `Unknown message type: ${msg.ffz_type}`
|
||||||
return `Unknown message type: ${msg.ffz_type}`
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.line_types.notice = {
|
this.line_types.notice = {
|
||||||
|
@ -179,19 +177,17 @@ export default class ChatLine extends Module {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.line_types.cheer = {
|
this.line_types.cheer = {
|
||||||
renderNotice: (msg, current_user, room, inst, e) => {
|
renderNotice: msg => this.i18n.tList(
|
||||||
return this.i18n.tList(
|
'chat.bits-message',
|
||||||
'chat.bits-message',
|
'Cheered {count, plural, one {# Bit} other {# Bits}}',
|
||||||
'Cheered {count, plural, one {# Bit} other {# Bits}}',
|
{
|
||||||
{
|
count: msg.bits || 0
|
||||||
count: msg.bits || 0
|
}
|
||||||
}
|
)
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.line_types.points = {
|
this.line_types.points = {
|
||||||
getClass: (msg) => {
|
getClass: msg => {
|
||||||
const highlight = msg.ffz_reward_highlight && this.chat.context.get('chat.points.allow-highlight') === 2;
|
const highlight = msg.ffz_reward_highlight && this.chat.context.get('chat.points.allow-highlight') === 2;
|
||||||
|
|
||||||
return `ffz--points-line tw-pd-l-1 tw-pd-r-2 ${highlight ? 'ffz-custom-color ffz--points-highlight' : ''}`;
|
return `ffz--points-line tw-pd-l-1 tw-pd-r-2 ${highlight ? 'ffz-custom-color ffz--points-highlight' : ''}`;
|
||||||
|
@ -1099,7 +1095,7 @@ other {# messages were deleted by a moderator.}
|
||||||
hl_position === 1
|
hl_position === 1
|
||||||
? 'ffz-highlight-tags__above'
|
? 'ffz-highlight-tags__above'
|
||||||
: 'tw-mg-r-05'
|
: 'tw-mg-r-05'
|
||||||
}`
|
}`
|
||||||
}, highlight_tags);
|
}, highlight_tags);
|
||||||
else
|
else
|
||||||
highlight_tags = null;
|
highlight_tags = null;
|
||||||
|
@ -1173,7 +1169,7 @@ other {# messages were deleted by a moderator.}
|
||||||
className: 'tw-font-size-8 tw-mg-t-05'
|
className: 'tw-font-size-8 tw-mg-t-05'
|
||||||
}, t.i18n.t('chat.sent-from-source', 'Sent from {source}', {source: source.displayName ?? source.login}))
|
}, t.i18n.t('chat.sent-from-source', 'Sent from {source}', {source: source.displayName ?? source.login}))
|
||||||
: null
|
: null
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
: want_source_tip
|
: want_source_tip
|
||||||
|
|
|
@ -729,7 +729,7 @@ export default class Scroller extends Module {
|
||||||
|
|
||||||
|
|
||||||
cleanMessages(el) {
|
cleanMessages(el) {
|
||||||
const react = ffz.site.fine.getReactInstance(el);
|
const react = window.ffz.site.fine.getReactInstance(el);
|
||||||
|
|
||||||
// Make sure we have the right thing.
|
// Make sure we have the right thing.
|
||||||
if (!react || !Array.isArray(react.child?.memoizedProps))
|
if (!react || !Array.isArray(react.child?.memoizedProps))
|
||||||
|
|
|
@ -671,9 +671,9 @@ export default class Directory extends Module {
|
||||||
|
|
||||||
clearCard(el, for_exp = false) {
|
clearCard(el, for_exp = false) {
|
||||||
this.clearUptime(el);
|
this.clearUptime(el);
|
||||||
this.clearFlags(el);
|
this.constructor.clearFlags(el);
|
||||||
|
|
||||||
const cont = this._getTopRightContainer(el, for_exp);
|
const cont = this.constructor._getTopRightContainer(el, for_exp);
|
||||||
if ( cont )
|
if ( cont )
|
||||||
cont.remove();
|
cont.remove();
|
||||||
|
|
||||||
|
@ -851,16 +851,16 @@ export default class Directory extends Module {
|
||||||
|
|
||||||
updateFlags(el, for_exp = false) {
|
updateFlags(el, for_exp = false) {
|
||||||
if ( ! document.contains(el) )
|
if ( ! document.contains(el) )
|
||||||
return this.clearFlags(el);
|
return this.constructor.clearFlags(el);
|
||||||
|
|
||||||
const setting = this.settings.get('directory.show-flags');
|
const setting = this.settings.get('directory.show-flags');
|
||||||
|
|
||||||
if ( ! setting || ! el._ffz_flags?.length )
|
if ( ! setting || ! el._ffz_flags?.length )
|
||||||
return this.clearFlags(el);
|
return this.constructor.clearFlags(el);
|
||||||
|
|
||||||
const container = this._getTopRightContainer(el, true, for_exp);
|
const container = this.constructor._getTopRightContainer(el, true, for_exp);
|
||||||
if ( ! container )
|
if ( ! container )
|
||||||
return this.clearFlags(el);
|
return this.constructor.clearFlags(el);
|
||||||
|
|
||||||
if ( ! el.ffz_flags_el )
|
if ( ! el.ffz_flags_el )
|
||||||
container.appendChild(el.ffz_flags_el = (<div class="tw-mg-y-05 ffz-flags-element tw-relative ffz-il-tooltip__container">
|
container.appendChild(el.ffz_flags_el = (<div class="tw-mg-y-05 ffz-flags-element tw-relative ffz-il-tooltip__container">
|
||||||
|
@ -873,12 +873,12 @@ export default class Directory extends Module {
|
||||||
else if ( ! el.contains(el.ffz_flags_el) )
|
else if ( ! el.contains(el.ffz_flags_el) )
|
||||||
container.appendChild(el.ffz_flags_el);
|
container.appendChild(el.ffz_flags_el);
|
||||||
|
|
||||||
el.ffz_flags_tt.textContent = this.i18n.t('metadata.flags.tooltip', 'Intended for certain audiences. May contain:')
|
el.ffz_flags_tt.textContent = `${this.i18n.t('metadata.flags.tooltip', 'Intended for certain audiences. May contain:')
|
||||||
+ '\n\n'
|
}\n\n${
|
||||||
+ el._ffz_flags.map(x => x.localizedName).join('\n');
|
el._ffz_flags.map(x => x.localizedName).join('\n')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearFlags(el) {
|
static clearFlags(el) {
|
||||||
if ( el.ffz_flags_el ) {
|
if ( el.ffz_flags_el ) {
|
||||||
el.ffz_flags_el.remove();
|
el.ffz_flags_el.remove();
|
||||||
el.ffz_flags_tt = null;
|
el.ffz_flags_tt = null;
|
||||||
|
@ -887,7 +887,7 @@ export default class Directory extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_getTopRightContainer(el, should_create = true, for_exp = false) {
|
static _getTopRightContainer(el, should_create = true, for_exp = false) {
|
||||||
let cont = el._ffz_top_right ?? el.querySelector('.ffz-top-right');
|
let cont = el._ffz_top_right ?? el.querySelector('.ffz-top-right');
|
||||||
if ( cont || ! should_create )
|
if ( cont || ! should_create )
|
||||||
return cont;
|
return cont;
|
||||||
|
@ -916,7 +916,7 @@ export default class Directory extends Module {
|
||||||
return this.clearUptime(el);
|
return this.clearUptime(el);
|
||||||
|
|
||||||
const setting = this.settings.get('directory.uptime'),
|
const setting = this.settings.get('directory.uptime'),
|
||||||
container = this._getTopRightContainer(el, setting > 0, for_exp);
|
container = this.constructor._getTopRightContainer(el, setting > 0, for_exp);
|
||||||
|
|
||||||
//const container = el.querySelector('a[data-a-target="preview-card-image-link"] > div'),
|
//const container = el.querySelector('a[data-a-target="preview-card-image-link"] > div'),
|
||||||
// setting = this.settings.get('directory.uptime');
|
// setting = this.settings.get('directory.uptime');
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { IS_FIREFOX } from 'src/utilities/constants';
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import {debounce, has} from 'utilities/object';
|
import {debounce} from 'utilities/object';
|
||||||
|
|
||||||
const PORTRAIT_ROUTES = ['user', 'video', 'user-video', 'user-clip', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following'];
|
const PORTRAIT_ROUTES = ['user', 'video', 'user-video', 'user-clip', 'user-videos', 'user-clips', 'user-collections', 'user-events', 'user-followers', 'user-following'];
|
||||||
const MINIMAL_ROUTES = ['popout', 'embed-chat', 'dash-chat'];
|
const MINIMAL_ROUTES = ['popout', 'embed-chat', 'dash-chat'];
|
||||||
|
@ -127,7 +127,7 @@ export default class Layout extends Module {
|
||||||
const ratio = size.width / size.height;
|
const ratio = size.width / size.height;
|
||||||
return ratio <= ctx.get('layout.portrait-threshold');
|
return ratio <= ctx.get('layout.portrait-threshold');
|
||||||
},
|
},
|
||||||
changed: () => this.updatePortraitMode()
|
// changed: () => this.updatePortraitMode()
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settings.add('layout.inject-portrait', {
|
this.settings.add('layout.inject-portrait', {
|
||||||
|
@ -184,7 +184,7 @@ export default class Layout extends Module {
|
||||||
// TODO: Calculate this based on the expected player height.
|
// TODO: Calculate this based on the expected player height.
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
changed: () => this.updatePortraitMode()
|
// changed: () => this.updatePortraitMode()
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settings.add('layout.portrait-extra-height', {
|
this.settings.add('layout.portrait-extra-height', {
|
||||||
|
@ -241,7 +241,7 @@ export default class Layout extends Module {
|
||||||
onEnable() {
|
onEnable() {
|
||||||
document.body.classList.toggle('ffz--portrait-invert', this.settings.get('layout.portrait-invert'));
|
document.body.classList.toggle('ffz--portrait-invert', this.settings.get('layout.portrait-invert'));
|
||||||
|
|
||||||
this.on(':update-nav', this.updateNavLinks, this);
|
// this.on(':update-nav', this.updateNavLinks, this);
|
||||||
this.on(':resize', this.handleResize, this);
|
this.on(':resize', this.handleResize, this);
|
||||||
|
|
||||||
this.settings.getChanges('layout.portrait-min-chat', val => this.css_tweaks.toggle('portrait-chat', val));
|
this.settings.getChanges('layout.portrait-min-chat', val => this.css_tweaks.toggle('portrait-chat', val));
|
||||||
|
@ -440,11 +440,11 @@ export default class Layout extends Module {
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
updateNavLinks() {
|
// updateNavLinks() {
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
updatePortraitMode() {
|
// updatePortraitMode() {
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ export default class ModView extends Module {
|
||||||
const root = this.fine.getReactInstance(el);
|
const root = this.fine.getReactInstance(el);
|
||||||
|
|
||||||
let channel = null;
|
let channel = null;
|
||||||
let node = this.fine.searchNode(root, n => {
|
this.fine.searchNode(root, n => {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let state = n.memoizedState;
|
let state = n.memoizedState;
|
||||||
while(state != null && channel == null && i < 50) {
|
while(state != null && channel == null && i < 50) {
|
||||||
|
|
|
@ -202,8 +202,8 @@ export default class Player extends PlayerBase {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.PlayerSource.on('mount', this.checkCarousel, this);
|
// this.PlayerSource.on('mount', this.checkCarousel, this);
|
||||||
this.PlayerSource.on('update', this.checkCarousel, this);
|
// this.PlayerSource.on('update', this.checkCarousel, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeOpenChat() {
|
maybeOpenChat() {
|
||||||
|
@ -220,24 +220,24 @@ export default class Player extends PlayerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
checkCarousel(inst) {
|
// checkCarousel(inst) {
|
||||||
/*if ( this.settings.get('channel.hosting.enable') )
|
// /*if ( this.settings.get('channel.hosting.enable') )
|
||||||
return;
|
// return;
|
||||||
|
//
|
||||||
if ( inst.props?.playerType === 'channel_home_carousel' ) {
|
// if ( inst.props?.playerType === 'channel_home_carousel' ) {
|
||||||
if ( inst.props.content?.hostChannel === inst._ffz_cached_login )
|
// if ( inst.props.content?.hostChannel === inst._ffz_cached_login )
|
||||||
return;
|
// return;
|
||||||
|
//
|
||||||
inst._ffz_cached_login = inst.props.content?.hostChannel;
|
// inst._ffz_cached_login = inst.props.content?.hostChannel;
|
||||||
if ( ! inst._ffz_cached_login )
|
// if ( ! inst._ffz_cached_login )
|
||||||
return;
|
// return;
|
||||||
|
//
|
||||||
const player = inst.props.mediaPlayerInstance,
|
// const player = inst.props.mediaPlayerInstance,
|
||||||
events = inst.props.playerEvents;
|
// events = inst.props.playerEvents;
|
||||||
|
//
|
||||||
this.stopPlayer(player, events, inst);
|
// this.stopPlayer(player, events, inst);
|
||||||
}*/
|
// }*/
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
getData() {
|
getData() {
|
||||||
|
@ -275,18 +275,18 @@ export default class Player extends PlayerBase {
|
||||||
* @memberof Player
|
* @memberof Player
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
repositionPlayer() {
|
// repositionPlayer() {
|
||||||
// TODO: New implementation that works.
|
// // TODO: New implementation that works.
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
updateSquadContext() {
|
// updateSquadContext() {
|
||||||
this.settings.updateContext({
|
// this.settings.updateContext({
|
||||||
squad_bar: this.hasSquadBar
|
// squad_bar: this.hasSquadBar
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
get hasSquadBar() {
|
// get hasSquadBar() {
|
||||||
// TODO: New implementation that works.
|
// // TODO: New implementation that works.
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Video Chat Hooks
|
// Video Chat Hooks
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import {get, has} from 'utilities/object';
|
import {get} from 'utilities/object';
|
||||||
import {print_duration} from 'utilities/time';
|
import {print_duration} from 'utilities/time';
|
||||||
//import {ClickOutside} from 'utilities/dom';
|
//import {ClickOutside} from 'utilities/dom';
|
||||||
import {formatBitsConfig} from '../chat';
|
import {formatBitsConfig} from '../chat';
|
||||||
|
@ -183,23 +183,23 @@ export default class VideoChatHook extends Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
// render() {
|
||||||
//if ( ! t.VideoChatMenu._class )
|
// //if ( ! t.VideoChatMenu._class )
|
||||||
return null;
|
// return null;
|
||||||
|
//
|
||||||
/*return (<div class={`tw-flex-shrink-0 video-chat__message-menu${this.state.force ? ' video-chat__message-menu--force-visible' : ''}`}>
|
// /*return (<div class={`tw-flex-shrink-0 video-chat__message-menu${this.state.force ? ' video-chat__message-menu--force-visible' : ''}`}>
|
||||||
<t.VideoChatMenu._class
|
// <t.VideoChatMenu._class
|
||||||
context={this.props.context}
|
// context={this.props.context}
|
||||||
isCurrentUserModerator={this.props.isCurrentUserModerator}
|
// isCurrentUserModerator={this.props.isCurrentUserModerator}
|
||||||
isExpandedLayout={this.props.isExpandedLayout}
|
// isExpandedLayout={this.props.isExpandedLayout}
|
||||||
onBanUserClick={this.onBanUser}
|
// onBanUserClick={this.onBanUser}
|
||||||
onClose={this.onClose}
|
// onClose={this.onClose}
|
||||||
onDeleteCommentClick={this.onDeleteComment}
|
// onDeleteCommentClick={this.onDeleteComment}
|
||||||
onOpen={this.onOpen}
|
// onOpen={this.onOpen}
|
||||||
onReplyClick={this.props.onReplyClick}
|
// onReplyClick={this.props.onReplyClick}
|
||||||
/>
|
// />
|
||||||
</div>);*/
|
// </div>);*/
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
this.VideoChatLine.ready(cls => {
|
this.VideoChatLine.ready(cls => {
|
||||||
|
|
|
@ -125,14 +125,14 @@ export default class SocketClient extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onEnable() {
|
// onEnable() {
|
||||||
// We don't connect anymore.
|
// We don't connect anymore.
|
||||||
// For now, stop connecting to the sockets for people using the
|
// For now, stop connecting to the sockets for people using the
|
||||||
// API links experiment.
|
// API links experiment.
|
||||||
//if ( this.experiments.getAssignment('api_links') )
|
// if ( this.experiments.getAssignment('api_links') )
|
||||||
// return;
|
// return;
|
||||||
//this.connect();
|
// this.connect();
|
||||||
}
|
// }
|
||||||
onDisable() { this.disconnect() }
|
onDisable() { this.disconnect() }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="tw-relative">
|
<div class="tw-relative">
|
||||||
<div class="tw-absolute tw-align-items-center tw-c-text-alt-2 tw-flex tw-full-height ffz-input__icon tw-justify-content-center tw-left-0 tw-top-0 tw-z-default">
|
<div class="tw-absolute tw-align-items-center tw-c-text-alt-2 tw-flex tw-full-height ffz-input__icon tw-justify-content-center tw-left-0 tw-top-0 tw-z-default">
|
||||||
<figure class="tw-mg-y-05 tw-mg-x-05">
|
<figure class="tw-mg-y-05 tw-mg-x-05">
|
||||||
<img class="ffz-preview-emote" v-if="val.src" :src="val.src" />
|
<img v-if="val.src" class="ffz-preview-emote" :src="val.src">
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
@focus="onFocus"
|
@focus="onFocus"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
@keydown.escape="open = false"
|
@keydown.escape="open = false"
|
||||||
/>
|
>
|
||||||
<button
|
<button
|
||||||
v-if="clearable"
|
v-if="clearable"
|
||||||
class="tw-absolute tw-right-0 tw-top-0 tw-button tw-button--text ffz-il-tooltip__container"
|
class="tw-absolute tw-right-0 tw-top-0 tw-button tw-button--text ffz-il-tooltip__container"
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
>
|
>
|
||||||
<figure :class="`tw-mg-y-05 tw-mg-x-1`">
|
<figure :class="`tw-mg-y-05 tw-mg-x-1`">
|
||||||
<img :src="i.src" />
|
<img :src="i.src">
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -232,7 +232,7 @@ export default {
|
||||||
id: val.id,
|
id: val.id,
|
||||||
name: val.name,
|
name: val.name,
|
||||||
src: val.src
|
src: val.src
|
||||||
},
|
};
|
||||||
this.$emit('input', this.val);
|
this.$emit('input', this.val);
|
||||||
if ( close )
|
if ( close )
|
||||||
this.open = false;
|
this.open = false;
|
||||||
|
@ -256,4 +256,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -33,10 +33,10 @@ export default {
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
const scroller = this.$refs.scroller;
|
const scroller = this.$refs.scroller;
|
||||||
if (!scroller || ! window.ffzSimplebar || scroller.SimpleBar)
|
if (!scroller || !window.ffzSimplebar || scroller.SimpleBar)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new ffzSimplebar(scroller, ffzSimplebar.getElOptions(scroller));
|
new window.ffzSimplebar(scroller, window.ffzSimplebar.getElOptions(scroller));
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -52,4 +52,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -87,7 +87,7 @@ export default {
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
//if ( ! this.context.matches_only )
|
//if ( ! this.context.matches_only )
|
||||||
return this.item.tabs;
|
return this.item.tabs;
|
||||||
|
|
||||||
//return this.item.tabs.filter(tab => this.shouldShow(tab));
|
//return this.item.tabs.filter(tab => this.shouldShow(tab));
|
||||||
},
|
},
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -550,9 +550,9 @@ TOKEN_TYPES.gallery = function(token, createElement, ctx) {
|
||||||
if ( ! Array.isArray(token.items) || ! token.items.length )
|
if ( ! Array.isArray(token.items) || ! token.items.length )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
let first_column = [],
|
const first_column = [],
|
||||||
second_column = [],
|
second_column = [];
|
||||||
first = true,
|
let first = true,
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
for(const item of token.items) {
|
for(const item of token.items) {
|
||||||
|
@ -673,7 +673,7 @@ function header_vue(token, h, ctx) {
|
||||||
background = renderWithCapture(token.background, h, ctx, token.markdown).content;
|
background = renderWithCapture(token.background, h, ctx, token.markdown).content;
|
||||||
}
|
}
|
||||||
|
|
||||||
let subtok = resolveToken(token.sub_logo, ctx);
|
const subtok = resolveToken(token.sub_logo, ctx);
|
||||||
if ( ! token.compact && subtok && canShowImage(subtok, ctx) ) {
|
if ( ! token.compact && subtok && canShowImage(subtok, ctx) ) {
|
||||||
const aspect = subtok.aspect;
|
const aspect = subtok.aspect;
|
||||||
|
|
||||||
|
@ -848,7 +848,7 @@ function header_normal(token, createElement, ctx) {
|
||||||
background = renderWithCapture(token.background, createElement, ctx, token.markdown).content;
|
background = renderWithCapture(token.background, createElement, ctx, token.markdown).content;
|
||||||
}
|
}
|
||||||
|
|
||||||
let subtok = resolveToken(token.sub_logo, ctx);
|
const subtok = resolveToken(token.sub_logo, ctx);
|
||||||
if ( ! token.compact && subtok && canShowImage(subtok, ctx) ) {
|
if ( ! token.compact && subtok && canShowImage(subtok, ctx) ) {
|
||||||
const aspect = subtok.aspect;
|
const aspect = subtok.aspect;
|
||||||
|
|
||||||
|
@ -1124,7 +1124,7 @@ function findMatchingLocale(locale, list) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// What about partials?
|
// What about partials?
|
||||||
let prefixed = `${locale.toLowerCase()}-`;
|
const prefixed = `${locale.toLowerCase()}-`;
|
||||||
for(const item of list) {
|
for(const item of list) {
|
||||||
if ( item.toLowerCase().startsWith(prefixed) )
|
if ( item.toLowerCase().startsWith(prefixed) )
|
||||||
return item;
|
return item;
|
||||||
|
@ -1141,7 +1141,7 @@ TOKEN_TYPES.i18n_select = function(token, createElement, ctx) {
|
||||||
|
|
||||||
// What locale and choices do we have.
|
// What locale and choices do we have.
|
||||||
const choices = token.choices || {};
|
const choices = token.choices || {};
|
||||||
let locale = ctx.i18n?.locale ?? 'en';
|
const locale = ctx.i18n?.locale ?? 'en';
|
||||||
|
|
||||||
// Try to find a valid match, or use the default.
|
// Try to find a valid match, or use the default.
|
||||||
let selected = findMatchingLocale(locale, Object.keys(choices));
|
let selected = findMatchingLocale(locale, Object.keys(choices));
|
||||||
|
@ -1182,7 +1182,7 @@ TOKEN_TYPES.link = function(token, createElement, ctx) {
|
||||||
klass.push(`ffz-link--inherit`);
|
klass.push(`ffz-link--inherit`);
|
||||||
|
|
||||||
if ( ctx.vue ) {
|
if ( ctx.vue ) {
|
||||||
let on = {};
|
const on = {};
|
||||||
if ( ctx.link_click_handler )
|
if ( ctx.link_click_handler )
|
||||||
on.click = ctx.link_click_handler;
|
on.click = ctx.link_click_handler;
|
||||||
|
|
||||||
|
@ -1317,8 +1317,8 @@ TOKEN_TYPES.player = function(token, createElement, ctx) {
|
||||||
const style = {};
|
const style = {};
|
||||||
|
|
||||||
const aspect = token.active_aspect ?? token.aspect;
|
const aspect = token.active_aspect ?? token.aspect;
|
||||||
if ( aspect )
|
if ( aspect )
|
||||||
style.aspectRatio = aspect;
|
style.aspectRatio = aspect;
|
||||||
|
|
||||||
if ( ctx.vue )
|
if ( ctx.vue )
|
||||||
return createElement(token.audio ? 'audio' : 'video', {
|
return createElement(token.audio ? 'audio' : 'video', {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue