From 67b29d10f6c56df9244fdb658cee1783d23c98ca Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Fri, 24 Apr 2026 05:42:26 +0700 Subject: [PATCH] chore(lint): hoist jsx-as-prop in desktop components Memoize inline JSX passed as props across desktop-permissions-section, desktop-updates-section, integrations-section, and pair-device-section to satisfy react-perf/jsx-no-jsx-as-prop. --- .../desktop-permissions-section.tsx | 38 +++++---- .../components/desktop-updates-section.tsx | 78 ++++++++++++------- .../components/integrations-section.tsx | 64 ++++++++------- .../components/pair-device-section.tsx | 36 ++++----- 4 files changed, 128 insertions(+), 88 deletions(-) diff --git a/packages/app/src/desktop/components/desktop-permissions-section.tsx b/packages/app/src/desktop/components/desktop-permissions-section.tsx index 5662798e2..b9812ec30 100644 --- a/packages/app/src/desktop/components/desktop-permissions-section.tsx +++ b/packages/app/src/desktop/components/desktop-permissions-section.tsx @@ -43,26 +43,34 @@ export function DesktopPermissionsSection() { void sendTestNotification(); }, [sendTestNotification]); - if (!isDesktopApp) { - return null; - } - const isBusy = isRefreshing || requestingPermission !== null; const notificationsGranted = snapshot?.notifications.state === "granted"; - const refreshButton = ( - + const refreshIcon = useMemo( + () => , + [theme.iconSize.md, theme.colors.foregroundMuted], ); + const refreshButton = useMemo( + () => ( + + ), + [refreshIcon, handleRefreshPress, isBusy, isRefreshing], + ); + + if (!isDesktopApp) { + return null; + } + return ( diff --git a/packages/app/src/desktop/components/desktop-updates-section.tsx b/packages/app/src/desktop/components/desktop-updates-section.tsx index ea83f0c44..6fc8a254b 100644 --- a/packages/app/src/desktop/components/desktop-updates-section.tsx +++ b/packages/app/src/desktop/components/desktop-updates-section.tsx @@ -1,4 +1,4 @@ -import { useCallback, useState } from "react"; +import { useCallback, useMemo, useState } from "react"; import { ActivityIndicator, Alert, Text, View } from "react-native"; import * as Clipboard from "expo-clipboard"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; @@ -247,24 +247,56 @@ export function LocalDaemonSection() { const handleCloseLogsModal = useCallback(() => setIsLogsModalOpen(false), []); const handleCloseCliStatusModal = useCallback(() => setIsCliStatusModalOpen(false), []); + const advancedSettingsIcon = useMemo( + () => , + [theme.iconSize.sm, theme.colors.foregroundMuted], + ); + const playIcon = useMemo( + () => , + [theme.iconSize.sm, theme.colors.foreground], + ); + const pauseIcon = useMemo( + () => , + [theme.iconSize.sm, theme.colors.foreground], + ); + const rotateIcon = useMemo( + () => , + [theme.iconSize.sm, theme.colors.foreground], + ); + const copyIcon = useMemo( + () => , + [theme.iconSize.sm, theme.colors.foreground], + ); + const fileTextIcon = useMemo( + () => , + [theme.iconSize.sm, theme.colors.foreground], + ); + const activityIcon = useMemo( + () => , + [theme.iconSize.sm, theme.colors.foreground], + ); + + const advancedSettingsButton = useMemo( + () => ( + + ), + [advancedSettingsIcon, handleOpenAdvancedSettings], + ); + if (!showSection) { return null; } - const advancedSettingsButton = ( - - ); - return ( - ) : ( - - ) - } + leftIcon={isDaemonManagementPaused ? playIcon : pauseIcon} onPress={handleToggleDaemonManagement} disabled={isUpdatingDaemonManagement} > @@ -330,7 +356,7 @@ export function LocalDaemonSection() { + + + ), + [arrowIcon, handleOpenCliDocs, handleOpenSkillsDocs], + ); + if (!showSection) { return null; } - const trailing = ( - - - - - ); - return ( diff --git a/packages/app/src/desktop/components/pair-device-section.tsx b/packages/app/src/desktop/components/pair-device-section.tsx index 5cacc0dd7..e098aa46d 100644 --- a/packages/app/src/desktop/components/pair-device-section.tsx +++ b/packages/app/src/desktop/components/pair-device-section.tsx @@ -55,6 +55,20 @@ export function PairDeviceSection() { [qrQuery.data], ); + const retryIcon = useMemo( + () => , + [theme.iconSize.sm, theme.colors.foreground], + ); + const copyButtonIcon = useMemo( + () => + copied ? ( + + ) : ( + + ), + [copied, theme.iconSize.sm, theme.colors.accent, theme.colors.foreground], + ); + if (!showSection) return null; return ( @@ -72,12 +86,7 @@ export function PairDeviceSection() { ? pairingQuery.error.message : "Failed to load pairing offer."} - @@ -88,12 +97,7 @@ export function PairDeviceSection() { ? "Relay is not enabled. Enable relay to pair a device." : "Pairing offer unavailable."} - @@ -124,13 +128,7 @@ export function PairDeviceSection() {