feat: sidebar runtime extraction + history-safe commands + checklist updates

This commit is contained in:
lix-2026
2026-05-25 17:36:17 +08:00
parent baae38786d
commit d84da5583b
17 changed files with 13166 additions and 11050 deletions
+12
View File
@@ -114,6 +114,18 @@ pub fn build_router(state: AppState) -> Router {
"/api/mnote-browser-runtime/filetree-context-menu-runtime.js",
get(web_shell::filetree_context_menu_runtime_asset),
)
.route(
"/api/mnote-browser-runtime/filetree-dnd-runtime.js",
get(web_shell::filetree_dnd_runtime_asset),
)
.route(
"/api/mnote-browser-runtime/filetree-keyboard-runtime.js",
get(web_shell::filetree_keyboard_runtime_asset),
)
.route(
"/api/mnote-browser-runtime/sidebar-tree-runtime.js",
get(web_shell::sidebar_tree_runtime_asset),
)
.route(
"/api/mnote-browser-runtime/tree-live-controller.js",
get(web_shell::tree_live_controller_runtime_asset),
@@ -2059,6 +2059,17 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
};
const acceptDiskVersion = async (session) => {
var _RT_ = window.__mnoteDocumentConflictPanelRuntime;
if (_RT_ && typeof _RT_.acceptDiskVersion === 'function') {
return _RT_.acceptDiskVersion(session, {
setSessionStatus: setSessionStatus,
fetchLatestResourceSnapshot: fetchLatestResourceSnapshot,
applyResourceSnapshotToSession: applyResourceSnapshotToSession,
fetchLatestSessionAggregate: fetchLatestSessionAggregate,
applyAggregateSnapshotToSession: applyAggregateSnapshotToSession,
});
}
// inline fallback
setSessionStatus(session, 'conflict-resolving', '...');
if (session.sessionKind === 'resource') {
const latestResource = await fetchLatestResourceSnapshot(session);
@@ -2070,6 +2081,23 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
};
const keepCurrentEditorVersion = async (session) => {
var _RT_ = window.__mnoteDocumentConflictPanelRuntime;
if (_RT_ && typeof _RT_.keepCurrentEditorVersion === 'function') {
return _RT_.keepCurrentEditorVersion(session, {
setSessionStatus: setSessionStatus,
fetchLatestResourceSnapshot: fetchLatestResourceSnapshot,
fetchLatestSessionAggregate: fetchLatestSessionAggregate,
sessionViews: sessionViews,
currentEditorText: currentEditorText,
normalizePlainText: normalizePlainText,
hydrateMindmapAttrsFromDom: hydrateMindmapAttrsFromDom,
textToTiptapDocument: textToTiptapDocument,
conflictDetectionKeyFromBody: conflictDetectionKeyFromBody,
clearSessionConflictSurface: clearSessionConflictSurface,
persistSession: persistSession,
});
}
// inline fallback
setSessionStatus(session, 'conflict-resolving', '...');
const latest = session.sessionKind === 'resource'
? await fetchLatestResourceSnapshot(session)
@@ -2101,6 +2129,18 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
};
const writeMergedConflictResult = async (session, panel, mergedText) => {
var _RT_ = window.__mnoteDocumentConflictPanelRuntime;
if (_RT_ && typeof _RT_.writeMergedConflictResult === 'function') {
return _RT_.writeMergedConflictResult(session, panel, mergedText, {
setSessionStatus: setSessionStatus,
fetchLatestResourceSnapshot: fetchLatestResourceSnapshot,
fetchLatestSessionAggregate: fetchLatestSessionAggregate,
conflictDetectionKeyFromBody: conflictDetectionKeyFromBody,
textToTiptapDocument: textToTiptapDocument,
persistSession: persistSession,
});
}
// inline fallback
setSessionStatus(session, 'conflict-resolving', '...');
const latest = session.sessionKind === 'resource'
? await fetchLatestResourceSnapshot(session)
@@ -4462,6 +4502,48 @@ pub async fn local_upload_runtime_asset() -> Response {
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_tree_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-tree-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, "no-store")
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(Body::from(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn filetree_keyboard_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/filetree-keyboard-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, "no-store")
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(Body::from(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn filetree_dnd_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/filetree-dnd-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, "no-store")
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(Body::from(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn filetree_context_menu_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/filetree-context-menu-runtime.js");
Response::builder()
@@ -5677,6 +5759,14 @@ mod tests {
assert!(DOCUMENT_CONFLICT_PANEL_RUNTIME_JS
.contains("runSessionConflictAction: runSessionConflictAction"));
assert!(DOCUMENT_CONFLICT_PANEL_RUNTIME_JS.contains("function runSessionConflictAction"));
assert!(DOCUMENT_CONFLICT_PANEL_RUNTIME_JS.contains("function acceptDiskVersion"));
assert!(DOCUMENT_CONFLICT_PANEL_RUNTIME_JS.contains("function keepCurrentEditorVersion"));
assert!(DOCUMENT_CONFLICT_PANEL_RUNTIME_JS.contains("function writeMergedConflictResult"));
assert!(DOCUMENT_CONFLICT_PANEL_RUNTIME_JS.contains("acceptDiskVersion: acceptDiskVersion"));
assert!(DOCUMENT_CONFLICT_PANEL_RUNTIME_JS
.contains("keepCurrentEditorVersion: keepCurrentEditorVersion"));
assert!(DOCUMENT_CONFLICT_PANEL_RUNTIME_JS
.contains("writeMergedConflictResult: writeMergedConflictResult"));
}
#[tokio::test]
File diff suppressed because it is too large Load Diff