diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp index 3a9016efd87916a1a1085e3bbf4402f3ec80f09b..adae3f86e42fe2e740586aa3d774f7192eadce8b 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp @@ -4445,8 +4445,7 @@ void RichEditorPattern::OnDragEnd(const RefPtr& event) IF_PRESENT(host, MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF)); } -RefPtr RichEditorPattern::ToStyledString(int32_t start, int32_t end, - std::optional>> spans) +RefPtr RichEditorPattern::ToStyledString(int32_t start, int32_t end) { auto length = GetTextContentLength(); int32_t realStart = (start == -1) ? 0 : std::clamp(start, 0, length); @@ -4458,8 +4457,7 @@ RefPtr RichEditorPattern::ToStyledString(int32_t start, int32_t end, if (aiWriteAdapter_->GetAIWrite()) { SetSubSpansWithAIWrite(spanString, realStart, realEnd); } else { - auto& spansNew = spans.has_value() ? spans.value() : spans_; - SetSubSpans(spanString, realStart, realEnd, spansNew); + SetSubSpans(spanString, realStart, realEnd, spans_); } SetSubMap(spanString); return spanString; @@ -8412,6 +8410,23 @@ void RichEditorPattern::HandleOnCopyStyledString() #endif } +std::list> RichEditorPattern::CopySpansForClipboard() +{ + std::list> copySpans; + for (const auto& spanItem : spans_) { + // only make normal/image spanItem, because copy or cut only for normal/image spanItem + auto newSpanItem = GetSameSpanItem(spanItem); + CHECK_NULL_CONTINUE(newSpanItem); + newSpanItem->position = spanItem->position; + newSpanItem->rangeStart = spanItem->rangeStart; + newSpanItem->paragraphIndex = spanItem->paragraphIndex; + newSpanItem->content = spanItem->content; + newSpanItem->description = spanItem->description; + copySpans.emplace_back(newSpanItem); + } + return copySpans; +} + void RichEditorPattern::OnCopyOperation(bool isUsingExternalKeyboard) { if (isSpanStringMode_) { @@ -8428,15 +8443,16 @@ void RichEditorPattern::OnCopyOperation(bool isUsingExternalKeyboard) auto textSelectInfo = GetSpansInfo(selectStart, selectEnd, GetSpansMethod::ONSELECT); auto copyResultObjects = textSelectInfo.GetSelection().resultObjects; CHECK_NULL_VOID(!copyResultObjects.empty()); + std::list> copySpans = CopySpansForClipboard(); ACE_SCOPED_TRACE("RichEditorOnCopyOperation"); taskExecutor->PostTask( - [weak = WeakClaim(this), task = WeakClaim(RawPtr(taskExecutor)), copyResultObjects, spans = spans_]() { + [weak = WeakClaim(this), task = WeakClaim(RawPtr(taskExecutor)), copyResultObjects, copySpans]() { auto richEditor = weak.Upgrade(); CHECK_NULL_VOID(richEditor); ACE_SCOPED_TRACE("RichEditorAsyncHandleOnCopy"); RefPtr pasteData = richEditor->clipboard_->CreatePasteDataMix(); for (auto resultObj = copyResultObjects.rbegin(); resultObj != copyResultObjects.rend(); ++resultObj) { - richEditor->ProcessResultObject(pasteData, *resultObj, spans); + richEditor->ProcessResultObject(pasteData, *resultObj, copySpans); } auto uiTaskExecutor = task.Upgrade(); CHECK_NULL_VOID(uiTaskExecutor); @@ -8449,7 +8465,7 @@ void RichEditorPattern::OnCopyOperation(bool isUsingExternalKeyboard) } void RichEditorPattern::ProcessResultObject(RefPtr pasteData, const ResultObject& result, - const std::list> spans) + const std::list>& spans) { CHECK_NULL_VOID(pasteData); auto multiTypeRecordImpl = AceType::MakeRefPtr(); @@ -8500,10 +8516,13 @@ std::pair RichEditorPattern::GetSpanRangeByResultObject(const } RefPtr RichEditorPattern::GetSpanStringByResultObject(const ResultObject& result, - const std::list> spans) + const std::list>& spans) { auto [selectStart, selectEnd] = GetSpanRangeByResultObject(result); - return ToStyledString(selectStart, selectEnd, spans); + RefPtr spanString = MakeRefPtr(u""); + SetSubSpans(spanString, selectStart, selectEnd, spans); + SetSubMap(spanString); + return spanString; } void RichEditorPattern::HandleOnCopy(bool isUsingExternalKeyboard) diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h index 04e11e8621acd510c25ada7f3a6fdad6d88296be..c7885a521465b319094228c8534c23ba4f46f93c 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h @@ -808,8 +808,7 @@ public: bool BeforeAddImage(RichEditorChangeValue& changeValue, const ImageSpanOptions& options, int32_t insertIndex); bool BeforeSpansChange(const UndoRedoRecord& record, bool isUndo); void AfterSpansChange(const UndoRedoRecord& record, bool isUndo); - RefPtr ToStyledString(int32_t start, int32_t end, - std::optional>> spans = std::nullopt); + RefPtr ToStyledString(int32_t start, int32_t end); SelectionInfo FromStyledString(const RefPtr& spanString); bool BeforeAddSymbol(RichEditorChangeValue& changeValue, const SymbolSpanOptions& options); void AfterContentChange(RichEditorChangeValue& changeValue); @@ -1695,9 +1694,9 @@ private: void UpdateGestureHotZone(const RefPtr& dirty); void ClearOnFocusTextField(FrameNode* node); void ProcessResultObject(RefPtr pasteData, const ResultObject& result, - const std::list> spans); + const std::list>& spans); RefPtr GetSpanStringByResultObject(const ResultObject& result, - const std::list> spans); + const std::list>& spans); bool InitPreviewText(const std::u16string& previewTextValue, const PreviewRange& range); bool ReplaceText(const std::u16string& previewTextValue, const PreviewRange& range); bool UpdatePreviewText(const std::u16string& previewTextValue, const PreviewRange& range); @@ -1711,6 +1710,7 @@ private: bool NeedShowPlaceholder(); bool IsSelectAll() override; std::pair GetSpanRangeByResultObject(const ResultObject& result); + std::list> CopySpansForClipboard(); #ifdef CROSS_PLATFORM bool UnableStandardInputCrossPlatform(TextInputConfiguration& config, bool isFocusViewChanged); #endif diff --git a/test/unittest/core/pattern/rich_editor/rich_editor_pattern_testseven_ng.cpp b/test/unittest/core/pattern/rich_editor/rich_editor_pattern_testseven_ng.cpp index d14af7ca062b44fc2394b807e19bca1aa54f3423..f4917fb56c202dede90f7d7f4f239ddae3f3c806 100644 --- a/test/unittest/core/pattern/rich_editor/rich_editor_pattern_testseven_ng.cpp +++ b/test/unittest/core/pattern/rich_editor/rich_editor_pattern_testseven_ng.cpp @@ -300,4 +300,39 @@ HWTEST_F(RichEditorPatternTestSevenNg, GetSpanRangeByResultObject, TestSize.Leve EXPECT_EQ(selectStart, selectStartResult); EXPECT_EQ(selectEnd, selectEndResult); } + +/** + * @tc.name: CopySpansForClipboard + * @tc.desc: test CopySpansForClipboard function + * @tc.type: FUNC + */ +HWTEST_F(RichEditorPatternTestSevenNg, CopySpansForClipboard, TestSize.Level1) +{ + ASSERT_NE(richEditorNode_, nullptr); + auto richEditorPattern = richEditorNode_->GetPattern(); + ASSERT_NE(richEditorPattern, nullptr); + RefPtr spanItem = AceType::MakeRefPtr(); + RefPtr spanItem1 = AceType::MakeRefPtr(); + spanItem->spanItemType = SpanItemType::SYMBOL; + spanItem1->spanItemType = SpanItemType::NORMAL; + int32_t position = 2; + spanItem1->position = position; + std::u16string content = u"123"; + spanItem1->content = content; + richEditorPattern->spans_.push_back(spanItem); + richEditorPattern->spans_.push_back(spanItem1); + auto copySpans = richEditorPattern->CopySpansForClipboard(); + std::u16string resultContent = u""; + int32_t resultPosition = -1; + if (!copySpans.empty()) { + for (const auto& spanItem : copySpans) { + if (spanItem->spanItemType == SpanItemType::NORMAL) { + resultContent = spanItem->content; + resultPosition = spanItem->position; + } + } + } + EXPECT_EQ(resultContent, content); + EXPECT_EQ(resultPosition, position); +} } // namespace OHOS::Ace::NG