|
@@ -8,6 +8,8 @@ import Redirect from "../components/redirect.astro";
|
|
|
import Contact from "../components/contact.astro";
|
|
import Contact from "../components/contact.astro";
|
|
|
import Pgp from "../components/pgp.astro";
|
|
import Pgp from "../components/pgp.astro";
|
|
|
import Projects from "../components/projects.astro";
|
|
import Projects from "../components/projects.astro";
|
|
|
|
|
+import Duolingo from "../components/duolingo.astro";
|
|
|
|
|
+import GitHubGraph from "../components/githubgraph.astro";
|
|
|
|
|
|
|
|
// Projects
|
|
// Projects
|
|
|
import Summize from "../components/projects/summize.astro";
|
|
import Summize from "../components/projects/summize.astro";
|
|
@@ -258,6 +260,8 @@ apps = apps.map((item) => {
|
|
|
<Summize />
|
|
<Summize />
|
|
|
<Notion />
|
|
<Notion />
|
|
|
<Imdb />
|
|
<Imdb />
|
|
|
|
|
+ <Duolingo />
|
|
|
|
|
+ <GitHubGraph />
|
|
|
</div>
|
|
</div>
|
|
|
<Taskbar />
|
|
<Taskbar />
|
|
|
</Layout>
|
|
</Layout>
|
|
@@ -317,7 +321,6 @@ apps = apps.map((item) => {
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
document.getElementById(id).style.display = "block";
|
|
document.getElementById(id).style.display = "block";
|
|
|
raiseUpSpec(id);
|
|
raiseUpSpec(id);
|
|
|
- // console.log("test");
|
|
|
|
|
}, 1);
|
|
}, 1);
|
|
|
};
|
|
};
|
|
|
});
|
|
});
|
|
@@ -347,10 +350,19 @@ apps = apps.map((item) => {
|
|
|
}
|
|
}
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
- Array.from(window.getElementsByClassName("close")).forEach((button) => {
|
|
|
|
|
- button.addEventListener("click", () => {
|
|
|
|
|
- window.style.display = "none";
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ Array.from(window.getElementsByClassName("close")).forEach((button, index) => {
|
|
|
|
|
+ if (index === 0) {
|
|
|
|
|
+ // First button is minimize
|
|
|
|
|
+ button.addEventListener("click", () => {
|
|
|
|
|
+ minimizeWindow(window.id);
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Second button is close
|
|
|
|
|
+ button.addEventListener("click", () => {
|
|
|
|
|
+ window.style.display = "none";
|
|
|
|
|
+ removeFromTaskbar(window.id);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -368,4 +380,198 @@ apps = apps.map((item) => {
|
|
|
appFunc();
|
|
appFunc();
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+ // Minimize and restore window functions
|
|
|
|
|
+ function minimizeWindow(windowId) {
|
|
|
|
|
+ const window = document.getElementById(windowId);
|
|
|
|
|
+
|
|
|
|
|
+ // First add to taskbar to get the button position
|
|
|
|
|
+ addToTaskbar(windowId);
|
|
|
|
|
+
|
|
|
|
|
+ // Get window and target button positions
|
|
|
|
|
+ const windowRect = window.getBoundingClientRect();
|
|
|
|
|
+ const taskbarButton = document.getElementById(`taskbar-${windowId}`);
|
|
|
|
|
+ const buttonRect = taskbarButton.getBoundingClientRect();
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate the translation needed
|
|
|
|
|
+ const translateX = buttonRect.left - windowRect.left;
|
|
|
|
|
+ const translateY = buttonRect.top - windowRect.top;
|
|
|
|
|
+
|
|
|
|
|
+ // Create custom animation
|
|
|
|
|
+ window.style.transition = "all 0.3s ease-out";
|
|
|
|
|
+ window.style.transform = `translate(${translateX}px, ${translateY}px) scale(0.1)`;
|
|
|
|
|
+ window.style.opacity = "0";
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ window.style.display = "none";
|
|
|
|
|
+ window.style.transition = "";
|
|
|
|
|
+ window.style.transform = "";
|
|
|
|
|
+ window.style.opacity = "";
|
|
|
|
|
+ }, 300);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function restoreWindow(windowId) {
|
|
|
|
|
+ const window = document.getElementById(windowId);
|
|
|
|
|
+ const taskbarButton = document.getElementById(`taskbar-${windowId}`);
|
|
|
|
|
+ const buttonRect = taskbarButton.getBoundingClientRect();
|
|
|
|
|
+ const windowRect = window.getBoundingClientRect();
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate starting position
|
|
|
|
|
+ const translateX = buttonRect.left - windowRect.left;
|
|
|
|
|
+ const translateY = buttonRect.top - windowRect.top;
|
|
|
|
|
+
|
|
|
|
|
+ // Set initial state
|
|
|
|
|
+ window.style.transform = `translate(${translateX}px, ${translateY}px) scale(0.1)`;
|
|
|
|
|
+ window.style.opacity = "0";
|
|
|
|
|
+ window.style.display = "block";
|
|
|
|
|
+
|
|
|
|
|
+ // Remove from taskbar
|
|
|
|
|
+ removeFromTaskbar(windowId);
|
|
|
|
|
+ raiseUpSpec(windowId);
|
|
|
|
|
+
|
|
|
|
|
+ // Trigger animation after a frame
|
|
|
|
|
+ requestAnimationFrame(() => {
|
|
|
|
|
+ window.style.transition = "all 0.3s ease-out";
|
|
|
|
|
+ window.style.transform = "translate(0, 0) scale(1)";
|
|
|
|
|
+ window.style.opacity = "1";
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ window.style.transition = "";
|
|
|
|
|
+ window.style.transform = "";
|
|
|
|
|
+ window.style.opacity = "";
|
|
|
|
|
+ }, 300);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function addToTaskbar(windowId) {
|
|
|
|
|
+ const taskbarWindows = document.getElementById("taskbar-windows");
|
|
|
|
|
+
|
|
|
|
|
+ // Check if already in taskbar
|
|
|
|
|
+ if (document.getElementById(`taskbar-${windowId}`)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const window = document.getElementById(windowId);
|
|
|
|
|
+ const titleBar = window.querySelector(".title-bar-text");
|
|
|
|
|
+ const title = titleBar ? titleBar.textContent : windowId;
|
|
|
|
|
+
|
|
|
|
|
+ // Get icon for the window
|
|
|
|
|
+ const iconMap = {
|
|
|
|
|
+ 'aboutme': '👤',
|
|
|
|
|
+ 'contact': '📧',
|
|
|
|
|
+ 'pgp': '🔐',
|
|
|
|
|
+ 'projects': '📁',
|
|
|
|
|
+ 'duolingo': '🦉',
|
|
|
|
|
+ 'redirect': '🔗',
|
|
|
|
|
+ 'summize': '📝',
|
|
|
|
|
+ 'notion': '📋',
|
|
|
|
|
+ 'imdb': '🎬'
|
|
|
|
|
+ };
|
|
|
|
|
+ const icon = iconMap[windowId] || '📄';
|
|
|
|
|
+
|
|
|
|
|
+ const button = document.createElement("button");
|
|
|
|
|
+ button.id = `taskbar-${windowId}`;
|
|
|
|
|
+ button.style.cssText = `
|
|
|
|
|
+ min-width: 140px;
|
|
|
|
|
+ max-width: 180px;
|
|
|
|
|
+ height: 2.25rem;
|
|
|
|
|
+ padding: 0 0.5rem;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ background-color: #c0c0c0;
|
|
|
|
|
+ box-shadow: -2px -2px #e0dede, -2px 0 #e0dede, 0 -2px #e0dede, -4px -4px white, -4px 0 white, 0 -4px white, 2px 2px #818181, 0 2px #818181, 2px 0 #818181, 2px -2px #e0dede, -2px 2px #818181, -4px 2px white, -4px 4px black, 4px 4px black, 4px 0 black, 0 4px black, 2px -4px white, 4px -4px black;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 0.35rem;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ `;
|
|
|
|
|
+
|
|
|
|
|
+ // Create icon span
|
|
|
|
|
+ const iconSpan = document.createElement("span");
|
|
|
|
|
+ iconSpan.textContent = icon;
|
|
|
|
|
+ iconSpan.style.cssText = `
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ line-height: 1;
|
|
|
|
|
+ `;
|
|
|
|
|
+
|
|
|
|
|
+ // Create text span
|
|
|
|
|
+ const textSpan = document.createElement("span");
|
|
|
|
|
+ textSpan.textContent = title;
|
|
|
|
|
+ textSpan.style.cssText = `
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ font-size: 11px;
|
|
|
|
|
+ letter-spacing: 0.3px;
|
|
|
|
|
+ `;
|
|
|
|
|
+
|
|
|
|
|
+ button.appendChild(iconSpan);
|
|
|
|
|
+ button.appendChild(textSpan);
|
|
|
|
|
+
|
|
|
|
|
+ // Add active state styling
|
|
|
|
|
+ button.addEventListener("mousedown", () => {
|
|
|
|
|
+ button.style.boxShadow = "-2px -2px #818181, -2px 0 #818181, 0 -2px #818181, -4px -4px black, -4px 0 black, 0 -4px black, 2px 2px #e0dede, 0 2px #e0dede, 2px 0 #e0dede, 2px -2px #818181, -2px 2px #e0dede, -4px 2px black, -4px 4px white, 4px 4px white, 4px 0 white, 0 4px white, 2px -4px black, 4px -4px white";
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ button.addEventListener("mouseup", () => {
|
|
|
|
|
+ button.style.boxShadow = "-2px -2px #e0dede, -2px 0 #e0dede, 0 -2px #e0dede, -4px -4px white, -4px 0 white, 0 -4px white, 2px 2px #818181, 0 2px #818181, 2px 0 #818181, 2px -2px #e0dede, -2px 2px #818181, -4px 2px white, -4px 4px black, 4px 4px black, 4px 0 black, 0 4px black, 2px -4px white, 4px -4px black";
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ button.addEventListener("click", () => {
|
|
|
|
|
+ restoreWindow(windowId);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ taskbarWindows.appendChild(button);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function removeFromTaskbar(windowId) {
|
|
|
|
|
+ const button = document.getElementById(`taskbar-${windowId}`);
|
|
|
|
|
+ if (button) {
|
|
|
|
|
+ button.remove();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Function to show Duolingo with animation
|
|
|
|
|
+ function showDuolingo() {
|
|
|
|
|
+ const duolingoWindow = document.getElementById("duolingo");
|
|
|
|
|
+ duolingoWindow.style.display = "block";
|
|
|
|
|
+ duolingoWindow.classList.add("show");
|
|
|
|
|
+ raiseUpSpec("duolingo");
|
|
|
|
|
+
|
|
|
|
|
+ // Remove animation class after it completes
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ duolingoWindow.classList.remove("show");
|
|
|
|
|
+ }, 400);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Function to show GitHub graph with animation
|
|
|
|
|
+ function showGitHubGraph() {
|
|
|
|
|
+ const githubWindow = document.getElementById("github-graph");
|
|
|
|
|
+ githubWindow.style.display = "block";
|
|
|
|
|
+ githubWindow.classList.add("show");
|
|
|
|
|
+ raiseUpSpec("github-graph");
|
|
|
|
|
+
|
|
|
|
|
+ // Remove animation class after it completes
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ githubWindow.classList.remove("show");
|
|
|
|
|
+ }, 400);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Track start button clicks
|
|
|
|
|
+ let startButtonClicks = 0;
|
|
|
|
|
+ const startButton = document.getElementById("start-button");
|
|
|
|
|
+ if (startButton) {
|
|
|
|
|
+ startButton.addEventListener("click", () => {
|
|
|
|
|
+ startButtonClicks++;
|
|
|
|
|
+ if (startButtonClicks === 1) {
|
|
|
|
|
+ showDuolingo();
|
|
|
|
|
+ } else if (startButtonClicks === 2) {
|
|
|
|
|
+ showGitHubGraph();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Don't auto-show Duolingo anymore - wait for start button click
|
|
|
</script>
|
|
</script>
|