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,78 @@
import type { OnChanges } from '@angular/core'
import type { AngularRenderableNode, AngularRenderContext } from '../shared/node-helpers'
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { getString } from '../shared/node-helpers'
import { resolveStreamingTextState } from '../TextNode/streamingTextState'
@Component({
selector: 'markstream-angular-inline-code-node',
standalone: true,
imports: [CommonModule],
template: `
<code>
<span *ngIf="settledCode">{{ settledCode }}</span>
<span
*ngIf="streamedDelta"
[class]="'markstream-angular-text__stream-delta ' + streamedDeltaClass"
(animationend)="settleStreamedDelta()"
>{{ streamedDelta }}</span>
</code>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InlineCodeNodeComponent implements OnChanges {
@Input({ required: true }) node!: AngularRenderableNode
@Input() context?: AngularRenderContext
@Input() indexKey?: string
@Input() typewriter?: boolean
settledCode = ''
streamedDelta = ''
private streamFadeVersion = 0
ngOnChanges() {
const nextCode = getString((this.node as any)?.code)
const streamStateKey = getString(this.indexKey).trim()
const textStreamState = this.context?.textStreamState
const rendered = `${this.settledCode}${this.streamedDelta}`
const previousPersisted = streamStateKey
? textStreamState?.get(streamStateKey)
: undefined
const previousCode = previousPersisted ?? rendered
const nextState = resolveStreamingTextState({
nextContent: nextCode,
previousContent: previousCode,
typewriterEnabled: this.typewriterEnabled,
})
this.settledCode = nextState.settledContent
this.streamedDelta = nextState.streamedDelta
if (nextState.appended)
this.streamFadeVersion += 1
if (streamStateKey)
textStreamState?.set(streamStateKey, nextCode)
}
get streamedDeltaClass() {
return this.streamFadeVersion % 2 === 0
? 'markstream-angular-text__stream-delta--a'
: 'markstream-angular-text__stream-delta--b'
}
get typewriterEnabled() {
if (typeof this.typewriter === 'boolean')
return this.typewriter
if (typeof this.context?.typewriter === 'boolean')
return this.context.typewriter
return true
}
settleStreamedDelta() {
if (!this.streamedDelta)
return
this.settledCode = `${this.settledCode}${this.streamedDelta}`
this.streamedDelta = ''
}
}