Мелочи по косметике

- вывод деталей о листе только при онлайн статусе
- копирование ссылки без промпта
- мелочи по подсказкам к разным элементам
This commit is contained in:
2025-10-29 00:40:47 +08:00
parent 3b0e1d8f18
commit ba8d59644c
4 changed files with 98 additions and 39 deletions

View File

@@ -31,7 +31,7 @@
{% block header %}
<h2>О плейлисте: {{ playlist.name }}</h2>
{% if playlist.isOnline is same as(false) %}
{% if playlist.isOnline is same as (false) %}
<div class="alert alert-danger small" role="alert">
Ошибка плейлиста: {{ playlist.content }}
</div>
@@ -80,21 +80,19 @@
<tr>
<th class="w-25" scope="row">Код</th>
<th class="text-break">
{% if playlist.isOnline is same as(true) %}
<span class="pe-3 font-monospace text-success">{{ playlist.code }}</span>
<span class="badge small text-dark bg-success">online</span>
{% elseif playlist.isOnline is same as(false) %}
<span class="pe-3 font-monospace text-danger">{{ playlist.code }}</span>
<span class="badge small text-dark bg-danger">offline</span>
{% elseif playlist.isOnline is same as(null) %}
<span class="pe-3 font-monospace">{{ playlist.code }}</span>
<span class="badge small text-dark bg-secondary" title="Не проверялся">unknown</span>
{% endif %}
{% if "adult" in playlist.tags %}
<span class="cursor-help badge small bg-warning text-dark"
title="Есть каналы для взрослых!"
>18+</span>
<span class="pe-3 font-monospace">{{ playlist.code }}</span>
{% if playlist.isOnline is same as (true) %}
<span class="cursor-help badge small text-dark bg-success"
title="Вероятно, работает"
>online</span>
{% elseif playlist.isOnline is same as (false) %}
<span class="cursor-help badge small text-dark bg-danger"
title="Вероятно, не работает"
>offline</span>
{% elseif playlist.isOnline is same as (null) %}
<span class="cursor-help badge small text-dark bg-secondary"
title="Не проверялся"
>unknown</span>
{% endif %}
</th>
</tr>
@@ -105,11 +103,13 @@
<tr>
<th scope="row">Ccылка для ТВ</th>
<td>
<b onclick="prompt('Скопируй адрес плейлиста. Если не работает, добавь \'.m3u\' в конец.', '{{ base_url(playlist.code) }}')"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
class="font-monospace cursor-pointer text-break">{{ base_url(playlist.code) }}</b>
<span onclick="copyPlaylistUrl('{{ playlist.code }}')"
class="cursor-pointer"
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
>
<b class="cursor-pointer font-monospace text-break">{{ base_url(playlist.code) }}</b>
<ion-icon name="copy-outline"></ion-icon>
</span>
</td>
</tr>
<tr>
@@ -119,27 +119,37 @@
<tr>
<th scope="row">Наполнение</th>
<td class="text-break">
<ion-icon name="folder-open-outline"></ion-icon>&nbsp;группы: {{ playlist.groups|length }}<br>
<ion-icon name="videocam-outline"></ion-icon>&nbsp;каналы:
<span class="cursor-help text-success" title="Возможно, рабочие каналы">
{{ playlist.onlineCount }} ({{ playlist.onlinePercent }}%)
</span>
+
<span class="cursor-help text-danger" title="Возможно, НЕрабочие каналы">
{{ playlist.offlineCount }} ({{ playlist.offlinePercent }}%)
</span>
= {{ playlist.channels|length }}
{% if playlist.isOnline is same as (true) %}
{% if playlist.hasTokens is same as (true) %}
<span class="cursor-help badge bg-info text-dark">
<ion-icon name="paw"></ion-icon>
</span>&nbsp;могут быть нестабильные каналы<br>
{% endif %}
{% if playlist.hasTokens is same as (true) %}
<br><ion-icon name="paw" class="text-info"></ion-icon>&nbsp;могут быть нестабильные каналы
{% if "adult" in playlist.tags %}
<span class="cursor-help badge small bg-warning text-dark">18+</span>&nbsp;есть каналы для взрослых<br>
{% endif %}
<ion-icon name="folder-open-outline"></ion-icon>&nbsp;группы: {{ playlist.groups|length }}<br>
<ion-icon name="videocam-outline"></ion-icon>&nbsp;каналы:
<span class="cursor-help text-success" title="Возможно, рабочие каналы">
{{ playlist.onlineCount }} ({{ playlist.onlinePercent }}%)
</span>
+
<span class="cursor-help text-danger" title="Возможно, НЕрабочие каналы">
{{ playlist.offlineCount }} ({{ playlist.offlinePercent }}%)
</span>
= {{ playlist.channels|length }}
{% endif %}
</td>
</tr>
<tr>
<th scope="row">Возможности</th>
<td class="text-break">
<ion-icon name="newspaper-outline"></ion-icon>&nbsp;Программа передач:&nbsp;{{ playlist.hasTvg ? 'есть' : 'нет' }}<br>
<ion-icon name="play-back"></ion-icon>&nbsp;Перемотка&nbsp;(архив):&nbsp;{{ playlist.hasCatchup ? 'есть' : 'нет' }}
{% if playlist.isOnline is same as (true) %}
<ion-icon name="newspaper-outline"></ion-icon>&nbsp;Программа передач:&nbsp;{{ playlist.hasTvg ? 'есть' : 'нет' }}<br>
<ion-icon name="play-back"></ion-icon>&nbsp;Перемотка&nbsp;(архив):&nbsp;{{ playlist.hasCatchup ? 'есть' : 'нет' }}
{% endif %}
</td>
</tr>
<tr class="text-secondary">
@@ -154,7 +164,7 @@
</span>
</td>
</tr>
{% if playlist.isOnline is same as(false) %}
{% if playlist.isOnline is same as (false) %}
<tr class="text-secondary">
<th class="w-25" scope="row">Ошибка проверки</th>
<td class="text-break">{{ playlist.content }}</td>

