Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ crate-type = ["staticlib", "cdylib", "rlib"]

[profile.release]
lto = "fat"
codegen-units = 1
strip = true

[profile.dev]
debug = false
Expand Down
23 changes: 12 additions & 11 deletions src-tauri/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,21 @@ pub async fn join(
};

let login_clone = login.clone();
let id_clone = id.clone();

async_runtime::spawn(
async move {
if let Some(eventsub) = eventsub {
let ch_cond = json!({
"broadcaster_user_id": id_clone
"broadcaster_user_id": id
});

let ch_with_user_cond = json!({
"broadcaster_user_id": id_clone,
"broadcaster_user_id": id,
"user_id": token.user_id
});

let ch_with_mod_cond = json!({
"broadcaster_user_id": id_clone,
"broadcaster_user_id": id,
"moderator_user_id": token.user_id
});

Expand Down Expand Up @@ -136,7 +135,7 @@ pub async fn join(
let channel_cond = json!({
"ctx": "channel",
"platform": "TWITCH",
"id": id_clone
"id": id
});

seventv
Expand Down Expand Up @@ -219,15 +218,17 @@ pub async fn fetch_user_emotes(app_handle: AppHandle) {
async_runtime::spawn(
async move {
let state = app_handle.state::<Mutex<AppState>>();
let state = state.lock().await;

let Some(token) = state.token.as_ref() else {
return Ok::<_, Error>(());
let (helix, token) = {
let state = state.lock().await;
let Some(token) = state.token.clone() else {
return Ok::<_, Error>(());
};
(state.helix.clone(), token)
};

let emotes: Vec<_> = state
.helix
.get_user_emotes(&token.user_id, token)
let emotes: Vec<_> = helix
.get_user_emotes(&token.user_id, &token)
.try_collect()
.await?;

Expand Down
20 changes: 13 additions & 7 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,22 @@ pub fn get_cache_size(app_handle: AppHandle) -> i64 {
}

fn format_bytes(bytes: u64) -> String {
let i = ((bytes as f64).ln() / 1024_f64.ln()).floor();
const UNITS: [&str; 5] = ["bytes", "KB", "MB", "GB", "TB"];

if i == 0.0 {
"0 bytes".to_string()
} else {
let value = bytes as f64 / 1024_f64.powf(i);
let unit = ["bytes", "KB", "MB", "GB", "TB"][i as usize];
if bytes == 0 {
return "0 bytes".to_string();
}

let i = ((bytes as f64).log2() / 10.0).floor() as usize;
let i = i.min(UNITS.len() - 1);

format!("{value:.2} {unit}")
if i == 0 {
return format!("{bytes} bytes");
}

let value = bytes as f64 / (1u64 << (i * 10)) as f64;

format!("{value:.2} {}", UNITS[i])
}

#[tauri::command]
Expand Down
8 changes: 4 additions & 4 deletions src-tauri/src/eventsub/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ impl EventSubClient {
tracing::info!("Connected to EventSub");
self.set_connected(true);

let _ = self.clone().process_stream(stream).await;
let _ = Arc::clone(&self).process_stream(stream).await;

self.set_connected(false);
*self.session_id.lock().await = None;
Expand All @@ -201,7 +201,7 @@ impl EventSubClient {
stream.send(Message::Pong(data)).await?;
}
Message::Text(data) => {
if let Some(new_stream) = self.clone().handle_text(&data).await? {
if let Some(new_stream) = Arc::clone(&self).handle_text(&data).await? {
let frame = CloseFrame {
code: CloseCode::Normal,
reason: "Reconnecting".into(),
Expand All @@ -228,7 +228,7 @@ impl EventSubClient {
Some(Err(err)) => {
tracing::error!(%err, "EventSub connection error");

match self.clone().reconnect(TWITCH_EVENTSUB_WS_URI).await {
match Arc::clone(&self).reconnect(TWITCH_EVENTSUB_WS_URI).await {
Ok(new_stream) => {
stream = new_stream;
}
Expand All @@ -252,7 +252,7 @@ impl EventSubClient {

async fn handle_text(self: Arc<Self>, data: &str) -> Result<Option<Stream>, Error> {
if let Ok(msg) = serde_json::from_str(data)
&& let Some(url) = self.clone().handle_message(msg).await?
&& let Some(url) = Arc::clone(&self).handle_message(msg).await?
{
tracing::info!("Reconnecting to EventSub at {url}");
return Ok(Some(self.reconnect(&url).await?));
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/src/eventsub/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ pub async fn connect_eventsub(
let (mut incoming, client) = EventSubClient::new(helix, Arc::new(token));
let client = Arc::new(client);

guard.eventsub = Some(client.clone());
guard.eventsub = Some(Arc::clone(&client));
drop(guard);

async_runtime::spawn(async move {
if client.clone().connect().await.is_err() {
if Arc::clone(&client).connect().await.is_err() {
let state = app_handle.state::<Mutex<AppState>>();
let mut state = state.lock().await;

Expand Down
20 changes: 12 additions & 8 deletions src-tauri/src/irc/connection/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,11 +409,8 @@ impl ConnectionLoopStateMethods for ConnectionLoopOpenState {

match server_message {
Ok(server_message) => {
self.connection_incoming_tx
.send(ConnectionIncomingMessage::IncomingMessage(Box::new(
server_message.clone(),
)))
.ok();
let should_close =
matches!(&server_message, ServerMessage::Reconnect(_));

match &server_message {
ServerMessage::Ping(_) => {
Expand All @@ -422,11 +419,18 @@ impl ConnectionLoopStateMethods for ConnectionLoopOpenState {
ServerMessage::Pong(_) => {
self.pong_received = true;
}
ServerMessage::Reconnect(_) => {
return self.transition_to_closed(Error::ReconnectCmd);
}
_ => {}
}

self.connection_incoming_tx
.send(ConnectionIncomingMessage::IncomingMessage(Box::new(
server_message,
)))
.ok();

if should_close {
return self.transition_to_closed(Error::ReconnectCmd);
}
}
Err(parse_error) => {
self.connection_incoming_tx
Expand Down
14 changes: 6 additions & 8 deletions src-tauri/src/irc/message/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,7 @@ impl IrcMessageParseExt for IrcMessage {
return Ok(vec![]);
}

let chars: Vec<char> = message_text.chars().collect();
let mut emotes = Vec::new();

let make_error = || MalformedTagValue(self.to_owned(), tag_key, tag_value.to_owned());
Expand All @@ -1107,13 +1108,11 @@ impl IrcMessageParseExt for IrcMessage {
let start = usize::from_str(start).map_err(|_| make_error())?;
let end = usize::from_str(end).map_err(|_| make_error())? + 1;

let code_length = end - start;

let code = message_text
.chars()
.skip(start)
.take(code_length)
.collect::<String>();
let code: String = chars
.get(start..end)
.unwrap_or_default()
.iter()
.collect();
Comment on lines +1111 to +1115

emotes.push(Emote {
id: emote_id.to_owned(),
Expand Down Expand Up @@ -1142,7 +1141,6 @@ impl IrcMessageParseExt for IrcMessage {
}

fn try_get_badges(&self, tag_key: &'static str) -> Result<Vec<Badge>, ServerMessageParseError> {
// TODO same thing as above, could be optimized to not clone the tag value as well
let tag_value = self.try_get_tag_value(tag_key)?;

if tag_value.is_empty() {
Expand Down
5 changes: 2 additions & 3 deletions src-tauri/src/irc/message/tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,13 @@ impl IrcTags {
panic!("invalid input")
}

let mut tags = IrcTags::new();
let tag_count = source.as_bytes().iter().filter(|&&b| b == b';').count() + 1;
let mut tags = IrcTags(HashMap::with_capacity(tag_count));

for raw_tag in source.split(';') {
let mut tag_split = raw_tag.splitn(2, '=');

// always expected to be present, even splitting an empty string yields [""]
let key = tag_split.next().unwrap();
// can be missing if no = is present
let value = tag_split
.next()
.map_or_else(|| "".to_owned(), decode_tag_value);
Expand Down
5 changes: 4 additions & 1 deletion src-tauri/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ impl<'de> Deserialize<'de> for LogLevel {
"info" => Ok(LogLevel::Info),
"warn" => Ok(LogLevel::Warn),
"error" => Ok(LogLevel::Error),
_ => unreachable!(),
other => Err(serde::de::Error::unknown_variant(
other,
&["trace", "debug", "info", "warn", "error"],
)),
}
}
}
Expand Down
25 changes: 13 additions & 12 deletions src-tauri/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,18 +114,19 @@ async fn handle_connection(mut stream: TcpStream) -> Option<String> {
</html>"
);

stream
.write_all(
format!(
"HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{response}",
response.len()
)
.as_bytes(),
)
.await
.unwrap();

stream.flush().await.unwrap();
let header = format!(
"HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{response}",
response.len()
);

if let Err(err) = stream.write_all(header.as_bytes()).await {
tracing::error!(%err, "Failed to write response");
return None;
}

if let Err(err) = stream.flush().await {
tracing::error!(%err, "Failed to flush response");
}

None
}
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/src/seventv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ pub async fn connect_seventv(
let (mut incoming, client) = SeventTvClient::new();
let client = Arc::new(client);

state.seventv = Some(client.clone());
state.seventv = Some(Arc::clone(&client));
drop(state);

async_runtime::spawn(async move {
if client.clone().connect().await.is_err() {
if Arc::clone(&client).connect().await.is_err() {
let state = app_handle.state::<Mutex<AppState>>();
let mut state = state.lock().await;

Expand Down
Loading