mirror of
https://github.com/mikedilger/gossip.git
synced 2024-10-01 09:21:53 +00:00
SVG support
This commit is contained in:
parent
a77eb9abb3
commit
c3e9f8b51f
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1133,6 +1133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1975cd88ff7430f93b29e6b9868b648a8ff6a43b08b9ff8474ee0a648bd8f9a6"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"image",
|
||||
"resvg",
|
||||
"serde",
|
||||
"tiny-skia 0.6.6",
|
||||
|
@ -17,12 +17,12 @@ base64 = "0.20"
|
||||
dashmap = "5.4"
|
||||
dirs = "4.0"
|
||||
eframe = { version = "0.20", features = [ "dark-light", "persistence" ] }
|
||||
egui_extras = { version = "0.20", features = [ "svg", "tracing" ] }
|
||||
egui_extras = { version = "0.20", features = [ "image", "svg", "tracing" ] }
|
||||
futures = "0.3"
|
||||
futures-util = "0.3"
|
||||
hex = "0.4"
|
||||
http = "0.2"
|
||||
image = "0.24"
|
||||
image = { version = "0.24", features = [ "png", "jpeg" ] }
|
||||
lazy_static = "1.4"
|
||||
linkify = "0.9"
|
||||
nostr-types = { git = "https://github.com/mikedilger/nostr-types" }
|
||||
|
@ -130,7 +130,8 @@ pub async fn prune() -> Result<(), Error> {
|
||||
let mut stmt = db.prepare(sql)?;
|
||||
stmt.execute(())?;
|
||||
Ok::<(), Error>(())
|
||||
}).await??;
|
||||
})
|
||||
.await??;
|
||||
|
||||
*GLOBALS.status_message.write().await = "Database prune has completed.".to_owned();
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::db::DbPerson;
|
||||
use crate::error::Error;
|
||||
use crate::globals::GLOBALS;
|
||||
use crate::AVATAR_SIZE;
|
||||
use dashmap::{DashMap, DashSet};
|
||||
use image::RgbaImage;
|
||||
use eframe::egui::ColorImage;
|
||||
use egui_extras::image::FitTo;
|
||||
use nostr_types::{Metadata, PublicKeyHex, Unixtime, Url};
|
||||
use std::cmp::Ordering;
|
||||
use std::time::Duration;
|
||||
@ -15,7 +17,7 @@ pub struct People {
|
||||
// until the UI next asks for them, at which point we remove them
|
||||
// and hand them over. This way we can do the work that takes
|
||||
// longer and the UI can do as little work as possible.
|
||||
avatars_temp: DashMap<PublicKeyHex, RgbaImage>,
|
||||
avatars_temp: DashMap<PublicKeyHex, ColorImage>,
|
||||
avatars_pending_processing: DashSet<PublicKeyHex>,
|
||||
avatars_failed: DashSet<PublicKeyHex>,
|
||||
}
|
||||
@ -264,7 +266,7 @@ impl People {
|
||||
}
|
||||
|
||||
// If returns Err, means you're never going to get it so stop trying.
|
||||
pub fn get_avatar(&self, pubkeyhex: &PublicKeyHex) -> Result<Option<image::RgbaImage>, ()> {
|
||||
pub fn get_avatar(&self, pubkeyhex: &PublicKeyHex) -> Result<Option<ColorImage>, ()> {
|
||||
// If we have it, hand it over (we won't need a copy anymore)
|
||||
if let Some(th) = self.avatars_temp.remove(pubkeyhex) {
|
||||
return Ok(Some(th.1));
|
||||
@ -305,25 +307,31 @@ impl People {
|
||||
match GLOBALS.fetcher.try_get(url) {
|
||||
Ok(None) => Ok(None),
|
||||
Ok(Some(bytes)) => {
|
||||
// Finish this later
|
||||
// Finish this later (spawn)
|
||||
let apubkeyhex = pubkeyhex.to_owned();
|
||||
tokio::spawn(async move {
|
||||
let image = match image::load_from_memory(&bytes) {
|
||||
// DynamicImage
|
||||
Ok(di) => di,
|
||||
Err(_) => {
|
||||
let _ = GLOBALS.people.avatars_failed.insert(apubkeyhex.clone());
|
||||
return;
|
||||
}
|
||||
if let Ok(image) = image::load_from_memory(&bytes) {
|
||||
// Note: we can't use egui_extras::image::load_image_bytes because we
|
||||
// need to force a resize
|
||||
let image = image.resize(
|
||||
AVATAR_SIZE,
|
||||
AVATAR_SIZE,
|
||||
image::imageops::FilterType::Nearest,
|
||||
); // DynamicImage
|
||||
let image_buffer = image.into_rgba8(); // RgbaImage (ImageBuffer)
|
||||
let color_image = ColorImage::from_rgba_unmultiplied(
|
||||
[image_buffer.width() as usize, image_buffer.height() as usize],
|
||||
image_buffer.as_flat_samples().as_slice(),
|
||||
);
|
||||
GLOBALS.people.avatars_temp.insert(apubkeyhex, color_image);
|
||||
} else if let Ok(color_image) = egui_extras::image::load_svg_bytes_with_size(
|
||||
&bytes,
|
||||
FitTo::Size(AVATAR_SIZE, AVATAR_SIZE),
|
||||
) {
|
||||
GLOBALS.people.avatars_temp.insert(apubkeyhex, color_image);
|
||||
} else {
|
||||
GLOBALS.people.avatars_failed.insert(apubkeyhex.clone());
|
||||
};
|
||||
let image = image.resize(
|
||||
crate::AVATAR_SIZE,
|
||||
crate::AVATAR_SIZE,
|
||||
image::imageops::FilterType::Nearest,
|
||||
); // DynamicImage
|
||||
let image_buffer = image.into_rgba8(); // RgbaImage (ImageBuffer)
|
||||
|
||||
GLOBALS.people.avatars_temp.insert(apubkeyhex, image_buffer);
|
||||
});
|
||||
self.avatars_pending_processing.insert(pubkeyhex.to_owned());
|
||||
Ok(None)
|
||||
|
@ -5,8 +5,8 @@ use crate::globals::{Globals, GLOBALS};
|
||||
use crate::ui::widgets::CopyButton;
|
||||
use eframe::egui;
|
||||
use egui::{
|
||||
Align, Color32, Context, Frame, Image, Label, Layout, RichText, ScrollArea, SelectableLabel, Sense,
|
||||
Separator, Stroke, TextEdit, TextStyle, Ui, Vec2,
|
||||
Align, Color32, Context, Frame, Image, Label, Layout, RichText, ScrollArea, SelectableLabel,
|
||||
Sense, Separator, Stroke, TextEdit, TextStyle, Ui, Vec2,
|
||||
};
|
||||
use linkify::{LinkFinder, LinkKind};
|
||||
use nostr_types::{Event, EventKind, Id, IdHex, Tag};
|
||||
@ -533,7 +533,10 @@ fn render_post_actual(
|
||||
|
||||
ui.add_space(24.0);
|
||||
|
||||
if ui.add(Label::new(RichText::new("💬").size(18.0)).sense(Sense::click())).clicked() {
|
||||
if ui
|
||||
.add(Label::new(RichText::new("💬").size(18.0)).sense(Sense::click()))
|
||||
.clicked()
|
||||
{
|
||||
app.replying_to = Some(event.id);
|
||||
|
||||
// Cleanup tags
|
||||
@ -552,7 +555,10 @@ fn render_post_actual(
|
||||
|
||||
ui.add_space(24.0);
|
||||
|
||||
if ui.add(Label::new(RichText::new("♡").size(20.0)).sense(Sense::click())).clicked() {
|
||||
if ui
|
||||
.add(Label::new(RichText::new("♡").size(20.0)).sense(Sense::click()))
|
||||
.clicked()
|
||||
{
|
||||
let _ = GLOBALS
|
||||
.to_overlord
|
||||
.send(ToOverlordMessage::Like(event.id, event.pubkey));
|
||||
|
@ -405,14 +405,9 @@ impl GossipUi {
|
||||
.insert(pubkeyhex.to_owned());
|
||||
None
|
||||
}
|
||||
Ok(Some(rgbaimage)) => {
|
||||
let size = [rgbaimage.width() as _, rgbaimage.height() as _];
|
||||
let pixels = rgbaimage.as_flat_samples();
|
||||
let texture_handle = ctx.load_texture(
|
||||
pubkeyhex.0.clone(),
|
||||
ImageData::Color(ColorImage::from_rgba_unmultiplied(size, pixels.as_slice())),
|
||||
TextureOptions::default(),
|
||||
);
|
||||
Ok(Some(color_image)) => {
|
||||
let texture_handle =
|
||||
ctx.load_texture(pubkeyhex.0.clone(), color_image, TextureOptions::default());
|
||||
self.avatars
|
||||
.insert(pubkeyhex.to_owned(), texture_handle.clone());
|
||||
Some(texture_handle)
|
||||
|
@ -1,6 +1,8 @@
|
||||
use eframe::{egui, epaint};
|
||||
use egui::style::{Selection, Visuals, Widgets};
|
||||
use egui::{Color32, FontData, FontDefinitions, FontFamily, FontId, FontTweak, Rounding, Stroke, TextStyle};
|
||||
use egui::{
|
||||
Color32, FontData, FontDefinitions, FontFamily, FontId, FontTweak, Rounding, Stroke, TextStyle,
|
||||
};
|
||||
use epaint::Shadow;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
@ -141,30 +143,23 @@ pub(super) fn font_definitions() -> FontDefinitions {
|
||||
// Some good looking emojis. Use as first priority:
|
||||
font_data.insert(
|
||||
"NotoEmoji-Regular".to_owned(),
|
||||
FontData::from_static(include_bytes!("../../fonts/NotoEmoji-Regular.ttf"))
|
||||
.tweak(
|
||||
FontTweak {
|
||||
scale: 1.1, // make them a touch larger
|
||||
y_offset_factor: -0.2, // move them up
|
||||
y_offset: 0.0,
|
||||
},
|
||||
)
|
||||
FontData::from_static(include_bytes!("../../fonts/NotoEmoji-Regular.ttf")).tweak(
|
||||
FontTweak {
|
||||
scale: 1.1, // make them a touch larger
|
||||
y_offset_factor: -0.2, // move them up
|
||||
y_offset: 0.0,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
families.insert(
|
||||
FontFamily::Proportional,
|
||||
vec![
|
||||
"DejaVuSans".to_owned(),
|
||||
"NotoEmoji-Regular".to_owned(),
|
||||
],
|
||||
vec!["DejaVuSans".to_owned(), "NotoEmoji-Regular".to_owned()],
|
||||
);
|
||||
|
||||
families.insert(
|
||||
FontFamily::Monospace,
|
||||
vec![
|
||||
"Inconsolata".to_owned(),
|
||||
"NotoEmoji-Regular".to_owned(),
|
||||
],
|
||||
vec!["Inconsolata".to_owned(), "NotoEmoji-Regular".to_owned()],
|
||||
);
|
||||
|
||||
FontDefinitions {
|
||||
|
Loading…
Reference in New Issue
Block a user