From eef8c4ec57d285bc062028824b74e7fc22c28985 Mon Sep 17 00:00:00 2001 From: Sergey Antropoff Date: Wed, 29 Jul 2026 21:03:51 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20create=20UI,=20PWA-=D0=B8=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D0=BA=D0=B8,=20tooltip=20A2HS=20=D0=B8=20breakpoint=20?= =?UTF-8?q?=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD-=D0=BC=D0=B5=D0=BD=D1=8E=201015p?= =?UTF-8?q?x.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- app/static/apple-touch-icon.png | Bin 2256 -> 2178 bytes app/static/css/app.css | 72 +++++++++++++++---------------- app/static/icon-192.png | Bin 0 -> 2338 bytes app/static/icon-512.png | Bin 0 -> 5687 bytes app/static/js/admin-nav.js | 2 +- app/static/js/create.js | 74 ++++++++------------------------ app/static/manifest.webmanifest | 24 +++++++++-- app/templates/create.html | 12 +++--- 9 files changed, 80 insertions(+), 106 deletions(-) create mode 100644 app/static/icon-192.png create mode 100644 app/static/icon-512.png diff --git a/README.md b/README.md index fca2166..da255d7 100644 --- a/README.md +++ b/README.md @@ -341,7 +341,7 @@ services: ### UX (v0.1.3+) - После создания: **QR** на share-link, иконки **скачать QR (PNG)** и **Web Share** (если есть `navigator.share`) под QR; отдельные кнопки Copy для ссылки / токена / пароля; пароль не советуется слать в той же переписке. -- Create: счётчик размера `≈ used / max`; **число открытий** 1–3 (потолок в админке); опционально **«доступно с»** (дата+время); человеческие TTL (в т.ч. «до вечера»); шаблоны текста; подписи элементов пакета. +- Create: счётчик размера `≈ used / max`; **число открытий** 1–3 (потолок в админке); опционально **«доступно с»** (дата + время); человеческие TTL (в т.ч. «до вечера»). - Unwrap: Enter в поле пароля; focus+select при ошибках пароля; zip all; trust-строка; экран **ещё недоступно** до `available_from`; при N>1 ciphertext остаётся до последнего открытия. - Картинки: lightbox. Тема: `prefers-color-scheme` при первом визите; haptic на Copy. PWA manifest + кнопка **На экран Домой** (Chrome install / iOS подсказка). - Страница [`/verify`](/verify) — как проверить ZK-модель. diff --git a/app/static/apple-touch-icon.png b/app/static/apple-touch-icon.png index b4a1fa6392765661b97caa71acfc2e886ea4c797..4a030b098d8481e2c6332b8e97cfa4924754eabd 100644 GIT binary patch delta 2165 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 SkOa*D0000 .brand { flex: 0 0 auto; } diff --git a/app/static/icon-192.png b/app/static/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..4dad87b719da108e3f2463aedc4b5d91051df876 GIT binary patch literal 2338 zcmV+-3ElRIP)&xCDuK<@x=5#Ah_$V zul1A#Qn{1s9ujsJU0Qo{T~QE5_fg!+mZ7d`3^P`ei(EmVi82T@y2n&5A&`p z3tt4GZ@6*%7U4%~Tv_&(m)Ihh@FQ))X0qz4*+lq}VwbC&399rug*4M^fO4I}sH{~=EQ>gC>43*^V2&B!)f+h}|rl+-QP0@3~?YpAZV;NQb} z|E?YEGq6W;m3})kVh?_~pP>*EEdb_#xD3@bguGq;tkAD=ZeSqs$94&eV2eUu zX+J22>Sc1*LlMkiLpp+At{Ce2DTJUh9xYHs0}XYFKHj`nUsIF6{-UKw>-z^a?UkEo zfl?Iw*+t-sQV99afkG&b0!UHllPClq#V~_4z*7T_=?Z?SLeM%Z^ic?+*8u&EwaP}? zW`)L?qHpLMQWA-5fou(aT!oN-Or#Zpm;!Jm^hp(hlw!!Z{#oGuEt{1TI@bvWv%+`7 z%2gQ`p< z=f52q33y^}hL`~$8fySVW^;y^0U#P{07PeThL`~$8fySVW^;ykB^Vmmn<3r|hv+QM z5NiO4#^(VLnavqu27qWa+5XMqZENo>)5lP>t^V;(K@P%h%m5Ir#_!*3|I^fa+w^f1 zsj2t2@pB*b4>JHnvwjVb+nO#h3+OT#;8&z(k9P{rd(@3rf)SD%xvBA=hAZ2)OLt5k zPZ6X4wo7-6pKDzkYXFE=lYK9@L)*5CBc_k3+oS)*5##4r=f(^G(VSWX9Sb&vGy;&dvbM7w($g1*bGSdOZ0|uyB(BM}JpyQe%D@65rNx zVbt{Tbt3#N+2iOrxjEYc0ixavS88kNVHSuq`uB_)KZmit8P0!CG*F7``4G_pZSNT~ zy$e>3{@Vo{HxUH@DCxf`zO{Qyb+@ii(ghv;Tf4`m`eeuPff$q^BNw7tpw{ktO0wXi z|2-vzr~&|H%XkjH!Ks|Ku5s1XwoFMAbo6iQ8W+*~i=F|pCmC}{JT4*&K-$R;GWxd( zIv)AB3go!J@AX$Qb0Fq*fMRx>zpu{kSgNFlf5-XzqWb=PVq2hslP^8|f{8Bx7ehe! zgLC==G1Y84&OcDH!tXy{^T*xvCVCAp+s<Pg6V&QN-{FugN zP*ImUeVp%n%m78~Joiw!7=D|cS5jC5l(6gULv?o7V&zKs{pUm9KNmAVrO>z%eiX%J z&9JWO#8Toc7aG zVLRQv$awg3`@*@b9xYHr)8R86euR<{! z{z%8`00!hjo?i$A-{4gs(><8fZST|2`+u9>7f;|eGXt;!FlO&p6C8hoa)qEi_~v&` z1H|~^y_da$HNbQw0D|yJFhrZV3dCnfA$bP)eCtb807S^odco@eQ~;!zllc$7{)4MQ zaMovAU-Zhq5={Id2v>n1TG6)uqh8t|xaVY3Vf$0&&2TJ-A-DxP+4KSx0H>77bm_N4 z(*!|)vLpSzOMg-Zu-=Jn&wHV+0+qWVV1r5-<}xTm3pB#-yZ9Ha5Ug{e`MHYu4&37G zrwCw?;{n27RSOjK4gu4u$tr6Ah*tHezW>4`tq@Y{c+0%1G99X|IY1F0g^pDj{?IK@ zmIs?pVvSp>rI0BtOtY5x|^d+rx+7r=^uSND;t*qY=aJ)7r}) z?D>a6K{`b?}DO{{095Rj(e=On&pJ=8@ZptK`x$pk;g=vAAKyZ)mXpbocXe_O8+skm%O zA;@&tVDNK{??5pWgqsehAn>!LZih07*qo IM6N<$f*ibaxBvhE literal 0 HcmV?d00001 diff --git a/app/static/icon-512.png b/app/static/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..12df585c002e0fc9ff60abf8ff19575f4b7b0e89 GIT binary patch literal 5687 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 { const open = top.classList.contains("is-nav-open"); diff --git a/app/static/js/create.js b/app/static/js/create.js index ff6d3b9..6cfa0de 100644 --- a/app/static/js/create.js +++ b/app/static/js/create.js @@ -1,14 +1,12 @@ (() => { const t = (k, vars) => window.WrappedI18n.t(k, vars); - /** @type {{ file: File, label: string }[]} */ + /** @type {File[]} */ const files = []; let settings = null; let captchaWidgetId = null; const els = { text: document.getElementById("payload-text"), - textLabel: document.getElementById("text-label"), - templateChips: document.getElementById("template-chips"), lang: document.getElementById("text-language"), langChip: document.getElementById("lang-chip"), langChipText: document.getElementById("lang-chip-text"), @@ -18,7 +16,8 @@ editor: document.getElementById("code-editor"), ttl: document.getElementById("ttl-seconds"), maxOpens: document.getElementById("max-opens"), - availableFrom: document.getElementById("available-from"), + availableFromDate: document.getElementById("available-from-date"), + availableFromTime: document.getElementById("available-from-time"), password: document.getElementById("password"), generatePassword: document.getElementById("generate-password"), dropzone: document.getElementById("dropzone"), @@ -114,7 +113,7 @@ function estimatePayloadBytes() { const textBytes = new TextEncoder().encode(els.text?.value || "").length; - const fileBytes = files.reduce((sum, entry) => sum + (Number(entry.file.size) || 0), 0); + const fileBytes = files.reduce((sum, f) => sum + (Number(f.size) || 0), 0); return textBytes + fileBytes; } @@ -142,21 +141,9 @@ function renderFiles() { els.fileList.innerHTML = ""; - files.forEach((entry, idx) => { - const f = entry.file; + files.forEach((f, idx) => { const li = document.createElement("li"); - li.className = "file-list-item"; - const meta = document.createElement("span"); - meta.innerHTML = `${escapeHtml(f.name)} (${escapeHtml(f.type || "file")} · ${window.WrappedUI.formatBytes(f.size)})`; - const labelInput = document.createElement("input"); - labelInput.type = "text"; - labelInput.className = "file-label-input"; - labelInput.maxLength = 120; - labelInput.placeholder = t("create.itemLabelPlaceholder"); - labelInput.value = entry.label || ""; - labelInput.addEventListener("input", () => { - entry.label = labelInput.value; - }); + li.innerHTML = `${escapeHtml(f.name)} (${escapeHtml(f.type || "file")} · ${window.WrappedUI.formatBytes(f.size)})`; const btn = document.createElement("button"); btn.type = "button"; btn.textContent = "×"; @@ -164,8 +151,6 @@ files.splice(idx, 1); renderFiles(); }); - li.appendChild(meta); - li.appendChild(labelInput); li.appendChild(btn); els.fileList.appendChild(li); }); @@ -186,7 +171,7 @@ showError(t("create.mimeDenied") + `: ${f.type || f.name}`); continue; } - files.push({ file: f, label: "" }); + files.push(f); } renderFiles(); } @@ -245,31 +230,11 @@ .join(""); } - function renderTemplates() { - if (!els.templateChips) return; - els.templateChips.innerHTML = ""; - const keys = [ - { id: "access", key: "create.tpl.access" }, - { id: "code", key: "create.tpl.code" }, - { id: "fileNote", key: "create.tpl.fileNote" }, - ]; - for (const item of keys) { - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "template-chip"; - btn.textContent = t(`create.tpl.${item.id}.name`); - btn.addEventListener("click", () => { - els.text.value = t(`create.tpl.${item.id}.body`); - refreshHighlight(); - refreshSizeMeter(); - }); - els.templateChips.appendChild(btn); - } - } - - function datetimeLocalToIso(value) { - if (!value) return null; - const d = new Date(value); + function availableFromToIso() { + const date = (els.availableFromDate?.value || "").trim(); + if (!date) return null; + const time = (els.availableFromTime?.value || "").trim() || "00:00"; + const d = new Date(`${date}T${time}`); if (Number.isNaN(d.getTime())) return null; return d.toISOString(); } @@ -351,7 +316,6 @@ settings = await resp.json(); fillTtl(); fillMaxOpens(); - renderTemplates(); loadCaptcha(); setLanguage("plaintext", { silent: true }); refreshHighlight(); @@ -525,18 +489,15 @@ const items = []; const contentTypes = []; if (text.trim()) { - const textItem = { + items.push({ type: "text", language: els.lang.value, content: text, - }; - const label = (els.textLabel?.value || "").trim(); - if (label) textItem.label = label.slice(0, 120); - items.push(textItem); + }); contentTypes.push("text/plain"); } - for (const entry of files) { - const item = await window.WrappedCrypto.fileToItem(entry.file, entry.label); + for (const f of files) { + const item = await window.WrappedCrypto.fileToItem(f); items.push(item); contentTypes.push(item.mime); } @@ -550,7 +511,7 @@ const password = els.password.value || ""; const maxOpens = Number(els.maxOpens?.value || 1); - const availableFromIso = datetimeLocalToIso(els.availableFrom?.value || ""); + const availableFromIso = availableFromToIso(); els.wrapBtn.disabled = true; window.WrappedUI.showBusy(t("create.working")); try { @@ -638,7 +599,6 @@ window.WrappedI18n.onChange(() => { fillTtl(); fillMaxOpens(); - renderTemplates(); refreshExpiresMeta(); refreshSuccessBadges(); refreshSizeMeter(); diff --git a/app/static/manifest.webmanifest b/app/static/manifest.webmanifest index 081ab98..4297c7b 100644 --- a/app/static/manifest.webmanifest +++ b/app/static/manifest.webmanifest @@ -8,10 +8,28 @@ "theme_color": "#0b1020", "icons": [ { - "src": "/static/favicon.svg", - "sizes": "any", - "type": "image/svg+xml", + "src": "/static/icon-192.png", + "sizes": "192x192", + "type": "image/png", "purpose": "any" + }, + { + "src": "/static/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/static/icon-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/static/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" } ] } diff --git a/app/templates/create.html b/app/templates/create.html index 5afa02e..9fa7480 100644 --- a/app/templates/create.html +++ b/app/templates/create.html @@ -14,11 +14,6 @@ -
-
- - -
@@ -43,8 +38,11 @@
- - + Available from (optional) +
+ + +

Empty = available immediately