Files
mnote/rust/crates/mnote-web/browser/document-conflict-panel-runtime.js
T

88 lines
3.9 KiB
JavaScript
Raw Normal View History

// MNote document conflict panel 运行时外置模块。
// 第一刀:纯 DOM 清理 helper clearSessionConflictSurface。
// 本文件以 type="module" 加载,执行时机可能晚于 inline script。
// web_shell.rs 的 inline clearSessionConflictSurface 会优先委托到
// window.__mnoteDocumentConflictPanelRuntime
// 模块尚未加载或加载失败时,inline script 保留原地实现兜底。
/**
* 清除指定 session 所有视图中冲突面板 DOM。
* 只做 DOM 清理,不处理冲突 merge/accept/keep 业务逻辑。
* @param {Object} session - document session 对象
* @param {Object} deps - 依赖注入,从 inline 上下文传入
* @param {Function} deps.sessionViews - session.views 迭代器
*/
function clearSessionConflictSurface(session, deps) {
var views = deps && typeof deps.sessionViews === 'function'
? deps.sessionViews(session)
: [];
views.forEach(function(view) {
var host = view.runtimeDescriptor.root.closest('.document-pane') || view.runtimeDescriptor.root;
if (!(host instanceof HTMLElement)) return;
host.querySelectorAll('[data-testid="mnote-editor-conflict-panel"]').forEach(function(node) { node.remove(); });
});
}
2026-05-25 01:35:19 +08:00
function createSessionConflictPanel(session, message, deps) {
deps = deps || {};
var externalConflictMessage = String(deps.externalConflictMessage || '').trim() || '文件已在外部修改';
var panel = document.createElement('section');
panel.className = 'mnote-editor-conflict-panel';
panel.setAttribute('data-testid', 'mnote-editor-conflict-panel');
panel.setAttribute('role', 'status');
panel.setAttribute('aria-live', 'polite');
var heading = document.createElement('h2');
heading.textContent = '文件冲突';
var text = document.createElement('p');
text.textContent = message || externalConflictMessage;
var meta = document.createElement('div');
meta.className = 'mnote-conflict-meta';
var fileLabel = session && session.sessionKind === 'resource'
? String(session.rootUri || '') + '/' + String(session.resourcePath || session.documentId || '')
: String(session && (session.rootUri || session.documentId) || '');
var sourceLabel = typeof deps.conflictSourceLabel === 'function'
? deps.conflictSourceLabel(session)
: '';
meta.textContent = '文件:' + fileLabel + ' · 来源:' + (sourceLabel || '本地文件变更');
var actions = document.createElement('div');
actions.className = 'mnote-conflict-actions';
var acceptDisk = document.createElement('button');
acceptDisk.type = 'button';
acceptDisk.textContent = '接受磁盘版本';
acceptDisk.setAttribute('data-testid', 'mnote-conflict-accept-disk');
var keepCurrent = document.createElement('button');
keepCurrent.type = 'button';
keepCurrent.textContent = '保留当前编辑器版本';
keepCurrent.setAttribute('data-testid', 'mnote-conflict-keep-current');
var openDiff = document.createElement('button');
openDiff.type = 'button';
openDiff.textContent = '打开 diff';
openDiff.setAttribute('data-testid', 'mnote-conflict-open-diff');
actions.append(acceptDisk, keepCurrent, openDiff);
var diffPanel = document.createElement('div');
diffPanel.className = 'mnote-conflict-diff-panel';
diffPanel.setAttribute('data-testid', 'mnote-conflict-diff-panel');
diffPanel.hidden = true;
panel.append(heading, text, meta, actions, diffPanel);
acceptDisk.addEventListener('click', function() {
if (typeof deps.onAcceptDisk === 'function') deps.onAcceptDisk(session, panel);
});
keepCurrent.addEventListener('click', function() {
if (typeof deps.onKeepCurrent === 'function') deps.onKeepCurrent(session, panel);
});
openDiff.addEventListener('click', function() {
if (typeof deps.onOpenDiff === 'function') deps.onOpenDiff(session, panel);
});
return panel;
}
window.__mnoteDocumentConflictPanelRuntime = {
2026-05-25 01:35:19 +08:00
clearSessionConflictSurface: clearSessionConflictSurface,
createSessionConflictPanel: createSessionConflictPanel
};