wip
This commit is contained in:
parent
0e19c1a8f3
commit
f7021094bc
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -1639,7 +1639,7 @@ checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf"
|
||||
[[package]]
|
||||
name = "enostr"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.v0l.io/nostr/notedeck.git?rev=e08e30f9125b9cf7391e97a2683ba0034bff1644#e08e30f9125b9cf7391e97a2683ba0034bff1644"
|
||||
source = "git+https://github.com/damus-io/notedeck?rev=06417ff69e772f24ffd7fb2b025f879463d8c51f#06417ff69e772f24ffd7fb2b025f879463d8c51f"
|
||||
dependencies = [
|
||||
"bech32",
|
||||
"ewebsock",
|
||||
@ -3023,7 +3023,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "notedeck"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.v0l.io/nostr/notedeck.git?rev=e08e30f9125b9cf7391e97a2683ba0034bff1644#e08e30f9125b9cf7391e97a2683ba0034bff1644"
|
||||
source = "git+https://github.com/damus-io/notedeck?rev=06417ff69e772f24ffd7fb2b025f879463d8c51f#06417ff69e772f24ffd7fb2b025f879463d8c51f"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"dirs",
|
||||
@ -3036,6 +3036,7 @@ dependencies = [
|
||||
"security-framework",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"thiserror 2.0.9",
|
||||
@ -3047,7 +3048,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "notedeck_chrome"
|
||||
version = "0.2.0"
|
||||
source = "git+https://git.v0l.io/nostr/notedeck.git?rev=e08e30f9125b9cf7391e97a2683ba0034bff1644#e08e30f9125b9cf7391e97a2683ba0034bff1644"
|
||||
source = "git+https://github.com/damus-io/notedeck?rev=06417ff69e772f24ffd7fb2b025f879463d8c51f#06417ff69e772f24ffd7fb2b025f879463d8c51f"
|
||||
dependencies = [
|
||||
"android-activity 0.4.3",
|
||||
"eframe",
|
||||
@ -3071,7 +3072,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "notedeck_columns"
|
||||
version = "0.2.0"
|
||||
source = "git+https://git.v0l.io/nostr/notedeck.git?rev=e08e30f9125b9cf7391e97a2683ba0034bff1644#e08e30f9125b9cf7391e97a2683ba0034bff1644"
|
||||
source = "git+https://github.com/damus-io/notedeck?rev=06417ff69e772f24ffd7fb2b025f879463d8c51f#06417ff69e772f24ffd7fb2b025f879463d8c51f"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"dirs",
|
||||
|
@ -26,9 +26,9 @@ egui-video = { git = "https://github.com/v0l/egui-video.git", rev = "d2ea3b4db21
|
||||
# notedeck stuff
|
||||
nostr = { version = "0.37.0", default-features = false, features = ["std", "nip49"] }
|
||||
nostrdb = { git = "https://github.com/damus-io/nostrdb-rs", rev = "2111948b078b24a1659d0bd5d8570f370269c99b" }
|
||||
notedeck-chrome = { git = "https://git.v0l.io/nostr/notedeck.git", rev = "e08e30f9125b9cf7391e97a2683ba0034bff1644", package = "notedeck_chrome", optional = true }
|
||||
notedeck = { git = "https://git.v0l.io/nostr/notedeck.git", rev = "e08e30f9125b9cf7391e97a2683ba0034bff1644", package = "notedeck", optional = true }
|
||||
enostr = { git = "https://git.v0l.io/nostr/notedeck.git", rev = "e08e30f9125b9cf7391e97a2683ba0034bff1644", package = "enostr", optional = true }
|
||||
notedeck-chrome = { git = "https://github.com/damus-io/notedeck", rev = "06417ff69e772f24ffd7fb2b025f879463d8c51f", package = "notedeck_chrome", optional = true }
|
||||
notedeck = { git = "https://github.com/damus-io/notedeck", rev = "06417ff69e772f24ffd7fb2b025f879463d8c51f", package = "notedeck", optional = true }
|
||||
enostr = { git = "https://github.com/damus-io/notedeck", rev = "06417ff69e772f24ffd7fb2b025f879463d8c51f", package = "enostr", optional = true }
|
||||
poll-promise = "0.3.0"
|
||||
ehttp = "0.5.0"
|
||||
|
||||
|
45
src/app.rs
45
src/app.rs
@ -1,14 +1,13 @@
|
||||
use crate::route::{page, RouteServices, RouteType};
|
||||
use crate::profiles::ProfileLoader;
|
||||
use crate::route::{page, RouteAction, RouteServices, RouteType};
|
||||
use crate::widgets::{Header, NostrWidget};
|
||||
use eframe::epaint::{FontFamily, Margin};
|
||||
use eframe::CreationContext;
|
||||
use egui::{Color32, FontData, FontDefinitions, Ui};
|
||||
use enostr::ewebsock::{WsEvent, WsMessage};
|
||||
use egui::{Color32, FontData, FontDefinitions, Theme, Ui, Visuals};
|
||||
use enostr::{PoolEvent, RelayEvent, RelayMessage};
|
||||
use log::{error, info, warn};
|
||||
use nostrdb::Transaction;
|
||||
use nostrdb::{Filter, Transaction};
|
||||
use notedeck::AppContext;
|
||||
use std::ops::Div;
|
||||
use std::sync::mpsc;
|
||||
|
||||
pub struct ZapStreamApp {
|
||||
@ -17,6 +16,7 @@ pub struct ZapStreamApp {
|
||||
routes_tx: mpsc::Sender<RouteType>,
|
||||
|
||||
widget: Box<dyn NostrWidget>,
|
||||
profiles: ProfileLoader,
|
||||
}
|
||||
|
||||
impl ZapStreamApp {
|
||||
@ -34,6 +34,7 @@ impl ZapStreamApp {
|
||||
Self {
|
||||
current: RouteType::HomePage,
|
||||
widget: Box::new(page::HomePage::new()),
|
||||
profiles: ProfileLoader::new(),
|
||||
routes_tx: tx,
|
||||
routes_rx: rx,
|
||||
}
|
||||
@ -59,16 +60,26 @@ impl notedeck::App for ZapStreamApp {
|
||||
}
|
||||
}
|
||||
|
||||
let mut app_frame = egui::containers::Frame::default();
|
||||
let margin = self.frame_margin();
|
||||
// reset theme
|
||||
ui.ctx().set_visuals_of(
|
||||
Theme::Dark,
|
||||
Visuals {
|
||||
panel_fill: Color32::BLACK,
|
||||
override_text_color: Some(Color32::WHITE),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
app_frame.inner_margin = margin;
|
||||
app_frame.stroke.color = Color32::BLACK;
|
||||
let mut app_frame = egui::containers::Frame::default();
|
||||
app_frame.inner_margin = self.frame_margin();
|
||||
|
||||
// handle app state changes
|
||||
while let Ok(r) = self.routes_rx.try_recv() {
|
||||
if let RouteType::Action(a) = r {
|
||||
match a {
|
||||
RouteAction::DemandProfile(p) => {
|
||||
self.profiles.demand(p);
|
||||
}
|
||||
_ => info!("Not implemented"),
|
||||
}
|
||||
} else {
|
||||
@ -91,17 +102,16 @@ impl notedeck::App for ZapStreamApp {
|
||||
egui::CentralPanel::default()
|
||||
.frame(app_frame)
|
||||
.show(ui.ctx(), |ui| {
|
||||
ui.visuals_mut().override_text_color = Some(Color32::WHITE);
|
||||
|
||||
let tx = Transaction::new(ctx.ndb).expect("transaction");
|
||||
// display app
|
||||
ui.vertical(|ui| {
|
||||
let mut svc = RouteServices {
|
||||
router: self.routes_tx.clone(),
|
||||
tx: Transaction::new(ctx.ndb).expect("transaction"),
|
||||
tx: &tx,
|
||||
egui: ui.ctx().clone(),
|
||||
ctx,
|
||||
};
|
||||
Header::new().render(ui, &mut svc);
|
||||
Header::new().render(ui, &mut svc, &tx);
|
||||
if let Err(e) = self.widget.update(&mut svc) {
|
||||
error!("{}", e);
|
||||
}
|
||||
@ -109,6 +119,15 @@ impl notedeck::App for ZapStreamApp {
|
||||
})
|
||||
.response
|
||||
});
|
||||
|
||||
let profiles = self.profiles.next();
|
||||
if !profiles.is_empty() {
|
||||
info!("Profiles: {:?}", profiles);
|
||||
ctx.pool.subscribe(
|
||||
"profiles".to_string(),
|
||||
vec![Filter::new().kinds([0]).authors(&profiles).build()],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,14 +2,15 @@
|
||||
mod android;
|
||||
pub mod app;
|
||||
mod link;
|
||||
mod note_ref;
|
||||
mod note_util;
|
||||
mod note_view;
|
||||
mod profiles;
|
||||
mod route;
|
||||
mod services;
|
||||
mod stream_info;
|
||||
mod theme;
|
||||
mod widgets;
|
||||
mod note_ref;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
use android_activity::AndroidApp;
|
||||
|
30
src/profiles.rs
Normal file
30
src/profiles.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub struct ProfileLoader {
|
||||
queue: HashSet<[u8; 32]>,
|
||||
fetched: HashSet<[u8; 32]>,
|
||||
}
|
||||
|
||||
impl ProfileLoader {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
queue: HashSet::new(),
|
||||
fetched: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn demand(&mut self, pubkey: [u8; 32]) {
|
||||
if self.fetched.contains(&pubkey) {
|
||||
return;
|
||||
}
|
||||
self.queue.insert(pubkey);
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> Vec<[u8; 32]> {
|
||||
let ret: Vec<[u8; 32]> = self.queue.drain().collect();
|
||||
for p in ret.iter() {
|
||||
self.fetched.insert(*p);
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
@ -37,7 +37,8 @@ impl NostrWidget for HomePage {
|
||||
.collect();
|
||||
|
||||
let events_live = NotesView::from_vec(
|
||||
events.iter()
|
||||
events
|
||||
.iter()
|
||||
.filter(|r| matches!(r.status(), StreamStatus::Live))
|
||||
.collect(),
|
||||
);
|
||||
@ -50,7 +51,8 @@ impl NostrWidget for HomePage {
|
||||
.render(ui, services);
|
||||
}
|
||||
let events_planned = NotesView::from_vec(
|
||||
events.iter()
|
||||
events
|
||||
.iter()
|
||||
.filter(|r| matches!(r.status(), StreamStatus::Planned))
|
||||
.collect(),
|
||||
);
|
||||
@ -63,7 +65,8 @@ impl NostrWidget for HomePage {
|
||||
.render(ui, services);
|
||||
}
|
||||
let events_ended = NotesView::from_vec(
|
||||
events.iter()
|
||||
events
|
||||
.iter()
|
||||
.filter(|r| matches!(r.status(), StreamStatus::Ended))
|
||||
.collect(),
|
||||
);
|
||||
|
@ -1,21 +1,18 @@
|
||||
use crate::link::NostrLink;
|
||||
use crate::route::home::HomePage;
|
||||
use crate::route::login::LoginPage;
|
||||
use crate::route::stream::StreamPage;
|
||||
use crate::services::ffmpeg_loader::FfmpegLoader;
|
||||
use crate::widgets::{Header, NostrWidget, PlaceholderRect};
|
||||
use anyhow::{bail, Result};
|
||||
use egui::{Context, Image, Response, TextureHandle, Ui};
|
||||
use egui_inbox::{RequestRepaintTrait, UiInbox, UiInboxSender};
|
||||
use enostr::{EventClientMessage, Note};
|
||||
use egui::load::SizedTexture;
|
||||
use egui::{Context, Image, TextureHandle};
|
||||
use egui_inbox::RequestRepaintTrait;
|
||||
use enostr::EventClientMessage;
|
||||
use itertools::Itertools;
|
||||
use log::{info, warn};
|
||||
use nostr::{ClientMessage, Event, EventBuilder, JsonUtil, Kind, Tag};
|
||||
use nostrdb::{Ndb, NdbProfile, NoteKey, Transaction};
|
||||
use nostr::{Event, EventBuilder, JsonUtil, Kind, Tag};
|
||||
use nostrdb::{NdbProfile, NoteKey, Transaction};
|
||||
use notedeck::{AppContext, ImageCache};
|
||||
use poll_promise::Promise;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
use std::sync::mpsc;
|
||||
use std::task::Poll;
|
||||
|
||||
mod home;
|
||||
mod login;
|
||||
@ -46,12 +43,14 @@ pub enum RouteType {
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum RouteAction {}
|
||||
pub enum RouteAction {
|
||||
DemandProfile([u8; 32]),
|
||||
}
|
||||
|
||||
pub struct RouteServices<'a, 'ctx> {
|
||||
pub router: mpsc::Sender<RouteType>,
|
||||
pub tx: Transaction,
|
||||
pub egui: Context,
|
||||
pub tx: &'a Transaction,
|
||||
pub ctx: &'a mut AppContext<'ctx>,
|
||||
}
|
||||
|
||||
@ -82,8 +81,17 @@ impl<'a, 'ctx> RouteServices<'a, 'ctx> {
|
||||
|
||||
/// Load/Fetch profiles
|
||||
pub fn profile(&self, pk: &[u8; 32]) -> Option<NdbProfile<'a>> {
|
||||
// TODO
|
||||
None
|
||||
let p = self
|
||||
.ctx
|
||||
.ndb
|
||||
.get_profile_by_pubkey(self.tx, pk)
|
||||
.map(|p| p.record().profile())
|
||||
.ok()
|
||||
.flatten();
|
||||
if p.is_none() {
|
||||
self.action(RouteAction::DemandProfile(pk.clone()));
|
||||
}
|
||||
p
|
||||
}
|
||||
|
||||
/// Load image from URL
|
||||
@ -116,14 +124,18 @@ impl<'a, 'ctx> RouteServices<'a, 'ctx> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
const BLACK_PIXEL: [u8; 4] = [0, 0, 0, 0];
|
||||
pub fn image_from_cache<'a>(img_cache: &mut ImageCache, ctx: &Context, url: &str) -> Image<'a> {
|
||||
let m_cached_promise = img_cache.map().get(url);
|
||||
if m_cached_promise.is_none() {
|
||||
if let Some(promise) = img_cache.map().get(url) {
|
||||
match promise.poll() {
|
||||
Poll::Ready(Ok(t)) => Image::new(SizedTexture::from_handle(t)),
|
||||
_ => Image::from_bytes(url.to_string(), &BLACK_PIXEL),
|
||||
}
|
||||
} else {
|
||||
let fetch = fetch_img(img_cache, ctx, url);
|
||||
img_cache.map_mut().insert(url.to_string(), fetch);
|
||||
Image::from_bytes(url.to_string(), &BLACK_PIXEL)
|
||||
}
|
||||
Image::new(url.to_string())
|
||||
}
|
||||
|
||||
fn fetch_img(
|
||||
@ -137,7 +149,8 @@ fn fetch_img(
|
||||
let ctx = ctx.clone();
|
||||
let url = url.to_owned();
|
||||
let dst_path = dst_path.clone();
|
||||
Promise::spawn_async(async move {
|
||||
Promise::spawn_blocking(move || {
|
||||
info!("Loading image from disk: {}", dst_path.display());
|
||||
match FfmpegLoader::new().load_image(dst_path) {
|
||||
Ok(img) => Ok(ctx.load_texture(&url, img, Default::default())),
|
||||
Err(e) => Err(notedeck::Error::Generic(e.to_string())),
|
||||
@ -159,12 +172,18 @@ fn fetch_img_from_net(
|
||||
let cloned_url = url.to_owned();
|
||||
let cache_path = cache_path.to_owned();
|
||||
ehttp::fetch(request, move |response| {
|
||||
let handle = response.map_err(notedeck::Error::Generic).map(|img| {
|
||||
std::fs::write(&cache_path, &img.bytes).unwrap();
|
||||
let img_loaded = FfmpegLoader::new().load_image(cache_path).unwrap();
|
||||
let handle = response
|
||||
.and_then(|img| {
|
||||
std::fs::create_dir_all(cache_path.parent().unwrap()).unwrap();
|
||||
std::fs::write(&cache_path, &img.bytes).unwrap();
|
||||
info!("Loading image from net: {}", cloned_url);
|
||||
let img_loaded = FfmpegLoader::new()
|
||||
.load_image(cache_path)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
ctx.load_texture(&cloned_url, img_loaded, Default::default())
|
||||
});
|
||||
Ok(ctx.load_texture(&cloned_url, img_loaded, Default::default()))
|
||||
})
|
||||
.map_err(notedeck::Error::Generic);
|
||||
|
||||
sender.send(handle);
|
||||
ctx.request_repaint();
|
||||
|
@ -6,7 +6,7 @@ use crate::widgets::{
|
||||
sub_or_poll, Chat, NostrWidget, PlaceholderRect, StreamPlayer, StreamTitle, WriteChat,
|
||||
};
|
||||
use egui::{vec2, Align, Frame, Layout, Response, Stroke, Ui, Vec2, Widget};
|
||||
use nostrdb::{Filter, Note, NoteKey, Subscription};
|
||||
use nostrdb::{Filter, Note, Subscription};
|
||||
|
||||
use crate::note_ref::NoteRef;
|
||||
use std::borrow::Borrow;
|
||||
@ -14,7 +14,6 @@ use std::collections::HashSet;
|
||||
|
||||
pub struct StreamPage {
|
||||
link: NostrLink,
|
||||
event: Option<NoteKey>,
|
||||
player: Option<StreamPlayer>,
|
||||
chat: Option<Chat>,
|
||||
new_msg: WriteChat,
|
||||
@ -28,7 +27,6 @@ impl StreamPage {
|
||||
Self {
|
||||
new_msg: WriteChat::new(link.clone()),
|
||||
link,
|
||||
event: None,
|
||||
chat: None,
|
||||
player: None,
|
||||
events: HashSet::new(),
|
||||
@ -146,7 +144,11 @@ impl StreamPage {
|
||||
|
||||
impl NostrWidget for StreamPage {
|
||||
fn render(&mut self, ui: &mut Ui, services: &mut RouteServices<'_, '_>) -> Response {
|
||||
let events: Vec<Note> = vec![];
|
||||
let events: Vec<Note> = self
|
||||
.events
|
||||
.iter()
|
||||
.map_while(|e| services.ctx.ndb.get_note_by_key(services.tx, e.key).ok())
|
||||
.collect();
|
||||
|
||||
if let Some(event) = events.first() {
|
||||
if let Some(stream) = event.stream() {
|
||||
@ -173,14 +175,14 @@ impl NostrWidget for StreamPage {
|
||||
}
|
||||
|
||||
fn update(&mut self, services: &mut RouteServices<'_, '_>) -> anyhow::Result<()> {
|
||||
let filt = self.get_filters();
|
||||
let filters = self.get_filters();
|
||||
sub_or_poll(
|
||||
services.ctx.ndb,
|
||||
&services.tx,
|
||||
&mut services.ctx.pool,
|
||||
&mut self.events,
|
||||
&mut self.sub,
|
||||
filt,
|
||||
filters,
|
||||
)?;
|
||||
if let Some(c) = self.chat.as_mut() {
|
||||
c.update(services)?;
|
||||
|
@ -17,11 +17,7 @@ impl FfmpegLoader {
|
||||
Self::load_image_from_demuxer(demux)
|
||||
}
|
||||
|
||||
pub fn load_image_bytes(
|
||||
&self,
|
||||
key: &str,
|
||||
data: &'static [u8],
|
||||
) -> Result<ColorImage, Error> {
|
||||
pub fn load_image_bytes(&self, key: &str, data: &'static [u8]) -> Result<ColorImage, Error> {
|
||||
let demux = Demuxer::new_custom_io(data, Some(key.to_string()))?;
|
||||
Self::load_image_from_demuxer(demux)
|
||||
}
|
||||
@ -57,6 +53,7 @@ impl FfmpegLoader {
|
||||
av_frame_free(&mut frame);
|
||||
|
||||
let image = video_frame_to_image(frame_rgb);
|
||||
av_packet_free(&mut pkt);
|
||||
return Ok(image);
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ impl NostrWidget for Chat {
|
||||
let stream = services
|
||||
.ctx
|
||||
.ndb
|
||||
.get_note_by_key(&services.tx, self.stream)
|
||||
.get_note_by_key(services.tx, self.stream)
|
||||
.unwrap();
|
||||
|
||||
ScrollArea::vertical()
|
||||
@ -55,9 +55,10 @@ impl NostrWidget for Chat {
|
||||
.sorted_by(|a, b| a.created_at.cmp(&b.created_at))
|
||||
{
|
||||
if let Ok(ev) =
|
||||
services.ctx.ndb.get_note_by_key(&services.tx, ev.key)
|
||||
services.ctx.ndb.get_note_by_key(services.tx, ev.key)
|
||||
{
|
||||
ChatMessage::new(&stream, &ev, &None)
|
||||
let profile = services.profile(ev.pubkey());
|
||||
ChatMessage::new(&stream, &ev, &profile)
|
||||
.render(ui, services.ctx.img_cache);
|
||||
}
|
||||
}
|
||||
@ -72,7 +73,7 @@ impl NostrWidget for Chat {
|
||||
let filters = vec![self.get_filter()];
|
||||
sub_or_poll(
|
||||
services.ctx.ndb,
|
||||
&services.tx,
|
||||
services.tx,
|
||||
&mut services.ctx.pool,
|
||||
&mut self.events,
|
||||
&mut self.sub,
|
||||
|
@ -33,7 +33,9 @@ impl<'a> ChatMessage<'a> {
|
||||
job.wrap.break_anywhere = true;
|
||||
|
||||
let is_host = self.stream.host().eq(self.ev.pubkey());
|
||||
let name = self.profile.map_or("Nostrich", |f| f.name().map_or("Nostrich", |f| f));
|
||||
let name = self
|
||||
.profile
|
||||
.map_or("Nostrich", |f| f.name().map_or("Nostrich", |f| f));
|
||||
|
||||
let name_color = if is_host { PRIMARY } else { NEUTRAL_500 };
|
||||
|
||||
|
@ -4,6 +4,7 @@ use crate::widgets::{Button, NostrWidget};
|
||||
use eframe::emath::Align;
|
||||
use eframe::epaint::Vec2;
|
||||
use egui::{CursorIcon, Frame, Layout, Margin, Response, Sense, Ui, Widget};
|
||||
use nostrdb::Transaction;
|
||||
|
||||
pub struct Header;
|
||||
|
||||
@ -11,10 +12,12 @@ impl Header {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl NostrWidget for Header {
|
||||
fn render(&mut self, ui: &mut Ui, services: &mut RouteServices<'_, '_>) -> Response {
|
||||
pub fn render(
|
||||
&mut self,
|
||||
ui: &mut Ui,
|
||||
services: &mut RouteServices<'_, '_>,
|
||||
tx: &Transaction,
|
||||
) -> Response {
|
||||
let logo_bytes = include_bytes!("../resources/logo.svg");
|
||||
Frame::none()
|
||||
.outer_margin(Margin::symmetric(16., 8.))
|
||||
@ -37,7 +40,8 @@ impl NostrWidget for Header {
|
||||
|
||||
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
|
||||
if let Some(acc) = services.ctx.accounts.get_selected_account() {
|
||||
Avatar::pubkey(&acc.pubkey, services.ctx.ndb, &services.tx).render(ui, services.ctx.img_cache);
|
||||
Avatar::pubkey(&acc.pubkey, services.ctx.ndb, tx)
|
||||
.render(ui, services.ctx.img_cache);
|
||||
} else if Button::new().show(ui, |ui| ui.label("Login")).clicked() {
|
||||
services.navigate(RouteType::LoginPage);
|
||||
}
|
||||
@ -47,8 +51,4 @@ impl NostrWidget for Header {
|
||||
})
|
||||
.response
|
||||
}
|
||||
|
||||
fn update(&mut self, _services: &mut RouteServices<'_, '_>) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,8 @@ impl<'a> StreamEvent<'a> {
|
||||
pub fn new(event: &'a Note<'a>) -> Self {
|
||||
Self { event }
|
||||
}
|
||||
}
|
||||
impl NostrWidget for StreamEvent<'_> {
|
||||
fn render(&mut self, ui: &mut Ui, services: &mut RouteServices<'_, '_>) -> Response {
|
||||
|
||||
pub fn render(&mut self, ui: &mut Ui, services: &mut RouteServices<'_, '_>) -> Response {
|
||||
ui.vertical(|ui| {
|
||||
ui.style_mut().spacing.item_spacing = Vec2::new(12., 16.);
|
||||
|
||||
@ -127,8 +126,4 @@ impl NostrWidget for StreamEvent<'_> {
|
||||
})
|
||||
.response
|
||||
}
|
||||
|
||||
fn update(&mut self, _services: &mut RouteServices<'_, '_>) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -13,10 +13,7 @@ impl<'a> StreamTitle<'a> {
|
||||
pub fn new(event: &'a Note<'a>) -> StreamTitle<'a> {
|
||||
StreamTitle { event }
|
||||
}
|
||||
}
|
||||
|
||||
impl NostrWidget for StreamTitle<'_> {
|
||||
fn render(&mut self, ui: &mut Ui, services: &mut RouteServices<'_, '_>) -> Response {
|
||||
pub fn render(&mut self, ui: &mut Ui, services: &mut RouteServices<'_, '_>) -> Response {
|
||||
Frame::none()
|
||||
.outer_margin(Margin::symmetric(12., 8.))
|
||||
.show(ui, |ui| {
|
||||
@ -43,8 +40,4 @@ impl NostrWidget for StreamTitle<'_> {
|
||||
})
|
||||
.response
|
||||
}
|
||||
|
||||
fn update(&mut self, _services: &mut RouteServices<'_, '_>) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,10 @@
|
||||
use crate::link::NostrLink;
|
||||
use crate::route::RouteServices;
|
||||
use crate::theme::{MARGIN_DEFAULT, NEUTRAL_900, ROUNDING_DEFAULT};
|
||||
use crate::widgets::{NativeTextInput, NostrWidget};
|
||||
use crate::widgets::NativeTextInput;
|
||||
use eframe::emath::Align;
|
||||
use egui::{Frame, Layout, Response, Sense, Ui, Widget};
|
||||
use log::info;
|
||||
use nostrdb::Filter;
|
||||
use notedeck::AppContext;
|
||||
|
||||
pub struct WriteChat {
|
||||
link: NostrLink,
|
||||
@ -20,10 +18,8 @@ impl WriteChat {
|
||||
msg: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NostrWidget for WriteChat {
|
||||
fn render(&mut self, ui: &mut Ui, services: &mut RouteServices<'_, '_>) -> Response {
|
||||
pub fn render(&mut self, ui: &mut Ui, services: &mut RouteServices<'_, '_>) -> Response {
|
||||
let logo_bytes = include_bytes!("../resources/send-03.svg");
|
||||
Frame::none()
|
||||
.inner_margin(MARGIN_DEFAULT)
|
||||
@ -52,8 +48,4 @@ impl NostrWidget for WriteChat {
|
||||
})
|
||||
.response
|
||||
}
|
||||
|
||||
fn update(&mut self, _services: &mut RouteServices<'_, '_>) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user