Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions src/_includes/system-log.njk
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
<button id="reopen-console-btn" onclick="reopenConsole()" class="fixed bottom-6 right-6 p-3 bg-black/80 border border-green-500/30 rounded-full text-green-500 hover:scale-110 transition-all z-[999]" title="Open System Log">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
</button>
<div id="matrix-console-container" class="fixed bottom-6 right-6 w-80 z-[1000] transition-all duration-300 ease-in-out hidden"
style="opacity: 0; transform: translateY(20px);">
<div id="matrix-console-container" class="fixed bottom-6 right-6 w-80 z-[1000] transition-all duration-300 ease-in-out hidden" style="opacity: 0; transform: translateY(20px);">
<div class="bg-black/90 backdrop-blur-xl border border-green-500/30 rounded-t-lg overflow-hidden shadow-2xl">

<div class="bg-green-500/10 border-b border-green-500/30 px-3 py-2 flex justify-between items-center cursor-grab select-none">
<div class="flex items-center gap-2">
<span class="text-[10px] font-mono text-green-500 uppercase tracking-widest opacity-70">System_Log</span>
</div>

<div class="flex gap-2">
<button onclick="minimizeConsole()" class="w-3 h-3 rounded-full bg-yellow-500/20 border border-yellow-500/50 hover:bg-yellow-500/50 transition-colors" title="Minimize"></button>
<button onclick="maximizeConsole()" class="w-3 h-3 rounded-full bg-green-500/20 border border-green-500/50 hover:bg-green-500/50 transition-colors" title="Maximize"></button>
<button onclick="closeConsole()" class="w-3 h-3 rounded-full bg-red-500/20 border border-red-500/50 hover:bg-red-500/50 transition-colors" title="Close"></button>
</div>
</div>

<div id="matrix-console-output" class="h-48 p-3 overflow-y-auto font-mono text-[11px] leading-tight">
<p class="text-green-500/40">// Terminal link established...</p>
</div>
</div>

<div class="resize-handle resize-handle-n" style="position:absolute;top:-3px;left:8px;right:8px;height:6px;cursor:n-resize;z-index:1;"></div>
<div class="resize-handle resize-handle-s" style="position:absolute;bottom:-3px;left:8px;right:8px;height:6px;cursor:s-resize;z-index:1;"></div>
<div class="resize-handle resize-handle-e" style="position:absolute;right:-3px;top:8px;bottom:8px;width:6px;cursor:e-resize;z-index:1;"></div>
<div class="resize-handle resize-handle-w" style="position:absolute;left:-3px;top:8px;bottom:8px;width:6px;cursor:w-resize;z-index:1;"></div>
<div class="resize-handle resize-handle-ne" style="position:absolute;top:-4px;right:-4px;width:10px;height:10px;cursor:ne-resize;z-index:2;"></div>
<div class="resize-handle resize-handle-nw" style="position:absolute;top:-4px;left:-4px;width:10px;height:10px;cursor:nw-resize;z-index:2;"></div>
<div class="resize-handle resize-handle-se" style="position:absolute;bottom:-4px;right:-4px;width:10px;height:10px;cursor:se-resize;z-index:2;"></div>
<div class="resize-handle resize-handle-sw" style="position:absolute;bottom:-4px;left:-4px;width:10px;height:10px;cursor:sw-resize;z-index:2;"></div>
</div>
133 changes: 106 additions & 27 deletions src/assets/js/script.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
// Variables
let isResizing = false;
let resizeDirection = "";
let resizeStartX = 0;
let resizeStartY = 0;
let resizeStartWidth = 0;
let resizeStartOutputHeight = 0;
let resizeStartLeft = 0;
let resizeStartTop = 0;
// Load saved level or start at 0
let currentLevel = Number(localStorage.getItem("userLevel")) || 0;

// Load saved XP or start at 0
let currentXP = parseInt(localStorage.getItem("userXP")) || 0;

let isSurging = false;

let audioCtx;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uninitialized `audioCtx` declaration delays initialization


