fix: async mutex lock forever
This commit is contained in:
@@ -285,7 +285,7 @@ pub async fn login(
|
|||||||
// NIP-03: Get user's contact list
|
// NIP-03: Get user's contact list
|
||||||
let contact_list = {
|
let contact_list = {
|
||||||
if let Ok(contacts) = client.get_contact_list(Some(Duration::from_secs(5))).await {
|
if let Ok(contacts) = client.get_contact_list(Some(Duration::from_secs(5))).await {
|
||||||
state.contact_list.lock().await.clone_from(&contacts);
|
state.contact_list.lock().unwrap().clone_from(&contacts);
|
||||||
contacts
|
contacts
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
@@ -375,7 +375,7 @@ pub async fn login(
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Update app's state
|
// Update app's state
|
||||||
state.trusted_list.lock().await.clone_from(&trusted_list);
|
state.trusted_list.lock().unwrap().clone_from(&trusted_list);
|
||||||
|
|
||||||
let trusted_users: Vec<PublicKey> = trusted_list.into_iter().collect();
|
let trusted_users: Vec<PublicKey> = trusted_list.into_iter().collect();
|
||||||
println!("Total trusted users: {}", trusted_users.len());
|
println!("Total trusted users: {}", trusted_users.len());
|
||||||
|
|||||||
@@ -73,15 +73,13 @@ pub async fn get_event(id: String, state: State<'_, Nostr>) -> Result<RichEvent,
|
|||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub async fn get_event_from(
|
pub async fn get_event_from(
|
||||||
id: String,
|
id: String,
|
||||||
relay_hint: String,
|
_relay_hint: String,
|
||||||
state: State<'_, Nostr>,
|
state: State<'_, Nostr>,
|
||||||
) -> Result<RichEvent, String> {
|
) -> Result<RichEvent, String> {
|
||||||
let client = &state.client;
|
let client = &state.client;
|
||||||
let settings = state.settings.lock().await;
|
|
||||||
let event_id = EventId::parse(&id).map_err(|err| err.to_string())?;
|
let event_id = EventId::parse(&id).map_err(|err| err.to_string())?;
|
||||||
let filter = Filter::new().id(event_id);
|
let filter = Filter::new().id(event_id);
|
||||||
|
|
||||||
if !settings.use_relay_hint {
|
|
||||||
match client
|
match client
|
||||||
.get_events_of(
|
.get_events_of(
|
||||||
vec![filter],
|
vec![filter],
|
||||||
@@ -105,40 +103,6 @@ pub async fn get_event_from(
|
|||||||
}
|
}
|
||||||
Err(err) => Err(err.to_string()),
|
Err(err) => Err(err.to_string()),
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Add relay hint to relay pool
|
|
||||||
if let Err(e) = client.add_relay(&relay_hint).await {
|
|
||||||
return Err(e.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(e) = client.connect_relay(&relay_hint).await {
|
|
||||||
return Err(e.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
match client
|
|
||||||
.get_events_of(
|
|
||||||
vec![Filter::new().id(event_id)],
|
|
||||||
EventSource::both(Some(Duration::from_secs(5))),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(events) => {
|
|
||||||
if let Some(event) = events.first() {
|
|
||||||
let raw = event.as_json();
|
|
||||||
let parsed = if event.kind == Kind::TextNote {
|
|
||||||
Some(parse_event(&event.content).await)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(RichEvent { raw, parsed })
|
|
||||||
} else {
|
|
||||||
Err("Cannot found this event with current relay list".into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => Err(err.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
|||||||
@@ -107,8 +107,8 @@ pub async fn set_contact_list(
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub async fn get_contact_list(state: State<'_, Nostr>) -> Result<Vec<String>, String> {
|
pub fn get_contact_list(state: State<'_, Nostr>) -> Result<Vec<String>, String> {
|
||||||
let contact_list = state.contact_list.lock().await.clone();
|
let contact_list = state.contact_list.lock().unwrap().clone();
|
||||||
let vec: Vec<String> = contact_list
|
let vec: Vec<String> = contact_list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|f| f.public_key.to_hex())
|
.map(|f| f.public_key.to_hex())
|
||||||
@@ -152,8 +152,8 @@ pub async fn set_profile(profile: Profile, state: State<'_, Nostr>) -> Result<St
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub async fn check_contact(id: String, state: State<'_, Nostr>) -> Result<bool, String> {
|
pub fn check_contact(id: String, state: State<'_, Nostr>) -> Result<bool, String> {
|
||||||
let contact_list = &state.contact_list.lock().await;
|
let contact_list = &state.contact_list.lock().unwrap();
|
||||||
let public_key = PublicKey::from_str(&id).map_err(|e| e.to_string())?;
|
let public_key = PublicKey::from_str(&id).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
match contact_list.iter().position(|x| x.public_key == public_key) {
|
match contact_list.iter().position(|x| x.public_key == public_key) {
|
||||||
@@ -577,8 +577,8 @@ pub async fn get_notifications(state: State<'_, Nostr>) -> Result<Vec<String>, S
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub async fn get_user_settings(state: State<'_, Nostr>) -> Result<Settings, ()> {
|
pub fn get_user_settings(state: State<'_, Nostr>) -> Result<Settings, String> {
|
||||||
Ok(state.settings.lock().await.clone())
|
Ok(state.settings.lock().unwrap().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -597,7 +597,7 @@ pub async fn set_user_settings(
|
|||||||
let parsed: Settings = serde_json::from_str(&settings).map_err(|e| e.to_string())?;
|
let parsed: Settings = serde_json::from_str(&settings).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
state.settings.lock().await.clone_from(&parsed);
|
state.settings.lock().unwrap().clone_from(&parsed);
|
||||||
|
|
||||||
// Emit new changes to frontend
|
// Emit new changes to frontend
|
||||||
NewSettings(parsed).emit(&handle).unwrap();
|
NewSettings(parsed).emit(&handle).unwrap();
|
||||||
@@ -622,8 +622,8 @@ pub async fn verify_nip05(id: String, nip05: &str) -> Result<bool, String> {
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub async fn is_trusted_user(id: String, state: State<'_, Nostr>) -> Result<bool, String> {
|
pub fn is_trusted_user(id: String, state: State<'_, Nostr>) -> Result<bool, String> {
|
||||||
let trusted_list = &state.trusted_list.lock().await;
|
let trusted_list = &state.trusted_list.lock().unwrap();
|
||||||
let public_key = PublicKey::from_str(&id).map_err(|e| e.to_string())?;
|
let public_key = PublicKey::from_str(&id).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
Ok(trusted_list.contains(&public_key))
|
Ok(trusted_list.contains(&public_key))
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ use std::{
|
|||||||
fs,
|
fs,
|
||||||
io::{self, BufRead},
|
io::{self, BufRead},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
|
sync::Mutex,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
use tauri::{path::BaseDirectory, Emitter, EventTarget, Manager};
|
use tauri::{path::BaseDirectory, Emitter, EventTarget, Manager};
|
||||||
use tauri_plugin_decorum::WebviewWindowExt;
|
use tauri_plugin_decorum::WebviewWindowExt;
|
||||||
use tauri_plugin_notification::{NotificationExt, PermissionState};
|
use tauri_plugin_notification::{NotificationExt, PermissionState};
|
||||||
use tauri_specta::{collect_commands, collect_events, Builder, Event as TauriEvent};
|
use tauri_specta::{collect_commands, collect_events, Builder, Event as TauriEvent};
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod common;
|
pub mod common;
|
||||||
@@ -317,11 +317,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let contact_list = client
|
let contact_list = state.contact_list.lock().unwrap().clone();
|
||||||
.get_contact_list(Some(Duration::from_secs(5)))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if !contact_list.is_empty() {
|
if !contact_list.is_empty() {
|
||||||
let authors: Vec<PublicKey> =
|
let authors: Vec<PublicKey> =
|
||||||
contact_list.iter().map(|f| f.public_key).collect();
|
contact_list.iter().map(|f| f.public_key).collect();
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ async getNotifications() : Promise<Result<string[], string>> {
|
|||||||
else return { status: "error", error: e as any };
|
else return { status: "error", error: e as any };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getUserSettings() : Promise<Result<Settings, null>> {
|
async getUserSettings() : Promise<Result<Settings, string>> {
|
||||||
try {
|
try {
|
||||||
return { status: "ok", data: await TAURI_INVOKE("get_user_settings") };
|
return { status: "ok", data: await TAURI_INVOKE("get_user_settings") };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -98,22 +98,32 @@ function Content({ text, className }: { text: string; className?: string }) {
|
|||||||
));
|
));
|
||||||
|
|
||||||
for (const word of nostr) {
|
for (const word of nostr) {
|
||||||
const bech32 = word.replace("nostr:", "");
|
const bech32 = word.replace("nostr:", "").replace(/[^\w\s]/gi, "");
|
||||||
|
try {
|
||||||
const data = nip19.decode(bech32);
|
const data = nip19.decode(bech32);
|
||||||
|
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "npub":
|
case "npub":
|
||||||
replacedText = reactStringReplace(replacedText, word, (match, i) => (
|
replacedText = reactStringReplace(
|
||||||
<MentionUser key={match + i} pubkey={data.data} />
|
replacedText,
|
||||||
));
|
word,
|
||||||
|
(match, i) => <MentionUser key={match + i} pubkey={data.data} />,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "nprofile":
|
case "nprofile":
|
||||||
replacedText = reactStringReplace(replacedText, word, (match, i) => (
|
replacedText = reactStringReplace(
|
||||||
|
replacedText,
|
||||||
|
word,
|
||||||
|
(match, i) => (
|
||||||
<MentionUser key={match + i} pubkey={data.data.pubkey} />
|
<MentionUser key={match + i} pubkey={data.data.pubkey} />
|
||||||
));
|
),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
replacedText = reactStringReplace(replacedText, word, (match, i) => (
|
replacedText = reactStringReplace(
|
||||||
|
replacedText,
|
||||||
|
word,
|
||||||
|
(match, i) => (
|
||||||
<a
|
<a
|
||||||
key={match + i}
|
key={match + i}
|
||||||
href={`https://njump.me/${bech32}`}
|
href={`https://njump.me/${bech32}`}
|
||||||
@@ -123,9 +133,13 @@ function Content({ text, className }: { text: string; className?: string }) {
|
|||||||
>
|
>
|
||||||
{match}
|
{match}
|
||||||
</a>
|
</a>
|
||||||
));
|
),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} catch {
|
||||||
|
console.log(word);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return replacedText;
|
return replacedText;
|
||||||
|
|||||||
@@ -188,22 +188,33 @@ function Content({ text, className }: { text: string; className?: string }) {
|
|||||||
));
|
));
|
||||||
|
|
||||||
for (const word of nostr) {
|
for (const word of nostr) {
|
||||||
const bech32 = word.replace("nostr:", "");
|
const bech32 = word.replace("nostr:", "").replace(/[^\w\s]/gi, "");
|
||||||
|
|
||||||
|
try {
|
||||||
const data = nip19.decode(bech32);
|
const data = nip19.decode(bech32);
|
||||||
|
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "npub":
|
case "npub":
|
||||||
replacedText = reactStringReplace(replacedText, word, (match, i) => (
|
replacedText = reactStringReplace(
|
||||||
<MentionUser key={match + i} pubkey={data.data} />
|
replacedText,
|
||||||
));
|
word,
|
||||||
|
(match, i) => <MentionUser key={match + i} pubkey={data.data} />,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case "nprofile":
|
case "nprofile":
|
||||||
replacedText = reactStringReplace(replacedText, word, (match, i) => (
|
replacedText = reactStringReplace(
|
||||||
|
replacedText,
|
||||||
|
word,
|
||||||
|
(match, i) => (
|
||||||
<MentionUser key={match + i} pubkey={data.data.pubkey} />
|
<MentionUser key={match + i} pubkey={data.data.pubkey} />
|
||||||
));
|
),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
replacedText = reactStringReplace(replacedText, word, (match, i) => (
|
replacedText = reactStringReplace(
|
||||||
|
replacedText,
|
||||||
|
word,
|
||||||
|
(match, i) => (
|
||||||
<a
|
<a
|
||||||
key={match + i}
|
key={match + i}
|
||||||
href={`https://njump.me/${bech32}`}
|
href={`https://njump.me/${bech32}`}
|
||||||
@@ -213,9 +224,13 @@ function Content({ text, className }: { text: string; className?: string }) {
|
|||||||
>
|
>
|
||||||
{match}
|
{match}
|
||||||
</a>
|
</a>
|
||||||
));
|
),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} catch {
|
||||||
|
console.log(word);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return replacedText;
|
return replacedText;
|
||||||
|
|||||||
Reference in New Issue
Block a user