@@ -13,7 +13,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use notedeck::{Accounts, AppAction, AppContext, DataPath, DataPathType, FilterState, UnknownIds};
|
||||
use notedeck_ui::NoteOptions;
|
||||
use notedeck_ui::{jobs::JobsCache, NoteOptions};
|
||||
|
||||
use enostr::{ClientMessage, Keypair, PoolRelay, Pubkey, RelayEvent, RelayMessage, RelayPool};
|
||||
use uuid::Uuid;
|
||||
@@ -42,6 +42,7 @@ pub struct Damus {
|
||||
pub timeline_cache: TimelineCache,
|
||||
pub subscriptions: Subscriptions,
|
||||
pub support: Support,
|
||||
pub jobs: JobsCache,
|
||||
|
||||
//frame_history: crate::frame_history::FrameHistory,
|
||||
|
||||
@@ -430,6 +431,8 @@ impl Damus {
|
||||
note_options.set_scramble_text(parsed_args.scramble);
|
||||
note_options.set_hide_media(parsed_args.no_media);
|
||||
|
||||
let jobs = JobsCache::default();
|
||||
|
||||
Self {
|
||||
subscriptions: Subscriptions::default(),
|
||||
since_optimize: parsed_args.since_optimize,
|
||||
@@ -444,6 +447,7 @@ impl Damus {
|
||||
decks_cache,
|
||||
debug,
|
||||
unrecognized_args,
|
||||
jobs,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,6 +491,7 @@ impl Damus {
|
||||
support,
|
||||
decks_cache,
|
||||
unrecognized_args: BTreeSet::default(),
|
||||
jobs: JobsCache::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
153
crates/notedeck_ui/src/jobs.rs
Normal file
153
crates/notedeck_ui/src/jobs.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
use egui::TextureHandle;
|
||||
use hashbrown::{hash_map::RawEntryMut, HashMap};
|
||||
use notedeck::JobPool;
|
||||
use poll_promise::Promise;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct JobsCache {
|
||||
jobs: HashMap<JobIdOwned, JobState>,
|
||||
}
|
||||
|
||||
pub enum JobState {
|
||||
Pending(Promise<Option<Result<Job, JobError>>>),
|
||||
Error(JobError),
|
||||
Completed(Job),
|
||||
}
|
||||
|
||||
pub enum JobError {
|
||||
InvalidParameters,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum JobParams<'a> {
|
||||
Blurhash(BlurhashParams<'a>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum JobParamsOwned {
|
||||
Blurhash(BlurhashParamsOwned),
|
||||
}
|
||||
|
||||
impl<'a> From<BlurhashParams<'a>> for BlurhashParamsOwned {
|
||||
fn from(params: BlurhashParams<'a>) -> Self {
|
||||
BlurhashParamsOwned {
|
||||
blurhash: params.blurhash.to_owned(),
|
||||
url: params.url.to_owned(),
|
||||
ctx: params.ctx.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<JobParams<'a>> for JobParamsOwned {
|
||||
fn from(params: JobParams<'a>) -> Self {
|
||||
match params {
|
||||
JobParams::Blurhash(bp) => JobParamsOwned::Blurhash(bp.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BlurhashParams<'a> {
|
||||
pub blurhash: &'a str,
|
||||
pub url: &'a str,
|
||||
pub ctx: &'a egui::Context,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BlurhashParamsOwned {
|
||||
pub blurhash: String,
|
||||
pub url: String,
|
||||
pub ctx: egui::Context,
|
||||
}
|
||||
|
||||
impl JobsCache {
|
||||
pub fn get_or_insert_with<
|
||||
'a,
|
||||
F: FnOnce(Option<JobParamsOwned>) -> Result<Job, JobError> + Send + 'static,
|
||||
>(
|
||||
&'a mut self,
|
||||
job_pool: &mut JobPool,
|
||||
jobid: &JobId,
|
||||
params: Option<JobParams>,
|
||||
run_job: F,
|
||||
) -> &'a mut JobState {
|
||||
match self.jobs.raw_entry_mut().from_key(jobid) {
|
||||
RawEntryMut::Occupied(entry) => 's: {
|
||||
let mut state = entry.into_mut();
|
||||
|
||||
let JobState::Pending(promise) = &mut state else {
|
||||
break 's state;
|
||||
};
|
||||
|
||||
let Some(res) = promise.ready_mut() else {
|
||||
break 's state;
|
||||
};
|
||||
|
||||
let Some(res) = res.take() else {
|
||||
tracing::error!("Failed to take the promise for job: {:?}", jobid);
|
||||
break 's state;
|
||||
};
|
||||
|
||||
*state = match res {
|
||||
Ok(j) => JobState::Completed(j),
|
||||
Err(e) => JobState::Error(e),
|
||||
};
|
||||
|
||||
state
|
||||
}
|
||||
RawEntryMut::Vacant(entry) => {
|
||||
let owned_params = params.map(JobParams::into);
|
||||
let wrapped: Box<dyn FnOnce() -> Option<Result<Job, JobError>> + Send + 'static> =
|
||||
Box::new(move || Some(run_job(owned_params)));
|
||||
|
||||
let promise = Promise::spawn_async(job_pool.schedule(wrapped));
|
||||
|
||||
let (_, state) = entry.insert(jobid.into(), JobState::Pending(promise));
|
||||
|
||||
state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, jobid: &JobId) -> Option<&JobState> {
|
||||
self.jobs.get(jobid)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&JobId<'a>> for JobIdOwned {
|
||||
fn from(jobid: &JobId<'a>) -> Self {
|
||||
match jobid {
|
||||
JobId::Blurhash(s) => JobIdOwned::Blurhash(s.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl hashbrown::Equivalent<JobIdOwned> for JobId<'_> {
|
||||
fn equivalent(&self, key: &JobIdOwned) -> bool {
|
||||
match (self, key) {
|
||||
(JobId::Blurhash(a), JobIdOwned::Blurhash(b)) => *a == b.as_str(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||
enum JobIdOwned {
|
||||
Blurhash(String), // image URL
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash)]
|
||||
pub enum JobId<'a> {
|
||||
Blurhash(&'a str), // image URL
|
||||
}
|
||||
|
||||
pub enum Job {
|
||||
Blurhash(Option<TextureHandle>),
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Job {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Job::Blurhash(_) => write!(f, "Blurhash"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ pub mod contacts;
|
||||
pub mod gif;
|
||||
pub mod icons;
|
||||
pub mod images;
|
||||
pub mod jobs;
|
||||
pub mod mention;
|
||||
pub mod note;
|
||||
pub mod profile;
|
||||
|
||||
Reference in New Issue
Block a user