finish blog

 add first blog entry
🎨 rework ui+ux
 add freemono
This commit is contained in:
lia
2025-08-24 03:46:08 +00:00
parent f1c471839f
commit 2e397c5be3
19 changed files with 788 additions and 322 deletions

View File

@@ -22,14 +22,16 @@ serde = { version = "1.0" }
wasm-bindgen-futures = "0.4.50"
serde_json = "1.0.143"
lsp-types = "0.97"
chrono = "0.4"
yew-markdown = { git = "https://git.celesteflare.cc/i0uring/page_md.git", rev = "1e9840" }
yew-hooks = "0.3"
[patch.crates-io]
yew = { git = "https://github.com/yewstack/yew.git", rev = "21f373b", features = [
"csr",
], optional = false }
[dependencies.web-sys]
version = "0.3"
features = [
'HtmlCanvasElement',
'WebGlBuffer',
'WebGlProgram',
'WebGlRenderingContext',
'WebGl2RenderingContext',
'WebGlShader',
'WebGlUniformLocation',
]
features = ["HtmlCanvasElement", "WebGlBuffer", "WebGlProgram", "WebGlRenderingContext", "WebGl2RenderingContext", "WebGlShader", "WebGlUniformLocation", "Navigator", "Clipboard"]

View File

@@ -10,6 +10,8 @@
<link data-trunk rel="copy-file" href="public/misc/404.png" />
<link data-trunk rel="copy-file" href="public/misc/profile.avif" />
<link data-trunk rel="copy-file" href="public/misc/oneko.gif" />
<link data-trunk rel="copy-file" href="public/misc/freemono.ttf" />
<link data-trunk rel="copy-file" href="public/misc/monocraft.ttf" />
<link data-trunk rel="copy-file" href="public/blog/testimage.jpg" />
@@ -31,7 +33,7 @@
<link data-trunk rel="copy-file" href="public/buttons/void.png" />
<link data-trunk rel="copy-file" href="public/buttons/aqueer.png" />
<!--<link data-trunk rel="sass" href="main.scss" />-->
<link data-trunk rel="sass" href="main.scss" />
<link data-trunk rel="rust" />
<base data-trunk-public-url />
</head>

View File

