This commit is contained in:
2026-02-23 12:58:38 +01:00
parent 1375a4dd09
commit 273859902d
9 changed files with 332 additions and 9 deletions

156
ai-chat.js Normal file
View File

@@ -0,0 +1,156 @@
(() => {
const introMessage =
"Witaj, jestem twoim wirtualnym agentem Krzak.org, w czym mogę Ci pomóc?";
const baseReplies = [
"Niestety, nie umiem jeszcze tego zrobić",
"Nie jestem pewien o co Ci chodzi",
];
const offerFrom = [
"pedałów",
"pajaca",
"noży",
"gwoździ",
"przypraw",
"słoika",
"słoików",
"tabletek",
"spreju",
"narzędzi",
"samolotu",
"osrtzałki",
"szafki",
"pojemnika",
"pojemników",
"ładowarki",
"ładowarek",
"wieszaków",
"wieszaka",
"półki",
"półek",
];
const offerTo = [
"gwoździ",
"roweru",
"krojenia cebuli",
"pedałów",
"latania",
"łatania",
"podatków",
"sprzątania",
"wyrywania zębów",
"zmywarki",
"śmieci",
"krojenia chleba",
"krojenia ogórków",
"krojenia pomidorów",
"krojenia cebuli",
"krojenia ogórków",
"krojenia pomidorów",
"jedzenia",
"picia",
"kuchni",
"książek",
];
const chatRoot = document.createElement("div");
chatRoot.className = "ai-chat";
chatRoot.innerHTML = `
<button class="ai-chat__fab" type="button" aria-expanded="false" aria-controls="ai-chat-panel">AI chat</button>
<section class="ai-chat__panel" id="ai-chat-panel" aria-hidden="true">
<header class="ai-chat__header">
<strong>Agent Krzak.org</strong>
<button class="ai-chat__close" type="button" aria-label="Close chat">x</button>
</header>
<div class="ai-chat__messages"></div>
<form class="ai-chat__form">
<input class="ai-chat__input" type="text" placeholder="Napisz wiadomość..." autocomplete="off" />
<button class="ai-chat__send" type="submit">Wyslij</button>
</form>
</section>
`;
document.body.appendChild(chatRoot);
const fab = chatRoot.querySelector(".ai-chat__fab");
const panel = chatRoot.querySelector(".ai-chat__panel");
const closeBtn = chatRoot.querySelector(".ai-chat__close");
const messages = chatRoot.querySelector(".ai-chat__messages");
const form = chatRoot.querySelector(".ai-chat__form");
const input = chatRoot.querySelector(".ai-chat__input");
const backToTop = document.getElementById("back-to-top");
function addMessage(text, fromUser) {
const bubble = document.createElement("p");
bubble.className = fromUser
? "ai-chat__bubble ai-chat__bubble--user"
: "ai-chat__bubble";
bubble.textContent = text;
messages.appendChild(bubble);
messages.scrollTop = messages.scrollHeight;
}
function openChat() {
panel.classList.add("is-open");
panel.setAttribute("aria-hidden", "false");
fab.setAttribute("aria-expanded", "true");
if (!messages.hasChildNodes()) {
addMessage(introMessage, false);
}
input.focus();
}
function closeChat() {
panel.classList.remove("is-open");
panel.setAttribute("aria-hidden", "true");
fab.setAttribute("aria-expanded", "false");
}
function randomItem(items) {
return items[Math.floor(Math.random() * items.length)];
}
function buildReply() {
return `${randomItem(baseReplies)}, ale mogę Ci zaoferować kupno ${randomItem(offerFrom)} do ${randomItem(offerTo)}.`;
}
function syncChatPosition() {
if (!backToTop) {
chatRoot.classList.remove("ai-chat--raised");
return;
}
chatRoot.classList.toggle(
"ai-chat--raised",
backToTop.classList.contains("visible"),
);
}
fab.addEventListener("click", () => {
if (panel.classList.contains("is-open")) {
closeChat();
return;
}
openChat();
});
closeBtn.addEventListener("click", closeChat);
form.addEventListener("submit", (event) => {
event.preventDefault();
const text = input.value.trim();
if (!text) {
return;
}
addMessage(text, true);
addMessage(buildReply(), false);
input.value = "";
});
if (backToTop) {
const observer = new MutationObserver(syncChatPosition);
observer.observe(backToTop, {
attributes: true,
attributeFilter: ["class"],
});
window.addEventListener("resize", syncChatPosition);
}
syncChatPosition();
})();

View File

@@ -197,5 +197,6 @@
<script src="/refresh.js"></script>
<script src="/animations.js"></script>
<script src="/ai-chat.js"></script>
</body>
</html>

View File

@@ -121,6 +121,7 @@
<script src="/refresh.js"></script>
<script src="/animations.js"></script>
<script src="/ai-chat.js"></script>
</div>
</body>
</html>

View File

@@ -97,5 +97,6 @@
<script src="/refresh.js"></script>
<script src="/animations.js"></script>
<script src="/ai-chat.js"></script>
</body>
</html>

