Release v4.1 (#229)

* refactor: remove custom icon packs

* fix: command not work on windows

* fix: make open_window command async

* feat: improve commands

* feat: improve

* refactor: column

* feat: improve thread column

* feat: improve

* feat: add stories column

* feat: improve

* feat: add search column

* feat: add reset password

* feat: add subscription

* refactor: settings

* chore: improve commands

* fix: crash on production

* feat: use tauri store plugin for cache

* feat: new icon

* chore: update icon for windows

* chore: improve some columns

* chore: polish code
This commit is contained in:
雨宮蓮
2024-08-27 19:37:30 +07:00
committed by GitHub
parent 26ae473521
commit 61ad96ca63
318 changed files with 5564 additions and 8458 deletions

View File

@@ -46,106 +46,27 @@ const NOSTR_MENTIONS: [&str; 10] = [
const IMAGES: [&str; 7] = ["jpg", "jpeg", "gif", "png", "webp", "avif", "tiff"];
const VIDEOS: [&str; 5] = ["mp4", "mov", "avi", "webm", "mkv"];
pub async fn init_nip65(client: &Client) {
let signer = match client.signer().await {
Ok(signer) => signer,
Err(e) => {
eprintln!("Failed to get signer: {:?}", e);
return;
}
};
let public_key = match signer.public_key().await {
Ok(public_key) => public_key,
Err(e) => {
eprintln!("Failed to get public key: {:?}", e);
return;
}
};
let filter = Filter::new()
.author(public_key)
.kind(Kind::RelayList)
.limit(1);
if let Ok(events) = client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
if let Some(event) = events.first() {
let relay_list = nip65::extract_relay_list(event);
for (url, metadata) in relay_list {
let opts = match metadata {
Some(RelayMetadata::Read) => RelayOptions::new().read(true).write(false),
Some(_) => RelayOptions::new().write(true).read(false),
None => RelayOptions::default(),
};
if let Err(e) = client.add_relay_with_opts(&url.to_string(), opts).await {
eprintln!("Failed to add relay {}: {:?}", url, e);
}
if let Err(e) = client.connect_relay(url.to_string()).await {
eprintln!("Failed to connect to relay {}: {:?}", url, e);
} else {
println!("Connecting to relay: {} - {:?}", url, metadata);
}
}
}
} else {
eprintln!("Failed to get events for RelayList.");
}
}
pub async fn get_user_settings(client: &Client) -> Result<Settings, String> {
let ident = "lume:settings";
let signer = client
.signer()
.await
.map_err(|e| format!("Failed to get signer: {:?}", e))?;
let public_key = signer
.public_key()
.await
.map_err(|e| format!("Failed to get public key: {:?}", e))?;
let filter = Filter::new()
.author(public_key)
.kind(Kind::ApplicationSpecificData)
.identifier(ident)
.limit(1);
match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
if let Some(event) = events.first() {
let content = event.content();
match signer.nip44_decrypt(public_key, content).await {
Ok(decrypted) => match serde_json::from_str(&decrypted) {
Ok(parsed) => Ok(parsed),
Err(_) => Err("Could not parse settings payload".into()),
},
Err(e) => Err(format!("Failed to decrypt settings content: {:?}", e)),
}
} else {
Err("Settings not found.".into())
}
}
Err(e) => Err(format!(
"Failed to get events for ApplicationSpecificData: {:?}",
e
)),
}
}
pub fn get_latest_event(events: &[Event]) -> Option<&Event> {
events.iter().next()
}
pub fn filter_converstation(events: Vec<Event>) -> Vec<Event> {
events
.into_iter()
.filter_map(|ev| {
let tags = ev.get_tags_content(TagKind::SingleLetter(SingleLetterTag::lowercase(
Alphabet::E,
)));
if tags.is_empty() {
Some(ev)
} else {
None
}
})
.collect::<Vec<Event>>()
}
pub fn dedup_event(events: &[Event]) -> Vec<Event> {
let mut seen_ids = HashSet::new();
events
@@ -331,6 +252,102 @@ pub fn create_event_tags(content: &str) -> Vec<Tag> {
tags
}
pub async fn init_nip65(client: &Client) {
let signer = match client.signer().await {
Ok(signer) => signer,
Err(e) => {
eprintln!("Failed to get signer: {:?}", e);
return;
}
};
let public_key = match signer.public_key().await {
Ok(public_key) => public_key,
Err(e) => {
eprintln!("Failed to get public key: {:?}", e);
return;
}
};
let filter = Filter::new()
.author(public_key)
.kind(Kind::RelayList)
.limit(1);
if let Ok(events) = client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
if let Some(event) = events.first() {
let relay_list = nip65::extract_relay_list(event);
for (url, metadata) in relay_list {
let opts = match metadata {
Some(RelayMetadata::Read) => RelayOptions::new().read(true).write(false),
Some(_) => RelayOptions::new().write(true).read(false),
None => RelayOptions::default(),
};
if let Err(e) = client.add_relay_with_opts(&url.to_string(), opts).await {
eprintln!("Failed to add relay {}: {:?}", url, e);
}
if let Err(e) = client.connect_relay(url.to_string()).await {
eprintln!("Failed to connect to relay {}: {:?}", url, e);
} else {
println!("Connecting to relay: {} - {:?}", url, metadata);
}
}
}
} else {
eprintln!("Failed to get events for RelayList.");
}
}
pub async fn get_user_settings(client: &Client) -> Result<Settings, String> {
let ident = "lume_v4:settings";
let signer = client
.signer()
.await
.map_err(|e| format!("Failed to get signer: {:?}", e))?;
let public_key = signer
.public_key()
.await
.map_err(|e| format!("Failed to get public key: {:?}", e))?;
let filter = Filter::new()
.author(public_key)
.kind(Kind::ApplicationSpecificData)
.identifier(ident)
.limit(1);
match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
if let Some(event) = events.first() {
let content = event.content();
match signer.nip44_decrypt(public_key, content).await {
Ok(decrypted) => match serde_json::from_str(&decrypted) {
Ok(parsed) => Ok(parsed),
Err(_) => Err("Could not parse settings payload".into()),
},
Err(e) => Err(format!("Failed to decrypt settings content: {:?}", e)),
}
} else {
Err("Settings not found.".into())
}
}
Err(e) => Err(format!(
"Failed to get events for ApplicationSpecificData: {:?}",
e
)),
}
}
#[cfg(test)]
mod tests {
use super::*;