Files
portfolio/index.html

603 lines
21 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2uf</title>
<link rel="icon" href="images/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
font-family: 'Poppins', sans-serif;
overflow: hidden;
color: white;
}
#video-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
z-index: -1;
}
.preload-screen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
z-index: 100;
cursor: pointer;
}
.preload-text {
font-size: 2rem;
font-weight: bold;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 0.6; }
50% { opacity: 1; }
100% { opacity: 0.6; }
}
.main-content {
opacity: 0;
transition: opacity 0.5s ease;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 20px;
gap: 15px;
}
.discord-box,
.github-repos {
width: 100%;
max-width: 600px;
box-sizing: border-box;
background-color: rgba(24, 23, 23, 0.411);
color: #efe6e6;
backdrop-filter: blur(10px);
border-radius: 5px;
border: 1px solid #14181B;
position: relative;
z-index: 2;
opacity: 0;
transform: translateY(20px);
transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.discord-box.animate-in,
.github-repos.animate-in {
opacity: 1;
transform: translateY(0);
}
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.discord-box {
padding: 20px;
text-decoration: none;
color: white;
display: flex;
flex-direction: column;
gap: 12px;
animation: fadeInUp 0.8s ease-out 0.3s forwards;
cursor: pointer;
}
.discord-header {
display: flex;
align-items: center;
gap: 15px;
}
.discord-pic {
width: 55px;
height: 55px;
border-radius: 50%;
border: 5px solid #14181B;
}
.discord-info {
flex-grow: 1;
text-align: left;
}
.discord-name {
font-weight: bold;
font-size: 19px;
margin-bottom: 3px;
}
.discord-status {
display: flex;
align-items: center;
font-size: 13px;
opacity: 0.8;
}
.status-indicator {
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 5px;
}
.status-online {
background: #3ba55c;
}
.status-idle {
background: #faa61a;
}
.status-dnd {
background: #ed4245;
}
.status-offline {
background: #747f8d;
}
#dm-button {
padding: 8px 15px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
background-color: #101517;
border: 1px solid #13191B;
color: white;
font-size: 16px;
font-weight: 500;
transition: all 0.2s ease;
text-decoration: none;
flex-shrink: 0;
gap: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
}
#dm-button:hover {
background-color: rgba(255, 255, 255, 0.2);
transform: scale(1.02);
}
.discord-activity {
font-size: 14px;
padding: 8px;
background: rgba(0, 0, 0, 0.2);
border-radius: 8px;
display: none;
flex-direction: column;
gap: 6px;
}
.activity-game-image {
width: 100%;
max-height: 60px;
object-fit: cover;
border-radius: 10px;
margin-top: 5px;
display: none;
}
.activity-label {
font-weight: bold;
margin-bottom: 5px;
}
.spotify-image-small {
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 8px;
flex-shrink: 0;
}
.spotify-flex-content {
display: flex;
align-items: center;
gap: 10px;
}
#spotify-progress-container {
width: 100%;
height: 5px;
background: rgba(255, 255, 255, 0.3);
border-radius: 5px;
margin-top: 5px;
}
#spotify-progress-bar {
height: 100%;
background: #1DB954;
border-radius: 5px;
width: 0%;
transition: width 1s linear;
}
.time-info {
display: flex;
justify-content: space-between;
font-size: 12px;
opacity: 0.7;
}
.github-repos {
padding: 20px;
animation: fadeInUp 0.8s ease-out 0.5s forwards;
display: flex;
flex-direction: column;
gap: 15px;
border: 1px solid #14181B;
background-color: rgba(24, 23, 23, 0.411)
}
.github-repos h3 {
font-size: 20px;
font-weight: bold;
color: #c9d1d9;
margin-top: 0px;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.repo-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.repo-link {
padding: 10px 15px;
background-color: rgba(24, 23, 23, 0.411);
border-radius: 10px;
text-decoration: none;
color: #efe6e6;
display: flex;
align-items: center;
justify-content: space-between;
transition: background-color 0.2s ease, transform 0.2s ease;
font-size: 15px;
}
.repo-link:hover {
background-color: rgba(255, 255, 255, 0.15);
transform: translateX(5px);
}
.repo-link span {
display: flex;
align-items: center;
gap: 8px;
}
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,400&display=swap');
</style>
</head>
<body>
<video id="video-background" autoplay muted loop>
<source src="images/background.mp4" type="video/mp4" onerror="this.onerror=null; this.remove(); this.src='https://assets.mixkit.co/videos/preview/mixkit-flying-through-a-dark-abstract-tunnel-4493-large.mp4';">
</video>
<audio id="music-player" loop>
<source src="music/song.mp3" type="audio/mpeg" onerror="this.src='#';">
Your browser does not support the audio element.
</audio>
<div class="preload-screen">
<div class="preload-text">Click to reveal</div>
</div>
<div class="main-content">
<div class="container">
<div class="discord-box" id="discord-profile">
<div class="discord-header">
<img id="discord-avatar" class="discord-pic" src="images/discord.jpg" alt="Discord Avatar" onerror="this.src='https://placehold.co/55x55/5865f2/FFFFFF?text=DIS'">
<div class="discord-info">
<div class="discord-name" id="discord-username">Loading...</div>
<div class="discord-status">
<div class="status-indicator" id="status-indicator"></div>
<span id="discord-status-text">Status: -</span>
</div>
</div>
<a href="#" id="dm-button" title="Send a DM (Opens Discord Profile)">
<i class="fas fa-comment-dots"></i> DM
</a>
</div>
<div class="discord-activity" id="activity-section">
<div class="activity-label">Activity:</div>
<div id="discord-activity-name">-</div>
<div id="discord-activity-time">Time: -</div>
<img id="activity-image" class="activity-game-image" src="" alt="Activity Image" onerror="this.style.display='none'">
</div>
<div class="discord-activity" id="spotify-section">
<div class="activity-label">Listening on Spotify:</div>
<div class="spotify-flex-content">
<img id="spotify-image" class="spotify-image-small" src="" alt="Spotify Album Cover" onerror="this.style.display='none'" >
<div style="flex-grow: 1; align-self: center; overflow: hidden; display: flex; flex-direction: column; gap: 2px;">
<div id="discord-spotify-info" style="font-weight: 600; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">-</div>
<div id="spotify-progress-container">
<div id="spotify-progress-bar"></div>
</div>
<div class="time-info" id="spotify-time-info">
<span id="spotify-current-time">0:00</span>
<span id="spotify-duration">0:00</span>
</div>
</div>
</div>
</div>
</div>
<div class="github-repos animate-in">
<h3><i class="fab fa-github"></i> Github Repos</h3>
<a href="https://github.com/luuooss" target="_blank" class="repo-link">
<span><i class="fas fa-user-circle"></i> Profil (luuooss)</span>
<i class="fas fa-arrow-right"></i>
</a>
<a href="https://github.com/luuooss/module-patcher" target="_blank" class="repo-link">
<span><i class="fas fa-code"></i> Module Patcher</span>
<i class="fas fa-arrow-right"></i>
</a>
<a href="https://github.com/luuooss/remove-text-from-filenames" target="_blank" class="repo-link">
<span><i class="fab fa-roblox"></i> Remove Text Form Files Names</span>
<i class="fas fa-arrow-right"></i>
</a>
</div>
</div>
</div>
<script>
document.querySelector('.preload-screen').addEventListener('click', function() {
this.style.display = 'none';
document.querySelector('.main-content').style.opacity = '1';
document.querySelector('.discord-box').classList.add('animate-in');
document.querySelector('.github-repos').classList.add('animate-in');
fetchDiscordStatus();
});
const titleText = "2uf";
let currentIndex = 0;
let isDeleting = false;
const typingSpeed = 150;
function typeTitle() {
const currentTitle = titleText.slice(0, currentIndex) + "|";
document.title = currentTitle;
if (!isDeleting && currentIndex < titleText.length) {
currentIndex++;
} else if (isDeleting && currentIndex > 0) {
currentIndex--;
}
if (currentIndex === titleText.length && !isDeleting) {
setTimeout(() => isDeleting = true, 1000);
} else if (currentIndex === 0 && isDeleting) {
isDeleting = false;
}
setTimeout(typeTitle, isDeleting ? typingSpeed / 2 : typingSpeed);
}
typeTitle();
const userId = "1316227800281124976";
let spotifyUrl = "#";
let spotifyProgressInterval;
function formatTime(ms) {
const totalSeconds = Math.floor(ms / 1000);
const minutes = Math.floor(totalSeconds / 60);
const seconds = Math.floor(totalSeconds % 60);
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
}
function formatDuration(startTimestamp) {
const now = Date.now();
const diff = now - startTimestamp;
const minutes = Math.floor(diff / 60000);
const seconds = Math.floor((diff % 60000) / 1000);
return `${minutes}m ${seconds}s`;
}
function updateSpotifyProgress(startTimestamp, endTimestamp) {
const now = Date.now();
const start = new Date(startTimestamp).getTime();
const end = new Date(endTimestamp).getTime();
const duration = end - start;
let current = now - start;
if (current > duration) {
current = duration;
}
const progressPercent = (current / duration) * 100;
const progressBar = document.getElementById('spotify-progress-bar');
const currentTimeElement = document.getElementById('spotify-current-time');
const durationElement = document.getElementById('spotify-duration');
if (progressBar && currentTimeElement && durationElement) {
progressBar.style.width = `${progressPercent}%`;
currentTimeElement.textContent = formatTime(current);
durationElement.textContent = formatTime(duration);
}
}
async function fetchDiscordStatus() {
clearInterval(spotifyProgressInterval);
try {
let data = null;
const maxRetries = 3;
for (let i = 0; i < maxRetries; i++) {
try {
const res = await fetch(`https://api.lanyard.rest/v1/users/${userId}`);
data = await res.json();
if (data.success) break;
} catch (e) {
if (i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw e;
}
}
}
if (!data || !data.success) return;
const d = data.data;
const avatarURL = `https://cdn.discordapp.com/avatars/${d.discord_user.id}/${d.discord_user.avatar}.png?size=128`;
document.getElementById("discord-avatar").src = avatarURL;
const username = `${d.discord_user.username}`;
document.getElementById("discord-username").textContent = username;
const statusText = {
online: "Online",
idle: "Idle",
dnd: "Do Not Disturb",
offline: "Offline"
};
document.getElementById("discord-status-text").textContent = statusText[d.discord_status] || d.discord_status;
const statusIndicator = document.getElementById("status-indicator");
statusIndicator.className = "status-indicator";
statusIndicator.classList.add(`status-${d.discord_status}`);
document.getElementById("activity-section").style.display = "none";
document.getElementById("spotify-section").style.display = "none";
const game = d.activities.find(a => a.type === 0);
const gameImg = document.getElementById("activity-image");
gameImg.classList.add('activity-game-image');
if (game) {
document.getElementById("activity-section").style.display = "flex";
document.getElementById("discord-activity-name").textContent = game.name;
if (game.timestamps?.start) {
document.getElementById("discord-activity-time").textContent = `For: ${formatDuration(game.timestamps.start)}`;
} else {
document.getElementById("discord-activity-time").textContent = "Time: unknown";
}
if (game.assets?.large_image) {
let imgKey = game.assets.large_image;
if (imgKey.startsWith("mp:external")) {
gameImg.src = imgKey.replace(/^mp:/, "https:");
} else {
gameImg.src = `https://cdn.discordapp.com/app-assets/${game.application_id}/${imgKey}.png`;
}
gameImg.style.display = "block";
} else {
gameImg.style.display = "none";
}
} else {
gameImg.style.display = "none";
}
const spotifyImg = document.getElementById("spotify-image");
if (d.listening_to_spotify && d.spotify) {
document.getElementById("spotify-section").style.display = "flex";
const song = `${d.spotify.song} - ${d.spotify.artist}`;
document.getElementById("discord-spotify-info").textContent = song;
spotifyUrl = `https://open.spotify.com/track/${d.spotify.track_id}`;
spotifyImg.src = d.spotify.album_art_url;
spotifyImg.style.display = "block";
const { start, end } = d.spotify.timestamps;
updateSpotifyProgress(start, end);
spotifyProgressInterval = setInterval(() => {
updateSpotifyProgress(start, end);
}, 1000);
} else {
spotifyUrl = "#";
}
} catch (error) {
console.error("Error fetching Discord status:", error);
document.getElementById("discord-username").textContent = "Load error";
document.getElementById("discord-status-text").textContent = "Status: unknown";
spotifyUrl = "#";
}
}
document.getElementById('dm-button').addEventListener('click', function(e) {
e.stopPropagation();
window.open(`https://discord.com/users/${userId}`, '_blank');
});
document.getElementById('discord-profile').addEventListener('click', function(e) {
if (document.getElementById("spotify-section").style.display === "flex" && spotifyUrl !== "#") {
window.open(spotifyUrl, '_blank');
} else {
window.open(`https://discord.com/users/${userId}`, '_blank');
}
});
let statusInterval;
document.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'visible') {
fetchDiscordStatus();
statusInterval = setInterval(fetchDiscordStatus, 10000);
} else {
clearInterval(statusInterval);
clearInterval(spotifyProgressInterval);
}
});
if (document.querySelector('.preload-screen').style.display === 'none') {
statusInterval = setInterval(fetchDiscordStatus, 10000);
}
</script>
</body>
</html>