Show connected host daemon versions on the About page (#1220)
* Show connected host daemon versions on the About page * Update About E2E assertion for the App version label
This commit is contained in:
@@ -156,7 +156,7 @@ export async function expectDiagnosticsContent(page: Page): Promise<void> {
|
||||
}
|
||||
|
||||
export async function expectAboutContent(page: Page): Promise<void> {
|
||||
await expect(page.getByText("Version", { exact: true }).first()).toBeVisible();
|
||||
await expect(page.getByText("App version", { exact: true }).first()).toBeVisible();
|
||||
}
|
||||
|
||||
export async function expectGeneralContent(page: Page): Promise<void> {
|
||||
|
||||
@@ -45,7 +45,14 @@ import {
|
||||
type Settings as EffectiveSettings,
|
||||
} from "@/hooks/use-settings";
|
||||
import { THEME_SWATCHES } from "@/styles/theme";
|
||||
import { getHostRuntimeStore, isHostRuntimeConnected, useHosts } from "@/runtime/host-runtime";
|
||||
import {
|
||||
getHostRuntimeStore,
|
||||
isHostRuntimeConnected,
|
||||
useHostRuntimeIsConnected,
|
||||
useHosts,
|
||||
} from "@/runtime/host-runtime";
|
||||
import { useSessionStore } from "@/stores/session-store";
|
||||
import type { HostProfile } from "@/types/host-connection";
|
||||
import { TitlebarDragRegion } from "@/components/desktop/titlebar-drag-region";
|
||||
import { useWindowControlsPadding } from "@/utils/desktop-window";
|
||||
import { confirmDialog } from "@/utils/confirm-dialog";
|
||||
@@ -442,29 +449,114 @@ function DiagnosticsSection({
|
||||
}
|
||||
|
||||
interface AboutSectionProps {
|
||||
appVersion: string | null;
|
||||
appVersionText: string;
|
||||
isDesktopApp: boolean;
|
||||
}
|
||||
|
||||
function AboutSection({ appVersionText, isDesktopApp }: AboutSectionProps) {
|
||||
function AboutSection({ appVersion, appVersionText, isDesktopApp }: AboutSectionProps) {
|
||||
return (
|
||||
<SettingsSection title="About">
|
||||
<View style={settingsStyles.card}>
|
||||
<View style={settingsStyles.row}>
|
||||
<View style={settingsStyles.rowContent}>
|
||||
<Text style={settingsStyles.rowTitle}>Version</Text>
|
||||
<>
|
||||
<SettingsSection title="About">
|
||||
<View style={settingsStyles.card}>
|
||||
<View style={settingsStyles.row}>
|
||||
<View style={settingsStyles.rowContent}>
|
||||
<Text style={settingsStyles.rowTitle}>App version</Text>
|
||||
<Text style={settingsStyles.rowHint}>This device</Text>
|
||||
</View>
|
||||
<Text style={styles.aboutValue}>{appVersionText}</Text>
|
||||
</View>
|
||||
<Text style={styles.aboutValue}>{appVersionText}</Text>
|
||||
{isDesktopApp ? <DesktopAppUpdateRow /> : null}
|
||||
</View>
|
||||
{isDesktopApp ? <DesktopAppUpdateRow /> : null}
|
||||
</View>
|
||||
</SettingsSection>
|
||||
<ConnectedHostsSection clientVersion={appVersion} />
|
||||
<View style={styles.aboutCommunity}>
|
||||
<CommunityLinks />
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeVersion(version: string | null | undefined): string | null {
|
||||
const trimmed = version?.trim();
|
||||
if (!trimmed) return null;
|
||||
return trimmed.replace(/^v/i, "");
|
||||
}
|
||||
|
||||
function ConnectedHostsSection({ clientVersion }: { clientVersion: string | null }) {
|
||||
const hosts = useHosts();
|
||||
if (hosts.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<SettingsSection title="Connected hosts">
|
||||
<View style={settingsStyles.card}>
|
||||
{hosts.map((host, index) => (
|
||||
<HostVersionRow
|
||||
key={host.serverId}
|
||||
host={host}
|
||||
showBorder={index > 0}
|
||||
clientVersion={clientVersion}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</SettingsSection>
|
||||
);
|
||||
}
|
||||
|
||||
function HostVersionRow({
|
||||
host,
|
||||
showBorder,
|
||||
clientVersion,
|
||||
}: {
|
||||
host: HostProfile;
|
||||
showBorder: boolean;
|
||||
clientVersion: string | null;
|
||||
}) {
|
||||
const isConnected = useHostRuntimeIsConnected(host.serverId);
|
||||
const daemonVersion = useSessionStore(
|
||||
(state) => state.sessions[host.serverId]?.serverInfo?.version ?? null,
|
||||
);
|
||||
|
||||
const rowStyle = useMemo(
|
||||
() => [settingsStyles.row, showBorder && settingsStyles.rowBorder],
|
||||
[showBorder],
|
||||
);
|
||||
|
||||
const normalizedHost = normalizeVersion(daemonVersion);
|
||||
const normalizedClient = normalizeVersion(clientVersion);
|
||||
const isMismatch =
|
||||
normalizedHost !== null && normalizedClient !== null && normalizedHost !== normalizedClient;
|
||||
|
||||
let valueText: string;
|
||||
if (!isConnected) {
|
||||
valueText = "Offline";
|
||||
} else if (normalizedHost) {
|
||||
valueText = formatVersionWithPrefix(normalizedHost);
|
||||
} else {
|
||||
valueText = "—";
|
||||
}
|
||||
|
||||
const valueStyle = useMemo(
|
||||
() => [styles.aboutValue, isMismatch && styles.aboutVersionMismatch],
|
||||
[isMismatch],
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={rowStyle}>
|
||||
<View style={settingsStyles.rowContent}>
|
||||
<Text style={settingsStyles.rowTitle} numberOfLines={1}>
|
||||
{host.label}
|
||||
</Text>
|
||||
{isMismatch ? (
|
||||
<Text style={settingsStyles.rowHint}>Version differs from this device</Text>
|
||||
) : null}
|
||||
</View>
|
||||
<Text style={valueStyle}>{valueText}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function getUpdateButtonLabel(
|
||||
isInstalling: boolean,
|
||||
latestVersion: string | null | undefined,
|
||||
@@ -1106,7 +1198,13 @@ export default function SettingsScreen({ view }: SettingsScreenProps) {
|
||||
/>
|
||||
);
|
||||
case "about":
|
||||
return <AboutSection appVersionText={appVersionText} isDesktopApp={isDesktopApp} />;
|
||||
return (
|
||||
<AboutSection
|
||||
appVersion={appVersion}
|
||||
appVersionText={appVersionText}
|
||||
isDesktopApp={isDesktopApp}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1266,6 +1364,9 @@ const styles = StyleSheet.create((theme) => ({
|
||||
color: theme.colors.foregroundMuted,
|
||||
fontSize: theme.fontSize.sm,
|
||||
},
|
||||
aboutVersionMismatch: {
|
||||
color: theme.colors.palette.amber[500],
|
||||
},
|
||||
aboutErrorText: {
|
||||
color: theme.colors.palette.red[300],
|
||||
fontSize: theme.fontSize.xs,
|
||||
|
||||
Reference in New Issue
Block a user