mirror of https://github.com/wayvr-org/wayvr.git
dash-frontend: remove dangling popups immediately
This commit is contained in:
parent
aee5bf69da
commit
24e3099b7b
|
|
@ -28,7 +28,7 @@ use crate::{
|
||||||
assets,
|
assets,
|
||||||
tab::{Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings},
|
tab::{Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings},
|
||||||
util::{
|
util::{
|
||||||
popup_manager::{MountPopupOnceParams, MountPopupParams, PopupManager, PopupManagerParams},
|
popup_manager::{MountPopupOnceParams, PopupManager, PopupManagerParams},
|
||||||
toast_manager::ToastManager,
|
toast_manager::ToastManager,
|
||||||
},
|
},
|
||||||
views,
|
views,
|
||||||
|
|
@ -101,7 +101,6 @@ pub enum FrontendTask {
|
||||||
SetTab(TabType),
|
SetTab(TabType),
|
||||||
RefreshClock,
|
RefreshClock,
|
||||||
RefreshBackground,
|
RefreshBackground,
|
||||||
MountPopup(MountPopupParams),
|
|
||||||
MountPopupOnce(MountPopupOnceParams),
|
MountPopupOnce(MountPopupOnceParams),
|
||||||
RefreshPopupManager,
|
RefreshPopupManager,
|
||||||
ShowAudioSettings,
|
ShowAudioSettings,
|
||||||
|
|
@ -305,15 +304,6 @@ impl<T: 'static> Frontend<T> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_popup(&mut self, params: MountPopupParams, data: &mut T) -> anyhow::Result<()> {
|
|
||||||
let config = self.interface.general_config(data);
|
|
||||||
|
|
||||||
self
|
|
||||||
.popup_manager
|
|
||||||
.mount_popup(&self.globals, &mut self.layout, &self.tasks, params, config)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mount_popup_once(&mut self, params: MountPopupOnceParams, data: &mut T) -> anyhow::Result<()> {
|
fn mount_popup_once(&mut self, params: MountPopupOnceParams, data: &mut T) -> anyhow::Result<()> {
|
||||||
let config = self.interface.general_config(data);
|
let config = self.interface.general_config(data);
|
||||||
|
|
||||||
|
|
@ -357,7 +347,6 @@ impl<T: 'static> Frontend<T> {
|
||||||
FrontendTask::SetTab(tab_type) => self.set_tab(params.data, tab_type)?,
|
FrontendTask::SetTab(tab_type) => self.set_tab(params.data, tab_type)?,
|
||||||
FrontendTask::RefreshClock => self.update_time(params.data)?,
|
FrontendTask::RefreshClock => self.update_time(params.data)?,
|
||||||
FrontendTask::RefreshBackground => self.update_background(params.data)?,
|
FrontendTask::RefreshBackground => self.update_background(params.data)?,
|
||||||
FrontendTask::MountPopup(popup_params) => self.mount_popup(popup_params, params.data)?,
|
|
||||||
FrontendTask::MountPopupOnce(popup_params) => self.mount_popup_once(popup_params, params.data)?,
|
FrontendTask::MountPopupOnce(popup_params) => self.mount_popup_once(popup_params, params.data)?,
|
||||||
FrontendTask::RefreshPopupManager => self.refresh_popup_manager()?,
|
FrontendTask::RefreshPopupManager => self.refresh_popup_manager()?,
|
||||||
FrontendTask::ShowAudioSettings => self.action_show_audio_settings()?,
|
FrontendTask::ShowAudioSettings => self.action_show_audio_settings()?,
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ pub struct MountedPopup {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct MountedPopupState {
|
struct MountedPopupState {
|
||||||
mounted_popup: Option<MountedPopup>,
|
mounted_popup: Option<MountedPopup>,
|
||||||
|
closed_callback: Option<PopupClosedCallback>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
|
|
@ -71,6 +72,13 @@ impl<ViewType> Default for PopupHolder<ViewType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<ViewType> PopupHolderState<ViewType> {
|
||||||
|
fn close(&mut self) {
|
||||||
|
self.view = None;
|
||||||
|
self.popup_handle.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// we can't derive(Clone) due to the fact that ViewType is non-cloneable
|
// we can't derive(Clone) due to the fact that ViewType is non-cloneable
|
||||||
impl<ViewType> Clone for PopupHolder<ViewType> {
|
impl<ViewType> Clone for PopupHolder<ViewType> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
|
|
@ -82,9 +90,7 @@ impl<ViewType> Clone for PopupHolder<ViewType> {
|
||||||
|
|
||||||
impl<ViewType> PopupHolder<ViewType> {
|
impl<ViewType> PopupHolder<ViewType> {
|
||||||
pub fn close(&self) {
|
pub fn close(&self) {
|
||||||
let mut state = self.state.borrow_mut();
|
self.state.borrow_mut().close();
|
||||||
state.view = None;
|
|
||||||
state.popup_handle.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_view(&self, handle: PopupHandle, view: ViewType) {
|
pub fn set_view(&self, handle: PopupHandle, view: ViewType) {
|
||||||
|
|
@ -129,8 +135,12 @@ impl<ViewType> PopupHolder<ViewType> {
|
||||||
where
|
where
|
||||||
ViewType: 'static,
|
ViewType: 'static,
|
||||||
{
|
{
|
||||||
let this = self.clone();
|
let weak_state = Rc::downgrade(&self.state);
|
||||||
Box::new(move || this.close())
|
Box::new(move || {
|
||||||
|
if let Some(state) = weak_state.upgrade() {
|
||||||
|
state.borrow_mut().close();
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,22 +162,21 @@ pub struct PopupContentFuncData<'a> {
|
||||||
pub id_content: WidgetID,
|
pub id_content: WidgetID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
type PopupClosedCallback = Box<dyn FnOnce()>;
|
||||||
pub struct MountPopupParams {
|
|
||||||
pub title: Translation,
|
|
||||||
pub on_content: Rc<dyn Fn(PopupContentFuncData) -> anyhow::Result<()>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to implement Clone here, but the underlying function can be called only once.
|
// we need to implement Clone here, but the underlying function can be called only once.
|
||||||
// on_content will be cleared after the first call
|
// on_content will be cleared after the first call
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct MountPopupOnceParams {
|
pub struct MountPopupOnceParams {
|
||||||
title: Translation,
|
title: Translation,
|
||||||
on_content: Rc<RefCell<Option<Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<()>>>>>,
|
on_content: Rc<RefCell<Option<Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<PopupClosedCallback>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MountPopupOnceParams {
|
impl MountPopupOnceParams {
|
||||||
pub fn new(title: Translation, on_content: Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<()>>) -> Self {
|
pub fn new(
|
||||||
|
title: Translation,
|
||||||
|
on_content: Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<PopupClosedCallback>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
title,
|
title,
|
||||||
on_content: Rc::new(RefCell::new(Some(on_content))),
|
on_content: Rc::new(RefCell::new(Some(on_content))),
|
||||||
|
|
@ -186,10 +195,16 @@ impl State {
|
||||||
fn refresh_stack(&mut self, alterables: &mut EventAlterables) {
|
fn refresh_stack(&mut self, alterables: &mut EventAlterables) {
|
||||||
// show only the topmost popup
|
// show only the topmost popup
|
||||||
self.popup_stack.retain(|weak| {
|
self.popup_stack.retain(|weak| {
|
||||||
let Some(popup) = weak.upgrade() else {
|
let retain = {
|
||||||
return false;
|
let Some(popup) = weak.upgrade() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
popup.borrow_mut().mounted_popup.is_some()
|
||||||
};
|
};
|
||||||
popup.borrow_mut().mounted_popup.is_some()
|
if !retain {
|
||||||
|
log::debug!("removing popup from popup_stack");
|
||||||
|
}
|
||||||
|
retain
|
||||||
});
|
});
|
||||||
|
|
||||||
for (idx, popup) in self.popup_stack.iter().enumerate() {
|
for (idx, popup) in self.popup_stack.iter().enumerate() {
|
||||||
|
|
@ -257,6 +272,7 @@ impl PopupManager {
|
||||||
|
|
||||||
let mounted_popup_state = MountedPopupState {
|
let mounted_popup_state = MountedPopupState {
|
||||||
mounted_popup: Some(mounted_popup),
|
mounted_popup: Some(mounted_popup),
|
||||||
|
closed_callback: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let popup_handle = PopupHandle {
|
let popup_handle = PopupHandle {
|
||||||
|
|
@ -264,13 +280,21 @@ impl PopupManager {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
|
log::debug!("pushing popup to popup_stack");
|
||||||
state.popup_stack.push(Rc::downgrade(&popup_handle.state));
|
state.popup_stack.push(Rc::downgrade(&popup_handle.state));
|
||||||
|
|
||||||
but_back.on_click({
|
but_back.on_click({
|
||||||
let popup_handle = Rc::downgrade(&popup_handle.state);
|
let popup_handle = Rc::downgrade(&popup_handle.state);
|
||||||
Rc::new(move |_common, _evt| {
|
Rc::new(move |_common, _evt| {
|
||||||
if let Some(popup_handle) = popup_handle.upgrade() {
|
if let Some(popup_handle) = popup_handle.upgrade() {
|
||||||
popup_handle.borrow_mut().mounted_popup = None; // will call Drop
|
if let Some(closed_callback) = {
|
||||||
|
let mut state = popup_handle.borrow_mut();
|
||||||
|
state.mounted_popup = None; // will call Drop
|
||||||
|
state.closed_callback.take()
|
||||||
|
} {
|
||||||
|
log::debug!("closed_callback called");
|
||||||
|
closed_callback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|
@ -280,7 +304,7 @@ impl PopupManager {
|
||||||
Ok((popup_handle, id_content))
|
Ok((popup_handle, id_content))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mount a new popup on top of the existing popup stack (non-cloneable version).
|
/// Mount a new popup on top of the existing popup stack.
|
||||||
/// Only the topmost popup is visible.
|
/// Only the topmost popup is visible.
|
||||||
pub fn mount_popup_once(
|
pub fn mount_popup_once(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -298,35 +322,14 @@ impl PopupManager {
|
||||||
let (popup_handle, id_content) = self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title)?;
|
let (popup_handle, id_content) = self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title)?;
|
||||||
|
|
||||||
// mount user-set popup content
|
// mount user-set popup content
|
||||||
on_content_func(PopupContentFuncData {
|
let closed_callback = on_content_func(PopupContentFuncData {
|
||||||
layout,
|
layout,
|
||||||
handle: popup_handle.clone(),
|
handle: popup_handle.clone(),
|
||||||
id_content,
|
id_content,
|
||||||
config,
|
config,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
popup_handle.state.borrow_mut().closed_callback = Some(closed_callback);
|
||||||
}
|
|
||||||
|
|
||||||
/// Mount a new popup on top of the existing popup stack.
|
|
||||||
/// Only the topmost popup is visible.
|
|
||||||
pub fn mount_popup(
|
|
||||||
&mut self,
|
|
||||||
globals: &WguiGlobals,
|
|
||||||
layout: &mut Layout,
|
|
||||||
frontend_tasks: &FrontendTasks,
|
|
||||||
params: MountPopupParams,
|
|
||||||
config: &GeneralConfig,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
let (popup_handle, id_content) = self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title)?;
|
|
||||||
|
|
||||||
// mount user-set popup content
|
|
||||||
(*params.on_content)(PopupContentFuncData {
|
|
||||||
layout,
|
|
||||||
handle: popup_handle.clone(),
|
|
||||||
id_content,
|
|
||||||
config,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,7 @@ pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, entry: D
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
popup.set_view(data.handle, view);
|
popup.set_view(data.handle, view);
|
||||||
Ok(())
|
Ok(popup.get_close_callback())
|
||||||
}),
|
}),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ pub fn mount_popup(
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
popup.set_view(data.handle, view);
|
popup.set_view(data.handle, view);
|
||||||
Ok(())
|
Ok(popup.get_close_callback())
|
||||||
}),
|
}),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ pub fn mount_popup(
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
popup.set_view(data.handle, view);
|
popup.set_view(data.handle, view);
|
||||||
Ok(())
|
Ok(popup.get_close_callback())
|
||||||
}),
|
}),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ pub fn mount_popup(
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
popup.set_view(data.handle, view);
|
popup.set_view(data.handle, view);
|
||||||
Ok(())
|
Ok(popup.get_close_callback())
|
||||||
}),
|
}),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue