responzivni a hezci verze
This commit is contained in:
parent
c7070ec08b
commit
5faea39889
@ -13,7 +13,7 @@ body {
|
|||||||
font-family: system-ui, sans-serif;
|
font-family: system-ui, sans-serif;
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
color: #111;
|
color: #111;
|
||||||
max-width: 800px;
|
max-width: 1200px;
|
||||||
margin: 2rem auto;
|
margin: 2rem auto;
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
}
|
}
|
||||||
@ -79,3 +79,35 @@ button.secondary:hover { background: #e5e7eb; }
|
|||||||
pointer-events:none;
|
pointer-events:none;
|
||||||
}
|
}
|
||||||
#toast.show { opacity:1; }
|
#toast.show { opacity:1; }
|
||||||
|
|
||||||
|
/* Responsivita pro mobily */
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
body { padding: 0 .5rem; }
|
||||||
|
.row, .link-row {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
textarea { min-height: 140px; }
|
||||||
|
button { width: 100%; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid layout pro široké obrazovky */
|
||||||
|
.grid {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 1.5rem;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
.left-col, .right-col {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,5 +3,6 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<textarea id="plainOut" readonly style="height:120px">{{.}}</textarea>
|
<textarea id="plainOut" readonly style="height:120px">{{.}}</textarea>
|
||||||
<button type="button" class="secondary" onclick="copyEl('plainOut')">Copy</button>
|
<button type="button" class="secondary" onclick="copyEl('plainOut')">Copy</button>
|
||||||
|
<button type="button" class="secondary" onclick="clearEl('plainOut')">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,24 +1,26 @@
|
|||||||
<!DOCTYPE html>
|
<body>
|
||||||
<html lang="cs">
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Encryptor (HTMX)</title>
|
<title>Encryptor (HTMX)</title>
|
||||||
<script src="https://unpkg.com/htmx.org"></script>
|
|
||||||
<link rel="stylesheet" href="/static/style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<h1>🔐 Encryptor</h1>
|
|
||||||
<p class="subtitle">Jednoduché HTMX rozhraní pro šifrování zpráv cizím klíčem</p>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
|
<!-- CSS má být v <head> -->
|
||||||
|
<link rel="stylesheet" href="/static/style.css">
|
||||||
|
|
||||||
|
<!-- Tohle jsi omylem smazal; bez toho HTMX nefunguje -->
|
||||||
|
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="grid">
|
||||||
|
<div class="left-col">
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Můj veřejný klíč</h2>
|
<h2>Můj veřejný klíč</h2>
|
||||||
<div class="link-row">
|
<div class="row">
|
||||||
<a href="/public.pem" target="_blank">public.pem</a>
|
<a href="/public.pem" target="_blank">public.pem</a>
|
||||||
<button onclick="copyFromUrl('/public.pem')">Copy</button>
|
<button onclick="copyFromUrl('/public.pem')">Copy</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="link-row">
|
<div class="row">
|
||||||
<a href="/public.crt" target="_blank">identity.crt</a>
|
<a href="/public.crt" target="_blank">identity.crt</a>
|
||||||
<button onclick="copyFromUrl('/public.crt')">Copy</button>
|
<button onclick="copyFromUrl('/public.crt')">Copy</button>
|
||||||
</div>
|
</div>
|
||||||
@ -32,19 +34,23 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<textarea id="msg" name="message" placeholder="Sem napiš zprávu..."></textarea>
|
<textarea id="msg" name="message" placeholder="Sem napiš zprávu..."></textarea>
|
||||||
<button type="button" class="secondary" onclick="copyEl('msg')">Copy</button>
|
<button type="button" class="secondary" onclick="copyEl('msg')">Copy</button>
|
||||||
|
<button type="button" class="secondary" onclick="clearEl('msg')">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label>Veřejný klíč příjemce (PEM nebo CERT)</label>
|
<label>Veřejný klíč příjemce (PEM nebo CERT)</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<textarea id="peerKey" name="pubkey" placeholder="-----BEGIN PUBLIC KEY----- ..."></textarea>
|
<textarea id="peerKey" name="pubkey" placeholder="-----BEGIN PUBLIC KEY----- ..."></textarea>
|
||||||
<button type="button" class="secondary" onclick="copyEl('peerKey')">Copy</button>
|
<button type="button" class="secondary" onclick="copyEl('peerKey')">Copy</button>
|
||||||
|
<button type="button" class="secondary" onclick="clearEl('peerKey')">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="primary">Encrypt</button>
|
<button type="submit" class="primary">Encrypt</button>
|
||||||
</form>
|
</form>
|
||||||
<div id="encryptResult" class="result"></div>
|
<div id="encryptResult" class="result"></div>
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right-col">
|
||||||
<section class="card">
|
<section class="card">
|
||||||
<h2>Dešifrovat</h2>
|
<h2>Dešifrovat</h2>
|
||||||
<form hx-post="/decrypt" hx-target="#decryptResult" hx-swap="innerHTML">
|
<form hx-post="/decrypt" hx-target="#decryptResult" hx-swap="innerHTML">
|
||||||
@ -52,13 +58,17 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<textarea id="payload" name="payload" placeholder='{"ek":"...","n":"...","ct":"..."}'></textarea>
|
<textarea id="payload" name="payload" placeholder='{"ek":"...","n":"...","ct":"..."}'></textarea>
|
||||||
<button type="button" class="secondary" onclick="copyEl('payload')">Copy</button>
|
<button type="button" class="secondary" onclick="copyEl('payload')">Copy</button>
|
||||||
|
<button type="button" class="secondary" onclick="clearEl('payload')">Clear</button>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="primary">Decrypt</button>
|
<button type="submit" class="primary">Decrypt</button>
|
||||||
</form>
|
</form>
|
||||||
<div id="decryptResult" class="result"></div>
|
<div id="decryptResult" class="result"></div>
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
<div id="toast">Zkopírováno</div>
|
<div id="toast">Zkopírováno</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function showToast(msg='Zkopírováno') {
|
function showToast(msg='Zkopírováno') {
|
||||||
const t = document.getElementById('toast');
|
const t = document.getElementById('toast');
|
||||||
@ -66,18 +76,57 @@
|
|||||||
t.classList.add('show');
|
t.classList.add('show');
|
||||||
setTimeout(() => t.classList.remove('show'), 1200);
|
setTimeout(() => t.classList.remove('show'), 1200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function copyText(text) {
|
||||||
|
try {
|
||||||
|
if (navigator.clipboard && window.isSecureContext) {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
} else {
|
||||||
|
const ta = document.createElement('textarea');
|
||||||
|
ta.value = text;
|
||||||
|
ta.style.position = 'fixed';
|
||||||
|
ta.style.left = '-9999px';
|
||||||
|
document.body.appendChild(ta);
|
||||||
|
ta.focus();
|
||||||
|
ta.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(ta);
|
||||||
|
}
|
||||||
|
showToast();
|
||||||
|
} catch (e) {
|
||||||
|
console.error('copyText error:', e);
|
||||||
|
alert('Nepodařilo se zkopírovat do schránky.\n' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function copyEl(id) {
|
async function copyEl(id) {
|
||||||
const el = document.getElementById(id);
|
const el = document.getElementById(id);
|
||||||
const val = (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT') ? el.value : el.textContent;
|
const val = (el && (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT'))
|
||||||
await navigator.clipboard.writeText(val || '');
|
? el.value
|
||||||
showToast();
|
: (el?.textContent ?? '');
|
||||||
|
await copyText(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyFromUrl(url) {
|
async function copyFromUrl(url) {
|
||||||
const res = await fetch(url);
|
try {
|
||||||
|
const res = await fetch(url, {cache: 'no-store'});
|
||||||
|
if (!res.ok) throw new Error('HTTP ' + res.status);
|
||||||
const text = await res.text();
|
const text = await res.text();
|
||||||
await navigator.clipboard.writeText(text);
|
await copyText(text);
|
||||||
showToast();
|
} catch (e) {
|
||||||
|
console.error('copyFromUrl error:', e);
|
||||||
|
alert('Nepodařilo se načíst obsah ke zkopírování.\n' + e);
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
|
||||||
|
function clearEl(id) {
|
||||||
|
const el = document.getElementById(id);
|
||||||
|
if (el && (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT')) {
|
||||||
|
el.value = '';
|
||||||
|
} else if (el) {
|
||||||
|
el.textContent = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user