mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-19 01:24:21 +01:00
notedeck app: add clndash
a core-lightning dashboard i'm working on feature-gate it behind --clndash Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
37
Cargo.lock
generated
37
Cargo.lock
generated
@@ -2336,6 +2336,12 @@ version = "0.12.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.4"
|
version = "0.15.4"
|
||||||
@@ -3064,6 +3070,22 @@ version = "0.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
|
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lnsocket"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a88bd51e5bb3753f89b0d3e73baa565064c5a9f5b2aad3ab3f3db5fffb89955"
|
||||||
|
dependencies = [
|
||||||
|
"bitcoin",
|
||||||
|
"hashbrown 0.13.2",
|
||||||
|
"hex",
|
||||||
|
"lightning-types",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
@@ -3540,6 +3562,7 @@ dependencies = [
|
|||||||
"egui_tabs",
|
"egui_tabs",
|
||||||
"nostrdb",
|
"nostrdb",
|
||||||
"notedeck",
|
"notedeck",
|
||||||
|
"notedeck_clndash",
|
||||||
"notedeck_columns",
|
"notedeck_columns",
|
||||||
"notedeck_dave",
|
"notedeck_dave",
|
||||||
"notedeck_notebook",
|
"notedeck_notebook",
|
||||||
@@ -3559,6 +3582,20 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notedeck_clndash"
|
||||||
|
version = "0.6.0"
|
||||||
|
dependencies = [
|
||||||
|
"eframe",
|
||||||
|
"egui",
|
||||||
|
"lnsocket",
|
||||||
|
"notedeck",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notedeck_columns"
|
name = "notedeck_columns"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ members = [
|
|||||||
"crates/notedeck_dave",
|
"crates/notedeck_dave",
|
||||||
"crates/notedeck_notebook",
|
"crates/notedeck_notebook",
|
||||||
"crates/notedeck_ui",
|
"crates/notedeck_ui",
|
||||||
|
"crates/notedeck_clndash",
|
||||||
|
|
||||||
"crates/enostr", "crates/tokenator", "crates/notedeck_dave", "crates/notedeck_ui",
|
"crates/enostr", "crates/tokenator", "crates/notedeck_dave", "crates/notedeck_ui", "crates/notedeck_clndash",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
@@ -48,6 +49,7 @@ nostrdb = { git = "https://github.com/damus-io/nostrdb-rs", rev = "2b2e5e43c019b
|
|||||||
#nostrdb = "0.6.1"
|
#nostrdb = "0.6.1"
|
||||||
notedeck = { path = "crates/notedeck" }
|
notedeck = { path = "crates/notedeck" }
|
||||||
notedeck_chrome = { path = "crates/notedeck_chrome" }
|
notedeck_chrome = { path = "crates/notedeck_chrome" }
|
||||||
|
notedeck_clndash = { path = "crates/notedeck_clndash" }
|
||||||
notedeck_columns = { path = "crates/notedeck_columns" }
|
notedeck_columns = { path = "crates/notedeck_columns" }
|
||||||
notedeck_dave = { path = "crates/notedeck_dave" }
|
notedeck_dave = { path = "crates/notedeck_dave" }
|
||||||
notedeck_notebook = { path = "crates/notedeck_notebook" }
|
notedeck_notebook = { path = "crates/notedeck_notebook" }
|
||||||
|
|||||||
57
assets/icons/clnlogo.svg
Normal file
57
assets/icons/clnlogo.svg
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="256mm"
|
||||||
|
height="256mm"
|
||||||
|
viewBox="0 0 256 256"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
|
sodipodi:docname="clnlogo.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:zoom="1.078823"
|
||||||
|
inkscape:cx="396.72867"
|
||||||
|
inkscape:cy="561.25984"
|
||||||
|
inkscape:window-width="2020"
|
||||||
|
inkscape:window-height="1420"
|
||||||
|
inkscape:window-x="270"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" />
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="matrix(1.0800571,0,0,1.0347966,-2.6149197,-3.0116377)"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g4"
|
||||||
|
transform="matrix(0.43515072,0,0,0.43515072,68.289343,9.0200629)">
|
||||||
|
<path
|
||||||
|
class="st1"
|
||||||
|
d="M 214.6,0 2.2,285.8 246.4,222.3 100.1,222.4 Z"
|
||||||
|
id="path3"
|
||||||
|
style="fill:#f0d003" />
|
||||||
|
<path
|
||||||
|
fill="#fffae6"
|
||||||
|
d="M 31.8,550.7 244.1,264.9 0,328.4 146.3,328.3 Z"
|
||||||
|
id="path4" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -126,6 +126,8 @@ impl Args {
|
|||||||
res.options.set(NotedeckOptions::RelayDebug, true);
|
res.options.set(NotedeckOptions::RelayDebug, true);
|
||||||
} else if arg == "--notebook" {
|
} else if arg == "--notebook" {
|
||||||
res.options.set(NotedeckOptions::FeatureNotebook, true);
|
res.options.set(NotedeckOptions::FeatureNotebook, true);
|
||||||
|
} else if arg == "--clndash" {
|
||||||
|
res.options.set(NotedeckOptions::FeatureClnDash, true);
|
||||||
} else {
|
} else {
|
||||||
unrecognized_args.insert(arg.clone());
|
unrecognized_args.insert(arg.clone());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ bitflags! {
|
|||||||
// ===== Feature Flags ======
|
// ===== Feature Flags ======
|
||||||
/// Is notebook enabled?
|
/// Is notebook enabled?
|
||||||
const FeatureNotebook = 1 << 32;
|
const FeatureNotebook = 1 << 32;
|
||||||
|
|
||||||
|
/// Is clndash enabled?
|
||||||
|
const FeatureClnDash = 1 << 33;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ notedeck_columns = { workspace = true }
|
|||||||
notedeck_ui = { workspace = true }
|
notedeck_ui = { workspace = true }
|
||||||
notedeck_dave = { workspace = true }
|
notedeck_dave = { workspace = true }
|
||||||
notedeck_notebook = { workspace = true }
|
notedeck_notebook = { workspace = true }
|
||||||
|
notedeck_clndash = { workspace = true }
|
||||||
notedeck = { workspace = true }
|
notedeck = { workspace = true }
|
||||||
nostrdb = { workspace = true }
|
nostrdb = { workspace = true }
|
||||||
puffin = { workspace = true, optional = true }
|
puffin = { workspace = true, optional = true }
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use notedeck::{AppAction, AppContext};
|
use notedeck::{AppAction, AppContext};
|
||||||
|
use notedeck_clndash::ClnDash;
|
||||||
use notedeck_columns::Damus;
|
use notedeck_columns::Damus;
|
||||||
use notedeck_dave::Dave;
|
use notedeck_dave::Dave;
|
||||||
use notedeck_notebook::Notebook;
|
use notedeck_notebook::Notebook;
|
||||||
@@ -8,6 +9,7 @@ pub enum NotedeckApp {
|
|||||||
Dave(Box<Dave>),
|
Dave(Box<Dave>),
|
||||||
Columns(Box<Damus>),
|
Columns(Box<Damus>),
|
||||||
Notebook(Box<Notebook>),
|
Notebook(Box<Notebook>),
|
||||||
|
ClnDash(Box<ClnDash>),
|
||||||
Other(Box<dyn notedeck::App>),
|
Other(Box<dyn notedeck::App>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ impl notedeck::App for NotedeckApp {
|
|||||||
NotedeckApp::Dave(dave) => dave.update(ctx, ui),
|
NotedeckApp::Dave(dave) => dave.update(ctx, ui),
|
||||||
NotedeckApp::Columns(columns) => columns.update(ctx, ui),
|
NotedeckApp::Columns(columns) => columns.update(ctx, ui),
|
||||||
NotedeckApp::Notebook(notebook) => notebook.update(ctx, ui),
|
NotedeckApp::Notebook(notebook) => notebook.update(ctx, ui),
|
||||||
|
NotedeckApp::ClnDash(clndash) => clndash.update(ctx, ui),
|
||||||
NotedeckApp::Other(other) => other.update(ctx, ui),
|
NotedeckApp::Other(other) => other.update(ctx, ui),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ use notedeck_columns::{
|
|||||||
Damus,
|
Damus,
|
||||||
};
|
};
|
||||||
use notedeck_dave::{Dave, DaveAvatar};
|
use notedeck_dave::{Dave, DaveAvatar};
|
||||||
use notedeck_notebook::Notebook;
|
|
||||||
use notedeck_ui::{app_images, AnimationHelper, ProfilePic};
|
use notedeck_ui::{app_images, AnimationHelper, ProfilePic};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@@ -198,6 +197,10 @@ impl Chrome {
|
|||||||
chrome.add_app(NotedeckApp::Notebook(Box::default()));
|
chrome.add_app(NotedeckApp::Notebook(Box::default()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if notedeck.has_option(NotedeckOptions::FeatureClnDash) {
|
||||||
|
chrome.add_app(NotedeckApp::ClnDash(Box::default()));
|
||||||
|
}
|
||||||
|
|
||||||
chrome.set_active(0);
|
chrome.set_active(0);
|
||||||
|
|
||||||
Ok(chrome)
|
Ok(chrome)
|
||||||
@@ -231,16 +234,6 @@ impl Chrome {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notebook(&mut self) -> Option<&mut Notebook> {
|
|
||||||
for app in &mut self.apps {
|
|
||||||
if let NotedeckApp::Notebook(notebook) = app {
|
|
||||||
return Some(notebook);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn switch_to_dave(&mut self) {
|
fn switch_to_dave(&mut self) {
|
||||||
for (i, app) in self.apps.iter().enumerate() {
|
for (i, app) in self.apps.iter().enumerate() {
|
||||||
if let NotedeckApp::Dave(_) = app {
|
if let NotedeckApp::Dave(_) = app {
|
||||||
@@ -249,14 +242,6 @@ impl Chrome {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch_to_notebook(&mut self) {
|
|
||||||
for (i, app) in self.apps.iter().enumerate() {
|
|
||||||
if let NotedeckApp::Notebook(_) = app {
|
|
||||||
self.active = i as i32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn switch_to_columns(&mut self) {
|
fn switch_to_columns(&mut self) {
|
||||||
for (i, app) in self.apps.iter().enumerate() {
|
for (i, app) in self.apps.iter().enumerate() {
|
||||||
if let NotedeckApp::Columns(_) = app {
|
if let NotedeckApp::Columns(_) = app {
|
||||||
@@ -498,32 +483,32 @@ impl Chrome {
|
|||||||
|
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
ui.add(milestone_name(i18n));
|
ui.add(milestone_name(i18n));
|
||||||
ui.add_space(16.0);
|
|
||||||
//let dark_mode = ui.ctx().style().visuals.dark_mode;
|
//let dark_mode = ui.ctx().style().visuals.dark_mode;
|
||||||
if columns_button(ui)
|
|
||||||
.on_hover_cursor(egui::CursorIcon::PointingHand)
|
|
||||||
.clicked()
|
|
||||||
{
|
|
||||||
self.active = 0;
|
|
||||||
}
|
|
||||||
ui.add_space(32.0);
|
|
||||||
|
|
||||||
if let Some(dave) = self.get_dave() {
|
for (i, app) in self.apps.iter_mut().enumerate() {
|
||||||
let rect = dave_sidebar_rect(ui);
|
let r = match app {
|
||||||
let dave_resp = dave_button(dave.avatar_mut(), ui, rect)
|
NotedeckApp::Columns(_columns_app) => columns_button(ui),
|
||||||
.on_hover_cursor(egui::CursorIcon::PointingHand);
|
|
||||||
if dave_resp.clicked() {
|
|
||||||
self.switch_to_dave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//ui.add_space(32.0);
|
|
||||||
|
|
||||||
if let Some(_notebook) = self.get_notebook() {
|
NotedeckApp::Dave(dave) => {
|
||||||
if notebook_button(ui)
|
ui.add_space(24.0);
|
||||||
.on_hover_cursor(egui::CursorIcon::PointingHand)
|
let rect = dave_sidebar_rect(ui);
|
||||||
.clicked()
|
dave_button(dave.avatar_mut(), ui, rect)
|
||||||
{
|
}
|
||||||
self.switch_to_notebook();
|
|
||||||
|
NotedeckApp::ClnDash(_clndash) => clndash_button(ui),
|
||||||
|
|
||||||
|
NotedeckApp::Notebook(_notebook) => notebook_button(ui),
|
||||||
|
|
||||||
|
NotedeckApp::Other(_other) => {
|
||||||
|
// app provides its own button rendering ui?
|
||||||
|
panic!("TODO: implement other apps")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.add_space(4.0);
|
||||||
|
|
||||||
|
if r.on_hover_cursor(egui::CursorIcon::PointingHand).clicked() {
|
||||||
|
self.active = i as i32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -720,6 +705,17 @@ fn accounts_button(ui: &mut egui::Ui) -> egui::Response {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clndash_button(ui: &mut egui::Ui) -> egui::Response {
|
||||||
|
expanding_button(
|
||||||
|
"clndash-button",
|
||||||
|
24.0,
|
||||||
|
app_images::cln_image(),
|
||||||
|
app_images::cln_image(),
|
||||||
|
ui,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn notebook_button(ui: &mut egui::Ui) -> egui::Response {
|
fn notebook_button(ui: &mut egui::Ui) -> egui::Response {
|
||||||
expanding_button(
|
expanding_button(
|
||||||
"notebook-button",
|
"notebook-button",
|
||||||
|
|||||||
15
crates/notedeck_clndash/Cargo.toml
Normal file
15
crates/notedeck_clndash/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "notedeck_clndash"
|
||||||
|
edition = "2024"
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
egui = { workspace = true }
|
||||||
|
notedeck = { workspace = true }
|
||||||
|
#notedeck_ui = { workspace = true }
|
||||||
|
eframe = { workspace = true }
|
||||||
|
lnsocket = "0.3.0"
|
||||||
|
tracing = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
195
crates/notedeck_clndash/src/lib.rs
Normal file
195
crates/notedeck_clndash/src/lib.rs
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
use egui::{Color32, Label, RichText};
|
||||||
|
use lnsocket::bitcoin::secp256k1::{PublicKey, SecretKey, rand};
|
||||||
|
use lnsocket::{CommandoClient, LNSocket};
|
||||||
|
use notedeck::{AppAction, AppContext};
|
||||||
|
use serde_json::{Value, json};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ClnDash {
|
||||||
|
initialized: bool,
|
||||||
|
connection_state: ConnectionState,
|
||||||
|
get_info: Option<String>,
|
||||||
|
channel: Option<Channel>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ConnectionState {
|
||||||
|
fn default() -> Self {
|
||||||
|
ConnectionState::Dead("uninitialized".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Channel {
|
||||||
|
req_tx: UnboundedSender<Request>,
|
||||||
|
event_rx: UnboundedReceiver<Event>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Responses from the socket
|
||||||
|
enum ClnResponse {
|
||||||
|
GetInfo(Result<Value, String>),
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ConnectionState {
|
||||||
|
Dead(String),
|
||||||
|
Connecting,
|
||||||
|
Active,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Request {
|
||||||
|
GetInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Event {
|
||||||
|
/// We lost the socket somehow
|
||||||
|
Ended {
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
Connected,
|
||||||
|
|
||||||
|
Response(ClnResponse),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl notedeck::App for ClnDash {
|
||||||
|
fn update(&mut self, _ctx: &mut AppContext<'_>, ui: &mut egui::Ui) -> Option<AppAction> {
|
||||||
|
if !self.initialized {
|
||||||
|
self.connection_state = ConnectionState::Connecting;
|
||||||
|
self.setup_connection();
|
||||||
|
self.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.process_events();
|
||||||
|
|
||||||
|
self.show(ui);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connection_state_ui(ui: &mut egui::Ui, state: &ConnectionState) {
|
||||||
|
match state {
|
||||||
|
ConnectionState::Active => {
|
||||||
|
ui.add(Label::new(RichText::new("Connected").color(Color32::GREEN)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionState::Connecting => {
|
||||||
|
ui.add(Label::new(
|
||||||
|
RichText::new("Connecting").color(Color32::YELLOW),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionState::Dead(reason) => {
|
||||||
|
ui.add(Label::new(
|
||||||
|
RichText::new(format!("Disconnected: {reason}")).color(Color32::RED),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClnDash {
|
||||||
|
fn show(&mut self, ui: &mut egui::Ui) {
|
||||||
|
egui::Frame::new()
|
||||||
|
.inner_margin(egui::Margin::same(50))
|
||||||
|
.show(ui, |ui| {
|
||||||
|
connection_state_ui(ui, &self.connection_state);
|
||||||
|
|
||||||
|
if let Some(info) = self.get_info.as_ref() {
|
||||||
|
get_info_ui(ui, info);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_connection(&mut self) {
|
||||||
|
let (req_tx, mut req_rx) = unbounded_channel::<Request>();
|
||||||
|
let (event_tx, event_rx) = unbounded_channel::<Event>();
|
||||||
|
self.channel = Some(Channel { req_tx, event_rx });
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let key = SecretKey::new(&mut rand::thread_rng());
|
||||||
|
let their_pubkey = PublicKey::from_str(
|
||||||
|
"03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let lnsocket =
|
||||||
|
match LNSocket::connect_and_init(key, their_pubkey, "ln.damus.io:9735").await {
|
||||||
|
Err(err) => {
|
||||||
|
let _ = event_tx.send(Event::Ended {
|
||||||
|
reason: err.to_string(),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(lnsocket) => {
|
||||||
|
let _ = event_tx.send(Event::Connected);
|
||||||
|
lnsocket
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let rune = "Vns1Zxvidr4J8pP2ZCg3Wjp2SyGyyf5RHgvFG8L36yM9MzMmbWV0aG9kPWdldGluZm8="; // getinfo only atm
|
||||||
|
let commando = CommandoClient::spawn(lnsocket, rune);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match req_rx.recv().await {
|
||||||
|
None => {
|
||||||
|
let _ = event_tx.send(Event::Ended {
|
||||||
|
reason: "channel dead?".to_string(),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(req) => match req {
|
||||||
|
Request::GetInfo => match commando.call("getinfo", json!({})).await {
|
||||||
|
Ok(v) => {
|
||||||
|
let _ = event_tx.send(Event::Response(ClnResponse::GetInfo(Ok(v))));
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let _ = event_tx.send(Event::Ended {
|
||||||
|
reason: err.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_events(&mut self) {
|
||||||
|
let Some(channel) = &mut self.channel else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Ok(event) = channel.event_rx.try_recv() {
|
||||||
|
match event {
|
||||||
|
Event::Ended { reason } => {
|
||||||
|
self.connection_state = ConnectionState::Dead(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::Connected => {
|
||||||
|
self.connection_state = ConnectionState::Active;
|
||||||
|
let _ = channel.req_tx.send(Request::GetInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::Response(resp) => match resp {
|
||||||
|
ClnResponse::GetInfo(value) => {
|
||||||
|
let Ok(value) = value else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(s) = serde_json::to_string_pretty(&value) {
|
||||||
|
self.get_info = Some(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_info_ui(ui: &mut egui::Ui, info: &str) {
|
||||||
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
ui.add(Label::new(info).wrap_mode(egui::TextWrapMode::Wrap));
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -15,6 +15,10 @@ pub fn accounts_image() -> Image<'static> {
|
|||||||
Image::new(include_image!("../../../assets/icons/accounts.png"))
|
Image::new(include_image!("../../../assets/icons/accounts.png"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cln_image() -> Image<'static> {
|
||||||
|
Image::new(include_image!("../../../assets/icons/clnlogo.svg"))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_column_dark_image() -> Image<'static> {
|
pub fn add_column_dark_image() -> Image<'static> {
|
||||||
Image::new(include_image!(
|
Image::new(include_image!(
|
||||||
"../../../assets/icons/add_column_dark_4x.png"
|
"../../../assets/icons/add_column_dark_4x.png"
|
||||||
|
|||||||
Reference in New Issue
Block a user