Compare commits

..

19 commits

Author SHA1 Message Date
b3f310db3d Merge pull request 'migrate to astro' (#1) from astro into main
Reviewed-on: #1
2024-07-29 21:07:15 +00:00
e194941b5c Added license 2024-07-29 21:06:59 +00:00
8da480329b dockerfile testing time 2024-07-29 16:52:47 -04:00
9b58091459 added buttons 2024-07-29 16:48:24 -04:00
6d7b18dc01 move mainwindow to component 2024-07-29 16:30:20 -04:00
0ee0b19d16 better mobile 2024-07-29 16:29:17 -04:00
b47f03ff2a added nojs warning 2024-07-29 16:23:17 -04:00
fc7959737f ?remind 120h STOP USING console.log FOR LOGGING SHIT 2024-07-29 16:23:10 -04:00
eb07a77584 made window draggable 2024-07-29 16:14:46 -04:00
161e28d5f3 added socials 2024-07-29 16:10:40 -04:00
af797ba515 Added presence 2024-07-29 15:37:29 -04:00
6f6c9f229f added own header 2024-07-29 13:42:01 -04:00
f9b8428d2b made window 2024-07-29 13:10:58 -04:00
2e77b84df3 initial commit 2024-07-29 10:55:50 -04:00
bfc0c43b12 rip 2024-07-29 10:44:44 -04:00
e40b97f984 added bad drag and drop 2024-07-28 10:20:10 -04:00
305a81508e made everything work 2024-07-28 09:31:15 -04:00
45496ace17 ejs will suffer 2024-07-28 09:29:05 -04:00
c8414116ca restructured everything :trolley: 2024-07-28 09:26:14 -04:00
39 changed files with 4172 additions and 474 deletions

24
.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

4
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

View file

@ -1,4 +1,8 @@
FROM lipanski/docker-static-website:latest
# Copy your static files
COPY . .
FROM node:lts-alpine3.17
WORKDIR /usr/src/app
COPY ["package.json", "pnpm-lock.yaml", "dist/*", "./"]
RUN pnpm i
EXPOSE 4321
RUN chown -R node /usr/src/app
USER node
CMD ["pnpm", "start"]

View file

@ -1,3 +1,3 @@
Copyright (c) 2024 nin0dev (https://github.com/nin0-dev, https://codeberg.org/nin0dev, https://git.nin0.dev/nin0, https://nin0.dev)
Usage and reproduction is prohibited.
All rights reserved.
All rights reserved.

47
README.md Normal file
View file

@ -0,0 +1,47 @@
# Astro Starter Kit: Minimal
```sh
npm create astro@latest -- --template minimal
```
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal)
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal)
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json)
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```text
/
├── public/
├── src/
│ └── pages/
│ └── index.astro
└── package.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).

11
astro.config.mjs Normal file
View file

@ -0,0 +1,11 @@
import { defineConfig } from 'astro/config';
import node from "@astrojs/node";
// https://astro.build/config
export default defineConfig({
output: "server",
adapter: node({
mode: "standalone"
})
});

View file

@ -1,104 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* {
font-family: sans-serif !important;
}
</style>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>nin0dev</title>
<link rel="stylesheet" href="https://unpkg.com/7.css">
<link rel="stylesheet" href="style.css">
<link rel="icon" type="image/x-icon" href="logo-but-round.png">
<meta name="theme-color" content="#00D0D0">
<meta property="og:url" content="https://nin0.dev" />
<meta property="og:title" content="nin0dev" />
<meta property="og:description" content="Hey, I'm nin0dev, a Canadian software developer." />
<meta property="og:image" content="https://nin0.dev/logo.png" />
</head>
<body>
<div class="window" id="main-window">
<div class="title-bar">
<div class="title-bar-text">Home</div>
</div>
<div class="window-body">
<div id="header">
<img src="logo.png" alt="the nin0dev logo" id="pfp">
<h3>nin0dev <span style="font-size: 0.4em;">(he/him)</span></h3>
</div>
<br/>
<div id="presence" style="display: none; margin-bottom: 12px;">
<img src="game.ico" id="presence-icon">
<p id="presence-content"></p>
</div>
<fieldset>
<legend>About me</legend>
I'm a Canadian self-taught software developer that makes useless things in Python, HTML, JavaScript, and Kotlin.
<br/>
yeah that's it
</fieldset>
<br/>
<fieldset>
<legend>My projects</legend>
<ul style="margin-top: 5px; margin-bottom: 5px; padding-left: 20px;">
<li>
VendroidEnhanced: A Discord client for Android that loads the mobile website and injects Vencord.
<ul>
<li><a href="https://github.com/VendroidEnhanced/Vendroid">GitHub repo</a></li>
<li>Actively maintained</li>
<li>Fork of <a href="https://github.com/Vencord/Vendroid">Vencord/Vendroid</a></li>
</ul>
</li>
<li>
website: The website you're currently viewing
<ul>
<li><a href="https://github.com/nin0-dev/website">GitHub repo</a></li>
</ul>
</li>
<li>
nin0-bot: An in-development kitchen-sink Discord Bot with moderation, fun and utility
<ul>
<li><a href="https://github.com/nin0-dev/Sink">GitHub repo</a></li>
<li>In development</li>
</ul>
</li>
</ul>
</fieldset>
</br>
<fieldset>
<legend>Reach out!</legend>
<ul style="margin-top: 5px; margin-bottom: 5px; padding-left: 20px;">
<li>Discord: @nin0.dev</li>
<li>
Email: <a href="mailto:support@nin0.dev">support@nin0.dev</a>
</li>
<li>Telegram: <a href="https://t.me/nin0dev">@nin0dev</a></li>
<li>GitHub: <a href="https://github.com/nin0-dev">nin0-dev</a></li>
</ul>
</fieldset>
<span id="credits" style="display: none;">
<br/>
<fieldset>
<legend>Credits</legend>
<ul style="margin-top: 5px; margin-bottom: 5px; padding-left: 20px;">
<li>UI library: <a href="https://jdan.github.io/98.css/">98.css by jdan</a></li>
<li>Presence/status API: <a href="https://discord.gg/lanyard">Lanyard</a></li>
<li>Icons: <a href="https://win98icons.alexmeub.com/">official Windows 98 icons</a></li>
</ul>
</fieldset>
</span>
<div id="bottom-actions" style="margin-top: 13px;">
<button onclick="showCredits()" id="credits-button">Credits</button>
</div>
</div>
</div>
<script src="oneko.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lanyard-wrapper/dist/index.browser.js"></script>
<script src="index.js"></script>
</body>
</html>

View file

@ -1,65 +0,0 @@
let shouldLog = false;
function log(content) {
if (shouldLog) console.log(content);
}
function onUpdate(data) {
// set status
log(data)
const pfp = document.getElementById("pfp");
switch(data["discord_status"]) {
case "online":
pfp.style.borderColor = "var(--online-color)";
break;
case "idle":
pfp.style.borderColor = "var(--idle-color)";
break;
case "dnd":
pfp.style.borderColor = "var(--dnd-color)";
break;
case "offline":
pfp.style.borderColor = "var(--offline-color)";
break;
}
// set presence
log(data["activities"])
let listening = false
let content = ""
data["activities"].forEach(presence => {
if(presence["application_id"] == "463151177836658699" && presence["assets"]["small_text"] != "Paused") { // premid
listening = true
artist = presence["state"].substring(0, presence["state"].indexOf(" -"))
if (artist == "") {
artist = presence["state"]
}
content = `Listening to ${presence["details"]} - ${artist}`
}
if(presence["application_id"] == "1108588077900898414") { // vencord lastfm
listening = true
content = `Listening to ${presence["details"]} - ${presence["state"]}`
}
if(presence["application_id"] == "1054951789318909972") { // vendetta lastfm
listening = true
content = `Listening to ${presence["details"]} - ${presence["state"]}`
}
if(presence["id"] == "spotify:1") { // built in spotify hooluy shit normal presence)
listening = true
content = `Listening to ${presence["details"]} - ${presence["state"]}`
}
if(presence["type"] == 0 && presence["application_id"] != "463151177836658699" && presence["application_id"] != "1108588077900898414") { // generic playing status that isn't vencord lastfm or premid
listening = false
content = `Playing ${presence["name"]}`
}
});
document.getElementById("presence").style.display = content == "" ? "none": "flex"
document.getElementById("presence-content").innerText = content
document.getElementById("presence-icon").src = listening ? "music.ico" : "game.ico"
}
LanyardWrapper.connectWebSocket("886685857560539176", onUpdate)
.catch(err => {
console.error(err);
});
function showCredits() {
document.getElementById("credits").style.display = "block"
document.getElementById("credits-button").style.display = "none"
}

4
info/contacts/discord.md Normal file
View file

@ -0,0 +1,4 @@
---
platform: "Discord"
name: "nin0.dev"
---

6
info/contacts/email.md Normal file
View file

@ -0,0 +1,6 @@
---
platform: "Email"
name: "support@nin0.dev"
url: "mailto:support@nin0.dev"
note: "Replies may be slow"
---

View file

@ -0,0 +1,6 @@
---
platform: "Telegram"
url: "https://nin0dev.t.me"
name: "@nin0dev"
note: "Use for quick replies"
---

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

BIN
oneko.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

239
oneko.js
View file

@ -1,239 +0,0 @@
// oneko.js: https://github.com/adryd325/oneko.js
(function oneko() {
const isReducedMotion =
window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||
window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;
if (isReducedMotion) return;
const nekoEl = document.createElement("div");
let nekoPosX = 32;
let nekoPosY = 32;
let mousePosX = 0;
let mousePosY = 0;
let frameCount = 0;
let idleTime = 0;
let idleAnimation = null;
let idleAnimationFrame = 0;
const nekoSpeed = 10;
const spriteSets = {
idle: [[-3, -3]],
alert: [[-7, -3]],
scratchSelf: [
[-5, 0],
[-6, 0],
[-7, 0],
],
scratchWallN: [
[0, 0],
[0, -1],
],
scratchWallS: [
[-7, -1],
[-6, -2],
],
scratchWallE: [
[-2, -2],
[-2, -3],
],
scratchWallW: [
[-4, 0],
[-4, -1],
],
tired: [[-3, -2]],
sleeping: [
[-2, 0],
[-2, -1],
],
N: [
[-1, -2],
[-1, -3],
],
NE: [
[0, -2],
[0, -3],
],
E: [
[-3, 0],
[-3, -1],
],
SE: [
[-5, -1],
[-5, -2],
],
S: [
[-6, -3],
[-7, -2],
],
SW: [
[-5, -3],
[-6, -1],
],
W: [
[-4, -2],
[-4, -3],
],
NW: [
[-1, 0],
[-1, -1],
],
};
function init() {
nekoEl.id = "oneko";
nekoEl.ariaHidden = true;
nekoEl.style.width = "32px";
nekoEl.style.height = "32px";
nekoEl.style.position = "fixed";
nekoEl.style.pointerEvents = "none";
nekoEl.style.imageRendering = "pixelated";
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
nekoEl.style.zIndex = Number.MAX_VALUE;
let nekoFile = "./oneko.gif"
const curScript = document.currentScript
if (curScript && curScript.dataset.cat) {
nekoFile = curScript.dataset.cat
}
nekoEl.style.backgroundImage = `url(${nekoFile})`;
document.body.appendChild(nekoEl);
document.addEventListener("mousemove", function (event) {
mousePosX = event.clientX;
mousePosY = event.clientY;
});
window.requestAnimationFrame(onAnimationFrame);
}
let lastFrameTimestamp;
function onAnimationFrame(timestamp) {
// Stops execution if the neko element is removed from DOM
if (!nekoEl.isConnected) {
return;
}
if (!lastFrameTimestamp) {
lastFrameTimestamp = timestamp;
}
if (timestamp - lastFrameTimestamp > 100) {
lastFrameTimestamp = timestamp
frame()
}
window.requestAnimationFrame(onAnimationFrame);
}
function setSprite(name, frame) {
const sprite = spriteSets[name][frame % spriteSets[name].length];
nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`;
}
function resetIdleAnimation() {
idleAnimation = null;
idleAnimationFrame = 0;
}
function idle() {
idleTime += 1;
// every ~ 20 seconds
if (
idleTime > 10 &&
Math.floor(Math.random() * 200) == 0 &&
idleAnimation == null
) {
let avalibleIdleAnimations = ["sleeping", "scratchSelf"];
if (nekoPosX < 32) {
avalibleIdleAnimations.push("scratchWallW");
}
if (nekoPosY < 32) {
avalibleIdleAnimations.push("scratchWallN");
}
if (nekoPosX > window.innerWidth - 32) {
avalibleIdleAnimations.push("scratchWallE");
}
if (nekoPosY > window.innerHeight - 32) {
avalibleIdleAnimations.push("scratchWallS");
}
idleAnimation =
avalibleIdleAnimations[
Math.floor(Math.random() * avalibleIdleAnimations.length)
];
}
switch (idleAnimation) {
case "sleeping":
if (idleAnimationFrame < 8) {
setSprite("tired", 0);
break;
}
setSprite("sleeping", Math.floor(idleAnimationFrame / 4));
if (idleAnimationFrame > 192) {
resetIdleAnimation();
}
break;
case "scratchWallN":
case "scratchWallS":
case "scratchWallE":
case "scratchWallW":
case "scratchSelf":
setSprite(idleAnimation, idleAnimationFrame);
if (idleAnimationFrame > 9) {
resetIdleAnimation();
}
break;
default:
setSprite("idle", 0);
return;
}
idleAnimationFrame += 1;
}
function frame() {
frameCount += 1;
const diffX = nekoPosX - mousePosX;
const diffY = nekoPosY - mousePosY;
const distance = Math.sqrt(diffX ** 2 + diffY ** 2);
if (distance < nekoSpeed || distance < 48) {
idle();
return;
}
idleAnimation = null;
idleAnimationFrame = 0;
if (idleTime > 1) {
setSprite("alert", 0);
// count down after being alerted before moving
idleTime = Math.min(idleTime, 7);
idleTime -= 1;
return;
}
let direction;
direction = diffY / distance > 0.5 ? "N" : "";
direction += diffY / distance < -0.5 ? "S" : "";
direction += diffX / distance > 0.5 ? "W" : "";
direction += diffX / distance < -0.5 ? "E" : "";
setSprite(direction, frameCount);
nekoPosX -= (diffX / distance) * nekoSpeed;
nekoPosY -= (diffY / distance) * nekoSpeed;
nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16);
nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16);
nekoEl.style.left = `${nekoPosX - 16}px`;
nekoEl.style.top = `${nekoPosY - 16}px`;
}
init();
})();

