mirror of
https://github.com/mikedilger/gossip.git
synced 2024-10-01 09:21:53 +00:00
highlight npub/etc references in the textarea.
This commit is contained in:
parent
f86cba1626
commit
4f97237049
23
Cargo.lock
generated
23
Cargo.lock
generated
@ -1712,6 +1712,7 @@ dependencies = [
|
||||
"image",
|
||||
"lazy_static",
|
||||
"linkify",
|
||||
"memoize",
|
||||
"nostr-types",
|
||||
"parking_lot",
|
||||
"rand 0.8.5",
|
||||
@ -2191,6 +2192,28 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoize"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c25d125e4063f313300d87c8f658e5b3d69257095df9a4221c12ba50b0421bff"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"memoize-inner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoize-inner"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8b7d5160e6ffcc59d4c571c38238ec5b7065bc91a5a24f511988dabcddda723"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.16"
|
||||
|
@ -25,6 +25,7 @@ http = "0.2"
|
||||
image = { version = "0.24", features = [ "png", "jpeg" ] }
|
||||
lazy_static = "1.4"
|
||||
linkify = "0.9"
|
||||
memoize = "0.3"
|
||||
nostr-types = { git = "https://github.com/mikedilger/nostr-types" }
|
||||
parking_lot = "0.12"
|
||||
rand = "0.8"
|
||||
|
75
src/tags.rs
75
src/tags.rs
@ -1,4 +1,9 @@
|
||||
use crate::db::DbRelay;
|
||||
use eframe::epaint::{
|
||||
text::{LayoutJob, TextFormat},
|
||||
Color32, FontFamily, FontId,
|
||||
};
|
||||
use memoize::memoize;
|
||||
use nostr_types::{Id, PublicKey, PublicKeyHex, Tag};
|
||||
|
||||
pub fn keys_from_text(text: &str) -> Vec<(String, PublicKey)> {
|
||||
@ -87,6 +92,76 @@ pub async fn add_event_to_tags(existing_tags: &mut Vec<Tag>, added: Id, marker:
|
||||
}
|
||||
}
|
||||
|
||||
enum HighlightType {
|
||||
Nothing,
|
||||
PublicKey,
|
||||
Event,
|
||||
}
|
||||
|
||||
#[memoize]
|
||||
pub fn textarea_highlighter(text: String) -> LayoutJob {
|
||||
let mut job = LayoutJob::default();
|
||||
|
||||
let ids = notes_from_text(&text);
|
||||
let pks = keys_from_text(&text);
|
||||
|
||||
// we will gather indices such that we can split the text in chunks
|
||||
let mut indices: Vec<(usize, HighlightType)> = vec![];
|
||||
for pk in pks {
|
||||
for m in text.match_indices(&pk.0) {
|
||||
indices.push((m.0, HighlightType::Nothing));
|
||||
indices.push((m.0 + pk.0.len(), HighlightType::PublicKey));
|
||||
}
|
||||
}
|
||||
for id in ids {
|
||||
for m in text.match_indices(&id.0) {
|
||||
indices.push((m.0, HighlightType::Nothing));
|
||||
indices.push((m.0 + id.0.len(), HighlightType::Event));
|
||||
}
|
||||
}
|
||||
indices.sort_by_key(|x| x.0);
|
||||
indices.dedup_by_key(|x| x.0);
|
||||
|
||||
// add a breakpoint at the end if it doesn't exist
|
||||
if indices.is_empty() || indices[indices.len() - 1].0 != text.len() {
|
||||
indices.push((text.len(), HighlightType::Nothing));
|
||||
}
|
||||
|
||||
// now we will add each chunk back to the textarea with custom formatting
|
||||
let mut curr = 0;
|
||||
for (index, highlight) in indices {
|
||||
let chunk = &text[curr..index];
|
||||
|
||||
job.append(
|
||||
chunk,
|
||||
0.0,
|
||||
match highlight {
|
||||
HighlightType::Nothing => TextFormat {
|
||||
font_id: FontId::new(14.0, FontFamily::Proportional),
|
||||
color: Color32::BLACK,
|
||||
..Default::default()
|
||||
},
|
||||
HighlightType::PublicKey => TextFormat {
|
||||
font_id: FontId::new(16.0, FontFamily::Monospace),
|
||||
background: Color32::LIGHT_GRAY,
|
||||
color: Color32::DARK_GREEN,
|
||||
..Default::default()
|
||||
},
|
||||
HighlightType::Event => TextFormat {
|
||||
font_id: FontId::new(16.0, FontFamily::Monospace),
|
||||
background: Color32::LIGHT_GRAY,
|
||||
color: Color32::DARK_RED,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
curr = index;
|
||||
}
|
||||
|
||||
job
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -2,7 +2,7 @@ use super::{GossipUi, Page};
|
||||
use crate::comms::ToOverlordMessage;
|
||||
use crate::feed::FeedKind;
|
||||
use crate::globals::{Globals, GLOBALS};
|
||||
use crate::tags::keys_from_text;
|
||||
use crate::tags::{keys_from_text, textarea_highlighter};
|
||||
use crate::ui::widgets::CopyButton;
|
||||
use crate::AVATAR_SIZE_F32;
|
||||
use eframe::egui;
|
||||
@ -185,11 +185,18 @@ fn real_posting_area(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
||||
});
|
||||
|
||||
// Text area
|
||||
let mut layouter = |ui: &Ui, text: &str, wrap_width: f32| {
|
||||
let mut layout_job = textarea_highlighter(text.to_owned());
|
||||
layout_job.wrap.max_width = wrap_width;
|
||||
ui.fonts().layout_job(layout_job)
|
||||
};
|
||||
|
||||
ui.add(
|
||||
TextEdit::multiline(&mut app.draft)
|
||||
.hint_text("Type your message here")
|
||||
.desired_width(f32::INFINITY)
|
||||
.lock_focus(true),
|
||||
.lock_focus(true)
|
||||
.layouter(&mut layouter),
|
||||
);
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user