refactor: externalize upload and conflict helpers

This commit is contained in:
lix-2026
2026-05-25 01:13:08 +08:00
parent 7975ce0997
commit ac15424328
6 changed files with 128 additions and 15 deletions
+5
View File
@@ -122,6 +122,10 @@ pub fn build_router(state: AppState) -> Router {
"/api/mnote-browser-runtime/tree-shell-runtime.js",
get(web_shell::tree_shell_runtime_asset),
)
.route(
"/api/mnote-browser-runtime/document-conflict-panel-runtime.js",
get(web_shell::document_conflict_panel_runtime_asset),
)
.route("/api/search/documents", post(search::documents))
.route(
"/api/search/local-index/refresh",
@@ -530,6 +534,7 @@ mod tests {
"/api/mnote-browser-runtime/filetree-context-menu-runtime.js",
"/api/mnote-browser-runtime/tree-live-controller.js",
"/api/mnote-browser-runtime/tree-shell-runtime.js",
"/api/mnote-browser-runtime/document-conflict-panel-runtime.js",
] {
let response = app(false)
.oneshot(
@@ -246,6 +246,7 @@ pub async fn document_page_shell(
{}
{}
{}
{}
</body>
</html>"#,
escape_html(title),
@@ -270,6 +271,7 @@ pub async fn document_page_shell(
.unwrap_or_default(),
render_document_title_controller_script(),
render_editor_island_adapter_script(),
r#"<script type="module" src="/api/mnote-browser-runtime/document-conflict-panel-runtime.js"></script>"#.to_string(),
);
let mut response = Html(html).into_response();
stamp_shell_headers(response.headers_mut(), "document");
@@ -1896,6 +1898,11 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
};
const clearSessionConflictSurface = (session) => {
var _rt_ = window.__mnoteDocumentConflictPanelRuntime;
if (_rt_ && typeof _rt_.clearSessionConflictSurface === 'function') {
_rt_.clearSessionConflictSurface(session, { sessionViews: sessionViews });
return;
}
sessionViews(session).forEach((view) => {
const host = view.runtimeDescriptor.root.closest('.document-pane') || view.runtimeDescriptor.root;
if (!(host instanceof HTMLElement)) return;
@@ -4465,6 +4472,21 @@ pub async fn tree_shell_runtime_asset() -> Response {
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn document_conflict_panel_runtime_asset() -> Response {
// include_str! 路径相对于当前源文件 (src/routes/web_shell.rs -> ../../browser/)
const JS: &str = include_str!("../../browser/document-conflict-panel-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 leptos_tiptap_manifest() -> Response {
let manifest = json!({
"entryAssetPath": "mnote-leptos-tiptap-spike-island.js",
+27 -15
View File
@@ -4003,21 +4003,32 @@ const SIDEBAR_TREE_JS: &str = r##"
if (!rootUri || !uploadIntent) {
throw new Error(' Markdown rootUri documentId');
}
var localForm = new FormData();
localForm.append('file', file);
localForm.append('rootUri', rootUri);
localForm.append('uploadIntent', uploadIntent);
if (documentId) localForm.append('documentId', documentId);
if (hasFolderTarget) localForm.append('targetRelativePath', String(plan.targetRelativePath || ''));
localForm.append('kind', file && String(file.type || '').indexOf('image/') === 0 ? 'image' : 'attachment');
var localResponse = await fetchWithTimeout('/api/local-folder/assets/upload', {
method: 'POST',
credentials: 'include',
body: localForm
}, 15000, '');
var localPayload = await localResponse.json().catch(function() { return null; });
if (!localResponse.ok || !localPayload || !localPayload.asset) {
throw new Error(localPayload && localPayload.error ? localPayload.error : '');
var localUploadRuntime = localUploadRuntimeFunction('uploadLocalFolderAsset');
var localPayload = null;
if (localUploadRuntime) {
var localResult = await localUploadRuntime(file, plan, {
rootUri: rootUri,
documentId: documentId,
timeoutMs: 15000
});
localPayload = localResult && localResult.asset ? { asset: localResult.asset } : null;
} else {
var localForm = new FormData();
localForm.append('file', file);
localForm.append('rootUri', rootUri);
localForm.append('uploadIntent', uploadIntent);
if (documentId) localForm.append('documentId', documentId);
if (hasFolderTarget) localForm.append('targetRelativePath', String(plan.targetRelativePath || ''));
localForm.append('kind', file && String(file.type || '').indexOf('image/') === 0 ? 'image' : 'attachment');
var localResponse = await fetchWithTimeout('/api/local-folder/assets/upload', {
method: 'POST',
credentials: 'include',
body: localForm
}, 15000, '');
localPayload = await localResponse.json().catch(function() { return null; });
if (!localResponse.ok || !localPayload || !localPayload.asset) {
throw new Error(localPayload && localPayload.error ? localPayload.error : '');
}
}
if (options && options.insertIntoEditor) {
await insertUploadedAssetIntoEditor(localPayload.asset, editorRootFromUploadOptions(options));
@@ -10935,6 +10946,7 @@ mod tests {
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function editorRootFromUploadOptions"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function openEditorUploadFilePicker"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function fetchWithTimeout"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function uploadLocalFolderAsset"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("uploadFilesWithResolvedTarget"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("__mnoteLastEditorUploadRoot"));
}