feat: publish HoloLake model-native living system source
This commit is contained in:
parent
6ad10edde1
commit
c395dd3a99
2467 changed files with 615073 additions and 0 deletions
|
|
@ -0,0 +1,171 @@
|
|||
import { useCallback, useRef, useState, type ChangeEvent, type FormEvent } from 'react'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import type { GitAddRemoteResult } from '../types'
|
||||
import { isTauri, mockInvoke } from '../mock-tauri'
|
||||
|
||||
type ConnectState = 'idle' | 'connecting'
|
||||
|
||||
interface AddRemoteModalProps {
|
||||
open: boolean
|
||||
vaultPath: string
|
||||
onClose: () => void
|
||||
onRemoteConnected: (message: string) => void | Promise<void>
|
||||
}
|
||||
|
||||
function tauriCall<T>(command: string, args: Record<string, unknown>): Promise<T> {
|
||||
return isTauri() ? invoke<T>(command, args) : mockInvoke<T>(command, args)
|
||||
}
|
||||
|
||||
function shouldCloseAfterResult(result: GitAddRemoteResult): boolean {
|
||||
return result.status === 'connected' || result.status === 'already_configured'
|
||||
}
|
||||
|
||||
async function submitRemoteConnection(
|
||||
vaultPath: string,
|
||||
remoteUrl: string,
|
||||
): Promise<GitAddRemoteResult> {
|
||||
return tauriCall<GitAddRemoteResult>('git_add_remote', {
|
||||
request: {
|
||||
vaultPath,
|
||||
remoteUrl,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async function getConnectErrorMessage({
|
||||
vaultPath,
|
||||
remoteUrl,
|
||||
onRemoteConnected,
|
||||
onClose,
|
||||
}: {
|
||||
vaultPath: string
|
||||
remoteUrl: string
|
||||
onRemoteConnected: (message: string) => void | Promise<void>
|
||||
onClose: () => void
|
||||
}): Promise<string | null> {
|
||||
try {
|
||||
const result = await submitRemoteConnection(vaultPath, remoteUrl)
|
||||
|
||||
if (shouldCloseAfterResult(result)) {
|
||||
await onRemoteConnected(result.message)
|
||||
onClose()
|
||||
return null
|
||||
}
|
||||
|
||||
return result.message
|
||||
} catch (error) {
|
||||
return `Could not connect that remote: ${String(error)}`
|
||||
}
|
||||
}
|
||||
|
||||
export function AddRemoteModal({
|
||||
open,
|
||||
vaultPath,
|
||||
onClose,
|
||||
onRemoteConnected,
|
||||
}: AddRemoteModalProps) {
|
||||
const [remoteUrl, setRemoteUrl] = useState('')
|
||||
const [connectState, setConnectState] = useState<ConnectState>('idle')
|
||||
const [connectError, setConnectError] = useState<string | null>(null)
|
||||
const inputRef = useRef<HTMLInputElement | null>(null)
|
||||
|
||||
const resetState = useCallback(() => {
|
||||
setRemoteUrl('')
|
||||
setConnectState('idle')
|
||||
setConnectError(null)
|
||||
}, [])
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
resetState()
|
||||
onClose()
|
||||
}, [onClose, resetState])
|
||||
|
||||
const handleOpenChange = useCallback((isOpen: boolean) => {
|
||||
if (!isOpen) {
|
||||
handleClose()
|
||||
}
|
||||
}, [handleClose])
|
||||
const handleRemoteUrlChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
|
||||
setRemoteUrl(event.target.value)
|
||||
setConnectError(null)
|
||||
}, [])
|
||||
|
||||
const handleSubmit = useCallback(async (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
|
||||
const trimmedUrl = remoteUrl.trim()
|
||||
if (!trimmedUrl) return
|
||||
|
||||
setConnectState('connecting')
|
||||
setConnectError(null)
|
||||
|
||||
const errorMessage = await getConnectErrorMessage({
|
||||
vaultPath,
|
||||
remoteUrl: trimmedUrl,
|
||||
onRemoteConnected,
|
||||
onClose: handleClose,
|
||||
})
|
||||
|
||||
if (errorMessage) {
|
||||
setConnectError(errorMessage)
|
||||
}
|
||||
|
||||
setConnectState('idle')
|
||||
}, [handleClose, onRemoteConnected, remoteUrl, vaultPath])
|
||||
|
||||
const connectDisabled = connectState === 'connecting' || !remoteUrl.trim()
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||
<DialogContent className="sm:max-w-[520px]" data-testid="add-remote-modal">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Remote</DialogTitle>
|
||||
<DialogDescription>
|
||||
Connect this local vault to a git remote. Your existing local commits stay intact; HoloLake Era
|
||||
will only connect the vault when the remote history is safe to use.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<form className="flex flex-col gap-4 py-2" onSubmit={handleSubmit}>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<label className="text-xs font-medium text-foreground" htmlFor="add-remote-url">Repository URL</label>
|
||||
<Input
|
||||
id="add-remote-url"
|
||||
ref={inputRef}
|
||||
autoFocus
|
||||
placeholder="git@host:owner/repo.git or https://host/owner/repo.git"
|
||||
value={remoteUrl}
|
||||
onChange={handleRemoteUrlChange}
|
||||
data-testid="add-remote-url"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="text-xs leading-relaxed text-muted-foreground">
|
||||
Use an empty repository or one created from this vault. SSH keys, Git Credential Manager,
|
||||
and other system git auth methods all work.
|
||||
</p>
|
||||
|
||||
{connectError && (
|
||||
<p className="text-xs text-destructive" data-testid="add-remote-error">{connectError}</p>
|
||||
)}
|
||||
|
||||
<DialogFooter className="flex-row items-center justify-end sm:justify-end">
|
||||
<Button type="submit" disabled={connectDisabled} data-testid="add-remote-submit">
|
||||
{connectState === 'connecting' ? 'Connecting...' : 'Connect Remote'}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
Loading…
Reference in a new issue