Restore from Gitea ZIP snapshot (12.08.2026) after full instance reinstall

Git history was lost when the previous Gitea instance was wiped and
reinstalled due to an unresolved corruption bug — this commit is the
last known-good file content, exported before the reinstall. Prior
commit history is not recoverable through this path.
This commit is contained in:
Claude Sonnet 5
2026-08-12 19:24:03 +00:00
commit 52ca317e9c
138 changed files with 24016 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
// Web Push service worker. Deliberately minimal — no offline caching, no
// asset interception. Its only job is to keep receiving push events even
// when the page's own tab is frozen or closed, and turn them into an OS
// notification.
self.addEventListener("push", (event) => {
let payload = { title: "top-tickets", body: "", url: "/dashboard" };
try {
if (event.data) payload = { ...payload, ...event.data.json() };
} catch {
// malformed payload — fall back to the generic notification above
}
event.waitUntil(
self.registration.showNotification(payload.title, {
body: payload.body,
icon: "/icon.svg",
data: { url: payload.url },
}),
);
});
self.addEventListener("notificationclick", (event) => {
event.notification.close();
const url = event.notification.data && event.notification.data.url ? event.notification.data.url : "/dashboard";
event.waitUntil(
(async () => {
const clientsList = await self.clients.matchAll({ type: "window", includeUncontrolled: true });
const existing = clientsList.find((c) => "focus" in c);
if (existing) {
await existing.navigate(url);
await existing.focus();
return;
}
await self.clients.openWindow(url);
})(),
);
});
+78
View File
@@ -0,0 +1,78 @@
(function () {
var scriptEl = document.currentScript;
if (!scriptEl) return;
var siteKey = scriptEl.getAttribute("data-key");
if (!siteKey) {
console.error("[top-tickets widget] missing data-key attribute");
return;
}
var origin = new URL(scriptEl.src).origin;
var open = false;
var button = document.createElement("button");
button.setAttribute("aria-label", "Открыть чат поддержки");
button.style.cssText = [
"position:fixed", "right:20px", "bottom:20px", "z-index:2147483000",
"width:56px", "height:56px", "border-radius:999px", "border:none",
"background:#7c3aed", "color:#fff", "cursor:pointer",
"box-shadow:0 6px 20px rgba(0,0,0,.25)",
"display:flex", "align-items:center", "justify-content:center",
"font-family:system-ui,sans-serif",
].join(";");
button.innerHTML =
'<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>';
var badge = document.createElement("span");
badge.style.cssText = [
"position:absolute", "top:-2px", "right:-2px", "width:12px", "height:12px",
"border-radius:999px", "background:#dc2626", "border:2px solid #fff",
"display:none",
].join(";");
button.style.position = "fixed";
button.appendChild(badge);
var panel = document.createElement("div");
var isMobile = window.innerWidth < 480;
panel.style.cssText = [
"position:fixed",
isMobile ? "right:0" : "right:20px",
isMobile ? "bottom:0" : "bottom:88px",
isMobile ? "width:100vw" : "width:360px",
isMobile ? "height:100vh" : "height:520px",
"max-height:80vh",
"border-radius:" + (isMobile ? "0" : "16px"),
"overflow:hidden",
"box-shadow:0 12px 40px rgba(0,0,0,.3)",
"z-index:2147483000",
"display:none",
].join(";");
var iframe = document.createElement("iframe");
iframe.src = origin + "/widget/chat?key=" + encodeURIComponent(siteKey);
iframe.style.cssText = "width:100%;height:100%;border:none;";
panel.appendChild(iframe);
function setOpen(next) {
open = next;
panel.style.display = open ? "block" : "none";
if (open) {
badge.style.display = "none";
}
}
button.addEventListener("click", function () {
setOpen(!open);
});
window.addEventListener("message", function (event) {
if (event.origin !== origin) return;
if (event.data && event.data.type === "top-tickets:new-message" && !open) {
badge.style.display = "block";
}
});
document.body.appendChild(panel);
document.body.appendChild(button);
})();