This commit is contained in:
Michael Zhang 2023-08-10 18:25:47 -05:00
parent f1f4df2902
commit 52a292a4d5
6 changed files with 149 additions and 21 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
/target /target
/node_modules /node_modules
/dist

83
Cargo.lock generated
View file

@ -510,7 +510,9 @@ dependencies = [
"derivative", "derivative",
"flume", "flume",
"futures", "futures",
"mime_guess",
"mzlib", "mzlib",
"rust-embed",
"serde", "serde",
"serde_bytes", "serde_bytes",
"serde_json", "serde_json",
@ -744,6 +746,16 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.1" version = "0.7.1"
@ -940,6 +952,40 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "rust-embed"
version = "6.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
"walkdir",
]
[[package]]
name = "rust-embed-impl"
version = "6.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn 2.0.28",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
version = "7.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74"
dependencies = [
"sha2",
"walkdir",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.23" version = "0.1.23"
@ -958,6 +1004,15 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@ -1332,6 +1387,15 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "unicase"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.13" version = "0.3.13"
@ -1386,6 +1450,16 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
dependencies = [
"same-file",
"winapi-util",
]
[[package]] [[package]]
name = "want" name = "want"
version = "0.3.1" version = "0.3.1"
@ -1477,6 +1551,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"

View file

@ -13,6 +13,8 @@ dashmap = "5.5.0"
derivative = "2.2.0" derivative = "2.2.0"
flume = "0.10.14" flume = "0.10.14"
futures = "0.3.28" futures = "0.3.28"
mime_guess = "2.0.4"
rust-embed = "6.8.1"
serde = { version = "1.0.183", features = ["derive"] } serde = { version = "1.0.183", features = ["derive"] }
serde_bytes = "0.11.12" serde_bytes = "0.11.12"
serde_json = "1.0.104" serde_json = "1.0.104"

View file

@ -1,6 +1,7 @@
{ {
"scripts": { "scripts": {
"dev": "vite" "dev": "vite",
"build": "vite build"
}, },
"devDependencies": { "devDependencies": {
"@types/libsodium-wrappers": "^0.7.10", "@types/libsodium-wrappers": "^0.7.10",

View file

@ -7,7 +7,7 @@ use std::{io::Cursor, mem, sync::Arc};
use automerge::{ use automerge::{
sync::{State as SyncState, SyncDoc}, sync::{State as SyncState, SyncDoc},
Automerge, Value, Automerge,
}; };
use axum::{ use axum::{
extract::{ extract::{
@ -18,9 +18,10 @@ use axum::{
routing::get, routing::get,
Router, Router,
}; };
use chrono::{DateTime, Utc}; use chrono::Utc;
use dashmap::{DashMap, DashSet}; use dashmap::{DashMap, DashSet};
use flume::r#async::SendSink; use flume::r#async::SendSink;
use frontend::frontend;
use futures::{stream, FutureExt, SinkExt, StreamExt}; use futures::{stream, FutureExt, SinkExt, StreamExt};
use message::Message; use message::Message;
use mzlib::axum_error::Result; use mzlib::axum_error::Result;
@ -61,7 +62,10 @@ impl Room {
async fn main() -> Result<()> { async fn main() -> Result<()> {
let state = AppState::default(); let state = AppState::default();
let app = Router::new().route("/ws", get(handler)).with_state(state); let app = Router::new()
.route("/ws", get(handler))
.fallback(frontend)
.with_state(state);
axum::Server::bind(&"0.0.0.0:3100".parse().unwrap()) axum::Server::bind(&"0.0.0.0:3100".parse().unwrap())
.serve(app.into_make_service()) .serve(app.into_make_service())
@ -70,6 +74,45 @@ async fn main() -> Result<()> {
Ok(()) Ok(())
} }
#[allow(non_upper_case_globals)]
mod frontend {
use axum::{
body::{Body, HttpBody},
http::{header::CONTENT_TYPE, HeaderMap, HeaderValue, StatusCode, Uri},
response::IntoResponse,
};
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "dist/"]
struct Frontend;
pub async fn frontend(uri: Uri) -> impl IntoResponse {
let path = uri.path().trim_start_matches("/").to_owned();
match Frontend::get(&path).or_else(|| Frontend::get("index.html")) {
Some(file) => {
let guess = mime_guess::from_path(path);
let mut headers = HeaderMap::default();
if let Some(guess) = guess.first() {
headers.append(
CONTENT_TYPE,
HeaderValue::from_str(&guess.to_string()).unwrap(),
);
}
let data = file.data.as_ref();
let body = Body::from(data.to_owned());
let body = body.boxed();
(headers, body).into_response()
}
None => {
(StatusCode::NOT_FOUND, format!("No route for {}", uri)).into_response()
}
}
}
}
async fn handler( async fn handler(
ws: WebSocketUpgrade, ws: WebSocketUpgrade,
State(state): State<AppState>, State(state): State<AppState>,
@ -78,7 +121,7 @@ async fn handler(
} }
async fn handle_socket(state: AppState, socket: WebSocket) -> Result<()> { async fn handle_socket(state: AppState, socket: WebSocket) -> Result<()> {
let (mut socket_tx, socket_rx) = socket.split(); let (socket_tx, socket_rx) = socket.split();
// Generate an ID for this connection // Generate an ID for this connection
let client_id = Uuid::new_v4(); let client_id = Uuid::new_v4();
@ -148,7 +191,7 @@ async fn handle_socket(state: AppState, socket: WebSocket) -> Result<()> {
// println!("inner doc: {:?}", room.document); // println!("inner doc: {:?}", room.document);
// Remove current client, so send to everyone else // Remove current client, so send to everyone else
let mut connected_clients = room.connected_clients.clone(); let connected_clients = room.connected_clients.clone();
connected_clients.remove(client_id); connected_clients.remove(client_id);
// Send to everyone else // Send to everyone else
@ -183,11 +226,11 @@ async fn handle_socket(state: AppState, socket: WebSocket) -> Result<()> {
} }
Message::ChatMessage { Message::ChatMessage {
timestamp, timestamp: _,
message_id, message_id: _,
room_id, room_id,
author, author: _,
content, content: _,
} => { } => {
let room = state let room = state
.rooms .rooms
@ -217,17 +260,15 @@ async fn handle_socket(state: AppState, socket: WebSocket) -> Result<()> {
connected_clients.remove(&client_id); connected_clients.remove(&client_id);
match &message { match &message {
Message::FileUploadBegin { header, .. } => { Message::FileUploadBegin { .. } => match room.current_uploader {
match room.current_uploader { Some(v) if v == client_id => {}
Some(v) if v == client_id => {} Some(_v) => continue,
Some(v) => continue, None => room.current_uploader = Some(client_id.clone()),
None => room.current_uploader = Some(client_id.clone()), },
}
}
Message::FileUploadComplete { .. } => { Message::FileUploadComplete { .. } => {
room.current_uploader = None; room.current_uploader = None;
} }
Message::FileUploadChunk { data, .. } => {} Message::FileUploadChunk { .. } => {}
_ => {} _ => {}
}; };

View file

@ -1,10 +1,10 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::fmt::{write, Formatter}; use std::fmt::{Formatter};
use std::io::Cursor; use std::io::Cursor;
use axum::extract::ws; use axum::extract::ws;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use ciborium::Value;
use mzlib::axum_error::Result; use mzlib::axum_error::Result;
use serde::de::Visitor; use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};