advance 1-8 post-mvp execution batches
This commit is contained in:
@@ -1214,6 +1214,110 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
trigger.closest('[data-testid="wolai-workspace-identity"]')?.appendChild(menu);
|
||||
}
|
||||
|
||||
function closeAccountMenu() {
|
||||
var existing = document.querySelector('[data-testid="mnote-account-menu"]');
|
||||
if (existing && existing.parentElement) existing.parentElement.removeChild(existing);
|
||||
document.querySelectorAll('[data-testid="mnote-account-menu-trigger"]').forEach(function(trigger) {
|
||||
if (trigger instanceof HTMLElement) trigger.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
}
|
||||
|
||||
function accountMenuFallbackSession() {
|
||||
var body = document.body instanceof HTMLElement ? document.body : null;
|
||||
var actorId = body ? String(body.getAttribute('data-mnote-actor-id') || '').trim() : '';
|
||||
return {
|
||||
ok: true,
|
||||
name: actorId || '当前用户',
|
||||
email: '',
|
||||
userId: actorId || 'anonymous',
|
||||
actorType: actorId && actorId !== 'anonymous' ? 'user' : 'anonymous',
|
||||
authMode: 'browser'
|
||||
};
|
||||
}
|
||||
|
||||
function renderAccountInfo(menu, session) {
|
||||
var nameNode = menu.querySelector('[data-account-info="name"]');
|
||||
var emailNode = menu.querySelector('[data-account-info="email"]');
|
||||
var idNode = menu.querySelector('[data-account-info="user-id"]');
|
||||
var typeNode = menu.querySelector('[data-account-info="actor-type"]');
|
||||
if (nameNode) nameNode.textContent = session.name || session.userId || '当前用户';
|
||||
if (emailNode) emailNode.textContent = session.email || '未提供邮箱';
|
||||
if (idNode) idNode.textContent = session.userId || 'anonymous';
|
||||
if (typeNode) typeNode.textContent = session.actorType || session.authMode || 'unknown';
|
||||
}
|
||||
|
||||
async function loadAccountInfo(menu) {
|
||||
try {
|
||||
var response = await fetch('/api/auth/session', {
|
||||
method: 'GET',
|
||||
headers: { 'accept': 'application/json' },
|
||||
credentials: 'include'
|
||||
});
|
||||
var payload = await response.json().catch(function() { return null; });
|
||||
if (!response.ok || !payload) throw new Error('session_failed_' + response.status);
|
||||
renderAccountInfo(menu, payload);
|
||||
} catch (_) {
|
||||
renderAccountInfo(menu, accountMenuFallbackSession());
|
||||
}
|
||||
}
|
||||
|
||||
async function signOutAccount(trigger) {
|
||||
setCommandPending(trigger, true);
|
||||
try {
|
||||
var response = await fetch('/api/auth', {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ action: 'auth:signOut', args: {} })
|
||||
});
|
||||
var payload = await response.json().catch(function() { return {}; });
|
||||
payload = payload || {};
|
||||
if (!response.ok || payload.error) {
|
||||
throw new Error(payload.error || '退出登录失败');
|
||||
}
|
||||
window.location.assign('/auth');
|
||||
} catch (error) {
|
||||
var menu = document.querySelector('[data-testid="mnote-account-menu"]');
|
||||
var errorNode = menu ? menu.querySelector('[data-account-error]') : null;
|
||||
if (errorNode instanceof HTMLElement) {
|
||||
errorNode.textContent = error && error.message ? error.message : '退出登录失败';
|
||||
errorNode.hidden = false;
|
||||
}
|
||||
setCommandPending(trigger, false);
|
||||
}
|
||||
}
|
||||
|
||||
function openAccountMenu(trigger) {
|
||||
closeAccountMenu();
|
||||
if (!(trigger instanceof HTMLElement)) return;
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
var menu = document.createElement('div');
|
||||
menu.className = 'mnote-workspace-source-menu mnote-account-menu';
|
||||
menu.setAttribute('data-testid', 'mnote-account-menu');
|
||||
menu.setAttribute('role', 'menu');
|
||||
menu.innerHTML =
|
||||
'<div class="mnote-account-menu__profile" role="group" aria-label="个人信息">' +
|
||||
'<div class="mnote-account-menu__title">个人设置</div>' +
|
||||
'<div class="mnote-account-menu__name" data-account-info="name">正在读取...</div>' +
|
||||
'<div class="mnote-account-menu__row"><span>邮箱</span><strong data-account-info="email">正在读取...</strong></div>' +
|
||||
'<div class="mnote-account-menu__row"><span>用户 ID</span><strong data-account-info="user-id">正在读取...</strong></div>' +
|
||||
'<div class="mnote-account-menu__row"><span>身份</span><strong data-account-info="actor-type">正在读取...</strong></div>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-account-menu__separator" aria-hidden="true"></div>' +
|
||||
'<button type="button" class="mnote-workspace-source-menu__item mnote-account-menu__logout" data-testid="mnote-account-sign-out" role="menuitem">退出登录</button>' +
|
||||
'<div class="mnote-account-menu__error" data-account-error hidden></div>';
|
||||
var signOutButton = menu.querySelector('[data-testid="mnote-account-sign-out"]');
|
||||
if (signOutButton) {
|
||||
signOutButton.addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
void signOutAccount(signOutButton);
|
||||
});
|
||||
}
|
||||
var host = trigger.closest('[data-testid="wolai-sidebar-quick-actions"]') || trigger.parentElement;
|
||||
if (host) host.appendChild(menu);
|
||||
void loadAccountInfo(menu);
|
||||
}
|
||||
|
||||
autoOpenRecentLocalRootOnHome();
|
||||
|
||||
function setCommandPending(trigger, pending) {
|
||||
@@ -1825,7 +1929,7 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
});
|
||||
var activeId = currentDocumentId();
|
||||
var activeRowId = currentFileTreeActiveRowId();
|
||||
tree.innerHTML = '<ul class="tree-root" role="tree" data-rust-page-renderer="initial_v1">' + (rows.length ? renderPageRows('', groupRowsByParent(rows), activeId, 0) : '<li class="tree-empty" data-rust-rendered-row="page-empty">暂无页面</li>') + '</ul>';
|
||||
tree.innerHTML = '<ul class="tree-root" role="tree" data-rust-page-renderer="initial_v1">' + (rows.length ? renderPageRows('', groupRowsByParent(rows), activeId, 0) : '') + '</ul>';
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1934,7 +2038,7 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
var rows = projectionItems(projection);
|
||||
var activeId = currentDocumentId();
|
||||
var activeRowId = currentFileTreeActiveRowId();
|
||||
tree.innerHTML = '<ul class="tree-root" role="tree" data-rust-filetree-renderer="initial_v1">' + (rows.length ? renderFileRows('', groupRowsByParent(rows), activeId, activeRowId) : '<li class="tree-empty" data-rust-rendered-row="filetree-empty">暂无文件或页面</li>') + '</ul>';
|
||||
tree.innerHTML = '<ul class="tree-root" role="tree" data-rust-filetree-renderer="initial_v1">' + (rows.length ? renderFileRows('', groupRowsByParent(rows), activeId, activeRowId) : '') + '</ul>';
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2006,6 +2110,9 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
};
|
||||
var poll = async function() {
|
||||
if (document.hidden) return;
|
||||
// If tree live SSE transport is active for local_folder, skip polling (fallback)
|
||||
var treeTransport = document.documentElement.getAttribute('data-mnote-tree-live-transport') || '';
|
||||
if (treeTransport === 'local-folder-events') return;
|
||||
var url = new URL('/api/tree/local-folder-watch', window.location.origin);
|
||||
url.searchParams.set('rootUri', rootUri);
|
||||
var response = await fetch(url.toString(), { headers: { accept: 'application/json' } });
|
||||
@@ -8864,6 +8971,17 @@ const SIDEBAR_TREE_JS: &str = r##"
|
||||
var sourceMenu = closestAction(e.target, '[data-testid="mnote-workspace-source-menu"]');
|
||||
if (!sourceMenu) closeWorkspaceSourceMenu();
|
||||
|
||||
var accountMenuTrigger = closestAction(e.target, '[data-mnote-action="open-account-menu"]');
|
||||
if (accountMenuTrigger) {
|
||||
e.preventDefault();
|
||||
var existingAccountMenu = document.querySelector('[data-testid="mnote-account-menu"]');
|
||||
if (existingAccountMenu) closeAccountMenu();
|
||||
else openAccountMenu(accountMenuTrigger);
|
||||
return;
|
||||
}
|
||||
var accountMenu = closestAction(e.target, '[data-testid="mnote-account-menu"]');
|
||||
if (!accountMenu) closeAccountMenu();
|
||||
|
||||
var trashTrigger = closestAction(e.target, '[data-mnote-action="open-trash-modal"]');
|
||||
if (trashTrigger) {
|
||||
e.preventDefault();
|
||||
@@ -9706,6 +9824,18 @@ const TREE_LIVE_CONTROLLER_JS: &str = r##"
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var sourceKind = (params.get('sourceKind') || '').trim();
|
||||
if (sourceKind === 'local_folder') {
|
||||
applyTransport('local-folder-events');
|
||||
applyStatus('connecting');
|
||||
var localRootUri = (params.get('rootUri') || '').trim()
|
||||
|| (document.body instanceof HTMLElement ? (document.body.getAttribute('data-mnote-root-uri') || '').trim() : '');
|
||||
if (localRootUri && 'EventSource' in window) {
|
||||
var url = new URL('/api/local-folder/events', window.location.origin);
|
||||
url.searchParams.set('rootUri', localRootUri);
|
||||
url.searchParams.set('treeLive', 'true');
|
||||
startWithSse(bootstrap, '', url);
|
||||
return;
|
||||
}
|
||||
// No rootUri or EventSource unavailable — mark static and let polling fallback handle it
|
||||
applyTransport('local-folder-static');
|
||||
applyStatus('static');
|
||||
return;
|
||||
@@ -9841,7 +9971,7 @@ pub fn PageLayout(
|
||||
<span class="wolai-sidebar-chevron" aria-hidden="true">"⌄"</span>
|
||||
</button>
|
||||
</div>
|
||||
<nav class="mnote-sidebar-nav wolai-quick-actions" aria-label="快捷操作">
|
||||
<nav class="mnote-sidebar-nav wolai-quick-actions" aria-label="快捷操作" data-testid="wolai-sidebar-quick-actions">
|
||||
<a href="/search" class:active={current_nav == "search"} title="搜索" aria-label="搜索" data-mnote-action="open-search-modal"><span class="material-symbols-outlined nav-icon" data-icon="search" aria-hidden="true"></span></a>
|
||||
<a href="/graph" title="关系图" aria-label="关系图"><span class="material-symbols-outlined nav-icon" data-icon="account_tree" aria-hidden="true"></span></a>
|
||||
<a href="/actions" title="快捷动作" aria-label="快捷动作"><span class="material-symbols-outlined nav-icon" data-icon="bolt" aria-hidden="true"></span></a>
|
||||
@@ -9863,7 +9993,17 @@ pub fn PageLayout(
|
||||
} else {
|
||||
view! {}.into_any()
|
||||
}}
|
||||
<a href="/more" title="更多" aria-label="更多"><span class="material-symbols-outlined nav-icon" data-icon="more_horiz" aria-hidden="true"></span></a>
|
||||
<button
|
||||
type="button"
|
||||
title="更多"
|
||||
aria-label="更多"
|
||||
data-testid="mnote-account-menu-trigger"
|
||||
data-mnote-action="open-account-menu"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="material-symbols-outlined nav-icon" data-icon="more_horiz" aria-hidden="true"></span>
|
||||
</button>
|
||||
</nav>
|
||||
<div class="wolai-sidebar-body" inner_html={sidebar_sections_html}></div>
|
||||
<script id="__MNOTE_TREE_LIVE_BOOTSTRAP__" type="application/json" inner_html={tree_live_bootstrap}></script>
|
||||
|
||||
Reference in New Issue
Block a user