Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dab00dce2f |
@@ -18,9 +18,9 @@ jobs:
|
|||||||
run: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
|
run: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
|
||||||
|
|
||||||
- name: Install dioxus-cli
|
- name: Install dioxus-cli
|
||||||
run: cargo binstall dioxus-cli --version 0.7.3
|
run: cargo binstall dioxus-cli --version 0.7.2
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
#- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
- name: Build dioxus project
|
- name: Build dioxus project
|
||||||
run: dx build --platform web --release -p mumble-web2-gui
|
run: dx build --platform web --release -p mumble-web2-gui
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ RUN yes | /opt/android-tools/cmdline-tools/latest/bin/sdkmanager --install "plat
|
|||||||
RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
|
RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
|
||||||
|
|
||||||
# Install dioxus-cli
|
# Install dioxus-cli
|
||||||
RUN cargo binstall dioxus-cli@0.7.3
|
RUN cargo binstall dioxus-cli@0.7.2
|
||||||
|
|
||||||
# Install bindgen-cli
|
# Install bindgen-cli
|
||||||
RUN cargo binstall bindgen-cli
|
RUN cargo binstall bindgen-cli
|
||||||
|
|||||||
@@ -44,12 +44,14 @@ RUN choco install rustup.install -y --no-progress
|
|||||||
RUN rustup toolchain install stable-x86_64-pc-windows-msvc
|
RUN rustup toolchain install stable-x86_64-pc-windows-msvc
|
||||||
RUN rustup default stable-x86_64-pc-windows-msvc
|
RUN rustup default stable-x86_64-pc-windows-msvc
|
||||||
|
|
||||||
# Install cargo binstall
|
# Install carog binstall
|
||||||
RUN Set-ExecutionPolicy Unrestricted -Scope Process; `
|
RUN Set-ExecutionPolicy Unrestricted -Scope Process; `
|
||||||
iex (Invoke-WebRequest "https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.ps1" -UseBasicParsing).Content
|
iex (Invoke-WebRequest "https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.ps1" -UseBasicParsing).Content
|
||||||
|
|
||||||
SHELL ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
|
SHELL ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
|
||||||
# Install dioxus-cli
|
# Install dioxus-cli from git HEAD with cargo
|
||||||
RUN cargo binstall dioxus-cli@0.7.3
|
# This is to work around a bug in the windows builder upstream.
|
||||||
|
# Dioxus has released 0.7.2, but it seems to be broken for now.
|
||||||
|
RUN cargo binstall dioxus-cli
|
||||||
|
|
||||||
ENTRYPOINT ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
|
ENTRYPOINT ["C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat", "&&", "powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
|
||||||
|
|||||||
+13
-118
@@ -4,7 +4,7 @@ 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 std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::imp;
|
use crate::imp;
|
||||||
|
|
||||||
@@ -54,6 +54,14 @@ pub enum Command {
|
|||||||
use Command::*;
|
use Command::*;
|
||||||
use ConnectionState::*;
|
use ConnectionState::*;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ChannelState {
|
||||||
|
pub name: String,
|
||||||
|
pub children: OrderSet<ChannelId>,
|
||||||
|
pub users: OrderSet<UserId>,
|
||||||
|
pub parent: Option<ChannelId>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct UserState {
|
pub struct UserState {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@@ -85,122 +93,9 @@ pub struct Chat {
|
|||||||
pub sender: Option<UserId>,
|
pub sender: Option<UserId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ChannelState {
|
|
||||||
pub name: String,
|
|
||||||
pub children: OrderSet<ChannelId>,
|
|
||||||
pub users: OrderSet<UserId>,
|
|
||||||
pub parent: Option<ChannelId>,
|
|
||||||
pub position: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ChannelState {
|
|
||||||
pub fn update_from_channel_state(
|
|
||||||
&mut self,
|
|
||||||
channel_state: &mumble_protocol::control::msgs::ChannelState,
|
|
||||||
) {
|
|
||||||
if channel_state.has_position() {
|
|
||||||
self.position = channel_state.get_position();
|
|
||||||
}
|
|
||||||
if channel_state.has_parent() {
|
|
||||||
self.parent = Some(channel_state.get_parent());
|
|
||||||
}
|
|
||||||
if channel_state.has_name() {
|
|
||||||
self.name = channel_state.get_name().to_string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct ChannelsState {
|
|
||||||
pub channels: HashMap<ChannelId, ChannelState>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ChannelsState {
|
|
||||||
pub fn update_from_channel_state(
|
|
||||||
&mut self,
|
|
||||||
channel_state: &mumble_protocol::control::msgs::ChannelState,
|
|
||||||
) {
|
|
||||||
self.channels
|
|
||||||
.entry(channel_state.get_channel_id())
|
|
||||||
.or_default()
|
|
||||||
.update_from_channel_state(channel_state);
|
|
||||||
|
|
||||||
self.update_channel_parents();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_from_channel_remove(
|
|
||||||
&mut self,
|
|
||||||
channel_remove: &mumble_protocol::control::msgs::ChannelRemove,
|
|
||||||
) {
|
|
||||||
self.channels.remove(&channel_remove.get_channel_id());
|
|
||||||
self.update_channel_parents();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_channel_parents(&mut self) {
|
|
||||||
// Zero out existing children
|
|
||||||
for state in self.channels.values_mut() {
|
|
||||||
state.children.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut to_sort: Vec<(ChannelId, Option<ChannelId>, i32, String)> = Vec::new();
|
|
||||||
for (id, state) in self.channels.iter() {
|
|
||||||
// Handle channels with no parent (the root channel)
|
|
||||||
let Some(parent_id) = state.parent else {
|
|
||||||
to_sort.push((*id, None, 0, state.name.clone()));
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
// If a channel has a parent that we haven't gotten a channel
|
|
||||||
// state packet for, ignore it
|
|
||||||
if !self.channels.contains_key(&parent_id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
to_sort.push((*id, Some(parent_id), state.position, state.name.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let pos_name: HashMap<ChannelId, (i32, String)> = self
|
|
||||||
.channels
|
|
||||||
.iter()
|
|
||||||
.map(|(&id, state)| (id, (state.position, state.name.clone())))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut updated: HashSet<ChannelId> = HashSet::new();
|
|
||||||
|
|
||||||
while updated.len() < to_sort.len() {
|
|
||||||
for &(id, ref parent_id, position, ref name) in &to_sort {
|
|
||||||
let Some(parent_id) = parent_id else {
|
|
||||||
updated.insert(id);
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
if updated.contains(&id) || !updated.contains(&parent_id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap should never fail here since we pre filter
|
|
||||||
let parent = self.channels.get_mut(&parent_id).unwrap();
|
|
||||||
|
|
||||||
let mut insert_index = parent.children.len();
|
|
||||||
for (i, &child) in parent.children.iter().enumerate() {
|
|
||||||
let (p, ref n) = pos_name[&child];
|
|
||||||
if (position == p && name < n) || p > position {
|
|
||||||
insert_index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parent.children.insert_before(insert_index, id);
|
|
||||||
updated.insert(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ServerState {
|
pub struct ServerState {
|
||||||
pub channels_state: ChannelsState,
|
pub channels: HashMap<ChannelId, ChannelState>,
|
||||||
pub users: HashMap<UserId, UserState>,
|
pub users: HashMap<UserId, UserState>,
|
||||||
pub chat: Vec<Chat>,
|
pub chat: Vec<Chat>,
|
||||||
pub session: Option<UserId>,
|
pub session: Option<UserId>,
|
||||||
@@ -287,7 +182,7 @@ pub fn Channel(id: ChannelId) -> Element {
|
|||||||
let net: Coroutine<Command> = use_coroutine_handle();
|
let net: Coroutine<Command> = use_coroutine_handle();
|
||||||
let server = STATE.server.read();
|
let server = STATE.server.read();
|
||||||
let user = server.session.unwrap();
|
let user = server.session.unwrap();
|
||||||
let Some(state) = server.channels_state.channels.get(&id) else {
|
let Some(state) = server.channels.get(&id) else {
|
||||||
return rsx!("missing channel {id}");
|
return rsx!("missing channel {id}");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -441,7 +336,7 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
|
|||||||
return rsx!();
|
return rsx!();
|
||||||
};
|
};
|
||||||
|
|
||||||
let current_channel_name = server.channels_state.channels[&channel].name.clone();
|
let current_channel_name = server.channels[&channel].name.clone();
|
||||||
|
|
||||||
let proxy_url = config
|
let proxy_url = config
|
||||||
.read_unchecked()
|
.read_unchecked()
|
||||||
@@ -633,7 +528,7 @@ pub fn ServerView(config: Resource<ClientConfig>) -> Element {
|
|||||||
class: "server_grid",
|
class: "server_grid",
|
||||||
div {
|
div {
|
||||||
class: "server_channel_box",
|
class: "server_channel_box",
|
||||||
for (id, state) in server.channels_state.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 }
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-5
@@ -335,11 +335,41 @@ fn accept_packet(
|
|||||||
}
|
}
|
||||||
ControlPacket::ChannelState(u) => {
|
ControlPacket::ChannelState(u) => {
|
||||||
let mut server = STATE.server.write();
|
let mut server = STATE.server.write();
|
||||||
server.channels_state.update_from_channel_state(&u);
|
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) => {
|
ControlPacket::ChannelRemove(u) => {
|
||||||
let mut server = STATE.server.write();
|
let mut server = STATE.server.write();
|
||||||
server.channels_state.update_from_channel_remove(&u);
|
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) => {
|
ControlPacket::UserState(u) => {
|
||||||
let mut server = STATE.server.write();
|
let mut server = STATE.server.write();
|
||||||
@@ -351,13 +381,12 @@ fn accept_packet(
|
|||||||
let state = state_entry.or_default();
|
let state = state_entry.or_default();
|
||||||
// the server might now send a channel_id if the user is in channel=0
|
// the server might now send a channel_id if the user is in channel=0
|
||||||
if u.has_channel_id() || new {
|
if u.has_channel_id() || new {
|
||||||
if let Some(parent) = server.channels_state.channels.get_mut(&state.channel) {
|
if let Some(parent) = server.channels.get_mut(&state.channel) {
|
||||||
parent.users.remove(&id);
|
parent.users.remove(&id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel_id = u.get_channel_id();
|
let channel_id = u.get_channel_id();
|
||||||
server
|
server
|
||||||
.channels_state
|
|
||||||
.channels
|
.channels
|
||||||
.entry(channel_id)
|
.entry(channel_id)
|
||||||
.or_default()
|
.or_default()
|
||||||
@@ -389,7 +418,7 @@ fn accept_packet(
|
|||||||
let mut server = STATE.server.write();
|
let mut server = STATE.server.write();
|
||||||
let id = u.get_session();
|
let id = u.get_session();
|
||||||
if let Some(state) = server.users.remove(&id) {
|
if let Some(state) = server.users.remove(&id) {
|
||||||
if let Some(parent) = server.channels_state.channels.get_mut(&state.channel) {
|
if let Some(parent) = server.channels.get_mut(&state.channel) {
|
||||||
parent.users.remove(&id);
|
parent.users.remove(&id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user