refactor(app): move startup routing logic into welcome screen and simplify index route
This commit is contained in:
@@ -1,36 +0,0 @@
|
|||||||
export const WELCOME_ROUTE = "/welcome";
|
|
||||||
|
|
||||||
export function shouldWaitOnStartupRace(input: {
|
|
||||||
onlineServerId: string | null;
|
|
||||||
hasTimedOut: boolean;
|
|
||||||
isDesktopStartupRace: boolean;
|
|
||||||
daemonCount: number;
|
|
||||||
pathname: string;
|
|
||||||
}): boolean {
|
|
||||||
if (input.onlineServerId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (input.pathname === WELCOME_ROUTE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (input.hasTimedOut) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return input.isDesktopStartupRace || input.daemonCount > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function shouldRedirectToWelcome(input: {
|
|
||||||
onlineServerId: string | null;
|
|
||||||
hasTimedOut: boolean;
|
|
||||||
pathname: string;
|
|
||||||
isDesktopStartupRace: boolean;
|
|
||||||
daemonCount: number;
|
|
||||||
}): boolean {
|
|
||||||
if (input.onlineServerId || !input.hasTimedOut) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (input.pathname !== "/" && input.pathname !== "") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return input.isDesktopStartupRace || input.daemonCount > 0;
|
|
||||||
}
|
|
||||||
@@ -25,6 +25,9 @@ import {
|
|||||||
useHostMutations,
|
useHostMutations,
|
||||||
useHostRuntimeClient,
|
useHostRuntimeClient,
|
||||||
} from "@/runtime/host-runtime";
|
} from "@/runtime/host-runtime";
|
||||||
|
import { shouldUseDesktopDaemon } from "@/desktop/daemon/desktop-daemon";
|
||||||
|
import { StartupSplashScreen } from "@/screens/startup-splash-screen";
|
||||||
|
import { loadSettingsFromStorage } from "@/hooks/use-settings";
|
||||||
import { SessionProvider } from "@/contexts/session-context";
|
import { SessionProvider } from "@/contexts/session-context";
|
||||||
import type { HostProfile } from "@/types/host-connection";
|
import type { HostProfile } from "@/types/host-connection";
|
||||||
import {
|
import {
|
||||||
@@ -210,14 +213,22 @@ function HostRuntimeBootstrapProvider({ children }: { children: ReactNode }) {
|
|||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
const store = getHostRuntimeStore();
|
const store = getHostRuntimeStore();
|
||||||
|
|
||||||
void store
|
const init = async () => {
|
||||||
.loadFromStorage()
|
const settings = await loadSettingsFromStorage();
|
||||||
|
const isDesktopManaged = shouldUseDesktopDaemon() && settings.manageBuiltInDaemon;
|
||||||
|
await store.loadFromStorage();
|
||||||
|
if (isDesktopManaged) {
|
||||||
|
await store.bootstrap({ manageBuiltInDaemon: true });
|
||||||
|
} else {
|
||||||
|
void store.bootstrap({ manageBuiltInDaemon: settings.manageBuiltInDaemon });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void init()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (cancelled) {
|
if (!cancelled) {
|
||||||
return;
|
setReady(true);
|
||||||
}
|
}
|
||||||
setReady(true);
|
|
||||||
void store.bootstrap();
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("[HostRuntime] Failed to initialize store", error);
|
console.error("[HostRuntime] Failed to initialize store", error);
|
||||||
@@ -415,7 +426,9 @@ function ProvidersWrapper({ children }: { children: ReactNode }) {
|
|||||||
}, [isLoading, settings.theme]);
|
}, [isLoading, settings.theme]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <LoadingView />;
|
const isDesktopManaged =
|
||||||
|
!settingsLoading && shouldUseDesktopDaemon() && settings.manageBuiltInDaemon;
|
||||||
|
return isDesktopManaged ? <StartupSplashScreen /> : <LoadingView />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,113 +1,18 @@
|
|||||||
import { useEffect, useSyncExternalStore, useState } from "react";
|
import { useEffect } from "react";
|
||||||
import { usePathname, useRouter } from "expo-router";
|
import { usePathname, useRouter } from "expo-router";
|
||||||
import { useHosts } from "@/runtime/host-runtime";
|
|
||||||
import { shouldUseDesktopDaemon } from "@/desktop/daemon/desktop-daemon";
|
|
||||||
import { buildHostRootRoute } from "@/utils/host-routes";
|
|
||||||
import { StartupSplashScreen } from "@/screens/startup-splash-screen";
|
|
||||||
import { WelcomeScreen } from "@/components/welcome-screen";
|
|
||||||
import { getHostRuntimeStore, isHostRuntimeConnected } from "@/runtime/host-runtime";
|
|
||||||
import {
|
|
||||||
shouldRedirectToWelcome,
|
|
||||||
shouldWaitOnStartupRace,
|
|
||||||
WELCOME_ROUTE,
|
|
||||||
} from "@/app-support/index-startup";
|
|
||||||
|
|
||||||
const STARTUP_TIMEOUT_MS = 30_000;
|
const WELCOME_ROUTE = "/welcome";
|
||||||
function useAnyHostOnline(serverIds: string[]): string | null {
|
|
||||||
const runtime = getHostRuntimeStore();
|
|
||||||
return useSyncExternalStore(
|
|
||||||
(onStoreChange) => runtime.subscribeAll(onStoreChange),
|
|
||||||
() => {
|
|
||||||
let firstOnlineServerId: string | null = null;
|
|
||||||
let firstOnlineAt: string | null = null;
|
|
||||||
for (const serverId of serverIds) {
|
|
||||||
const snapshot = runtime.getSnapshot(serverId);
|
|
||||||
const lastOnlineAt = snapshot?.lastOnlineAt ?? null;
|
|
||||||
if (!isHostRuntimeConnected(snapshot) || !lastOnlineAt) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!firstOnlineAt || lastOnlineAt < firstOnlineAt) {
|
|
||||||
firstOnlineAt = lastOnlineAt;
|
|
||||||
firstOnlineServerId = serverId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return firstOnlineServerId;
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
let firstOnlineServerId: string | null = null;
|
|
||||||
let firstOnlineAt: string | null = null;
|
|
||||||
for (const serverId of serverIds) {
|
|
||||||
const snapshot = runtime.getSnapshot(serverId);
|
|
||||||
const lastOnlineAt = snapshot?.lastOnlineAt ?? null;
|
|
||||||
if (!isHostRuntimeConnected(snapshot) || !lastOnlineAt) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!firstOnlineAt || lastOnlineAt < firstOnlineAt) {
|
|
||||||
firstOnlineAt = lastOnlineAt;
|
|
||||||
firstOnlineServerId = serverId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return firstOnlineServerId;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const daemons = useHosts();
|
|
||||||
const [hasTimedOut, setHasTimedOut] = useState(false);
|
|
||||||
const isDesktopStartupRace = shouldUseDesktopDaemon();
|
|
||||||
const onlineServerId = useAnyHostOnline(daemons.map((daemon) => daemon.serverId));
|
|
||||||
useEffect(() => {
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
setHasTimedOut(true);
|
|
||||||
}, STARTUP_TIMEOUT_MS);
|
|
||||||
return () => {
|
|
||||||
clearTimeout(timer);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!onlineServerId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pathname !== "/" && pathname !== "") {
|
if (pathname !== "/" && pathname !== "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
router.replace(buildHostRootRoute(onlineServerId) as any);
|
|
||||||
}, [onlineServerId, pathname, router]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (
|
|
||||||
!shouldRedirectToWelcome({
|
|
||||||
onlineServerId,
|
|
||||||
hasTimedOut,
|
|
||||||
pathname,
|
|
||||||
isDesktopStartupRace,
|
|
||||||
daemonCount: daemons.length,
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
router.replace(WELCOME_ROUTE as any);
|
router.replace(WELCOME_ROUTE as any);
|
||||||
}, [daemons.length, hasTimedOut, isDesktopStartupRace, onlineServerId, pathname, router]);
|
}, [pathname, router]);
|
||||||
|
|
||||||
if (
|
|
||||||
shouldWaitOnStartupRace({
|
|
||||||
onlineServerId,
|
|
||||||
hasTimedOut,
|
|
||||||
isDesktopStartupRace,
|
|
||||||
daemonCount: daemons.length,
|
|
||||||
pathname,
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
return <StartupSplashScreen />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!onlineServerId) {
|
|
||||||
return <WelcomeScreen />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState, useSyncExternalStore } from "react";
|
||||||
import { Pressable, Text, View, Platform, ScrollView } from "react-native";
|
import { Pressable, Text, View, Platform, ScrollView } from "react-native";
|
||||||
import { useRouter } from "expo-router";
|
import { useRouter } from "expo-router";
|
||||||
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
||||||
import { QrCode, Link2, ClipboardPaste } from "lucide-react-native";
|
import { QrCode, Link2, ClipboardPaste } from "lucide-react-native";
|
||||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
import type { HostProfile } from "@/types/host-connection";
|
import type { HostProfile } from "@/types/host-connection";
|
||||||
import { useHostMutations } from "@/runtime/host-runtime";
|
import {
|
||||||
|
getHostRuntimeStore,
|
||||||
|
isHostRuntimeConnected,
|
||||||
|
useHostMutations,
|
||||||
|
useHostRuntimeSnapshot,
|
||||||
|
useHosts,
|
||||||
|
} from "@/runtime/host-runtime";
|
||||||
import { useSessionStore } from "@/stores/session-store";
|
import { useSessionStore } from "@/stores/session-store";
|
||||||
import { AddHostModal } from "./add-host-modal";
|
import { AddHostModal } from "./add-host-modal";
|
||||||
import { PairLinkModal } from "./pair-link-modal";
|
import { PairLinkModal } from "./pair-link-modal";
|
||||||
@@ -79,6 +85,39 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
actionTextPrimary: {
|
actionTextPrimary: {
|
||||||
color: theme.colors.accentForeground,
|
color: theme.colors.accentForeground,
|
||||||
},
|
},
|
||||||
|
hostList: {
|
||||||
|
width: "100%",
|
||||||
|
maxWidth: 420,
|
||||||
|
marginTop: theme.spacing[6],
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderTopColor: theme.colors.border,
|
||||||
|
paddingTop: theme.spacing[4],
|
||||||
|
gap: theme.spacing[2],
|
||||||
|
},
|
||||||
|
hostRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: theme.spacing[3],
|
||||||
|
paddingVertical: theme.spacing[2],
|
||||||
|
},
|
||||||
|
statusDot: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
hostLabel: {
|
||||||
|
flex: 1,
|
||||||
|
color: theme.colors.foreground,
|
||||||
|
fontSize: theme.fontSize.sm,
|
||||||
|
},
|
||||||
|
hostStatus: {
|
||||||
|
color: theme.colors.foregroundMuted,
|
||||||
|
fontSize: theme.fontSize.sm,
|
||||||
|
},
|
||||||
|
hostStatusError: {
|
||||||
|
color: theme.colors.destructive,
|
||||||
|
fontSize: theme.fontSize.sm,
|
||||||
|
},
|
||||||
versionLabel: {
|
versionLabel: {
|
||||||
color: theme.colors.foregroundMuted,
|
color: theme.colors.foregroundMuted,
|
||||||
fontSize: theme.fontSize.xs,
|
fontSize: theme.fontSize.xs,
|
||||||
@@ -87,6 +126,89 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
function useAnyHostOnline(serverIds: string[]): string | null {
|
||||||
|
const runtime = getHostRuntimeStore();
|
||||||
|
return useSyncExternalStore(
|
||||||
|
(onStoreChange) => runtime.subscribeAll(onStoreChange),
|
||||||
|
() => {
|
||||||
|
let firstOnlineServerId: string | null = null;
|
||||||
|
let firstOnlineAt: string | null = null;
|
||||||
|
for (const serverId of serverIds) {
|
||||||
|
const snapshot = runtime.getSnapshot(serverId);
|
||||||
|
const lastOnlineAt = snapshot?.lastOnlineAt ?? null;
|
||||||
|
if (!isHostRuntimeConnected(snapshot) || !lastOnlineAt) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!firstOnlineAt || lastOnlineAt < firstOnlineAt) {
|
||||||
|
firstOnlineAt = lastOnlineAt;
|
||||||
|
firstOnlineServerId = serverId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return firstOnlineServerId;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
let firstOnlineServerId: string | null = null;
|
||||||
|
let firstOnlineAt: string | null = null;
|
||||||
|
for (const serverId of serverIds) {
|
||||||
|
const snapshot = runtime.getSnapshot(serverId);
|
||||||
|
const lastOnlineAt = snapshot?.lastOnlineAt ?? null;
|
||||||
|
if (!isHostRuntimeConnected(snapshot) || !lastOnlineAt) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!firstOnlineAt || lastOnlineAt < firstOnlineAt) {
|
||||||
|
firstOnlineAt = lastOnlineAt;
|
||||||
|
firstOnlineServerId = serverId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return firstOnlineServerId;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function HostStatusRow({ serverId, label }: { serverId: string; label: string }) {
|
||||||
|
const { theme } = useUnistyles();
|
||||||
|
const snapshot = useHostRuntimeSnapshot(serverId);
|
||||||
|
const status = snapshot?.connectionStatus ?? "connecting";
|
||||||
|
const lastError = snapshot?.lastError ?? null;
|
||||||
|
|
||||||
|
let dotColor: string;
|
||||||
|
let statusText: string;
|
||||||
|
let isError = false;
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case "online":
|
||||||
|
dotColor = theme.colors.success;
|
||||||
|
statusText = "Online";
|
||||||
|
break;
|
||||||
|
case "connecting":
|
||||||
|
case "idle":
|
||||||
|
dotColor = theme.colors.foregroundMuted;
|
||||||
|
statusText = "Connecting…";
|
||||||
|
break;
|
||||||
|
case "offline":
|
||||||
|
dotColor = theme.colors.foregroundMuted;
|
||||||
|
statusText = "Offline";
|
||||||
|
break;
|
||||||
|
case "error":
|
||||||
|
dotColor = theme.colors.destructive;
|
||||||
|
statusText = lastError ? lastError.slice(0, 40) : "Connection error";
|
||||||
|
isError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.hostRow}>
|
||||||
|
<View style={[styles.statusDot, { backgroundColor: dotColor }]} />
|
||||||
|
<Text style={styles.hostLabel} numberOfLines={1}>
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
<Text style={isError ? styles.hostStatusError : styles.hostStatus} numberOfLines={1}>
|
||||||
|
{statusText}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export interface WelcomeScreenProps {
|
export interface WelcomeScreenProps {
|
||||||
onHostAdded?: (profile: HostProfile) => void;
|
onHostAdded?: (profile: HostProfile) => void;
|
||||||
}
|
}
|
||||||
@@ -105,6 +227,8 @@ export function WelcomeScreen({ onHostAdded }: WelcomeScreenProps) {
|
|||||||
hostname: string | null;
|
hostname: string | null;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [pendingRedirectServerId, setPendingRedirectServerId] = useState<string | null>(null);
|
const [pendingRedirectServerId, setPendingRedirectServerId] = useState<string | null>(null);
|
||||||
|
const hosts = useHosts();
|
||||||
|
const anyOnlineServerId = useAnyHostOnline(hosts.map((h) => h.serverId));
|
||||||
const pendingNameHostname = useSessionStore(
|
const pendingNameHostname = useSessionStore(
|
||||||
useCallback(
|
useCallback(
|
||||||
(state) => {
|
(state) => {
|
||||||
@@ -119,6 +243,16 @@ export function WelcomeScreen({ onHostAdded }: WelcomeScreenProps) {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!anyOnlineServerId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pendingNameHost) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
router.replace(buildHostRootRoute(anyOnlineServerId) as any);
|
||||||
|
}, [anyOnlineServerId, pendingNameHost, router]);
|
||||||
|
|
||||||
const finishOnboarding = useCallback(
|
const finishOnboarding = useCallback(
|
||||||
(serverId: string) => {
|
(serverId: string) => {
|
||||||
router.replace(buildHostRootRoute(serverId) as any);
|
router.replace(buildHostRootRoute(serverId) as any);
|
||||||
@@ -173,6 +307,8 @@ export function WelcomeScreen({ onHostAdded }: WelcomeScreenProps) {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const showHostList = hosts.length > 0 && !anyOnlineServerId;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
style={{ flex: 1, backgroundColor: theme.colors.surface0 }}
|
style={{ flex: 1, backgroundColor: theme.colors.surface0 }}
|
||||||
@@ -186,7 +322,9 @@ export function WelcomeScreen({ onHostAdded }: WelcomeScreenProps) {
|
|||||||
<View style={styles.content}>
|
<View style={styles.content}>
|
||||||
<PaseoLogo size={96} color={theme.colors.foreground} />
|
<PaseoLogo size={96} color={theme.colors.foreground} />
|
||||||
<Text style={styles.title}>Welcome to Paseo</Text>
|
<Text style={styles.title}>Welcome to Paseo</Text>
|
||||||
<Text style={styles.subtitle}>Connect to your host to start</Text>
|
<Text style={styles.subtitle}>
|
||||||
|
{showHostList ? "Connecting to your hosts…" : "Connect to your host to start"}
|
||||||
|
</Text>
|
||||||
|
|
||||||
<View style={styles.actions}>
|
<View style={styles.actions}>
|
||||||
{actions.map((action) => {
|
{actions.map((action) => {
|
||||||
@@ -209,6 +347,14 @@ export function WelcomeScreen({ onHostAdded }: WelcomeScreenProps) {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{showHostList && (
|
||||||
|
<View style={styles.hostList}>
|
||||||
|
{hosts.map((host) => (
|
||||||
|
<HostStatusRow key={host.serverId} serverId={host.serverId} label={host.label} />
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.versionLabel}>{appVersionText}</Text>
|
<Text style={styles.versionLabel}>{appVersionText}</Text>
|
||||||
|
|
||||||
|
|||||||
@@ -1137,7 +1137,7 @@ export class HostRuntimeStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async bootstrap(): Promise<void> {
|
async bootstrap(options?: { manageBuiltInDaemon?: boolean }): Promise<void> {
|
||||||
if (this.bootstrapAttempted) {
|
if (this.bootstrapAttempted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1153,7 +1153,9 @@ export class HostRuntimeStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shouldUseDesktopDaemon()) {
|
if (shouldUseDesktopDaemon()) {
|
||||||
await this.bootstrapDesktop();
|
if (options?.manageBuiltInDaemon ?? true) {
|
||||||
|
await this.bootstrapDesktop();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await this.bootstrapLocalhost();
|
await this.bootstrapLocalhost();
|
||||||
}
|
}
|
||||||
@@ -1163,20 +1165,16 @@ export class HostRuntimeStore {
|
|||||||
try {
|
try {
|
||||||
const daemon = await startDesktopDaemon();
|
const daemon = await startDesktopDaemon();
|
||||||
const connection = connectionFromListen(daemon.listen);
|
const connection = connectionFromListen(daemon.listen);
|
||||||
if (!connection) {
|
if (!connection || !daemon.serverId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { client, serverId, hostname } = await connectToDaemon(connection, {
|
|
||||||
timeoutMs: DEFAULT_LOCALHOST_BOOTSTRAP_TIMEOUT_MS,
|
|
||||||
});
|
|
||||||
await this.upsertHostConnection({
|
await this.upsertHostConnection({
|
||||||
serverId,
|
serverId: daemon.serverId,
|
||||||
label: hostname ?? daemon.hostname ?? undefined,
|
label: daemon.hostname ?? undefined,
|
||||||
connection,
|
connection,
|
||||||
existingClient: client,
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("[HostRuntime] Failed to bootstrap desktop daemon connection", error);
|
console.warn("[HostRuntime] Failed to bootstrap desktop daemon", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user