✨ finish blog
✨ add first blog entry 🎨 rework ui+ux ✨ add freemono
This commit is contained in:
20
Cargo.toml
20
Cargo.toml
@@ -22,14 +22,16 @@ serde = { version = "1.0" }
|
|||||||
wasm-bindgen-futures = "0.4.50"
|
wasm-bindgen-futures = "0.4.50"
|
||||||
serde_json = "1.0.143"
|
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]
|
[dependencies.web-sys]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
features = [
|
features = ["HtmlCanvasElement", "WebGlBuffer", "WebGlProgram", "WebGlRenderingContext", "WebGl2RenderingContext", "WebGlShader", "WebGlUniformLocation", "Navigator", "Clipboard"]
|
||||||
'HtmlCanvasElement',
|
|
||||||
'WebGlBuffer',
|
|
||||||
'WebGlProgram',
|
|
||||||
'WebGlRenderingContext',
|
|
||||||
'WebGl2RenderingContext',
|
|
||||||
'WebGlShader',
|
|
||||||
'WebGlUniformLocation',
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
<link data-trunk rel="copy-file" href="public/misc/404.png" />
|
<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/profile.avif" />
|
||||||
<link data-trunk rel="copy-file" href="public/misc/oneko.gif" />
|
<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/misc/monocraft.ttf" />
|
||||||
|
|
||||||
<link data-trunk rel="copy-file" href="public/blog/testimage.jpg" />
|
<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/void.png" />
|
||||||
<link data-trunk rel="copy-file" href="public/buttons/aqueer.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" />
|
<link data-trunk rel="rust" />
|
||||||
<base data-trunk-public-url />
|
<base data-trunk-public-url />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
27
main.scss
27
main.scss
@@ -1,12 +1,17 @@
|
|||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: freemono;
|
||||||
|
src: url("freemono.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: monocraft;
|
font-family: monocraft;
|
||||||
src: url("monocraft.ttf");
|
src: url("monocraft.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
html * {
|
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-color: hsla(232, 97%, 85%, 0.5) hsla(240, 21.05%, 14.9%, 0.7) !important;
|
||||||
scrollbar-width: thin !important;
|
scrollbar-width: thin !important;
|
||||||
scroll-behavior: smooth !important;
|
scroll-behavior: smooth !important;
|
||||||
@@ -47,14 +52,30 @@ a.navbar-item:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
::-moz-selection {
|
::-moz-selection {
|
||||||
background: hsla(232, 97%, 85%, 0.4125) !important;
|
background: #F5C2E740 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background: hsla(232, 97%, 85%, 0.4125) !important;
|
background: #F5C2E740 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #F5C2E7FF !important;
|
||||||
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: underline !important;
|
text-decoration: underline !important;
|
||||||
filter: url("post.bloom.svg#process") !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
BIN
public/misc/freemono.ttf
Normal file
Binary file not shown.
137
src/main.rs
137
src/main.rs
@@ -1,3 +1,6 @@
|
|||||||
|
#![feature(iter_intersperse)]
|
||||||
|
extern crate core;
|
||||||
|
|
||||||
use js_sys::Float32Array;
|
use js_sys::Float32Array;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@@ -15,7 +18,7 @@ use crate::pages::blog::authors::Authors;
|
|||||||
use crate::pages::blog::entries::Entries;
|
use crate::pages::blog::entries::Entries;
|
||||||
use crate::pages::blog::entry::Entry;
|
use crate::pages::blog::entry::Entry;
|
||||||
use crate::pages::findme::FindMe;
|
use crate::pages::findme::FindMe;
|
||||||
use crate::pages::projects::Projects;
|
use crate::pages::projects::projects::Projects;
|
||||||
use pages::not_found::PageNotFound;
|
use pages::not_found::PageNotFound;
|
||||||
|
|
||||||
#[derive(Routable, PartialEq, Eq, Clone, Debug)]
|
#[derive(Routable, PartialEq, Eq, Clone, Debug)]
|
||||||
@@ -45,30 +48,15 @@ pub enum Route {
|
|||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
node_ref: NodeRef,
|
node_ref: NodeRef,
|
||||||
navbar_active: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Msg {
|
|
||||||
ToggleNavbar,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for App {
|
impl Component for App {
|
||||||
type Message = Msg;
|
type Message = ();
|
||||||
type Properties = ();
|
type Properties = ();
|
||||||
|
|
||||||
fn create(_ctx: &Context<Self>) -> Self {
|
fn create(_ctx: &Context<Self>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
node_ref: NodeRef::default(),
|
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()} />
|
" ref={self.node_ref.clone()} />
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<header style="
|
<header style="
|
||||||
z-index: 1 !important;
|
z-index: 2 !important;
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
color: white !important;
|
color: white !important;
|
||||||
font-family: monospace !important;
|
|
||||||
flex-direction: row !important;
|
flex-direction: row !important;
|
||||||
align-items: center !important;
|
align-items: center !important;
|
||||||
justify-content: center !important;
|
justify-content: center !important;
|
||||||
@@ -97,25 +84,17 @@ impl Component for App {
|
|||||||
min-height: 20px !important;
|
min-height: 20px !important;
|
||||||
height: 20px !important;
|
height: 20px !important;
|
||||||
max-height: 20px !important;
|
max-height: 20px !important;
|
||||||
filter: url(post.bloom.svg#process) !important;
|
filter: url(post.bloom.svg) !important;
|
||||||
">
|
">
|
||||||
<p>{r"-»{ "}</p>
|
<h3>{r"»[ "}</h3>
|
||||||
<Link<Route> to={Route::About}>
|
<h3><Link<Route> to={Route::About}>{r"about"}</Link<Route>></h3>
|
||||||
<a style="color: #CBA6F7FF !important;">{r"about"}</a>
|
<h3>{r"|"}</h3>
|
||||||
</Link<Route>>
|
<h3><Link<Route> to={Route::Entries}>{r"blog"}</Link<Route>></h3>
|
||||||
/*<p>{r"."}</p>
|
<h3>{r"|"}</h3>
|
||||||
<Link<Route> to={Route::Entries}>
|
<h3><Link<Route> to={Route::FindMe}>{r"findme"}</Link<Route>></h3>
|
||||||
<a style="color: #CBA6F7FF !important;">{r"blog"}</a>
|
<h3>{r"|"}</h3>
|
||||||
</Link<Route>>*/
|
<h3><Link<Route> to={Route::Projects}>{r"projects"}</Link<Route>></h3>
|
||||||
<p>{r"."}</p>
|
<h3>{r" ]«"}</h3>
|
||||||
<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>
|
|
||||||
</header>
|
</header>
|
||||||
<main style="
|
<main style="
|
||||||
z-index: 1 !important;
|
z-index: 1 !important;
|
||||||
@@ -125,7 +104,6 @@ impl Component for App {
|
|||||||
flex-direction: column !important;
|
flex-direction: column !important;
|
||||||
min-width: fit-content !important;
|
min-width: fit-content !important;
|
||||||
width: calc(100vw - 18 px) !important;
|
width: calc(100vw - 18 px) !important;
|
||||||
font-family: monospace !important;
|
|
||||||
flex-wrap: nowrap !important;
|
flex-wrap: nowrap !important;
|
||||||
justify-content: space-between !important;
|
justify-content: space-between !important;
|
||||||
align-items: center !important;
|
align-items: center !important;
|
||||||
@@ -228,59 +206,114 @@ impl App {
|
|||||||
">
|
">
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://i0ur.ing/"><img loading="eager" alt="iouring" src="iouring.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://webassembly.org/"><img loading="eager" alt="wasm" src="wasm.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://beta.servfail.network/"><img loading="eager" alt="servfail" src="servfail.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://www.dataforest.net/en/"><img loading="eager" alt="dataforest" src="dataforest.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://fedoraproject.org/"><img loading="eager" alt="fedora" src="fedora.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://artixlinux.org/"><img loading="eager" alt="artix" src="artix.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://nixos.org/"><img loading="eager" alt="nixos" src="nixos.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://chimera-linux.org/"><img loading="eager" alt="void" src="chimera.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://voidlinux.org/"><img loading="eager" alt="void" src="void.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://www.rust-lang.org/"><img loading="eager" alt="rust" src="rust.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://dotnet.microsoft.com/en-us/"><img loading="eager" alt="csharp" src="csharp.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://kotlinlang.org/"><img loading="eager" alt="kotlin" src="kotlin.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
" href="https://www.java.com/"><img loading="eager" alt="java" src="java.png" /></a>
|
||||||
<a style="
|
<a style="
|
||||||
width: 88px !important;
|
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>
|
"><img loading="eager" alt="aqueer" src="aqueer.png" /></a>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ impl Component for About {
|
|||||||
font-weight: bold !important;
|
font-weight: bold !important;
|
||||||
font-style: italic !important;
|
font-style: italic !important;
|
||||||
font-size: xx-large !important;
|
font-size: xx-large !important;
|
||||||
">{r"intro"}<br /><p style="
|
">{r">intro_"}<br /><p style="
|
||||||
font-weight: normal !important;
|
font-weight: normal !important;
|
||||||
font-style: normal !important;
|
font-style: normal !important;
|
||||||
font-size: medium !important;
|
font-size: medium !important;
|
||||||
@@ -58,9 +58,9 @@ impl Component for About {
|
|||||||
may sound naive as fuck but fuck it we ball.
|
may sound naive as fuck but fuck it we ball.
|
||||||
audhd (certified) and probably bpd or ptsd. i'm not a psychologist tho.
|
audhd (certified) and probably bpd or ptsd. i'm not a psychologist tho.
|
||||||
interact with caution, may bite.
|
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.
|
figure it yourself. use your brain.
|
||||||
"#}</p>{r"hobbies"}<br /><p style="
|
"#}</p>{r">hobbies_"}<br /><p style="
|
||||||
font-weight: normal !important;
|
font-weight: normal !important;
|
||||||
font-style: normal !important;
|
font-style: normal !important;
|
||||||
font-size: medium !important;
|
font-size: medium !important;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::pages::blog::content;
|
use crate::pages::blog::content;
|
||||||
use crate::pages::blog::content::BlogEntry;
|
use crate::pages::blog::content::{BlogEntry, Post};
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
use crate::pages::blog::authorcard::AuthorCard;
|
||||||
|
use crate::pages::blog::entrycard::EntryCard;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
|
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
|
||||||
pub struct Props {
|
pub struct Props {
|
||||||
@@ -27,20 +29,42 @@ impl Component for Author {
|
|||||||
|
|
||||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
fn view(&self, _ctx: &Context<Self>) -> Html {
|
||||||
let Self { author } = self;
|
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! {
|
html! {
|
||||||
<div>
|
<div style="
|
||||||
<img alt="insert pfp here" loading="eager" src={author.image_url.clone()} />
|
display: flex !important;
|
||||||
<div style="vertical-align: top !important;">
|
width: 100% !important;
|
||||||
<p style="filter: url(post.bloom.svg#process) !important; color: #B4BEFE !important;">{author.name.clone()}</p>
|
flex-direction: column !important;
|
||||||
<p style="background-clip: text !important; background-image: linear-gradient(45deg, #5BCEFAFF, #F5A9B8FF, #FFFFFFFF) !important;">
|
flex-wrap: wrap !important;
|
||||||
{ for author.keywords.iter().map(|tag| html! { <p>{ tag }</p> }) }
|
justify-content: center !important;
|
||||||
</p>
|
margin-bottom: 2rem !important;
|
||||||
</div>
|
">
|
||||||
<hr style="background-color: #B4BEFE60 !important;" />
|
<h2 style="text-align: center !important;">{ "about me" }</h2>
|
||||||
<p>{r#"about me"#}</p>
|
<div style="
|
||||||
<div>
|
display: flex !important;
|
||||||
{ author.about.clone() }
|
width: 100% !important;
|
||||||
</div>
|
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>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,32 +32,41 @@ impl Component for AuthorCard {
|
|||||||
|
|
||||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
fn view(&self, _ctx: &Context<Self>) -> Html {
|
||||||
let Self { author } = self;
|
let Self { author } = self;
|
||||||
|
let keywords = author.keywords.iter().map(|keyword| html! {
|
||||||
|
<p style="margin: unset !important;">{*keyword}</p>
|
||||||
|
}).collect::<Html>();
|
||||||
html! {
|
html! {
|
||||||
<>
|
<div style="
|
||||||
<div>
|
display: flex !important;
|
||||||
<div>
|
flex-direction: row !important;
|
||||||
<div>
|
flex-wrap: wrap !important;
|
||||||
<div>
|
background-color: #ECBEE130 !important;
|
||||||
<figure>
|
border-radius: 0.5rem !important;
|
||||||
<img alt="this should normally show an image mew,," src={author.image_url.clone()} />
|
width: fit-content !important;
|
||||||
</figure>
|
height: fit-content !important;
|
||||||
</div>
|
text-align: left !important;
|
||||||
<div>
|
margin: 1rem 1rem 0 0 !important;
|
||||||
<p>{ &author.name }</p>
|
">
|
||||||
<p>
|
<img style="
|
||||||
{ "I like " }
|
float: left !important;
|
||||||
<b>{ author.keywords.join(", ") }</b>
|
margin-right: 0.3rem !important;
|
||||||
</p>
|
border-radius: 0.5rem !important;
|
||||||
</div>
|
" alt="insert pfp here" width="96" height="96" src={author.image_url} />
|
||||||
</div>
|
<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>
|
</div>
|
||||||
<footer>
|
|
||||||
<Link<Route> classes={classes!("card-footer-item")} to={Route::Author { id: author.id }}>
|
|
||||||
{ "Profile" }
|
|
||||||
</Link<Route>>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
|
||||||
use crate::pages::blog::authorcard::AuthorCard;
|
use crate::pages::blog::authorcard::AuthorCard;
|
||||||
|
use crate::pages::blog::content::{Author, BlogEntry};
|
||||||
|
|
||||||
/*pub enum Msg {
|
pub struct Authors;
|
||||||
NextAuthors,
|
|
||||||
}*/
|
|
||||||
|
|
||||||
pub struct Authors {
|
|
||||||
ids: Vec<u8>,
|
|
||||||
}
|
|
||||||
impl Component for Authors {
|
impl Component for Authors {
|
||||||
type Message = (); //Msg;
|
type Message = ();
|
||||||
type Properties = ();
|
type Properties = ();
|
||||||
|
|
||||||
fn create(_ctx: &Context<Self>) -> Self {
|
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 {
|
fn view(&self, _: &Context<Self>) -> Html {
|
||||||
html! {
|
html! {
|
||||||
{ for self.ids.iter().map(|&id| { html! {
|
<div style="
|
||||||
<AuthorCard {id} />
|
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>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +1,48 @@
|
|||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub struct Author {
|
pub struct Author {
|
||||||
pub id: u8,
|
pub id: u8,
|
||||||
pub image_url: String,
|
pub image_url: &'static str,
|
||||||
pub name: String,
|
pub name: &'static str,
|
||||||
pub keywords: Vec<String>,
|
pub keywords: &'static [&'static str],
|
||||||
pub about: String,
|
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 {
|
impl BlogEntry for Author {
|
||||||
fn from_entry(entry: &mut Entry) -> Self {
|
fn from_entry(entry: &mut Entry) -> Self {
|
||||||
match entry.id {
|
*Self::AUTHORS
|
||||||
0 => Self {
|
.get(entry.id as usize)
|
||||||
id: entry.id,
|
.cloned()
|
||||||
image_url: "profile.avif".to_string(),
|
.unwrap_or(&Self {
|
||||||
name: "iouring".to_string(),
|
|
||||||
keywords: vec!["meow".to_string(), "mrrp".to_string(), "mew".to_string()],
|
|
||||||
about: "sup".to_string(),
|
|
||||||
},
|
|
||||||
_ => Self {
|
|
||||||
id: u8::MAX,
|
id: u8::MAX,
|
||||||
image_url: "".to_string(),
|
image_url: "",
|
||||||
name: "not found".to_string(),
|
name: "not found",
|
||||||
keywords: vec![],
|
keywords: [].as_slice(),
|
||||||
about: "".to_string(),
|
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 {
|
impl BlogEntry for Post {
|
||||||
fn from_entry(entry: &mut Entry) -> Self {
|
fn from_entry(entry: &mut Entry) -> Self {
|
||||||
return match entry.id {
|
*Self::POSTS
|
||||||
0 => Self {
|
.get(entry.id as usize)
|
||||||
id: 0,
|
.cloned()
|
||||||
author: Author::from_id(0),
|
.unwrap_or(&Self {
|
||||||
title: "meow".parse().unwrap(),
|
|
||||||
content: vec!["<h1>meow</h1>", "mrrp", "meow"]
|
|
||||||
.iter()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect(),
|
|
||||||
},
|
|
||||||
_ => Self {
|
|
||||||
id: u8::MAX,
|
id: u8::MAX,
|
||||||
author: Author::from_id(u8::MAX),
|
authors: &[u8::MAX],
|
||||||
title: "not found".parse().unwrap(),
|
title: "not found",
|
||||||
content: vec![],
|
utcdate: "1970-01-01",
|
||||||
},
|
content: "",
|
||||||
};
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,10 +55,170 @@ impl Entry {
|
|||||||
Self { id: seed }
|
Self { id: seed }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BlogEntry: Sized {
|
pub trait BlogEntry: Sized {
|
||||||
fn from_entry(entry: &mut Entry) -> Self;
|
fn from_entry(entry: &mut Entry) -> Self;
|
||||||
fn from_id(id: u8) -> Self {
|
fn from_id(id: u8) -> Self {
|
||||||
Self::from_entry(&mut Entry::from_id(id))
|
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
|
||||||
|
"#,
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
|
||||||
use crate::pages::blog::content::{Author, Post};
|
|
||||||
use crate::pages::blog::content::BlogEntry;
|
use crate::pages::blog::content::BlogEntry;
|
||||||
|
use crate::pages::blog::content::Post;
|
||||||
use crate::pages::blog::entrycard::EntryCard;
|
use crate::pages::blog::entrycard::EntryCard;
|
||||||
|
|
||||||
pub struct Entries {}
|
pub struct Entries {}
|
||||||
@@ -10,15 +10,18 @@ impl Component for Entries {
|
|||||||
type Message = ();
|
type Message = ();
|
||||||
type Properties = ();
|
type Properties = ();
|
||||||
|
|
||||||
fn create(ctx: &Context<Self>) -> Self {
|
fn create(_ctx: &Context<Self>) -> Self {
|
||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self, ctx: &Context<Self>) -> Html {
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||||
html! {
|
html! {
|
||||||
<div>
|
<div>
|
||||||
<h1>{ "entries" }</h1>
|
<h1 style="margin: unset !important;">{ "entries" }</h1>
|
||||||
<h2>{ "here are some things i yapped about" }</h2>
|
<h2 style="
|
||||||
|
margin: unset !important;
|
||||||
|
margin-bottom: 1rem !important;
|
||||||
|
">{ "here are some things i yapped about" }</h2>
|
||||||
{ self.view_posts(ctx) }
|
{ self.view_posts(ctx) }
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -26,12 +29,27 @@ impl Component for Entries {
|
|||||||
}
|
}
|
||||||
impl Entries {
|
impl Entries {
|
||||||
fn view_posts(&self, _ctx: &Context<Self>) -> Html {
|
fn view_posts(&self, _ctx: &Context<Self>) -> Html {
|
||||||
let cards: Vec<_> = (0..2) // TODO: ... | add var
|
let cards: Vec<_> = (0..Post::POSTS.len()) // TODO: ... | add var
|
||||||
.filter(|&id_offset| Post::from_id(id_offset).author.id != u8::MAX)
|
.filter(|&id_offset| {
|
||||||
.map(|id_offset| {
|
Post::from_id(id_offset as u8)
|
||||||
html! {<EntryCard id={id_offset} />}
|
.authors
|
||||||
|
.iter()
|
||||||
|
.all(|id| *id != u8::MAX)
|
||||||
})
|
})
|
||||||
|
.map(|id_offset| html! {<EntryCard id={id_offset as u8} />})
|
||||||
.collect();
|
.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>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
use yew_markdown::Markdown;
|
||||||
use yew_router::prelude::*;
|
use yew_router::prelude::*;
|
||||||
|
|
||||||
use crate::pages::blog::content;
|
use crate::pages::blog::content;
|
||||||
use crate::pages::blog::content::BlogEntry;
|
use crate::pages::blog::content::{Author, BlogEntry};
|
||||||
use crate::Route;
|
use crate::Route;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
|
#[derive(Clone, Debug, Eq, PartialEq, Properties)]
|
||||||
@@ -47,18 +48,30 @@ pub fn Entry(props: &Props) -> Html {
|
|||||||
|
|
||||||
html! {
|
html! {
|
||||||
<>
|
<>
|
||||||
<h1>
|
<h1 style="
|
||||||
{ &post.title }
|
color: #F5C2E7FF !important;
|
||||||
</h1>
|
margin: unset !important;
|
||||||
<h2>
|
filter: url(post.bloom.svg#process) !important;
|
||||||
{ "by " }
|
">{ &*post.title }</h1>
|
||||||
<Link<Route> to={Route::Author { id: post.author.id }}>
|
<div style="flex-direction: column !important;">
|
||||||
{ &post.author.name }
|
<h2 style="margin: unset !important;">
|
||||||
</Link<Route>>
|
{ "written by " } {
|
||||||
</h2>
|
post.authors.iter().map(|id| {
|
||||||
<div>
|
let author = Author::from_id(*id);
|
||||||
{ for post.content.iter() }
|
html! {
|
||||||
|
<Link<Route> to={crate::Route::Author { id: author.id }}>
|
||||||
|
{ &*author.name }
|
||||||
|
</Link<Route>>
|
||||||
|
}
|
||||||
|
}).intersperse(html! { ", " }).collect::<Html>()
|
||||||
|
} { format!(" on {}", &post.utcdate) }
|
||||||
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<Markdown
|
||||||
|
src={post.content}
|
||||||
|
hard_line_breaks={true}
|
||||||
|
send_debug_info={Callback::noop()}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
use yew_router::components::Link;
|
use yew_router::components::Link;
|
||||||
|
|
||||||
use crate::pages::blog::content::{BlogEntry, Post};
|
use crate::pages::blog::content::{Author, BlogEntry, Post};
|
||||||
|
|
||||||
use crate::Route;
|
use crate::Route;
|
||||||
|
|
||||||
@@ -48,13 +47,52 @@ pub fn EntryCard(props: &PropsEntryCard) -> Html {
|
|||||||
let post = &post.inner;
|
let post = &post.inner;
|
||||||
|
|
||||||
html! {
|
html! {
|
||||||
<div style="height: fit-content !important; width: fit-content !important;">
|
<div style="
|
||||||
<Link<Route> classes={classes!("title", "is-block")} to={Route::Entry { id: post.id }}>
|
display: flex !important;
|
||||||
{ &post.title }
|
flex-direction: column !important;
|
||||||
</Link<Route>>
|
flex-wrap: wrap !important;
|
||||||
<Link<Route> classes={classes!("subtitle", "is-block")} to={Route::Author { id: post.author.id }}>
|
background-color: #ECBEE130 !important;
|
||||||
{ &post.author.name }
|
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>>
|
</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>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use web_sys::window;
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
|
||||||
pub struct FindMe;
|
pub struct FindMe;
|
||||||
@@ -10,58 +11,128 @@ impl Component for FindMe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self, _ctx: &Context<Self>) -> Html {
|
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! {
|
html! {
|
||||||
<>
|
<div style="
|
||||||
<p style="
|
display: flex !important;
|
||||||
font-weight: bold !important;
|
flex-direction: row !mportant;
|
||||||
font-style: italic !important;
|
flex-wrap: wrap !important;
|
||||||
font-size: xx-large !important;
|
justify-content: center !important;
|
||||||
">{r"follow us"}<br /><p style="
|
width: 100% !important;
|
||||||
font-weight: normal !important;
|
">
|
||||||
font-style: normal !important;
|
<div style="
|
||||||
font-size: medium !important;
|
width: fit-content !important;
|
||||||
">{" × "}<a style="
|
height: fit-content !important;
|
||||||
color: #F5C2E7FF !important;
|
margin: 1rem 1rem 1rem 1rem !important;
|
||||||
text-decoration: none !important;
|
">
|
||||||
filter: url(post.bloom.svg#process) !important;
|
<p style="
|
||||||
" href="https://ice.stellaris.fyi/@iouring">{r"fediverse"}</a><br />
|
font-weight: bold !important;
|
||||||
{" × "}<a style="
|
font-style: normal !important;
|
||||||
color: #B4BEFEFF !important;
|
font-size: xx-large !important;
|
||||||
text-decoration: none !important;
|
text-align: center !important;
|
||||||
" href="https://bsky.app/profile/i0ur.ing">{r"bluesky"}</a><br />
|
margin: unset !important;
|
||||||
</p>{r"write us"}<br /><p style="
|
">{r"follow us"}</p>
|
||||||
font-weight: normal !important;
|
<p style="
|
||||||
font-style: normal !important;
|
font-weight: normal !important;
|
||||||
font-size: medium !important;
|
font-style: normal !important;
|
||||||
"><a style="
|
font-size: large !important;
|
||||||
color: #94E2D5FF !important;
|
">{" × "}<a style="
|
||||||
filter: url(post.bloom.svg#process) !important;
|
color: #F5C2E7FF !important;
|
||||||
">{r" × matrix » @iouring:hi.stellaris.fyi"}</a><br />
|
" href="https://ice.stellaris.fyi/@iouring">{r"fediverse"}</a><br />
|
||||||
<a style="color: #89B4FAFF !important;">{r" × telegr » @luc1ell3"}</a><br />
|
{" × "}<a style="
|
||||||
<a style="color: #F38BA8FF !important;">{r" × ewcord » @donotusedisc0rdkthxbye"}</a>
|
color: #B4BEFEFF !important;
|
||||||
</p>{r"git gud"}<br /><p style="
|
" href="https://bsky.app/profile/i0ur.ing">{r"bluesky"}</a><br />
|
||||||
font-weight: normal !important;
|
</p>
|
||||||
font-style: normal !important;
|
</div>
|
||||||
font-size: medium !important;
|
<div style="
|
||||||
">{" × "}<a style="
|
width: fit-content !important;
|
||||||
color: #F5C2E7FF !important;
|
height: fit-content !important;
|
||||||
text-decoration: none !important;
|
margin: 1rem 1rem 1rem 1rem !important;
|
||||||
filter: url(post.bloom.svg#process) !important;
|
">
|
||||||
" href="https://git.celesteflare.cc/i0uring">{r"my own!!!"}</a><br />
|
<p style="
|
||||||
{" × "}<a style="
|
font-weight: bold !important;
|
||||||
color: #CBA6F7FF !important;
|
font-style: normal !important;
|
||||||
text-decoration: none !important;
|
font-size: xx-large !important;
|
||||||
" href="https://git.gay/luciel">{r"the gay one"}</a><br />
|
text-align: center !important;
|
||||||
{" × "}<a style="
|
margin: unset !important;
|
||||||
color: #B4BEFEFF !important;
|
">{r"write us"}</p>
|
||||||
text-decoration: none !important;
|
<p style="
|
||||||
" href="https://git.rimuru.club/i0uring">{r"git of fren"}</a><br />
|
font-weight: normal !important;
|
||||||
{" × "}<a style="
|
font-style: normal !important;
|
||||||
color: #89B4FAFF !important;
|
font-size: large !important;
|
||||||
text-decoration: none !important;
|
">
|
||||||
" href="https://codeberg.org/i0uring">{r"a mountain what"}</a>
|
{"× "}
|
||||||
</p></p>
|
<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>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
51
src/pages/projects/content.rs
Normal file
51
src/pages/projects/content.rs
Normal 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",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
3
src/pages/projects/mod.rs
Normal file
3
src/pages/projects/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod content;
|
||||||
|
pub mod projectcard;
|
||||||
|
pub mod projects;
|
||||||
54
src/pages/projects/projectcard.rs
Normal file
54
src/pages/projects/projectcard.rs
Normal 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>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/pages/projects/projects.rs
Normal file
54
src/pages/projects/projects.rs
Normal 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>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user