Pass a handle to the current view model when spawning

Most of the time, we'll want a way to get a reference back to the current view or model, so this facilitates that common case.
This commit is contained in:
Nathan Sobo 2021-05-12 15:28:59 -06:00
parent fa6bd1f926
commit a3be5595dd
6 changed files with 41 additions and 44 deletions

View file

@ -1654,11 +1654,12 @@ impl<'a, T: Entity> ModelContext<'a, T> {
pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S> pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
where where
F: FnOnce(AsyncAppContext) -> Fut, F: FnOnce(ModelHandle<T>, AsyncAppContext) -> Fut,
Fut: 'static + Future<Output = S>, Fut: 'static + Future<Output = S>,
S: 'static, S: 'static,
{ {
self.app.spawn(f) let handle = self.handle();
self.app.spawn(|ctx| f(handle, ctx))
} }
} }
@ -1909,11 +1910,12 @@ impl<'a, T: View> ViewContext<'a, T> {
pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S> pub fn spawn<F, Fut, S>(&self, f: F) -> Task<S>
where where
F: FnOnce(AsyncAppContext) -> Fut, F: FnOnce(ViewHandle<T>, AsyncAppContext) -> Fut,
Fut: 'static + Future<Output = S>, Fut: 'static + Future<Output = S>,
S: 'static, S: 'static,
{ {
self.app.spawn(f) let handle = self.handle();
self.app.spawn(|ctx| f(handle, ctx))
} }
} }

View file

