Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/common/VNoteMainManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ void VNoteMainManager::initConnections()
connect(m_richTextManager, &WebRichTextManager::noteTextChanged, this, &VNoteMainManager::onNoteChanged, Qt::QueuedConnection);
connect(m_richTextManager, &WebRichTextManager::updateSearch, this, &VNoteMainManager::updateSearch);
connect(m_richTextManager, &WebRichTextManager::scrollChange, this, &VNoteMainManager::scrollChange);
connect(TiptapChannelBridge::instance(), &TiptapChannelBridge::scrollChanged, this, &VNoteMainManager::scrollChange);
connect(m_richTextManager, &WebRichTextManager::finishedUpdateNote, this, &VNoteMainManager::onRichTextSaveFinished);
connect(VoiceRecoderHandler::instance(), &VoiceRecoderHandler::finishedRecod, this, &VNoteMainManager::insertVoice);
qInfo() << "Connections initialized";
Expand Down
10 changes: 10 additions & 0 deletions src/common/tiptapchannelbridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,16 @@ void TiptapChannelBridge::jsPasteImage(const QString &dataUrl)
emit insertImage(QJsonDocument(info).toJson(QJsonDocument::Compact));
}

// ---------------------------------------------------------------------------
// 滚动位置上报(JS→C++)
// ---------------------------------------------------------------------------

void TiptapChannelBridge::jsReportScroll(int scrollTop)
{
const bool isTop = (scrollTop <= 0);
emit scrollChanged(isTop);
}


// ---------------------------------------------------------------------------
// Voice 播放/转写入口(JS→C++)
Expand Down
6 changes: 6 additions & 0 deletions src/common/tiptapchannelbridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class TiptapChannelBridge : public QObject
// 前端粘贴剪贴板图片数据(data URL),宿主保存到 images/ 后回插
Q_INVOKABLE void jsPasteImage(const QString &dataUrl);

// 前端上报编辑器滚动位置(scrollTop),宿主据此驱动标题栏阴影状态
Q_INVOKABLE void jsReportScroll(int scrollTop);

// 宿主侧下发字体列表(未就绪时缓存,就绪后补发)
Q_INVOKABLE void sendFontList(const QStringList &fonts, const QString &defaultFont);

Expand Down Expand Up @@ -172,6 +175,9 @@ class TiptapChannelBridge : public QObject
void themeProvided(const QString &theme, const QString &highlightColor,
const QString &disableHighlightColor, const QString &backgroundColor);

// JS→C++:滚动位置上报(isTop=true 表示已滚到顶部)
void scrollChanged(bool isTop);

// C++ 内部请求信号(WebEngineHandler 连接处理)
void voicePlaybackRequested(const QString &voiceInfoJson, bool isSame);
void voicePlaybackStopRequested();
Expand Down
63 changes: 61 additions & 2 deletions src/gui/mainwindow/WebEngineView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,11 @@ Item {
messageDialogLoader.showDialog(type);
}
onTriggerWebAction: action => {
webView.triggerWebAction(action);
if (TiptapChannel.debugEnabled && tiptapLoader.item) {
tiptapWebView.triggerWebAction(action);
} else {
webView.triggerWebAction(action);
}
}
onViewPicture: filePath => {
viewPictureLoader.path = filePath;
Expand Down Expand Up @@ -501,6 +505,34 @@ Item {
tiptapWebView.webChannel = tiptapWebChannel;
tiptapWebView.url = Qt.resolvedUrl(TiptapChannel.tiptapHtmlPath());
}

onContextMenuRequested: req => {
req.accepted = true;
var rawX = Number(req.position.x);
var rawY = Number(req.position.y);
if (isNaN(rawX) || isNaN(rawY)) return;
var sx = String(Math.round(rawX));
var sy = String(Math.round(rawY));
tiptapWebView.runJavaScript(
"(function(){"
+ "var el=document.elementFromPoint(" + sx + "," + sy + ");"
+ "if(!el) return JSON.stringify({type:2,json:''});"
+ "var vb=el.closest?el.closest('.voiceInfoBox'):null;"
+ "if(vb&&vb.getAttribute('data-type')==='voice-block'){"
+ "return JSON.stringify({type:1,json:vb.getAttribute('data-voice-meta')||''});}"
+ "var img=el.closest?el.closest('img[data-rel-path]'):null;"
+ "if(img) return JSON.stringify({type:0,json:''});"
+ "return JSON.stringify({type:2,json:''});"
+ "})()",
function(result) {
var info = null;
try { info = JSON.parse(result); } catch(e) {}
if (!info) return;
if (info.type === 0) return;
handler.onSaveMenuParam(info.type, info.json);
handler.onContextMenuRequested(req);
});
}
}