The variable audioCtx is declared without being initialized, which can make the code less clear and increase the risk of using it before assignment. Uninitialized variables can cause unexpected runtime errors or logic bugs if accessed prematurely.
Initialize variables like audioCtx at the time of declaration to improve code clarity and reduce the chance of accidental misuse.


let unlockedEggs = JSON.parse(localStorage.getItem("unlockedEggs")) || [];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use `const` for variables never reassigned


The variable unlockedEggs is assigned once and never reassigned, so declaring it with let is misleading and allows accidental reassignments that can introduce bugs. Using const signals the variable's value is fixed after initialization, improving code clarity and safety.

Replace let with const for unlockedEggs to prevent unintended reassignment and clearly indicate its intended immutability.

let surpriseClickCount = 0;
let matrixActive = false;
let destructInterval;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uninitialized `let` declaration risks undefined usage


Declaring destructInterval with let without initializing it means it holds an undefined value until explicitly assigned. Accessing it before assignment can cause runtime errors or logic issues.

Initialize destructInterval during declaration with an appropriate default value to ensure defined behavior and prevent undefined usage.


let isDragging = false;
let offsetLeft = 0;
let offsetTop = 0;

// Const Variables
const MIN_CONSOLE_WIDTH = 200;
const MIN_OUTPUT_HEIGHT = 50;
const XP_PER_LEVEL = 45;

// XP rewards for events and secrets
Expand All @@ -13,13 +44,6 @@ const XP_FOOTER_SURGE = 1000; // Footer surge secret
const XP_BADGE_CLICK = 45; // Badge click reward

const NUM_LEVELS = LEVELS.length;
// Load saved level or start at 0
let currentLevel = Number(localStorage.getItem("userLevel")) || 0;

// Load saved XP or start at 0
let currentXP = parseInt(localStorage.getItem("userXP")) || 0;

let isSurging = false;

