mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-08-14 15:33:38 +00:00
Splice AI text result into the selected span
This commit is contained in:
@@ -7588,6 +7588,81 @@ State::ActiveTextBlockActionResult State::applyActiveTextBlockAction(
|
||||
});
|
||||
}
|
||||
|
||||
State::ActiveTextBlockActionResult
|
||||
State::replaceActiveTextSelectionWithRichPage(
|
||||
std::shared_ptr<const RichPage> page,
|
||||
ActiveTextInsertContext context) {
|
||||
return applyCheckedMutation(ActiveTextBlockActionResult{
|
||||
.result = ApplyResult::Failed,
|
||||
}, [page = std::move(page), context = std::move(context)](
|
||||
State &candidate) mutable {
|
||||
ActiveTextBlockActionResult result{
|
||||
.result = ApplyResult::Failed,
|
||||
};
|
||||
const auto failed = [&] {
|
||||
return CheckedMutationResult<ActiveTextBlockActionResult>{
|
||||
.result = result,
|
||||
};
|
||||
};
|
||||
if (!page || page->blocks.empty()) {
|
||||
return failed();
|
||||
}
|
||||
const auto descriptor = candidate.textNode(
|
||||
candidate._activeTextOrdinal);
|
||||
if (!descriptor || (descriptor->leaf.kind == LeafKind::MathFormula)) {
|
||||
return failed();
|
||||
}
|
||||
const auto singleParagraph = (page->blocks.size() == 1)
|
||||
&& (page->blocks.front().kind == BlockKind::Paragraph)
|
||||
&& page->blocks.front().blocks.empty()
|
||||
&& (descriptor->leaf.kind != LeafKind::TableCellText);
|
||||
if (singleParagraph) {
|
||||
const auto &inner = page->blocks.front().text.text;
|
||||
const auto selectionFrom = int(context.before.text.size());
|
||||
const auto selectionTo = selectionFrom + int(inner.text.size());
|
||||
const auto applied = candidate.applyActiveTextUnchecked(JoinText(
|
||||
context.before,
|
||||
inner,
|
||||
context.after));
|
||||
if (applied == ApplyResult::Failed) {
|
||||
return failed();
|
||||
}
|
||||
const auto updated = candidate.textNode(
|
||||
candidate._activeTextOrdinal);
|
||||
return CheckedMutationResult<ActiveTextBlockActionResult>{
|
||||
.apply = true,
|
||||
.result = {
|
||||
.result = ApplyResult::Changed,
|
||||
.destinationLeaf = (updated
|
||||
? updated->leaf
|
||||
: descriptor->leaf),
|
||||
.selectionFrom = selectionFrom,
|
||||
.selectionTo = selectionTo,
|
||||
},
|
||||
};
|
||||
}
|
||||
auto blocks = page->blocks;
|
||||
const auto applied = candidate.insertBlocksAfterActiveUnchecked(
|
||||
std::move(blocks),
|
||||
context);
|
||||
if (!applied) {
|
||||
return failed();
|
||||
}
|
||||
const auto updated = candidate.textNode(candidate._activeTextOrdinal);
|
||||
return CheckedMutationResult<ActiveTextBlockActionResult>{
|
||||
.apply = true,
|
||||
.result = {
|
||||
.result = ApplyResult::Changed,
|
||||
.destinationLeaf = (updated
|
||||
? updated->leaf
|
||||
: descriptor->leaf),
|
||||
.selectionFrom = 0,
|
||||
.selectionTo = 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
bool State::insertBlockAfterActive(
|
||||
InsertAction action,
|
||||
std::optional<ActiveTextInsertContext> context) {
|
||||
|
||||
@@ -412,6 +412,10 @@ public:
|
||||
[[nodiscard]] ActiveTextBlockActionResult applyActiveTextBlockAction(
|
||||
InsertAction action,
|
||||
ActiveTextInsertContext context);
|
||||
[[nodiscard]] ActiveTextBlockActionResult
|
||||
replaceActiveTextSelectionWithRichPage(
|
||||
std::shared_ptr<const RichPage> page,
|
||||
ActiveTextInsertContext context);
|
||||
[[nodiscard]] bool insertPreparedBlockAfterActive(RichPage::Block block);
|
||||
[[nodiscard]] bool insertPreparedBlocksAfterActive(
|
||||
std::vector<RichPage::Block> blocks,
|
||||
|
||||
@@ -3678,6 +3678,100 @@ void Widget::replaceCurrentSelectionWithRichPage(
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto data = ClipboardBlockData();
|
||||
data.blocks = page->blocks;
|
||||
pasteStructuredClipboardData(ClipboardData(std::move(data)));
|
||||
return;
|
||||
}
|
||||
if (auto context = activeTextInsertContext()) {
|
||||
recordMutationTransaction([&] {
|
||||
const auto restoreLeaf = _fieldLeaf;
|
||||
const auto restoreStyleKey = _activeFieldStyleKey;
|
||||
const auto restoreMode = _fieldMode;
|
||||
const auto restoreSelection
|
||||
= captureHistoryViewState().leafSelection;
|
||||
_pendingOrdinal = -1;
|
||||
_pendingCursorOffset = 0;
|
||||
hideInlineField();
|
||||
clearInlineFieldEditSession(true);
|
||||
auto restore = true;
|
||||
const auto restoreInlineField = gsl::finally([&] {
|
||||
if (!restore) {
|
||||
return;
|
||||
}
|
||||
if (restoreLeaf && restoreStyleKey) {
|
||||
if (auto revived = reviveRetainedLeafField(
|
||||
_historyIndex,
|
||||
*restoreLeaf,
|
||||
restoreMode,
|
||||
*restoreStyleKey)) {
|
||||
_field = std::move(revived);
|
||||
_activeFieldStyleKey = restoreStyleKey;
|
||||
_fieldMode = restoreMode;
|
||||
_fieldLeaf = *restoreLeaf;
|
||||
refreshInlineFieldPlaceholder();
|
||||
_fieldUndoAvailable = _field->isUndoAvailable();
|
||||
_fieldRedoAvailable = _field->isRedoAvailable();
|
||||
clearFieldUndoRedoNoopState();
|
||||
}
|
||||
}
|
||||
if (!_fieldLeaf && restoreSelection) {
|
||||
const auto ordinal = _state->textOrdinalForLeafPath(
|
||||
restoreSelection->leaf);
|
||||
if (ordinal >= 0) {
|
||||
activateTextOrdinal(
|
||||
ordinal,
|
||||
restoreSelection->anchorOffset,
|
||||
restoreSelection->cursorOffset);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_field->show();
|
||||
syncInlineFieldGeometry();
|
||||
updateInlineFieldHeightOverride();
|
||||
syncArticleVisibleTopBottom();
|
||||
revealActiveInlineField();
|
||||
_field->raise();
|
||||
_field->setFocusFast();
|
||||
notifyToolbarStateChanged();
|
||||
});
|
||||
const auto applied = _state->replaceActiveTextSelectionWithRichPage(
|
||||
page,
|
||||
*context);
|
||||
if (applied.result != ApplyResult::Changed) {
|
||||
showLastLimitToast();
|
||||
return MutationTransactionResult{
|
||||
.committed = ApplyResult::Unchanged,
|
||||
};
|
||||
}
|
||||
restore = false;
|
||||
refreshPreparedContent();
|
||||
auto restored = false;
|
||||
if (applied.destinationLeaf) {
|
||||
const auto ordinal = _state->textOrdinalForLeafPath(
|
||||
*applied.destinationLeaf);
|
||||
if (ordinal >= 0) {
|
||||
activateTextOrdinal(
|
||||
ordinal,
|
||||
applied.selectionFrom,
|
||||
applied.selectionTo);
|
||||
restored = true;
|
||||
}
|
||||
}
|
||||
if (!restored) {
|
||||
const auto ordinal = _state->activeTextOrdinal();
|
||||
if (ordinal >= 0 && ordinal < _state->textNodeCount()) {
|
||||
activateTextOrdinal(ordinal, 0);
|
||||
} else {
|
||||
activateInitialNode();
|
||||
}
|
||||
}
|
||||
return MutationTransactionResult{
|
||||
.committed = ApplyResult::Unchanged,
|
||||
.changed = true,
|
||||
};
|
||||
});
|
||||
return;
|
||||
}
|
||||
auto data = ClipboardBlockData();
|
||||
data.blocks = page->blocks;
|
||||
|
||||
Reference in New Issue
Block a user