diff --git a/frameworks/core/components/web/resource/web_client_impl.cpp b/frameworks/core/components/web/resource/web_client_impl.cpp index ac6d708047aa16a3b3f11ce74b38c40ac94329eb..71d2b845ce7ea0dc62088b4adbdaef487f547b2d 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 c5aaf768aa260f8aad3c0b4b79178b9f75dd9794..057d2015fd22e224ee896eacae979cc63996963c 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 5e2d8c8350ed2d61a6141e6ec739bde740a1c445..38f510a7cfdf2c7d4286518abec8156cabbaaf73 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 f241e29876be38d455a68ce7f8bfc8738af5ccaa..89d7e294495d8b83a5d60ab388f03b58cea894a1 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 f55abe8c5fa10c4833eb93612292974ddf020827..e0d77f278d9c600167464c2bbc65d74b7d3a4b97 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 96946b1b5f73f0846089826f53f78f25d1a5c9bb..692812ae2e67cc436927a0b4cbd8e2162c7c87a5 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 bbc8e2181e6bd8d1fad5d7e2011cf654131cf498..16c3daf9fde332602d69b66874fcc1dc3643293e 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 a025e8ee772a617a60b6033b7ff16ae53da0bb9e..7b7e9f4d6ffacec676745719d725b98ebef3e45f 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 d81dd08784a21c596c1800191e019b4556de4e39..58eaf6aaf50e42b93b64e8a75ef6790b8ab75100 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.