Skip to content

Commit

Permalink
File upload
Browse files Browse the repository at this point in the history
  • Loading branch information
nanoqsh committed Jun 8, 2022
1 parent 33b4e54 commit 6310cb0
Show file tree
Hide file tree
Showing 10 changed files with 235 additions and 47 deletions.
28 changes: 24 additions & 4 deletions base/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,23 @@ use std::fmt;

#[derive(BorrowDecode, Encode)]
pub enum ClientMessage<'a> {
SignUp { name: &'a str, pass: &'a str },
Login { name: &'a str, pass: &'a str },
Say { chan: u32, text: &'a str },
SignUp {
name: &'a str,
pass: &'a str,
},
Login {
name: &'a str,
pass: &'a str,
},
Say {
chan: u32,
text: &'a str,
},
File {
chan: u32,
ext: &'a str,
bytes: &'a [u8],
},
}

#[derive(Decode, Encode)]
Expand Down Expand Up @@ -40,11 +54,17 @@ pub struct Channel {
pub history: Vec<Message>,
}

#[derive(Clone, Decode, Encode)]
pub enum MessageType {
Text(String),
File(String),
}

#[derive(Clone, Decode, Encode)]
pub struct Message {
pub from: u32,
pub chan: u32,
pub text: String,
pub content: MessageType,
}

#[derive(Decode, Encode)]
Expand Down
5 changes: 3 additions & 2 deletions server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ edition = "2021"

[dependencies]
base = { path = "../base" }
websocket = { package = "tokio-tungstenite", version = "0.17" }
futures = "0.3"
clap = { version = "3.1", features = ["derive"] }
futures = "0.3"
rand = "0.8"
websocket = { package = "tokio-tungstenite", version = "0.17" }

[dependencies.tokio]
version = "1.18"
Expand Down
53 changes: 52 additions & 1 deletion server/src/manage.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::event::*;
use base::{api, decode, encode};
use rand::Rng;
use std::{
collections::{hash_map::Entry, HashMap},
net::SocketAddr,
Expand Down Expand Up @@ -167,7 +168,29 @@ pub async fn manage(mut receiver: Receiver<Event>) -> ! {
let message = Message {
from: id,
chan,
text: text.into(),
content: MessageType::Text(text.into()),
};

// Send this to all clients
for client in clients.values() {
let message = ServerMessage::Message(message.clone());
send(&client.sender, message).await;
}

history.push(message);
continue;
}
None => ServerMessage::Closed,
},
ClientMessage::File { chan, ext, bytes } => match client.logged {
Some(id) => {
let saved = save_file(ext, bytes);
println!("saved file {}", saved);

let message = Message {
from: id,
chan,
content: MessageType::File(saved),
};

// Send this to all clients
Expand Down Expand Up @@ -230,3 +253,31 @@ async fn send(sender: &Sender<Vec<u8>>, message: api::ServerMessage) {
encode(&message, &mut buf).expect("encode");
let _ = sender.send(buf).await;
}

fn save_file(ext: &str, bytes: &[u8]) -> String {
use std::{fs::File, io::Write, path::PathBuf};

let mut rng = rand::thread_rng();
let name = {
let mut name: String = (0..20)
.map(|_| match rng.gen_range(0..=2) {
0 => rng.gen_range('a'..='z'),
1 => rng.gen_range('A'..='Z'),
2 => rng.gen_range('0'..='9'),
_ => unreachable!(),
})
.collect();

name.push('.');
name.push_str(ext);
name
};

let mut path = PathBuf::from("./static/images");
path.push(&name);
let mut file = File::create(&path).expect("create file");
file.write_all(bytes).expect("write");
file.flush().expect("flush");

name
}
2 changes: 1 addition & 1 deletion web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ wasm-bindgen = "0.2"
wasm_futures = { package = "wasm-bindgen-futures", version = "0.4" }
wee_alloc = "0.4"
yew = "0.19"
futures = "0.3.21"
futures = "0.3"

[dependencies.web-sys]
version = "0.3"
Expand Down
9 changes: 7 additions & 2 deletions web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ pub fn main() -> Result<(), JsValue> {
Action::Send { chan, text } => {
write.request(ClientMessage::Say { chan, text: &text })
}
Action::File { chan, ext, bytes } => write.request(ClientMessage::File {
chan,
ext: &ext,
bytes: &bytes,
}),
}
}),
onlogin: Callback::from(move |(name, pass): (String, String)| {
Expand Down Expand Up @@ -108,7 +113,7 @@ pub fn main() -> Result<(), JsValue> {
message.chan,
Message {
from: message.from,
text: message.text.into(),
content: message.content.into(),
},
);
}
Expand All @@ -121,7 +126,7 @@ pub fn main() -> Result<(), JsValue> {
message.chan,
Message {
from: message.from,
text: message.text.into(),
content: message.content.into(),
},
);

Expand Down
27 changes: 23 additions & 4 deletions web/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
use base::api::MessageType;
use im::{HashMap, OrdMap, Vector};
use std::{fmt, rc::Rc};

#[derive(Clone, PartialEq)]
pub enum MessageContent {
Text(Rc<str>),
File(Rc<str>),
}

impl From<MessageType> for MessageContent {
fn from(message: MessageType) -> Self {
match message {
MessageType::Text(text) => MessageContent::Text(text.into()),
MessageType::File(file) => MessageContent::File(file.into()),
}
}
}

#[derive(Clone, PartialEq)]
pub struct Message {
pub from: u32,
pub text: Rc<str>,
pub content: MessageContent,
}

#[derive(Clone)]
Expand Down Expand Up @@ -34,7 +50,10 @@ impl Channel {
pub fn last_message(&self) -> LastMessage {
self.messages
.last()
.map(|message| message.text.as_ref())
.map(|message| match &message.content {
MessageContent::Text(text) => text.as_ref(),
MessageContent::File(_) => "..",
})
.unwrap_or_default()
.into()
}
Expand Down Expand Up @@ -119,7 +138,7 @@ impl State {
self.channels.values()
}

pub fn messages(&self, chan: u32) -> Vector<(u32, Vector<Rc<str>>)> {
pub fn messages(&self, chan: u32) -> Vector<(u32, Vector<MessageContent>)> {
use itertools::Itertools;

self.channels
Expand All @@ -132,7 +151,7 @@ impl State {
.map(|(from, messages)| {
(
from,
messages.map(|message| &message.text).cloned().collect(),
messages.map(|message| &message.content).cloned().collect(),
)
})
.collect()
Expand Down
17 changes: 15 additions & 2 deletions web/src/view/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ pub enum Event {
}

pub enum Action {
Send { chan: u32, text: Rc<str> },
Send {
chan: u32,
text: Rc<str>,
},
File {
chan: u32,
ext: String,
bytes: Vec<u8>,
},
}

#[derive(PartialEq, Properties)]
Expand Down Expand Up @@ -64,14 +72,19 @@ impl Component for App {
move |(chan, text)| onaction.emit(Action::Send { chan, text })
});

let onfile = Callback::from({
let onaction = ctx.props().onaction.clone();
move |(chan, ext, bytes)| onaction.emit(Action::File { chan, ext, bytes })
});

html! {
<ContextProvider<Data> { context }>
{
match login {
Some(_) => html! {
<div class="app">
<Channels { onselect } />
<Chat { onsend } />
<Chat { onsend } { onfile } />
</div>
},
None => html! {
Expand Down
Loading

0 comments on commit 6310cb0

Please sign in to comment.