18
package.json Normal file
View file

@ -0,0 +1,18 @@
{
"name": "",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"7.css": "^0.16.0",
"@astrojs/node": "^8.3.2",
"astro": "^4.12.2",
"lanyard-wrapper": "^2.0.1"
}
}

3626
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load diff

View file

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View file

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View file

@ -0,0 +1,9 @@
---
const {position, text, url, id} = Astro.props;
---
<style>
button, a {
width: 100%;
}
</style>
{url ? <a href={url}><button id={id}>{text}</button></a> : <button id={id}>{text}</button>}

View file

@ -0,0 +1,10 @@
<style>
div {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
}
</style>
<div class="button-collection">
<slot />
</div>

View file

@ -0,0 +1,8 @@
---
import Social from "./Social.astro"
const contacts = await Astro.glob("../../info/contacts/*.md")
---
<ul>
{contacts.map(contact => <Social platform={contact.frontmatter.platform} url={contact.frontmatter.url} name={contact.frontmatter.name} note={contact.frontmatter.note}/>)}
</ul>

View file

@ -0,0 +1,23 @@
<style>
div {
color: black;
background-color: lightcoral;
padding: 10px;
margin-bottom: 20px;
border-radius: 10px;
}
a {
color: blue;
}
</style>
<noscript>
<div>
<p>
<h4>ENABLE JAVASCRIPT OR I WILL KILL YOU</h4>
I will not. However, you seem to be living in fear of technology, as you have JavaScript disabled. This means that some features (eg. dragging, submitting forms) will not work. Enable JS to fully enjoy this website!
<br/>
Rest assured, there's no external tracking. You can check this site's source code on the <a href="https://git.nin0.dev/nin0/website">nin0/website</a> repository on my Forgejo.
</p>
</div>
</noscript>

