switch to scss asset & remove sir

This commit is contained in:
2025-10-27 18:54:34 -06:00
parent 987cfd57d2
commit 4e30be3ebd
4 changed files with 339 additions and 498 deletions
Generated
-66
View File
@@ -107,12 +107,6 @@ dependencies = [
"pkg-config", "pkg-config",
] ]
[[package]]
name = "arc-swap"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]] [[package]]
name = "ashpd" name = "ashpd"
version = "0.8.1" version = "0.8.1"
@@ -3256,15 +3250,6 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
[[package]]
name = "litrs"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
dependencies = [
"proc-macro2",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.12" version = "0.4.12"
@@ -3651,7 +3636,6 @@ dependencies = [
"serde", "serde",
"serde-wasm-bindgen 0.6.5", "serde-wasm-bindgen 0.6.5",
"serde_json", "serde_json",
"sir",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tokio-util", "tokio-util",
@@ -3860,17 +3844,6 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.19" version = "0.2.19"
@@ -5022,23 +4995,6 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "rsass"
version = "0.28.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212e14dfa9e48df42c0125c80a213a9a0269103130c8c154080fdbbb79ce7d52"
dependencies = [
"arc-swap",
"fastrand",
"lazy_static",
"nom",
"num-bigint",
"num-integer",
"num-rational",
"num-traits",
"tracing",
]
[[package]] [[package]]
name = "rust-embed" name = "rust-embed"
version = "8.5.0" version = "8.5.0"
@@ -5782,28 +5738,6 @@ version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "sir"
version = "0.6.0-alpha.4"
source = "git+https://gitlab.com/samsartor/sir#99ac4db5c0a02debf15c145c998fe90d854269b2"
dependencies = [
"dioxus",
"once_cell",
"sir-macro",
]
[[package]]
name = "sir-macro"
version = "0.5.0"
source = "git+https://gitlab.com/samsartor/sir#99ac4db5c0a02debf15c145c998fe90d854269b2"
dependencies = [
"litrs",
"proc-macro2",
"quote",
"rand 0.8.5",
"rsass",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
-3
View File
@@ -82,9 +82,6 @@ ordermap = "0.5.3"
html-purifier = "0.3.0" html-purifier = "0.3.0"
markdown = "0.3.0" markdown = "0.3.0"
futures-channel = "0.3.30" futures-channel = "0.3.30"
sir = { git = "https://gitlab.com/samsartor/sir", features = [
"dioxus",
] } # dioxus 0.6
mumble-web2-common = { workspace = true } mumble-web2-common = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
tracing-subscriber = { version = "0.3.18", features = ["ansi"] } tracing-subscriber = { version = "0.3.18", features = ["ansi"] }
+293
View File
@@ -0,0 +1,293 @@
:root {
--txt-color: oklch(0.9 0 99);
--bg-color: oklch(0.15 0.01 338.64);
--light-bg-color: oklch(0.25 0.01 338.64);
--login-bg-color: #5d7680;
--primary-btn-color: #7bad9f;
--accent-normal: #7bad9f;
--accent-muted: #ff746c;
--accent-deafened: #464459;
--line-width: 2px;
--line-color: white;
}
body {
margin: 0;
}
#main {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-around;
background-color: var(--bg-color);
overflow: auto;
color: var(--txt-color);
font-family: Nunito;
font-size: 15pt;
font-weight: 600;
}
button {
font-weight: bold;
font-size: medium;
border: none;
border-radius: 4px;
color: var(--txt-color);
background-color: var(--primary-btn-color);
cursor: pointer;
}
input {
border: none;
border-radius: 4px;
background-color: white;
color: black;
}
input:focus,
input:focus-visible {
border: none;
outline: solid var(--line-width) var(--accent-normal);
outline-offset: -3px;
}
a:link {
color: var(--accent-normal);
}
a:visited {
color: var(--accent-muted);
}
.userpil {
border-radius: 100px;
padding: 4px 8px;
width: fit-content;
img {
height: 1em;
vertical-align: text-bottom;
}
&.is_self {
font-weight: bolder;
}
}
.channel {
&_details {
flex: 0 0 100%;
summary {
cursor: pointer;
}
summary:focus-visible {
outline: none;
}
}
&_children {
border-left: solid var(--line-color) var(--line-width);
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 8px;
margin-left: 5px;
padding-left: 11px;
padding-top: 4px;
}
}
.chat {
&_panel {
display: flex;
flex-direction: column;
}
&_history {
overflow-y: auto;
flex: 1 0 0;
}
&_message {
display: flex;
flex-direction: row;
margin: 16px;
gap: 8px;
align-items: center;
}
&_box_wrapper {
padding: 16px;
border-top: solid var(--line-color) var(--line-width);
}
&_box {
display: flex;
flex-direction: row;
gap: 16px;
background-color: var(--light-bg-color);
padding-top: 16px;
padding-bottom: 16px;
padding-left: 8px;
padding-right: 16px;
border-radius: 8px;
input {
color: white;
background-color: var(--light-bg-color);
font-size: larger;
flex-grow: 1;
border: none;
}
input:focus {
outline: none;
}
}
}
.user_edit_button {
background-color: oklch(0.53 0.1431 264.18);
border-radius: 50%;
aspect-ratio: 1 / 1;
}
.button_row {
display: flex;
gap: 10px;
.spacer {
flex-grow: 1;
}
}
.toggle_button {
padding: 8px;
height: 100%;
aspect-ratio: 1 / 1;
background-color: unset;
border: solid rgb(255 255 255 / 0.1) 3px;
border-radius: 10px;
color: rgb(255 255 255 / 50%);
transition: all 0.5s ease-in-out;
&.is_on {
background-color: oklch(0.5 0.1381 21.71 / 20.12%);
color: oklch(0.53 0.1505 21.71 / 89.38%);
}
.material-symbols-outlined {
font-variation-settings: 'FILL' 1, 'wght' 700, 'GRAD' 0, 'opsz' 48;
vertical-align: middle;
font-size: 35px;
}
}
.server {
&_grid {
display: grid;
height: 100%;
background-color: var(--bg-color);
grid-template-rows: 1fr auto;
grid-template-columns: 1fr 2fr;
grid-template-areas:
"tree chat"
"control chat";
@media screen and (max-width: 720px) {
grid-template-rows: auto 1fr 1fr;
grid-template-columns: 1fr;
grid-template-areas:
"tree"
"control"
"chat";
}
}
&_channel_box {
padding: 16px;
overflow: auto;
grid-area: tree;
}
&_chat_box {
display: flex;
flex-direction: row;
grid-area: chat;
border-left: solid var(--line-color) var(--line-width);
@media screen and (max-width: 720px) {
border-left: unset;
border-top: solid var(--line-color) var(--line-width);
}
}
&_control_box {
padding: 16px;
margin: 16px;
background-color: var(--light-bg-color);
border-radius: 10px;
overflow: hidden;
grid-area: control;
display: flex;
gap: 10px;
flex-direction: column;
}
}
.login {
max-width: 50vw;
align-self: center;
padding: 32px;
border-radius: 16px;
background-color: var(--login-bg-color);
display: flex;
flex-direction: column;
gap: 16px;
input,
button {
padding: 8px;
}
h1 {
margin: 0;
color: #b3c6b4;
}
&_bttn {
font-weight: bold;
font-size: large;
}
&_error {
background-color: white;
border-radius: 4px;
overflow: auto;
padding: 4px;
color: red;
pre {
color: black;
}
}
}
+46 -429
View File
@@ -4,7 +4,6 @@ use dioxus::prelude::*;
use mime_guess::Mime; use mime_guess::Mime;
use mumble_web2_common::{ClientConfig, ServerStatus}; use mumble_web2_common::{ClientConfig, ServerStatus};
use ordermap::OrderSet; use ordermap::OrderSet;
use sir::{css, global_css};
use std::collections::HashMap; use std::collections::HashMap;
use crate::imp; use crate::imp;
@@ -138,25 +137,6 @@ impl UserIcon {
#[component] #[component]
pub fn UserPill(name: String, icon: UserIcon, isself: bool) -> Element { pub fn UserPill(name: String, icon: UserIcon, isself: bool) -> Element {
let pill = css!(
"
border-radius: 100px;
padding: 4px 8px;
width: fit-content;
img {
height: 1em;
vertical-align: text-bottom;
}
"
);
let pill_self = css!(
"
font-weight: bolder;
"
);
let color = match icon { let color = match icon {
UserIcon::Normal => "var(--accent-normal)", UserIcon::Normal => "var(--accent-normal)",
UserIcon::Muted => "var(--accent-muted)", UserIcon::Muted => "var(--accent-muted)",
@@ -166,7 +146,7 @@ pub fn UserPill(name: String, icon: UserIcon, isself: bool) -> Element {
rsx!( rsx!(
div { div {
class: match isself { true => format!("{pill} {pill_self}"), false => format!("{pill}") }, class: match isself { true => "userpil is_self", false => "userpil" },
style: "background-color: {color}", style: "background-color: {color}",
{ icon.url().map(|url| rsx!(img { src: url })) } { icon.url().map(|url| rsx!(img { src: url })) }
"\u{00A0}{name}\u{00A0}" "\u{00A0}{name}\u{00A0}"
@@ -200,34 +180,9 @@ pub fn Channel(id: ChannelId) -> Element {
return rsx!("missing channel {id}"); return rsx!("missing channel {id}");
}; };
let channel_details = css!(
"
flex: 0 0 100%;
summary {
cursor: pointer;
}
summary:focus-visible {
outline: none;
}
"
);
let channel_children = css!(
"
border-left: solid var(--line-color) var(--line-width);
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 8px;
margin-left: 5px;
padding-left: 11px;
padding-top: 4px; "
);
rsx!( rsx!(
details { details {
class: "{channel_details}", class: "channel_details",
open: true, open: true,
summary { summary {
span { span {
@@ -242,7 +197,7 @@ pub fn Channel(id: ChannelId) -> Element {
} }
if state.users.len() + state.children.len() > 0 { if state.users.len() + state.children.len() > 0 {
div { div {
class: "{channel_children}", class: "channel_children",
for id in state.users.iter() { for id in state.users.iter() {
User { id: *id } User { id: *id }
} }
@@ -283,71 +238,6 @@ pub fn ChatView() -> Element {
let server = STATE.server.read(); let server = STATE.server.read();
let mut draft = use_signal(|| "".to_string()); let mut draft = use_signal(|| "".to_string());
let chat_panel = css!(
"
display: flex;
flex-direction: column;
"
);
let chat_history = css!(
"
overflow-y: auto;
flex: 1 0 0;
"
);
let chat_message = css!(
"
display: flex;
flex-direction: row;
margin: 16px;
gap: 8px;
align-items: center;
"
);
let chat_box_wrapper = css!(
"
padding: 16px;
border-top: solid var(--line-color) var(--line-width);
"
);
let chat_box = css!(
"
display: flex;
flex-direction: row;
gap: 16px;
background-color: var(--light-bg-color);
padding-top: 16px;
padding-bottom: 16px;
padding-left: 8px;
padding-right: 16px;
border-radius: 8px;
input {
color: white;
background-color: var(--light-bg-color);
font-size: larger;
flex-grow: 1;
border: none;
}
input:focus {
outline: none;
}
"
);
let mut do_send = move || { let mut do_send = move || {
if let Some(user) = STATE.server.read().this_user() { if let Some(user) = STATE.server.read().this_user() {
net.send(SendChat { net.send(SendChat {
@@ -359,12 +249,12 @@ pub fn ChatView() -> Element {
rsx!( rsx!(
div { div {
class: "{chat_panel}", class: "chat_panel",
div { div {
class: "{chat_history}", class: "chat_history",
for chat in server.chat.iter() { for chat in server.chat.iter() {
div { div {
class: "{chat_message}", class: "chat_message",
if let Some(sender) = chat.sender.and_then(|u| server.users.get(&u)) { if let Some(sender) = chat.sender.and_then(|u| server.users.get(&u)) {
UserPill { UserPill {
name: sender.name.clone(), name: sender.name.clone(),
@@ -379,9 +269,9 @@ pub fn ChatView() -> Element {
} }
} }
div { div {
class: "{chat_box_wrapper}", class: "chat_box_wrapper",
div { div {
class: "{chat_box}", class: "chat_box",
input { input {
placeholder: "say something", placeholder: "say something",
value: "{draft.read()}", value: "{draft.read()}",
@@ -418,25 +308,6 @@ pub fn ChatView() -> Element {
) )
} }
// true => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "mic_off"}),
//Connecting => rsx! {
// div {
// class: "{connecting_status}",
// span {
// class: "material-symbols-outlined",
// style: "vertical-align: middle; font-size: 30px;",
// "signal_cellular_alt_2_bar"
// }
// span {
// style: "width: 5px; display: inline-block;"
// }
// span {
// style: "vertical-align: middle; font-size: 30px;",
// "Connecting"
// }
// }
//},
#[component] #[component]
pub fn ControlView(config: Resource<ClientConfig>) -> Element { pub fn ControlView(config: Resource<ClientConfig>) -> Element {
let net: Coroutine<Command> = use_coroutine_handle(); let net: Coroutine<Command> = use_coroutine_handle();
@@ -462,99 +333,15 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
.as_ref() .as_ref()
.and_then(|gui_config| gui_config.proxy_url.clone()); .and_then(|gui_config| gui_config.proxy_url.clone());
let button_row = css!( let connecting_color = "yellow";
r#" let connected_color = "oklch(0.55 0.1184 141.35)";
display: flex; let disconnected_color = "gray";
gap: 10px; let failed_color = "red";
"#
);
let spacer = css!(
r#"
flex-grow: 1;
"#
);
let toggle_button = css!(
r#"
padding: 8px;
height: 100%;
aspect-ratio: 1 / 1;
background-color: unset;
border: solid rgb(255 255 255 / 0.1) 3px;
border-radius: 10px;
color: rgb(255 255 255 / 50%);
transition: all 0.5s ease-in-out;
"#
);
let toggle_button_on = css!(
r#"
padding: 8px;
height: 100%;
aspect-ratio: 1 / 1;
background-color: oklch(0.5 0.1381 21.71 / 20.12%);
border: solid rgb(255 255 255 / 0) 3px;
border-radius: 10px;
color: oklch(0.53 0.1505 21.71 / 89.38%);
transition: all 0.25s ease-in-out;
"#
);
let button_style = r#"
font-variation-settings: 'FILL' 1, 'wght' 700, 'GRAD' 0, 'opsz' 48;
vertical-align: middle;
font-size: 35px;
"#;
let connecting_status = css!(
r#"
color: yellow;
"#
);
let connected_status = css!(
r#"
color: oklch(0.55 0.1184 141.35);
"#
);
let disconnected_status = css!(
r#"
color: gray;
"#
);
let failed_status = css!(
r#"
color: red;
"#
);
let connection_info = css!(
r#"
color: gray;
"#
);
let user_edit_button = css!(
r#"
background-color: oklch(0.53 0.1431 264.18);
border-radius: 50%;
aspect-ratio: 1 / 1;
"#
);
let connection_status = match &*status.read() { let connection_status = match &*status.read() {
Connecting => rsx! { Connecting => rsx! {
div { div {
class: "{connecting_status}", style: "color: \"{connecting_color}\";",
span { span {
class: "material-symbols-outlined", class: "material-symbols-outlined",
style: "vertical-align: middle; font-size: 30px;", style: "vertical-align: middle; font-size: 30px;",
@@ -572,7 +359,7 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
Connected => rsx! { Connected => rsx! {
div { div {
div { div {
class: "{connected_status}", style: "color: \"{connected_color}\";",
span { span {
class: "material-symbols-outlined", class: "material-symbols-outlined",
style: "vertical-align: middle; font-size: 30px;", style: "vertical-align: middle; font-size: 30px;",
@@ -587,7 +374,6 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
} }
} }
div { div {
class: "{connection_info}",
span { style: "width: 3px; display: inline-block;"} span { style: "width: 3px; display: inline-block;"}
span { "{current_channel_name}" } span { "{current_channel_name}" }
if let Some(proxy_url) = proxy_url { if let Some(proxy_url) = proxy_url {
@@ -599,7 +385,7 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
}, },
Disconnected => rsx! { Disconnected => rsx! {
div { div {
class: "{disconnected_status}", style: "color: \"{disconnected_color}\";",
span { span {
class: "material-symbols-outlined", class: "material-symbols-outlined",
style: "vertical-align: middle;", style: "vertical-align: middle;",
@@ -616,7 +402,7 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
}, },
Failed(_) => rsx! { Failed(_) => rsx! {
div { div {
class: "{failed_status}", style: "color: \"{failed_color}\";",
span { span {
class: "material-symbols-outlined", class: "material-symbols-outlined",
style: "vertical-align: middle;", style: "vertical-align: middle;",
@@ -637,17 +423,16 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
rsx!( rsx!(
// Server control // Server control
div { div {
class: "{button_row}", class: "button_row",
div { div {
{connection_status} {connection_status}
} }
span { class: "{spacer}" } span { class: "spacer" }
button { button {
class: "{toggle_button}", class: "toggle_button",
onclick: move |_| net.send(Disconnect), onclick: move |_| net.send(Disconnect),
span { span {
class: "material-symbols-outlined", class: "material-symbols-outlined",
style: "{button_style}",
"signal_disconnected" "signal_disconnected"
} }
} }
@@ -655,9 +440,9 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
hr { style: "width: 100%;" } hr { style: "width: 100%;" }
// User control // User control
div { div {
class: "{button_row}", class: "button_row",
button { button {
class: "{user_edit_button}", class: "user_edit_button",
span { span {
class: "material-symbols-outlined", class: "material-symbols-outlined",
style: "color: oklch(0.65 0.2245 28.06); font-size: 45px; font-variation-settings: 'FILL' 1, 'wght' 700, 'GRAD' 0, 'opsz' 48;", style: "color: oklch(0.65 0.2245 28.06); font-size: 45px; font-variation-settings: 'FILL' 1, 'wght' 700, 'GRAD' 0, 'opsz' 48;",
@@ -672,11 +457,11 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
span { style: "font-size: 20px; color: gray;", "some data" } span { style: "font-size: 20px; color: gray;", "some data" }
} }
} }
span { class: "{spacer}" } span { class: "spacer" }
button { button {
class: match denoise() { class: match denoise() {
true => toggle_button_on, true => "toggle_button is_on",
false => toggle_button, false => "toggle_button",
}, },
role: "switch", role: "switch",
aria_checked: denoise(), aria_checked: denoise(),
@@ -686,36 +471,36 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
net.send(UpdateMicEffects { denoise: new_denoise }) net.send(UpdateMicEffects { denoise: new_denoise })
}, },
match denoise() { match denoise() {
true => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "cadence"}), true => rsx!(span { class: "material-symbols-outlined", "cadence"}),
false => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "graphic_eq"}), false => rsx!(span { class: "material-symbols-outlined", "graphic_eq"}),
} }
} }
button { button {
class: match mute || self_mute { class: match mute || self_mute {
true => toggle_button_on, true => "toggle_button is_on",
false => toggle_button, false => "toggle_button",
}, },
role: "switch", role: "switch",
aria_checked: mute || self_mute, aria_checked: mute || self_mute,
disabled: mute, disabled: mute,
onclick: move |_| net.send(SetMute { mute: !self_mute }), onclick: move |_| net.send(SetMute { mute: !self_mute }),
match mute || self_mute { match mute || self_mute {
true => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "mic_off"}), true => rsx!(span { class: "material-symbols-outlined", "mic_off"}),
false => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "mic"}), false => rsx!(span { class: "material-symbols-outlined", "mic"}),
} }
} }
button { button {
class: match deaf || self_deaf { class: match deaf || self_deaf {
true => toggle_button_on, true => "toggle_button in_on",
false => toggle_button, false => "toggle_button",
}, },
role: "switch", role: "switch",
aria_checked: deaf || self_deaf, aria_checked: deaf || self_deaf,
disabled: deaf, disabled: deaf,
onclick: move |_| net.send(SetDeaf { deaf: !self_deaf }), onclick: move |_| net.send(SetDeaf { deaf: !self_deaf }),
match deaf || self_deaf { match deaf || self_deaf {
true => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "volume_off"}), true => rsx!(span { class: "material-symbols-outlined", "volume_off"}),
false => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "volume_up"}), false => rsx!(span { class: "material-symbols-outlined", "volume_up"}),
} }
} }
} }
@@ -737,71 +522,11 @@ pub fn ServerView(config: Resource<ClientConfig>) -> Element {
return rsx!(); return rsx!();
}; };
let grid = css!(
r#"
display: grid;
height: 100%;
background-color: var(--bg-color);
grid-template-rows: 1fr auto;
grid-template-columns: 1fr 2fr;
grid-template-areas:
"tree chat"
"control chat";
@media screen and (max-width: 720px) {
grid-template-rows: auto 1fr 1fr;
grid-template-columns: 1fr;
grid-template-areas:
"tree"
"control"
"chat";
}
"#
);
let channel_box = css!(
"
padding: 16px;
overflow: auto;
grid-area: tree;
"
);
let chat_box = css!(
"
display: flex;
flex-direction: row;
grid-area: chat;
border-left: solid var(--line-color) var(--line-width);
@media screen and (max-width: 720px) {
border-left:unset;
border-top: solid var(--line-color) var(--line-width);
}
"
);
let control_box = css!(
"
padding: 16px;
margin: 16px;
background-color: var(--light-bg-color);
border-radius: 10px;
overflow: hidden;
grid-area: control;
display: flex;
gap: 10px;
flex-direction: column;
"
);
rsx!( rsx!(
div { div {
class: "{grid}", class: "server_grid",
div { div {
class: "{channel_box}", class: "server_channel_box",
for (id, state) in server.channels.iter() { for (id, state) in server.channels.iter() {
if state.parent.is_none() { if state.parent.is_none() {
Channel { id: *id } Channel { id: *id }
@@ -809,11 +534,11 @@ pub fn ServerView(config: Resource<ClientConfig>) -> Element {
} }
} }
div { div {
class: "{chat_box}", class: "server_chat_box",
ChatView {} ChatView {}
} }
div { div {
class: "{control_box}", class: "server_control_box",
ControlView { config } ControlView { config }
} }
} }
@@ -865,49 +590,6 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
let previous_username = imp::load_username(); let previous_username = imp::load_username();
let mut username = use_signal(|| previous_username.unwrap_or(String::new())); let mut username = use_signal(|| previous_username.unwrap_or(String::new()));
let error = css!(
"
background-color: white;
border-radius: 4px;
overflow: auto;
padding: 4px;
color: red;
pre {
color: black;
}
"
);
let login_box = css!(
"
max-width: 50vw;
align-self: center;
padding: 32px;
border-radius: 16px;
background-color: var(--login-bg-color);
display: flex;
flex-direction: column;
gap: 16px;
input,button {
padding: 8px;
}
h1 {
margin: 0;
color: #b3c6b4;
}
"
);
let bttn = css!(
"
font-weight: bold;
font-size: large;
"
);
let do_connect = move |_| { let do_connect = move |_| {
//let _ = set_default_username(&username.read()); //let _ = set_default_username(&username.read());
let _ = imp::set_default_username(&username.read()); let _ = imp::set_default_username(&username.read());
@@ -921,25 +603,25 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
let bottom = match &*status.read() { let bottom = match &*status.read() {
Disconnected => rsx! { Disconnected => rsx! {
button { button {
class: "{bttn}", class: "login_bttn",
onclick: do_connect.clone(), onclick: do_connect.clone(),
"Connect" "Connect"
} }
}, },
Connecting => rsx! { Connecting => rsx! {
div { div {
class: "{bttn}", class: "login_bttn",
"Connecting..." "Connecting..."
} }
}, },
Failed(msg) => rsx!( Failed(msg) => rsx!(
button { button {
class: "{bttn}", class: "login_bttn",
onclick: do_connect.clone(), onclick: do_connect.clone(),
"Reconnect" "Reconnect"
} }
div { div {
class: "{error}", class: "login_error",
"Failed to connect:" "Failed to connect:"
pre { pre {
"{msg}" "{msg}"
@@ -950,7 +632,7 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
}; };
rsx!( rsx!(
div { div {
class: "{login_box}", class: "login",
h1 { h1 {
"Mumble Web" "Mumble Web"
} }
@@ -1025,6 +707,8 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
} }
pub fn app() -> Element { pub fn app() -> Element {
static STYLE: Asset = asset!("/assets/main.scss");
use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx)); use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
let config = use_resource(|| async move { let config = use_resource(|| async move {
match imp::load_config().await { match imp::load_config().await {
@@ -1033,78 +717,11 @@ pub fn app() -> Element {
} }
}); });
global_css!(
"
:root {
--txt-color: oklch(0.9 0 99);
--bg-color: oklch(0.15 0.01 338.64);
--light-bg-color: oklch(0.25 0.01 338.64);
--login-bg-color: #5d7680;
--primary-btn-color: #7bad9f;
--accent-normal: #7bad9f;
--accent-muted: #ff746c;
--accent-deafened: #464459;
--line-width: 2px;
--line-color: white;
}
body {
margin: 0;
}
#main {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-around;
background-color: var(--bg-color);
overflow: auto;
color: var(--txt-color);
font-family: Nunito;
font-size: 15pt;
font-weight: 600;
}
button {
font-weight: bold;
font-size: medium;
border: none;
border-radius: 4px;
color: var(--txt-color);
background-color: var(--primary-btn-color);
cursor: pointer;
}
input {
border: none;
border-radius: 4px;
background-color: white;
color: black;
}
input:focus,input:focus-visible {
border: none;
outline: solid var(--line-width) var(--accent-normal);
outline-offset: -3px;
}
a:link {
color: var(--accent-normal);
}
a:visited {
color: var(--accent-muted);
}
"
);
rsx!( rsx!(
document::Link{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap" } document::Link{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap" }
document::Link{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" } document::Link{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" }
document::Link{ rel: "stylesheet", href: STYLE }
sir::AppStyle { }
match *STATE.status.read() { match *STATE.status.read() {
Connected => rsx!(ServerView { config }), Connected => rsx!(ServerView { config }),
_ => rsx!(LoginView { config }), _ => rsx!(LoginView { config }),