@@ -73,7 +73,7 @@ impl<'a> AccountLoginView<'a> {
|
|||||||
.rect_filled(top_rect, Rounding::ZERO, top_background_color);
|
.rect_filled(top_rect, Rounding::ZERO, top_background_color);
|
||||||
|
|
||||||
egui::CentralPanel::default()
|
egui::CentralPanel::default()
|
||||||
.show(ui.ctx(), |ui: &mut egui::Ui| {})
|
.show(ui.ctx(), |_ui: &mut egui::Ui| {})
|
||||||
.response
|
.response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
67
src/app.rs
67
src/app.rs
@@ -36,19 +36,19 @@ pub struct NoteRef {
|
|||||||
pub created_at: u64,
|
pub created_at: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for NoteRef {
|
impl Ord for NoteRef {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
match self.created_at.cmp(&other.created_at) {
|
match self.created_at.cmp(&other.created_at) {
|
||||||
Ordering::Equal => self.key.cmp(&other.key).into(),
|
Ordering::Equal => self.key.cmp(&other.key),
|
||||||
Ordering::Less => Some(Ordering::Greater),
|
Ordering::Less => Ordering::Greater,
|
||||||
Ordering::Greater => Some(Ordering::Less),
|
Ordering::Greater => Ordering::Less,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for NoteRef {
|
impl PartialOrd for NoteRef {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
self.partial_cmp(other).unwrap()
|
Some(self.cmp(other))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +60,7 @@ struct Timeline {
|
|||||||
|
|
||||||
impl Timeline {
|
impl Timeline {
|
||||||
pub fn new(filter: Vec<Filter>) -> Self {
|
pub fn new(filter: Vec<Filter>) -> Self {
|
||||||
let mut notes: Vec<NoteRef> = vec![];
|
let notes: Vec<NoteRef> = Vec::with_capacity(1000);
|
||||||
notes.reserve(1000);
|
|
||||||
let subscription: Option<Subscription> = None;
|
let subscription: Option<Subscription> = None;
|
||||||
|
|
||||||
Timeline {
|
Timeline {
|
||||||
@@ -215,9 +214,11 @@ fn get_unknown_note_ids<'a>(
|
|||||||
|
|
||||||
let blocks = ndb.get_blocks_by_key(txn, note_key)?;
|
let blocks = ndb.get_blocks_by_key(txn, note_key)?;
|
||||||
for block in blocks.iter(note) {
|
for block in blocks.iter(note) {
|
||||||
let _blocktype = block.blocktype();
|
if block.blocktype() != BlockType::MentionBech32 {
|
||||||
match block.blocktype() {
|
continue;
|
||||||
BlockType::MentionBech32 => match block.as_mention().unwrap() {
|
}
|
||||||
|
|
||||||
|
match block.as_mention().unwrap() {
|
||||||
Mention::Pubkey(npub) => {
|
Mention::Pubkey(npub) => {
|
||||||
if ndb.get_profile_by_pubkey(txn, npub.pubkey()).is_err() {
|
if ndb.get_profile_by_pubkey(txn, npub.pubkey()).is_err() {
|
||||||
ids.insert(UnknownId::Pubkey(npub.pubkey()));
|
ids.insert(UnknownId::Pubkey(npub.pubkey()));
|
||||||
@@ -253,9 +254,6 @@ fn get_unknown_note_ids<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,15 +273,15 @@ fn poll_notes_for_timeline<'a>(
|
|||||||
return Err(Error::NoActiveSubscription);
|
return Err(Error::NoActiveSubscription);
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_note_ids = damus.ndb.poll_for_notes(&sub, 100);
|
let new_note_ids = damus.ndb.poll_for_notes(sub, 100);
|
||||||
if new_note_ids.len() > 0 {
|
if !new_note_ids.is_empty() {
|
||||||
debug!("{} new notes! {:?}", new_note_ids.len(), new_note_ids);
|
debug!("{} new notes! {:?}", new_note_ids.len(), new_note_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_refs = new_note_ids
|
let new_refs: Vec<NoteRef> = new_note_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|key| {
|
.map(|key| {
|
||||||
let note = damus.ndb.get_note_by_key(&txn, *key).expect("no note??");
|
let note = damus.ndb.get_note_by_key(txn, *key).expect("no note??");
|
||||||
|
|
||||||
let _ = get_unknown_note_ids(&damus.ndb, txn, ¬e, *key, ids);
|
let _ = get_unknown_note_ids(&damus.ndb, txn, ¬e, *key, ids);
|
||||||
|
|
||||||
@@ -310,7 +308,7 @@ fn setup_initial_nostrdb_subs(damus: &mut Damus) -> Result<()> {
|
|||||||
let filters: Vec<nostrdb::Filter> = timeline
|
let filters: Vec<nostrdb::Filter> = timeline
|
||||||
.filter
|
.filter
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| crate::filter::convert_enostr_filter(f))
|
.map(crate::filter::convert_enostr_filter)
|
||||||
.collect();
|
.collect();
|
||||||
timeline.subscription = Some(damus.ndb.subscribe(filters.clone())?);
|
timeline.subscription = Some(damus.ndb.subscribe(filters.clone())?);
|
||||||
let txn = Transaction::new(&damus.ndb)?;
|
let txn = Transaction::new(&damus.ndb)?;
|
||||||
@@ -357,7 +355,7 @@ fn process_event(damus: &mut Damus, _subid: &str, event: &str) {
|
|||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
|
|
||||||
//info!("processing event {}", event);
|
//info!("processing event {}", event);
|
||||||
if let Err(_err) = damus.ndb.process_event(&event) {
|
if let Err(_err) = damus.ndb.process_event(event) {
|
||||||
error!("error processing event {}", event);
|
error!("error processing event {}", event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,7 +368,7 @@ fn get_unknown_ids<'a>(txn: &'a Transaction, damus: &Damus) -> Result<Vec<Unknow
|
|||||||
|
|
||||||
for timeline in &damus.timelines {
|
for timeline in &damus.timelines {
|
||||||
for noteref in &timeline.notes {
|
for noteref in &timeline.notes {
|
||||||
let note = damus.ndb.get_note_by_key(&txn, noteref.key)?;
|
let note = damus.ndb.get_note_by_key(txn, noteref.key)?;
|
||||||
let _ = get_unknown_note_ids(&damus.ndb, txn, ¬e, note.key().unwrap(), &mut ids);
|
let _ = get_unknown_note_ids(&damus.ndb, txn, ¬e, note.key().unwrap(), &mut ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -378,7 +376,7 @@ fn get_unknown_ids<'a>(txn: &'a Transaction, damus: &Damus) -> Result<Vec<Unknow
|
|||||||
Ok(ids.into_iter().collect())
|
Ok(ids.into_iter().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_unknown_ids_filter<'a>(ids: &[UnknownId<'a>]) -> Option<Vec<Filter>> {
|
fn get_unknown_ids_filter(ids: &[UnknownId<'_>]) -> Option<Vec<Filter>> {
|
||||||
if ids.is_empty() {
|
if ids.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -427,11 +425,11 @@ fn handle_eose(damus: &mut Damus, subid: &str, relay_url: &str) -> Result<()> {
|
|||||||
|
|
||||||
fn process_message(damus: &mut Damus, relay: &str, msg: &RelayMessage) {
|
fn process_message(damus: &mut Damus, relay: &str, msg: &RelayMessage) {
|
||||||
match msg {
|
match msg {
|
||||||
RelayMessage::Event(subid, ev) => process_event(damus, &subid, ev),
|
RelayMessage::Event(subid, ev) => process_event(damus, subid, ev),
|
||||||
RelayMessage::Notice(msg) => warn!("Notice from {}: {}", relay, msg),
|
RelayMessage::Notice(msg) => warn!("Notice from {}: {}", relay, msg),
|
||||||
RelayMessage::OK(cr) => info!("OK {:?}", cr),
|
RelayMessage::OK(cr) => info!("OK {:?}", cr),
|
||||||
RelayMessage::Eose(sid) => {
|
RelayMessage::Eose(sid) => {
|
||||||
if let Err(err) = handle_eose(damus, &sid, relay) {
|
if let Err(err) = handle_eose(damus, sid, relay) {
|
||||||
error!("error handling eose: {}", err);
|
error!("error handling eose: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -474,11 +472,11 @@ impl Damus {
|
|||||||
let _initial_limit = 100;
|
let _initial_limit = 100;
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
for arg in &args[1..] {
|
for arg in &args[1..] {
|
||||||
let filter = serde_json::from_str(&arg).unwrap();
|
let filter = serde_json::from_str(arg).unwrap();
|
||||||
timelines.push(Timeline::new(filter));
|
timelines.push(Timeline::new(filter));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let filter = serde_json::from_str(&include_str!("../queries/global.json")).unwrap();
|
let filter = serde_json::from_str(include_str!("../queries/global.json")).unwrap();
|
||||||
timelines.push(Timeline::new(filter));
|
timelines.push(Timeline::new(filter));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -604,11 +602,12 @@ fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn top_panel(ctx: &egui::Context) -> egui::TopBottomPanel {
|
fn top_panel(ctx: &egui::Context) -> egui::TopBottomPanel {
|
||||||
let mut top_margin = Margin::default();
|
let top_margin = egui::Margin {
|
||||||
top_margin.top = 4.0;
|
top: 4.0,
|
||||||
top_margin.left = 8.0;
|
left: 8.0,
|
||||||
top_margin.right = 8.0;
|
right: 8.0,
|
||||||
//top_margin.bottom = -20.0;
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
let frame = Frame {
|
let frame = Frame {
|
||||||
inner_margin: top_margin,
|
inner_margin: top_margin,
|
||||||
@@ -621,7 +620,7 @@ fn top_panel(ctx: &egui::Context) -> egui::TopBottomPanel {
|
|||||||
.show_separator_line(false)
|
.show_separator_line(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_panel<'a>(ctx: &egui::Context, app: &'a mut Damus, timeline_ind: usize) {
|
fn render_panel(ctx: &egui::Context, app: &mut Damus, timeline_ind: usize) {
|
||||||
top_panel(ctx).show(ctx, |ui| {
|
top_panel(ctx).show(ctx, |ui| {
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
|
||||||
ui.visuals_mut().button_frame = false;
|
ui.visuals_mut().button_frame = false;
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ pub enum NamedFontFamily {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NamedFontFamily {
|
impl NamedFontFamily {
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(&mut self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
//Self::Bold => "bold",
|
//Self::Bold => "bold",
|
||||||
Self::Medium => "medium",
|
Self::Medium => "medium",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_family(self) -> egui::FontFamily {
|
pub fn as_family(&mut self) -> egui::FontFamily {
|
||||||
egui::FontFamily::Name(self.as_str().into())
|
egui::FontFamily::Name(self.as_str().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub fn round_image(image: &mut ColorImage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn process_pfp_bitmap(size: u32, image: &mut image::DynamicImage) -> ColorImage {
|
fn process_pfp_bitmap(size: u32, image: &mut image::DynamicImage) -> ColorImage {
|
||||||
#[cfg(features = "profiling")]
|
#[cfg(feature = "profiling")]
|
||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
|
|
||||||
// Crop square
|
// Crop square
|
||||||
@@ -144,7 +144,7 @@ pub fn fetch_img(
|
|||||||
size: u32,
|
size: u32,
|
||||||
) -> Promise<Result<TextureHandle>> {
|
) -> Promise<Result<TextureHandle>> {
|
||||||
let key = ImageCache::key(url);
|
let key = ImageCache::key(url);
|
||||||
let path = img_cache.cache_dir.join(&key);
|
let path = img_cache.cache_dir.join(key);
|
||||||
|
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
fetch_img_from_disk(ctx, url, &path)
|
fetch_img_from_disk(ctx, url, &path)
|
||||||
|
|||||||
@@ -26,8 +26,12 @@ impl ImageCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(cache_dir: &path::Path, url: &str, data: ColorImage) -> Result<()> {
|
pub fn write(cache_dir: &path::Path, url: &str, data: ColorImage) -> Result<()> {
|
||||||
let file_path = cache_dir.join(&Self::key(url));
|
let file_path = cache_dir.join(Self::key(url));
|
||||||
let file = File::options().write(true).create(true).open(file_path)?;
|
let file = File::options()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(file_path)?;
|
||||||
let encoder = image::codecs::webp::WebPEncoder::new_lossless(file);
|
let encoder = image::codecs::webp::WebPEncoder::new_lossless(file);
|
||||||
|
|
||||||
encoder.encode(
|
encoder.encode(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use poll_promise::Promise;
|
|||||||
|
|
||||||
/// Helper storage object for retrieving the plaintext key from the user and converting it into a
|
/// Helper storage object for retrieving the plaintext key from the user and converting it into a
|
||||||
/// nostr-sdk Keys object if possible.
|
/// nostr-sdk Keys object if possible.
|
||||||
|
#[derive(Default)]
|
||||||
pub struct LoginManager {
|
pub struct LoginManager {
|
||||||
pub login_key: String,
|
pub login_key: String,
|
||||||
pub promise: Option<Promise<Result<Keys, LoginError>>>,
|
pub promise: Option<Promise<Result<Keys, LoginError>>>,
|
||||||
@@ -13,11 +14,6 @@ pub struct LoginManager {
|
|||||||
|
|
||||||
impl LoginManager {
|
impl LoginManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
LoginManager {
|
LoginManager::default()
|
||||||
login_key: String::new(),
|
|
||||||
promise: None,
|
|
||||||
error: None,
|
|
||||||
key_on_error: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ impl NoteCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reltime_str(&mut self) -> &str {
|
pub fn reltime_str(&mut self) -> &str {
|
||||||
return &self.reltime.get();
|
return self.reltime.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ pub fn time_ago_since(timestamp: u64) -> String {
|
|||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
.expect("Time went backwards")
|
.expect("Time went backwards")
|
||||||
.as_secs();
|
.as_secs();
|
||||||
let duration = now.checked_sub(timestamp).unwrap_or(0);
|
let duration = now.saturating_sub(timestamp);
|
||||||
|
|
||||||
let years = duration / 31_536_000; // seconds in a year
|
let years = duration / 31_536_000; // seconds in a year
|
||||||
if years >= 1 {
|
if years >= 1 {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
pub fn merge_sorted_vecs<T: Ord + Copy>(vec1: &Vec<T>, vec2: &Vec<T>) -> Vec<T> {
|
pub fn merge_sorted_vecs<T: Ord + Copy>(vec1: &[T], vec2: &[T]) -> Vec<T> {
|
||||||
let mut merged = Vec::with_capacity(vec1.len() + vec2.len());
|
let mut merged = Vec::with_capacity(vec1.len() + vec2.len());
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ fn render_pfp(ui: &mut egui::Ui, damus: &mut Damus, url: &str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pfp_image<'a>(ui: &mut egui::Ui, img: &TextureHandle, size: f32) -> egui::Response {
|
fn pfp_image(ui: &mut egui::Ui, img: &TextureHandle, size: f32) -> egui::Response {
|
||||||
#[cfg(feature = "profiling")]
|
#[cfg(feature = "profiling")]
|
||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
|
|
||||||
|
|||||||
@@ -24,18 +24,18 @@ impl NoteOptions {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_note_previews(&mut self, enable: bool) {
|
pub fn set_note_previews(&mut self, enable: bool) {
|
||||||
if enable {
|
if enable {
|
||||||
*self = *self | NoteOptions::note_previews;
|
*self |= NoteOptions::note_previews;
|
||||||
} else {
|
} else {
|
||||||
*self = *self & !NoteOptions::note_previews;
|
*self &= !NoteOptions::note_previews;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_actionbar(&mut self, enable: bool) {
|
pub fn set_actionbar(&mut self, enable: bool) {
|
||||||
if enable {
|
if enable {
|
||||||
*self = *self | NoteOptions::actionbar;
|
*self |= NoteOptions::actionbar;
|
||||||
} else {
|
} else {
|
||||||
*self = *self & !NoteOptions::actionbar;
|
*self &= !NoteOptions::actionbar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user