View file

@ -0,0 +1,16 @@
---
const {name} = Astro.props
---
<style>
fieldset {
margin-top: 10px;
margin-bottom: 0px;
padding: 0px 15px;
}
</style>
<fieldset>
<legend>{name}</legend>
<slot />
</fieldset>

View file

@ -0,0 +1,31 @@
---
import Contacts from "../components/Contacts.astro";
import GroupBox from "../components/GroupBox.astro";
import Me from "../components/Me.astro";
import Presence from "../components/Presence.astro";
import Window from "../components/Window.astro";
import Button from "./Button.astro";
import ButtonCollection from "./ButtonCollection.astro";
import Spacer from "./Spacer.astro";
---
<Window title="Home" maxWidth="600px">
<Me />
<Presence />
<GroupBox name="About me">
<p>
I'm a Canadian self-taught software developer that makes things some people find useful in Python, HTML, JavaScript, and Kotlin.
<br/>
I occasionally code with Java or C#, and am currently learning Rust.
</p>
</GroupBox>
<GroupBox name="Reach out">
<Contacts />
</GroupBox>
<ButtonCollection>
<Button position="left" text="Projects (soon)" url="/projects"/>
<Spacer />
<Button position="left" text="Code (soon)" url="/code"/>
<Spacer />
<Button position="left" text="Blog (ETA: 100 years)" url="/code"/>
</ButtonCollection>
</Window>

