full-screen app css
This commit is contained in:
+170
-52
@@ -1,10 +1,9 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use ordermap::OrderSet;
|
use ordermap::OrderSet;
|
||||||
use sir::{css, global_css};
|
use sir::{css, global_css};
|
||||||
|
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||||
|
|
||||||
pub type ChannelId = u32;
|
pub type ChannelId = u32;
|
||||||
pub type UserId = u32;
|
pub type UserId = u32;
|
||||||
@@ -13,6 +12,7 @@ pub enum ConnectionState {
|
|||||||
Disconnected,
|
Disconnected,
|
||||||
Connecting,
|
Connecting,
|
||||||
Connected,
|
Connected,
|
||||||
|
Failed(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -150,12 +150,13 @@ 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_history_box = css!(
|
let chat_history = css!(
|
||||||
"
|
"
|
||||||
margin: 16px;
|
overflow-y: auto;
|
||||||
border: solid black 1px;
|
flex: 1 0 0;
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
let chat_message = css!(
|
let chat_message = css!(
|
||||||
"
|
"
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -165,12 +166,14 @@ pub fn ChatView() -> Element {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
let chat_box = css!(
|
let chat_box = css!(
|
||||||
"
|
"
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
margin: 16px;
|
padding: 16px;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
border-top: solid black 1px;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@@ -190,7 +193,7 @@ pub fn ChatView() -> Element {
|
|||||||
|
|
||||||
rsx!(
|
rsx!(
|
||||||
div {
|
div {
|
||||||
class: "{chat_history_box}",
|
class: "{chat_history}",
|
||||||
for chat in server.chat.iter() {
|
for chat in server.chat.iter() {
|
||||||
div {
|
div {
|
||||||
class: "{chat_message}",
|
class: "{chat_message}",
|
||||||
@@ -202,22 +205,22 @@ pub fn ChatView() -> Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div {
|
}
|
||||||
class: "{chat_box}",
|
div {
|
||||||
input {
|
class: "{chat_box}",
|
||||||
placeholder: "say something",
|
input {
|
||||||
value: "{draft.read()}",
|
placeholder: "say something",
|
||||||
oninput: move |evt| draft.set(evt.value().clone()),
|
value: "{draft.read()}",
|
||||||
onkeypress: move |evt: Event<KeyboardData>| {
|
oninput: move |evt| draft.set(evt.value().clone()),
|
||||||
if evt.code() == Code::Enter && evt.modifiers().is_empty() {
|
onkeypress: move |evt: Event<KeyboardData>| {
|
||||||
do_send();
|
if evt.code() == Code::Enter && evt.modifiers().is_empty() {
|
||||||
}
|
do_send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
button {
|
}
|
||||||
onclick: move |_| do_send(),
|
button {
|
||||||
"Send"
|
onclick: move |_| do_send(),
|
||||||
}
|
"Send"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -225,73 +228,188 @@ pub fn ChatView() -> Element {
|
|||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ServerView() -> Element {
|
pub fn ServerView() -> Element {
|
||||||
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
let server = STATE.server.read();
|
let server = STATE.server.read();
|
||||||
|
|
||||||
|
let grid = css!(
|
||||||
|
"
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
height: 100%;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
gap: 4px;
|
||||||
|
padding: 4px;
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
let channel_box = css!(
|
let channel_box = css!(
|
||||||
"
|
"
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin: 16px;
|
|
||||||
border: solid black 1px;
|
border: solid black 1px;
|
||||||
|
grid-row: 2;
|
||||||
|
overflow: auto;
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
let chat_box = css!(
|
||||||
|
"
|
||||||
|
border: solid black 1px;
|
||||||
|
grid-row: 2;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
let top_bar = css!(
|
||||||
|
"
|
||||||
|
padding: 16px;
|
||||||
|
border: solid black 1px;
|
||||||
|
grid-row: 1;
|
||||||
|
grid-column: span 2;
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
rsx!(
|
rsx!(
|
||||||
div {
|
div {
|
||||||
class: "framed_box {channel_box}",
|
class: "{grid}",
|
||||||
for (id, state) in server.channels.iter() {
|
div {
|
||||||
if state.parent.is_none() {
|
class: "{top_bar}",
|
||||||
Channel { id: *id }
|
button {
|
||||||
|
onclick: move |_| net.send(Disconnect),
|
||||||
|
"Disconnect"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
class: "{channel_box}",
|
||||||
|
for (id, state) in server.channels.iter() {
|
||||||
|
if state.parent.is_none() {
|
||||||
|
Channel { id: *id }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
div {
|
||||||
|
class: "{chat_box}",
|
||||||
|
ChatView {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ChatView {}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn app() -> Element {
|
#[component]
|
||||||
let net = use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
|
pub fn LoginView() -> Element {
|
||||||
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
let mut username = use_signal(|| "".to_string());
|
let mut username = use_signal(|| "".to_string());
|
||||||
let default_address = option_env!("MUMBLEWEB2_WEBTRANSPORT_SERVER_ADDRESS").unwrap_or("");
|
let default_address = option_env!("MUMBLEWEB2_WEBTRANSPORT_SERVER_ADDRESS").unwrap_or("");
|
||||||
let mut address = use_signal(|| default_address.to_string());
|
let mut address = use_signal(|| default_address.to_string());
|
||||||
|
|
||||||
|
let error = css!(
|
||||||
|
"
|
||||||
|
color: red;
|
||||||
|
pre {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
let login_box = css!(
|
||||||
|
"
|
||||||
|
max-width: 50vw;
|
||||||
|
min-width: 640px;
|
||||||
|
align-self: center;
|
||||||
|
padding: 16px;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
input,button {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
let do_connect = move |_| {
|
||||||
|
net.send(Connect{address: address.read().clone(), username: username.read().clone(), hash: "[39, 96, 204, 127, 26, 59, 35, 209, 197, 103, 192, 6, 3, 98, 203, 228, 124, 46, 247, 72, 44, 224, 123, 238, 218, 140, 128, 100, 115, 14, 23, 233]".to_string()})
|
||||||
|
};
|
||||||
let status = &STATE.status;
|
let status = &STATE.status;
|
||||||
|
let bottom = match &*status.read() {
|
||||||
|
Disconnected => rsx! {
|
||||||
|
button {
|
||||||
|
onclick: do_connect.clone(),
|
||||||
|
"Connect!"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Connecting => rsx! {
|
||||||
|
"Connecting..."
|
||||||
|
},
|
||||||
|
Failed(msg) => rsx!(
|
||||||
|
button {
|
||||||
|
onclick: do_connect.clone(),
|
||||||
|
"Reconnect!"
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
class: "{error}",
|
||||||
|
"Failed to connect:"
|
||||||
|
pre {
|
||||||
|
"{msg}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Connected => unreachable!(),
|
||||||
|
};
|
||||||
rsx!(
|
rsx!(
|
||||||
sir::AppStyle { }
|
|
||||||
div {
|
div {
|
||||||
|
class: "{login_box}",
|
||||||
input {
|
input {
|
||||||
placeholder: "username",
|
placeholder: "username",
|
||||||
value: "{username.read()}",
|
value: "{username.read()}",
|
||||||
autofocus: "true",
|
autofocus: "true",
|
||||||
oninput: move |evt| username.set(evt.value().clone()),
|
oninput: move |evt| username.set(evt.value().clone()),
|
||||||
}
|
}
|
||||||
br {}
|
|
||||||
input {
|
input {
|
||||||
placeholder: "server address",
|
placeholder: "server address",
|
||||||
value: "{address.read()}",
|
value: "{address.read()}",
|
||||||
autofocus: "true",
|
autofocus: "true",
|
||||||
oninput: move |evt| address.set(evt.value().clone()),
|
oninput: move |evt| address.set(evt.value().clone()),
|
||||||
}
|
}
|
||||||
br {}
|
{bottom}
|
||||||
match *status.read() {
|
}
|
||||||
Disconnected => rsx!{
|
)
|
||||||
button {
|
}
|
||||||
onclick: move |event| net.send(Connect{address: address.read().clone(), username: username.read().clone(), hash: "[39, 96, 204, 127, 26, 59, 35, 209, 197, 103, 192, 6, 3, 98, 203, 228, 124, 46, 247, 72, 44, 224, 123, 238, 218, 140, 128, 100, 115, 14, 23, 233]".to_string()}),
|
|
||||||
"Connect!"
|
pub fn app() -> Element {
|
||||||
}
|
use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
|
||||||
},
|
|
||||||
Connecting => rsx!{
|
global_css!(
|
||||||
"Connecting..."
|
"
|
||||||
},
|
body {
|
||||||
Connected => rsx!{
|
margin: 0;
|
||||||
button {
|
}
|
||||||
onclick: move |event| net.send(Disconnect),
|
|
||||||
"Disconnect"
|
#main {
|
||||||
}
|
height: 100vh;
|
||||||
br {}
|
display: flex;
|
||||||
ServerView {}
|
flex-direction: column;
|
||||||
}
|
justify-content: space-around;
|
||||||
}
|
background-color: grey;
|
||||||
br {}
|
overflow: auto;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
rsx!(
|
||||||
|
sir::AppStyle { }
|
||||||
|
match *STATE.status.read() {
|
||||||
|
Connected => rsx!(ServerView {}),
|
||||||
|
_ => rsx!(LoginView {}),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -354,6 +354,7 @@ pub async fn network_entrypoint(mut event_rx: UnboundedReceiver<Command>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Err(error) = network_connect(address, username, &mut event_rx).await {
|
if let Err(error) = network_connect(address, username, &mut event_rx).await {
|
||||||
|
*STATE.status.write() = ConnectionState::Failed(format!("{error:?}"));
|
||||||
console::error_1(&error);
|
console::error_1(&error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user