fix local folder resource lifecycle and workspace switch
This commit is contained in:
@@ -763,7 +763,7 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
|
||||
function rememberCloudWorkspaceId(workspaceId) {
|
||||
var normalized = String(workspaceId || '').trim();
|
||||
if (!normalized || normalized === 'local-folder' || normalized === 'default') return;
|
||||
if (!normalized || normalized === 'local-folder' || normalized === 'default' || normalized.indexOf('local-ws:') === 0) return;
|
||||
try {
|
||||
if (window.localStorage) window.localStorage.setItem(MNOTE_LAST_CLOUD_WORKSPACE_KEY, normalized);
|
||||
} catch (_) {}
|
||||
@@ -773,11 +773,11 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
if (currentSourceKind() === 'local_folder') return '';
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var fromUrl = (params.get('workspaceId') || '').trim();
|
||||
if (fromUrl && fromUrl !== 'default') return fromUrl;
|
||||
if (fromUrl && fromUrl !== 'default' && fromUrl.indexOf('local-ws:') !== 0) return fromUrl;
|
||||
var fromDom = document.querySelector('[data-workspace-id]');
|
||||
if (fromDom instanceof HTMLElement) {
|
||||
var value = (fromDom.getAttribute('data-workspace-id') || '').trim();
|
||||
if (value && value !== 'local-folder' && value !== 'default') return value;
|
||||
if (value && value !== 'local-folder' && value !== 'default' && value.indexOf('local-ws:') !== 0) return value;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
@@ -789,15 +789,15 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
function readLastCloudWorkspaceId() {
|
||||
try {
|
||||
var stored = window.localStorage ? window.localStorage.getItem(MNOTE_LAST_CLOUD_WORKSPACE_KEY) : '';
|
||||
if (stored && stored.trim() && stored.trim() !== 'default') return stored.trim();
|
||||
if (stored && stored.trim() && stored.trim() !== 'default' && stored.trim().indexOf('local-ws:') !== 0) return stored.trim();
|
||||
} catch (_) {}
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var fromUrl = (params.get('workspaceId') || '').trim();
|
||||
if (fromUrl && currentSourceKind() !== 'local_folder') return fromUrl;
|
||||
if (fromUrl && currentSourceKind() !== 'local_folder' && fromUrl.indexOf('local-ws:') !== 0) return fromUrl;
|
||||
var fromDom = document.querySelector('[data-workspace-id]');
|
||||
if (fromDom instanceof HTMLElement) {
|
||||
var value = (fromDom.getAttribute('data-workspace-id') || '').trim();
|
||||
if (value && value !== 'local-folder') return value;
|
||||
if (value && value !== 'local-folder' && value.indexOf('local-ws:') !== 0) return value;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
@@ -925,9 +925,8 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
|
||||
function switchToCloudWorkspace() {
|
||||
var targetUrl = new URL('/', window.location.origin);
|
||||
var workspaceId = readLastCloudWorkspaceId();
|
||||
if (workspaceId) targetUrl.searchParams.set('workspaceId', workspaceId);
|
||||
targetUrl.searchParams.set('sourceKind', 'convex_workspace');
|
||||
targetUrl.searchParams.set('treeView', activeSidebarTreeMode() || 'filetree');
|
||||
targetUrl.searchParams.set('mnoteHome', '1');
|
||||
window.location.href = targetUrl.toString();
|
||||
}
|
||||
|
||||
@@ -1311,6 +1310,7 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
if ((params.get('rootUri') || '').trim()) return false;
|
||||
if ((params.get('workspaceId') || '').trim()) return false;
|
||||
if ((params.get('pageId') || '').trim()) return false;
|
||||
if ((params.get('mnoteHome') || '').trim() === '1') return false;
|
||||
var recent = readRecentLocalRoots();
|
||||
if (!recent.length) return false;
|
||||
openLocalFolderRoot(recent[0]);
|
||||
@@ -1346,7 +1346,7 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
cloudButton.className = 'mnote-workspace-source-menu__item';
|
||||
cloudButton.setAttribute('data-testid', 'mnote-switch-cloud-workspace');
|
||||
cloudButton.setAttribute('role', 'menuitem');
|
||||
cloudButton.textContent = '云空间';
|
||||
cloudButton.textContent = '我的空间';
|
||||
cloudButton.addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
closeWorkspaceSourceMenu();
|
||||
@@ -10512,7 +10512,7 @@ pub fn PageLayout(
|
||||
data-mnote-action="open-workspace-source-menu"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="false"
|
||||
title="切换云空间或本地文件夹"
|
||||
title="切换我的空间或本地文件夹"
|
||||
>
|
||||
<span class="sidebar-workspace-name">{ws_name.clone()}</span>
|
||||
<span class="wolai-sidebar-chevron" aria-hidden="true">"⌄"</span>
|
||||
@@ -10810,11 +10810,24 @@ mod tests {
|
||||
fn sidebar_workspace_source_switch_remembers_real_cloud_workspace_before_local_folder() {
|
||||
assert!(
|
||||
!SIDEBAR_TREE_JS.contains("rememberCloudWorkspaceId(resolveWorkspaceId(document.body))"),
|
||||
"进入本地文件夹前不能用 document.body 推导云空间 workspaceId;它会在无 workspaceId URL 时回退成 default"
|
||||
"进入本地文件夹前不能用 document.body 推导 workspaceId;它会在无 workspaceId URL 时回退成 default"
|
||||
);
|
||||
assert!(
|
||||
SIDEBAR_TREE_JS.contains("rememberCurrentCloudWorkspaceId()"),
|
||||
"进入本地文件夹前应从 URL 或 DOM 子树读取真实云空间 workspaceId"
|
||||
"进入本地文件夹前应从 URL 或 DOM 子树读取真实 workspaceId"
|
||||
);
|
||||
assert!(
|
||||
SIDEBAR_TREE_JS.contains("normalized.indexOf('local-ws:') === 0"),
|
||||
"本地文件夹 workspaceId 不能写入 lastCloudWorkspaceId"
|
||||
);
|
||||
assert!(
|
||||
SIDEBAR_TREE_JS.contains("stored.trim().indexOf('local-ws:') !== 0"),
|
||||
"切回工作区时不能复用 local-ws:* 作为旧云 workspace"
|
||||
);
|
||||
assert!(
|
||||
!SIDEBAR_TREE_JS
|
||||
.contains("targetUrl.searchParams.set('sourceKind', 'convex_workspace')"),
|
||||
"默认来源菜单不能跳到已退出 dev 主链的 convex_workspace"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1187,6 +1187,13 @@ function __wbg_get_imports() {
|
||||
const ret = arg0.target;
|
||||
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||
},
|
||||
__wbg_textContent_1f28330a124ec047: function(arg0, arg1) {
|
||||
const ret = arg1.textContent;
|
||||
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len1 = WASM_VECTOR_LEN;
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||
},
|
||||
__wbg_then_792e0c862b060889: function(arg0, arg1, arg2) {
|
||||
const ret = arg0.then(arg1, arg2);
|
||||
return ret;
|
||||
@@ -1195,6 +1202,10 @@ function __wbg_get_imports() {
|
||||
const ret = arg0.then(arg1);
|
||||
return ret;
|
||||
},
|
||||
__wbg_toString_306ed0b9f320c1ca: function(arg0) {
|
||||
const ret = arg0.toString();
|
||||
return ret;
|
||||
},
|
||||
__wbg_top_158f7c4dd1427771: function(arg0) {
|
||||
const ret = arg0.top;
|
||||
return ret;
|
||||
|
||||
BIN
Binary file not shown.
@@ -5261,6 +5261,34 @@ fn hovered_block_from_selection() -> Option<HoveredBlockState> {
|
||||
block_state_from_index(index)
|
||||
}
|
||||
|
||||
fn selected_local_attachment_block_index() -> Option<usize> {
|
||||
let selection = window().and_then(|win| win.get_selection().ok().flatten())?;
|
||||
let selected_text = String::from(selection.to_string()).trim().to_string();
|
||||
if selected_text.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let root = editor_root_element()?;
|
||||
let links = root.get_elements_by_tag_name("a");
|
||||
for index in 0..links.length() {
|
||||
let Some(link) = links.item(index) else {
|
||||
continue;
|
||||
};
|
||||
let href = link.get_attribute("href").unwrap_or_default();
|
||||
if !href.contains("/api/local-folder/files/open") {
|
||||
continue;
|
||||
}
|
||||
let text = link.text_content().unwrap_or_default();
|
||||
if text.trim() != selected_text {
|
||||
continue;
|
||||
}
|
||||
let block = direct_block_from_element(link, &root)?;
|
||||
return top_level_block_index(&root, &block);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn block_state_from_index(index: usize) -> Option<HoveredBlockState> {
|
||||
let root = editor_root_element()?;
|
||||
let stage = editor_stage_element()?;
|
||||
@@ -8708,7 +8736,9 @@ fn App(mount_options: MountOptions) -> impl IntoView {
|
||||
let editor = editor;
|
||||
let document_id = document_id;
|
||||
let workspace_id = workspace_id;
|
||||
let dirty_count = dirty_count;
|
||||
let title = title;
|
||||
let editor_focused = editor_focused;
|
||||
let set_dirty_count = set_dirty_count;
|
||||
let set_html_output = set_html_output;
|
||||
let set_document_json = set_document_json;
|
||||
@@ -8729,6 +8759,9 @@ fn App(mount_options: MountOptions) -> impl IntoView {
|
||||
let set_color_menu_open = set_color_menu_open;
|
||||
let more_menu_open = more_menu_open;
|
||||
let set_more_menu_open = set_more_menu_open;
|
||||
let revision = revision;
|
||||
let conflict_detection_key = conflict_detection_key;
|
||||
let read_only = read_only;
|
||||
let set_locked_toolbar_anchor = set_locked_toolbar_anchor;
|
||||
let set_text_selection_active = set_text_selection_active;
|
||||
let set_floating_toolbar_anchor = set_floating_toolbar_anchor;
|
||||
@@ -8752,6 +8785,59 @@ fn App(mount_options: MountOptions) -> impl IntoView {
|
||||
return;
|
||||
}
|
||||
|
||||
if !event.ctrl_key()
|
||||
&& !event.meta_key()
|
||||
&& !event.alt_key()
|
||||
&& matches!(event.key().as_str(), "Backspace" | "Delete")
|
||||
{
|
||||
if let Some(block_index) = selected_local_attachment_block_index() {
|
||||
event.prevent_default();
|
||||
match editor.get_html() {
|
||||
Ok(current_html) => {
|
||||
match delete_top_level_block_html(¤t_html, block_index) {
|
||||
Ok(next_html) => {
|
||||
apply_html_update(
|
||||
editor,
|
||||
&runtime_persisted_identity(document_id, workspace_id),
|
||||
next_html,
|
||||
document_id,
|
||||
workspace_id,
|
||||
dirty_count,
|
||||
set_dirty_count,
|
||||
set_html_output,
|
||||
set_document_json,
|
||||
set_json_output,
|
||||
title,
|
||||
hovered_block,
|
||||
editor_focused,
|
||||
slash_open,
|
||||
turn_into_open,
|
||||
color_menu_open,
|
||||
more_menu_open,
|
||||
revision,
|
||||
conflict_detection_key,
|
||||
read_only,
|
||||
set_command_feedback,
|
||||
"已删除附件引用",
|
||||
);
|
||||
let _ = set_hovered_block.try_set(None);
|
||||
let _ = set_block_menu_open.try_set(false);
|
||||
let _ = set_block_menu_anchor.try_set(None);
|
||||
}
|
||||
Err(err) => {
|
||||
let _ = set_command_feedback.try_set(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let _ =
|
||||
set_command_feedback.try_set(format!("读取当前 HTML 失败:{err}"));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.ctrl_key() || event.meta_key())
|
||||
&& event.shift_key()
|
||||
&& event.key().eq_ignore_ascii_case("u")
|
||||
|
||||
Reference in New Issue
Block a user