@ -477,9 +477,8 @@ impl Buffer {
let snapshot = self.snapshot(); let snapshot = self.snapshot();
let version = self.version.clone(); let version = self.version.clone();
let file = self.file.clone(); let file = self.file.clone();
let handle = ctx.handle();
ctx.spawn(|mut ctx| async move { ctx.spawn(|handle, mut ctx| async move {
if let Some(file) = new_file.as_ref().or(file.as_ref()) { if let Some(file) = new_file.as_ref().or(file.as_ref()) {
let result = ctx.read(|ctx| file.save(snapshot, ctx.as_ref())).await; let result = ctx.read(|ctx| file.save(snapshot, ctx.as_ref())).await;
if result.is_ok() { if result.is_ok() {

View file

@ -2347,10 +2347,9 @@ impl BufferView {
ctx.notify(); ctx.notify();
let epoch = self.next_blink_epoch(); let epoch = self.next_blink_epoch();
let handle = ctx.handle(); ctx.spawn(|this, mut ctx| async move {
ctx.spawn(|mut ctx| async move {
Timer::after(CURSOR_BLINK_INTERVAL).await; Timer::after(CURSOR_BLINK_INTERVAL).await;
handle.update(&mut ctx, |this, ctx| { this.update(&mut ctx, |this, ctx| {
this.resume_cursor_blinking(epoch, ctx); this.resume_cursor_blinking(epoch, ctx);
}) })
}) })
@ -2370,10 +2369,9 @@ impl BufferView {
ctx.notify(); ctx.notify();
let epoch = self.next_blink_epoch(); let epoch = self.next_blink_epoch();
let handle = ctx.handle(); ctx.spawn(|this, mut ctx| async move {
ctx.spawn(|mut ctx| async move {
Timer::after(CURSOR_BLINK_INTERVAL).await; Timer::after(CURSOR_BLINK_INTERVAL).await;
handle.update(&mut ctx, |this, ctx| this.blink_cursors(epoch, ctx)); this.update(&mut ctx, |this, ctx| this.blink_cursors(epoch, ctx));
}) })
.detach(); .detach();
} }

View file

@ -415,10 +415,9 @@ impl FileFinder {
(search_id, did_cancel, query, matches) (search_id, did_cancel, query, matches)
}); });
let handle = ctx.handle(); ctx.spawn(|this, mut ctx| async move {
ctx.spawn(|mut ctx| async move {
let matches = background_task.await; let matches = background_task.await;
handle.update(&mut ctx, |this, ctx| this.update_matches(matches, ctx)); this.update(&mut ctx, |this, ctx| this.update_matches(matches, ctx));
}) })
.detach(); .detach();

View file

@ -359,13 +359,12 @@ impl Workspace {
.cloned() .cloned()
.zip(entries.into_iter()) .zip(entries.into_iter())
.map(|(abs_path, file)| { .map(|(abs_path, file)| {
let handle = ctx.handle();
let is_file = bg.spawn(async move { abs_path.is_file() }); let is_file = bg.spawn(async move { abs_path.is_file() });
ctx.spawn(|mut ctx| async move { ctx.spawn(|this, mut ctx| async move {
let is_file = is_file.await; let is_file = is_file.await;
handle.update(&mut ctx, |me, ctx| { this.update(&mut ctx, |this, ctx| {
if is_file { if is_file {
me.open_entry(file.entry_id(), ctx) this.open_entry(file.entry_id(), ctx)
} else { } else {
None None
} }
@ -513,8 +512,7 @@ impl Workspace {
let mut watch = self.loading_items.get(&entry).unwrap().clone(); let mut watch = self.loading_items.get(&entry).unwrap().clone();
let handle = ctx.handle(); Some(ctx.spawn(|this, mut ctx| async move {
Some(ctx.spawn(|mut ctx| async move {
let load_result = loop { let load_result = loop {
if let Some(load_result) = watch.borrow().as_ref() { if let Some(load_result) = watch.borrow().as_ref() {
break load_result.clone(); break load_result.clone();
@ -522,16 +520,16 @@ impl Workspace {
watch.next().await; watch.next().await;
}; };
handle.update(&mut ctx, |me, ctx| { this.update(&mut ctx, |this, ctx| {
me.loading_items.remove(&entry); this.loading_items.remove(&entry);
match load_result { match load_result {
Ok(item) => { Ok(item) => {
let weak_item = item.downgrade(); let weak_item = item.downgrade();
let view = weak_item let view = weak_item
.add_view(ctx.window_id(), settings, ctx.as_mut()) .add_view(ctx.window_id(), settings, ctx.as_mut())
.unwrap(); .unwrap();
me.items.push(weak_item); this.items.push(weak_item);
me.add_item_view(view, ctx); this.add_item_view(view, ctx);
} }
Err(error) => { Err(error) => {
log::error!("error opening item: {}", error); log::error!("error opening item: {}", error);

View file

@ -98,20 +98,23 @@ impl Worktree {
scanner.run(event_stream) scanner.run(event_stream)
}); });
let handle = ctx.handle().downgrade(); ctx.spawn(|this, mut ctx| {
ctx.spawn(|mut ctx| async move { let this = this.downgrade();
while let Ok(scan_state) = scan_state_rx.recv().await { async move {
let alive = ctx.update(|ctx| { while let Ok(scan_state) = scan_state_rx.recv().await {
if let Some(handle) = handle.upgrade(&ctx) { let alive = ctx.update(|ctx| {
handle.update(ctx, |this, ctx| this.observe_scan_state(scan_state, ctx)); if let Some(handle) = this.upgrade(&ctx) {
true handle
} else { .update(ctx, |this, ctx| this.observe_scan_state(scan_state, ctx));
false true
} } else {
}); false
}
});
if !alive { if !alive {
break; break;
}
} }
} }
}) })
@ -133,10 +136,9 @@ impl Worktree {
pub fn next_scan_complete(&self, ctx: &mut ModelContext<Self>) -> impl Future<Output = ()> { pub fn next_scan_complete(&self, ctx: &mut ModelContext<Self>) -> impl Future<Output = ()> {
let scan_id = self.snapshot.scan_id; let scan_id = self.snapshot.scan_id;
let mut scan_state = self.scan_state.1.clone(); let mut scan_state = self.scan_state.1.clone();
let handle = ctx.handle(); ctx.spawn(|this, ctx| async move {
ctx.spawn(|ctx| async move {
while let Some(scan_state) = scan_state.recv().await { while let Some(scan_state) = scan_state.recv().await {
if handle.read_with(&ctx, |this, _| { if this.read_with(&ctx, |this, _| {
matches!(scan_state, ScanState::Idle) && this.snapshot.scan_id > scan_id matches!(scan_state, ScanState::Idle) && this.snapshot.scan_id > scan_id
}) { }) {
break; break;
@ -155,9 +157,8 @@ impl Worktree {
ctx.notify(); ctx.notify();
if self.is_scanning() && !self.poll_scheduled { if self.is_scanning() && !self.poll_scheduled {
let handle = ctx.handle(); ctx.spawn(|this, mut ctx| async move {
ctx.spawn(|mut ctx| async move { this.update(&mut ctx, |this, ctx| {
handle.update(&mut ctx, |this, ctx| {
this.poll_scheduled = false; this.poll_scheduled = false;
this.poll_entries(ctx); this.poll_entries(ctx);
}) })