user control box with some styling
This commit is contained in:
+1
-3
@@ -11,9 +11,7 @@ mumble-web2-common = { path = "common" }
|
||||
version = "0.5.0"
|
||||
package = "mumble-protocol-2x"
|
||||
default-features = false
|
||||
features = [
|
||||
"asynchronous-codec",
|
||||
]
|
||||
features = ["asynchronous-codec"]
|
||||
|
||||
[profile]
|
||||
|
||||
|
||||
+12
-2
@@ -82,7 +82,9 @@ ordermap = "0.5.3"
|
||||
html-purifier = "0.3.0"
|
||||
markdown = "0.3.0"
|
||||
futures-channel = "0.3.30"
|
||||
sir = { git = "https://gitlab.com/samsartor/sir", features = ["dioxus"] } # dioxus 0.6
|
||||
sir = { git = "https://gitlab.com/samsartor/sir", features = [
|
||||
"dioxus",
|
||||
] } # dioxus 0.6
|
||||
mumble-web2-common = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tracing-subscriber = { version = "0.3.18", features = ["ansi"] }
|
||||
@@ -107,4 +109,12 @@ web = [
|
||||
"gloo-timers",
|
||||
"tracing-web",
|
||||
]
|
||||
desktop = ["dioxus/desktop", "tokio", "tokio-rustls", "tracing-subscriber/env-filter", "opus", "cpal", "dasp_ring_buffer"]
|
||||
desktop = [
|
||||
"dioxus/desktop",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tracing-subscriber/env-filter",
|
||||
"opus",
|
||||
"cpal",
|
||||
"dasp_ring_buffer",
|
||||
]
|
||||
|
||||
+290
-53
@@ -363,6 +363,269 @@ pub fn ChatView() -> Element {
|
||||
)
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn ControlView() -> Element {
|
||||
let net: Coroutine<Command> = use_coroutine_handle();
|
||||
let status = &STATE.status;
|
||||
let server = STATE.server.read();
|
||||
let Some(&UserState {
|
||||
deaf,
|
||||
self_deaf,
|
||||
mute,
|
||||
self_mute,
|
||||
ref name,
|
||||
channel,
|
||||
..
|
||||
}) = server.this_user()
|
||||
else {
|
||||
return rsx!();
|
||||
};
|
||||
|
||||
let current_channel_name = server.channels[&channel].name.clone();
|
||||
let Some(proxy_url) = &CONFIG.proxy_url else {
|
||||
return rsx!();
|
||||
};
|
||||
|
||||
let button_row = css!(
|
||||
r#"
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
"#
|
||||
);
|
||||
|
||||
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() {
|
||||
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"
|
||||
}
|
||||
}
|
||||
},
|
||||
Connected => rsx! {
|
||||
div {
|
||||
div {
|
||||
class: "{connected_status}",
|
||||
span {
|
||||
class: "material-symbols-outlined",
|
||||
style: "vertical-align: middle; font-size: 30px;",
|
||||
"signal_cellular_alt"
|
||||
}
|
||||
span {
|
||||
style: "width: 5px; display: inline-block;"
|
||||
}
|
||||
span {
|
||||
style: "vertical-align: middle; font-size: 25px;",
|
||||
"Connected"
|
||||
}
|
||||
}
|
||||
div {
|
||||
class: "{connection_info}",
|
||||
span { style: "width: 3px; display: inline-block;"}
|
||||
span { "{current_channel_name}" }
|
||||
span { " — " }
|
||||
span { "{proxy_url}" }
|
||||
}
|
||||
}
|
||||
},
|
||||
Disconnected => rsx! {
|
||||
div {
|
||||
class: "{disconnected_status}",
|
||||
span {
|
||||
class: "material-symbols-outlined",
|
||||
style: "vertical-align: middle;",
|
||||
"signal_disconnected"
|
||||
}
|
||||
span {
|
||||
style: "width: 5px; display: inline-block;"
|
||||
}
|
||||
span {
|
||||
style: "vertical-align: middle;",
|
||||
"Disconnected"
|
||||
}
|
||||
}
|
||||
},
|
||||
Failed(_) => rsx! {
|
||||
div {
|
||||
class: "{failed_status}",
|
||||
span {
|
||||
class: "material-symbols-outlined",
|
||||
style: "vertical-align: middle;",
|
||||
"error"
|
||||
}
|
||||
span {
|
||||
style: "width: 5px; display: inline-block;"
|
||||
}
|
||||
span {
|
||||
style: "vertical-align: middle;",
|
||||
"Failed"
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
rsx!(
|
||||
// Server control
|
||||
div {
|
||||
class: "{button_row}",
|
||||
div {
|
||||
{connection_status}
|
||||
}
|
||||
span { class: "{spacer}" }
|
||||
button {
|
||||
class: "{toggle_button}",
|
||||
onclick: move |_| net.send(Disconnect),
|
||||
span {
|
||||
class: "material-symbols-outlined",
|
||||
style: "{button_style}",
|
||||
"signal_disconnected"
|
||||
}
|
||||
}
|
||||
}
|
||||
hr { style: "width: 100%;" }
|
||||
// User control
|
||||
div {
|
||||
class: "{button_row}",
|
||||
button {
|
||||
class: "{user_edit_button}",
|
||||
span {
|
||||
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;",
|
||||
"person_edit"
|
||||
}
|
||||
}
|
||||
div {
|
||||
div {
|
||||
span { style: "font-size: 25px;", "{name}" }
|
||||
}
|
||||
div {
|
||||
span { style: "font-size: 20px; color: gray;", "some data" }
|
||||
}
|
||||
}
|
||||
span { class: "{spacer}" }
|
||||
button {
|
||||
class: match mute || self_mute {
|
||||
true => toggle_button_on,
|
||||
false => toggle_button,
|
||||
},
|
||||
role: "switch",
|
||||
aria_checked: mute || self_mute,
|
||||
disabled: mute,
|
||||
onclick: move |_| net.send(SetMute { mute: !self_mute }),
|
||||
match mute || self_mute {
|
||||
true => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "mic_off"}),
|
||||
false => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "mic"}),
|
||||
}
|
||||
}
|
||||
button {
|
||||
class: match deaf || self_deaf {
|
||||
true => toggle_button_on,
|
||||
false => toggle_button,
|
||||
},
|
||||
role: "switch",
|
||||
aria_checked: deaf || self_deaf,
|
||||
disabled: deaf,
|
||||
onclick: move |_| net.send(SetDeaf { deaf: !self_deaf }),
|
||||
match deaf || self_deaf {
|
||||
true => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "volume_off"}),
|
||||
false => rsx!(span { class: "material-symbols-outlined", style: "{button_style}", "volume_up"}),
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn ServerView() -> Element {
|
||||
let net: Coroutine<Command> = use_coroutine_handle();
|
||||
@@ -384,18 +647,18 @@ pub fn ServerView() -> Element {
|
||||
height: 100%;
|
||||
background-color: var(--bg-color);
|
||||
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr auto;
|
||||
grid-template-columns: 1fr 2fr;
|
||||
grid-template-areas:
|
||||
"bar bar"
|
||||
"tree chat";
|
||||
"tree chat"
|
||||
"control chat";
|
||||
|
||||
@media screen and (max-width: 720px) {
|
||||
grid-template-rows: auto 1fr 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-areas:
|
||||
"bar"
|
||||
"tree"
|
||||
"control"
|
||||
"chat";
|
||||
}
|
||||
"#
|
||||
@@ -423,60 +686,24 @@ pub fn ServerView() -> Element {
|
||||
"
|
||||
);
|
||||
|
||||
let top_bar = css!(
|
||||
let control_box = css!(
|
||||
"
|
||||
padding: 16px;
|
||||
grid-area: bar;
|
||||
background-color: var(--login-bg-color);
|
||||
margin: 16px;
|
||||
background-color: var(--light-bg-color);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
grid-area: control;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
|
||||
button {
|
||||
padding: 8px;
|
||||
|
||||
img {
|
||||
height: 1em;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
}
|
||||
gap: 10px;
|
||||
flex-direction: column;
|
||||
"
|
||||
);
|
||||
|
||||
rsx!(
|
||||
div {
|
||||
class: "{grid}",
|
||||
div {
|
||||
class: "{top_bar}",
|
||||
button {
|
||||
onclick: move |_| net.send(Disconnect),
|
||||
"Disconnect"
|
||||
}
|
||||
button {
|
||||
role: "switch",
|
||||
aria_checked: mute || self_mute,
|
||||
disabled: mute,
|
||||
onclick: move |_| net.send(SetMute { mute: !self_mute }),
|
||||
match mute || self_mute {
|
||||
true => rsx!(img { src: asset!("assets/mic-off-svgrepo-com.svg") }),
|
||||
false => rsx!(img { src: asset!("assets/mic-svgrepo-com.svg") }),
|
||||
}
|
||||
"\u{00A0}Mute"
|
||||
}
|
||||
button {
|
||||
role: "switch",
|
||||
aria_checked: deaf || self_deaf,
|
||||
disabled: deaf,
|
||||
onclick: move |_| net.send(SetDeaf { deaf: !self_deaf }),
|
||||
match deaf || self_deaf {
|
||||
true => rsx!(img { src: asset!("assets/speaker-muted-svgrepo-com.svg") }),
|
||||
false => rsx!(img { src: asset!("assets/speaker-medium-svgrepo-com.svg") }),
|
||||
}
|
||||
"\u{00A0}Deafen"
|
||||
}
|
||||
}
|
||||
div {
|
||||
class: "{channel_box}",
|
||||
for (id, state) in server.channels.iter() {
|
||||
@@ -489,6 +716,10 @@ pub fn ServerView() -> Element {
|
||||
class: "{chat_box}",
|
||||
ChatView {}
|
||||
}
|
||||
div {
|
||||
class: "{control_box}",
|
||||
ControlView {}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -613,8 +844,9 @@ pub fn app() -> Element {
|
||||
global_css!(
|
||||
"
|
||||
:root {
|
||||
--txt-color: white;
|
||||
--bg-color: #372f3a;
|
||||
--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;
|
||||
@@ -637,8 +869,10 @@ pub fn app() -> Element {
|
||||
overflow: auto;
|
||||
color: var(--txt-color);
|
||||
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
font-family: Nunito;
|
||||
font-size: 15pt;
|
||||
font-weight: 600;
|
||||
|
||||
}
|
||||
|
||||
button {
|
||||
@@ -675,6 +909,9 @@ pub fn app() -> Element {
|
||||
);
|
||||
|
||||
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=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" }
|
||||
|
||||
sir::AppStyle { }
|
||||
match *STATE.status.read() {
|
||||
Connected => rsx!(ServerView {}),
|
||||
|
||||
Reference in New Issue
Block a user