45
src/components/Me.astro Normal file
View file

@ -0,0 +1,45 @@
---
import {fetchUserData, type DiscordStatus} from "lanyard-wrapper";
const rawUserData = await fetchUserData("886685857560539176");
const statusColor = () => {
switch (rawUserData.discord_status) {
case "online":
return "#23a55a";
case "idle":
return "#f0b232";
case "dnd":
return "#f23f43";
case "offline":
return "#80848e";
default:
return "#80848e";
}
};
---
<style define:vars={{statusColor: statusColor()}}>
div {
display: flex;
}
h3 {
font-weight: 400;
margin-left: 20px;
margin-top: auto;
margin-bottom: auto;
}
img {
width: 90px;
height: 90px;
border-radius: 6px;
box-shadow: 10px black;
border-color: var(--statusColor);
border-style: solid;
border-width: 2px;
}
</style>
<div>
<img src="logo.png" alt="the nin0dev logo">
<h3>nin0dev <span style="font-size: 0.4em;">(he/him)</span></h3>
</div>

View file

@ -0,0 +1,55 @@
---
import {fetchUserData} from "lanyard-wrapper";
const rawUserData = await fetchUserData("886685857560539176");
const activity = (() => {
let finalActivity = {
type: undefined,
name: undefined,
artist: undefined
};
rawUserData.activities.some((activity => {
if(activity.type === 0) {
finalActivity = {
type: "playing",
name: activity.name,
artist: undefined
};
return;
}
}));
if(finalActivity.type !== undefined) return finalActivity;
if(rawUserData.listening_to_spotify) {
finalActivity = {
type: "listening",
name: rawUserData.spotify.song,
artist: rawUserData.spotify.artist
};
};
return finalActivity;
})();
---
<style>
div {
margin-top: 10px;
display: flex;
}
p {
margin-top: auto;
margin-bottom: auto;
margin-left: 10px;
}
img {
width: 30px;
height: 30px;
}
</style>
{
activity.type !== undefined &&
<div>
<img src={activity.type === "playing" ? "/game.ico" : "/music.ico"}>
<p>{`${activity.type === "playing" ? "Playing" : "Listening to"} ${activity.name}${activity.type === "listening" ? ` - ${activity.artist}` : ""}`}</p>
</div>
}

