From 4b805656e24e5a1b9c5a79bea99a62801865164f Mon Sep 17 00:00:00 2001 From: Terranom674 Date: Mon, 17 Aug 2026 00:06:30 +0200 Subject: [PATCH] Add share tags and password generator --- template/album_shares_admin.tpl | 95 ++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 14 deletions(-) diff --git a/template/album_shares_admin.tpl b/template/album_shares_admin.tpl index 10445b6..7c76e7b 100644 --- a/template/album_shares_admin.tpl +++ b/template/album_shares_admin.tpl @@ -83,8 +83,16 @@ {/foreach} + + + - +
+ + + + +
@@ -98,7 +106,7 @@

Hinweis

Jede Freigabe erhält einen eigenen, nicht erratbaren Link. Ein Passwort ist optional; ohne Passwort genügt der Link bis zum Widerruf oder Ablaufdatum.

-

Passwörter werden nur als Hash gespeichert. Der Freigabelink bleibt in der Liste unten sichtbar und kann jederzeit kopiert werden.

+

Mit dem Freigabe-Tag kannst du mehrere Freigaben desselben Albums auseinanderhalten. Passwörter werden nach dem Erstellen nur als Hash gespeichert.

@@ -111,6 +119,7 @@ Album + Tag Schutz Ablauf Freigabelink @@ -121,6 +130,7 @@ {foreach from=$BRATONIEN_ALBUM_SHARES item=share} {$share.category_name|default:'Gelöschtes Album'|escape:html} + {if $share.share_tag != ''}{$share.share_tag|escape:html}{else}{/if} {if $share.password_protected}Passwort{else}Nur Link{/if} {if $share.expires_at}{$share.expires_at|escape:html}{else}Unbegrenzt{/if} @@ -158,21 +168,14 @@ (function () { 'use strict'; - document.addEventListener('click', function (event) { - var button = event.target.closest('.bratonien-copy-share'); - if (!button) return; - - var input = document.getElementById(button.getAttribute('data-copy-target')); - if (!input) return; + function copyInput(input, button) { + if (!input || !input.value) return; function copied() { - var oldTitle = button.getAttribute('title') || 'Freigabelink kopieren'; + if (!button) return; + var oldTitle = button.getAttribute('title') || 'Kopieren'; button.setAttribute('title', 'Kopiert'); - button.setAttribute('aria-label', 'Freigabelink kopiert'); - setTimeout(function () { - button.setAttribute('title', oldTitle); - button.setAttribute('aria-label', 'Freigabelink kopieren'); - }, 1400); + setTimeout(function () { button.setAttribute('title', oldTitle); }, 1400); } if (navigator.clipboard && window.isSecureContext) { @@ -189,7 +192,71 @@ input.select(); document.execCommand('copy'); copied(); + } + + document.addEventListener('click', function (event) { + var shareCopy = event.target.closest('.bratonien-copy-share'); + if (shareCopy) { + copyInput(document.getElementById(shareCopy.getAttribute('data-copy-target')), shareCopy); + return; + } + + var generate = event.target.closest('#br-generate-share-password'); + if (generate) { + var input = document.getElementById('share_password'); + if (!input) return; + + var lower = 'abcdefghijkmnopqrstuvwxyz'; + var upper = 'ABCDEFGHJKLMNPQRSTUVWXYZ'; + var digits = '23456789'; + var symbols = '!@#$%&*+-=?'; + var all = lower + upper + digits + symbols; + var chars = [ + lower[randomIndex(lower.length)], + upper[randomIndex(upper.length)], + digits[randomIndex(digits.length)], + symbols[randomIndex(symbols.length)] + ]; + while (chars.length < 18) chars.push(all[randomIndex(all.length)]); + secureShuffle(chars); + input.value = chars.join(''); + input.type = 'text'; + input.focus(); + input.select(); + return; + } + + var toggle = event.target.closest('#br-toggle-share-password'); + if (toggle) { + var password = document.getElementById('share_password'); + if (password) password.type = password.type === 'password' ? 'text' : 'password'; + return; + } + + var copyPassword = event.target.closest('#br-copy-share-password'); + if (copyPassword) { + copyInput(document.getElementById('share_password'), copyPassword); + } }); + + function randomIndex(max) { + if (window.crypto && window.crypto.getRandomValues) { + var limit = Math.floor(0x100000000 / max) * max; + var values = new Uint32Array(1); + do { window.crypto.getRandomValues(values); } while (values[0] >= limit); + return values[0] % max; + } + return Math.floor(Math.random() * max); + } + + function secureShuffle(values) { + for (var i = values.length - 1; i > 0; i--) { + var j = randomIndex(i + 1); + var tmp = values[i]; + values[i] = values[j]; + values[j] = tmp; + } + } })(); {/literal}