app: fix emoji picker due to recent changes

This commit is contained in:
jkds
2026-01-06 05:56:33 +01:00
parent 22f9597908
commit 74b18df957
5 changed files with 592 additions and 703 deletions

View File

@@ -63,11 +63,7 @@ pub struct App {
}
impl App {
pub fn new(
sg_root: SceneNodePtr,
render_api: RenderApi,
ex: ExecutorPtr,
) -> Arc<Self> {
pub fn new(sg_root: SceneNodePtr, render_api: RenderApi, ex: ExecutorPtr) -> Arc<Self> {
Arc::new(Self { sg_root, ex, render_api, tasks: SyncMutex::new(vec![]) })
}

View File

@@ -512,8 +512,7 @@ impl FileMessage {
for layout in layouts {
all_instrs.push(DrawInstruction::Move(Point::new(0., -line_height)));
let instrs =
text::render_layout(&layout, render_api, gfxtag!("chatview_filemsg_text"));
let instrs = text::render_layout(&layout, render_api, gfxtag!("chatview_filemsg_text"));
all_instrs.extend(instrs);
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@ use std::{
fs::File,
io::{BufRead, BufReader},
path::{Path, PathBuf},
sync::{Arc, LazyLock},
sync::Arc,
};
use crate::{
@@ -30,35 +30,19 @@ use crate::{
text,
};
use super::default;
#[cfg(target_os = "android")]
pub fn get_emoji_list_path() -> PathBuf {
crate::android::get_external_storage_path().join("emoji.txt")
}
#[cfg(not(target_os = "android"))]
pub fn get_emoji_list_path() -> PathBuf {
dirs::data_local_dir().unwrap().join("darkfi/emoji.txt")
}
use super::default::DEFAULT_EMOJI_LIST;
pub type EmojiMeshesPtr = Arc<AsyncMutex<EmojiMeshes>>;
pub struct EmojiMeshes {
render_api: RenderApi,
emoji_size: f32,
emoji_list: LazyLock<Vec<String>>,
meshes: Vec<DrawMesh>,
}
impl EmojiMeshes {
pub fn new(render_api: RenderApi, emoji_size: f32) -> EmojiMeshesPtr {
Arc::new(AsyncMutex::new(Self {
render_api,
emoji_size,
emoji_list: LazyLock::new(load_emoji_list),
meshes: vec![],
}))
Arc::new(AsyncMutex::new(Self { render_api, emoji_size, meshes: vec![] }))
}
pub fn clear(&mut self) {
@@ -66,14 +50,13 @@ impl EmojiMeshes {
}
pub async fn get(&mut self, i: usize) -> DrawMesh {
let emoji_list = self.get_list();
assert!(i < emoji_list.len());
self.meshes.reserve_exact(emoji_list.len());
assert!(i < DEFAULT_EMOJI_LIST.len());
self.meshes.reserve_exact(DEFAULT_EMOJI_LIST.len());
if i >= self.meshes.len() {
//d!("EmojiMeshes loading new glyphs");
for j in self.meshes.len()..=i {
let emoji = &self.emoji_list[j];
let emoji = DEFAULT_EMOJI_LIST[j];
let mesh = self.gen_emoji_mesh(emoji).await;
self.meshes.push(mesh);
}
@@ -100,85 +83,7 @@ impl EmojiMeshes {
_ => panic!("Expected Draw instruction for emoji"),
};
// Emoji's vary in size. We make them all a consistent size.
// We need to scale the mesh to match emoji_size.
// TODO: Implement proper scaling for text2 API
/*
let bbox = layout.metrics().bounds;
let orig_w = bbox.width().max(1.0);
let orig_h = bbox.height().max(1.0);
let w = self.emoji_size;
let h = self.emoji_size * orig_h / orig_w;
// Create a new mesh with the scaled size centered at origin
let x = -w / 2.;
let y = -h / 2.;
let mut mesh_builder = MeshBuilder::new(gfxtag!("emoji_mesh"));
*/
// For now, just return the original mesh since scaling is complex with textures
mesh
}
pub fn get_list<'a>(&'a self) -> &'a Vec<String> {
LazyLock::force(&self.emoji_list)
}
}
fn load_emoji_list() -> Vec<String> {
match load_custom_emoji_list(&get_emoji_list_path()) {
Some(emojis) => emojis,
None => default::create_default_emoji_list(),
}
}
fn load_custom_emoji_list(path: &Path) -> Option<Vec<String>> {
let file = File::open(path).ok()?;
let reader = BufReader::new(file);
let mut emojis = vec![];
for mut line in reader.lines().map_while(Result::ok) {
remove_whitespace(&mut line);
let line = strip_comment(&line);
if line.is_empty() {
continue
}
let emoji = unescape_unicode(line)?;
emojis.push(emoji);
}
Some(emojis)
}
fn unescape_unicode(input: &str) -> Option<String> {
let re = regex::Regex::new(r"\\u\{([0-9A-Fa-f]+)\}").unwrap();
// There is no way to bail from a failed regex so we use this workaround instead.
let mut failed = false;
let result = re
.replace_all(input, |caps: &regex::Captures| {
let Ok(code) = u32::from_str_radix(&caps[1], 16) else {
failed = true;
return String::new()
};
let Some(chr) = char::from_u32(code) else {
failed = true;
return String::new()
};
chr.to_string()
})
.into_owned();
if failed {
return None
}
Some(result)
}
fn remove_whitespace(s: &mut String) {
s.retain(|c| !c.is_whitespace());
}
fn strip_comment(s: &str) -> &str {
s.split('#').next().unwrap_or(s)
}

View File

@@ -38,6 +38,7 @@ use crate::{
use super::{DrawUpdate, OnModify, UIObject};
mod default;
use default::DEFAULT_EMOJI_LIST;
mod emoji;
pub use emoji::{EmojiMeshes, EmojiMeshesPtr};
@@ -126,7 +127,7 @@ impl EmojiPicker {
}
async fn max_scroll(&self) -> f32 {
let emojis_len = self.emoji_meshes.lock().await.get_list().len() as f32;
let emojis_len = DEFAULT_EMOJI_LIST.len() as f32;
let emoji_size = self.emoji_size.get();
let cols = self.emojis_per_line();
let rows = (emojis_len / cols).ceil();
@@ -161,10 +162,8 @@ impl EmojiPicker {
let emoji_selected = {
let emoji_meshes = self.emoji_meshes.lock().await;
let emoji_list = emoji_meshes.get_list();
if idx < emoji_list.len() {
let emoji = emoji_list[idx].clone();
if idx < DEFAULT_EMOJI_LIST.len() {
let emoji = DEFAULT_EMOJI_LIST[idx].to_string();
Some(emoji)
} else {
None
@@ -215,21 +214,16 @@ impl EmojiPicker {
let off_x = self.calc_off_x();
let emoji_size = self.emoji_size.get();
let emoji_list_len = {
let emoji_meshes = self.emoji_meshes.lock().await;
emoji_meshes.get_list().len()
};
let mut x = emoji_size / 2.;
let mut y = emoji_size / 2. - self.scroll.get();
for i in 0..emoji_list_len {
let mut x = 0.;
let mut y = -self.scroll.get();
for i in 0..DEFAULT_EMOJI_LIST.len() {
let pos = Point::new(x, y);
let mesh = self.emoji_meshes.lock().await.get(i).await;
instrs.extend_from_slice(&[DrawInstruction::SetPos(pos), DrawInstruction::Draw(mesh)]);
x += off_x;
if x > rect.w {
x = emoji_size / 2.;
x = 0.;
y += emoji_size;
//d!("Line break after idx={i}");
}