From 41b302bf7a72828fb9a3623c30baa03ac86dd0e4 Mon Sep 17 00:00:00 2001 From: SuperKali Date: Mon, 19 Jan 2026 22:02:35 +0100 Subject: [PATCH] feat: add image status warning for nightly builds and community boards Add a warning modal during OS image selection for builds that may have issues: - Nightly builds (trunk versions) on any board - Any image on community-supported boards The warning ensures users understand the risks before proceeding. Community boards are maintained by volunteers and may not receive the same level of testing as official builds. Users expect these boards to work seamlessly, but Armbian doesn't officially test or support them. Priority logic: Community board warnings take precedence over nightly warnings when both conditions apply (nightly build on community board). Implementation: - Added state management and warning dialog to ImageModal - Reset warning state when modal closes to prevent stale state leaks - Updated all 18 locale files with clear warning messages - Community warning explicitly mentions images may not boot or work correctly Closes #82 --- src/components/modals/ImageModal.tsx | 72 +++++++++++++++++++++++++++- src/locales/de.json | 5 +- src/locales/en.json | 5 +- src/locales/es.json | 5 +- src/locales/fr.json | 5 +- src/locales/hr.json | 5 +- src/locales/it.json | 5 +- src/locales/ja.json | 5 +- src/locales/ko.json | 5 +- src/locales/nl.json | 5 +- src/locales/pl.json | 5 +- src/locales/pt-BR.json | 5 +- src/locales/pt.json | 5 +- src/locales/ru.json | 5 +- src/locales/sl.json | 5 +- src/locales/sv.json | 5 +- src/locales/tr.json | 5 +- src/locales/uk.json | 5 +- src/locales/zh.json | 5 +- 19 files changed, 142 insertions(+), 20 deletions(-) diff --git a/src/components/modals/ImageModal.tsx b/src/components/modals/ImageModal.tsx index 37a1940..6ca155e 100644 --- a/src/components/modals/ImageModal.tsx +++ b/src/components/modals/ImageModal.tsx @@ -2,7 +2,7 @@ import { useState, useMemo, useEffect } from 'react'; import { Download, Package, Monitor, Terminal, Zap, Star, Layers, Shield, FlaskConical, AppWindow, Box } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { Modal } from './Modal'; -import { ErrorDisplay, ListItemSkeleton } from '../shared'; +import { ErrorDisplay, ListItemSkeleton, ConfirmationDialog } from '../shared'; import type { BoardInfo, ImageInfo, ImageFilterType } from '../../types'; import { getImagesForBoard } from '../../hooks/useTauri'; import { useAsyncDataWhen } from '../../hooks/useAsyncData'; @@ -75,6 +75,9 @@ export function ImageModal({ isOpen, onClose, onSelect, board }: ImageModalProps const { t } = useTranslation(); const [filterType, setFilterType] = useState('all'); const [showSkeleton, setShowSkeleton] = useState(false); + // State for unstable image warning + const [pendingImage, setPendingImage] = useState(null); + const [showUnstableWarning, setShowUnstableWarning] = useState(false); // Use hook for async data fetching const { data: allImages, loading, error, reload } = useAsyncDataWhen( @@ -109,6 +112,53 @@ export function ImageModal({ isOpen, onClose, onSelect, board }: ImageModalProps }; }, [loading, imagesReady]); + // Reset warning state when modal is closed + useEffect(() => { + if (!isOpen) { + // eslint-disable-next-line react-hooks/set-state-in-effect -- Reset warning state when modal closes to prevent stale state from leaking into next session + setPendingImage(null); + setShowUnstableWarning(false); + } + }, [isOpen]); + + /** + * Handle image click - show warning for unstable images before selecting + */ + function handleImageClick(image: ImageInfo) { + // Check if warning is needed + const isNightly = image.armbian_version.includes('trunk'); + const isCommunityBoard = board?.has_community_support === true; + + // No warning for custom images or stable images on supported boards + if (!isNightly && !isCommunityBoard) { + onSelect(image); + return; + } + + // Show warning for nightly builds or community-supported boards + setPendingImage(image); + setShowUnstableWarning(true); + } + + /** + * Confirm unstable image selection - proceed with pending image + */ + function handleUnstableWarningConfirm() { + if (pendingImage) { + onSelect(pendingImage); + setPendingImage(null); + } + setShowUnstableWarning(false); + } + + /** + * Cancel unstable image selection - return to image list + */ + function handleUnstableWarningCancel() { + setPendingImage(null); + setShowUnstableWarning(false); + } + // Calculate available filters based on all images const availableFilters = useMemo(() => { if (!allImages) return { recommended: false, stable: false, nightly: false, apps: false, barebone: false }; @@ -181,7 +231,7 @@ export function ImageModal({ isOpen, onClose, onSelect, board }: ImageModalProps