diff --git a/.gitignore b/.gitignore index 80aab8e..0cd7db5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ # These are backup files generated by rustfmt **/*.rs.bk +serveurhttp +test diff --git a/Cargo.lock b/Cargo.lock index c4d1fc1..2ba2086 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa7e52a4c5c547c741610a2c6f123f3881e409b714cd27e6798ef020c514f0a" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.8.8" @@ -323,6 +345,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -415,6 +439,15 @@ dependencies = [ "half", ] +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + [[package]] name = "cocoa" version = "0.26.1" @@ -887,6 +920,17 @@ dependencies = [ "web-sys", ] +[[package]] +name = "dioxus-attributes" +version = "0.1.0" +source = "git+https://github.com/DioxusLabs/components#6ed7699b85fa4f4f50381138fc9d16e988768933" +dependencies = [ + "dioxus-rsx", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "dioxus-cli-config" version = "0.7.3" @@ -981,7 +1025,7 @@ dependencies = [ "global-hotkey", "infer", "jni 0.21.1", - "lazy-js-bundle", + "lazy-js-bundle 0.7.3", "libc", "muda", "ndk", @@ -1052,7 +1096,7 @@ dependencies = [ "futures-channel", "futures-util", "generational-box", - "lazy-js-bundle", + "lazy-js-bundle 0.7.3", "serde", "serde_json", "tracing", @@ -1098,7 +1142,7 @@ dependencies = [ "js-sys", "mime", "pin-project", - "reqwest", + "reqwest 0.12.28", "rustversion", "send_wrapper", "serde", @@ -1118,7 +1162,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", "xxhash-rust", ] @@ -1210,7 +1254,7 @@ dependencies = [ "futures-util", "generational-box", "keyboard-types", - "lazy-js-bundle", + "lazy-js-bundle 0.7.3", "rustversion", "serde", "serde_json", @@ -1240,7 +1284,7 @@ dependencies = [ "dioxus-core-types", "dioxus-html", "js-sys", - "lazy-js-bundle", + "lazy-js-bundle 0.7.3", "rustc-hash 2.1.1", "serde", "sledgehammer_bindgen", @@ -1290,6 +1334,21 @@ dependencies = [ "tracing-wasm", ] +[[package]] +name = "dioxus-primitives" +version = "0.0.1" +source = "git+https://github.com/DioxusLabs/components#6ed7699b85fa4f4f50381138fc9d16e988768933" +dependencies = [ + "dioxus", + "dioxus-attributes", + "dioxus-sdk-time", + "lazy-js-bundle 0.6.2", + "num-integer", + "serde", + "time", + "tracing", +] + [[package]] name = "dioxus-router" version = "0.7.3" @@ -1339,6 +1398,18 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dioxus-sdk-time" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80c25ae93a3f72e734873b97fbd09d9b1b6adff97205fb0ffd8543e3564fb78e" +dependencies = [ + "dioxus", + "futures", + "gloo-timers", + "tokio", +] + [[package]] name = "dioxus-server" version = "0.7.3" @@ -1470,7 +1541,7 @@ dependencies = [ "generational-box", "gloo-timers", "js-sys", - "lazy-js-bundle", + "lazy-js-bundle 0.7.3", "rustc-hash 2.1.1", "send_wrapper", "serde", @@ -1479,7 +1550,7 @@ dependencies = [ "tracing", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", ] @@ -1642,6 +1713,15 @@ dependencies = [ "serde", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -1752,6 +1832,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futf" version = "0.1.5" @@ -2390,6 +2476,14 @@ name = "httpserver" version = "0.1.0" dependencies = [ "dioxus", + "dioxus-html", + "dioxus-primitives", + "futures", + "random-string", + "reqwest 0.13.2", + "tracing", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -2617,6 +2711,15 @@ dependencies = [ "cfb", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "inventory" version = "0.3.22" @@ -2742,6 +2845,16 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.91" @@ -2775,6 +2888,12 @@ dependencies = [ "selectors", ] +[[package]] +name = "lazy-js-bundle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49596223b9d9d4947a14a25c142a6e7d8ab3f27eb3ade269d238bb8b5c267e2" + [[package]] name = "lazy-js-bundle" version = "0.7.3" @@ -3210,6 +3329,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -3241,6 +3369,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc" version = "0.2.7" @@ -3805,6 +3942,7 @@ version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -3965,6 +4103,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "random-string" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f70fd13c3024ae3f17381bb5c4d409c6dc9ea6895c08fa2147aba305bea3c4af" +dependencies = [ + "fastrand 1.9.0", +] + [[package]] name = "raw-window-handle" version = "0.5.2" @@ -4053,11 +4200,52 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", "webpki-roots", ] +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.5.0", + "web-sys", +] + [[package]] name = "rfd" version = "0.17.2" @@ -4136,6 +4324,7 @@ version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ + "aws-lc-rs", "once_cell", "ring", "rustls-pki-types", @@ -4144,6 +4333,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pki-types" version = "1.14.0" @@ -4154,12 +4355,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni 0.21.1", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -4762,7 +4991,7 @@ version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ - "fastrand", + "fastrand 2.3.0", "getrandom 0.4.2", "once_cell", "rustix", @@ -4837,7 +5066,9 @@ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde_core", "time-core", @@ -5487,6 +5718,19 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasmparser" version = "0.244.0" @@ -5579,6 +5823,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "1.0.6" diff --git a/Cargo.toml b/Cargo.toml index b7e43a2..c641ef7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,14 @@ edition = "2021" [dependencies] dioxus = { version = "0.7.1", features = ["router", "fullstack"] } +dioxus-html = "0.7.3" +dioxus-primitives = { git = "https://github.com/DioxusLabs/components", version = "0.0.1", default-features = false } +futures = "0.3.32" +random-string = "1.1.0" +reqwest = { version = "0.13.2", features = ["stream"] } +tracing = "0.1.44" +wasm-bindgen = "0.2.114" +web-sys = { version = "0.3.91", features = ["XmlHttpRequest", "XmlHttpRequestUpload", "ProgressEvent" ] } [features] default = ["web"] @@ -19,3 +27,11 @@ desktop = ["dioxus/desktop"] mobile = ["dioxus/mobile"] # The feature that are only required for the server = ["dioxus/server"] build target should be optional and only enabled in the server = ["dioxus/server"] feature server = ["dioxus/server"] + +[profile.release] +opt-level = "z" +debug = false +lto = true +codegen-units = 1 +panic = "abort" +incremental = false diff --git a/assets/dx-components-theme.css b/assets/dx-components-theme.css new file mode 100644 index 0000000..c55ca4a --- /dev/null +++ b/assets/dx-components-theme.css @@ -0,0 +1,87 @@ +/* This file contains the global styles for the styled dioxus components. You only + * need to import this file once in your project root. + */ +@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"); + +body { + color: var(--secondary-color-4); + font-family: Inter, sans-serif; + font-optical-sizing: auto; + font-style: normal; + font-weight: 400; +} + +html[data-theme="dark"] { + --dark: initial; + --light: ; +} + +html[data-theme="light"] { + --dark: ; + --light: initial; +} + +@media (prefers-color-scheme: dark) { + :root { + --dark: initial; + --light: ; + } +} + +@media (prefers-color-scheme: light) { + :root { + --dark: ; + --light: initial; + } +} + +:root { + /* Primary colors */ + --primary-color: var(--dark, #000) var(--light, #fff); + --primary-color-1: var(--dark, #0e0e0e) var(--light, #fbfbfb); + --primary-color-2: var(--dark, #0a0a0a) var(--light, #fff); + --primary-color-3: var(--dark, #141313) var(--light, #f8f8f8); + --primary-color-4: var(--dark, #1a1a1a) var(--light, #f8f8f8); + --primary-color-5: var(--dark, #262626) var(--light, #f5f5f5); + --primary-color-6: var(--dark, #232323) var(--light, #e5e5e5); + --primary-color-7: var(--dark, #3e3e3e) var(--light, #b0b0b0); + + /* Secondary colors */ + --secondary-color: var(--dark, #fff) var(--light, #000); + --secondary-color-1: var(--dark, #fafafa) var(--light, #000); + --secondary-color-2: var(--dark, #e6e6e6) var(--light, #0d0d0d); + --secondary-color-3: var(--dark, #dcdcdc) var(--light, #2b2b2b); + --secondary-color-4: var(--dark, #d4d4d4) var(--light, #111); + --secondary-color-5: var(--dark, #a1a1a1) var(--light, #848484); + --secondary-color-6: var(--dark, #5d5d5d) var(--light, #d0d0d0); + + /* Highlight colors */ + --focused-border-color: var(--dark, #2b7fff) var(--light, #2b7fff); + --primary-success-color: var(--dark, #02271c) var(--light, #ecfdf5); + --secondary-success-color: var(--dark, #b6fae3) var(--light, #10b981); + --primary-warning-color: var(--dark, #342203) var(--light, #fffbeb); + --secondary-warning-color: var(--dark, #feeac7) var(--light, #f59e0b); + --primary-error-color: var(--dark, #a22e2e) var(--light, #dc2626); + --secondary-error-color: var(--dark, #9b1c1c) var(--light, #ef4444); + --contrast-error-color: var(--dark, var(--secondary-color-3)) var(--light, var(--primary-color)); + --primary-info-color: var(--dark, var(--primary-color-5)) var(--light, var(--primary-color)); + --secondary-info-color: var(--dark, var(--primary-color-7)) var(--light, var(--secondary-color-3)); +} + +/* Modern browsers with `scrollbar-*` support */ +@supports (scrollbar-width: auto) { + :not(:hover) { + scrollbar-color: rgb(0 0 0 / 0%) rgb(0 0 0 / 0%); + } + + :hover { + scrollbar-color: var(--secondary-color-2) rgb(0 0 0 / 0%); + } +} + +/* Legacy browsers with `::-webkit-scrollbar-*` support */ +@supports selector(::-webkit-scrollbar) { + :root::-webkit-scrollbar-track { + background: transparent; + } +} diff --git a/assets/styling/blog.css b/assets/styling/blog.css deleted file mode 100644 index f27f060..0000000 --- a/assets/styling/blog.css +++ /dev/null @@ -1,8 +0,0 @@ -#blog { - margin-top: 50px; -} - -#blog a { - color: #ffffff; - margin-top: 50px; -} \ No newline at end of file diff --git a/assets/styling/echo.css b/assets/styling/echo.css deleted file mode 100644 index 67d9b2b..0000000 --- a/assets/styling/echo.css +++ /dev/null @@ -1,34 +0,0 @@ -#echo { - width: 360px; - margin-left: auto; - margin-right: auto; - margin-top: 50px; - background-color: #1e222d; - padding: 20px; - border-radius: 10px; -} - -#echo>h4 { - margin: 0px 0px 15px 0px; -} - - -#echo>input { - border: none; - border-bottom: 1px white solid; - background-color: transparent; - color: #ffffff; - transition: border-bottom-color 0.2s ease; - outline: none; - display: block; - padding: 0px 0px 5px 0px; - width: 100%; -} - -#echo>input:focus { - border-bottom-color: #6d85c6; -} - -#echo>p { - margin: 20px 0px 0px auto; -} \ No newline at end of file diff --git a/assets/styling/main.css b/assets/styling/main.css deleted file mode 100644 index e13b92d..0000000 --- a/assets/styling/main.css +++ /dev/null @@ -1,42 +0,0 @@ -body { - background-color: #0f1116; - color: #ffffff; - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; - margin: 20px; -} - -#hero { - margin: 0; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -#links { - width: 400px; - text-align: left; - font-size: x-large; - color: white; - display: flex; - flex-direction: column; -} - -#links a { - color: white; - text-decoration: none; - margin-top: 20px; - margin: 10px 0px; - border: white 1px solid; - border-radius: 5px; - padding: 10px; -} - -#links a:hover { - background-color: #1f1f1f; - cursor: pointer; -} - -#header { - max-width: 1200px; -} \ No newline at end of file diff --git a/assets/styling/navbar.css b/assets/styling/navbar.css deleted file mode 100644 index 7372c63..0000000 --- a/assets/styling/navbar.css +++ /dev/null @@ -1,16 +0,0 @@ -#navbar { - display: flex; - flex-direction: row; -} - -#navbar a { - color: #ffffff; - margin-right: 20px; - text-decoration: none; - transition: color 0.2s ease; -} - -#navbar a:hover { - cursor: pointer; - color: #91a4d2; -} \ No newline at end of file diff --git a/assets/tailwind.css b/assets/tailwind.css index fdfa637..0af5088 100644 --- a/assets/tailwind.css +++ b/assets/tailwind.css @@ -7,6 +7,10 @@ 'Noto Color Emoji'; --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + --spacing: 0.25rem; + --text-4xl: 2.25rem; + --text-4xl--line-height: calc(2.5 / 2.25); + --font-weight-bold: 700; --default-font-family: var(--font-sans); --default-mono-font-family: var(--font-mono); } @@ -160,18 +164,41 @@ .visible { visibility: visible; } - .relative { - position: relative; + .m-0 { + margin: calc(var(--spacing) * 0); } - .block { - display: block; + .hidden { + display: none; } - .contents { - display: contents; + .table { + display: table; + } + .w-1 { + width: calc(var(--spacing) * 1); } .transform { transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); } + .p-1 { + padding: calc(var(--spacing) * 1); + } + .p-2 { + padding: calc(var(--spacing) * 2); + } + .px-2 { + padding-inline: calc(var(--spacing) * 2); + } + .ps-6 { + padding-inline-start: calc(var(--spacing) * 6); + } + .text-4xl { + font-size: var(--text-4xl); + line-height: var(--tw-leading, var(--text-4xl--line-height)); + } + .font-bold { + --tw-font-weight: var(--font-weight-bold); + font-weight: var(--font-weight-bold); + } } @property --tw-rotate-x { syntax: "*"; @@ -193,6 +220,10 @@ syntax: "*"; inherits: false; } +@property --tw-font-weight { + syntax: "*"; + inherits: false; +} @layer properties { @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { *, ::before, ::after, ::backdrop { @@ -201,6 +232,7 @@ --tw-rotate-z: initial; --tw-skew-x: initial; --tw-skew-y: initial; + --tw-font-weight: initial; } } } diff --git a/shell.nix b/shell.nix index ddf11e9..886a391 100644 --- a/shell.nix +++ b/shell.nix @@ -5,6 +5,12 @@ pkgs.mkShell { ]; nativeBuildInputs = with pkgs;[ openssl + glib + gdk-pixbuf + pango + atk + xdo + lld ]; PKG_CONFIG_PATH = "${pkgs.openssl.dev}/lib/pkgconfig"; } diff --git a/src/components/echo.rs b/src/components/echo.rs index f42b21c..1d3567e 100644 --- a/src/components/echo.rs +++ b/src/components/echo.rs @@ -1,13 +1,13 @@ use dioxus::prelude::*; -const ECHO_CSS: Asset = asset!("/assets/styling/echo.css"); +//const ECHO_CSS: Asset = asset!("/assets/styling/echo.css"); #[component] pub fn Echo() -> Element { let mut response = use_signal(|| String::new()); rsx! { - document::Link { rel: "stylesheet", href: ECHO_CSS } +// document::Link { rel: "stylesheet", href: ECHO_CSS } div { id: "echo", diff --git a/src/components/mod.rs b/src/components/mod.rs index 4270a85..1d45b58 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -4,3 +4,4 @@ pub use hero::Hero; mod echo; pub use echo::Echo; +pub mod progress; diff --git a/src/components/progress/component.rs b/src/components/progress/component.rs new file mode 100644 index 0000000..7bc588a --- /dev/null +++ b/src/components/progress/component.rs @@ -0,0 +1,23 @@ +use dioxus::prelude::*; +use dioxus_primitives::progress::{self, ProgressIndicatorProps, ProgressProps}; + +#[component] +pub fn Progress(props: ProgressProps) -> Element { + rsx! { + document::Link { rel: "stylesheet", href: asset!("./style.css") } + progress::Progress { + class: "progress", + value: props.value, + max: props.max, + attributes: props.attributes, + {props.children} + } + } +} + +#[component] +pub fn ProgressIndicator(props: ProgressIndicatorProps) -> Element { + rsx! { + progress::ProgressIndicator { class: "progress-indicator", attributes: props.attributes, {props.children} } + } +} diff --git a/src/components/progress/mod.rs b/src/components/progress/mod.rs new file mode 100644 index 0000000..9a8ae55 --- /dev/null +++ b/src/components/progress/mod.rs @@ -0,0 +1,2 @@ +mod component; +pub use component::*; \ No newline at end of file diff --git a/src/components/progress/style.css b/src/components/progress/style.css new file mode 100644 index 0000000..43b9870 --- /dev/null +++ b/src/components/progress/style.css @@ -0,0 +1,31 @@ +.progress { + position: relative; + overflow: hidden; + width: 200px; + height: .5rem; + box-sizing: border-box; + border-radius: 9999px; + background: var(--primary-color-5); +} + +.progress[data-state='indeterminate'] .progress-indicator { + width: 50%; + animation: indeterminate 1s infinite linear; +} + +.progress-indicator { + width: var(--progress-value, 0%); + height: 100%; + background-color: var(--secondary-color-1); + transition: width 250ms ease; +} + +@keyframes indeterminate { + 0% { + transform: translateX(-100%); + } + + 100% { + transform: translateX(200%); + } +} diff --git a/src/main.rs b/src/main.rs index 2244433..44e1943 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use dioxus::prelude::*; - -use views::{Blog, Home, Navbar}; +use views::{Blog, Home, Navbar, Upload}; +use tracing::Level; mod components; mod views; @@ -9,6 +9,8 @@ mod views; #[derive(Debug, Clone, Routable, PartialEq)] #[rustfmt::skip] enum Route { + #[route("/upload")] + Upload {}, #[layout(Navbar)] #[route("/")] Home {}, @@ -17,10 +19,11 @@ enum Route { } const FAVICON: Asset = asset!("/assets/favicon.ico"); -const MAIN_CSS: Asset = asset!("/assets/styling/main.css"); +//const MAIN_CSS: Asset = asset!("/assets/styling/main.css"); const TAILWIND_CSS: Asset = asset!("/assets/tailwind.css"); fn main() { + dioxus::logger::init(Level::INFO).expect("failed to init logger"); dioxus::launch(App); } @@ -28,7 +31,7 @@ fn main() { fn App() -> Element { rsx! { document::Link { rel: "icon", href: FAVICON } - document::Link { rel: "stylesheet", href: MAIN_CSS } +// document::Link { rel: "stylesheet", href: MAIN_CSS } document::Link { rel: "stylesheet", href: TAILWIND_CSS } Router:: {} diff --git a/src/views/blog.rs b/src/views/blog.rs index 2d32a88..36b85a5 100644 --- a/src/views/blog.rs +++ b/src/views/blog.rs @@ -2,12 +2,12 @@ use crate::Route; use dioxus::prelude::*; use crate::components::{Hero}; -const BLOG_CSS: Asset = asset!("/assets/styling/blog.css"); +//const BLOG_CSS: Asset = asset!("/assets/styling/blog.css"); #[component] pub fn Blog(id: i32) -> Element { rsx! { - document::Link { rel: "stylesheet", href: BLOG_CSS } + // document::Link { rel: "stylesheet", href: BLOG_CSS } div { id: "blog", diff --git a/src/views/mod.rs b/src/views/mod.rs index dc25dba..c17be14 100644 --- a/src/views/mod.rs +++ b/src/views/mod.rs @@ -6,3 +6,6 @@ pub use blog::Blog; mod navbar; pub use navbar::Navbar; + +mod upload; +pub use upload::Upload; diff --git a/src/views/navbar.rs b/src/views/navbar.rs index 16bcf73..8b0cc7d 100644 --- a/src/views/navbar.rs +++ b/src/views/navbar.rs @@ -1,12 +1,12 @@ use crate::Route; use dioxus::prelude::*; -const NAVBAR_CSS: Asset = asset!("/assets/styling/navbar.css"); +//const NAVBAR_CSS: Asset = asset!("/assets/styling/navbar.css"); #[component] pub fn Navbar() -> Element { rsx! { - document::Link { rel: "stylesheet", href: NAVBAR_CSS } +// document::Link { rel: "stylesheet", href: NAVBAR_CSS } div { id: "navbar", diff --git a/src/views/upload.rs b/src/views/upload.rs new file mode 100644 index 0000000..5b8e46e --- /dev/null +++ b/src/views/upload.rs @@ -0,0 +1,154 @@ +use dioxus::{ + fullstack::{ByteStream, FileStream}, + prelude::*, +}; + +use dioxus_html::{FileData, HasFileData}; +use futures::StreamExt; + +use std::{ env, fs, io::Write }; + + +use random_string; + +pub fn byte_to_human_size(size: u64) -> String { + let sizes = vec!["B", "KB", "MB", "GB", "TB", "WTFAREYOUDOINGB"]; + let mut current = 0; + + let mut res_size: f64 = size as f64; + let mut res: String; + + while (res_size >= 1000.0 && current < sizes.len()) { + res_size /= 1000.0; + current += 1; + } + + res = ((res_size * 100.0).round() / 100.0).to_string() + " " + sizes[current]; + res +} + +#[post("/api/upload")] +async fn upload_file(mut upload: FileStream) -> Result { + let UPLOAD_SIZE_LIMIT: u64 = 1024 * 1024 * 1024 * 1; + let UPLOAD_FOLDER: String = match env::var("UPLOAD_FOLDER") { + Ok(value) => { value }, + Err(_) => { return HttpError::internal_server_error("UPLOAD_FOLDER not set"); } + }; + + let mut total_len: u64 = 0; + let mut error: Option<&str> = None; + + let filename: String = loop { + let cur = random_string::generate(20, "ABCDEFGHIJKLMNOPQRTSTUVWXYZ0123456789"); + if (!fs::exists(UPLOAD_FOLDER.clone() + &cur).expect("can't check if file exists")) { + break cur; + } + }; + + if upload.size().unwrap() > UPLOAD_SIZE_LIMIT { + return HttpError::payload_too_large("this file is too large"); + } + + + let mut file = match fs::File::create(UPLOAD_FOLDER.clone() + &filename) { + Ok(val) => { val }, + Err(_) => { return HttpError::internal_server_error("failed to open the output file") } + }; + + while let Some(chunk) = upload.next().await { + match chunk { + Ok(bytes) => { + total_len += bytes.len() as u64; + if total_len > UPLOAD_SIZE_LIMIT { + error = Some("Uploaded file to large"); + break; + } + + if file.write(&bytes).is_err() { error == Some("failed write"); break; }; + }, + Err(_) => { error = Some("unknown"); break; } + } + } + + match error { + Some(err)=> { + file.sync_data(); + fs::remove_file(UPLOAD_FOLDER.clone() + &filename); + HttpError::internal_server_error(err)? + } + None => { Ok(filename) } + } + +} + +pub fn build_table(files: Vec<(String, String, Option>)>) -> Element { + rsx! { + table { + tr { + th { "filename" } + th { "size" } + th { "url" } + } + + { files.iter().map(|file| rsx! { + tr { + td { class: "px-2", "{file.0}" } + td { class: "px-2", "{file.1}" } + td { class: "px-2", + match &file.2 { + Some(res) => { match res { + Ok(file_id) => { rsx! { input { type:"button" , "/upload/dl/{file_id}"} } }, + Err(e) => { + let msg = e.message.clone().unwrap(); + rsx! { p { "Upload failed, reason : {msg}" } } + } + } } + None => { rsx! { p { "Waiting for file to be uploaded" } } } + } + } + } + }) } + } + } +} + +#[component] +pub fn Upload() -> Element { + //TODO: global config struct + let UPLOAD_SIZE_LIMIT: u64 = 1024 * 1024 * 1024 * 1; + + let mut selected : Signal>)>> = use_signal(|| vec![]); + + rsx! { + div { class : "p-2", + p { class: "text-4xl font-bold p-1", "Upload a file" } + + form { + + label { for :"file", { + if selected.len() == 0 { + rsx! { "No file selected" } + } else { + build_table(selected()) + } + } } + + input { id: "file", r#type : "file" ,multiple: true, class : "hidden", oninput: move |e| async move { + for file in e.files() { + selected.with_mut(|files| {files.push((file.name(), byte_to_human_size(file.size()), None)); } ); + let idx = selected().len() - 1; + + if (file.size() > UPLOAD_SIZE_LIMIT) { + //messy but firefox can't handle when server returns early + selected.with_mut(|files| { files[idx].2 = Some(HttpError::payload_too_large("This file is too large")) }); + continue; + } + + let res = upload_file(file.clone().into()).await; + selected.with_mut(|files| { files[idx].2 = Some(res) }); + } + }} + } + } + } +} diff --git a/todo b/todo new file mode 100644 index 0000000..bf451f7 --- /dev/null +++ b/todo @@ -0,0 +1,12 @@ + +/upload + - can upload up to 100GB + - if video, set mime + - deletion rules: + - older than 1 month + - more than 300GB used and more than 7 days old + - show file deletion info + +/status (check status of dependent devices, maybe useless) + + /boot (later, previous program is bad)