From afe10afa3af388e6df909b06fe781a1a28188505 Mon Sep 17 00:00:00 2001 From: yangziyong Date: Wed, 7 Feb 2024 18:25:33 +0800 Subject: [PATCH] Feat: Dialog component supports disabling gesture exit Signed-off-by: yangziyong Change-Id: Iae3e0e836e78e2afc9334f3093dc9abc1f89dfa5 --- .../engine/jsEnumStyle.js | 7 +++ .../frontend_delegate_declarative.cpp | 14 ++++++ .../frontend_delegate_declarative.h | 1 + .../jsview/action_sheet/js_action_sheet.cpp | 4 ++ .../jsview/dialog/js_alert_dialog.cpp | 4 ++ .../dialog/js_custom_dialog_controller.cpp | 5 +++ .../jsview/js_view_abstract.cpp | 27 +++++++++++ .../jsview/js_view_abstract.h | 3 ++ .../bridge/js_frontend/frontend_delegate.h | 1 + .../components/dialog/dialog_properties.h | 2 + .../core/components_ng/base/view_abstract.cpp | 18 ++++++++ .../core/components_ng/base/view_abstract.h | 1 + .../components_ng/base/view_abstract_model.h | 1 + .../base/view_abstract_model_ng.h | 5 +++ .../pattern/action_sheet/action_sheet_model.h | 2 + .../action_sheet/action_sheet_model_ng.cpp | 6 +++ .../action_sheet/action_sheet_model_ng.h | 2 + .../pattern/dialog/alert_dialog_model.h | 2 + .../pattern/dialog/alert_dialog_model_ng.cpp | 11 +++++ .../pattern/dialog/alert_dialog_model_ng.h | 2 + .../pattern/dialog/dialog_pattern.cpp | 5 +++ .../pattern/dialog/dialog_pattern.h | 27 +++++++++++ .../pattern/dialog/dialog_view.cpp | 1 + .../pattern/overlay/overlay_manager.cpp | 14 ++++++ .../napi/kits/promptaction/prompt_action.cpp | 45 +++++++++++++++++++ 25 files changed, 210 insertions(+) diff --git a/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js b/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js index 85a4e560520..56c739df831 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js +++ b/frameworks/bridge/declarative_frontend/engine/jsEnumStyle.js @@ -963,6 +963,13 @@ var MenuPreviewMode; MenuPreviewMode[MenuPreviewMode["IMAGE"] = 1] = "IMAGE"; })(MenuPreviewMode || (MenuPreviewMode = {})); +var DismissReason; +(function (DismissReason) { +DismissReason[DismissReason["PRESS_BACK"] = 0] = "PRESSBACK" +DismissReason[DismissReason["TOUCH_OUTSIDE"] = 1] = "TOUCH_OUTSIDE"; +DismissReason[DismissReason["CLOSE_BUTTON"] = 2] = "CLOSE_BUTTON"; +})(DismissReason || (DismissReason = {})); + var HoverEffect; (function (HoverEffect) { HoverEffect[HoverEffect["Auto"] = 4] = "Auto"; diff --git a/frameworks/bridge/declarative_frontend/frontend_delegate_declarative.cpp b/frameworks/bridge/declarative_frontend/frontend_delegate_declarative.cpp index dfc847eb2bd..055ae646647 100644 --- a/frameworks/bridge/declarative_frontend/frontend_delegate_declarative.cpp +++ b/frameworks/bridge/declarative_frontend/frontend_delegate_declarative.cpp @@ -1557,6 +1557,19 @@ void FrontendDelegateDeclarative::ShowDialog(const PromptDialogAttr& dialogAttr, ShowDialogInner(dialogProperties, std::move(callback), callbacks); } +void FrontendDelegateDeclarative::RemoveCustomDialog() +{ + auto context = NG::PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(context); + auto overlayManager = context->GetOverlayManager(); + CHECK_NULL_VOID(overlayManager); + auto rootNode = overlayManager->GetRootNode().Upgrade(); + CHECK_NULL_VOID(rootNode); + auto overlay = AceType::DynamicCast(rootNode->GetLastChild()); + CHECK_NULL_VOID(overlay); + overlayManager->RemoveDialog(overlay, false, false); +} + void FrontendDelegateDeclarative::OpenCustomDialog(const PromptDialogAttr &dialogAttr, std::function &&callback) { @@ -1566,6 +1579,7 @@ void FrontendDelegateDeclarative::OpenCustomDialog(const PromptDialogAttr &dialo .isSysBlurStyle = false, .customBuilder = dialogAttr.customBuilder, .maskRect = dialogAttr.maskRect, + .onWillDismiss = dialogAttr.customOnWillDismiss }; if (dialogAttr.alignment.has_value()) { dialogProperties.alignment = dialogAttr.alignment.value(); diff --git a/frameworks/bridge/declarative_frontend/frontend_delegate_declarative.h b/frameworks/bridge/declarative_frontend/frontend_delegate_declarative.h index 0b49fd6d0f8..c83e1d9bf0c 100644 --- a/frameworks/bridge/declarative_frontend/frontend_delegate_declarative.h +++ b/frameworks/bridge/declarative_frontend/frontend_delegate_declarative.h @@ -203,6 +203,7 @@ public: std::function&& onStatusChanged) override; void ShowDialogInner(DialogProperties& dialogProperties, std::function&& callback, const std::set& callbacks); + void RemoveCustomDialog() override; void OpenCustomDialog(const PromptDialogAttr &dialogAttr, std::function &&callback) override; void CloseCustomDialog(const int32_t dialogId) override; diff --git a/frameworks/bridge/declarative_frontend/jsview/action_sheet/js_action_sheet.cpp b/frameworks/bridge/declarative_frontend/jsview/action_sheet/js_action_sheet.cpp index cd7ed27dfc5..eb40b3cc97b 100644 --- a/frameworks/bridge/declarative_frontend/jsview/action_sheet/js_action_sheet.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/action_sheet/js_action_sheet.cpp @@ -167,6 +167,10 @@ void JSActionSheet::Show(const JSCallbackInfo& args) ActionSheetModel::GetInstance()->SetCancel(eventFunc, properties); } + std::function onWillDismissFunc = nullptr; + ParseDialogCallback(obj, onWillDismissFunc); + ActionSheetModel::GetInstance()->SetOnWillDismiss(std::move(onWillDismissFunc), properties); + // Parse confirm. auto confirmVal = obj->GetProperty("confirm"); if (confirmVal->IsObject()) { diff --git a/frameworks/bridge/declarative_frontend/jsview/dialog/js_alert_dialog.cpp b/frameworks/bridge/declarative_frontend/jsview/dialog/js_alert_dialog.cpp index d1c7e084c3d..c44bade433d 100644 --- a/frameworks/bridge/declarative_frontend/jsview/dialog/js_alert_dialog.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/dialog/js_alert_dialog.cpp @@ -216,6 +216,10 @@ void JSAlertDialog::Show(const JSCallbackInfo& args) }; AlertDialogModel::GetInstance()->SetOnCancel(eventFunc, properties); } + + std::function onWillDismissFunc = nullptr; + ParseDialogCallback(obj, onWillDismissFunc); + AlertDialogModel::GetInstance()->SetOnWillDismiss(std::move(onWillDismissFunc), properties); if (obj->GetProperty("confirm")->IsObject()) { // Parse confirm. diff --git a/frameworks/bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.cpp b/frameworks/bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.cpp index 9bf3713acf1..8c548d0e1ce 100644 --- a/frameworks/bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.cpp @@ -26,6 +26,7 @@ #include "core/components_ng/pattern/dialog/custom_dialog_controller_model_ng.h" #include "core/pipeline_ng/pipeline_context.h" #include "frameworks/bridge/common/utils/engine_helper.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h" namespace OHOS::Ace { std::unique_ptr CustomDialogControllerModel::instance_ = nullptr; @@ -107,6 +108,10 @@ void JSCustomDialogController::ConstructorCallback(const JSCallbackInfo& info) instance->dialogProperties_.onCancel = onCancel; } + std::function onWillDismissFunc = nullptr; + JSViewAbstract::ParseDialogCallback(constructorArg, onWillDismissFunc); + instance->dialogProperties_.onWillDismiss = onWillDismissFunc; + // Parses autoCancel. JSRef autoCancelValue = constructorArg->GetProperty("autoCancel"); if (autoCancelValue->IsBoolean()) { diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index 29cfe9dea63..fd1a063bbd0 100755 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -143,6 +143,7 @@ constexpr double VISIBLE_RATIO_MAX = 1.0; constexpr int32_t PARAMETER_LENGTH_FIRST = 1; constexpr int32_t PARAMETER_LENGTH_SECOND = 2; constexpr int32_t PARAMETER_LENGTH_THIRD = 3; +constexpr uint32_t ON_WILL_DISMISS_FIELD_COUNT = 2; constexpr float DEFAULT_SCALE_LIGHT = 0.9f; constexpr float DEFAULT_SCALE_MIDDLE_OR_HEAVY = 0.95f; constexpr float MAX_ANGLE = 360.0f; @@ -5246,6 +5247,32 @@ void JSViewAbstract::JsBindPopup(const JSCallbackInfo& info) } #endif +void JSViewAbstract::ParseDialogCallback(const JSRef& paramObj, + std::function& onWillDismiss) +{ + auto onWillDismissFunc = paramObj->GetProperty("onWillDismiss"); + if (onWillDismissFunc->IsFunction()) { + RefPtr jsFunc = + AceType::MakeRefPtr(JSRef(), JSRef::Cast(onWillDismissFunc)); + onWillDismiss = [func = std::move(jsFunc)](const int32_t& info) { + JSRef objectTemplate = JSRef::New(); + objectTemplate->SetInternalFieldCount(ON_WILL_DISMISS_FIELD_COUNT); + JSRef dismissObj = objectTemplate->NewInstance(); + dismissObj->SetPropertyObject( + "dismiss", JSRef::New(JSViewAbstract::JsDismissDialog)); + dismissObj->SetProperty("reason", info); + JSRef newJSVal = JSRef::Cast(dismissObj); + func->ExecuteJS(1, &newJSVal); + }; + } +} + +panda::Local JSViewAbstract::JsDismissDialog(panda::JsiRuntimeCallInfo* runtimeCallInfo) +{ + ViewAbstractModel::GetInstance()->DismissDialog(); + return JSValueRef::Undefined(runtimeCallInfo->GetVM()); +} + void JSViewAbstract::JsLinearGradient(const JSCallbackInfo& info) { std::vector checkList { JSCallbackInfoType::OBJECT }; diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h index 78d0d310536..0093beff7a5 100755 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h @@ -359,6 +359,9 @@ public: * Binds the native methods to the the js object */ static void JSBind(BindingTarget globalObj); + static void ParseDialogCallback(const JSRef& paramObj, + std::function& onWillDismiss); + static panda::Local JsDismissDialog(panda::JsiRuntimeCallInfo* runtimeCallInfo); static RefPtr GetPipelineContext() { diff --git a/frameworks/bridge/js_frontend/frontend_delegate.h b/frameworks/bridge/js_frontend/frontend_delegate.h index c223c6816b0..5e80d9abfcf 100644 --- a/frameworks/bridge/js_frontend/frontend_delegate.h +++ b/frameworks/bridge/js_frontend/frontend_delegate.h @@ -149,6 +149,7 @@ public: virtual void ShowDialog(const PromptDialogAttr& dialogAttr, const std::vector& buttons, std::function&& callback, const std::set& callbacks, std::function&& onStatusChanged) {}; + virtual void RemoveCustomDialog() {}; virtual void OpenCustomDialog(const PromptDialogAttr &dialogAttr, std::function &&callback) {}; virtual void CloseCustomDialog(const int32_t dialogId) {}; diff --git a/frameworks/core/components/dialog/dialog_properties.h b/frameworks/core/components/dialog/dialog_properties.h index b64b2103b80..76d6f1c9da0 100644 --- a/frameworks/core/components/dialog/dialog_properties.h +++ b/frameworks/core/components/dialog/dialog_properties.h @@ -164,6 +164,7 @@ struct DialogProperties { bool isSelect = false; // init checkbox state std::vector buttons; std::function onCancel; // NG cancel callback + std::function onWillDismiss; // Cancel Dismiss Callback std::function onSuccess; // NG prompt success callback std::function onChange; // onChange success callback DialogAlignment alignment = DialogAlignment::DEFAULT; // Alignment of dialog. @@ -208,6 +209,7 @@ struct PromptDialogAttr { bool showInSubWindow = false; bool isModal = false; std::function customBuilder; + std::function customOnWillDismiss; std::optional alignment; std::optional offset; diff --git a/frameworks/core/components_ng/base/view_abstract.cpp b/frameworks/core/components_ng/base/view_abstract.cpp index bd978d62d0e..31f663f7bed 100755 --- a/frameworks/core/components_ng/base/view_abstract.cpp +++ b/frameworks/core/components_ng/base/view_abstract.cpp @@ -1387,6 +1387,24 @@ void ViewAbstract::BindPopup(const RefPtr ¶m, const RefPtrGetOverlayManager(); + CHECK_NULL_VOID(overlayManager); + auto rootNode = overlayManager->GetRootNode().Upgrade(); + CHECK_NULL_VOID(rootNode); + auto overlay = AceType::DynamicCast(rootNode->GetLastChild()); + CHECK_NULL_VOID(overlay); + overlayManager->RemoveDialog(overlay, false, false); + auto pattern = overlay->GetPattern(); + CHECK_NULL_VOID(pattern); + if (overlayManager->isMaskNode(pattern->GetHost()->GetId())) { + overlayManager->PopModalDialog(pattern->GetHost()->GetId()); + } +} + void ViewAbstract::BindMenuWithItems(std::vector &¶ms, const RefPtr &targetNode, const NG::OffsetF &offset, const MenuParam &menuParam) { diff --git a/frameworks/core/components_ng/base/view_abstract.h b/frameworks/core/components_ng/base/view_abstract.h index 88e84976090..1f1282fc84f 100644 --- a/frameworks/core/components_ng/base/view_abstract.h +++ b/frameworks/core/components_ng/base/view_abstract.h @@ -273,6 +273,7 @@ public: // Bind properties static void BindPopup(const RefPtr ¶m, const RefPtr &targetNode, const RefPtr &customNode); + static void DismissDialog(); static void BindMenuWithItems(std::vector &¶ms, const RefPtr &targetNode, const NG::OffsetF &offset, const MenuParam &menuParam); static void BindMenuWithCustomNode(const RefPtr &customNode, const RefPtr &targetNode, diff --git a/frameworks/core/components_ng/base/view_abstract_model.h b/frameworks/core/components_ng/base/view_abstract_model.h index f9530ae00e4..372c466ea62 100755 --- a/frameworks/core/components_ng/base/view_abstract_model.h +++ b/frameworks/core/components_ng/base/view_abstract_model.h @@ -296,6 +296,7 @@ public: std::function&& onAppear, std::function&& onDisappear, std::function&& shouldDismiss) = 0; virtual void DismissSheet() = 0; + virtual void DismissDialog() {}; // accessibility virtual void SetAccessibilityGroup(bool accessible) = 0; diff --git a/frameworks/core/components_ng/base/view_abstract_model_ng.h b/frameworks/core/components_ng/base/view_abstract_model_ng.h index 46b08610acc..828642e9c9c 100755 --- a/frameworks/core/components_ng/base/view_abstract_model_ng.h +++ b/frameworks/core/components_ng/base/view_abstract_model_ng.h @@ -992,6 +992,11 @@ public: ViewAbstract::BindPopup(param, targetNode, AceType::DynamicCast(customNode)); } + void DismissDialog() override + { + ViewAbstract::DismissDialog(); + } + void BindBackground(std::function&& buildFunc, const Alignment& align) override; void BindMenuGesture( diff --git a/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model.h b/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model.h index a58c0fc5832..299eb24ac55 100644 --- a/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model.h +++ b/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model.h @@ -32,6 +32,8 @@ public: virtual void SetCancel(std::function&& eventFunc, DialogProperties& arg) = 0; virtual void SetConfirm(GestureEventFunc&& gestureEvent, std::function&& eventFunc, ButtonInfo& buttonInfo, DialogProperties& arg) = 0; + virtual void SetOnWillDismiss(std::function&& onWillDismissFunc, + DialogProperties& arg) {}; private: static std::unique_ptr instance_; diff --git a/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model_ng.cpp b/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model_ng.cpp index 503166245c8..884f8cfada5 100644 --- a/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model_ng.cpp +++ b/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model_ng.cpp @@ -57,6 +57,12 @@ void ActionSheetModelNG::SetCancel(std::function&& eventFunc, DialogProp arg.onCancel = eventFunc; } +void ActionSheetModelNG::SetOnWillDismiss(std::function&& onWillDismissFunc, + DialogProperties& arg) +{ + arg.onWillDismiss = std::move(onWillDismissFunc); +} + void ActionSheetModelNG::SetConfirm( GestureEventFunc&& gestureEvent, std::function&& eventFunc, ButtonInfo& buttonInfo, DialogProperties& arg) { diff --git a/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model_ng.h b/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model_ng.h index dba53c6a5ac..7636b96d711 100644 --- a/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model_ng.h +++ b/frameworks/core/components_ng/pattern/action_sheet/action_sheet_model_ng.h @@ -27,6 +27,8 @@ public: void SetCancel(std::function&& eventFunc, DialogProperties& arg) override; void SetConfirm(GestureEventFunc&& gestureEvent, std::function&& eventFunc, ButtonInfo& buttonInfo, DialogProperties& arg) override; + void SetOnWillDismiss(std::function&& onWillDismissFunc, + DialogProperties& arg) override; }; } // namespace OHOS::Ace::NG #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_ACTION_SHEET_ACTION_SHEET_MODEL_NG_H diff --git a/frameworks/core/components_ng/pattern/dialog/alert_dialog_model.h b/frameworks/core/components_ng/pattern/dialog/alert_dialog_model.h index e8d2ac7ac16..99ba3559e52 100644 --- a/frameworks/core/components_ng/pattern/dialog/alert_dialog_model.h +++ b/frameworks/core/components_ng/pattern/dialog/alert_dialog_model.h @@ -29,6 +29,8 @@ public: const std::string& property) = 0; virtual void SetOnCancel(std::function&& eventFunc, DialogProperties& arg) = 0; virtual void SetShowDialog(const DialogProperties& arg) = 0; + virtual void SetOnWillDismiss(std::function&& onWillDismissFunc, + DialogProperties& arg) {}; private: static std::unique_ptr instance_; diff --git a/frameworks/core/components_ng/pattern/dialog/alert_dialog_model_ng.cpp b/frameworks/core/components_ng/pattern/dialog/alert_dialog_model_ng.cpp index 435636cb934..f3e4fc5927b 100644 --- a/frameworks/core/components_ng/pattern/dialog/alert_dialog_model_ng.cpp +++ b/frameworks/core/components_ng/pattern/dialog/alert_dialog_model_ng.cpp @@ -18,6 +18,7 @@ #include "core/common/ace_engine.h" #include "core/components_ng/base/ui_node.h" #include "core/components_ng/base/view_abstract.h" +#include "core/components_ng/pattern/dialog/dialog_pattern.h" #include "core/pipeline_ng/pipeline_context.h" namespace OHOS::Ace::NG { @@ -34,6 +35,12 @@ void AlertDialogModelNG::SetOnCancel(std::function&& eventFunc, DialogPr arg.onCancel = eventFunc; } +void AlertDialogModelNG::SetOnWillDismiss(std::function&& onWillDismissFunc, + DialogProperties& arg) +{ + arg.onWillDismiss = std::move(onWillDismissFunc); +} + void AlertDialogModelNG::SetShowDialog(const DialogProperties& arg) { auto container = Container::Current(); @@ -64,6 +71,7 @@ void AlertDialogModelNG::SetShowDialog(const DialogProperties& arg) DialogProperties Maskarg; Maskarg.isMask = true; Maskarg.autoCancel = arg.autoCancel; + Maskarg.onWillDismiss = arg.onWillDismiss; auto mask = overlayManager->ShowDialog(Maskarg, nullptr, false); overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId()); CHECK_NULL_VOID(mask); @@ -74,6 +82,9 @@ void AlertDialogModelNG::SetShowDialog(const DialogProperties& arg) } auto hub = dialog->GetEventHub(); hub->SetOnCancel(arg.onCancel); + auto pattern = dialog->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->SetOnWillDismiss(arg.onWillDismiss); }, TaskExecutor::TaskType::UI); } diff --git a/frameworks/core/components_ng/pattern/dialog/alert_dialog_model_ng.h b/frameworks/core/components_ng/pattern/dialog/alert_dialog_model_ng.h index 1a3ce339c2f..42e56c90e97 100644 --- a/frameworks/core/components_ng/pattern/dialog/alert_dialog_model_ng.h +++ b/frameworks/core/components_ng/pattern/dialog/alert_dialog_model_ng.h @@ -25,6 +25,8 @@ public: const std::string& property) override; void SetOnCancel(std::function&& eventFunc, DialogProperties& arg) override; void SetShowDialog(const DialogProperties& arg) override; + void SetOnWillDismiss(std::function&& onWillDismissFunc, + DialogProperties& arg) override; }; } // namespace OHOS::Ace::NG #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_DIALOG_FORM_FORM_MODEL_NG_H diff --git a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.cpp b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.cpp index 8fc446319ea..101826f0f85 100755 --- a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.cpp +++ b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.cpp @@ -137,6 +137,11 @@ void DialogPattern::HandleClick(const GestureEvent& info) auto&& clickPosition = info.GetGlobalLocation(); if (!contentRect.IsInRegion( PointF(clickPosition.GetX() - globalOffset.GetX(), clickPosition.GetY() - globalOffset.GetY()))) { + if (this->ShouldDismiss()) { + this->CallOnWillDismiss(static_cast(DialogDismissReason::DIALOG_TOUCH_OUTSIDE)); + TAG_LOGI(AceLogTag::ACE_DIALOG, "Dialog Should Dismiss"); + return; + } PopDialog(-1); auto pipeline = PipelineContext::GetCurrentContext(); CHECK_NULL_VOID(pipeline); diff --git a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h index e8728aa6423..4d818f52b21 100644 --- a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h +++ b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h @@ -31,6 +31,12 @@ #include "core/components_ng/pattern/overlay/popup_base_pattern.h" namespace OHOS::Ace::NG { + +enum class DialogDismissReason { + DIALOG_PRESS_BACK = 0, + DIALOG_TOUCH_OUTSIDE, + DIALOG_CLOSE_BUTTON, +}; class DialogPattern : public PopupBasePattern { DECLARE_ACE_TYPE(DialogPattern, PopupBasePattern); @@ -45,6 +51,26 @@ public: return false; } + void SetOnWillDismiss(const std::function& onWillDismiss) + { + onWillDismiss_ = onWillDismiss; + } + + bool ShouldDismiss() const + { + if (onWillDismiss_) { + return true; + } + return false; + } + + void CallOnWillDismiss(const int32_t reason) + { + if (onWillDismiss_) { + onWillDismiss_(reason); + } + } + RefPtr CreateLayoutProperty() override { return AceType::MakeRefPtr(); @@ -182,6 +208,7 @@ private: std::string message_; std::string title_; std::string subtitle_; + std::function onWillDismiss_; DialogProperties dialogProperties_; WeakPtr menuNode_; diff --git a/frameworks/core/components_ng/pattern/dialog/dialog_view.cpp b/frameworks/core/components_ng/pattern/dialog/dialog_view.cpp index 2010cdacba1..08477aac963 100644 --- a/frameworks/core/components_ng/pattern/dialog/dialog_view.cpp +++ b/frameworks/core/components_ng/pattern/dialog/dialog_view.cpp @@ -91,6 +91,7 @@ RefPtr DialogView::CreateDialogNode( auto pattern = dialog->GetPattern(); CHECK_NULL_RETURN(pattern, nullptr); pattern->BuildChild(param); + pattern->SetOnWillDismiss(param.onWillDismiss); // set open and close animation pattern->SetOpenAnimation(param.openAnimation); diff --git a/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp b/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp index 76df1a9786f..befca0a597d 100644 --- a/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp +++ b/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp @@ -1698,6 +1698,13 @@ bool OverlayManager::RemoveOverlay(bool isBackPressed, bool isPageRouter) } } if (InstanceOf(pattern)) { + auto dialogPattern = DynamicCast(pattern); + CHECK_NULL_RETURN(dialogPattern, false); + if (dialogPattern->ShouldDismiss()) { + dialogPattern->CallOnWillDismiss(static_cast(DialogDismissReason::DIALOG_PRESS_BACK)); + TAG_LOGI(AceLogTag::ACE_OVERLAY, "Dialog Should Dismiss"); + return true; + } return RemoveDialog(overlay, isBackPressed, isPageRouter); } if (InstanceOf(pattern)) { @@ -1912,6 +1919,13 @@ bool OverlayManager::RemoveOverlayInSubwindow() // close dialog with animation auto pattern = overlay->GetPattern(); if (InstanceOf(pattern)) { + auto dialogPattern = DynamicCast(pattern); + CHECK_NULL_RETURN(dialogPattern, false); + if (dialogPattern->ShouldDismiss()) { + dialogPattern->CallOnWillDismiss(static_cast(DialogDismissReason::DIALOG_PRESS_BACK)); + TAG_LOGI(AceLogTag::ACE_OVERLAY, "Dialog Should Dismiss"); + return true; + } return RemoveDialog(overlay, false, false); } if (InstanceOf(pattern)) { diff --git a/interfaces/napi/kits/promptaction/prompt_action.cpp b/interfaces/napi/kits/promptaction/prompt_action.cpp index 53e697d9d9d..9565c404236 100644 --- a/interfaces/napi/kits/promptaction/prompt_action.cpp +++ b/interfaces/napi/kits/promptaction/prompt_action.cpp @@ -226,6 +226,7 @@ struct PromptAsyncContext { napi_value offsetApi = nullptr; napi_value maskRectApi = nullptr; napi_value builder = nullptr; + napi_value onWillDismiss = nullptr; napi_ref callbackSuccess = nullptr; napi_ref callbackCancel = nullptr; napi_ref callbackComplete = nullptr; @@ -242,6 +243,7 @@ struct PromptAsyncContext { napi_deferred deferred = nullptr; napi_ref callbackRef = nullptr; napi_ref builderRef = nullptr; + napi_ref onWillDismissRef = nullptr; int32_t callbackType = -1; int32_t successType = -1; bool valid = true; @@ -423,6 +425,12 @@ bool JSPromptParseParam(napi_env env, size_t argc, napi_value* argv, std::shared if (valueType == napi_boolean) { napi_get_value_bool(env, asyncContext->isModal, &asyncContext->isModalBool); } + + napi_get_named_property(env, argv[0], "onWillDismiss", &asyncContext->onWillDismiss); + napi_typeof(env, asyncContext->onWillDismiss, &valueType); + if (valueType == napi_function) { + napi_create_reference(env, asyncContext->onWillDismiss, 1, &asyncContext->onWillDismissRef); + } } else if (valueType == napi_function) { napi_create_reference(env, argv[i], 1, &asyncContext->callbackRef); } else { @@ -890,6 +898,38 @@ napi_value JSPromptShowActionMenu(napi_env env, napi_callback_info info) return result; } +napi_value JSRemoveCustomDialog(napi_env env, napi_callback_info info) +{ + auto delegate = EngineHelper::GetCurrentDelegateSafely(); + if (delegate) { + delegate->RemoveCustomDialog(); + } + return nullptr; +} + +void ParseDialogCallback(std::shared_ptr& asyncContext, + std::function& onWillDismiss) +{ + onWillDismiss = [env = asyncContext->env, onWillDismissRef = asyncContext->onWillDismissRef] + (const int32_t& info) { + if (onWillDismissRef) { + napi_value onWillDismissFunc = nullptr; + napi_value value = nullptr; + napi_value funcValue = nullptr; + napi_value paramObj = nullptr; + napi_create_object(env, ¶mObj); + + napi_create_function(env, "dismiss", strlen("dismiss"), JSRemoveCustomDialog, nullptr, &funcValue); + napi_set_named_property(env, paramObj, "dismiss", funcValue); + + napi_create_int32(env, info, &value); + napi_set_named_property(env, paramObj, "reason", value); + napi_get_reference_value(env, onWillDismissRef, &onWillDismissFunc); + napi_call_function(env, nullptr, onWillDismissFunc, 1, ¶mObj, nullptr); + } + }; +} + napi_value JSPromptOpenCustomDialog(napi_env env, napi_callback_info info) { size_t requireArgc = 1; @@ -972,10 +1012,15 @@ napi_value JSPromptOpenCustomDialog(napi_env env, napi_callback_info info) napi_delete_reference(env, builderRef); } }; + std::function onWillDismiss = nullptr; + if (asyncContext->onWillDismissRef) { + ParseDialogCallback(asyncContext, onWillDismiss); + } PromptDialogAttr promptDialogAttr = { .showInSubWindow = asyncContext->showInSubWindowBool, .isModal = asyncContext->isModalBool, .customBuilder = std::move(builder), + .customOnWillDismiss = std::move(onWillDismiss), .alignment = alignment, .offset = offset, .maskRect = maskRect, -- Gitee