Мелочи по косметике
- вывод деталей о листе только при онлайн статусе - копирование ссылки без промпта - мелочи по подсказкам к разным элементам
This commit is contained in:
@@ -86,6 +86,6 @@ class TwigExtention extends AbstractExtension
|
|||||||
*/
|
*/
|
||||||
public function toDate(?float $timestamp, string $format = 'd.m.Y H:i:s'): string
|
public function toDate(?float $timestamp, string $format = 'd.m.Y H:i:s'): string
|
||||||
{
|
{
|
||||||
return $timestamp === null ? '(неизвестно)' : date($format, (int)$timestamp);
|
return $timestamp === null ? '' : date($format, (int)$timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
<h2>О плейлисте: {{ playlist.name }}</h2>
|
<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">
|
<div class="alert alert-danger small" role="alert">
|
||||||
Ошибка плейлиста: {{ playlist.content }}
|
Ошибка плейлиста: {{ playlist.content }}
|
||||||
</div>
|
</div>
|
||||||
@@ -80,21 +80,19 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th class="w-25" scope="row">Код</th>
|
<th class="w-25" scope="row">Код</th>
|
||||||
<th class="text-break">
|
<th class="text-break">
|
||||||
{% if playlist.isOnline is same as(true) %}
|
<span class="pe-3 font-monospace">{{ playlist.code }}</span>
|
||||||
<span class="pe-3 font-monospace text-success">{{ playlist.code }}</span>
|
{% if playlist.isOnline is same as (true) %}
|
||||||
<span class="badge small text-dark bg-success">online</span>
|
<span class="cursor-help badge small text-dark bg-success"
|
||||||
{% elseif playlist.isOnline is same as(false) %}
|
title="Вероятно, работает"
|
||||||
<span class="pe-3 font-monospace text-danger">{{ playlist.code }}</span>
|
>online</span>
|
||||||
<span class="badge small text-dark bg-danger">offline</span>
|
{% elseif playlist.isOnline is same as (false) %}
|
||||||
{% elseif playlist.isOnline is same as(null) %}
|
<span class="cursor-help badge small text-dark bg-danger"
|
||||||
<span class="pe-3 font-monospace">{{ playlist.code }}</span>
|
title="Вероятно, не работает"
|
||||||
<span class="badge small text-dark bg-secondary" title="Не проверялся">unknown</span>
|
>offline</span>
|
||||||
{% endif %}
|
{% elseif playlist.isOnline is same as (null) %}
|
||||||
|
<span class="cursor-help badge small text-dark bg-secondary"
|
||||||
{% if "adult" in playlist.tags %}
|
title="Не проверялся"
|
||||||
<span class="cursor-help badge small bg-warning text-dark"
|
>unknown</span>
|
||||||
title="Есть каналы для взрослых!"
|
|
||||||
>18+</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -105,11 +103,13 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Ccылка для ТВ</th>
|
<th scope="row">Ccылка для ТВ</th>
|
||||||
<td>
|
<td>
|
||||||
<b onclick="prompt('Скопируй адрес плейлиста. Если не работает, добавь \'.m3u\' в конец.', '{{ base_url(playlist.code) }}')"
|
<span onclick="copyPlaylistUrl('{{ playlist.code }}')"
|
||||||
data-bs-toggle="tooltip"
|
class="cursor-pointer"
|
||||||
data-bs-placement="top"
|
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
|
||||||
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
|
>
|
||||||
class="font-monospace cursor-pointer text-break">{{ base_url(playlist.code) }}</b>
|
<b class="cursor-pointer font-monospace text-break">{{ base_url(playlist.code) }}</b>
|
||||||
|
<ion-icon name="copy-outline"></ion-icon>
|
||||||
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -119,27 +119,37 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Наполнение</th>
|
<th scope="row">Наполнение</th>
|
||||||
<td class="text-break">
|
<td class="text-break">
|
||||||
<ion-icon name="folder-open-outline"></ion-icon> группы: {{ playlist.groups|length }}<br>
|
{% if playlist.isOnline is same as (true) %}
|
||||||
<ion-icon name="videocam-outline"></ion-icon> каналы:
|
{% if playlist.hasTokens is same as (true) %}
|
||||||
<span class="cursor-help text-success" title="Возможно, рабочие каналы">
|
<span class="cursor-help badge bg-info text-dark">
|
||||||
{{ playlist.onlineCount }} ({{ playlist.onlinePercent }}%)
|
<ion-icon name="paw"></ion-icon>
|
||||||
</span>
|
</span> могут быть нестабильные каналы<br>
|
||||||
+
|
{% endif %}
|
||||||
<span class="cursor-help text-danger" title="Возможно, НЕрабочие каналы">
|
|
||||||
{{ playlist.offlineCount }} ({{ playlist.offlinePercent }}%)
|
|
||||||
</span>
|
|
||||||
= {{ playlist.channels|length }}
|
|
||||||
|
|
||||||
{% if playlist.hasTokens is same as (true) %}
|
{% if "adult" in playlist.tags %}
|
||||||
<br><ion-icon name="paw" class="text-info"></ion-icon> могут быть нестабильные каналы
|
<span class="cursor-help badge small bg-warning text-dark">18+</span> есть каналы для взрослых<br>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<ion-icon name="folder-open-outline"></ion-icon> группы: {{ playlist.groups|length }}<br>
|
||||||
|
<ion-icon name="videocam-outline"></ion-icon> каналы:
|
||||||
|
<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 %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Возможности</th>
|
<th scope="row">Возможности</th>
|
||||||
<td class="text-break">
|
<td class="text-break">
|
||||||
<ion-icon name="newspaper-outline"></ion-icon> Программа передач: {{ playlist.hasTvg ? 'есть' : 'нет' }}<br>
|
{% if playlist.isOnline is same as (true) %}
|
||||||
<ion-icon name="play-back"></ion-icon> Перемотка (архив): {{ playlist.hasCatchup ? 'есть' : 'нет' }}
|
<ion-icon name="newspaper-outline"></ion-icon> Программа передач: {{ playlist.hasTvg ? 'есть' : 'нет' }}<br>
|
||||||
|
<ion-icon name="play-back"></ion-icon> Перемотка (архив): {{ playlist.hasCatchup ? 'есть' : 'нет' }}
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="text-secondary">
|
<tr class="text-secondary">
|
||||||
@@ -154,7 +164,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if playlist.isOnline is same as(false) %}
|
{% if playlist.isOnline is same as (false) %}
|
||||||
<tr class="text-secondary">
|
<tr class="text-secondary">
|
||||||
<th class="w-25" scope="row">Ошибка проверки</th>
|
<th class="w-25" scope="row">Ошибка проверки</th>
|
||||||
<td class="text-break">{{ playlist.content }}</td>
|
<td class="text-break">{{ playlist.content }}</td>
|
||||||
|
|||||||
@@ -116,8 +116,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-footer cursor-pointer"
|
<div class="card-footer cursor-pointer"
|
||||||
onclick="prompt('Скопируй адрес плейлиста. Если не работает, добавь \'.m3u\' в конец.', '{{ base_url(playlist.code) }}')"
|
onclick="copyPlaylistUrl('{{ playlist.code }}')"
|
||||||
title="Нажми чтобы скопировать"
|
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
|
||||||
>
|
>
|
||||||
<div class="d-flex justify-content-between align-items-center small">
|
<div class="d-flex justify-content-between align-items-center small">
|
||||||
<span class="font-monospace text-truncate">
|
<span class="font-monospace text-truncate">
|
||||||
|
|||||||
@@ -132,6 +132,55 @@
|
|||||||
<script src="/js/bootstrap.bundle.min.js"></script>
|
<script src="/js/bootstrap.bundle.min.js"></script>
|
||||||
{% block footer %}{% endblock %}
|
{% 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 %}
|
{% include("custom.twig") ignore missing %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user