Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d778d82302 | |||
| 30fad6e2e3 | |||
| 6f01cc1793 | |||
| 144127952a | |||
| 6209236041 | |||
| cf70296b04 | |||
| 105518282f | |||
| 7791f6a684 | |||
| 79c47a3632 | |||
| c03449526a | |||
| cd630f0372 | |||
| 1ee1461d51 | |||
| cf13e2a2bf |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
@@ -98,18 +98,22 @@ interface DiscordActivity {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveDiscordAsset(image: string | undefined): string {
|
function resolveDiscordAsset(applicationId: string | undefined, image: string | undefined): string {
|
||||||
if (!image) return "";
|
if (!image) return "";
|
||||||
|
|
||||||
if (image.startsWith("mp:external/")) {
|
if (image.startsWith("mp:external/")) {
|
||||||
const httpsIndex = image.indexOf("/https/");
|
const httpsIndex = image.indexOf("/https/");
|
||||||
if (httpsIndex !== -1) {
|
if (httpsIndex !== -1) {
|
||||||
const after = image.slice(httpsIndex + "/https/".length);
|
return `https://${image.slice(httpsIndex + "/https/".length)}`;
|
||||||
return `https://${after}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/^\d+$/.test(image) || image.startsWith("spotify:")) return "";
|
if (image.startsWith("spotify:"))
|
||||||
|
return "";
|
||||||
|
|
||||||
|
|
||||||
|
if (applicationId && image)
|
||||||
|
return `https://cdn.discordapp.com/app-assets/${applicationId}/${image}.png`;
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
@@ -130,13 +134,14 @@ export function DiscordStatus({ userId }: DiscordStatusParams) {
|
|||||||
const [loading, setLoading] = useState<boolean>(true);
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let interval: NodeJS.Timeout | null = null;
|
||||||
|
|
||||||
async function fetchRichPresence() {
|
async function fetchRichPresence() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`https://api.lanyard.rest/v1/users/${userId}`);
|
const response = await fetch(`https://api.lanyard.rest/v1/users/${userId}`);
|
||||||
const json: LanyardResponse = await response.json();
|
const json: LanyardResponse = await response.json();
|
||||||
if (json.success) {
|
if (json.success)
|
||||||
setPresence(json.data);
|
setPresence(json.data);
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch Lanyard presence:", error);
|
console.error("Failed to fetch Lanyard presence:", error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -144,9 +149,39 @@ export function DiscordStatus({ userId }: DiscordStatusParams) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const startPolling = () => {
|
||||||
|
if (!interval) {
|
||||||
fetchRichPresence();
|
fetchRichPresence();
|
||||||
const interval = setInterval(fetchRichPresence, 30000);
|
interval = setInterval(fetchRichPresence, 30000);
|
||||||
return () => clearInterval(interval);
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopPolling = () => {
|
||||||
|
if (interval) {
|
||||||
|
clearInterval(interval);
|
||||||
|
interval = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVisibilityChange = () => {
|
||||||
|
if (document.visibilityState === 'visible')
|
||||||
|
startPolling();
|
||||||
|
else
|
||||||
|
stopPolling();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.visibilityState === 'visible')
|
||||||
|
startPolling();
|
||||||
|
else
|
||||||
|
setLoading(false);
|
||||||
|
|
||||||
|
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||||
|
stopPolling();
|
||||||
|
};
|
||||||
}, [userId]);
|
}, [userId]);
|
||||||
|
|
||||||
if (loading)
|
if (loading)
|
||||||
@@ -177,9 +212,10 @@ export function DiscordStatus({ userId }: DiscordStatusParams) {
|
|||||||
if (gameActivity.details)
|
if (gameActivity.details)
|
||||||
activityText += ` • ${gameActivity.details}`;
|
activityText += ` • ${gameActivity.details}`;
|
||||||
|
|
||||||
activityImage = gameActivity.assets
|
if (gameActivity.assets) {
|
||||||
? resolveDiscordAsset(gameActivity.assets.small_image || gameActivity.assets.large_image)
|
const targetImage = gameActivity.assets.small_image || gameActivity.assets.large_image;
|
||||||
: "";
|
activityImage = resolveDiscordAsset(gameActivity.application_id, targetImage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (isListeningToSpotify && presence.spotify) {
|
else if (isListeningToSpotify && presence.spotify) {
|
||||||
primaryActivity = { name: "Spotify" } as DiscordActivity;
|
primaryActivity = { name: "Spotify" } as DiscordActivity;
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ export const metadata: Metadata = {
|
|||||||
// description: '',
|
// description: '',
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
url: 'https://neru.rip/ok.jpg',
|
url: 'https://neru.rip/img/ok.jpg',
|
||||||
width: 734,
|
width: 734,
|
||||||
height: 1104,
|
height: 1104,
|
||||||
},
|
},
|
||||||
|
|||||||
+37
-18
@@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
cursor: url('https://cdn.cursors-4u.net/previews/my-custom-cursor-8-957a5617-32.webp') 32 32, auto;
|
cursor: url('/cur/kuromi.webp') 32 32, auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -64,7 +64,7 @@ body {
|
|||||||
padding: 35px 25px 25px 25px;
|
padding: 35px 25px 25px 25px;
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
width: 100%;
|
width: calc(100% - 30px);
|
||||||
|
|
||||||
border: 1px solid var(--pink-accent);
|
border: 1px solid var(--pink-accent);
|
||||||
outline: 4px solid #fff;
|
outline: 4px solid #fff;
|
||||||
@@ -115,7 +115,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
text stuffs
|
text stuff
|
||||||
*/
|
*/
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 1.8rem;
|
font-size: 1.8rem;
|
||||||
@@ -156,6 +156,23 @@ h1 {
|
|||||||
border-bottom: 1px dashed var(--pink-accent);
|
border-bottom: 1px dashed var(--pink-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.social-links button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-main);
|
||||||
|
padding: 2px 6px;
|
||||||
|
margin: 0 6px;
|
||||||
|
border-bottom: 1px dashed transparent;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-links button:hover {
|
||||||
|
color: var(--pink-accent);
|
||||||
|
border-bottom: 1px dashed var(--pink-accent);
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
@@ -172,22 +189,17 @@ h1 {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.directory a {
|
.directory a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
padding: 3px 8px;
|
|
||||||
font-size: 0.73rem;
|
font-size: 0.73rem;
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
border: 1px solid #fff;
|
|
||||||
|
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
|
|
||||||
border: 1px solid var(--accent);
|
border: 1px solid var(--accent);
|
||||||
box-shadow: 2px 2px 0px var(--pink-accent);
|
box-shadow: 2px 2px 0px var(--pink-accent);
|
||||||
|
|
||||||
transition: 0.2s ease;
|
transition: 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,16 +208,19 @@ h1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.directory a::after {
|
.directory a::after {
|
||||||
content:" ›"
|
content: " ›"
|
||||||
}
|
}
|
||||||
|
|
||||||
.directory a:hover {
|
.directory a:hover {
|
||||||
cursor: url('https://cdn.cursors-4u.net/previews/my-custom-cursor-8-1-e2eeed6e-preview-32.webp') 0 0, auto !important;
|
cursor: url('/cur/kuromi-hearts.webp') 0 0, auto !important;
|
||||||
color: var(--text-header);
|
color: var(--text-header);
|
||||||
box-shadow: 1px 1px 0px var(--pink-accent);
|
box-shadow: 1px 1px 0px var(--pink-accent);
|
||||||
background: var(--pink-accent);
|
background: var(--pink-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
marquee stuff at the bottom
|
||||||
|
*/
|
||||||
.marquee {
|
.marquee {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -222,19 +237,23 @@ h1 {
|
|||||||
background: linear-gradient(to right, transparent, rgba(255, 214, 245, 0.3), transparent);
|
background: linear-gradient(to right, transparent, rgba(255, 214, 245, 0.3), transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.marquee span {
|
.marquee-track {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
padding-left: 100%;
|
width: max-content;
|
||||||
animation: marquee 25s linear infinite;
|
animation: marquee-loop 10s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes marquee {
|
.marquee-track span {
|
||||||
|
padding-right: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes marquee-loop {
|
||||||
0% {
|
0% {
|
||||||
transform: translate(0, 0);
|
transform: translate3d(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
transform: translate(-100%, 0);
|
transform: translate3d(-50%, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-12
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import './page.css';
|
import './page.css';
|
||||||
import { DiscordStatus } from './components/discordstatus';
|
import { DiscordStatus } from './components/discordstatus';
|
||||||
|
|
||||||
@@ -14,6 +14,17 @@ function Content() {
|
|||||||
|
|
||||||
const toggleModal = () => setIsOpen(!isOpen);
|
const toggleModal = () => setIsOpen(!isOpen);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Escape' && isOpen)
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
|
const marqueeText = "✧ ꒰ა˵• ﻌ •˵ა꒱ ✧ ฅ^•ﻌ•^ฅ ✧ ᶻ 𝗓 𐰁 /ᐠ. 。 .ᐟ\\ ✧ ฅ/ᐠ. ̫ .ᐟ\\ฅ ✧ ꒰ა≽^•⩊•^≼໒꒱ ✧ ₍˄·͈༝·͈˄₎ ✧ /ᐠ. ⩊ .ᐟ\\ノ ✧ 𓏲ּ ֶָ ࣪ /ᐠ .ᆺ. ᐟ\\ノ ✧";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="main-frame">
|
<div className="main-frame">
|
||||||
@@ -23,9 +34,9 @@ function Content() {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<nav className="social-links">
|
<nav className="social-links">
|
||||||
<a href={TWITTER_LINK}>twitter</a> •
|
<a href={TWITTER_LINK} target="_blank" rel="noopener noreferrer">twitter</a> •
|
||||||
<a onClick={toggleModal}>discord</a> •
|
<button onClick={toggleModal}>discord</button> •
|
||||||
<a href={STEAM_LINK} style={{ cursor: 'pointer' }}>steam</a>
|
<a href={STEAM_LINK} target="_blank" rel="noopener noreferrer">steam</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<section className="content-box">
|
<section className="content-box">
|
||||||
@@ -36,18 +47,18 @@ function Content() {
|
|||||||
<section className="content-box">
|
<section className="content-box">
|
||||||
<h2 className="title">✧ projects im currently working on ✧</h2>
|
<h2 className="title">✧ projects im currently working on ✧</h2>
|
||||||
<ul className="directory">
|
<ul className="directory">
|
||||||
<li><a href="https://git.neru.rip/neru/seallib">seallib</a></li>
|
<li><a href="https://git.neru.rip/neru/seallib" target="_blank" rel="noopener noreferrer">seallib</a></li>
|
||||||
<li><a href="https://git.neru.rip/neru/tinymitm">tinymitm</a></li>
|
<li><a href="https://git.neru.rip/neru/tinymitm" target="_blank" rel="noopener noreferrer">tinymitm</a></li>
|
||||||
<li><a href="https://git.neru.rip/neru/luma">luma</a></li>
|
<li><a href="https://git.neru.rip/neru/luma" target="_blank" rel="noopener noreferrer">luma</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="content-box">
|
<section className="content-box">
|
||||||
<h2 className="title">✧ sites ✧</h2>
|
<h2 className="title">✧ sites ✧</h2>
|
||||||
<ul className="directory">
|
<ul className="directory">
|
||||||
<li><a href="https://git.neru.rip">gitea</a></li>
|
<li><a href="https://git.neru.rip" target="_blank" rel="noopener noreferrer">gitea</a></li>
|
||||||
<li><a href="https://zl.neru.rip">zipline</a></li>
|
<li><a href="https://zl.neru.rip" target="_blank" rel="noopener noreferrer">zipline</a></li>
|
||||||
<li><a href="https://files.neru.rip">files</a></li>
|
<li><a href="https://files.neru.rip" target="_blank" rel="noopener noreferrer">files</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -61,9 +72,11 @@ function Content() {
|
|||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<div className="marquee">
|
<div className="marquee">
|
||||||
<span>✧ ꒰ა˵• ﻌ •˵ა꒱ ✧ ฅ^•ﻌ•^ฅ ✧ ᶻ 𝗓 𐰁 /ᐠ. 。 .ᐟ\ ✧ ฅ/ᐠ. ̫ .ᐟ\ฅ ✧ ꒰ა≽^•⩊•^≼໒꒱ ✧ ₍˄·͈༝·͈˄₎ ✧ /ᐠ. ⩊ .ᐟ\ノ ✧ 𓏲ּ ֶָ ࣪ /ᐠ .ᆺ. ᐟ\ノ ✧</span>
|
<div className="marquee-track">
|
||||||
|
<span>{marqueeText}</span>
|
||||||
|
<span>{marqueeText}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* <p style={{ fontSize: '0.65rem', opacity: 0.5 }}>✼ ҉ ✼ ҉ ✼ ҉ ✼</p> */}
|
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
|
|||||||
Reference in New Issue
Block a user