simple channel & user tree
This commit is contained in:
Generated
+12
-2
@@ -1446,9 +1446,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.2.6"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@@ -1748,6 +1748,7 @@ dependencies = [
|
|||||||
"mumble-protocol-2x",
|
"mumble-protocol-2x",
|
||||||
"ogg",
|
"ogg",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"ordermap",
|
||||||
"serde-wasm-bindgen 0.6.5",
|
"serde-wasm-bindgen 0.6.5",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
@@ -1870,6 +1871,15 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordermap"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "31f2bd7b03bf2c767e1bb7b91505dbe022833776e60480275e6f2fb0db0c7503"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|||||||
@@ -23,3 +23,4 @@ async-std = "1.12.0"
|
|||||||
anyhow = "1.0.86"
|
anyhow = "1.0.86"
|
||||||
byteorder = "1.5.0"
|
byteorder = "1.5.0"
|
||||||
ogg = "0.9.1"
|
ogg = "0.9.1"
|
||||||
|
ordermap = "0.5.3"
|
||||||
|
|||||||
+70
@@ -1,19 +1,87 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use ordermap::OrderSet;
|
||||||
|
|
||||||
use super::Command;
|
use super::Command;
|
||||||
use super::Command::*;
|
use super::Command::*;
|
||||||
use super::ConnectionState::{self, *};
|
use super::ConnectionState::{self, *};
|
||||||
|
|
||||||
|
pub type ChannelId = u32;
|
||||||
|
pub type UserId = u32;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ChannelState {
|
||||||
|
pub name: String,
|
||||||
|
pub children: OrderSet<ChannelId>,
|
||||||
|
pub users: OrderSet<UserId>,
|
||||||
|
pub parent: Option<ChannelId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct UserState {
|
||||||
|
pub name: String,
|
||||||
|
pub channel: ChannelId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ServerState {
|
||||||
|
pub channels: HashMap<ChannelId, ChannelState>,
|
||||||
|
pub users: HashMap<UserId, UserState>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub status: GlobalSignal<ConnectionState>,
|
pub status: GlobalSignal<ConnectionState>,
|
||||||
|
pub server: GlobalSignal<ServerState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static STATE: State = State {
|
pub static STATE: State = State {
|
||||||
status: Signal::global(|| Disconnected),
|
status: Signal::global(|| Disconnected),
|
||||||
|
server: Signal::global(|| Default::default()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn User(id: UserId) -> Element {
|
||||||
|
let server = STATE.server.read();
|
||||||
|
let state = server.users.get(&id)?;
|
||||||
|
rsx!(
|
||||||
|
span {
|
||||||
|
style: "border: solid black 1px; border-radius: 4px;",
|
||||||
|
"{state.name}"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Channel(id: ChannelId) -> Element {
|
||||||
|
let server = STATE.server.read();
|
||||||
|
let state = server.channels.get(&id)?;
|
||||||
|
rsx!(
|
||||||
|
"{state.name}"
|
||||||
|
div {
|
||||||
|
style: "border-left: solid black 1px; padding-left: 8px;",
|
||||||
|
for child in state.children.iter() {
|
||||||
|
Channel { id: *child }
|
||||||
|
}
|
||||||
|
for id in state.users.iter() {
|
||||||
|
User { id: *id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn ServerView() -> Element {
|
||||||
|
let server = STATE.server.read();
|
||||||
|
rsx!(for (id, state) in server.channels.iter() {
|
||||||
|
if state.parent.is_none() {
|
||||||
|
Channel { id: *id }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn app() -> Element {
|
pub fn app() -> Element {
|
||||||
let net = use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
|
let net = use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
|
||||||
let mut username = use_signal(|| "".to_string());
|
let mut username = use_signal(|| "".to_string());
|
||||||
@@ -52,6 +120,8 @@ pub fn app() -> Element {
|
|||||||
onclick: move |event| net.send(Disconnect),
|
onclick: move |event| net.send(Disconnect),
|
||||||
"Disconnect"
|
"Disconnect"
|
||||||
}
|
}
|
||||||
|
br {}
|
||||||
|
ServerView {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
br {}
|
br {}
|
||||||
|
|||||||
+78
-3
@@ -1,5 +1,7 @@
|
|||||||
pub mod app;
|
pub mod app;
|
||||||
|
|
||||||
|
use app::ChannelState;
|
||||||
|
use app::UserState;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
@@ -28,7 +30,6 @@ use web_sys::window;
|
|||||||
use web_sys::AudioContext;
|
use web_sys::AudioContext;
|
||||||
use web_sys::AudioContextOptions;
|
use web_sys::AudioContextOptions;
|
||||||
use web_sys::AudioData;
|
use web_sys::AudioData;
|
||||||
use web_sys::AudioDataInit;
|
|
||||||
use web_sys::AudioDecoder;
|
use web_sys::AudioDecoder;
|
||||||
use web_sys::AudioDecoderConfig;
|
use web_sys::AudioDecoderConfig;
|
||||||
use web_sys::AudioDecoderInit;
|
use web_sys::AudioDecoderInit;
|
||||||
@@ -368,6 +369,7 @@ pub async fn network_entrypoint(mut event_rx: UnboundedReceiver<Command>) {
|
|||||||
panic!("Did not receive connect command")
|
panic!("Did not receive connect command")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
*STATE.server.write() = Default::default();
|
||||||
*STATE.status.write() = ConnectionState::Connecting;
|
*STATE.status.write() = ConnectionState::Connecting;
|
||||||
|
|
||||||
console::log_1(&"Rust via WASM!".into());
|
console::log_1(&"Rust via WASM!".into());
|
||||||
@@ -540,6 +542,9 @@ fn accept_packet(
|
|||||||
audio_context: &AudioContext,
|
audio_context: &AudioContext,
|
||||||
decoder_map: &mut HashMap<u32, AudioDecoder>,
|
decoder_map: &mut HashMap<u32, AudioDecoder>,
|
||||||
) {
|
) {
|
||||||
|
if !matches!(msg, ControlPacket::UDPTunnel(_)) {
|
||||||
|
console::log_1(&format!("{:#?}", msg).into());
|
||||||
|
}
|
||||||
match msg {
|
match msg {
|
||||||
ControlPacket::UDPTunnel(u) => {
|
ControlPacket::UDPTunnel(u) => {
|
||||||
match *u.clone() {
|
match *u.clone() {
|
||||||
@@ -579,8 +584,78 @@ fn accept_packet(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
ControlPacket::ChannelState(u) => {
|
||||||
console::log_1(&format!("{:#?}", msg).into());
|
let mut server = STATE.server.write();
|
||||||
|
let id = u.get_channel_id();
|
||||||
|
|
||||||
|
let state = server.channels.entry(id).or_default();
|
||||||
|
let new_parent = if u.has_parent() {
|
||||||
|
if let Some(parent) = state.parent.and_then(|p| server.channels.get_mut(&p)) {
|
||||||
|
parent.children.remove(&id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent_id = u.get_parent();
|
||||||
|
let parent = server.channels.entry(parent_id).or_default();
|
||||||
|
if u.has_position() && u.get_position() as usize <= parent.children.len() {
|
||||||
|
// TODO: what if positions are received out of order? we need to sort afterwards?
|
||||||
|
parent.children.insert_before(u.get_position() as usize, id);
|
||||||
|
} else {
|
||||||
|
parent.children.insert(id);
|
||||||
|
}
|
||||||
|
Some(parent_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let state = server.channels.entry(id).or_default();
|
||||||
|
state.parent = new_parent;
|
||||||
|
if u.has_name() {
|
||||||
|
state.name = u.get_name().to_string();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ControlPacket::ChannelRemove(u) => {
|
||||||
|
let mut server = STATE.server.write();
|
||||||
|
let id = u.get_channel_id();
|
||||||
|
if let Some(channel) = server.channels.remove(&id) {
|
||||||
|
if let Some(parent) = channel.parent.and_then(|p| server.channels.get_mut(&p)) {
|
||||||
|
parent.children.remove(&id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ControlPacket::UserState(u) => {
|
||||||
|
let mut server = STATE.server.write();
|
||||||
|
let server = &mut *server;
|
||||||
|
let id = u.get_session();
|
||||||
|
|
||||||
|
let state = server.users.entry(id).or_default();
|
||||||
|
if u.has_channel_id() {
|
||||||
|
if let Some(parent) = server.channels.get_mut(&state.channel) {
|
||||||
|
parent.users.remove(&id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let channel_id = u.get_channel_id();
|
||||||
|
server
|
||||||
|
.channels
|
||||||
|
.entry(channel_id)
|
||||||
|
.or_default()
|
||||||
|
.users
|
||||||
|
.insert(id);
|
||||||
|
state.channel = channel_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.has_name() {
|
||||||
|
state.name = u.get_name().to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ControlPacket::UserRemove(u) => {
|
||||||
|
let mut server = STATE.server.write();
|
||||||
|
let id = u.get_session();
|
||||||
|
if let Some(state) = server.users.remove(&id) {
|
||||||
|
if let Some(parent) = server.channels.get_mut(&state.channel) {
|
||||||
|
parent.users.remove(&id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user