Косметика

- пересмотрено меню в шапке и подвале
- ссылка для тв + qr-код теперь по умолчанию зеркальные, с протоколом и подсказкой про .m3u
- предупреждение о большом кол-ве каналов теперь справа и скрывается после загрузки списка
- увеличен шрифт в табилце основных данных листа
This commit is contained in:
2025-06-10 09:37:43 +08:00
parent 7f10930b7b
commit a36b3e1e9a
6 changed files with 65 additions and 39 deletions

View File

@@ -46,8 +46,8 @@ class ApiController extends BasicController
'outputType' => QRCode::OUTPUT_IMAGE_JPG, 'outputType' => QRCode::OUTPUT_IMAGE_JPG,
'eccLevel' => QRCode::ECC_L, 'eccLevel' => QRCode::ECC_L,
]); ]);
$data = base_url("$code"); $data = config('app.mirror_url') ? mirror_url("$code.m3u") : base_url("$code.m3u");
$raw = (new QRCode($options))->render($data, $filePath); $raw = new QRCode($options)->render($data, $filePath);
$raw = base64_decode(str_replace('data:image/jpg;base64,', '', $raw)); $raw = base64_decode(str_replace('data:image/jpg;base64,', '', $raw));
} }

View File

@@ -28,6 +28,7 @@ class TwigExtention extends AbstractExtension
new TwigFunction('version', [$this, 'version']), new TwigFunction('version', [$this, 'version']),
new TwigFunction('is_file', [$this, 'isFile']), new TwigFunction('is_file', [$this, 'isFile']),
new TwigFunction('base_url', [$this, 'baseUrl']), new TwigFunction('base_url', [$this, 'baseUrl']),
new TwigFunction('mirror_url', [$this, 'mirrorUrl']),
new TwigFunction('to_date', [$this, 'toDate']), new TwigFunction('to_date', [$this, 'toDate']),
]; ];
} }
@@ -65,6 +66,17 @@ class TwigExtention extends AbstractExtension
return base_url($path); return base_url($path);
} }
/**
* Возвращает зеркальный URL приложения
*
* @param string $path
* @return string
*/
public function mirrorUrl(string $path = ''): string
{
return mirror_url($path);
}
/** /**
* Проверячет существование файла * Проверячет существование файла
* *

View File

@@ -27,11 +27,6 @@
{% block header %} {% block header %}
<h2>О плейлисте: {{ playlist.name }}</h2> <h2>О плейлисте: {{ playlist.name }}</h2>
{% if (playlist.channels|length > 500) %}
<div class="alert alert-warning small" role="alert">
В плейлисте очень много каналов. На загрузку их списка и логотипов потребуется некоторое время.
</div>
{% endif %}
{% 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 }}
@@ -64,7 +59,7 @@
</a> </a>
</li> </li>
</ul> </ul>
<div class="tab-content small"> <div class="tab-content">
<div class="tab-pane fade show active" id="tab-data" tabindex="0"> <div class="tab-pane fade show active" id="tab-data" tabindex="0">
<table class="table table-dark table-hover small mb-lg-5"> <table class="table table-dark table-hover small mb-lg-5">
<tbody> <tbody>
@@ -92,11 +87,13 @@
</tr> </tr>
<tr> <tr>
<th scope="row">Ccылка для ТВ</th> <th scope="row">Ccылка для ТВ</th>
<td><b onclick="prompt('Скопируй адрес плейлиста', 'm3u.su/{{ playlist.code }}')" <td>
<b onclick="prompt('Скопируй адрес плейлиста. Если не работает, добавь \'.m3u\' в конец.', '{{ mirror_url(playlist.code) }}')"
data-bs-toggle="tooltip" data-bs-toggle="tooltip"
data-bs-placement="top" data-bs-placement="top"
title="Нажми на ссылку, чтобы скопировать её в буфер обмена" title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
class="font-monospace cursor-pointer text-break">m3u.su/{{ playlist.code }}</b></td> class="font-monospace cursor-pointer text-break">{{ mirror_url(playlist.code) }}</b>
</td>
</tr> </tr>
<tr> <tr>
<th scope="row">Источник</th> <th scope="row">Источник</th>
@@ -166,11 +163,6 @@
> >
<ion-icon name="qr-code-outline"></ion-icon>&nbsp;QR-код <ion-icon name="qr-code-outline"></ion-icon>&nbsp;QR-код
</button> </button>
<textarea class="form-control bg-dark text-light font-monospace mb-3 mb-md-0 m3u-raw"
rows="40"
id="m3u-raw"
readonly
>{{ playlist.content }}</textarea>
<div class="modal fade" id="qrcode-popup" tabindex="-1"> <div class="modal fade" id="qrcode-popup" tabindex="-1">
<div class="modal-dialog "> <div class="modal-dialog ">
<div class="modal-content bg-dark"> <div class="modal-content bg-dark">
@@ -184,6 +176,11 @@
</div> </div>
</div> </div>
</div> </div>
<textarea class="form-control bg-dark text-light font-monospace mb-3 mb-md-0 m3u-raw"
rows="40"
id="m3u-raw"
readonly
>{{ playlist.content }}</textarea>
</div> </div>
</div> </div>
</div> </div>
@@ -194,6 +191,14 @@
{% if (playlist.groups|length > 1) %} {% if (playlist.groups|length > 1) %}
<div class="row my-3"> <div class="row my-3">
<div class="col-12"> <div class="col-12">
{% if (playlist.channels|length >= 500) %}
<div class="alert alert-warning small" role="alert" id="toomuchalert">
<div class="spinner-border text-success spinner-border-sm" role="status">
<span class="visually-hidden">Загрузка...</span>
</div>
В плейлисте очень много каналов. На загрузку их списка и логотипов потребуется некоторое время.
</div>
{% endif %}
<div class="input-group"> <div class="input-group">
<select id="groupSelector" <select id="groupSelector"
class="form-select form-select-sm border-secondary bg-dark text-light" class="form-select form-select-sm border-secondary bg-dark text-light"
@@ -382,6 +387,11 @@
list.on('updated', (data) => document.getElementById('chcount').innerText = data.visibleItems.length) list.on('updated', (data) => document.getElementById('chcount').innerText = data.visibleItems.length)
document.getElementById('search-field').addEventListener('keyup', (e) => list.search(e.target.value)) document.getElementById('search-field').addEventListener('keyup', (e) => list.search(e.target.value))
document.addEventListener("DOMContentLoaded", () => {
const alert = document.getElementById("toomuchalert");
!!alert && alert.remove()
});
function savePlaylist() { function savePlaylist() {
const link = document.createElement("a"); const link = document.createElement("a");
const content = document.getElementById("m3u-raw").value const content = document.getElementById("m3u-raw").value

View File

@@ -193,7 +193,7 @@
</h2> </h2>
<p>Кто-то воткнул платный канал в плейлист и распространил его как бесплатный.</p> <p>Кто-то воткнул платный канал в плейлист и распространил его как бесплатный.</p>
<p>Забудь про этот плейлист. Ищи другой. Без вариантов. Такова цена халявы.</p> <p>Забудь про этот плейлист. Ищи другой. Без вариантов. Такова цена халявы.</p>
<p>Нет, я не буду это исправлять.</p> <p>Я могу это исправить только удалением плейлиста с сайта. Это единственный вариант, который устроит всех.</p>
</div> </div>
<!-- Заглушка 2 --> <!-- Заглушка 2 -->
@@ -206,7 +206,7 @@
<p>Попробуй использовать плеер, который позволяет указать User-Agent, и указать User-Agent:</p> <p>Попробуй использовать плеер, который позволяет указать User-Agent, и указать User-Agent:</p>
<pre class="fw-bold">Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer</pre> <pre class="fw-bold">Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer</pre>
<p>Или подключи Wink. Или забудь про этот плейлист и ищи другой.</p> <p>Или подключи Wink. Или забудь про этот плейлист и ищи другой.</p>
<p>Нет, я не буду это исправлять.</p> <p>Я могу это исправить только удалением плейлиста с сайта. Это единственный вариант, который устроит всех.</p>
</div> </div>
<!-- Добавь канал! --> <!-- Добавь канал! -->

View File

@@ -33,7 +33,7 @@
<table class="table table-responsive table-dark table-hover small"> <table class="table table-responsive table-dark table-hover small">
<thead> <thead>
<tr> <tr>
<th class="col-1 text-center">ID</th> <th class="col-1 text-center">Код</th>
<th class="col-8">Информация о плейлисте</th> <th class="col-8">Информация о плейлисте</th>
<th class="col-1 text-center">Каналов</th> <th class="col-1 text-center">Каналов</th>
<th class="col-2 d-none d-sm-table-cell">Ссылка для ТВ</th> <th class="col-2 d-none d-sm-table-cell">Ссылка для ТВ</th>
@@ -87,11 +87,14 @@
{% endif %} {% endif %}
</td> </td>
<td class="d-none d-sm-table-cell"> <td class="d-none d-sm-table-cell">
<span onclick="prompt('Скопируй адрес плейлиста', 'm3u.su/{{ playlist.code }}')" <span onclick="prompt('Скопируй адрес плейлиста. Если не работает, добавь \'.m3u\' в конец.', '{{ mirror_url(playlist.code) }}')"
title="Нажми на ссылку, чтобы скопировать её в буфер обмена" title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
class="font-monospace cursor-pointer" class="font-monospace cursor-pointer"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
> >
m3u.su/{{ playlist.code }} {{ mirror_url(playlist.code) }}
</span> </span>
</td> </td>
</tr> </tr>

View File

@@ -46,31 +46,28 @@
<div class="collapse navbar-collapse" id="navbarNav"> <div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{{ base_url() }}">Главная</a> <a class="nav-link" href="/">Список</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/faq">FAQ</a> <a class="nav-link" href="/faq">FAQ</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="https://git.axenov.dev/IPTV">Исходники</a> <a class="nav-link" href="https://git.axenov.dev/IPTV/.profile/src/branch/master/README.md#помощь-проекту">Поддержка</a>
</li> </li>
<li class="nav-item"> <li class="nav-item dropdown">
<a class="nav-link" href="https://axenov.dev">axenov.dev</a> <a class="nav-link dropdown-toggle"
</li> href="#"
<li class="nav-item"> role="button"
<a class="nav-link" href="https://t.me/iptv_aggregator">Telegram</a> data-bs-toggle="dropdown"
</li> aria-expanded="false"
<li class="nav-item"> >
<a class="nav-link" href="https://boosty.to/anthonyaxenov"> Telegram
<img class="boosty" src="/boosty.svg" alt="Boosty">
Boosty
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://yoomoney.ru/to/41001685237530">
<ion-icon name="card-outline"></ion-icon>
Yoomoney
</a> </a>
<ul class="dropdown-menu dropdown-menu-dark">
<li><a class="dropdown-item" href="https://t.me/iptv_aggregator">Канал @iptv_aggregator</a></li>
<li><a class="dropdown-item" href="https://t.me/iptv_aggregator_chat">Чат @iptv_aggregator_chat</a></li>
<li><a class="dropdown-item" href="https://t.me/iptv_aggregator_bot">Бот @iptv_aggregator_bot</a></li>
</ul>
</li> </li>
</ul> </ul>
</div> </div>
@@ -88,7 +85,11 @@
<a href="/faq">FAQ</a>&nbsp;|&nbsp;<a <a href="/faq">FAQ</a>&nbsp;|&nbsp;<a
href="https://git.axenov.dev/IPTV">Исходники</a>&nbsp;|&nbsp;<a href="https://git.axenov.dev/IPTV">Исходники</a>&nbsp;|&nbsp;<a
href="https://axenov.dev">axenov.dev</a>&nbsp;|&nbsp;<a href="https://axenov.dev">axenov.dev</a>&nbsp;|&nbsp;<a
href="https://t.me/iptv_aggregator">Telegram</a><br> href="https://t.me/iptv_aggregator">Канал</a>&nbsp;|&nbsp;<a
href="https://t.me/iptv_aggregator_chat">Чат</a>&nbsp;|&nbsp;<a
href="https://t.me/iptv_aggregator_bot">Бот</a>
<br>
<a class="small text-secondary" <a class="small text-secondary"
href="https://git.axenov.dev/IPTV/web/releases/tag/v{{ version() }}" href="https://git.axenov.dev/IPTV/web/releases/tag/v{{ version() }}"
target="_blank" target="_blank"