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) + Send + '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>(
188 &self,
189 f: impl FnOnce(AsyncWindowContext) -> Fut + Send + 'static,
190 ) -> Task<R>
191 where
192 Fut: Future<Output = R> + Send + 'static,
193 R: Send + 'static,
194 {
195 let this = self.clone();
196 self.foreground_executor.spawn(async move { f(this).await })
197 }
198}
199
200impl Context for AsyncWindowContext {
201 type Result<T> = Result<T>;
202
203 fn build_model<T>(
204 &mut self,
205 build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
206 ) -> Result<Model<T>>
207 where
208 T: 'static,
209 {
210 self.window
211 .update(self, |_, cx| cx.build_model(build_model))
212 }
213
214 fn update_model<T: 'static, R>(
215 &mut self,
216 handle: &Model<T>,
217 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
218 ) -> Result<R> {
219 self.window
220 .update(self, |_, cx| cx.update_model(handle, update))
221 }
222
223 fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
224 where
225 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
226 {
227 self.app.update_window(window, update)
228 }
229}
230
231impl VisualContext for AsyncWindowContext {
232 fn build_view<V>(
233 &mut self,
234 build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
235 ) -> Self::Result<View<V>>
236 where
237 V: 'static,
238 {
239 self.window
240 .update(self, |_, cx| cx.build_view(build_view_state))
241 }
242
243 fn update_view<V: 'static, R>(
244 &mut self,
245 view: &View<V>,
246 update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
247 ) -> Self::Result<R> {
248 self.window
249 .update(self, |_, cx| cx.update_view(view, update))
250 }
251
252 fn replace_root_view<V>(
253 &mut self,
254 build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
255 ) -> Self::Result<View<V>>
256 where
257 V: Render,
258 {
259 self.window
260 .update(self, |_, cx| cx.replace_root_view(build_view))
261 }
262}