Release v2.5.4

This commit is contained in:
2026-08-03 21:20:54 +01:00
parent a5e8ecb21f
commit a45552fed3
22 changed files with 371 additions and 9 deletions
@@ -9,6 +9,29 @@
var methodSelect = form.querySelector('[data-api-source-auth-method]');
var authDetailsSection = form.querySelector('[data-api-source-auth-details-section]');
var panels = Array.prototype.slice.call(form.querySelectorAll('[data-api-source-auth-panel]'));
var bearerTokenInput = form.querySelector('[data-api-source-bearer-token-input]');
var bearerTokenToggle = form.querySelector('[data-api-source-bearer-token-toggle]');
function updateBearerTokenToggle() {
if (!bearerTokenInput || !bearerTokenToggle) {
return;
}
var isVisible = bearerTokenInput.type === 'text';
bearerTokenToggle.setAttribute('aria-pressed', String(isVisible));
bearerTokenToggle.setAttribute('aria-label', isVisible ? 'Hide bearer token' : 'Show bearer token');
bearerTokenToggle.innerHTML = '<i class="bi ' + (isVisible ? 'bi-eye-slash' : 'bi-eye') + '" aria-hidden="true"></i>';
}
function toggleBearerTokenVisibility() {
if (!bearerTokenInput) {
return;
}
bearerTokenInput.type = bearerTokenInput.type === 'password' ? 'text' : 'password';
updateBearerTokenToggle();
bearerTokenInput.focus();
}
function updatePanels() {
var method = String(methodSelect && methodSelect.value || 'none').trim();
@@ -28,5 +51,10 @@
methodSelect.addEventListener('change', updatePanels);
}
if (bearerTokenToggle && bearerTokenInput) {
bearerTokenToggle.addEventListener('click', toggleBearerTokenVisibility);
updateBearerTokenToggle();
}
updatePanels();
}());
+118
View File
@@ -0,0 +1,118 @@
// QR code region helpers for editor previews and defaults.
(function () {
var registry = window.pulseRegionTypes;
var utils = window.pulseRegionUtils || {};
function escapeHtml(value) {
return utils.escapeHtml ? utils.escapeHtml(value) : String(value === undefined || value === null ? '' : value);
}
function buildQrCodeUrl(value) {
var text = String(value && typeof value === 'object' ? (value.value !== undefined ? value.value : value.qr_code) : value || '').trim();
var svg = String(value && typeof value === 'object' && value.qr_svg ? value.qr_svg : '').trim();
if (svg) {
return svg;
}
if (!text || typeof window.qrcode !== 'function') {
return '';
}
try {
var code = window.qrcode(0, 'M');
code.addData(text);
code.make();
svg = code.createSvgTag(4, 1);
return svg || '';
} catch (_error) {
return '';
}
}
function normalizeQrSvg(svg) {
var markup = String(svg || '').trim();
if (!markup || markup.charAt(0) !== '<') {
return markup;
}
return markup.replace(/^<svg\b([^>]*)>/i, function (_match, attrText) {
var attrs = String(attrText || '');
if (!/\bwidth\s*=\s*/i.test(attrs)) {
attrs += ' width="95%"';
}
if (!/\bheight\s*=\s*/i.test(attrs)) {
attrs += ' height="95%"';
}
if (!/\bpreserveAspectRatio\s*=\s*/i.test(attrs)) {
attrs += ' preserveAspectRatio="xMidYMid meet"';
}
if (!/\bstyle\s*=\s*/i.test(attrs)) {
attrs += ' style="display:block;width:95%;height:95%;"';
}
return '<svg' + attrs + '>';
});
}
function renderPreview(region, value) {
var src = buildQrCodeUrl(value);
if (!src) {
return '<div class="slide-preview-placeholder">QR Code</div>';
}
if (String(src || '').trim().charAt(0) === '<') {
return '<div class="slide-preview-qr-code-frame" style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:#fff;overflow:hidden;">' + normalizeQrSvg(src) + '</div>';
}
return '<img class="slide-preview-qr-code" src="' + escapeHtml(src) + '" alt="QR code preview" style="width:100%;height:100%;object-fit:contain;display:block;background:#fff;" />';
}
function renderEditorCard(context) {
var region = context.region;
var current = String(context.current || '');
return '' +
'<div class="card card-outline card-secondary admin-form-card template-field-card mb-3" data-region-id="' + region.id + '">' +
'<div class="card-header template-field-head">' +
'<strong>' + escapeHtml(region.label) + '</strong>' +
'<div class="template-field-actions">' +
'<span class="chip">QR Code</span>' +
'</div>' +
'</div>' +
'<div class="card-body p-3 d-grid gap-2">' +
'<input type="url" name="region_qr_code_' + region.id + '" class="form-control" value="' + escapeHtml(current) + '" placeholder="https://example.com" />' +
'</label>' +
'<div class="muted slide-image-file">The QR code is generated from the URL above.</div>' +
'</div>' +
'</div>';
}
function buildEditorCardContext(context, existingContent) {
var existing = existingContent && context && context.region && existingContent[context.region.region_key] ? existingContent[context.region.region_key] : null;
return {
region: context.region,
current: String(context.current || (existing && (existing.value !== undefined ? existing.value : existing.qr_code)) || ''),
qr_svg: existing && existing.qr_svg ? existing.qr_svg : ''
};
}
function buildPreviewRenderContext(region, card, existingContent) {
var current = existingContent && existingContent[region.region_key] ? existingContent[region.region_key] : {};
var input = card && card.querySelector ? card.querySelector('input[type="url"][name="region_qr_code_' + region.id + '"]') : null;
return {
value: input ? input.value : (current && current.value !== undefined ? current.value : (current && current.qr_code !== undefined ? current.qr_code : '')),
existingContent: existingContent || {}
};
}
registry.register('qr-code', {
label: 'QR Code',
getDefaultRegionSize: function () {
return { width: 240, height: 240 };
},
renderPreview: renderPreview,
renderEditorCard: renderEditorCard,
buildEditorCardContext: buildEditorCardContext,
buildPreviewRenderContext: buildPreviewRenderContext
});
}());
+2
View File
@@ -592,6 +592,8 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
? ' slide-preview-video-region'
: region.region_type === 'webpage'
? ' slide-preview-webpage-region'
: region.region_type === 'qr-code'
? ' slide-preview-qr-code-region'
: region.region_type === 'rtmp'
? ' slide-preview-rtmp-region'
: region.region_type === 'rss'