View file

@ -0,0 +1,16 @@
---
const {platform, name, url, note} = Astro.props;
---
<style>
bl {
font-weight: 500;
}
it {
font-style: italic;
}
</style>
<li>
<bl>{platform}</bl>: {url ? <a href={url}>{name}</a> : name}{note && <it> ({note})</it>}
</li>

View file

@ -0,0 +1 @@
<span />

View file

@ -0,0 +1,35 @@
---
const {title, showClose, maxWidth} = Astro.props
---
<style define:vars={{ maxWidth }}>
.window {
max-width: var(--maxWidth);
position: absolute;
}
.window-body {
padding: 20px !important;
}
@media (pointer:coarse) {
.window {
margin-right: 20px;
}
}
</style>
<div class="background" class="window">
<div class="window glass active" style="max-width: 100%">
<div class="title-bar">
<div class="title-bar-text">{title}</div>
{
showClose &&
<div class="title-bar-controls">
<button aria-label="Close"></button>
</div>
}
</div>
<div class="window-body has-space">
<slot />
</div>
</div>
</div>

11
src/css/style.css Normal file
View file

@ -0,0 +1,11 @@
body {
background-color: #56a0d1;
padding: 30px;
font-family: sans-serif !important;
overflow: hidden;
}
@media (pointer:coarse) {
body {
overflow: scroll;
}
}

