Упрощение git/превью: copyCodeBlock, parseBlocks на splitMdBlocks, кэш diff, пагинация

- MdParser.copyCodeBlock(id): один вызов вместо get+copy в 3 QML-местах
- parseBlocks переписан на splitMdBlocks (убит regex только для ```, заодно чинит ~~~); renderInner без побочек, save/restore удалены
- Кэш diff-блоков (хеши+пути, 8 шт, >1МБ не кэшируем); регистрация кодов всегда в главном потоке
- История: пагинация limit+Показать ещё с сохранением выбора; willDelete; busy только на время async
- GitManager: commitFile точечно (общий commitFromIndex), fileExistedAt, workdirContent через DocumentManager.readTextFile, fileGitStatus через relativePath; удалены fileDiffText/Html и 2-arg fileHistory
- MarkdownView: дебаунс async-ветки 80мс + гашение протухших ответов
This commit is contained in:
2026-09-06 22:17:13 +03:00
parent 0846605c2b
commit 1f140d3433
9 changed files with 160 additions and 139 deletions
+1 -3
View File
@@ -157,9 +157,7 @@ Item {
background: Rectangle { color: Theme.editorBg }
onLinkActivated: (href) => {
if (href.startsWith("flora://copycode/")) {
const id = href.substring(17)
const code = mdParser.getCodeBlock(id)
if (code.length > 0) { mdParser.copyToClipboard(code); copyFeedback.visible = true; copyTimer.restart() }
if (mdParser.copyCodeBlock(href.substring(17))) { copyFeedback.visible = true; copyTimer.restart() }
return
}
if (href.startsWith("flora://task/")) {
+1 -4
View File
@@ -658,10 +658,7 @@ Item {
function handleLink(href) {
if (href.startsWith("flora://copycode/")) {
const id = href.substring(17)
const code = mdParser.getCodeBlock(id)
if (code.length > 0) {
mdParser.copyToClipboard(code)
if (mdParser.copyCodeBlock(href.substring(17))) {
copyFeedback.text = qsTr("Скопировано!")
copyFeedback.visible = true
copyTimer.restart()
+12 -6
View File
@@ -19,12 +19,21 @@ Item {
signal linkActivated(string href)
signal diffApplied()
// Для обновления
// Для обновления. Async-ветка идёт через дебаунс: updateDiff() в диалоге меняет
// markdown и compareMarkdown по очереди, без дебаунса уходили бы два запроса
// (первый заведомо протухает и отбрасывается по _diffReq).
Timer { id: asyncDebounce; interval: 80; onTriggered: root._requestDiff() }
function _requestDiff() {
if (compareMarkdown.length === 0)
return // пока таймер ждал, сравнение уже сняли
_diffReq = mdParser.parseBlocksWithDiffAsync(markdown, compareMarkdown, vaultRoot, fileDir)
}
function update() {
if (compareMarkdown.length > 0) {
_diffReq = mdParser.parseBlocksWithDiffAsync(markdown, compareMarkdown, vaultRoot, fileDir)
asyncDebounce.restart()
return
}
_diffReq = -1 // гасим возможный async в полёте: его ответ станет чужим
// Триггерим пересборку блоков
blocksModel.clear()
const blocks = mdParser.parseBlocks(markdown, vaultRoot, fileDir)
@@ -99,11 +108,8 @@ Item {
codeId: blockCodeId
highlightedText: blockHighlighted
onCopyRequested: (id) => {
const txt = mdParser.getCodeBlock(id)
if (txt.length > 0) {
mdParser.copyToClipboard(txt)
if (mdParser.copyCodeBlock(id))
root.linkActivated("flora://copycode/" + id)
}
}
}
}