@@ -1,12 +1,17 @@
@charset "UTF-8";
@font-face {
font-family: freemono;
src: url("freemono.ttf");
}
@font-face {
font-family: monocraft;
src: url("monocraft.ttf");
}
html * {
font-family: monocraft, monospace !important;
font-family: freemono, monocraft, monospace !important;
scrollbar-color: hsla(232, 97%, 85%, 0.5) hsla(240, 21.05%, 14.9%, 0.7) !important;
scrollbar-width: thin !important;
scroll-behavior: smooth !important;
@@ -47,14 +52,30 @@ a.navbar-item:hover {
}
::-moz-selection {
background: hsla(232, 97%, 85%, 0.4125) !important;
background: #F5C2E740 !important;
}
::selection {
background: hsla(232, 97%, 85%, 0.4125) !important;
background: #F5C2E740 !important;
}
a {
color: #F5C2E7FF !important;
text-decoration: none !important;
}
a:hover {
text-decoration: underline !important;
filter: url("post.bloom.svg#process") !important;
}
button {
background-color: transparent !important;
border-color: transparent !important;
color: white !important;
}
button:hover {
text-decoration: underline !important;
filter: url("post.bloom.svg#process") !important;
}

BIN
public/misc/freemono.ttf Normal file

Binary file not shown.

View File

@@ -1,3 +1,6 @@
#![feature(iter_intersperse)]
extern crate core;
use js_sys::Float32Array;
use log::{info, warn};
use std::cell::RefCell;
@@ -15,7 +18,7 @@ use crate::pages::blog::authors::Authors;
use crate::pages::blog::entries::Entries;
use crate::pages::blog::entry::Entry;
use crate::pages::findme::FindMe;
use crate::pages::projects::Projects;
use crate::pages::projects::projects::Projects;
use pages::not_found::PageNotFound;
#[derive(Routable, PartialEq, Eq, Clone, Debug)]
@@ -45,30 +48,15 @@ pub enum Route {
pub struct App {
node_ref: NodeRef,
navbar_active: bool,
}
pub enum Msg {
ToggleNavbar,
}
impl Component for App {
type Message = Msg;
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
node_ref: NodeRef::default(),
navbar_active: false,
}
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::ToggleNavbar => {
self.navbar_active = !self.navbar_active;
true
}
}
}
@@ -86,10 +74,9 @@ impl Component for App {
" ref={self.node_ref.clone()} />
<BrowserRouter>
<header style="
z-index: 1 !important;
z-index: 2 !important;
display: flex !important;
color: white !important;
font-family: monospace !important;
flex-direction: row !important;
align-items: center !important;
justify-content: center !important;
@@ -97,25 +84,17 @@ impl Component for App {
min-height: 20px !important;
height: 20px !important;
max-height: 20px !important;
filter: url(post.bloom.svg#process) !important;
filter: url(post.bloom.svg) !important;
">
<p>{r"-»{ "}</p>
<Link<Route> to={Route::About}>
<a style="color: #CBA6F7FF !important;">{r"about"}</a>
</Link<Route>>
/*<p>{r""}</p>
<Link<Route> to={Route::Entries}>
<a style="color: #CBA6F7FF !important;">{r"blog"}</a>
</Link<Route>>*/
<p>{r""}</p>
<Link<Route> to={Route::FindMe}>
<a style="color: #CBA6F7FF !important;">{r"findme"}</a>
</Link<Route>>
<p>{r""}</p>
<Link<Route> to={Route::Projects}>
<a style="color: #CBA6F7FF !important;">{r"projects"}</a>
</Link<Route>>
<p>{r" }«-"}</p>
<h3>{r"»[ "}</h3>
<h3><Link<Route> to={Route::About}>{r"about"}</Link<Route>></h3>
<h3>{r"|"}</h3>
<h3><Link<Route> to={Route::Entries}>{r"blog"}</Link<Route>></h3>
<h3>{r"|"}</h3>
<h3><Link<Route> to={Route::FindMe}>{r"findme"}</Link<Route>></h3>
<h3>{r"|"}</h3>
<h3><Link<Route> to={Route::Projects}>{r"projects"}</Link<Route>></h3>
<h3>{r""}</h3>
</header>
<main style="
z-index: 1 !important;
@@ -125,7 +104,6 @@ impl Component for App {
flex-direction: column !important;
min-width: fit-content !important;
width: calc(100vw - 18 px) !important;
font-family: monospace !important;
flex-wrap: nowrap !important;
justify-content: space-between !important;
align-items: center !important;
@@ -228,59 +206,114 @@ impl App {
">
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://i0ur.ing/"><img loading="eager" alt="iouring" src="iouring.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://webassembly.org/"><img loading="eager" alt="wasm" src="wasm.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://beta.servfail.network/"><img loading="eager" alt="servfail" src="servfail.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://www.dataforest.net/en/"><img loading="eager" alt="dataforest" src="dataforest.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://fedoraproject.org/"><img loading="eager" alt="fedora" src="fedora.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://artixlinux.org/"><img loading="eager" alt="artix" src="artix.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://nixos.org/"><img loading="eager" alt="nixos" src="nixos.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://chimera-linux.org/"><img loading="eager" alt="void" src="chimera.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://voidlinux.org/"><img loading="eager" alt="void" src="void.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://www.rust-lang.org/"><img loading="eager" alt="rust" src="rust.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://dotnet.microsoft.com/en-us/"><img loading="eager" alt="csharp" src="csharp.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://kotlinlang.org/"><img loading="eager" alt="kotlin" src="kotlin.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
margin-right: 0.2rem !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
" href="https://www.java.com/"><img loading="eager" alt="java" src="java.png" /></a>
<a style="
width: 88px !important;
height: 31px !important
height: 31px !important;
image-rendering: pixelated !important;
image-resolution: from-image !important;
image-orientation: from-image !important;
"><img loading="eager" alt="aqueer" src="aqueer.png" /></a>
</div>
}

View File

@@ -47,7 +47,7 @@ impl Component for About {
font-weight: bold !important;
font-style: italic !important;
font-size: xx-large !important;
">{r"intro"}<br /><p style="
">{r">intro_"}<br /><p style="
font-weight: normal !important;
font-style: normal !important;
font-size: medium !important;
@@ -58,9 +58,9 @@ impl Component for About {
may sound naive as fuck but fuck it we ball.
audhd (certified) and probably bpd or ptsd. i'm not a psychologist tho.
interact with caution, may bite.
political view's prolly too rad. should be enough to mention i'm social.
political view's prolly very obvious. should be enough to mention i'm social.
figure it yourself. use your brain.
"#}</p>{r"hobbies"}<br /><p style="
"#}</p>{r">hobbies_"}<br /><p style="
font-weight: normal !important;
font-style: normal !important;
font-size: medium !important;

View File

@@ -1,6 +1,8 @@
use crate::pages::blog::content;
use crate::pages::blog::content::BlogEntry;
use crate::pages::blog::content::{BlogEntry, Post};
use yew::prelude::*;
use crate::pages::blog::authorcard::AuthorCard;
use crate::pages::blog::entrycard::EntryCard;
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
pub struct Props {
@@ -27,20 +29,42 @@ impl Component for Author {
fn view(&self, _ctx: &Context<Self>) -> Html {
let Self { author } = self;
let id = author.id;
let cards: Vec<_> = (0..Post::POSTS.len()) // TODO: ... | add var
.filter(|&id_offset| {
Post::from_id(id_offset as u8)
.authors
.iter()
.any(|id1| *id1 == id)
})
.map(|id_offset| html! {<EntryCard id={id_offset as u8} />})
.collect();
html! {
<div>
<img alt="insert pfp here" loading="eager" src={author.image_url.clone()} />
<div style="vertical-align: top !important;">
<p style="filter: url(post.bloom.svg#process) !important; color: #B4BEFE !important;">{author.name.clone()}</p>
<p style="background-clip: text !important; background-image: linear-gradient(45deg, #5BCEFAFF, #F5A9B8FF, #FFFFFFFF) !important;">
{ for author.keywords.iter().map(|tag| html! { <p>{ tag }</p> }) }
</p>
</div>
<hr style="background-color: #B4BEFE60 !important;" />
<p>{r#"about me"#}</p>
<div>
{ author.about.clone() }
</div>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: column !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin-bottom: 2rem !important;
">
<h2 style="text-align: center !important;">{ "about me" }</h2>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin-bottom: 1rem !important;
"><AuthorCard {id} /></div>
<h2 style="text-align: center !important;">{ "my posts" }</h2>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: center !important;
">{ for cards }</div>
</div>
}
}

View File

@@ -32,32 +32,41 @@ impl Component for AuthorCard {
fn view(&self, _ctx: &Context<Self>) -> Html {
let Self { author } = self;
let keywords = author.keywords.iter().map(|keyword| html! {
<p style="margin: unset !important;">{*keyword}</p>
}).collect::<Html>();
html! {
<>
<div>
<div>
<div>
<div>
<figure>
<img alt="this should normally show an image mew,," src={author.image_url.clone()} />
</figure>
</div>
<div>
<p>{ &author.name }</p>
<p>
{ "I like " }
<b>{ author.keywords.join(", ") }</b>
</p>
</div>
</div>
<div style="
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
background-color: #ECBEE130 !important;
border-radius: 0.5rem !important;
width: fit-content !important;
height: fit-content !important;
text-align: left !important;
margin: 1rem 1rem 0 0 !important;
">
<img style="
float: left !important;
margin-right: 0.3rem !important;
border-radius: 0.5rem !important;
" alt="insert pfp here" width="96" height="96" src={author.image_url} />
<div style="
display: flex !important;
flex-direction: column !important;
flex-wrap: wrap !important;
margin-top: 0.3rem !important;
margin-right: 0.3rem !important;
">
<h3 style="margin: unset !important;">
<Link<Route> to={Route::Author { id: author.id }}>
{ &*author.name }
</Link<Route>>
</h3>
{ keywords }
</div>
<footer>
<Link<Route> classes={classes!("card-footer-item")} to={Route::Author { id: author.id }}>
{ "Profile" }
</Link<Route>>
</footer>
</div>
</>
}
}
}

View File

@@ -1,31 +1,31 @@
use yew::prelude::*;
use crate::pages::blog::authorcard::AuthorCard;
use crate::pages::blog::content::{Author, BlogEntry};
/*pub enum Msg {
NextAuthors,
}*/
pub struct Authors {
ids: Vec<u8>,
}
pub struct Authors;
impl Component for Authors {
type Message = (); //Msg;
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self { ids: vec![0], }
Self
}
/*fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg { Msg::NextAuthors => { self.ids = vec![0]; true } }
}*/
fn view(&self, _: &Context<Self>) -> Html {
html! {
{ for self.ids.iter().map(|&id| { html! {
<AuthorCard {id} />
} }) }
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin-top: 2rem !important;
margin-bottom: 2rem !important;
">{ for Author::AUTHORS.map(|author| {
let id = author.id;
html! { <AuthorCard {id} /> }
}) }</div>
}
}
}

View File

@@ -1,58 +1,48 @@
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Author {
pub id: u8,
pub image_url: String,
pub name: String,
pub keywords: Vec<String>,
pub about: String,
pub image_url: &'static str,
pub name: &'static str,
pub keywords: &'static [&'static str],
pub about: &'static str,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Post {
pub id: u8,
pub authors: &'static [u8],
pub title: &'static str,
pub utcdate: &'static str,
pub content: &'static str,
}
impl BlogEntry for Author {
fn from_entry(entry: &mut Entry) -> Self {
match entry.id {
0 => Self {
id: entry.id,
image_url: "profile.avif".to_string(),
name: "iouring".to_string(),
keywords: vec!["meow".to_string(), "mrrp".to_string(), "mew".to_string()],
about: "sup".to_string(),
},
_ => Self {
*Self::AUTHORS
.get(entry.id as usize)
.cloned()
.unwrap_or(&Self {
id: u8::MAX,
image_url: "".to_string(),
name: "not found".to_string(),
keywords: vec![],
about: "".to_string(),
},
}
image_url: "",
name: "not found",
keywords: [].as_slice(),
about: "",
})
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Post {
pub id: u8,
pub author: Author,
pub title: String,
pub content: Vec<String>,
}
impl BlogEntry for Post {
fn from_entry(entry: &mut Entry) -> Self {
return match entry.id {
0 => Self {
id: 0,
author: Author::from_id(0),
title: "meow".parse().unwrap(),
content: vec!["<h1>meow</h1>", "mrrp", "meow"]
.iter()
.map(|s| s.to_string())
.collect(),
},
_ => Self {
*Self::POSTS
.get(entry.id as usize)
.cloned()
.unwrap_or(&Self {
id: u8::MAX,
author: Author::from_id(u8::MAX),
title: "not found".parse().unwrap(),
content: vec![],
},
};
authors: &[u8::MAX],
title: "not found",
utcdate: "1970-01-01",
content: "",
})
}
}
@@ -65,10 +55,170 @@ impl Entry {
Self { id: seed }
}
}
pub trait BlogEntry: Sized {
fn from_entry(entry: &mut Entry) -> Self;
fn from_id(id: u8) -> Self {
Self::from_entry(&mut Entry::from_id(id))
}
const AUTHORS: [&'static Author; 2] = [
&Author {
id: 0,
image_url: "profile.avif",
name: "lia",
keywords: &[
"certified catgirl™",
"software engineer",
"professional yapper",
"neurospicy and disabled"
],
about: "",
},
&Author {
id: 1,
image_url: "",
name: "mreowww",
keywords: &["meow", "mrrp", "mew"],
about: "",
},
];
const POSTS: [&'static Post; 1] = [
/*&Post {
id: 0,
authors: &[0],
title: "sweet little poison",
utcdate: "1970-01-01",
content: r#"
### this will be a future write-up how i set up iocaine with caddy and docker.
### here's my docker-compose.yml:
```yml
services:
caddy:
image: caddy:alpine
container_name: proxy.caddy
hostname: proxy.caddy
restart: unless-stopped
cap_add:
- NET_ADMIN
ports:
- "80:80"
- "443:443"
- "443:443/udp"
networks:
- nginx
volumes:
- ./socks:/run/iocaine:ro
- ./nginx/pages:/var/www/html
- ./caddy/data:/data
- ./caddy/config:/config
- ./caddy/proxy:/etc/caddy/Caddyfile:ro
depends_on:
- iocaine
iocaine:
image: git.madhouse-project.org/iocaine/iocaine:2
container_name: proxy.iocaine
hostname: proxy.iocaine
restart: unless-stopped
ports:
- "42069:42069"
networks:
- nginx
volumes:
- ./iocaine:/data
- ./socks:/run/iocaine:rw
# - iocainesocket:/run/iocaine/waow.socket:rw
environment:
# - IOCAINE__SERVER__BIND="0.0.0.0:42069"
- IOCAINE__SERVER__BIND="/run/iocaine/waow.socket"
- IOCAINE__SERVER__UNIX_LISTEN_ACCESS="everybody"
- IOCAINE__SERVER__REQUEST_HANDLER__PATH="/data"
- IOCAINE__SERVER__REQUEST_HANDLER__LANGUAGE="roto"
- IOCAINE__SERVER__CONTROL__BIND="/run/iocaine/listen.socket"
- IOCAINE__SERVER__CONTROL__UNIX_LISTEN_ACCESS="owner"
- IOCAINE__SOURCES__WORDS="/data/words.txt"
- IOCAINE__SOURCES__MARKOV=["/data/1984.txt", "/data/brave-new-world.txt"]
- IOCAINE__METRICS__ENABLE=false
command: --config-file /data/config.toml
networks:
nginx:
external: true
```
### my file-tree:
```sh
services/proxy » tree iocaine
iocaine
├── 1984.txt
├── brave-new-world.txt
├── nam_shub_of_enki
│   ├── classify
│   │   └── mod.roto
│   ├── config.roto
│   ├── detect
│   │   └── mod.roto
│   ├── mod.roto
│   └── tests
│   └── mod.roto
├── nam-shub-of-enki-20250711.0.tar.zst
├── nam-shub-of-enki-latest.tar.zst
├── pkg.roto
├── robots.json
└── words.txt
```
### and my caddy-snippet with example:
```txt
(iocaine) {
@read method GET HEAD
@not-read not {
method GET HEAD
}
reverse_proxy @read unix//run/iocaine/waow.socket {
#reverse_proxy @read proxy.iocaine:42069 {
@fallback status 421
handle_response @fallback {
{blocks.handler}
}
}
handle @not-read {
{blocks.default}
}
}
example.com {
import iocaine {
handler {
reverse_proxy http://example:8080
}
default {
respond 405
}
}
}
```
"#,
},
*/&Post {
id: 0,
authors: &[0],
title: "haj, world!",
utcdate: "2025-08-24",
content: r#"
### my first blogpost
haj! and welcome to my first blogpost.
this blogpost won't have that much content.
fun fact: this post generates html from markdown :3
so i can include images, formatted text, code and content much easier.
i also added a too overcomplicated blog backend that allows authors and posts by u8::MAX, cause why not.
won't post that much either way, so why bother with higher values. /srs
nonetheless... have a great day, evening, whatever daytime it's for you rn and stay safe. ♡s
"#,
},
];
}

View File

@@ -1,7 +1,7 @@
use yew::prelude::*;
use crate::pages::blog::content::{Author, Post};
use crate::pages::blog::content::BlogEntry;
use crate::pages::blog::content::Post;
use crate::pages::blog::entrycard::EntryCard;
pub struct Entries {}
@@ -10,15 +10,18 @@ impl Component for Entries {
type Message = ();
type Properties = ();
fn create(ctx: &Context<Self>) -> Self {
fn create(_ctx: &Context<Self>) -> Self {
Self {}
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div>
<h1>{ "entries" }</h1>
<h2>{ "here are some things i yapped about" }</h2>
<h1 style="margin: unset !important;">{ "entries" }</h1>
<h2 style="
margin: unset !important;
margin-bottom: 1rem !important;
">{ "here are some things i yapped about" }</h2>
{ self.view_posts(ctx) }
</div>
}
@@ -26,12 +29,27 @@ impl Component for Entries {
}
impl Entries {
fn view_posts(&self, _ctx: &Context<Self>) -> Html {
let cards: Vec<_> = (0..2) // TODO: ... | add var
.filter(|&id_offset| Post::from_id(id_offset).author.id != u8::MAX)
.map(|id_offset| {
html! {<EntryCard id={id_offset} />}
let cards: Vec<_> = (0..Post::POSTS.len()) // TODO: ... | add var
.filter(|&id_offset| {
Post::from_id(id_offset as u8)
.authors
.iter()
.all(|id| *id != u8::MAX)
})
.map(|id_offset| html! {<EntryCard id={id_offset as u8} />})
.collect();
html! { { for cards } }
html! {
<div style="
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin: unset !important;
margin-bottom: 1rem !important;
width: 100% !important;
">
{ for cards }
</div>
}
}
}

View File

@@ -1,10 +1,11 @@
use std::rc::Rc;
use yew::prelude::*;
use yew_markdown::Markdown;
use yew_router::prelude::*;
use crate::pages::blog::content;
use crate::pages::blog::content::BlogEntry;
use crate::pages::blog::content::{Author, BlogEntry};
use crate::Route;
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
@@ -47,18 +48,30 @@ pub fn Entry(props: &Props) -> Html {
html! {
<>
<h1>
{ &post.title }
</h1>
<h2>
{ "by " }
<Link<Route> to={Route::Author { id: post.author.id }}>
{ &post.author.name }
</Link<Route>>
</h2>
<div>
{ for post.content.iter() }
<h1 style="
color: #F5C2E7FF !important;
margin: unset !important;
filter: url(post.bloom.svg#process) !important;
">{ &*post.title }</h1>
<div style="flex-direction: column !important;">
<h2 style="margin: unset !important;">
{ "written by " } {
post.authors.iter().map(|id| {
let author = Author::from_id(*id);
html! {
<Link<Route> to={crate::Route::Author { id: author.id }}>
{ &*author.name }
</Link<Route>>
}
}).intersperse(html! { ", " }).collect::<Html>()
} { format!(" on {}", &post.utcdate) }
</h2>
</div>
<Markdown
src={post.content}
hard_line_breaks={true}
send_debug_info={Callback::noop()}
/>
</>
}
}

View File

@@ -1,9 +1,8 @@
use std::rc::Rc;
use yew::prelude::*;
use yew_router::components::Link;
use crate::pages::blog::content::{BlogEntry, Post};
use crate::pages::blog::content::{Author, BlogEntry, Post};
use crate::Route;
@@ -48,13 +47,52 @@ pub fn EntryCard(props: &PropsEntryCard) -> Html {
let post = &post.inner;
html! {
<div style="height: fit-content !important; width: fit-content !important;">
<Link<Route> classes={classes!("title", "is-block")} to={Route::Entry { id: post.id }}>
{ &post.title }
</Link<Route>>
<Link<Route> classes={classes!("subtitle", "is-block")} to={Route::Author { id: post.author.id }}>
{ &post.author.name }
<div style="
display: flex !important;
flex-direction: column !important;
flex-wrap: wrap !important;
background-color: #ECBEE130 !important;
border-radius: 0.5rem !important;
width: fit-content !important;
height: fit-content !important;
text-align: left !important;
margin: 1rem 1rem 0 0 !important;
">
<Link<Route> to={Route::Entry { id: post.id }}>
<h2 style="
margin: unset !important;
margin-top: 0.3rem !important;
margin-left: 0.3rem !important;
margin-right: 0.3rem !important;
">{ &*post.title }</h2>
</Link<Route>>
<h3 style="
margin: unset !important;
margin-left: 0.3rem !important;
margin-right: 0.3rem !important;
">
{ format!("published {}", post.utcdate) }
</h3>
<div style="flex-direction: column !important;">
<h3 style="
margin: unset !important;
margin-left: 0.3rem !important;
margin-right: 0.3rem !important;
margin-bottom: 0.3rem !important;
">
{ "written by " }
{
post.authors.iter().map(|id| {
let author = Author::from_id(*id);
html! {
<Link<Route> to={crate::Route::Author { id: author.id }}>
{ &*author.name }
</Link<Route>>
}
}).intersperse(html! { ", " }).collect::<Html>()
}
</h3>
</div>
</div>
}
}

View File

@@ -1,3 +1,4 @@
use web_sys::window;
use yew::prelude::*;
pub struct FindMe;
@@ -10,58 +11,128 @@ impl Component for FindMe {
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let clipboard = window().expect("meow").navigator().clipboard();
let handle_copy_matrix = {
let clipboard = clipboard.clone();
Callback::from(move |_| {
let _ = clipboard.write_text(&*"@iouring:hi.stellaris.fyi".to_string());
})
};
let handle_copy_telegram = {
let clipboard = clipboard.clone();
Callback::from(move |_| {
let _ = clipboard.write_text(&*"@luc1ell3".to_string());
})
};
let handle_copy_discord = {
let clipboard = clipboard.clone();
Callback::from(move |_| {
let _ = clipboard.write_text(&*"@donotusedisc0rdkthxbye".to_string());
})
};
html! {
<>
<p style="
font-weight: bold !important;
font-style: italic !important;
font-size: xx-large !important;
">{r"follow us"}<br /><p style="
font-weight: normal !important;
font-style: normal !important;
font-size: medium !important;
">{" × "}<a style="
color: #F5C2E7FF !important;
text-decoration: none !important;
filter: url(post.bloom.svg#process) !important;
" href="https://ice.stellaris.fyi/@iouring">{r"fediverse"}</a><br />
{" × "}<a style="
color: #B4BEFEFF !important;
text-decoration: none !important;
" href="https://bsky.app/profile/i0ur.ing">{r"bluesky"}</a><br />
</p>{r"write us"}<br /><p style="
font-weight: normal !important;
font-style: normal !important;
font-size: medium !important;
"><a style="
color: #94E2D5FF !important;
filter: url(post.bloom.svg#process) !important;
">{r" × matrix » @iouring:hi.stellaris.fyi"}</a><br />
<a style="color: #89B4FAFF !important;">{r" × telegr » @luc1ell3"}</a><br />
<a style="color: #F38BA8FF !important;">{r" × ewcord » @donotusedisc0rdkthxbye"}</a>
</p>{r"git gud"}<br /><p style="
font-weight: normal !important;
font-style: normal !important;
font-size: medium !important;
">{" × "}<a style="
color: #F5C2E7FF !important;
text-decoration: none !important;
filter: url(post.bloom.svg#process) !important;
" href="https://git.celesteflare.cc/i0uring">{r"my own!!!"}</a><br />
{" × "}<a style="
color: #CBA6F7FF !important;
text-decoration: none !important;
" href="https://git.gay/luciel">{r"the gay one"}</a><br />
{" × "}<a style="
color: #B4BEFEFF !important;
text-decoration: none !important;
" href="https://git.rimuru.club/i0uring">{r"git of fren"}</a><br />
{" × "}<a style="
color: #89B4FAFF !important;
text-decoration: none !important;
" href="https://codeberg.org/i0uring">{r"a mountain what"}</a>
</p></p>
</>
<div style="
display: flex !important;
flex-direction: row !mportant;
flex-wrap: wrap !important;
justify-content: center !important;
width: 100% !important;
">
<div style="
width: fit-content !important;
height: fit-content !important;
margin: 1rem 1rem 1rem 1rem !important;
">
<p style="
font-weight: bold !important;
font-style: normal !important;
font-size: xx-large !important;
text-align: center !important;
margin: unset !important;
">{r"follow us"}</p>
<p style="
font-weight: normal !important;
font-style: normal !important;
font-size: large !important;
">{" × "}<a style="
color: #F5C2E7FF !important;
" href="https://ice.stellaris.fyi/@iouring">{r"fediverse"}</a><br />
{" × "}<a style="
color: #B4BEFEFF !important;
" href="https://bsky.app/profile/i0ur.ing">{r"bluesky"}</a><br />
</p>
</div>
<div style="
width: fit-content !important;
height: fit-content !important;
margin: 1rem 1rem 1rem 1rem !important;
">
<p style="
font-weight: bold !important;
font-style: normal !important;
font-size: xx-large !important;
text-align: center !important;
margin: unset !important;
">{r"write us"}</p>
<p style="
font-weight: normal !important;
font-style: normal !important;
font-size: large !important;
">
{"× "}
<button style="
color: #94E2D5FF !important;
font-size: large !important;
" onclick={handle_copy_matrix}>{r"matrix"}</button>
<br />
{"× "}
<button style="
color: #B4BEFEFF !important;
font-size: large !important;
" onclick={handle_copy_telegram}>{r"telegr"}</button>
<br />
{"× "}
<button style="
color: #F38BA8FF !important;
font-size: large !important;
" onclick={handle_copy_discord}>{r"ewcord"}</button>
</p>
</div>
<div style="
width: fit-content !important;
height: fit-content !important;
margin: 1rem 1rem 1rem 1rem !important;
">
<p style="
font-weight: bold !important;
font-style: normal !important;
font-size: xx-large !important;
text-align: center !important;
margin: unset !important;
">{r"git gud"}</p>
<p style="
font-weight: normal !important;
font-style: normal !important;
font-size: large !important;
">{" × "}<a style="
color: #F5C2E7FF !important;
" href="https://git.celesteflare.cc/i0uring">{r"my own!!!"}</a><br />
{" × "}<a style="
color: #CBA6F7FF !important;
" href="https://git.gay/luciel">{r"the gay one"}</a><br />
{" × "}<a style="
color: #B4BEFEFF !important;
" href="https://git.rimuru.club/i0uring">{r"git of fren"}</a><br />
{" × "}<a style="
color: #89B4FAFF !important;
" href="https://codeberg.org/i0uring">{r"a mountain what"}</a>
</p>
</div>
</div>
}
}
}

View File

@@ -1,77 +0,0 @@
use yew::prelude::*;
pub struct Projects;
impl Component for Projects {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
<>
<div style="height: auto !important;">
{ self.view_projects_ongoing() }
{ self.view_projects_finished() }
</div>
</>
}
}
}
impl Projects {
fn view_projects_ongoing(&self) -> Html {
html! {
<>
<p>{r#"ongoing projects"#}</p>
<div>
<p><a href="https://git.celesteflare.cc/i0uring/app_catnip">
{r#"catnip"#}
</a></p>
<p>{r#"all-rounder ide in the making"#}</p>
</div>
<div>
<p><a href="https://git.celesteflare.cc/i0uring/app_nekochat">
{r#"neko chat"#}
</a></p>
<p>{r#"my planned matrix client"#}</p>
</div>
</>
}
}
fn view_projects_finished(&self) -> Html {
html! {
<>
<p>{r#"finished projects"#}</p>
<div>
<div>
<p><a href="https://git.celesteflare.cc/i0uring/lib_tinyevents">
{r#"tiny events"#}
</a></p>
<p>{r#"a java seventeen (and up) event-sys that is able to be scaled in large systems."#}</p>
</div>
<div>
<p><a href="https://git.celesteflare.cc/i0uring/dotfiles">
{r#"dotfiles"#}
</a></p>
<p>{r#"my personal set of configurations for different things"#}</p>
</div>
<div>
<p><a href="https://git.celesteflare.cc/i0uring/lib_swingify">
{r#"swingify"#}
</a></p>
<p>{r#"my java swing wrapper to simplify window creation for bogus-brains."#}</p>
</div>
<div>
<p><a href="https://git.celesteflare.cc/stellaris/mod_mnet">
{r#"modern netty"#}
</a></p>
<p>{r#"fabric mod that adds experimental iouring and kqueue support."#}</p>
</div>
</div>
</>
}
}
}

View File

@@ -0,0 +1,51 @@
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Project {
pub url: &'static str,
pub name: &'static str,
pub desc: &'static str,
}
impl ProjectEntry for Project {}
pub trait ProjectEntry: Sized {
const PROJECTS_ONGOING: [&'static Project; 3] = [
&Project {
url: "https://git.celesteflare.cc/stellaris/mod_headsup",
name: "headsup mod",
desc: "extensible hud mc mod",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/app_catnip",
name: "catnip",
desc: "all-rounder ide in the making",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/app_nekochat",
name: "neko chat",
desc: "my planned matrix client",
},
];
const PROJECTS_FINISHED: [&'static Project; 4] = [
&Project {
url: "https://git.celesteflare.cc/i0uring/lib_tinyevents",
name: "tiny events",
desc: "a java 21+ event-sys",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/dotfiles",
name: "dotfiles",
desc: "personal set of configurations",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/lib_swingify",
name: "tiny events",
desc: "simplifies java swing window creation",
},
&Project {
url: "https://git.celesteflare.cc/i0uring/dotfiles",
name: "modern netty",
desc: "adds experimental netty handlers to mc",
},
];
}

View File

@@ -0,0 +1,3 @@
pub mod content;
pub mod projectcard;
pub mod projects;

View File

@@ -0,0 +1,54 @@
use yew::prelude::*;
use crate::pages::projects::content::Project;
#[derive(Clone, Debug, PartialEq, Eq, Properties)]
pub struct PropsAuthorCard {
pub project: Project,
}
pub struct ProjectCard {
project: Project,
}
impl Component for ProjectCard {
type Message = ();
type Properties = PropsAuthorCard;
fn create(ctx: &Context<Self>) -> Self {
Self {
project: ctx.props().project,
}
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let Self { project } = self;
html! {
<div style="
display: flex !important;
flex-direction: row !important;
flex-wrap: wrap !important;
background-color: #ECBEE130 !important;
border-radius: 0.5rem !important;
width: fit-content !important;
height: fit-content !important;
text-align: left !important;
margin: 1rem 1rem 0 0 !important;
">
<div style="
display: flex !important;
flex-direction: column !important;
flex-wrap: wrap !important;
margin: 0.3rem 0.3rem 0.3rem 0.3rem !important;
">
<h2 style="margin: unset !important;">
<a href={project.url}>{ &*project.name }</a>
</h2>
<h3 style="margin: unset !important;">
{ &*project.desc }
</h3>
</div>
</div>
}
}
}

View File

@@ -0,0 +1,54 @@
use crate::pages::projects::content::{Project, ProjectEntry};
use crate::pages::projects::projectcard::ProjectCard;
use yew::prelude::*;
pub struct Projects;
impl Component for Projects {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _ctx: &Context<Self>) -> Html {
let projects_ongoing = Project::PROJECTS_ONGOING.map(|project| {
let project = *project;
html! { <ProjectCard {project} /> }
});
let projects_finished = Project::PROJECTS_FINISHED.map(|project| {
let project = *project;
html! { <ProjectCard {project} /> }
});
html! {
<div style="
display: flex !important;
width: 100% !important;
flex-direction: column !important;
flex-wrap: wrap !important;
justify-content: center !important;
margin-bottom: 2rem !important;
">
<h2 style="text-align: center !important;">{ "ongoing projects" }</h2>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: flex-start !important;
margin-bottom: 1rem !important;
">{ for projects_ongoing }</div>
<h2 style="text-align: center !important;">{ "finished projects" }</h2>
<div style="
display: flex !important;
width: 100% !important;
flex-direction: row !important;
flex-wrap: wrap !important;
justify-content: flex-start !important;
">{ for projects_finished }</div>
</div>
}
}
}