1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-29 07:45:33 +00:00
* Added: Previews for rich chat embeds and rich tool-tips to the settings menu.
* Changed: Disabled Smooth Scrolling for now, as no one has been able to get it working correctly after Twitch's changes to how chat scrolling works.
This commit is contained in:
SirStendec 2019-09-12 13:11:08 -04:00
parent 512fe8898d
commit 1a171939ac
15 changed files with 178 additions and 40 deletions

View file

@ -1,7 +1,7 @@
{
"name": "frankerfacez",
"author": "Dan Salvato LLC",
"version": "4.9.5",
"version": "4.9.6",
"description": "FrankerFaceZ is a Twitch enhancement suite.",
"license": "Apache-2.0",
"scripts": {

View file

@ -0,0 +1,3 @@
'use strict';
export default require.context('./components', false, /\.vue$/);

View file

@ -2,34 +2,41 @@
<a :href="url" class="chat-card__link" target="_blank" rel="noreferrer noopener">
<div class="ffz--chat-card tw-elevation-1 tw-mg-t">
<div class="tw-c-background-base tw-flex tw-flex-nowrap tw-pd-05">
<div class="chat-card__preview-img tw-c-background-alt-2 tw-align-items-center tw-flex tw-flex-shrink-0 tw-justify-content-center">
<div class="tw-card-img tw-flex-shrink-0 tw-flex tw-justify-content-center">
<img
v-if="error"
class="chat-card__error-img"
src=""
data-test-selector="chat-card-error"
>
<figure
v-else
class="tw-aspect tw-aspect--16x9 tw-aspect--align-top"
>
<div class="chat-card__preview-img tw-align-items-center tw-c-background-alt-2 tw-flex tw-flex-shrink-0 tw-justify-content-center">
<img
v-if="error"
class="chat-card__error-img"
src=""
>
<div
v-else
class="tw-card-img tw-flex-shrink-0 tw-overflow-hidden"
>
<aspect :ratio="16/9">
<img
v-if="loaded && image"
:src="image"
:alt="title"
class="tw-image"
>
</figure>
</aspect>
</div>
</div>
<div
:class="{'ffz--two-line': desc_2}"
class="tw-overflow-hidden tw-align-items-center tw-flex"
class="ffz--card-text tw-overflow-hidden tw-align-items-center tw-flex"
>
<div class="tw-full-width tw-pd-l-1">
<div class="chat-card__title tw-ellipsis">
<span
v-if="! loaded"
class="tw-font-size-5"
data-test-selector="chat-card-title"
>
{{ t('card.loading', 'Loading...') }}
</span>
<span
v-else
:title="title"
class="tw-font-size-5"
data-test-selector="chat-card-title"
@ -37,7 +44,7 @@
{{ title }}
</span>
</div>
<div class="tw-ellipsis">
<div v-if="loaded" class="tw-ellipsis">
<span
:title="desc_1"
class="tw-c-text-alt-2 tw-font-size-6"
@ -46,7 +53,7 @@
{{ desc_1 }}
</span>
</div>
<div v-if="desc_2" class="tw-ellipsis">
<div v-if="loaded && desc_2" class="tw-ellipsis">
<span
:title="desc_2"
class="tw-c-text-alt-2 tw-font-size-6"

View file

@ -135,7 +135,11 @@ export default class Chat extends Module {
path: 'Chat > Appearance >> Rich Content',
title: 'Display rich content embeds for all links.',
description: '*Streamers: Please be aware that this is a potential vector for NSFW imagery via thumbnails, so be mindful when capturing chat with this enabled.*',
component: 'setting-check-box'
component: 'setting-check-box',
extra: {
component: 'chat-rich-example',
getChat: () => this
}
}
});
@ -672,7 +676,10 @@ export default class Chat extends Module {
sort: -1,
path: 'Chat > Tooltips >> Links',
title: 'Display rich tooltips for links.',
component: 'setting-check-box'
component: 'setting-check-box',
extra: {
component: 'chat-tooltip-example'
}
}
});

View file

