Make provider diagnostics easier to share (#1611)
* Show PATH matches in provider diagnostics * Add copyable provider command probes * Fix provider diagnostic path reporting * Clean up command probe diagnostics
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { AlertTriangle, FileText, Plus, RotateCw, Trash2 } from "lucide-react-native";
|
||||
import * as Clipboard from "expo-clipboard";
|
||||
import { AlertTriangle, Copy, FileText, Plus, RotateCw, Trash2 } from "lucide-react-native";
|
||||
import type { TFunction } from "i18next";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -20,6 +21,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { LoadingSpinner } from "@/components/ui/loading-spinner";
|
||||
import { useIsCompactFormFactor } from "@/constants/layout";
|
||||
import { isWeb } from "@/constants/platform";
|
||||
import { useToast } from "@/contexts/toast-context";
|
||||
import { CODE_SURFACE_DATASET } from "@/styles/code-surface";
|
||||
import { useDaemonConfig } from "@/hooks/use-daemon-config";
|
||||
import { useProvidersSnapshot } from "@/hooks/use-providers-snapshot";
|
||||
@@ -248,6 +250,7 @@ function DiagnosticSubSheet({
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { theme } = useUnistyles();
|
||||
const toast = useToast();
|
||||
const client = useHostRuntimeClient(serverId);
|
||||
const [diagnostic, setDiagnostic] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -288,31 +291,62 @@ function DiagnosticSubSheet({
|
||||
void fetchDiagnostic();
|
||||
}, [fetchDiagnostic]);
|
||||
|
||||
const copyButtonStyle = useCallback(
|
||||
({ hovered, pressed }: PressableStateCallbackType & { hovered?: boolean }) => [
|
||||
sheetStyles.iconButton,
|
||||
(Boolean(hovered) || pressed) && Boolean(diagnostic) && sheetStyles.iconButtonHovered,
|
||||
diagnostic ? null : sheetStyles.disabled,
|
||||
],
|
||||
[diagnostic],
|
||||
);
|
||||
|
||||
const handleCopyPress = useCallback(() => {
|
||||
if (!diagnostic) return;
|
||||
void Clipboard.setStringAsync(diagnostic)
|
||||
.then(() => toast.copied(t("settings.providers.diagnostic.copyLabel")))
|
||||
.catch(() => toast.error(t("settings.providers.diagnostic.copyFailed")));
|
||||
}, [diagnostic, t, toast]);
|
||||
|
||||
const header = useMemo<SheetHeader>(
|
||||
() => ({
|
||||
title: t("settings.providers.diagnostic.title"),
|
||||
actions: (
|
||||
<Pressable
|
||||
onPress={handleRefreshPress}
|
||||
disabled={loading}
|
||||
hitSlop={8}
|
||||
style={refreshButtonStyle}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={
|
||||
loading
|
||||
? t("settings.providers.diagnostic.refreshingAccessibility")
|
||||
: t("settings.providers.diagnostic.refreshAccessibility")
|
||||
}
|
||||
>
|
||||
{loading ? (
|
||||
<LoadingSpinner size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
) : (
|
||||
<RotateCw size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
)}
|
||||
</Pressable>
|
||||
<View style={sheetStyles.headerActions}>
|
||||
<Pressable
|
||||
onPress={handleCopyPress}
|
||||
disabled={!diagnostic}
|
||||
hitSlop={8}
|
||||
style={copyButtonStyle}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t("settings.providers.diagnostic.copyAccessibility")}
|
||||
>
|
||||
<Copy size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
</Pressable>
|
||||
<Pressable
|
||||
onPress={handleRefreshPress}
|
||||
disabled={loading}
|
||||
hitSlop={8}
|
||||
style={refreshButtonStyle}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={
|
||||
loading
|
||||
? t("settings.providers.diagnostic.refreshingAccessibility")
|
||||
: t("settings.providers.diagnostic.refreshAccessibility")
|
||||
}
|
||||
>
|
||||
{loading ? (
|
||||
<LoadingSpinner size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
) : (
|
||||
<RotateCw size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
)}
|
||||
</Pressable>
|
||||
</View>
|
||||
),
|
||||
}),
|
||||
[
|
||||
copyButtonStyle,
|
||||
diagnostic,
|
||||
handleCopyPress,
|
||||
handleRefreshPress,
|
||||
loading,
|
||||
refreshButtonStyle,
|
||||
@@ -733,6 +767,11 @@ const sheetStyles = StyleSheet.create((theme) => ({
|
||||
iconButtonHovered: {
|
||||
backgroundColor: theme.colors.surface2,
|
||||
},
|
||||
headerActions: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: theme.spacing[1],
|
||||
},
|
||||
disabled: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
|
||||
@@ -1778,6 +1778,9 @@ export const ar: TranslationResources = {
|
||||
button: "التشخيص",
|
||||
refresh: "ينعش",
|
||||
refreshing: "منعش...",
|
||||
copyLabel: "التشخيص",
|
||||
copyAccessibility: "نسخ التشخيص",
|
||||
copyFailed: "فشل نسخ التشخيص",
|
||||
refreshAccessibility: "تحديث التشخيص",
|
||||
refreshingAccessibility: "تحديث التشخيص",
|
||||
running: "تشغيل التشخيص...",
|
||||
|
||||
@@ -1786,6 +1786,9 @@ export const en = {
|
||||
button: "Diagnostic",
|
||||
refresh: "Refresh",
|
||||
refreshing: "Refreshing...",
|
||||
copyLabel: "diagnostic",
|
||||
copyAccessibility: "Copy diagnostic",
|
||||
copyFailed: "Failed to copy diagnostic",
|
||||
refreshAccessibility: "Refresh diagnostic",
|
||||
refreshingAccessibility: "Refreshing diagnostic",
|
||||
running: "Running diagnostic...",
|
||||
|
||||
@@ -1819,6 +1819,9 @@ export const es: TranslationResources = {
|
||||
button: "Diagnóstico",
|
||||
refresh: "Refrescar",
|
||||
refreshing: "Refrescante...",
|
||||
copyLabel: "diagnóstico",
|
||||
copyAccessibility: "Copiar diagnóstico",
|
||||
copyFailed: "No se pudo copiar el diagnóstico",
|
||||
refreshAccessibility: "Actualizar diagnóstico",
|
||||
refreshingAccessibility: "Diagnóstico refrescante",
|
||||
running: "Ejecutando diagnóstico...",
|
||||
|
||||
@@ -1824,6 +1824,9 @@ export const fr: TranslationResources = {
|
||||
button: "Diagnostique",
|
||||
refresh: "Rafraîchir",
|
||||
refreshing: "Rafraîchissant...",
|
||||
copyLabel: "diagnostic",
|
||||
copyAccessibility: "Copier le diagnostic",
|
||||
copyFailed: "Échec de la copie du diagnostic",
|
||||
refreshAccessibility: "Actualiser le diagnostic",
|
||||
refreshingAccessibility: "Diagnostic rafraîchissant",
|
||||
running: "Exécution du diagnostic...",
|
||||
|
||||
@@ -1810,6 +1810,9 @@ export const ru: TranslationResources = {
|
||||
button: "Диагностика",
|
||||
refresh: "Обновить",
|
||||
refreshing: "Освежающий...",
|
||||
copyLabel: "диагностика",
|
||||
copyAccessibility: "Скопировать диагностику",
|
||||
copyFailed: "Не удалось скопировать диагностику",
|
||||
refreshAccessibility: "Обновить диагностику",
|
||||
refreshingAccessibility: "Обновление диагностики",
|
||||
running: "Запускаю диагностику...",
|
||||
|
||||
@@ -1755,6 +1755,9 @@ export const zhCN: TranslationResources = {
|
||||
button: "诊断",
|
||||
refresh: "刷新",
|
||||
refreshing: "正在刷新...",
|
||||
copyLabel: "诊断",
|
||||
copyAccessibility: "复制诊断",
|
||||
copyFailed: "复制诊断失败",
|
||||
refreshAccessibility: "刷新诊断",
|
||||
refreshingAccessibility: "正在刷新诊断",
|
||||
running: "正在运行诊断...",
|
||||
|
||||
Reference in New Issue
Block a user