From 969b0da91ea3880b84058553490c5cba187d8c11 Mon Sep 17 00:00:00 2001 From: DuanXipu Date: Mon, 8 Sep 2025 19:50:26 +0800 Subject: [PATCH] add arkweb snapshot remove with animation function Signed-off-by: DuanXipu --- .../web/resource/web_client_impl.cpp | 7 +++ .../components/web/resource/web_client_impl.h | 1 + .../components/web/resource/web_delegate.cpp | 6 +-- .../components/web/resource/web_delegate.h | 2 +- .../components_ng/pattern/web/web_pattern.cpp | 44 ++++++++++++++++++- .../components_ng/pattern/web/web_pattern.h | 4 +- .../core/pattern/web/mock_web_delegate.cpp | 2 +- .../web/web_pattern_select_test_ng.cpp | 36 ++++++++++++++- .../core/pattern/web/web_pattern_test_ng.cpp | 31 ++++++++++++- 9 files changed, 123 insertions(+), 10 deletions(-) diff --git a/frameworks/core/components/web/resource/web_client_impl.cpp b/frameworks/core/components/web/resource/web_client_impl.cpp index ac6d708047a..71d2b845ce7 100644 --- a/frameworks/core/components/web/resource/web_client_impl.cpp +++ b/frameworks/core/components/web/resource/web_client_impl.cpp @@ -1621,4 +1621,11 @@ void WebClientImpl::OnRefreshAccessedHistoryV2(const std::string& url, bool isRe ContainerScope scope(delegate->GetInstanceId()); delegate->OnRefreshAccessedHistory(url, isReload, isMainFrame); } + +void WebClientImpl::OnRemoveBlanklessFrameWithAnimation(int delayTime) +{ + auto delegate = webDelegate_.Upgrade(); + CHECK_NULL_VOID(delegate); + delegate->RemoveSnapshotFrameNode(delayTime, true); +} } // namespace OHOS::Ace diff --git a/frameworks/core/components/web/resource/web_client_impl.h b/frameworks/core/components/web/resource/web_client_impl.h index c5aaf768aa2..057d2015fd2 100644 --- a/frameworks/core/components/web/resource/web_client_impl.h +++ b/frameworks/core/components/web/resource/web_client_impl.h @@ -347,6 +347,7 @@ public: bool IsShowHandle() override; void OnSafeBrowsingCheckFinish(int threat_type) override; void OnRefreshAccessedHistoryV2(const std::string& url, bool isReload, bool isMainFrame) override; + void OnRemoveBlanklessFrameWithAnimation(int delayTime) override; private: std::weak_ptr webviewWeak_; WeakPtr webDelegate_; diff --git a/frameworks/core/components/web/resource/web_delegate.cpp b/frameworks/core/components/web/resource/web_delegate.cpp index 5e2d8c8350e..38f510a7cfd 100644 --- a/frameworks/core/components/web/resource/web_delegate.cpp +++ b/frameworks/core/components/web/resource/web_delegate.cpp @@ -6199,19 +6199,19 @@ bool WebDelegate::OnHandleInterceptUrlLoading(const std::string& data) return result; } -void WebDelegate::RemoveSnapshotFrameNode(int removeDelayTime) +void WebDelegate::RemoveSnapshotFrameNode(int removeDelayTime, bool isAnimate) { TAG_LOGD(AceLogTag::ACE_WEB, "blankless WebDelegate::RemoveSnapshotFrameNode"); auto context = context_.Upgrade(); CHECK_NULL_VOID(context); CHECK_NULL_VOID(context->GetTaskExecutor()); context->GetTaskExecutor()->PostDelayedTask( - [weak = WeakClaim(this)]() { + [weak = WeakClaim(this), isAnimate]() { auto delegate = weak.Upgrade(); CHECK_NULL_VOID(delegate); auto webPattern = delegate->webPattern_.Upgrade(); CHECK_NULL_VOID(webPattern); - webPattern->RemoveSnapshotFrameNode(); + webPattern->RemoveSnapshotFrameNode(isAnimate); }, TaskExecutor::TaskType::UI, removeDelayTime, "ArkUIWebSnapshotRemove"); } diff --git a/frameworks/core/components/web/resource/web_delegate.h b/frameworks/core/components/web/resource/web_delegate.h index f241e29876b..89d7e294495 100644 --- a/frameworks/core/components/web/resource/web_delegate.h +++ b/frameworks/core/components/web/resource/web_delegate.h @@ -1420,7 +1420,7 @@ public: int GetLastHitTestResult(); int GetHitTestResult(); - void RemoveSnapshotFrameNode(int removeDelayTime); + void RemoveSnapshotFrameNode(int removeDelayTime, bool isAnimate = false); void CreateSnapshotFrameNode(const std::string& snapshotPath, uint32_t width = 0, uint32_t height = 0); void SetVisibility(bool isVisible); void RecordBlanklessFrameSize(uint32_t width, uint32_t height); diff --git a/frameworks/core/components_ng/pattern/web/web_pattern.cpp b/frameworks/core/components_ng/pattern/web/web_pattern.cpp index f55abe8c5fa..e0d77f278d9 100644 --- a/frameworks/core/components_ng/pattern/web/web_pattern.cpp +++ b/frameworks/core/components_ng/pattern/web/web_pattern.cpp @@ -111,6 +111,7 @@ const std::string WEB_SNAPSHOT_PATH_PNG_SUFFIX = ".png"; const std::string WEB_SNAPSHOT_PATH_HEIC_SUFFIX = ".heic"; constexpr int32_t UPDATE_WEB_LAYOUT_DELAY_TIME = 20; constexpr int32_t AUTOFILL_DELAY_TIME = 200; +constexpr int32_t SNAPSHOT_DURATION_TIME = 300; constexpr int32_t IMAGE_POINTER_CUSTOM_CHANNEL = 4; constexpr int32_t TOUCH_EVENT_MAX_SIZE = 5; constexpr int32_t MOUSE_EVENT_MAX_SIZE = 10; @@ -915,7 +916,45 @@ void WebPattern::CreateSnapshotImageFrameNode(const std::string& snapshotPath, u snapshotNode->MarkModifyDone(); } -void WebPattern::RemoveSnapshotFrameNode() +void WebPattern::RemoveSnapshotFrameNode(bool isAnimate) +{ + if (!isAnimate) { + RealRemoveSnapshotFrameNode(); + return; + } + if (!snapshotImageNodeId_.has_value()) { + return; + } + if (isSnapshotImageAnimating_) { + return; + } + if (delegate_) { + delegate_->RecordBlanklessFrameSize(0, 0); + } + TAG_LOGI(AceLogTag::ACE_WEB, "blankless RemoveSnapshotFrameNode with animation"); + auto snapshotNode = FrameNode::GetFrameNode(V2::IMAGE_ETS_TAG, snapshotImageNodeId_.value()); + isSnapshotImageAnimating_ = true; + auto webPattern = WeakClaim(this); + AnimationOption option; + option.SetDuration(SNAPSHOT_DURATION_TIME); + option.SetCurve(Curves::EASE_IN_OUT); + option.SetOnFinishEvent([webPattern]() { + auto web = webPattern.Upgrade(); + TAG_LOGI(AceLogTag::ACE_WEB, "blankless animation end"); + CHECK_NULL_VOID(web); + web->RealRemoveSnapshotFrameNode(); + }); + + auto snapshotRsContext = snapshotNode->GetRenderContext(); + CHECK_NULL_VOID(snapshotRsContext); + snapshotRsContext->OpacityAnimation(option, 1.0, 0.0); + auto parent = snapshotNode->GetParent(); + CHECK_NULL_VOID(parent); + parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); + TAG_LOGI(AceLogTag::ACE_WEB, "blankless animation start"); +} + +void WebPattern::RealRemoveSnapshotFrameNode() { if (!snapshotImageNodeId_.has_value()) { return; @@ -923,9 +962,10 @@ void WebPattern::RemoveSnapshotFrameNode() if (delegate_) { delegate_->RecordBlanklessFrameSize(0, 0); } - TAG_LOGI(AceLogTag::ACE_WEB, "blankless RemoveSnapshotFrameNode"); + TAG_LOGI(AceLogTag::ACE_WEB, "blankless RealRemoveSnapshotFrameNode"); auto snapshotNode = FrameNode::GetFrameNode(V2::IMAGE_ETS_TAG, snapshotImageNodeId_.value()); snapshotImageNodeId_.reset(); + isSnapshotImageAnimating_ = false; CHECK_NULL_VOID(snapshotNode); auto parent = snapshotNode->GetParent(); CHECK_NULL_VOID(parent); diff --git a/frameworks/core/components_ng/pattern/web/web_pattern.h b/frameworks/core/components_ng/pattern/web/web_pattern.h index 96946b1b5f7..692812ae2e6 100644 --- a/frameworks/core/components_ng/pattern/web/web_pattern.h +++ b/frameworks/core/components_ng/pattern/web/web_pattern.h @@ -907,7 +907,8 @@ public: } void CreateSnapshotImageFrameNode(const std::string& snapshotPath, uint32_t width, uint32_t height); - void RemoveSnapshotFrameNode(); + void RemoveSnapshotFrameNode(bool isAnimate = false); + void RealRemoveSnapshotFrameNode(); void OnPip(int status, int delegateId, int childId, int frameRoutingId, int width, int height); void SetPipNativeWindow(int delegateId, int childId, int frameRoutingId, void* window); @@ -1324,6 +1325,7 @@ private: WebElementType curElementType_ = WebElementType::NONE; ResponseType curResponseType_ = ResponseType::LONG_PRESS; bool curContextMenuResult_ = false; + bool isSnapshotImageAnimating_ = false; bool isWindowShow_ = true; bool isActive_ = true; diff --git a/test/unittest/core/pattern/web/mock_web_delegate.cpp b/test/unittest/core/pattern/web/mock_web_delegate.cpp index bbc8e2181e6..16c3daf9fde 100644 --- a/test/unittest/core/pattern/web/mock_web_delegate.cpp +++ b/test/unittest/core/pattern/web/mock_web_delegate.cpp @@ -1389,7 +1389,7 @@ bool WebDelegate::GetAccessibilityVisible(int64_t accessibilityId) return false; } -void WebDelegate::RemoveSnapshotFrameNode(int removeDelayTime) {} +void WebDelegate::RemoveSnapshotFrameNode(int removeDelayTime, bool isAnimate = false) {} void WebDelegate::CreateSnapshotFrameNode(const std::string& snapshotPath, uint32_t width, uint32_t height) {} void WebDelegate::SetVisibility(bool isVisible) { diff --git a/test/unittest/core/pattern/web/web_pattern_select_test_ng.cpp b/test/unittest/core/pattern/web/web_pattern_select_test_ng.cpp index a025e8ee772..7b7e9f4d6ff 100755 --- a/test/unittest/core/pattern/web/web_pattern_select_test_ng.cpp +++ b/test/unittest/core/pattern/web/web_pattern_select_test_ng.cpp @@ -1549,7 +1549,7 @@ HWTEST_F(WebPatternSelectTestNg, UninitRotationEventCallback_001, TestSize.Level HWTEST_F(WebPatternSelectTestNg, CreateSnapshotImageFrameNode_001, TestSize.Level1) { #ifdef OHOS_STANDARD_SYSTEM - auto* stack = ViewStackProcessor::GetInstance(); + auto* stack = ViewStackProcessor::GetInstance(); ASSERT_NE(stack, nullptr); auto nodeId = stack->ClaimNodeId(); auto frameNode = @@ -1575,6 +1575,40 @@ HWTEST_F(WebPatternSelectTestNg, CreateSnapshotImageFrameNode_001, TestSize.Leve #endif } +/** + * @tc.name: CreateSnapshotImageFrameNode_002 + * @tc.desc: CreateSnapshotImageFrameNode. + * @tc.type: FUNC + */ +HWTEST_F(WebPatternSelectTestNg, CreateSnapshotImageFrameNode_002, TestSize.Level1) +{ +#ifdef OHOS_STANDARD_SYSTEM + auto* stack = ViewStackProcessor::GetInstance(); + ASSERT_NE(stack, nullptr); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = + FrameNode::GetOrCreateFrameNode(V2::WEB_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + stack->Push(frameNode); + auto webPattern = frameNode->GetPattern(); + ASSERT_NE(webPattern, nullptr); + webPattern->OnModifyDone(); + ASSERT_NE(webPattern->delegate_, nullptr); + MockPipelineContext::SetUp(); + std::string snapshotPath = "/data/storage/el2/base/cache/web/snapshot/123456.png"; + webPattern->CreateSnapshotImageFrameNode(snapshotPath, 100, 100); + snapshotPath = "/data/storage/el2/base/cache/web/snapshot/web_frame_123456"; + webPattern->CreateSnapshotImageFrameNode(snapshotPath, 100, 100); + snapshotPath = "/data/storage/el2/base/cache/web/snapshot/web_frame_123456.png"; + webPattern->CreateSnapshotImageFrameNode(snapshotPath, 100, 100); + snapshotPath = "/data/storage/el2/base/cache/web/snapshot/web_frame_123456.heic"; + webPattern->CreateSnapshotImageFrameNode(snapshotPath, 100, 100); + webPattern->RemoveSnapshotFrameNode(true); + webPattern->RemoveSnapshotFrameNode(true); + ASSERT_NE(webPattern, nullptr); + MockPipelineContext::TearDown(); +#endif +} + /** * @tc.name: GetShadowFromTheme_001 * @tc.desc: GetShadowFromTheme when get type none. diff --git a/test/unittest/core/pattern/web/web_pattern_test_ng.cpp b/test/unittest/core/pattern/web/web_pattern_test_ng.cpp index d81dd08784a..58eaf6aaf50 100755 --- a/test/unittest/core/pattern/web/web_pattern_test_ng.cpp +++ b/test/unittest/core/pattern/web/web_pattern_test_ng.cpp @@ -4575,7 +4575,7 @@ HWTEST_F(WebPatternTestNg, OnPipPip_007, TestSize.Level1) HWTEST_F(WebPatternTestNg, CreateSnapshotImageFrameNode_001, TestSize.Level1) { #ifdef OHOS_STANDARD_SYSTEM - auto* stack = ViewStackProcessor::GetInstance(); + auto* stack = ViewStackProcessor::GetInstance(); ASSERT_NE(stack, nullptr); auto nodeId = stack->ClaimNodeId(); auto frameNode = @@ -4596,6 +4596,35 @@ HWTEST_F(WebPatternTestNg, CreateSnapshotImageFrameNode_001, TestSize.Level1) #endif } +/** + * @tc.name: CreateSnapshotImageFrameNode_002 + * @tc.desc: CreateSnapshotImageFrameNode. + * @tc.type: FUNC + */ +HWTEST_F(WebPatternTestNg, CreateSnapshotImageFrameNode_002, TestSize.Level1) +{ +#ifdef OHOS_STANDARD_SYSTEM + auto* stack = ViewStackProcessor::GetInstance(); + ASSERT_NE(stack, nullptr); + auto nodeId = stack->ClaimNodeId(); + auto frameNode = + FrameNode::GetOrCreateFrameNode(V2::WEB_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr(); }); + stack->Push(frameNode); + auto webPattern = frameNode->GetPattern(); + ASSERT_NE(webPattern, nullptr); + webPattern->OnModifyDone(); + ASSERT_NE(webPattern->delegate_, nullptr); + MockPipelineContext::SetUp(); + EXPECT_EQ(NWeb::IsSnapshotPathValid("/data/storage/el2/base/cache/web/snapshot/web_frame_123456.png"), true); + std::string snapshotPath = "/data/storage/el2/base/cache/web/snapshot/web_frame_123456.png"; + webPattern->CreateSnapshotImageFrameNode(snapshotPath, 100, 100); + webPattern->RemoveSnapshotFrameNode(true); + webPattern->RemoveSnapshotFrameNode(true); + ASSERT_NE(webPattern, nullptr); + MockPipelineContext::TearDown(); +#endif +} + /** * @tc.name: OnCssDisplayChangeEnabledUpdate_001 * @tc.desc: OnCssDisplayChangeEnabledUpdate. -- Gitee