View File

@@ -22,6 +22,7 @@
</p>
<script src="/refresh.js"></script>
<script src="/animations.js"></script>
<script src="/ai-chat.js"></script>
</div>
</body>
</html>

View File

@@ -85,7 +85,10 @@
</a>
</li>
<li class="slide-up" style="animation-delay: 0.15s">
<a href="https://discord.gg/CY3Zr6baD7" class="discord-link">
<a
href="https://discord.gg/CY3Zr6baD7"
class="discord-link"
>
<strong>Discord</strong>
<span>discord.gg/CY3Zr6baD7</span>
</a>
@@ -121,6 +124,7 @@
<script src="/refresh.js"></script>
<script src="/animations.js"></script>
<script src="/ai-chat.js"></script>
</div>
</body>
</html>

View File

@@ -167,23 +167,17 @@
</a>
</li>
<li class="slide-up" style="animation-delay: 0.8s">
<a href="/mc.html">
<strong>Minecraft Server</strong>
<span>Fabric 1.21.10</span>
</a>
</li>
<li class="slide-up" style="animation-delay: 0.85s">
<a href="/contact.html">
<strong>Contact</strong>
</a>
</li>
</ul>
<p class="fade-in" style="animation-delay: 0.9s">
<p class="fade-in" style="animation-delay: 0.85s">
If you want an account on any of these, want to suggest
something new or get a subdomain, just message me
</p>
<div class="librecounter fade-in" style="animation-delay: 0.95s">
<div class="librecounter fade-in" style="animation-delay: 0.9s">
<span class="librecounter-text">
Indexed by
<a
@@ -226,5 +220,6 @@
<script src="/refresh.js"></script>
<script src="/animations.js"></script>
<script src="/ai-chat.js"></script>
</body>
</html>

View File

@@ -504,6 +504,7 @@
<script src="/refresh.js"></script>
<script src="/animations.js"></script>
<script src="/ai-chat.js"></script>
<script>
// Configuration
const SERVER_ADDRESS = "krzak.org";

View File

@@ -876,3 +876,166 @@ li a span {
position: relative;
z-index: 1;
}
/* Floating AI chat joke widget */
.ai-chat {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 1100;
transition: bottom 0.25s ease;
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
"Helvetica Neue",
Arial,
sans-serif;
}
.ai-chat.ai-chat--raised {
bottom: 96px;
}
.ai-chat__fab {
border: 1px solid var(--accent-color);
background: rgba(26, 16, 60, 0.92);
color: var(--text-color);
border-radius: 999px;
height: 52px;
min-width: 110px;
padding: 0 18px;
font-weight: 700;
cursor: pointer;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}
.ai-chat__fab:hover {
box-shadow: 0 0 18px var(--accent-glow);
}
.ai-chat__panel {
position: absolute;
right: 0;
bottom: 64px;
width: min(90vw, 340px);
background: rgba(30, 20, 60, 0.92);
border: 1px solid var(--container-border);
border-radius: 16px;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
display: none;
overflow: hidden;
}
.ai-chat__panel.is-open {
display: block;
}
.ai-chat__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 14px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
color: var(--accent-color);
}
.ai-chat__close {
border: 0;
background: transparent;
color: var(--text-muted);
cursor: pointer;
font-size: 1rem;
font-weight: 700;
}
.ai-chat__messages {
max-height: 300px;
overflow-y: auto;
padding: 12px;
display: flex;
flex-direction: column;
gap: 8px;
}
.ai-chat__bubble {
margin: 0;
padding: 10px 12px;
border-radius: 12px;
background: rgba(255, 255, 255, 0.08);
color: var(--text-color);
font-size: 0.92rem;
line-height: 1.35;
text-align: left;
}
.ai-chat__bubble--user {
background: rgba(244, 162, 97, 0.2);
border: 1px solid rgba(244, 162, 97, 0.35);
}
.ai-chat__form {
display: flex;
gap: 8px;
padding: 12px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.ai-chat__input {
flex: 1;
min-width: 0;
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.15);
background: rgba(255, 255, 255, 0.05);
color: var(--text-color);
padding: 10px;
}
.ai-chat__input::placeholder {
color: var(--text-muted);
}
.ai-chat__send {
border: 1px solid var(--accent-color);
background: var(--accent-color);
color: #1a103c;
border-radius: 10px;
padding: 10px 12px;
font-weight: 700;
cursor: pointer;
}
@media (max-width: 600px) {
.ai-chat {
right: 14px;
bottom: 14px;
}
.ai-chat.ai-chat--raised {
bottom: 82px;
}
.ai-chat__panel {
position: fixed;
inset: 0;
width: 100vw;
max-width: none;
border-radius: 0;
bottom: 0;
right: 0;
}
.ai-chat__panel.is-open {
display: flex;
flex-direction: column;
}
.ai-chat__messages {
flex: 1;
max-height: none;
}
}