1
src/env.d.ts vendored Normal file
View file

@ -0,0 +1 @@
/// <reference types="astro/client" />

56
src/js/drag.js Normal file
View file

@ -0,0 +1,56 @@
// wow i love being fake programmer
// source: https://jams.hackclub.com/batch/webOS/part-3
function dragElement(element) {
// Step 2: Set up variables to keep track of the element's position.
var initialX = 0;
var initialY = 0;
var currentX = 0;
var currentY = 0;
// Step 3: Check if there is a special header element associated with the draggable element.
if (document.getElementById("title-bar")) {
// Step 4: If present, assign the `dragMouseDown` function to the header's `onmousedown` event.
// This allows you to drag the window around by its header.
document.getElementById("title-bar").onmousedown = startDragging;
} else {
// Step 5: If not present, assign the function directly to the draggable element's `onmousedown` event.
// This allows you to drag the window by holding down anywhere on the window.
element.onmousedown = startDragging;
}
// Step 6: Define the `startDragging` function to capture the initial mouse position and set up event listeners.
function startDragging(e) {
e = e || window.event;
e.preventDefault();
// Step 7: Get the mouse cursor position at startup.
initialX = e.clientX;
initialY = e.clientY;
// Step 8: Set up event listeners for mouse movement (`elementDrag`) and mouse button release (`closeDragElement`).
document.onmouseup = stopDragging;
document.onmousemove = dragElement;
}
// Step 9: Define the `elementDrag` function to calculate the new position of the element based on mouse movement.
function dragElement(e) {
e = e || window.event;
e.preventDefault();
// Step 10: Calculate the new cursor position.
currentX = initialX - e.clientX;
currentY = initialY - e.clientY;
initialX = e.clientX;
initialY = e.clientY;
// Step 11: Update the element's new position by modifying its `top` and `left` CSS properties.
console.log(element.offsetTop);
console.log(currentX);
element.style.top = (element.offsetTop - currentY) + "px";
element.style.left = (element.offsetLeft - currentX) + "px";
}
// Step 12: Define the `stopDragging` function to stop tracking mouse movement by removing the event listeners.
function stopDragging() {
document.onmouseup = null;
document.onmousemove = null;
console.log(element.offsetTop - currentY);
console.log(element.offsetLeft - currentX);
}
}