@ -41,7 +41,7 @@ export const Links = {
},
tooltip(target, tip) {
if ( ! this.context.get('tooltip.rich-links') )
if ( ! this.context.get('tooltip.rich-links') && ! target.dataset.forceTooltip )
return '';
if ( target.dataset.isMail === 'true' )

View file

@ -0,0 +1,57 @@
<template>
<div>
<div class="tw-c-text-alt tw-mg-b-05">
{{ t('setting.example', 'Example:') }}
</div>
<chat-rich
:data="data"
:url="url"
/>
</div>
</template>
<script>
const VIDEOS = [
'https://www.youtube.com/watch?v=BFSWlDpA6C4'
];
export default {
components: {
'chat-rich': async () => {
const stuff = await import(/* webpackChunkName: "chat" */ 'src/modules/chat/components');
return stuff.default('./chat-rich.vue').default;
}
},
props: ['context', 'item'],
data() {
const url = VIDEOS[Math.floor(Math.random() * VIDEOS.length)],
token = {
type: 'link',
is_mail: false,
url,
text: url
},
chat = this.item.extra.getChat();
let data = null;
if ( chat.__rich_providers ) {
for(const provider of chat.__rich_providers) {
if ( provider.test.call(chat, token, url) ) {
data = provider.process.call(chat, token);
break;
}
}
}
return {
data,
url
}
}
}
</script>

View file

@ -0,0 +1,38 @@
<template>
<div class="tw-c-text-alt-2">
{{ t('setting.tooltip-example', 'For an example, please hover this link:') }}
<a
:href="url"
:data-url="url"
class="ffz-tooltip"
data-tooltip-type="link"
data-force-tooltip="true"
data-is-mail="false"
rel="noopener noreferrer"
target="_blank"
>
{{ url }}
</a>
</div>
</template>
<script>
const VIDEOS = [
'https://www.youtube.com/watch?v=BFSWlDpA6C4'
];
export default {
props: ['context', 'item'],
data() {
const url = VIDEOS[Math.floor(Math.random() * VIDEOS.length)];
return {
url
}
}
}
</script>

View file

@ -44,6 +44,12 @@
>
<markdown :source="t(item.desc_i18n_key || `${item.i18n_key}.description`, item.description, item)" />
</section>
<section
v-if="item.extra"
style="padding-left:2.2rem"
>
<component :is="item.extra.component" :context="context" :item="item" />
</section>
</div>
</template>

View file

@ -41,6 +41,9 @@
>
<markdown :source="t(item.desc_i18n_key || `${item.i18n_key}.description`, item.description, item)" />
</section>
<section v-if="item.extra">
<component :is="item.extra.component" :context="context" :item="item" />
</section>
</div>
</template>

View file

@ -60,6 +60,9 @@
>
<markdown :source="t(item.desc_i18n_key || `${item.i18n_key}.description`, item.description, item)" />
</section>
<section v-if="item.extra">
<component :is="item.extra.component" :context="context" :item="item" />
</section>
</div>
</template>

View file

@ -26,6 +26,9 @@
>
<markdown :source="t(item.desc_i18n_key || `${item.i18n_key}.description`, item.description, item)" />
</section>
<section v-if="item.extra">
<component :is="item.extra.component" :context="context" :item="item" />
</section>
</div>
</template>

View file

@ -10,6 +10,9 @@
>
<markdown :source="t(item.desc_i18n_key || `${item.i18n_key}.description`, item.description, item)" />
</section>
<section v-if="item.extra">
<component :is="item.extra.component" :context="context" :item="item" />
</section>
<div v-for="(i, idx) in data" :key="idx" class="tw-mg-l-1">
<input
:id="item.full_key + idx"

View file

@ -48,6 +48,9 @@
>
<markdown :source="t(item.desc_i18n_key || `${item.i18n_key}.description`, item.description, item)" />
</section>
<section v-if="item.extra">
<component :is="item.extra.component" :context="context" :item="item" />
</section>
</div>
</template>

View file

@ -41,6 +41,9 @@
>
<markdown :source="t(item.desc_i18n_key || `${item.i18n_key}.description`, item.description, item)" />
</section>
<section v-if="item.extra">
<component :is="item.extra.component" :context="context" :item="item" />
</section>
</div>
</template>

View file

@ -36,7 +36,7 @@ export default class Scroller extends Module {
this.settings.add('chat.scroller.freeze', {
default: 0,
ui: {
path: 'Chat > Behavior >> Scrolling @{"description": "Please note that FrankerFaceZ is dependent on Twitch\'s own scrolling code working correctly. There are bugs with Twitch\'s scrolling code that have existed for more than six months. If you are using Firefox, Edge, or other non-Webkit browsers, expect to have issues."}',
path: 'Chat > Behavior >> Scrolling',
title: 'Pause Chat Scrolling',
description: 'Automatically stop chat from scrolling when moving the mouse over it or holding a key.',
component: 'setting-select-box',
@ -87,7 +87,7 @@ export default class Scroller extends Module {
ui: {
path: 'Chat > Behavior >> Scrolling',
title: 'Smooth Scrolling',
description: 'Smoothly slide new chat messages into view. Speed will increase as necessary to keep up with chat.',
description: '**Note:** This setting has been disabled until such time as someone is able to fix major bugs with it.\n\nSmoothly slide new chat messages into view. Speed will increase as necessary to keep up with chat.',
component: 'setting-select-box',
data: [
{value: 0, title: 'Disabled'},
@ -145,8 +145,9 @@ export default class Scroller extends Module {
inst.ffzMaybeUnpause();
});
this.smooth_scroll = this.chat.context.get('chat.scroller.smooth-scroll');
this.smooth_scroll = 0; // this.chat.context.get('chat.scroller.smooth-scroll');
this.chat.context.on('changed:chat.scroller.smooth-scroll', val => {
val = 0;
this.smooth_scroll = val;
for(const inst of this.ChatScroller.instances)
@ -167,15 +168,11 @@ export default class Scroller extends Module {
if ( old_snapshot )
cls.prototype.getSnapshotBeforeUpdate = function() {
let auto_state;
if ( this.state ) {
auto_state = this.state.isAutoScrolling;
this.state.isAutoScrolling = false;
}
const out = old_snapshot.call(this);
if ( this.state )
this.state.isAutoScrolling = auto_state;
this._ffz_snapshot = out;
this._ffz_snapshot = out || (this.lastLine && {
lastLine: this.lastLine,
offsetTop: this.lastLine.offsetTop
}) || null;
return out;
}
@ -265,16 +262,20 @@ export default class Scroller extends Module {
// WIP: Trying to fix the scroll position changing so that we can
// smooth scroll from the previous position.
if ( inst.ffz_smooth_scroll && ! inst._ffz_one_fast_scroll && inst._ffz_snapshot ) {
const adjustment = inst._ffz_snapshot && inst._ffz_snapshot.lastLine ? inst._ffz_snapshot.offsetTop - inst._ffz_snapshot.lastLine.offsetTop : 0;
if ( inst.scroll && inst.scroll.scrollContent && adjustment > 0 )
inst.scroll.scrollContent.scrollTop -= adjustment;
const adjustment = inst._ffz_snapshot && inst._ffz_snapshot.lastLine ? inst._ffz_snapshot.lastLine.offsetTop - inst._ffz_snapshot.offsetTop: 0;
if ( inst.scroll && inst.scroll.scrollContent && adjustment != 0 )
inst.scroll.scrollContent.scrollTop += adjustment;
}
inst._ffz_snapshot = null;
if ( inst.state.isPaused || inst._ffz_scroll_frame )
return;
this._ffz_scroll_frame = requestAnimationFrame(inst.ffz_doScroll);
if ( inst.state.isAutoScrolling && ! inst.state.isPaused ) {
if ( inst.ffz_smooth_scroll && ! inst._ffz_one_fast_scroll )
inst.smoothScrollBottom();
else {
inst._ffz_one_fast_scroll = false;
inst.ffz_oldScroll();
}
}
}
// New Scroll Event Handling
@ -617,7 +618,7 @@ export default class Scroller extends Module {
} else if ( difference > 200 ) {
// we are starting to fall behind, speed it up a bit
step += step * Math.floor(difference / 200);
}
}
const smoothAnimation = () => {
if ( this.state.isPaused || ! this.state.isAutoScrolling )
@ -631,10 +632,11 @@ export default class Scroller extends Module {
// we need to move at least one full pixel for scrollTop to do anything in this delta.
if ( current_step >= 1 ) {
const scroll_top = scroll_content.scrollTop,
next_top = scroll_top + current_step,
target_top = scroll_content.scrollHeight - scroll_content.clientHeight;
old_time = current_time;
if ( scroll_top < target_top ) {
if ( next_top < target_top ) {
scroll_content.scrollTop = scroll_top + current_step;
this._ffz_smooth_animation = requestAnimationFrame(smoothAnimation);