1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-09 07:40:53 +00:00
* Added: Link Cards. As an option, you can open a preview card when clicking on links in chat. These preview cards function similarly to the existing tool-tip or rich embed options but can provide for enhanced interaction (e.g. an embedded video player), with potential for more in the future.
* Changed: When using a custom theme with a dark background, use lighter border colors.
* Changed: Draw the FFZ Control Center and other dialogs with rounded corners.
* Fixed: Issue when clicking certain global Twitch emotes preventing the emote card from appearing correctly.
* Fixed: Issue with URL/safety data not being loaded correctly from the link service when the overall result was an error.
* Fixed: Issue with link tool-tips still appearing, but with no content, when link tool-tips are disabled.
* Fixed: Issue where (re)subscription notices in chat for multiple-month-at-once subscriptions would not be displayed correctly.
* Fixed: Tool-tips not displaying correctly in chat pop-outs in some circumstances.
* Fixed: Incorrect border styles when the chat is in portrait mode.
* Experiment Added: Set up an MQTT-based PubSub system. Let's see how well this scales.
This commit is contained in:
SirStendec 2023-09-26 17:40:25 -04:00
parent d01f66c6f3
commit 98e5373e9a
36 changed files with 1554 additions and 92 deletions

View file

@ -8,7 +8,7 @@ import {has} from 'utilities/object';
import Markdown from 'markdown-it';
import MILA from 'markdown-it-link-attributes';
export const VERSION = 7;
export const VERSION = 8;
export const TOKEN_TYPES = {};
@ -989,7 +989,11 @@ TOKEN_TYPES.link = function(token, createElement, ctx) {
if ( token.no_color )
klass.push(`ffz-link--inherit`);
if ( ctx.vue )
if ( ctx.vue ) {
let on = {};
if ( ctx.link_click_handler )
on.click = ctx.link_click_handler;
return createElement('a', {
class: klass,
attrs: {
@ -997,15 +1001,18 @@ TOKEN_TYPES.link = function(token, createElement, ctx) {
target: '_blank',
'data-tooltip-type': 'link',
href: token.url
}
},
on
}, content);
}
return createElement('a', {
className: klass.join(' '),
rel: 'noopener noreferrer',
target: '_blank',
'data-tooltip-type': 'link',
href: token.url
href: token.url,
onClick: ctx.link_click_handler
}, content);
}
@ -1065,6 +1072,140 @@ TOKEN_TYPES.overlay = function(token, createElement, ctx) {
}
// ============================================================================
// Token Type: Player
// ============================================================================
function handlePlayerClick(token, id, ctx, event) {
//console.log('clicked player', token, id, ctx, event);
if ( ctx.togglePlayer ) {
ctx.togglePlayer(id);
event.preventDefault();
event.stopPropagation();
}
const target = event.currentTarget;
if ( target instanceof HTMLVideoElement ) {
if ( target.paused )
target.play();
else
target.pause();
}
}
TOKEN_TYPES.player = function(token, createElement, ctx) {
// Make a unique ID for this player, within the context.
const id = ctx.last_player = (ctx.last_player || 0) + 1,
active = ctx.player_state?.[id];
const handler = handlePlayerClick.bind(this, token, id, ctx);
if ( token.iframe )
return render_player_iframe(id, active ?? false, handler, token, createElement, ctx);
if ( ! token.sources )
return null;
const autoplay = token.autoplay ?? false,
loop = token.loop ?? false,
playing = active ?? autoplay,
controls = ! token.silent || ! autoplay;
const muted = token.silent ? true : (active == null && autoplay);
const style = {};
const aspect = token.active_aspect ?? token.aspect;
if ( aspect )
style.aspectRatio = aspect;
if ( ctx.vue )
return createElement('video', {
style,
attrs: {
autoplay: playing,
loop,
controls,
poster: token.poster
},
domProps: {
muted
},
on: {
click: handler
}
}, token.sources.map(source => createElement('source', {
attrs: {
type: source.type,
src: source.src
}
})));
return createElement('video', {
style,
muted,
autoplay: playing,
loop,
poster: token.poster,
controls,
onClick: handler
}, token.sources.map(source => createElement('source', {
type: source.type,
src: source.src
})));
}
function render_player_iframe(id, active, handler, token, createElement, ctx) {
if ( active ) {
const style = {},
attrs = {
src: token.iframe,
frameborder: 0,
allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share',
allowfullscreen: true
};
const aspect = token.active_aspect ?? token.aspect;
if ( aspect )
style.aspectRatio = aspect;
if ( ctx.vue )
return createElement('iframe', {
style,
attrs
});
return createElement('iframe', {
style,
...attrs
});
}
const content = renderTokens(token.content, createElement, ctx, token.markdown),
classes = ['ffz--rich-player'],
style = {};
if ( token.aspect )
style.aspectRatio = token.aspect;
if ( ctx.vue )
return createElement('div', {
class: classes,
style,
on: {
click: handler
}
}, content);
return createElement('div', {
className: classes.join(' '),
onClick: handler,
style
}, content);
}
// ============================================================================
// Token Type: Style
// ============================================================================