mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-09 07:40:53 +00:00
4.55.2
* Fixed: Do not set `src` for images on Firefox, since that causes animations to reset when a new image is added to the DOM with the same `src`. For some reason. Thanks, Firefox. * Fixed: The FFZ Control Center, Emote Cards, and Link Cards are now all aware of each other in a limited sense. The most recently interacted-with window will appear on top of the others. * Fixed: Channel page links not having enhanced tool-tip preview support. (Still no link cards when you click them, but it's a start.) * Developer: Made it so the Link Tester in Debugging > Data Sources will properly open link cards, as long as you have link cards enabled. * API Added: Update to the latest FFZ rich tokens format, which has a new `i18n_select` token. This allows, for example, the link preview service to return multiple languages of titles and descriptions for a YouTube video so that your client can pick the best one to display. * Experiment Changed: The "API-Based Link Lookups" experiment now has a third option that uses Cloudflare Workers. It's set very low while I try to gauge how much traffic it would see, and if this is a viable option.
This commit is contained in:
parent
29419eee22
commit
5b65f6b735
19 changed files with 223 additions and 91 deletions
|
@ -8,7 +8,7 @@ import {has} from 'utilities/object';
|
|||
import Markdown from 'markdown-it';
|
||||
import MILA from 'markdown-it-link-attributes';
|
||||
|
||||
export const VERSION = 8;
|
||||
export const VERSION = 9;
|
||||
|
||||
export const TOKEN_TYPES = {};
|
||||
|
||||
|
@ -966,6 +966,53 @@ TOKEN_TYPES.i18n = function(token, createElement, ctx) {
|
|||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Token Type: I18n Select
|
||||
// ============================================================================
|
||||
|
||||
function findMatchingLocale(locale, list) {
|
||||
|
||||
// Is the locale present exactly?
|
||||
for(const item of list) {
|
||||
if ( item.localeCompare(locale, undefined, {sensitivity: 'accent'}) === 0 )
|
||||
return locale;
|
||||
}
|
||||
|
||||
// What about partials?
|
||||
let prefixed = `${locale.toLowerCase()}-`;
|
||||
for(const item of list) {
|
||||
if ( item.toLowerCase().startsWith(prefixed) )
|
||||
return item;
|
||||
}
|
||||
|
||||
// Last resort, do we have a - in the locale?
|
||||
const idx = locale.indexOf('-');
|
||||
if ( idx !== -1 )
|
||||
return findMatchingLocale(locale.slice(0, idx), list);
|
||||
|
||||
}
|
||||
|
||||
TOKEN_TYPES.i18n_select = function(token, createElement, ctx) {
|
||||
|
||||
// What locale and choices do we have.
|
||||
const choices = token.choices || {};
|
||||
let locale = ctx.i18n?.locale ?? 'en';
|
||||
|
||||
// Try to find a valid match, or use the default.
|
||||
let selected = findMatchingLocale(locale, Object.keys(choices));
|
||||
if ( ! selected )
|
||||
selected = token.default;
|
||||
|
||||
// Render it.
|
||||
return renderTokens(
|
||||
choices[selected],
|
||||
createElement,
|
||||
ctx,
|
||||
token.markdown
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Token Type: Link
|
||||
// ============================================================================
|
||||
|
@ -1078,19 +1125,25 @@ TOKEN_TYPES.overlay = function(token, createElement, ctx) {
|
|||
|
||||
function handlePlayerClick(token, id, ctx, event) {
|
||||
//console.log('clicked player', token, id, ctx, event);
|
||||
if ( ctx.togglePlayer ) {
|
||||
ctx.togglePlayer(id);
|
||||
const target = event.currentTarget,
|
||||
is_av = target instanceof HTMLVideoElement || target instanceof HTMLAudioElement;
|
||||
|
||||
if ( is_av || ctx.togglePlayer ) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
const target = event.currentTarget;
|
||||
if ( target instanceof HTMLVideoElement ) {
|
||||
if ( is_av ) {
|
||||
if ( target.paused )
|
||||
target.play();
|
||||
else
|
||||
target.pause();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ctx.togglePlayer )
|
||||
ctx.togglePlayer(id);
|
||||
}
|
||||
|
||||
TOKEN_TYPES.player = function(token, createElement, ctx) {
|
||||
|
@ -1101,6 +1154,9 @@ TOKEN_TYPES.player = function(token, createElement, ctx) {
|
|||
|
||||
const handler = handlePlayerClick.bind(this, token, id, ctx);
|
||||
|
||||
if ( ! active && (token.content || token.iframe) )
|
||||
return render_player_content(id, handler, token, createElement, ctx);
|
||||
|
||||
if ( token.iframe )
|
||||
return render_player_iframe(id, active ?? false, handler, token, createElement, ctx);
|
||||
|
||||
|
@ -1120,7 +1176,7 @@ TOKEN_TYPES.player = function(token, createElement, ctx) {
|
|||
style.aspectRatio = aspect;
|
||||
|
||||
if ( ctx.vue )
|
||||
return createElement('video', {
|
||||
return createElement(token.audio ? 'audio' : 'video', {
|
||||
style,
|
||||
attrs: {
|
||||
autoplay: playing,
|
||||
|
@ -1141,7 +1197,7 @@ TOKEN_TYPES.player = function(token, createElement, ctx) {
|
|||
}
|
||||
})));
|
||||
|
||||
return createElement('video', {
|
||||
return createElement(token.audio ? 'audio' : 'video', {
|
||||
style,
|
||||
muted,
|
||||
autoplay: playing,
|
||||
|
@ -1155,33 +1211,7 @@ TOKEN_TYPES.player = function(token, createElement, ctx) {
|
|||
})));
|
||||
}
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
function render_player_content(id, handler, token, createElement, ctx) {
|
||||
const content = renderTokens(token.content, createElement, ctx, token.markdown),
|
||||
classes = ['ffz--rich-player'],
|
||||
style = {};
|
||||
|
@ -1205,6 +1235,33 @@ function render_player_iframe(id, active, handler, token, createElement, ctx) {
|
|||
}, content);
|
||||
}
|
||||
|
||||
function render_player_iframe(id, active, handler, token, createElement, ctx) {
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Token Type: Style
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue