Ability to disable Personal M3U.
This commit is contained in:
@@ -43,6 +43,8 @@
|
||||
"personal_epg_label": "EPG URL (XMLTV) *",
|
||||
"personal_epg_m3u_label": "M3U URL",
|
||||
"personal_epg_optional": "optional",
|
||||
"personal_epg_m3u_enabled": "This instance allows a personal M3U playlist.",
|
||||
"personal_epg_m3u_disabled": "The administrator of this instance has disabled personal M3U playlists.",
|
||||
"cancel": "Cancel",
|
||||
"apply": "Apply",
|
||||
"setup_already_done": "Configuration already done. Use your admin key to access setup again.",
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
"personal_epg_label": "URL EPG (XMLTV) *",
|
||||
"personal_epg_m3u_label": "URL M3U",
|
||||
"personal_epg_optional": "opcional",
|
||||
"personal_epg_m3u_enabled": "Esta instancia permite una lista M3U personal.",
|
||||
"personal_epg_m3u_disabled": "El administrador de esta instancia ha desactivado las listas M3U personales.",
|
||||
"cancel": "Cancelar",
|
||||
"apply": "Aplicar",
|
||||
"setup_already_done": "Configuración ya realizada. Usa tu clave de administrador para volver al setup.",
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
"personal_epg_label": "URL EPG (XMLTV) *",
|
||||
"personal_epg_m3u_label": "URL M3U",
|
||||
"personal_epg_optional": "optionnel",
|
||||
"personal_epg_m3u_enabled": "Cette instance autorise l'ajout d'une playlist M3U personnelle.",
|
||||
"personal_epg_m3u_disabled": "L'administrateur de cette instance a désactivé l'ajout d'une playlist M3U personnelle.",
|
||||
"cancel": "Annuler",
|
||||
"apply": "Appliquer",
|
||||
"setup_already_done": "Configuration déjà effectuée. Utilisez votre clé admin pour accéder à nouveau au setup.",
|
||||
|
||||
@@ -69,6 +69,7 @@ if ($mode === 'setup' && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['
|
||||
} else {
|
||||
$group_name = trim($_POST['group_name'] ?? '');
|
||||
$allow_personal_epg = isset($_POST['allow_personal_epg']);
|
||||
$allow_personal_m3u = $allow_personal_epg && isset($_POST['allow_personal_m3u']);
|
||||
|
||||
$names = $_POST['source_name'] ?? [];
|
||||
$epg_urls = $_POST['source_epg_url'] ?? [];
|
||||
@@ -103,6 +104,7 @@ if ($mode === 'setup' && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['
|
||||
'group_name' => $group_name,
|
||||
'epg_sources' => $epg_sources,
|
||||
'allow_personal_epg' => $allow_personal_epg,
|
||||
'allow_personal_m3u' => $allow_personal_m3u,
|
||||
'admin_key' => $new_key,
|
||||
];
|
||||
$written = file_put_contents($config_path, json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
@@ -119,6 +121,9 @@ if ($mode === 'setup' && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['
|
||||
$prefill_group = $_POST['group_name'] ?? $existing['group_name'] ?? '';
|
||||
$prefill_sources = $existing['epg_sources'] ?? [];
|
||||
$prefill_epg = !empty($existing['allow_personal_epg']);
|
||||
$prefill_personal_m3u = array_key_exists('allow_personal_m3u', $existing)
|
||||
? !empty($existing['allow_personal_m3u'])
|
||||
: $prefill_epg;
|
||||
$submitted_key = trim($_POST['admin_key_input'] ?? $_POST['admin_key_hidden'] ?? '');
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
@@ -289,6 +294,17 @@ $submitted_key = trim($_POST['admin_key_input'] ?? $_POST['admin_key_hidden']
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="toggle-row">
|
||||
<div class="toggle-label">
|
||||
Allow personal M3U
|
||||
<small>Lets visitors add their own stream playlist in the Personal EPG modal.</small>
|
||||
</div>
|
||||
<label class="toggle">
|
||||
<input type="checkbox" name="allow_personal_m3u" id="allowPersonalM3u"<?= $prefill_personal_m3u ? ' checked' : '' ?><?= !$prefill_epg ? ' disabled' : '' ?>>
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<?php if (!$demo_mode): ?>
|
||||
<button type="submit" class="btn-submit">Save configuration</button>
|
||||
<?php endif; ?>
|
||||
@@ -324,6 +340,15 @@ function addSource() {
|
||||
function removeSource(btn) { btn.closest('.source-block').remove(); renumberSources(); updateRemoveButtons(); }
|
||||
function renumberSources() { document.querySelectorAll('.source-block').forEach((b,i) => b.querySelector('.source-num').textContent = `SOURCE ${i+1}`); }
|
||||
function updateRemoveButtons() { const b = document.querySelectorAll('.source-block'); b.forEach(bl => bl.querySelector('.source-remove').style.display = b.length > 1 ? '' : 'none'); }
|
||||
const allowPersonalEpgToggle = document.getElementById('allowPersonalEpg');
|
||||
const allowPersonalM3uToggle = document.getElementById('allowPersonalM3u');
|
||||
function syncPersonalM3uToggle() {
|
||||
if (!allowPersonalEpgToggle || !allowPersonalM3uToggle) return;
|
||||
allowPersonalM3uToggle.disabled = !allowPersonalEpgToggle.checked;
|
||||
if (!allowPersonalEpgToggle.checked) allowPersonalM3uToggle.checked = false;
|
||||
}
|
||||
allowPersonalEpgToggle?.addEventListener('change', syncPersonalM3uToggle);
|
||||
syncPersonalM3uToggle();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -29,6 +29,9 @@ if (isset($config['epg_url']) && !isset($config['epg_sources'])) {
|
||||
$group_name = htmlspecialchars($config['group_name'] ?? 'GridTV');
|
||||
$epg_sources = $config['epg_sources'] ?? [];
|
||||
$allow_personal_epg = !empty($config['allow_personal_epg']);
|
||||
$allow_personal_m3u = array_key_exists('allow_personal_m3u', $config)
|
||||
? !empty($config['allow_personal_m3u'])
|
||||
: $allow_personal_epg;
|
||||
|
||||
// Default to the first configured source to keep the rest of the app compatible.
|
||||
$first_source = $epg_sources[0] ?? [];
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
}
|
||||
.modal-field input:focus { border-color: var(--accent); }
|
||||
.modal-field input::placeholder { color: var(--text-dim); opacity: 0.4; }
|
||||
.modal-field-note {
|
||||
margin-top: 6px; font-size: 11px; line-height: 1.45; opacity: 0.82;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
.modal-field-note.is-disabled {
|
||||
color: #ffb0a5; opacity: 1;
|
||||
}
|
||||
.modal-actions { display: flex; gap: 10px; margin-top: 20px; justify-content: flex-end; }
|
||||
.modal-btn-cancel {
|
||||
background: none; border: 1px solid var(--border-bright); color: var(--text-dim);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const EPG_SOURCES = <?= json_encode(array_values($epg_sources)) ?>;
|
||||
const L = <?= json_encode($L) ?>;
|
||||
const ALLOW_PERSONAL_EPG = <?= $allow_personal_epg ? 'true' : 'false' ?>;
|
||||
const ALLOW_PERSONAL_M3U = <?= $allow_personal_m3u ? 'true' : 'false' ?>;
|
||||
|
||||
// Index of the currently selected source.
|
||||
let activeSourceIndex = 0;
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ window.addEventListener('load', () => {
|
||||
const savedSource = localStorage.getItem('gridtv-active-source');
|
||||
if (savedSource === 'personal') {
|
||||
const epg = localStorage.getItem('gridtv-personal-epg');
|
||||
const m3u = localStorage.getItem('gridtv-personal-m3u') ?? '';
|
||||
const m3u = ALLOW_PERSONAL_M3U ? (localStorage.getItem('gridtv-personal-m3u') ?? '') : '';
|
||||
if (epg) {
|
||||
currentEpgUrl = epg;
|
||||
currentM3uUrl = m3u;
|
||||
|
||||
+19
-3
@@ -28,8 +28,20 @@ function openPersonalEpgModal() {
|
||||
const saved_epg = localStorage.getItem('gridtv-personal-epg') ?? '';
|
||||
const saved_m3u = localStorage.getItem('gridtv-personal-m3u') ?? '';
|
||||
const modal = document.getElementById('personalEpgModal');
|
||||
const m3uInput = document.getElementById('personalM3uInput');
|
||||
const m3uHint = document.getElementById('personalM3uHint');
|
||||
document.getElementById('personalEpgInput').value = saved_epg;
|
||||
document.getElementById('personalM3uInput').value = saved_m3u;
|
||||
if (m3uInput) {
|
||||
m3uInput.value = ALLOW_PERSONAL_M3U ? saved_m3u : '';
|
||||
m3uInput.disabled = !ALLOW_PERSONAL_M3U;
|
||||
}
|
||||
if (m3uHint) {
|
||||
m3uHint.textContent = ALLOW_PERSONAL_M3U
|
||||
? (m3uHint.dataset.enabledText ?? '')
|
||||
: (m3uHint.dataset.disabledText ?? '');
|
||||
m3uHint.classList.toggle('is-disabled', !ALLOW_PERSONAL_M3U);
|
||||
m3uHint.style.display = '';
|
||||
}
|
||||
modal.classList.add('visible');
|
||||
}
|
||||
|
||||
@@ -44,10 +56,14 @@ function closePersonalEpgModal(applied) {
|
||||
|
||||
function applyPersonalEpg() {
|
||||
const epg = document.getElementById('personalEpgInput').value.trim();
|
||||
const m3u = document.getElementById('personalM3uInput').value.trim();
|
||||
const m3u = ALLOW_PERSONAL_M3U ? document.getElementById('personalM3uInput').value.trim() : '';
|
||||
if (!epg) { alert('URL EPG obligatoire'); return; }
|
||||
localStorage.setItem('gridtv-personal-epg', epg);
|
||||
localStorage.setItem('gridtv-personal-m3u', m3u);
|
||||
if (ALLOW_PERSONAL_M3U) {
|
||||
localStorage.setItem('gridtv-personal-m3u', m3u);
|
||||
} else {
|
||||
localStorage.removeItem('gridtv-personal-m3u');
|
||||
}
|
||||
localStorage.setItem('gridtv-active-source', 'personal');
|
||||
updateSourceDropdownLabel('✏ Personal EPG');
|
||||
currentEpgUrl = epg;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<div class="modal-field">
|
||||
<label><?= htmlspecialchars($L["personal_epg_m3u_label"]) ?> <span style="opacity:.5;font-size:10px">(<?= htmlspecialchars($L["personal_epg_optional"]) ?>)</span></label>
|
||||
<input type="url" id="personalM3uInput" placeholder="http://mon-serveur/channels.m3u">
|
||||
<div id="personalM3uHint" class="modal-field-note" data-enabled-text="<?= htmlspecialchars($L["personal_epg_m3u_enabled"]) ?>" data-disabled-text="<?= htmlspecialchars($L["personal_epg_m3u_disabled"]) ?>"></div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="modal-btn-cancel" onclick="closePersonalEpgModal()"><?= htmlspecialchars($L["cancel"]) ?></button>
|
||||
|
||||
Reference in New Issue
Block a user