Skip to content
Open
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
28 changes: 16 additions & 12 deletions src/avatars.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::{cmp, fs};
use std::fs::{DirEntry};
use crate::storage::custom_avatars_path;
use crate::{write_native_event, AppContext, NativeResponseEvent};
use base64::STANDARD_NO_PAD;
use indexmap::IndexMap;
use std::fs::DirEntry;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::time::SystemTime;
use base64::STANDARD_NO_PAD;
use indexmap::IndexMap;
use std::{cmp, fs};
use ulid::Ulid;
use crate::{AppContext, NativeResponseEvent, write_native_event};
use crate::storage::custom_avatars_path;

pub fn build_avatar_path(custom_avatars_path: &Path, ulid: Ulid, ext: &str) -> PathBuf {
let filename = ulid.to_string() + "." + ext;
Expand All @@ -17,15 +17,19 @@ pub fn build_avatar_path(custom_avatars_path: &Path, ulid: Ulid, ext: &str) -> P
pub fn list_avatars(custom_avatars_path: &Path) -> IndexMap<Ulid, PathBuf> {
if let Ok(r) = fs::read_dir(custom_avatars_path) {
// Sort by creation time descending
let mut dir_entries: Vec<(DirEntry, SystemTime)> = r.filter_map(|f| f.ok())
let mut dir_entries: Vec<(DirEntry, SystemTime)> = r
.filter_map(|f| f.ok())
.map(|e| {
let t = e.metadata()
let t = e
.metadata()
.and_then(|m| m.created())
.unwrap_or(SystemTime::UNIX_EPOCH);
(e, t)
})
.collect();

dir_entries.sort_by_key(|p| cmp::Reverse(p.1));

return dir_entries
.iter()
.filter_map(|f| {
Expand All @@ -35,10 +39,10 @@ pub fn list_avatars(custom_avatars_path: &Path) -> IndexMap<Ulid, PathBuf> {
.and_then(|f| Ulid::from_str(f).ok())
.map(|ulid| (ulid, path))
})
.collect()
.collect();
}

return IndexMap::new()
IndexMap::new()
}

pub fn update_and_native_notify_avatars(context: &AppContext) {
Expand All @@ -50,11 +54,11 @@ pub fn update_and_native_notify_avatars(context: &AppContext) {
*context.avatars.write().unwrap() = avatars;

write_native_event(NativeResponseEvent::AvatarsUpdated {
avatars: avatars_as_ulids
avatars: avatars_as_ulids,
});
}

const AVATAR_ENCODING: base64::Config = STANDARD_NO_PAD;
pub fn encode_avatar_to_string(avatar: Vec<u8>) -> String {
base64::encode_config(avatar, AVATAR_ENCODING)
}
}
46 changes: 26 additions & 20 deletions src/cmd/add_avatars.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
use std::fs;
use ulid::Ulid;
use crate::{AppContext, NativeResponse};
use crate::avatars::build_avatar_path;
use crate::ipc::notify_update_avatars;
use crate::native_resp::NativeResponseData::AvatarsUpdated;
use crate::profiles::ProfilesIniState;
use crate::storage::{custom_avatars_path};
use crate::storage::custom_avatars_path;
use crate::{AppContext, NativeResponse};
use std::fs;
use ulid::Ulid;

pub fn process_add_avatars(context: &AppContext, profiles: &ProfilesIniState) -> NativeResponse {
// Pick avatar
let result = match context.windowing.open_avatar_picker() {
Some(r) => r,
None => Vec::new()
};
let res = context.windowing.open_avatar_picker().unwrap_or_default();

// Load and create avatars dir
let avatars_dir = custom_avatars_path(context);
Expand All @@ -21,35 +18,44 @@ pub fn process_add_avatars(context: &AppContext, profiles: &ProfilesIniState) ->
}

// Verify avatars are the correct size
for path in &result {
for path in &res {
let metadata = match path.metadata() {
Ok(m) => m,
Err(e) => return NativeResponse::error_with_dbg_msg(format!("Could not load information on avatar: {}", path.display()), e)
Err(e) => {
return NativeResponse::error_with_dbg_msg(
format!("Could not load information on avatar: {}", path.display()),
e,
)
}
};

// 500 KB
if metadata.len() > 500000 {
return NativeResponse::error(format!("Avatar {} is too large, max size is 500 KB", path.display()));
return NativeResponse::error(format!(
"Avatar {} is too large, max size is 500 KB",
path.display()
));
}
}

// Save all the avatars
for path in result {
for path in res {
let extension = match path.extension().and_then(|x| x.to_str()) {
Some(e) => e,
None => return NativeResponse::error(&format!("Invalid avatar: {}", path.display()))
None => return NativeResponse::error(&format!("Invalid avatar: {}", path.display())),
};
let target_path = build_avatar_path(
&avatars_dir,
Ulid::new(),
&extension.to_lowercase(),
);

let target_path = build_avatar_path(&avatars_dir, Ulid::new(), &extension.to_lowercase());
if let Err(e) = fs::copy(&path, target_path) {
return NativeResponse::error(&format!("Failed to save avatar: {}. Error: {:?}", path.display(), e))
return NativeResponse::error(&format!(
"Failed to save avatar: {}. Error: {:?}",
path.display(),
e
));
}
}

notify_update_avatars(context, profiles);

NativeResponse::success(AvatarsUpdated)
}
}
14 changes: 8 additions & 6 deletions src/cmd/close_manager.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::AppContext;
use crate::profiles::ProfilesIniState;
use crate::native_resp::{NativeResponse, NativeResponseData};
use crate::ipc::notify_close_manager;
use crate::native_resp::{NativeResponse, NativeResponseData};
use crate::profiles::ProfilesIniState;
use crate::AppContext;

pub fn process_cmd_close_manager(context: &AppContext, profiles: &ProfilesIniState) -> NativeResponse {
pub fn process_cmd_close_manager(
context: &AppContext,
profiles: &ProfilesIniState,
) -> NativeResponse {
notify_close_manager(context, profiles);

return NativeResponse::success(NativeResponseData::ManagerClosed)
NativeResponse::success(NativeResponseData::ManagerClosed)
}

Loading