2025-09-10 23:43:41 +00:00
|
|
|
<script setup>
|
|
|
|
import Taskbar from '~/components/Taskbar.vue';
|
|
|
|
import AboutMeWindow from '~/components/AboutMeWindow.vue';
|
2025-09-11 11:45:25 +00:00
|
|
|
import { ref, reactive, onMounted, onUnmounted, computed } from 'vue';
|
2025-09-11 11:35:49 +00:00
|
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
|
2025-09-10 23:43:41 +00:00
|
|
|
|
|
|
|
// Reactive array to hold all window states
|
|
|
|
const windows = reactive([]);
|
|
|
|
|
|
|
|
// Keep track of the highest z-index to ensure new/focused windows are on top
|
|
|
|
const currentZIndex = ref(100);
|
|
|
|
|
|
|
|
// Function to generate a unique ID for each window instance
|
|
|
|
const generateUniqueId = () => {
|
|
|
|
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Load window states from localStorage on mount
|
|
|
|
onMounted(() => {
|
|
|
|
const savedWindows = localStorage.getItem('windows');
|
|
|
|
if (savedWindows) {
|
|
|
|
const parsedWindows = JSON.parse(savedWindows);
|
|
|
|
parsedWindows.forEach(win => {
|
|
|
|
// Ensure z-index is properly managed on load
|
|
|
|
if (win.zIndex > currentZIndex.value) {
|
|
|
|
currentZIndex.value = win.zIndex;
|
|
|
|
}
|
|
|
|
windows.push(win);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Save window states to localStorage whenever windows array changes
|
|
|
|
const saveWindowsToLocalStorage = () => {
|
|
|
|
localStorage.setItem('windows', JSON.stringify(windows));
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function to open a new window or bring an existing one to front
|
|
|
|
const openWindow = (type, titleKey, initialWidth = 400, initialHeight = 300) => {
|
|
|
|
const existingWindow = windows.find(w => w.type === type);
|
|
|
|
if (existingWindow) {
|
|
|
|
bringWindowToFront(existingWindow.id);
|
|
|
|
if (existingWindow.isMinimized) {
|
|
|
|
restoreWindow(existingWindow.id);
|
|
|
|
}
|
|
|
|
existingWindow.isVisible = true; // Ensure it's visible if it was closed
|
|
|
|
} else {
|
|
|
|
currentZIndex.value++;
|
|
|
|
// Calculate initial position to center the window within the desktop content area
|
|
|
|
const desktopWidth = window.innerWidth;
|
|
|
|
const desktopHeight = window.innerHeight - 40; // Minus taskbar height
|
|
|
|
const initialX = (desktopWidth - initialWidth) / 2;
|
|
|
|
const initialY = (desktopHeight - initialHeight) / 2 + 40; // Add taskbar height
|
|
|
|
|
|
|
|
const newWindow = {
|
|
|
|
id: generateUniqueId(),
|
|
|
|
type,
|
|
|
|
title: titleKey, // Store the translation key here
|
|
|
|
isVisible: true,
|
|
|
|
isMinimized: false,
|
|
|
|
x: initialX,
|
|
|
|
y: initialY,
|
|
|
|
width: initialWidth,
|
|
|
|
height: initialHeight,
|
|
|
|
zIndex: currentZIndex.value,
|
|
|
|
};
|
|
|
|
windows.push(newWindow);
|
|
|
|
saveWindowsToLocalStorage();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function to close a window
|
|
|
|
const closeWindow = (id) => {
|
|
|
|
const index = windows.findIndex(w => w.id === id);
|
|
|
|
if (index !== -1) {
|
|
|
|
windows.splice(index, 1);
|
|
|
|
saveWindowsToLocalStorage();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function to close all windows
|
|
|
|
const closeAllWindows = () => {
|
|
|
|
windows.splice(0, windows.length); // Clear the array
|
|
|
|
saveWindowsToLocalStorage();
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function to minimize a window
|
|
|
|
const minimizeWindow = (id) => {
|
|
|
|
const windowToMinimize = windows.find(w => w.id === id);
|
|
|
|
if (windowToMinimize) {
|
|
|
|
windowToMinimize.isMinimized = true;
|
|
|
|
saveWindowsToLocalStorage();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function to restore a minimized window
|
|
|
|
const restoreWindow = (id) => {
|
|
|
|
const windowToRestore = windows.find(w => w.id === id);
|
|
|
|
if (windowToRestore) {
|
|
|
|
windowToRestore.isMinimized = false;
|
|
|
|
bringWindowToFront(id);
|
|
|
|
saveWindowsToLocalStorage();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function to bring a window to the front (update z-index)
|
|
|
|
const bringWindowToFront = (id) => {
|
|
|
|
const windowToFront = windows.find(w => w.id === id);
|
|
|
|
if (windowToFront) {
|
|
|
|
currentZIndex.value++;
|
|
|
|
windowToFront.zIndex = currentZIndex.value;
|
|
|
|
saveWindowsToLocalStorage();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function to update window position (for dragging)
|
|
|
|
const updateWindowPosition = (id, newX, newY) => {
|
|
|
|
const windowToUpdate = windows.find(w => w.id === id);
|
|
|
|
if (windowToUpdate) {
|
|
|
|
windowToUpdate.x = newX;
|
|
|
|
windowToUpdate.y = newY;
|
|
|
|
saveWindowsToLocalStorage();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Handle opening About Me window from Taskbar
|
|
|
|
const openAboutMeWindow = () => {
|
|
|
|
openWindow('about-me', 'about_me'); // Pass the translation key
|
|
|
|
};
|
|
|
|
|
|
|
|
// Computed property for minimized windows
|
|
|
|
const minimizedWindows = computed(() => {
|
|
|
|
return windows.filter(win => win.isMinimized);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Clean up localStorage on component unmount (optional, for development)
|
|
|
|
onUnmounted(() => {
|
|
|
|
// localStorage.removeItem('windows');
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<div>
|
|
|
|
<Taskbar
|
|
|
|
@open-about-me="openAboutMeWindow"
|
|
|
|
@close-all-windows="closeAllWindows"
|
|
|
|
:minimized-windows="minimizedWindows"
|
|
|
|
@restore-window="restoreWindow"
|
|
|
|
/>
|
|
|
|
<div class="desktop-content">
|
|
|
|
<NuxtPage />
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Dynamically render windows -->
|
|
|
|
<template v-for="window in windows" :key="window.id">
|
|
|
|
<AboutMeWindow
|
|
|
|
v-if="window.type === 'about-me' && window.isVisible && !window.isMinimized"
|
|
|
|
:window-data="window"
|
|
|
|
@close="closeWindow(window.id)"
|
|
|
|
@minimize="minimizeWindow(window.id)"
|
|
|
|
@restore="restoreWindow(window.id)"
|
|
|
|
@bring-to-front="bringWindowToFront(window.id)"
|
|
|
|
@update-position="updateWindowPosition(window.id, $event.x, $event.y)"
|
|
|
|
/>
|
|
|
|
</template>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
body {
|
|
|
|
background-color: #008080; /* Windows 95 teal */
|
|
|
|
background-image: url('https://picsum.photos/1920/1080'); /* Placeholder wallpaper */
|
|
|
|
background-size: cover;
|
|
|
|
background-position: center;
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
font-family: 'Courier New', Courier, monospace;
|
|
|
|
margin: 0;
|
|
|
|
overflow: hidden; /* Hide scrollbars from the body */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Adjust Taskbar position */
|
|
|
|
.taskbar {
|
|
|
|
position: fixed;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
width: 100%;
|
|
|
|
height: 40px;
|
|
|
|
z-index: 1000; /* Ensure it's on top of other content */
|
|
|
|
}
|
|
|
|
|
|
|
|
.desktop-content {
|
|
|
|
/* Push content down by the height of the taskbar */
|
|
|
|
margin-top: 40px;
|
|
|
|
height: calc(100vh - 40px); /* Fill remaining height */
|
|
|
|
width: 100%;
|
|
|
|
box-sizing: border-box;
|
|
|
|
overflow-y: auto; /* Allow scrolling for desktop content if needed */
|
|
|
|
background-color: transparent; /* Changed to transparent */
|
|
|
|
border: none; /* Removed border */
|
|
|
|
box-shadow: none; /* Removed shadow */
|
|
|
|
}
|
|
|
|
</style>
|