смена галочки на тоггл и работа с текстом, замена апи

This commit is contained in:
Илья Братских 2026-06-24 08:55:07 +03:00 committed by KBAHTNET
parent 26bdf14af5
commit e4d289b9a3
4 changed files with 116 additions and 25 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ node_modules/
npm-debug.log*
node_trace.*.log
.env
flags

View File

@ -70,6 +70,7 @@
background: var(--surface);
box-shadow: var(--shadow);
backdrop-filter: blur(18px);
overflow: hidden;
}
.hero {
@ -171,7 +172,7 @@
.server-card {
display: grid;
grid-template-columns: 3.5rem 1fr auto;
grid-template-columns: 3.5rem minmax(0, 1fr) auto;
gap: 0.9rem;
align-items: center;
width: 100%;
@ -213,7 +214,15 @@
}
.server-name {
display: block;
font-weight: 800;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.server-info {
min-width: 0;
}
.server-meta,
@ -222,9 +231,18 @@
font-size: 0.82rem;
}
.server-meta {
display: block;
margin-top: 0.15rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ping {
min-width: 4.5rem;
text-align: right;
white-space: nowrap;
}
.pill {
@ -241,24 +259,82 @@
.controls-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-template-columns: minmax(0, 1fr);
gap: 0.8rem;
}
.checkbox-row {
.toggle-row {
display: flex;
align-items: center;
gap: 0.55rem;
justify-content: space-between;
gap: 0.85rem;
min-height: 100%;
border: 1px solid var(--border);
border-radius: 1rem;
padding: 0.75rem 0.9rem;
color: var(--muted);
background: var(--surface-strong);
cursor: pointer;
overflow: hidden;
}
.checkbox-row input {
accent-color: var(--accent);
.toggle-row input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.toggle-text {
display: grid;
gap: 0.15rem;
min-width: 0;
}
.toggle-title {
color: var(--text);
font-weight: 800;
}
.toggle-description {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 0.82rem;
}
.toggle-track {
position: relative;
flex: 0 0 auto;
width: 3.25rem;
height: 1.8rem;
border: 1px solid var(--border);
border-radius: 999px;
background: color-mix(in srgb, var(--muted) 22%, transparent);
transition:
background 0.2s,
border-color 0.2s;
}
.toggle-track::after {
content: "";
position: absolute;
top: 0.22rem;
left: 0.22rem;
width: 1.22rem;
height: 1.22rem;
border-radius: 50%;
background: var(--surface-strong);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.22);
transition: transform 0.2s;
}
.toggle-row input:checked + .toggle-track {
border-color: var(--accent);
background: var(--accent);
}
.toggle-row input:checked + .toggle-track::after {
transform: translateX(1.45rem);
}
.start-row {
@ -372,6 +448,7 @@
margin-top: 0.55rem;
color: var(--muted);
font-size: 0.9rem;
overflow-wrap: anywhere;
}
.graph-container {
@ -412,9 +489,8 @@
<div>
<h1>Измерение скорости сети</h1>
<p class="lead">
Выберите сервер, проверьте задержку до каждого узла и запустите
download/upload тест. Настройки темы и акцентного цвета сохраняются
в браузере.
Выберите ближайший сервер, проверьте задержку и запустите тест
скорости. Тема и акцентный цвет сохраняются в этом браузере.
</p>
</div>
@ -448,19 +524,25 @@
<aside class="panel" aria-label="Параметры теста">
<div class="controls-grid">
<label class="field">
Длительность этапа, минут
Длительность этапа, секунд
<input
type="number"
id="durationInput"
value="0.5"
min="0.1"
max="10"
step="0.1"
value="30"
min="5"
max="600"
step="5"
/>
</label>
<label class="checkbox-row">
<input type="checkbox" id="simultaneousCheckbox" checked />
Одновременный тест
<label class="toggle-row">
<span class="toggle-text">
<span class="toggle-title">Параллельный тест</span>
<span class="toggle-description">
Скачивание и отдача одновременно
</span>
</span>
<input type="checkbox" id="simultaneousCheckbox" />
<span class="toggle-track" aria-hidden="true"></span>
</label>
</div>
<div class="start-row">
@ -469,7 +551,7 @@
</button>
<div class="timer" id="timerDisplay">--:--</div>
</div>
<p class="status" id="targetServerText">Сервер не выбран</p>
<p class="status" id="targetServerText">Выберите сервер для теста</p>
</aside>
</div>
@ -660,7 +742,7 @@
button.innerHTML = `
<span class="flag">${flagContent}</span>
<span>
<span class="server-info">
<span class="server-name">${escapeHtml(server.name)}</span>
<span class="server-meta">${escapeHtml(server.country)} · ${escapeHtml(server.address)}</span>
</span>
@ -671,7 +753,7 @@
});
elements.serverStatus.textContent = servers.length
? "Выберите сервер для теста скорости."
? "Нажмите на карточку сервера, чтобы выбрать цель теста."
: "В конфиге нет серверов.";
}
@ -697,8 +779,8 @@
function updateSelectedServerText() {
const server = getSelectedServer();
elements.targetServerText.textContent = server
? `Цель: ${server.name}, ${server.country} (${server.address})`
: "Сервер не выбран";
? `Тест будет запущен через ${server.name} (${server.country}).`
: "Выберите сервер для теста.";
}
async function refreshAllPings() {
@ -1074,8 +1156,8 @@
elements.startBtn.disabled = true;
resetMetrics();
const minutes = parseFloat(elements.durationInput.value) || 0.5;
const singleDurationMs = Math.max(5000, minutes * 60 * 1000);
const seconds = parseFloat(elements.durationInput.value) || 30;
const singleDurationMs = Math.max(5000, seconds * 1000);
const simultaneous = elements.simultaneousCheckbox.checked;
totalTestDurationMs = simultaneous ? singleDurationMs : singleDurationMs * 2;
globalTestStartTime = performance.now();

View File

@ -16,7 +16,8 @@ const CHUNK_SIZE = 64 * 1024;
const INDEX_PATH = path.join(__dirname, "index.html");
const SERVERS_CONFIG_PATH = path.join(__dirname, "servers.json");
const FLAGS_DIR = path.join(__dirname, "flags");
const FLAG_API_URL = "https://flagcdn.com";
// const FLAG_API_URL = "https://flagcdn.com";
const FLAG_API_URL = "https://flagicons.lipis.dev/flags/4x3";
const serversConfig = loadServersConfig();

View File

@ -7,6 +7,13 @@
"address": "http://localhost:3000",
"country": "Локальный сервер",
"countryCode": "un"
},
{
"id": "vpn1",
"name": "VPN сервер в Нидерландах",
"address": "http://vpn1.bratskih.tech:3000",
"country": "Нидерланды",
"countryCode": "nl"
}
]
}