feat(desktop): embed BoosAPI Desktop client as a subproject

Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
This commit is contained in:
boos
2026-06-22 11:32:57 +08:00
parent d9c78ecc73
commit e0a5f57793
2305 changed files with 449355 additions and 0 deletions
@@ -0,0 +1,141 @@
import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom'
export type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right'
let tooltipEl: HTMLDivElement | null = null
let currentAnchor: HTMLElement | null = null
let cleanupAutoUpdate: (() => void) | null = null
let showTimer: ReturnType<typeof setTimeout> | null = null
let hideTimer: ReturnType<typeof setTimeout> | null = null
let currentId: string | null = null
let visible = false
function clearTimers() {
if (showTimer) {
clearTimeout(showTimer)
showTimer = null
}
if (hideTimer) {
clearTimeout(hideTimer)
hideTimer = null
}
}
function ensureTooltipEl() {
if (tooltipEl || typeof document === 'undefined')
return tooltipEl
tooltipEl = document.createElement('div')
tooltipEl.className = 'ms-tooltip'
tooltipEl.setAttribute('role', 'tooltip')
tooltipEl.dataset.visible = 'false'
tooltipEl.style.position = 'fixed'
tooltipEl.style.left = '0px'
tooltipEl.style.top = '0px'
tooltipEl.style.transform = 'translate3d(0,0,0)'
document.body.appendChild(tooltipEl)
return tooltipEl
}
function detectDarkModeHint(hint?: boolean | null) {
if (typeof hint === 'boolean')
return hint
if (typeof document !== 'undefined') {
try {
if (document.documentElement.classList.contains('dark'))
return true
}
catch {}
}
if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {
try {
return window.matchMedia('(prefers-color-scheme: dark)').matches
}
catch {}
}
return false
}
async function updatePosition(placement: TooltipPlacement) {
if (!tooltipEl || !currentAnchor)
return
const { x, y } = await computePosition(currentAnchor, tooltipEl, {
placement,
middleware: [offset(8), flip(), shift({ padding: 8 })],
strategy: 'fixed',
})
tooltipEl.style.transform = `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`
}
export function showTooltipForAnchor(
anchor: HTMLElement | null,
content: string,
placement: TooltipPlacement = 'top',
immediate = false,
_origin?: { x: number, y: number } | undefined,
isDark?: boolean | null,
) {
if (!anchor || typeof document === 'undefined')
return
ensureTooltipEl()
if (!tooltipEl)
return
clearTimers()
const doShow = async () => {
if (!tooltipEl)
return
currentAnchor = anchor
tooltipEl.textContent = content
tooltipEl.dataset.placement = placement
tooltipEl.dataset.dark = detectDarkModeHint(isDark) ? 'true' : 'false'
tooltipEl.dataset.visible = 'false'
currentId = `tooltip-${Date.now()}-${Math.random().toString(36).slice(2)}`
tooltipEl.id = currentId
try {
anchor.setAttribute('aria-describedby', currentId)
}
catch {}
await updatePosition(placement)
tooltipEl.dataset.visible = 'true'
visible = true
cleanupAutoUpdate?.()
cleanupAutoUpdate = autoUpdate(anchor, tooltipEl!, () => {
updatePosition(placement)
})
}
if (immediate)
void doShow()
else
showTimer = setTimeout(doShow, 80)
}
export function hideTooltip(immediate = false) {
if (!tooltipEl)
return
clearTimers()
const doHide = () => {
if (!tooltipEl)
return
tooltipEl.dataset.visible = 'false'
visible = false
if (currentAnchor && currentId) {
try {
currentAnchor.removeAttribute('aria-describedby')
}
catch {}
}
currentAnchor = null
currentId = null
if (cleanupAutoUpdate) {
cleanupAutoUpdate()
cleanupAutoUpdate = null
}
}
if (immediate)
doHide()
else
hideTimer = setTimeout(doHide, 120)
}
export function isTooltipVisible() {
return visible
}