diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index aa1eaf9..a9e7c6b 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -2,6 +2,7 @@ name: clippy on: workflow_dispatch: pull_request: + branches: [main, riir] types: - ready_for_review @@ -45,17 +46,9 @@ jobs: toolchain: nightly override: true components: clippy - - name: Cache .cargo and target - uses: actions/cache@v4 - with: - path: | - ~/.cargo - key: ${{ runner.os }}-cargo-leptos-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo-leptos-${{ hashFiles('**/Cargo.lock') }} - ${{ runner.os }}-cargo-leptos + - uses: cargo-bins/cargo-binstall@main - name: Install LeptosFmt - run: cargo install leptosfmt --version 0.1.33 + run: cargo binstall --disable-telemetry --no-confirm leptosfmt --version 0.1.33 - name: Check LeptosFmt run: leptosfmt --check src diff --git a/Cargo.lock b/Cargo.lock index a3b4415..32e7c4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,7 +72,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rand 0.10.2", + "rand 0.10.3", "sha1", "smallvec", "tokio", @@ -2329,7 +2329,7 @@ dependencies = [ "bytes", "getrandom 0.4.3", "lru-slab", - "rand 0.10.2", + "rand 0.10.3", "rand_pcg", "ring", "rustc-hash", @@ -2411,9 +2411,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" dependencies = [ "chacha20", "getrandom 0.4.3", @@ -2626,11 +2626,13 @@ dependencies = [ "actix-files", "actix-web", "console_error_panic_hook", + "getrandom 0.4.3", "leptos", "leptos-use", "leptos_actix", "leptos_meta", "leptos_router", + "rand 0.10.3", "reqwest", "rustlanges-components", "rusty-hook", diff --git a/Cargo.toml b/Cargo.toml index ce4ba52..83c9de7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,8 @@ reqwest = { version = "0.13.4", features = [ rustlanges-components = { path="design-system-components", features = ["leptos"] } leptos-use = { version = "0.19.0", features = [] } console_error_panic_hook = { version = "0.1.7", optional = true } +rand = "0.10.3" +getrandom = { version = "0.4.3", features = ["wasm_js"] } # leptos_theme = "0.1.2" [features] diff --git a/Makefile.toml b/Makefile.toml index bafe7d9..87d0d28 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -24,14 +24,14 @@ args = ["fmt", "--all"] [tasks.fmt-all] script = ''' -leptosfmt . +leptosfmt src cargo fmt --all cargo clippy --fix --features ssr -- -D warnings ''' [tasks.check] script = ''' -leptosfmt --check . +leptosfmt --check src cargo fmt --all --check cargo clippy --features ssr -- -D warnings ''' @@ -39,7 +39,7 @@ cargo clippy --features ssr -- -D warnings [tasks.leptos-format] install_crate = "leptosfmt" command = "leptosfmt" -args = ["."] +args = ["src"] [tasks.format] dependencies = ["cargo-format", "leptos-format"] diff --git a/design-system-components b/design-system-components index 3483e05..73d2708 160000 --- a/design-system-components +++ b/design-system-components @@ -1 +1 @@ -Subproject commit 3483e05f8b354ef3ee01f2e8113b98b3324e9851 +Subproject commit 73d27082b5521b93d402b0e1d17264eee98c609e diff --git a/flake.nix b/flake.nix index 6895172..ca90778 100644 --- a/flake.nix +++ b/flake.nix @@ -26,6 +26,7 @@ rustToolchain # WASM tools + nodejs tailwindcss_4 wasm-bindgen-cli_0_2_126 diff --git a/src/components/contributors.rs b/src/components/contributors.rs index d7a52eb..bf7dcd7 100644 --- a/src/components/contributors.rs +++ b/src/components/contributors.rs @@ -54,7 +54,7 @@ pub fn Contributors() -> impl IntoView { - }; + } }) .collect_view(); @@ -74,7 +74,7 @@ pub fn Contributors() -> impl IntoView {
- {{ contributors_list }} + {contributors_list}
diff --git a/src/components/icons/mod.rs b/src/components/icons/mod.rs index 0349f17..f94e075 100644 --- a/src/components/icons/mod.rs +++ b/src/components/icons/mod.rs @@ -5,6 +5,7 @@ mod linkedin_icon; mod location_icon; mod logo_rust_page; mod next; +mod sponsor_block; mod telegram_icon; mod twitter_icon; mod web_icon; @@ -17,6 +18,7 @@ pub use github_icon::*; pub use linkedin_icon::*; pub use location_icon::*; pub use next::*; +pub use sponsor_block::*; pub use telegram_icon::*; pub use twitter_icon::*; diff --git a/src/components/icons/sponsor_block.rs b/src/components/icons/sponsor_block.rs new file mode 100644 index 0000000..51ae05f --- /dev/null +++ b/src/components/icons/sponsor_block.rs @@ -0,0 +1,34 @@ +use leptos::prelude::*; + +#[component] +pub fn SponsorBlockIcon(#[prop(optional)] class: String) -> impl IntoView { + view! { + + + + + + + + } +} diff --git a/src/components/other_communities.rs b/src/components/other_communities.rs index 96f02cf..a760ecb 100644 --- a/src/components/other_communities.rs +++ b/src/components/other_communities.rs @@ -1,17 +1,113 @@ use leptos::prelude::*; use rustlanges_components::{ avatar::Avatar, - button::{Button, Variant as ButtonVariant}, + button::{Variant as ButtonVariant, button_class}, card::Card, chip::{Chip, Variant as ChipVariant}, - icons::Telegram, + icons::IconVariant, input::{Filter, InputSearch}, }; type ResourceAlias = Vec; +// TODO(@Lemin-n): quitar el pub, please +struct Community { + pub logo: &'static str, + pub name: &'static str, + pub country: &'static str, + pub description: &'static str, + pub link: Option<(&'static str, IconVariant)>, +} + +const COMMUNITIES: [Community; 7] = [ + Community { + name: "Rust Colombia", + country: "Colombia", + description: "Comunidad de Rust con dos sedes, en Medellín y en Bogotá", + logo: "https://rustlang-es.org/gen_assets/rust-colombia.webp", + link: Some(("https://discord.gg/krm22PuDVw", IconVariant::Discord)), + }, + Community { + name: "Rust Venezuela", + country: "Venezuela duh", + description: "Venezuela dih", + logo: "https://rustlang-es.org/gen_assets/rust-venezuela.webp", + link: Some(("https://t.me/rustlangVE", IconVariant::Telegram)), + }, + Community { + name: "Rust Argentina", + country: "Argentina claro", + description: "Anteriormente Rust Argentina, hoy una comunidad internacional", + logo: "https://rustlang-es.org/gen_assets/rust-argentina.webp", + link: Some(("https://t.me/rust_lang_es", IconVariant::Telegram)), + }, + Community { + name: "Rust Ecuador", + country: "Ecuador", + description: "¡Comunidad de Rust en Ecuador!", + logo: "https://rustlang-es.org/gen_assets/rust_ecuador.webp", + link: Some(("https://t.me/rustecuador", IconVariant::Telegram)), + }, + Community { + name: "Rust MX", + country: "Mexico", + description: "¡Comunidad de Rust en Mexico!", + logo: "https://rustlang-es.org/gen_assets/RustMX-min.webp", + link: Some(("https://t.me/RustMX", IconVariant::Telegram)), + }, + Community { + name: "Bcn Rust", + country: "España", + description: "Comunidad de Rust en Barcelona", + logo: "https://rustlang-es.org/gen_assets/RustBCN.webp", + link: Some(("https://discord.gg/DeZKCCyMcq", IconVariant::Discord)), + }, + Community { + name: "Rust Perú", + country: "Perú", + description: "¡Comunidad de Rust en Perú!", + logo: "https://rustlang-es.org/gen_assets/rust-peru.webp", + link: Some(("https://peru.rustlang-es.org/", IconVariant::Link)), + }, +]; + #[allow(non_snake_case)] pub fn OtherCommunities() -> impl IntoView { + let communities = COMMUNITIES.map(|community| { + let button_link = community.link.map(|(link, link_icon)| { + view! { + + {link_icon.to_view()} + + } + }); + + view! { +
+ +
+
+
+ {button_link} +
+

{community.name}

+ +

+ {community.description} +

+
+
+
+
+ } + }); + view! {
@@ -26,160 +122,7 @@ pub fn OtherCommunities() -> impl IntoView {
- -
- -
-
-
-
-

"Rust Colombia"

- -

- "Comunidad de Rust con dos sedes, en Medellín y en Bogotá" -

-
-
-
-
- -
- -
-
-
-
-

"Rust Venezuela"

- -
-
-
-
- -
- -
-
-
-
-

"Rust Argentina"

- -

- "Anteriormente Rust Argentina, hoy una comunidad internacional" -

-
-
-
-
- -
- -
-
-
-
-

"Rust Ecuador"

- -

- "¡Comunidad de Rust en Ecuador!" -

-
-
-
-
- -
- -
-
-
-
-

"Rust MX"

- -

- "¡Comunidad de Rust en Mexico!" -

-
-
-
-
- -
- -
-
-
-
-

"Rust Perú"

- -

- "¡Comunidad de Rust en Perú!" -

-
-
-
-
- + {communities}
diff --git a/src/components/our_sponsors.rs b/src/components/our_sponsors.rs index 70e3524..922eeba 100644 --- a/src/components/our_sponsors.rs +++ b/src/components/our_sponsors.rs @@ -1,6 +1,161 @@ -use leptos::prelude::*; +use leptos::{leptos_dom::logging::console_warn, prelude::*}; -use crate::components::sponsor_block::SponsorBlock; +use crate::components::sponsor_block::{SponsorBlock, SponsorVariant}; + +#[derive(Default)] +struct SponsorDef { + variant: SponsorVariant, + + img: &'static str, + alt: &'static str, + class: &'static str, +} + +enum SponsorBrick { + Sponsor(&'static str), + Empty(&'static str), + Space(&'static str), +} + +fn sponsors() -> impl IntoView { + use SponsorVariant::*; + + let mut sponsors_buf = vec![ + SponsorDef { + variant: Black, + img: "/assets/sponsors/sysarmy.webp", + alt: "SysArmy", + ..Default::default() + }, + SponsorDef { + variant: White, + img: "/assets/new/sponsors/testing-bolivia.png", + alt: "Testing Bolivia", + class: "mix-blend-difference", + }, + SponsorDef { + variant: Custom("#00c39d"), + img: "/assets/new/sponsors/frontendcafe.png", + alt: "FrontendCafe", + class: "shadow-frontendcafe w-full h-full object-contain", + }, + SponsorDef { + variant: Custom("#193270"), + img: "/assets/new/sponsors/universidad_nur.png", + alt: "Universidad Nur", + ..Default::default() + }, + SponsorDef { + variant: Black, + img: "/assets/sponsors/shuttle.webp", + alt: "ShuttleRS", + class: "mix-blend-difference", + }, + SponsorDef { + variant: Primary, + img: "/assets/new/sponsors/cloudflare.svg", + alt: "Cloudflare", + ..Default::default() + }, + SponsorDef { + variant: Custom("#051024"), + img: "/assets/new/sponsors/crabnebula.svg", + alt: "Crabnebula", + class: "mix-blend-difference", + }, + SponsorDef { + variant: Custom("var(--color-neutral-950)"), + img: "/assets/new/sponsors/tauri-logo.png", + alt: "Tauri", + ..Default::default() + }, + SponsorDef { + variant: White, + img: "/assets/new/sponsors/aws.svg", + alt: "Amazon Web Services", + ..Default::default() + }, + ]; + + // Sponsors will be "popped" from the buffer, so reverse it + // to get the same order as written + sponsors_buf.reverse(); + + const SPONSOR_BRICKS: usize = 26; + + const BRICKS: [SponsorBrick; SPONSOR_BRICKS] = [ + SponsorBrick::Sponsor("col-start-2 md:col-start-4"), + SponsorBrick::Empty(""), + SponsorBrick::Sponsor(""), + SponsorBrick::Space("hidden md:block lg:block"), + SponsorBrick::Space("hidden md:block lg:hidden"), + SponsorBrick::Sponsor(""), + SponsorBrick::Empty("lg:col-start-2"), + SponsorBrick::Space("block sm:hidden md:hidden lg:block"), + SponsorBrick::Sponsor("col-start-3 sm:col-start-[unset]"), + SponsorBrick::Space("hidden md:block lg:hidden"), + SponsorBrick::Empty("md:col-start-3 lg:col-start-[unset]"), + SponsorBrick::Sponsor("sm:col-start-3 md:col-start-[unset]"), + SponsorBrick::Empty(""), + SponsorBrick::Sponsor(""), + SponsorBrick::Empty("col-start-4 sm:col-start-[unset]"), + SponsorBrick::Sponsor(""), + SponsorBrick::Empty("col-start-2 sm:col-start-[unset]"), + SponsorBrick::Sponsor(""), + SponsorBrick::Empty("sm:col-start-2 md:col-start-[unset]"), + SponsorBrick::Space(""), + SponsorBrick::Sponsor("md:col-start-2 lg:col-start-3"), + SponsorBrick::Empty("col-start-3 md:col-start-[unset]"), + SponsorBrick::Space("hidden md:hidden lg:block"), + SponsorBrick::Empty(""), + SponsorBrick::Empty("hidden sm:block"), + SponsorBrick::Empty("hidden lg:block"), + ]; + + // Get a top-to-down zindex + let mut next_id = SPONSOR_BRICKS + 1; + let mut next_id = move || { + next_id -= 1; + next_id + }; + + let view = BRICKS.map(|b| match b { + SponsorBrick::Sponsor(c) if let Some(sponsor) = sponsors_buf.pop() => { + view! { + + sponsor.alt + + } + } + .into_any(), + // If there's no more sponsors, just show it as random empty brick. + // This allows to design and assign spaces to sponsors even if not enough + SponsorBrick::Sponsor(c) | SponsorBrick::Empty(c) => view! { } + .into_any(), + // Reserve an entire brick. + // Consult "What the hell???" section (below) to know more about this. + SponsorBrick::Space(c) => view! {
} + .into_any(), + }); + + if !sponsors_buf.is_empty() { + console_warn(&format!( + "{} Sponsors left. Some sponsors are not rendered: {}", + sponsors_buf.len(), + sponsors_buf + .into_iter() + .map(|s| s.alt) + .collect::>() + .join(", ") + )); + } + + view +} #[component] pub fn OurSponsorsSection() -> impl IntoView { @@ -18,170 +173,19 @@ pub fn OurSponsorsSection() -> impl IntoView {
-
- - - SysArmy - - - -
-
- - Testing Bolivia - - - - - FrontendCafe - - - -
-
- - Universidad Nur - - - - ShuttleRS - - - // End mobile - - -
-
- - Cloudflare - - - - Crabnebula - - - Tauri - - - // End mobile - -
-
- - FrontendCafe - - - - Amazon Web Services - + // What the hell??? + // R: The grid is composed from every brick section (each brick's top-connections) + // to align correctly in any™ position a brick is located. The cols are just an + // arbritrary amount of bricks that looks good in each breakpoint. +
+ {sponsors}
diff --git a/src/components/sponsor_block.rs b/src/components/sponsor_block.rs index b862a60..fd248f0 100644 --- a/src/components/sponsor_block.rs +++ b/src/components/sponsor_block.rs @@ -1,40 +1,128 @@ +use std::cell::RefCell; + use leptos::prelude::*; +use rand::seq::SliceRandom; +use wasm_bindgen::UnwrapThrowExt; + +use crate::components::icons::SponsorBlockIcon; + +const GHOST_DEBUG: bool = false; + +#[derive(Default, Clone, Copy, PartialEq, Eq)] +pub enum SponsorVariant { + #[default] + Primary, + Secondary, + Tertiary, + Quaternary, + Black, + White, + Custom(&'static str), +} + +impl SponsorVariant { + pub fn random_colored() -> Self { + thread_local! { + static COLOR_DISTRIBUTION: RefCell> = const {RefCell::new(Vec::new())}; + } + + COLOR_DISTRIBUTION.with_borrow_mut(|c| { + if let Some(color) = c.pop() { + color + } else { + *c = vec![ + Self::Primary, + Self::Secondary, + Self::Tertiary, + Self::Quaternary, + Self::Primary, + Self::Secondary, + Self::Tertiary, + Self::Quaternary, + ]; + + c.shuffle(&mut rand::rng()); + + c.pop().expect_throw("Just filled up") + } + }) + } +} #[component] pub fn SponsorBlock( - #[prop(into, default = "fill-primary-500")] class: &'static str, + #[prop(into, optional)] class: &'static str, + #[prop(optional)] variant: SponsorVariant, + #[prop(optional)] index: usize, #[prop(optional)] children: Option, ) -> impl IntoView { + let (variant_custom, variant_class) = match variant { + SponsorVariant::Primary => ( + None, + if GHOST_DEBUG { + "text-primary-500/5" + } else { + "text-primary-500" + }, + ), + SponsorVariant::Secondary => ( + None, + if GHOST_DEBUG { + "text-secondary-500/5" + } else { + "text-secondary-500" + }, + ), + SponsorVariant::Tertiary => ( + None, + if GHOST_DEBUG { + "text-primary-200/5" + } else { + "text-primary-200" + }, + ), + SponsorVariant::Quaternary => ( + None, + if GHOST_DEBUG { + "text-secondary-300/5" + } else { + "text-secondary-300" + }, + ), + SponsorVariant::Black => ( + None, + if GHOST_DEBUG { + "text-black/5" + } else { + "text-black" + }, + ), + SponsorVariant::White => ( + None, + if GHOST_DEBUG { + "text-white/5" + } else { + "text-white" + }, + ), + SponsorVariant::Custom(s) => (Some(s), "text-(--custom-color)"), + }; + view! { -
-
{children.map(|v| v())}
- - - - - - - -
- } + +
+ {children.map(|v| v())} +
+ +
+ }.into_any() }