From 4c3d6202503812216850303d96773b58dd0ff96c Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 31 Dec 2025 16:09:20 +0200 Subject: [PATCH] refactor(web): use AnyView return type for all components --- Dockerfile | 41 +++++++++++++------------ web/src/components/cipher_form.rs | 3 +- web/src/components/cipher_form_cbc.rs | 43 +++++++++++++++------------ web/src/components/config_section.rs | 3 +- web/src/components/file_input.rs | 18 +++++++---- 5 files changed, 62 insertions(+), 46 deletions(-) diff --git a/Dockerfile b/Dockerfile index c96f936..1c49ec8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,48 +1,51 @@ +# Compute recipe FROM lukemathwalker/cargo-chef:latest-rust-1 AS chef WORKDIR /app COPY . . RUN cargo chef prepare --recipe-path recipe.json +# Install tools and build dependencies FROM rustlang/rust:nightly-bookworm AS cacher +WORKDIR /app + +# Install cargo-binstall +RUN curl -L https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz | tar -xz -C /usr/local/bin -RUN curl -LO https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz -RUN tar -xvf cargo-binstall-x86_64-unknown-linux-musl.tgz -RUN cp cargo-binstall /usr/local/cargo/bin RUN cargo binstall cargo-leptos cargo-chef -y RUN apt-get update -y && apt-get install -y --no-install-recommends clang RUN rustup target add wasm32-unknown-unknown -WORKDIR /app +# Cook dependencies COPY --from=chef /app/recipe.json recipe.json RUN cargo chef cook --release --recipe-path recipe.json +# Actual build FROM rustlang/rust:nightly-bookworm AS builder - -RUN wget https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz -RUN tar -xvf cargo-binstall-x86_64-unknown-linux-musl.tgz -RUN cp cargo-binstall /usr/local/cargo/bin -RUN cargo binstall cargo-leptos -y -RUN apt-get update -y && apt-get install -y --no-install-recommends clang -RUN rustup target add wasm32-unknown-unknown - WORKDIR /app + +# Copy the tools from the cacher stage +COPY --from=cacher /usr/local/rustup /usr/local/rustup +COPY --from=cacher /usr/local/cargo /usr/local/cargo + +RUN apt-get update && apt-get install -y --no-install-recommends clang + +# Bring in the cooked dependencies COPY --from=cacher /app/target target COPY . . + +# Build the Leptos app RUN cargo leptos build --release -vv +# Runtime FROM debian:bookworm-slim AS runtime - WORKDIR /app -RUN apt-get update -y \ - && apt-get install -y --no-install-recommends openssl ca-certificates \ - && apt-get autoremove -y \ - && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y --no-install-recommends openssl ca-certificates \ + && apt-get clean && rm -rf /var/lib/apt/lists/* +# Copy binaries and assets COPY --from=builder /app/target/release/web /app/ COPY --from=builder /app/target/site /app/site COPY --from=builder /app/Cargo.toml /app/ EXPOSE 8080 - CMD ["/app/web"] diff --git a/web/src/components/cipher_form.rs b/web/src/components/cipher_form.rs index d36941a..1ee3e75 100644 --- a/web/src/components/cipher_form.rs +++ b/web/src/components/cipher_form.rs @@ -10,7 +10,7 @@ use leptos::prelude::*; use std::time::Duration; #[component] -pub fn CipherForm(algorithm: Algorithm) -> impl IntoView { +pub fn CipherForm(algorithm: Algorithm) -> AnyView { let (mode, set_mode) = signal(OperationMode::Encrypt); let (output_fmt, set_output_fmt) = signal(OutputFormat::Hex); @@ -101,4 +101,5 @@ pub fn CipherForm(algorithm: Algorithm) -> impl IntoView { } + .into_any() } diff --git a/web/src/components/cipher_form_cbc.rs b/web/src/components/cipher_form_cbc.rs index d67e0a0..17babdf 100644 --- a/web/src/components/cipher_form_cbc.rs +++ b/web/src/components/cipher_form_cbc.rs @@ -13,7 +13,7 @@ use wasm_bindgen::JsCast; use web_sys::{Blob, Url}; #[component] -pub fn CipherFormCbc() -> impl IntoView { +pub fn CipherFormCbc() -> AnyView { let (mode, set_mode) = signal(OperationMode::Encrypt); let (output_fmt, set_output_fmt) = signal(OutputFormat::Hex); @@ -56,7 +56,7 @@ pub fn CipherFormCbc() -> impl IntoView { let formatted_iv = format!("0x{iv}"); // Get input data - let input_data: Vec = match input_mode.get() { + let input_data = match input_mode.get() { InputMode::Text => { let text = text_content.get(); if text.is_empty() { @@ -192,7 +192,10 @@ pub fn CipherFormCbc() -> impl IntoView {
"Output ("{output_fmt.get().to_string()}")"
- {move || { @@ -201,7 +204,8 @@ pub fn CipherFormCbc() -> impl IntoView { - }.into_any() + } + .into_any() } else { view! { }.into_any() } @@ -209,21 +213,25 @@ pub fn CipherFormCbc() -> impl IntoView {
- {move || { - let out = output.get(); - if out.len() > 1000 { - format!("{}... ({} chars total)", &out[..1000], out.len()) - } else { - out - } - }} + + {move || { + let out = output.get(); + if out.len() > 1000 { + format!("{}... ({} chars total)", &out[..1000], out.len()) + } else { + out + } + }} +
- }.into_any() + } + .into_any() }} } + .into_any() } fn parse_hex_string(s: &str) -> Result, String> { @@ -234,7 +242,7 @@ fn parse_hex_string(s: &str) -> Result, String> { .unwrap_or(trimmed); // Remove whitespace and newlines - let s: String = s.chars().filter(|c| !c.is_whitespace()).collect(); + let s = s.chars().filter(|c| !c.is_whitespace()).collect::(); if !s.len().is_multiple_of(2) { return Err("Hex string must have even length".to_string()); @@ -282,10 +290,7 @@ fn download_bytes(bytes: &[u8], filename: &str) { return; }; - let Some(window) = web_sys::window() else { - return; - }; - let Some(document) = window.document() else { + let Some(document) = window().document() else { return; }; let Some(a) = document.create_element("a").ok() else { @@ -295,7 +300,7 @@ fn download_bytes(bytes: &[u8], filename: &str) { let _ = a.set_attribute("href", &url); let _ = a.set_attribute("download", filename); - let a: web_sys::HtmlElement = a.unchecked_into(); + let a = a.unchecked_into::(); a.click(); let _ = Url::revoke_object_url(&url); diff --git a/web/src/components/config_section.rs b/web/src/components/config_section.rs index 9aee874..973e467 100644 --- a/web/src/components/config_section.rs +++ b/web/src/components/config_section.rs @@ -10,7 +10,7 @@ pub fn ConfigurationSection( set_mode: WriteSignal, output_fmt: ReadSignal, update_output: impl Fn(OutputFormat) + Copy + Send + 'static, -) -> impl IntoView { +) -> AnyView { let handle_format_change = move |ev| { let val = event_target_value(&ev); let fmt = OutputFormat::from_str(&val).unwrap_or_default(); @@ -83,4 +83,5 @@ pub fn ConfigurationSection( } + .into_any() } diff --git a/web/src/components/file_input.rs b/web/src/components/file_input.rs index b85fbb3..2278d0c 100644 --- a/web/src/components/file_input.rs +++ b/web/src/components/file_input.rs @@ -41,7 +41,7 @@ fn read_file( fn InputModeToggle( input_mode: ReadSignal, set_input_mode: WriteSignal, -) -> impl IntoView { +) -> AnyView { view! {
} + .into_any() } #[component] @@ -71,7 +72,7 @@ fn TextAreaInput( text_content: ReadSignal, set_text_content: WriteSignal, is_decrypt_mode: Memo, -) -> impl IntoView { +) -> AnyView { let handle_text_change = move |ev: Event| { if let Some(target) = ev.target() { let textarea: web_sys::HtmlTextAreaElement = target.unchecked_into(); @@ -99,6 +100,7 @@ fn TextAreaInput( } + .into_any() } #[component] @@ -107,7 +109,7 @@ fn FileDropZone( set_file_data: WriteSignal>>, file_name: ReadSignal>, set_file_name: WriteSignal>, -) -> impl IntoView { +) -> AnyView { let (is_dragging, set_is_dragging) = signal(false); let handle_file_change = move |ev: Event| { @@ -193,6 +195,7 @@ fn FileDropZone( } + .into_any() } #[component] @@ -201,7 +204,7 @@ fn FileSelected( file_data: ReadSignal>>, set_file_name: WriteSignal>, set_file_data: WriteSignal>>, -) -> impl IntoView { +) -> AnyView { let clear_file = move |ev: web_sys::MouseEvent| { ev.prevent_default(); ev.stop_propagation(); @@ -221,16 +224,18 @@ fn FileSelected( } + .into_any() } #[component] -fn FilePlaceholder() -> impl IntoView { +fn FilePlaceholder() -> AnyView { view! {
"[+]" "Click to select a file or drag and drop"
} + .into_any() } #[component] @@ -244,7 +249,7 @@ pub fn FileTextInput( file_name: ReadSignal>, set_file_name: WriteSignal>, is_decrypt_mode: Memo, -) -> impl IntoView { +) -> AnyView { view! {
@@ -281,4 +286,5 @@ pub fn FileTextInput( }}
} + .into_any() }