wip: refactor
This commit is contained in:
@@ -16,8 +16,6 @@ reqwest_client.workspace = true
|
||||
|
||||
tokio.workspace = true
|
||||
nostr-sdk.workspace = true
|
||||
keyring-search.workspace = true
|
||||
keyring.workspace = true
|
||||
anyhow.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
pub const KEYRING_SERVICE: &str = "Coop Safe Storage";
|
||||
pub const APP_NAME: &str = "coop";
|
||||
pub const APP_NAME: &str = "Coop";
|
||||
pub const FAKE_SIG: &str = "f9e79d141c004977192d05a86f81ec7c585179c371f7350a5412d33575a2a356433f58e405c2296ed273e2fe0aafa25b641e39cc4e1f3f261ebf55bce0cbac83";
|
||||
pub const NEW_MESSAGE_SUB_ID: &str = "listen_new_giftwrap";
|
||||
pub const ALL_MESSAGES_SUB_ID: &str = "listen_all_giftwraps";
|
||||
|
||||
@@ -13,22 +13,25 @@ use tokio::{
|
||||
sync::{mpsc, Mutex},
|
||||
time::sleep,
|
||||
};
|
||||
use ui::Root;
|
||||
|
||||
use constants::{ALL_MESSAGES_SUB_ID, APP_NAME, FAKE_SIG, METADATA_DELAY, NEW_MESSAGE_SUB_ID};
|
||||
use constants::{
|
||||
ALL_MESSAGES_SUB_ID, APP_NAME, FAKE_SIG, KEYRING_SERVICE, METADATA_DELAY, NEW_MESSAGE_SUB_ID,
|
||||
};
|
||||
use ui::Root;
|
||||
use views::app::AppView;
|
||||
|
||||
use states::{
|
||||
account::AccountRegistry,
|
||||
chat::ChatRegistry,
|
||||
metadata::MetadataRegistry,
|
||||
signal::{Signal, SignalRegistry},
|
||||
};
|
||||
use views::app::AppView;
|
||||
|
||||
pub mod asset;
|
||||
pub mod constants;
|
||||
pub mod states;
|
||||
pub mod utils;
|
||||
pub mod views;
|
||||
mod asset;
|
||||
mod constants;
|
||||
mod states;
|
||||
mod utils;
|
||||
mod views;
|
||||
|
||||
actions!(main_menu, [Quit]);
|
||||
actions!(app, [ReloadMetadata]);
|
||||
@@ -128,8 +131,7 @@ async fn main() {
|
||||
|
||||
// Send event back to channel
|
||||
if subscription_id == new_message {
|
||||
if let Err(e) = signal_tx.send(Signal::RecvEvent(ev)).await
|
||||
{
|
||||
if let Err(e) = signal_tx.send(Signal::Event(ev)).await {
|
||||
println!("Send error: {}", e)
|
||||
}
|
||||
}
|
||||
@@ -138,13 +140,13 @@ async fn main() {
|
||||
Err(e) => println!("Unwrap error: {}", e),
|
||||
}
|
||||
} else if event.kind == Kind::Metadata {
|
||||
if let Err(e) = signal_tx.send(Signal::RecvMetadata(event.pubkey)).await {
|
||||
if let Err(e) = signal_tx.send(Signal::Metadata(event.pubkey)).await {
|
||||
println!("Send error: {}", e)
|
||||
}
|
||||
}
|
||||
} else if let RelayMessage::EndOfStoredEvents(subscription_id) = message {
|
||||
if subscription_id == all_messages {
|
||||
if let Err(e) = signal_tx.send(Signal::RecvEose(subscription_id)).await {
|
||||
if let Err(e) = signal_tx.send(Signal::Eose).await {
|
||||
println!("Send error: {}", e)
|
||||
}
|
||||
}
|
||||
@@ -211,6 +213,36 @@ async fn main() {
|
||||
// Set quit action
|
||||
cx.on_action(quit);
|
||||
|
||||
cx.spawn(|async_cx| {
|
||||
let task = cx.read_credentials(KEYRING_SERVICE);
|
||||
|
||||
async move {
|
||||
if let Ok(res) = task.await {
|
||||
if let Some((npub, secret)) = res {
|
||||
let public_key = PublicKey::from_bech32(&npub).unwrap();
|
||||
let hex = String::from_utf8(secret).unwrap();
|
||||
let keys = Keys::parse(&hex).unwrap();
|
||||
|
||||
_ = client.set_signer(keys).await;
|
||||
// Update global state
|
||||
_ = async_cx.update_global::<AccountRegistry, _>(|state, _cx| {
|
||||
state.set_user(Some(public_key));
|
||||
state.set_loading();
|
||||
});
|
||||
} else {
|
||||
_ = async_cx.update_global::<AccountRegistry, _>(|state, _| {
|
||||
state.set_loading();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
_ = async_cx.update_global::<AccountRegistry, _>(|state, _| {
|
||||
state.set_loading();
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.spawn(|async_cx| async move {
|
||||
let (tx, rx) = smol::channel::unbounded::<Signal>();
|
||||
|
||||
@@ -227,12 +259,12 @@ async fn main() {
|
||||
|
||||
while let Ok(signal) = rx.recv().await {
|
||||
match signal {
|
||||
Signal::RecvEose(_) => {
|
||||
Signal::Eose => {
|
||||
_ = async_cx.update_global::<ChatRegistry, _>(|state, _| {
|
||||
state.update();
|
||||
});
|
||||
}
|
||||
Signal::RecvEvent(event) => {
|
||||
Signal::Event(event) => {
|
||||
let metadata = async_cx
|
||||
.background_executor()
|
||||
.spawn(async move {
|
||||
@@ -248,7 +280,7 @@ async fn main() {
|
||||
state.push(event, metadata);
|
||||
});
|
||||
}
|
||||
Signal::RecvMetadata(public_key) => {
|
||||
Signal::Metadata(public_key) => {
|
||||
let metadata = async_cx
|
||||
.background_executor()
|
||||
.spawn(async move {
|
||||
@@ -264,7 +296,6 @@ async fn main() {
|
||||
state.seen(public_key, metadata);
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::{
|
||||
|
||||
pub struct AccountRegistry {
|
||||
public_key: Option<PublicKey>,
|
||||
pub(crate) is_loading: bool,
|
||||
}
|
||||
|
||||
impl Global for AccountRegistry {}
|
||||
@@ -58,6 +59,10 @@ impl AccountRegistry {
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn set_loading(&mut self) {
|
||||
self.is_loading = false
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Option<PublicKey> {
|
||||
self.public_key
|
||||
}
|
||||
@@ -71,6 +76,9 @@ impl AccountRegistry {
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
Self { public_key: None }
|
||||
Self {
|
||||
public_key: None,
|
||||
is_loading: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,6 @@ impl MetadataRegistry {
|
||||
cx.set_global(Self::new());
|
||||
}
|
||||
|
||||
pub fn contains(&self, public_key: PublicKey) -> bool {
|
||||
self.seens.lock().unwrap().contains(&public_key)
|
||||
}
|
||||
|
||||
pub fn seen(&mut self, public_key: PublicKey, metadata: Option<Metadata>) {
|
||||
let mut seens = self.seens.lock().unwrap();
|
||||
|
||||
|
||||
@@ -5,14 +5,12 @@ use tokio::sync::mpsc::UnboundedSender;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Signal {
|
||||
/// Request metadata
|
||||
ReqMetadata(PublicKey),
|
||||
/// Receive metadata
|
||||
RecvMetadata(PublicKey),
|
||||
/// Receive EOSE
|
||||
RecvEose(SubscriptionId),
|
||||
Metadata(PublicKey),
|
||||
/// Receive event
|
||||
RecvEvent(Event),
|
||||
Event(Event),
|
||||
/// Receive EOSE
|
||||
Eose,
|
||||
}
|
||||
|
||||
pub struct SignalRegistry {
|
||||
|
||||
@@ -1,32 +1,6 @@
|
||||
use chrono::{Duration, Local, TimeZone};
|
||||
use keyring::Entry;
|
||||
use keyring_search::{Limit, List, Search};
|
||||
use nostr_sdk::prelude::*;
|
||||
|
||||
use crate::constants::KEYRING_SERVICE;
|
||||
|
||||
pub fn get_all_accounts_from_keyring() -> Vec<PublicKey> {
|
||||
let search = Search::new().expect("Keyring not working.");
|
||||
let results = search.by_service("Coop Safe Storage");
|
||||
let list = List::list_credentials(&results, Limit::All);
|
||||
let accounts: Vec<PublicKey> = list
|
||||
.split_whitespace()
|
||||
.filter(|v| v.starts_with("npub1") && !v.ends_with("coop"))
|
||||
.filter_map(|i| PublicKey::from_bech32(i).ok())
|
||||
.collect();
|
||||
|
||||
accounts
|
||||
}
|
||||
|
||||
pub fn get_keys_by_account(public_key: PublicKey) -> Result<Keys, anyhow::Error> {
|
||||
let bech32 = public_key.to_bech32()?;
|
||||
let entry = Entry::new(KEYRING_SERVICE, &bech32)?;
|
||||
let password = entry.get_password()?;
|
||||
let keys = Keys::parse(&password)?;
|
||||
|
||||
Ok(keys)
|
||||
}
|
||||
|
||||
pub fn get_room_id(owner: &PublicKey, public_keys: &[PublicKey]) -> String {
|
||||
let hex: Vec<String> = public_keys
|
||||
.iter()
|
||||
|
||||
@@ -4,8 +4,9 @@ use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
use ui::{
|
||||
dock::{DockArea, DockItem, DockPlacement},
|
||||
indicator::Indicator,
|
||||
theme::Theme,
|
||||
Root, TitleBar,
|
||||
Root, Sizable, TitleBar,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -143,10 +144,20 @@ impl Render for AppView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let modal_layer = Root::render_modal_layer(cx);
|
||||
let notification_layer = Root::render_notification_layer(cx);
|
||||
let state = cx.global::<AccountRegistry>();
|
||||
|
||||
let mut content = div().size_full().flex().flex_col();
|
||||
|
||||
if cx.global::<AccountRegistry>().is_user_logged_in() {
|
||||
if state.is_loading {
|
||||
content = content.child(div()).child(
|
||||
div()
|
||||
.flex_1()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.child(Indicator::new().small()),
|
||||
)
|
||||
} else if state.is_user_logged_in() {
|
||||
content = content
|
||||
.child(
|
||||
TitleBar::new()
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use async_utility::task::spawn;
|
||||
use gpui::*;
|
||||
use keyring::Entry;
|
||||
use nostr_sdk::prelude::*;
|
||||
use ui::{
|
||||
input::{InputEvent, TextInput},
|
||||
@@ -34,26 +32,30 @@ impl Onboarding {
|
||||
|
||||
fn save_keys(content: &str, cx: &mut ViewContext<Self>) -> anyhow::Result<(), anyhow::Error> {
|
||||
let keys = Keys::parse(content)?;
|
||||
|
||||
let public_key = keys.public_key();
|
||||
let bech32 = public_key.to_bech32().unwrap();
|
||||
let bech32 = public_key.to_bech32()?;
|
||||
let secret = keys.secret_key().to_secret_hex();
|
||||
|
||||
let entry = Entry::new(KEYRING_SERVICE, &bech32).unwrap();
|
||||
let mut async_cx = cx.to_async();
|
||||
let view_id = cx.entity_id();
|
||||
|
||||
// Save secret key to keyring
|
||||
entry.set_password(&secret)?;
|
||||
cx.foreground_executor()
|
||||
.spawn({
|
||||
let client = get_client();
|
||||
let task = cx.write_credentials(KEYRING_SERVICE, &bech32, secret.as_bytes());
|
||||
|
||||
// Update signer
|
||||
spawn(async move {
|
||||
get_client().set_signer(keys).await;
|
||||
});
|
||||
|
||||
// Update globals state
|
||||
cx.update_global::<AccountRegistry, _>(|state, cx| {
|
||||
state.set_user(Some(public_key));
|
||||
cx.notify();
|
||||
});
|
||||
async move {
|
||||
if task.await.is_ok() {
|
||||
_ = client.set_signer(keys).await;
|
||||
// Update global state
|
||||
_ = async_cx.update_global::<AccountRegistry, _>(|state, cx| {
|
||||
state.set_user(Some(public_key));
|
||||
cx.notify(Some(view_id));
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user