DropArea {
Expand Down Expand Up @@ -807,7 +839,11 @@ Item {
hasScroll = !isTop;
}
onUpdateRichTextSearch: key => {
webView.findText(key);
if (TiptapChannel.debugEnabled && tiptapLoader.item) {
tiptapWebView.findText(key);
} else {
webView.findText(key);
}
}
}

Expand Down Expand Up @@ -871,4 +907,27 @@ Item {
}
}
}

Connections {
target: Webobj

onCallJsSelectAll: {
if (TiptapChannel.debugEnabled && tiptapLoader.item) {
tiptapWebView.runJavaScript(
"if(window.__dvnTiptapEditor)window.__dvnTiptapEditor.chain().selectAll().run()");
}
}
onCallJsDeleteSelection: {
if (TiptapChannel.debugEnabled && tiptapLoader.item) {
tiptapWebView.runJavaScript(
"if(window.__dvnTiptapEditor)window.__dvnTiptapEditor.chain().deleteSelection().run()");
}
}
onCallJsFocusEditor: {
if (TiptapChannel.debugEnabled && tiptapLoader.item) {
tiptapWebView.runJavaScript(
"if(window.__dvnTiptapEditor)window.__dvnTiptapEditor.commands.focus()");
}
}
}
}
12 changes: 8 additions & 4 deletions src/handler/web_engine_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -741,8 +741,10 @@ void WebEngineHandler::processVoiceMenuRequest(QObject *request)
// 异步操作,防止阻塞前端事件
QTimer::singleShot(0, this, [this] {
Q_EMIT requestMessageDialog(VNoteMessageDialogHandler::VoicePathNoAvail);
// 调用 js 删除删除语音文本
Q_EMIT JsContent::instance()->callJsDeleteSelection();
// 调试态下 Tiptap 编辑器不走 Summernote JS 删除路径
if (!TiptapChannelBridge::instance()->debugEnabled()) {
Q_EMIT JsContent::instance()->callJsDeleteSelection();
}
});
return;
}
Expand Down Expand Up @@ -777,8 +779,10 @@ void WebEngineHandler::processVoiceMenuRequest(QWebEngineContextMenuRequest *req
// 异步操作,防止阻塞前端事件
QTimer::singleShot(0, this, [this] {
Q_EMIT requestMessageDialog(VNoteMessageDialogHandler::VoicePathNoAvail);
// 调用 js 删除删除语音文本
Q_EMIT JsContent::instance()->callJsDeleteSelection();
// 调试态下 Tiptap 编辑器不走 Summernote JS 删除路径
if (!TiptapChannelBridge::instance()->debugEnabled()) {
Q_EMIT JsContent::instance()->callJsDeleteSelection();
}
});
return;
}
Expand Down
24 changes: 24 additions & 0 deletions tests/src/tiptapchannel/ut_tiptapchannelbridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,27 @@ TEST_F(UT_TiptapChannelBridge, UT_TiptapChannelBridge_currentVoiceId_001)
bridge.setCurrentVoiceId(QStringLiteral("voice-x"));
EXPECT_EQ(bridge.currentVoiceId(), QStringLiteral("voice-x"));
}

// ---------------------------------------------------------------------------
// 滚动位置上报(JS→C++):jsReportScroll + scrollChanged 信号
// ---------------------------------------------------------------------------

// jsReportScroll(0) → scrollChanged(true)(已到顶部)
TEST_F(UT_TiptapChannelBridge, UT_TiptapChannelBridge_jsReportScroll_top_001)
{
TiptapChannelBridge bridge;
QSignalSpy spy(&bridge, &TiptapChannelBridge::scrollChanged);
bridge.jsReportScroll(0);
ASSERT_EQ(spy.count(), 1);
EXPECT_EQ(spy.takeFirst().at(0).toBool(), true);
}

// jsReportScroll(正值) → scrollChanged(false)(未到顶部)
TEST_F(UT_TiptapChannelBridge, UT_TiptapChannelBridge_jsReportScroll_scrolled_001)
{
TiptapChannelBridge bridge;
QSignalSpy spy(&bridge, &TiptapChannelBridge::scrollChanged);
bridge.jsReportScroll(150);
ASSERT_EQ(spy.count(), 1);
EXPECT_EQ(spy.takeFirst().at(0).toBool(), false);
}
Loading