View File

@@ -116,8 +116,8 @@
</div>
<div class="card-footer cursor-pointer"
onclick="prompt('Скопируй адрес плейлиста. Если не работает, добавь \'.m3u\' в конец.', '{{ base_url(playlist.code) }}')"
title="Нажми чтобы скопировать"
onclick="copyPlaylistUrl('{{ playlist.code }}')"
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
>
<div class="d-flex justify-content-between align-items-center small">
<span class="font-monospace text-truncate">

View File

@@ -132,6 +132,55 @@
<script src="/js/bootstrap.bundle.min.js"></script>
{% block footer %}{% endblock %}
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div class="toast align-items-center text-bg-success border-0" role="alert" id="clipboardToast">
<div class="d-flex">
<div class="toast-body" id="clipboardToastBody"></div>
</div>
</div>
</div>
<script>
function showToast(message) {
const toastEl = document.getElementById('clipboardToast');
const toastBodyEl = document.getElementById('clipboardToastBody');
toastBodyEl.innerHTML = message;
const toast = new bootstrap.Toast(toastEl, {delay: 5000});
toast.show();
}
function copyPlaylistUrl(code) {
const url = '{{ base_url() }}/' + code;
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard
.writeText(url)
.then(() => showToast(`Ссылка на плейлист '${code}' скопирована в буфер обмена`))
.catch(err => console.error('Failed to copy:', err));
} else {
try {
const textArea = document.createElement("textarea");
textArea.value = url;
textArea.style.position = "fixed"; // Avoid scrolling to bottom
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
const successful = document.execCommand('copy');
document.body.removeChild(textArea);
if (successful) {
showToast(`Ссылка на плейлист '${code}' скопирована в буфер обмена`);
} else {
showToast('Ошибка при копировании ссылки', true);
}
} catch (err) {
console.error('Fallback copy failed:', err);
showToast('Ошибка при копировании ссылки', true);
}
}
}
</script>
{% include("custom.twig") ignore missing %}
</body>
</html>