function getContrastYIQ(hexcolor) {
hexcolor = hexcolor.replace("#", "");
Expand All @@ -29,11 +53,10 @@ function getContrastYIQ(hexcolor) {
var yiq = (r * 299 + g * 587 + b * 114) / 1000;
return yiq >= 128 ? "black" : "white";
}

/**
* 1. RETRO SOUND ENGINE
*/
let audioCtx;

function initAudio() {
try {
if (!audioCtx) {
Expand Down Expand Up @@ -104,11 +127,6 @@ function playSound(type) {
}
}

let unlockedEggs = JSON.parse(localStorage.getItem("unlockedEggs")) || [];
let surpriseClickCount = 0;
let matrixActive = false;
let destructInterval;

function getRank(lvl) {
const numericLevel = Number(lvl) || 0;

Expand All @@ -132,10 +150,6 @@ const consoleOutput = document.getElementById("matrix-console-output");
const dragContainer = document.getElementById("matrix-console-container");
const dragHeader = dragContainer.querySelector(".bg-green-500\\/10"); // Selects the header bar

let isDragging = false;
let offsetLeft = 0;
let offsetTop = 0;

dragHeader.addEventListener("mousedown", (e) => {
// Prevent dragging when clicking the minimize/close buttons
if (e.target.tagName === "BUTTON") return;
Expand All @@ -154,15 +168,12 @@ dragHeader.addEventListener("mousedown", (e) => {
document.addEventListener("mousemove", (e) => {
if (!isDragging) return;

// Calculate new position
let x = e.clientX - offsetLeft;
let y = e.clientY - offsetTop;

// Boundary Check (Optional: keeps it inside the screen)
x = Math.max(0, Math.min(x, window.innerWidth - dragContainer.offsetWidth));
y = Math.max(0, Math.min(y, window.innerHeight - dragContainer.offsetHeight));

// Apply position and remove Tailwind's 'bottom' and 'right' so they don't fight the 'top'/'left'
dragContainer.style.bottom = "auto";
dragContainer.style.right = "auto";
dragContainer.style.left = `${x}px`;
Expand All @@ -174,8 +185,81 @@ document.addEventListener("mouseup", () => {
dragHeader.style.cursor = "grab";
});

dragContainer.querySelectorAll(".resize-handle").forEach((handle) => {
handle.addEventListener("mousedown", (e) => {
e.preventDefault();
e.stopPropagation();

isResizing = true;

resizeDirection =
[...handle.classList]
.find((c) => c.startsWith("resize-handle-") && c !== "resize-handle")
?.replace("resize-handle-", "") || "se";

const rect = dragContainer.getBoundingClientRect();
resizeStartX = e.clientX;
resizeStartY = e.clientY;
resizeStartWidth = rect.width;
resizeStartLeft = rect.left;
resizeStartTop = rect.top;
resizeStartOutputHeight = consoleOutput.offsetHeight;

dragContainer.style.bottom = "auto";
dragContainer.style.right = "auto";
dragContainer.style.left = `${rect.left}px`;
dragContainer.style.top = `${rect.top}px`;

dragContainer.classList.remove(
"transition-all",
"duration-300",
"ease-in-out",
);
document.body.style.userSelect = "none";
document.body.style.cursor = handle.style.cursor;
});
});

document.addEventListener("mousemove", (e) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function with high cyclomatic complexity is hard to understand


The event listener function for the 'mousemove' event on document likely contains multiple branches or conditions increasing cyclomatic complexity. This complexity can introduce bugs and make the logic challenging to follow or extend.

Refactor the function by splitting complex logic into smaller functions, and reduce nested conditional statements to simplify the flow.

if (!isResizing) return;

const dx = e.clientX - resizeStartX;
const dy = e.clientY - resizeStartY;
const dir = resizeDirection;

if (dir.includes("e")) {
dragContainer.style.width = `${Math.max(MIN_CONSOLE_WIDTH, resizeStartWidth + dx)}px`;
}
if (dir.includes("w")) {
const newW = resizeStartWidth - dx;
if (newW >= MIN_CONSOLE_WIDTH) {
dragContainer.style.width = `${newW}px`;
dragContainer.style.left = `${resizeStartLeft + dx}px`;
}
}

if (dir.includes("s")) {
consoleOutput.style.height = `${Math.max(MIN_OUTPUT_HEIGHT, resizeStartOutputHeight + dy)}px`;
}
if (dir.includes("n")) {
const newH = resizeStartOutputHeight - dy;
if (newH >= MIN_OUTPUT_HEIGHT) {
consoleOutput.style.height = `${newH}px`;
dragContainer.style.top = `${resizeStartTop + dy}px`;
}
}
});

document.addEventListener("mouseup", () => {
if (!isResizing) return;
isResizing = false;
resizeDirection = "";
document.body.style.userSelect = "";
document.body.style.cursor = "";
dragContainer.classList.add("transition-all", "duration-300", "ease-in-out");
});
Comment on lines +241 to +260
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate `document` event listeners for `mousemove` and `mouseup`


The code adds mousemove and mouseup event listeners to the document object. However, listeners for these same events on document already exist for the drag functionality. Attaching multiple listeners for the same event on a global object is inefficient and makes the code harder to maintain and debug.

Consolidate the logic into a single mousemove and a single mouseup listener on the document. Use state variables like isDragging and isResizing within these listeners to delegate to the correct logic.


function minimizeConsole() {
// Toggles the height of the output area
if (consoleOutput.style.display === "none") {
consoleOutput.style.display = "block";
consoleContainer.style.width = "20rem"; // w-80
Expand All @@ -186,10 +270,8 @@ function minimizeConsole() {
}

function maximizeConsole() {
// Toggles a full-screen-ish mode
consoleContainer.classList.toggle("console-maximized");

// Adjust height when maximized
if (consoleContainer.classList.contains("console-maximized")) {
consoleOutput.style.height = "70vh";
consoleOutput.style.display = "block";
Expand Down Expand Up @@ -217,16 +299,13 @@ function reopenConsole() {
const container = document.getElementById("matrix-console-container");
const reopenBtn = document.getElementById("reopen-console-btn");

// Show the console
container.classList.remove("hidden");

// Trigger reflow for animation
void container.offsetWidth;

container.style.opacity = "1";
container.style.transform = "translateY(0)";

// Hide the reopen button
if (reopenBtn) reopenBtn.classList.add("hidden");
}

Expand Down