feat: store user data in correct dir, or according to config
This commit is contained in:
parent
18e907386d
commit
d0e1226559
|
@ -842,7 +842,7 @@ checksum = "2a76fa97167fa740dcdbfe18e8895601e1bc36525f09b044e00916e717c03a3c"
|
|||
dependencies = [
|
||||
"dconf_rs",
|
||||
"detect-desktop-environment",
|
||||
"dirs",
|
||||
"dirs 4.0.0",
|
||||
"objc",
|
||||
"rust-ini",
|
||||
"web-sys",
|
||||
|
@ -933,6 +933,15 @@ dependencies = [
|
|||
"dirs-sys 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
|
||||
dependencies = [
|
||||
"dirs-sys 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.7"
|
||||
|
@ -940,7 +949,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"redox_users 0.4.6",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -952,10 +961,22 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"redox_users 0.4.6",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users 0.5.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
|
@ -2334,6 +2355,7 @@ name = "macaw"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"confy",
|
||||
"dirs 6.0.0",
|
||||
"iced",
|
||||
"indexmap",
|
||||
"jid",
|
||||
|
@ -3458,6 +3480,17 @@ dependencies = [
|
|||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
"libredox",
|
||||
"thiserror 2.0.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "renderdoc-sys"
|
||||
version = "1.1.0"
|
||||
|
|
|
@ -18,3 +18,4 @@ indexmap = "2.7.1"
|
|||
serde = { version = "1.0.218", features = ["derive"] }
|
||||
thiserror = "2.0.11"
|
||||
toml = "0.8"
|
||||
dirs = "6.0.0"
|
||||
|
|
|
@ -34,16 +34,16 @@ pub enum Message {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Error {
|
||||
InvalidJID(String),
|
||||
DatabaseConnection,
|
||||
InvalidJID,
|
||||
}
|
||||
|
||||
pub enum Action {
|
||||
None,
|
||||
ClientCreated(Task<crate::Message>),
|
||||
CreateClient(String, String, bool),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct Creds {
|
||||
pub jid: String,
|
||||
pub password: String,
|
||||
|
@ -69,85 +69,7 @@ impl LoginModal {
|
|||
let jid_str = self.jid.clone();
|
||||
let password = self.password.clone();
|
||||
let remember_me = self.remember_me.clone();
|
||||
Action::ClientCreated(
|
||||
Task::future(async move {
|
||||
let jid: Result<JID, _> = jid_str.parse();
|
||||
match jid {
|
||||
Ok(j) => {
|
||||
let result =
|
||||
LuzHandle::new(j.clone(), password.to_string(), "macaw.db")
|
||||
.await;
|
||||
match result {
|
||||
Ok((luz_handle, receiver)) => {
|
||||
let mut tasks = Vec::new();
|
||||
tasks.push(Task::done(crate::Message::ClientCreated(
|
||||
Client {
|
||||
client: luz_handle,
|
||||
jid: j,
|
||||
connection_status: Presence::Offline(
|
||||
Offline::default(),
|
||||
),
|
||||
},
|
||||
)));
|
||||
let stream = ReceiverStream::new(receiver);
|
||||
let stream =
|
||||
stream.map(|message| crate::Message::Luz(message));
|
||||
tasks.push(Task::stream(stream));
|
||||
|
||||
if remember_me {
|
||||
let entry = Entry::new("macaw", "macaw");
|
||||
match entry {
|
||||
Ok(e) => {
|
||||
let creds = Creds {
|
||||
jid: jid_str,
|
||||
password,
|
||||
};
|
||||
let creds = toml::to_string(&creds);
|
||||
match creds {
|
||||
Ok(c) => {
|
||||
let result = e.set_password(&c);
|
||||
if let Err(e) = result {
|
||||
tasks.push(Task::done(crate::Message::Error(
|
||||
crate::Error::CredentialsSave(e.into()),
|
||||
)));
|
||||
}
|
||||
}
|
||||
Err(e) => tasks.push(Task::done(
|
||||
crate::Message::Error(
|
||||
crate::Error::CredentialsSave(
|
||||
e.into(),
|
||||
),
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
tasks.push(Task::done(crate::Message::Error(
|
||||
crate::Error::CredentialsSave(e.into()),
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks
|
||||
}
|
||||
Err(_e) => {
|
||||
tracing::error!("error (database probably)");
|
||||
return vec![Task::done(crate::Message::LoginModal(
|
||||
Message::Error(Error::DatabaseConnection),
|
||||
))];
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
tracing::error!("parsing jid");
|
||||
return vec![Task::done(crate::Message::LoginModal(
|
||||
Message::Error(Error::InvalidJID(jid_str.to_string())),
|
||||
))];
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(|tasks| Task::batch(tasks)),
|
||||
)
|
||||
Action::CreateClient(jid_str, password, remember_me)
|
||||
}
|
||||
Message::Error(error) => {
|
||||
self.error = Some(error);
|
||||
|
|
160
src/main.rs
160
src/main.rs
|
@ -2,6 +2,8 @@ use std::borrow::Cow;
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Debug;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::futures::{SinkExt, Stream, StreamExt};
|
||||
|
@ -30,14 +32,20 @@ use uuid::Uuid;
|
|||
|
||||
mod login_modal;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct Config {
|
||||
auto_connect: bool,
|
||||
storage_dir: Option<String>,
|
||||
dburl: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self { auto_connect: true }
|
||||
Self {
|
||||
auto_connect: true,
|
||||
storage_dir: None,
|
||||
dburl: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,6 +117,42 @@ impl Deref for Client {
|
|||
}
|
||||
}
|
||||
|
||||
async fn luz(jid: &JID, creds: &Creds, cfg: &Config) -> (LuzHandle, mpsc::Receiver<UpdateMessage>) {
|
||||
let luz;
|
||||
if let Some(ref dburl) = cfg.dburl {
|
||||
// TODO: have some sort of crash popup for this stuff
|
||||
let db_path = dburl.strip_prefix("sqlite://").unwrap_or(&dburl);
|
||||
let db_path = PathBuf::from_str(db_path).expect("invalid database path");
|
||||
let db = luz::db::Db::create_connect_and_migrate(db_path)
|
||||
.await
|
||||
.unwrap();
|
||||
luz = LuzHandle::new(jid.clone(), creds.password.to_string(), db);
|
||||
} else if let Some(ref dir) = cfg.storage_dir {
|
||||
let mut data_dir = PathBuf::from_str(&dir).expect("invalid storage directory path");
|
||||
data_dir.push(creds.jid.clone());
|
||||
data_dir.push(creds.jid.clone());
|
||||
data_dir.set_extension("db");
|
||||
let db = luz::db::Db::create_connect_and_migrate(data_dir)
|
||||
.await
|
||||
.unwrap();
|
||||
luz = LuzHandle::new(jid.clone(), creds.password.to_string(), db);
|
||||
} else {
|
||||
let mut data_dir = dirs::data_dir()
|
||||
.expect("operating system does not support retreiving determining default data dir");
|
||||
data_dir.push("macaw");
|
||||
data_dir.push(creds.jid.clone());
|
||||
data_dir.push(creds.jid.clone());
|
||||
// TODO: better lol
|
||||
data_dir.set_extension("db");
|
||||
info!("db_path: {:?}", data_dir);
|
||||
let db = luz::db::Db::create_connect_and_migrate(data_dir)
|
||||
.await
|
||||
.unwrap();
|
||||
luz = LuzHandle::new(jid.clone(), creds.password.to_string(), db);
|
||||
}
|
||||
luz
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> iced::Result {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
@ -154,11 +198,8 @@ async fn main() -> iced::Result {
|
|||
let jid = creds.jid.parse::<JID>();
|
||||
match jid {
|
||||
Ok(jid) => {
|
||||
let luz = LuzHandle::new(jid.clone(), creds.password.to_string(), "macaw.db").await;
|
||||
match luz {
|
||||
Ok((handle, recv)) => client = Some((jid.as_bare(), handle, recv)),
|
||||
Err(e) => client_creation_error = Some(Error::ClientCreation(e)),
|
||||
}
|
||||
let (handle, updates) = luz(&jid, &creds, &cfg).await;
|
||||
client = Some((jid, handle, updates));
|
||||
}
|
||||
Err(e) => client_creation_error = Some(Error::CredentialsLoad(e.into())),
|
||||
}
|
||||
|
@ -168,10 +209,43 @@ async fn main() -> iced::Result {
|
|||
let stream = ReceiverStream::new(update_recv);
|
||||
let stream = stream.map(|message| Message::Luz(message));
|
||||
let task = {
|
||||
let luz_handle1 = luz_handle.clone();
|
||||
let luz_handle2 = luz_handle.clone();
|
||||
if cfg.auto_connect {
|
||||
Task::batch([Task::stream(stream), Task::done(Message::Connect)])
|
||||
Task::batch([
|
||||
Task::perform(async move { luz_handle1.get_roster().await }, |result| {
|
||||
let roster = result.unwrap();
|
||||
let mut macaw_roster = HashMap::new();
|
||||
for contact in roster {
|
||||
macaw_roster.insert(contact.user_jid.clone(), contact);
|
||||
}
|
||||
Message::Roster(macaw_roster)
|
||||
}),
|
||||
Task::perform(async move { luz_handle2.get_chats().await }, |chats| {
|
||||
let chats = chats.unwrap();
|
||||
info!("got chats: {:?}", chats);
|
||||
Message::GotChats(chats)
|
||||
}),
|
||||
Task::stream(stream),
|
||||
Task::done(Message::Connect),
|
||||
])
|
||||
} else {
|
||||
Task::stream(stream)
|
||||
Task::batch([
|
||||
Task::perform(async move { luz_handle1.get_roster().await }, |result| {
|
||||
let roster = result.unwrap();
|
||||
let mut macaw_roster = HashMap::new();
|
||||
for contact in roster {
|
||||
macaw_roster.insert(contact.user_jid.clone(), contact);
|
||||
}
|
||||
Message::Roster(macaw_roster)
|
||||
}),
|
||||
Task::perform(async move { luz_handle2.get_chats().await }, |chats| {
|
||||
let chats = chats.unwrap();
|
||||
info!("got chats: {:?}", chats);
|
||||
Message::GotChats(chats)
|
||||
}),
|
||||
Task::stream(stream),
|
||||
])
|
||||
}
|
||||
};
|
||||
iced::application("Macaw", Macaw::update, Macaw::view).run_with(|| {
|
||||
|
@ -185,7 +259,6 @@ async fn main() -> iced::Result {
|
|||
}),
|
||||
cfg,
|
||||
),
|
||||
// TODO: autoconnect config
|
||||
task,
|
||||
)
|
||||
})
|
||||
|
@ -345,6 +418,7 @@ impl Macaw {
|
|||
// .into_iter()
|
||||
// .map(|chat| (chat.correspondent.clone(), (chat, IndexMap::new())))
|
||||
// .collect();
|
||||
info!("got chats: {:?}", chats);
|
||||
Message::GotChats(chats)
|
||||
}),
|
||||
Task::done(Message::Connect),
|
||||
|
@ -365,6 +439,7 @@ impl Macaw {
|
|||
// .into_iter()
|
||||
// .map(|chat| (chat.correspondent.clone(), (chat, IndexMap::new())))
|
||||
// .collect();
|
||||
info!("got chats: {:?}", chats);
|
||||
Message::GotChats(chats)
|
||||
}),
|
||||
])
|
||||
|
@ -409,6 +484,71 @@ impl Macaw {
|
|||
let action = login_modal.update(login_modal_message);
|
||||
match action {
|
||||
login_modal::Action::None => Task::none(),
|
||||
login_modal::Action::CreateClient(jid, password, remember_me) => {
|
||||
let creds = Creds { jid, password };
|
||||
let jid = creds.jid.parse::<JID>();
|
||||
let config = self.config.clone();
|
||||
match jid {
|
||||
Ok(jid) => {
|
||||
Task::perform(async move {
|
||||
let (jid, creds, config) = (jid, creds, config);
|
||||
let (handle, recv) = luz(&jid, &creds, &config).await;
|
||||
(handle, recv, jid, creds, config)
|
||||
}, move |(handle, recv, jid, creds, config)| {
|
||||
let creds = creds;
|
||||
let mut tasks = Vec::new();
|
||||
tasks.push(Task::done(crate::Message::ClientCreated(
|
||||
Client {
|
||||
client: handle,
|
||||
jid,
|
||||
connection_status: Presence::Offline(
|
||||
Offline::default(),
|
||||
),
|
||||
},
|
||||
)));
|
||||
let stream = ReceiverStream::new(recv);
|
||||
let stream =
|
||||
stream.map(|message| crate::Message::Luz(message));
|
||||
tasks.push(Task::stream(stream));
|
||||
|
||||
if remember_me {
|
||||
let entry = Entry::new("macaw", "macaw");
|
||||
match entry {
|
||||
Ok(e) => {
|
||||
let creds = toml::to_string(&creds);
|
||||
match creds {
|
||||
Ok(c) => {
|
||||
let result = e.set_password(&c);
|
||||
if let Err(e) = result {
|
||||
tasks.push(Task::done(crate::Message::Error(
|
||||
crate::Error::CredentialsSave(e.into()),
|
||||
)));
|
||||
}
|
||||
}
|
||||
Err(e) => tasks.push(Task::done(
|
||||
crate::Message::Error(
|
||||
crate::Error::CredentialsSave(
|
||||
e.into(),
|
||||
),
|
||||
),
|
||||
)),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
tasks.push(Task::done(crate::Message::Error(
|
||||
crate::Error::CredentialsSave(e.into()),
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks
|
||||
}).then(|tasks| Task::batch(tasks))
|
||||
}
|
||||
Err(e) => Task::done(Message::LoginModal(
|
||||
login_modal::Message::Error(login_modal::Error::InvalidJID),
|
||||
)),
|
||||
}
|
||||
}
|
||||
login_modal::Action::ClientCreated(task) => task,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue