From 35d2514c8ab49aa8bd487cb0addea15f16f6567a Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Tue, 3 Jan 2023 18:37:25 +1300 Subject: [PATCH] Likes --- src/overlord/minion/handle_websocket.rs | 4 +- src/overlord/mod.rs | 70 +++++++++++++ src/ui/feed.rs | 46 +++++---- src/ui/widgets/copy_button.rs | 4 +- src/ui/widgets/like_button.rs | 128 ++++++++++++++++++++++++ src/ui/widgets/mod.rs | 3 + src/ui/widgets/reply_button.rs | 4 +- 7 files changed, 230 insertions(+), 29 deletions(-) create mode 100644 src/ui/widgets/like_button.rs diff --git a/src/overlord/minion/handle_websocket.rs b/src/overlord/minion/handle_websocket.rs index 48ed5b78..58f3913a 100644 --- a/src/overlord/minion/handle_websocket.rs +++ b/src/overlord/minion/handle_websocket.rs @@ -31,8 +31,7 @@ impl Minion { tracing::debug!("{}: {}: NEW EVENT", &self.url, handle); // Try processing everything immediately - crate::process::process_new_event(&event, true, Some(self.url.clone())) - .await?; + crate::process::process_new_event(&event, true, Some(self.url.clone())).await?; /* if event.kind == EventKind::TextNote { @@ -48,7 +47,6 @@ impl Minion { .await?; } */ - } } RelayMessage::Notice(msg) => { diff --git a/src/overlord/mod.rs b/src/overlord/mod.rs index 930f8725..583d6d43 100644 --- a/src/overlord/mod.rs +++ b/src/overlord/mod.rs @@ -505,6 +505,11 @@ impl Overlord { serde_json::from_str(&bus_message.json_payload)?; self.post_reply(content, reply_to).await?; } + "like" => { + let (id, pubkey): (Id, PublicKey) = + serde_json::from_str(&bus_message.json_payload)?; + self.post_like(id, pubkey).await?; + } "process_incoming_events" => { // Clear new events GLOBALS.event_is_new.write().await.clear(); @@ -852,4 +857,69 @@ impl Overlord { Ok(()) } + + async fn post_like(&mut self, id: Id, pubkey: PublicKey) -> Result<(), Error> { + let event = { + let public_key = match GLOBALS.signer.read().await.public_key() { + Some(pk) => pk, + None => { + tracing::warn!("No public key! Not posting"); + return Ok(()); + } + }; + + let pre_event = PreEvent { + pubkey: public_key, + created_at: Unixtime::now().unwrap(), + kind: EventKind::Reaction, + tags: vec![ + Tag::Event { + id, + recommended_relay_url: DbRelay::recommended_relay_for_reply(id).await?, + marker: None, + }, + Tag::Pubkey { + pubkey, + recommended_relay_url: None, + petname: None, + }, + ], + content: "+".to_owned(), + ots: None, + }; + + let powint = GLOBALS.settings.read().await.pow; + let pow = if powint > 0 { Some(powint) } else { None }; + GLOBALS.signer.read().await.sign_preevent(pre_event, pow)? + }; + + let relays: Vec = GLOBALS + .relays + .read() + .await + .iter() + .filter_map(|(_, r)| if r.post { Some(r.to_owned()) } else { None }) + .collect(); + + for relay in relays { + // Start a minion for it, if there is none + if !self.urls_watching.contains(&Url::new(&relay.url)) { + self.start_minion(relay.url.clone()).await?; + } + + // Send it the event to post + tracing::debug!("Asking {} to post", &relay.url); + + let _ = self.to_minions.send(BusMessage { + target: relay.url.clone(), + kind: "post_event".to_string(), + json_payload: serde_json::to_string(&event).unwrap(), + }); + } + + // Process the message for ourself + crate::process::process_new_event(&event, false, None).await?; + + Ok(()) + } } diff --git a/src/ui/feed.rs b/src/ui/feed.rs index 0d3e1510..ef03413a 100644 --- a/src/ui/feed.rs +++ b/src/ui/feed.rs @@ -2,7 +2,7 @@ use super::{GossipUi, Page}; use crate::comms::BusMessage; use crate::feed::FeedKind; use crate::globals::{Globals, GLOBALS}; -use crate::ui::widgets::{CopyButton, ReplyButton}; +use crate::ui::widgets::{CopyButton, LikeButton, ReplyButton}; use eframe::egui; use egui::{ Align, Color32, Context, Frame, Image, Layout, RichText, ScrollArea, SelectableLabel, Sense, @@ -453,27 +453,6 @@ fn render_post_actual( }); }); - // Second row - ui.horizontal(|ui| { - for (ch, count) in reactions.iter() { - if *ch == '+' { - ui.label( - RichText::new(format!("{} {}", ch, count)) - .strong() - .color(Color32::DARK_GREEN), - ); - } else if *ch == '-' { - ui.label( - RichText::new(format!("{} {}", ch, count)) - .strong() - .color(Color32::DARK_RED), - ); - } else { - ui.label(RichText::new(format!("{} {}", ch, count)).strong()); - } - } - }); - render_content(ui, &event.content); // Under row @@ -488,6 +467,29 @@ fn render_post_actual( if ui.add(ReplyButton {}).clicked() { app.replying_to = Some(event.id); } + + ui.add_space(24.0); + + if ui.add(LikeButton {}).clicked() { + let tx = GLOBALS.to_overlord.clone(); + let _ = tx.send(BusMessage { + target: "overlord".to_string(), + kind: "like".to_string(), + json_payload: serde_json::to_string(&(&event.id, &event.pubkey)) + .unwrap(), + }); + } + for (ch, count) in reactions.iter() { + if *ch == '+' { + ui.label(format!("{}", count)); + } + } + ui.add_space(12.0); + for (ch, count) in reactions.iter() { + if *ch != '+' { + ui.label(RichText::new(format!("{} {}", ch, count)).strong()); + } + } }); } }); diff --git a/src/ui/widgets/copy_button.rs b/src/ui/widgets/copy_button.rs index 8fd79f8f..d957b760 100644 --- a/src/ui/widgets/copy_button.rs +++ b/src/ui/widgets/copy_button.rs @@ -74,8 +74,8 @@ impl Widget for CopyButton { fn ui(self, ui: &mut Ui) -> Response { let padding = ui.spacing().button_padding; let space = Vec2 { - x: 12.0 + padding.x * 2.0, - y: 12.0 + padding.y * 2.0, + x: 16.0 + padding.x * 2.0, + y: 16.0 + padding.y * 2.0, }; let (id, rect) = ui.allocate_space(space); let response = ui.interact(rect, id, Sense::click()); diff --git a/src/ui/widgets/like_button.rs b/src/ui/widgets/like_button.rs new file mode 100644 index 00000000..c31e7976 --- /dev/null +++ b/src/ui/widgets/like_button.rs @@ -0,0 +1,128 @@ +use eframe::{egui, epaint}; +use egui::{Color32, Pos2, Response, Sense, Shape, Ui, Vec2, Widget}; +use epaint::{PathShape, Stroke}; + +pub struct LikeButton {} + +impl LikeButton { + fn paint(ui: &mut Ui, corner: Pos2) { + ui.painter().add(Shape::Path(PathShape { + points: vec![ + Pos2 { + x: corner.x + 8.0, + y: corner.y + 16.0, + }, + Pos2 { + x: corner.x + 9.0, + y: corner.y + 15.0, + }, + Pos2 { + x: corner.x + 12.0, + y: corner.y + 13.0, + }, + Pos2 { + x: corner.x + 15.0, + y: corner.y + 9.0, + }, + Pos2 { + x: corner.x + 16.0, + y: corner.y + 6.0, + }, + Pos2 { + x: corner.x + 16.0, + y: corner.y + 4.0, + }, + Pos2 { + x: corner.x + 15.0, + y: corner.y + 2.0, + }, + Pos2 { + x: corner.x + 13.0, + y: corner.y + 0.0, + }, + Pos2 { + x: corner.x + 12.0, + y: corner.y + 0.0, + }, + Pos2 { + x: corner.x + 10.0, + y: corner.y + 1.0, + }, + Pos2 { + x: corner.x + 8.0, + y: corner.y + 3.0, + }, + Pos2 { + x: corner.x + 6.0, + y: corner.y + 1.0, + }, + Pos2 { + x: corner.x + 4.0, + y: corner.y + 0.0, + }, + Pos2 { + x: corner.x + 3.0, + y: corner.y + 0.0, + }, + Pos2 { + x: corner.x + 1.0, + y: corner.y + 2.0, + }, + Pos2 { + x: corner.x + 0.0, + y: corner.y + 4.0, + }, + Pos2 { + x: corner.x + 0.0, + y: corner.y + 6.0, + }, + Pos2 { + x: corner.x + 1.0, + y: corner.y + 9.0, + }, + Pos2 { + x: corner.x + 4.0, + y: corner.y + 13.0, + }, + Pos2 { + x: corner.x + 7.0, + y: corner.y + 15.0, + }, + Pos2 { + x: corner.x + 8.0, + y: corner.y + 16.0, + }, + ], + closed: true, + fill: Color32::TRANSPARENT, + stroke: Stroke { + width: 1.0, + color: Color32::from_rgb(0x8d, 0x7f, 0x73), + }, + })); + } +} + +impl Widget for LikeButton { + fn ui(self, ui: &mut Ui) -> Response { + let padding = ui.spacing().button_padding; + let space = Vec2 { + x: 16.0 + padding.x * 2.0, + y: 16.0 + padding.y * 2.0, + }; + let (id, rect) = ui.allocate_space(space); + let response = ui.interact(rect, id, Sense::click()); + let shift = if response.is_pointer_button_down_on() { + 2.0 + } else { + 0.0 + }; + let pos = Pos2 { + x: rect.min.x + padding.x + shift, + y: rect.min.y + padding.y + shift, + }; + Self::paint(ui, ui.painter().round_pos_to_pixels(pos)); + + response + } +} diff --git a/src/ui/widgets/mod.rs b/src/ui/widgets/mod.rs index 21099bf3..4cd87d32 100644 --- a/src/ui/widgets/mod.rs +++ b/src/ui/widgets/mod.rs @@ -3,3 +3,6 @@ pub use copy_button::CopyButton; mod reply_button; pub use reply_button::ReplyButton; + +mod like_button; +pub use like_button::LikeButton; diff --git a/src/ui/widgets/reply_button.rs b/src/ui/widgets/reply_button.rs index 71abb16a..040a8d74 100644 --- a/src/ui/widgets/reply_button.rs +++ b/src/ui/widgets/reply_button.rs @@ -71,8 +71,8 @@ impl Widget for ReplyButton { fn ui(self, ui: &mut Ui) -> Response { let padding = ui.spacing().button_padding; let space = Vec2 { - x: 12.0 + padding.x * 2.0, - y: 12.0 + padding.y * 2.0, + x: 16.0 + padding.x * 2.0, + y: 16.0 + padding.y * 2.0, }; let (id, rect) = ui.allocate_space(space); let response = ui.interact(rect, id, Sense::click());