View file

@ -0,0 +1,76 @@
---
import "7.css/dist/7.css";
import "../css/style.css";
const {tabTitle} = Astro.props;
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>{tabTitle}</title>
</head>
<body>
<slot />
<script>
function dragElement(element) {
// Step 2: Set up variables to keep track of the element's position.
var initialX = 0;
var initialY = 0;
var currentX = 0;
var currentY = 0;
// Step 3: Check if there is a special header element associated with the draggable element.
if (document.getElementById("title-bar")) {
// Step 4: If present, assign the `dragMouseDown` function to the header's `onmousedown` event.
// This allows you to drag the window around by its header.
document.getElementById("title-bar").onmousedown = startDragging;
} else {
// Step 5: If not present, assign the function directly to the draggable element's `onmousedown` event.
// This allows you to drag the window by holding down anywhere on the window.
element.onmousedown = startDragging;
}
// Step 6: Define the `startDragging` function to capture the initial mouse position and set up event listeners.
function startDragging(e) {
e = e || window.event;
e.preventDefault();
// Step 7: Get the mouse cursor position at startup.
initialX = e.clientX;
initialY = e.clientY;
// Step 8: Set up event listeners for mouse movement (`elementDrag`) and mouse button release (`closeDragElement`).
document.onmouseup = stopDragging;
document.onmousemove = dragElement;
}
// Step 9: Define the `elementDrag` function to calculate the new position of the element based on mouse movement.
function dragElement(e) {
e = e || window.event;
e.preventDefault();
// Step 10: Calculate the new cursor position.
currentX = initialX - e.clientX;
currentY = initialY - e.clientY;
initialX = e.clientX;
initialY = e.clientY;
// Step 11: Update the element's new position by modifying its `top` and `left` CSS properties.
element.style.top = (element.offsetTop - currentY) + "px";
element.style.left = (element.offsetLeft - currentX) + "px";
}
// Step 12: Define the `stopDragging` function to stop tracking mouse movement by removing the event listeners.
function stopDragging() {
document.onmouseup = null;
document.onmousemove = null;
}
}
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll(".window").forEach(window => {
dragElement(window);
});
});
</script>
</body>
</html>

10
src/pages/index.astro Normal file
View file

@ -0,0 +1,10 @@
---
import FearOfTechnology from "../components/FearOfTechnology.astro";
import MainWindow from "../components/MainWindow.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
---
<BaseLayout tabTitle="Home - nin0dev">
<FearOfTechnology />
<MainWindow />
</BaseLayout>

View file

@ -1,61 +0,0 @@
:root {
--online-color: #23a55a;
--idle-color: #f0b232;
--dnd-color: #f23f43;
--offline-color: #80848e;
}
body {
padding: 30px;
font-family: "Segoe UI", "Roboto", sans-serif !important;
background-color: #56a0d1;
}
#main-window {
max-width: 600px;
}
.window-body {
padding: 10px;
}
#header {
display: flex;
}
#header h3 {
font-weight: 400;
margin-left: 20px;
margin-top: auto;
margin-bottom: auto;
}
#pfp {
width: 90px;
height: 90px;
border-radius: 6px;
box-shadow: 10px black;
border-color: var(--offline-color);
border-style: solid;
border-width: 2px;
}
a {
color: blue;
}
li {
padding: 2px;
}
#presence img {
width: 30px;
height: 30px;
}
#presence-content {
margin-top: auto;
margin-bottom: auto;
margin-left: 10px;
}
#presence {
display: flex;
}
#bottom-actions {
display: flex;
align-items: end;
justify-content: right;
}

3
tsconfig.json Normal file
View file

@ -0,0 +1,3 @@
{
"extends": "astro/tsconfigs/base"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB