1use crate::{
2 AnyView, AnyWindowHandle, AppContext, BackgroundExecutor, Context, ForegroundExecutor, Model,
3 ModelContext, Render, Result, Task, View, ViewContext, VisualContext, WindowContext,
4};
5use anyhow::{anyhow, Context as _};
6use derive_more::{Deref, DerefMut};
7use std::{cell::RefCell, future::Future, rc::Weak};
8
9#[derive(Clone)]
10pub struct AsyncAppContext {
11 pub(crate) app: Weak<RefCell<AppContext>>,
12 pub(crate) background_executor: BackgroundExecutor,
13 pub(crate) foreground_executor: ForegroundExecutor,
14}
15
16impl Context for AsyncAppContext {
17 type Result<T> = Result<T>;
18
19 fn build_model<T: 'static>(
20 &mut self,
21 build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
22 ) -> Self::Result<Model<T>>
23 where
24 T: 'static,
25 {
26 let app = self
27 .app
28 .upgrade()
29 .ok_or_else(|| anyhow!("app was released"))?;
30 let mut app = app.borrow_mut();
31 Ok(app.build_model(build_model))
32 }
33
34 fn update_model<T: 'static, R>(
35 &mut self,
36 handle: &Model<T>,
37 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
38 ) -> Self::Result<R> {
39 let app = self
40 .app
41 .upgrade()
42 .ok_or_else(|| anyhow!("app was released"))?;
43 let mut app = app.borrow_mut();
44 Ok(app.update_model(handle, update))
45 }
46
47 fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
48 where
49 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
50 {
51 let app = self.app.upgrade().context("app was released")?;
52 let mut lock = app.borrow_mut();
53 lock.update_window(window, f)
54 }
55}
56
57impl AsyncAppContext {
58 pub fn refresh(&mut self) -> Result<()> {
59 let app = self
60 .app
61 .upgrade()
62 .ok_or_else(|| anyhow!("app was released"))?;
63 let mut lock = app.borrow_mut();
64 lock.refresh();
65 Ok(())
66 }
67
68 pub fn background_executor(&self) -> &BackgroundExecutor {
69 &self.background_executor
70 }
71
72 pub fn foreground_executor(&self) -> &ForegroundExecutor {
73 &self.foreground_executor
74 }
75
76 pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> Result<R> {
77 let app = self
78 .app
79 .upgrade()
80 .ok_or_else(|| anyhow!("app was released"))?;
81 let mut lock = app.borrow_mut();
82 Ok(f(&mut *lock))
83 }
84
85 pub fn update_window<R>(
86 &self,
87 handle: AnyWindowHandle,
88 update: impl FnOnce(AnyView, &mut WindowContext) -> R,
89 ) -> Result<R> {
90 let app = self
91 .app
92 .upgrade()
93 .ok_or_else(|| anyhow!("app was released"))?;
94 let mut app_context = app.borrow_mut();
95 app_context.update_window(handle, update)
96 }
97
98 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
99 where
100 Fut: Future<Output = R> + 'static,
101 R: 'static,
102 {
103 self.foreground_executor.spawn(f(self.clone()))
104 }
105
106 pub fn has_global<G: 'static>(&self) -> Result<bool> {
107 let app = self
108 .app
109 .upgrade()
110 .ok_or_else(|| anyhow!("app was released"))?;
111 let app = app.borrow_mut();
112 Ok(app.has_global::<G>())
113 }
114
115 pub fn read_global<G: 'static, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
116 let app = self
117 .app
118 .upgrade()
119 .ok_or_else(|| anyhow!("app was released"))?;
120 let app = app.borrow_mut(); // Need this to compile
121 Ok(read(app.global(), &app))
122 }
123
124 pub fn try_read_global<G: 'static, R>(
125 &self,
126 read: impl FnOnce(&G, &AppContext) -> R,
127 ) -> Option<R> {
128 let app = self.app.upgrade()?;
129 let app = app.borrow_mut();
130 Some(read(app.try_global()?, &app))
131 }
132
133 pub fn update_global<G: 'static, R>(
134 &mut self,
135 update: impl FnOnce(&mut G, &mut AppContext) -> R,
136 ) -> Result<R> {
137 let app = self
138 .app
139 .upgrade()
140 .ok_or_else(|| anyhow!("app was released"))?;
141 let mut app = app.borrow_mut();
142 Ok(app.update_global(update))
143 }
144}
145
146#[derive(Clone, Deref, DerefMut)]
147pub struct AsyncWindowContext {
148 #[deref]
149 #[deref_mut]
150 app: AsyncAppContext,
151 window: AnyWindowHandle,
152}
153
154impl AsyncWindowContext {
155 pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
156 Self { app, window }
157 }
158
159 pub fn update<R>(
160 &mut self,
161 update: impl FnOnce(AnyView, &mut WindowContext) -> R,
162 ) -> Result<R> {
163 self.app.update_window(self.window, update)
164 }
165
166 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
167 self.window.update(self, |_, cx| cx.on_next_frame(f)).ok();
168 }
169
170 pub fn read_global<G: 'static, R>(
171 &mut self,
172 read: impl FnOnce(&G, &WindowContext) -> R,
173 ) -> Result<R> {
174 self.window.update(self, |_, cx| read(cx.global(), cx))
175 }
176
177 pub fn update_global<G, R>(
178 &mut self,
179 update: impl FnOnce(&mut G, &mut WindowContext) -> R,
180 ) -> Result<R>
181 where
182 G: 'static,
183 {
184 self.window.update(self, |_, cx| cx.update_global(update))
185 }
186
187 pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncWindowContext) -> Fut + 'static) -> Task<R>
188 where
189 Fut: Future<Output = R> + 'static,
190 R: 'static,
191 {
192 let this = self.clone();
193 self.foreground_executor.spawn(async move { f(this).await })
194 }
195}
196
197impl Context for AsyncWindowContext {
198 type Result<T> = Result<T>;
199
200 fn build_model<T>(
201 &mut self,
202 build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
203 ) -> Result<Model<T>>
204 where
205 T: 'static,
206 {
207 self.window
208 .update(self, |_, cx| cx.build_model(build_model))
209 }
210
211 fn update_model<T: 'static, R>(
212 &mut self,
213 handle: &Model<T>,
214 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
215 ) -> Result<R> {
216 self.window
217 .update(self, |_, cx| cx.update_model(handle, update))
218 }
219
220 fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
221 where
222 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
223 {
224 self.app.update_window(window, update)
225 }
226}
227
228impl VisualContext for AsyncWindowContext {
229 fn build_view<V>(
230 &mut self,
231 build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
232 ) -> Self::Result<View<V>>
233 where
234 V: 'static,
235 {
236 self.window
237 .update(self, |_, cx| cx.build_view(build_view_state))
238 }
239
240 fn update_view<V: 'static, R>(
241 &mut self,
242 view: &View<V>,
243 update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
244 ) -> Self::Result<R> {
245 self.window
246 .update(self, |_, cx| cx.update_view(view, update))
247 }
248
249 fn replace_root_view<V>(
250 &mut self,
251 build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
252 ) -> Self::Result<View<V>>
253 where
254 V: Render,
255 {
256 self.window
257 .update(self, |_, cx| cx.replace_root_view(build_view))
258 }
259}