diff --git a/AppImage/components/storage-overview.tsx b/AppImage/components/storage-overview.tsx index f2117493..4b3e47e8 100644 --- a/AppImage/components/storage-overview.tsx +++ b/AppImage/components/storage-overview.tsx @@ -1335,8 +1335,134 @@ export function StorageOverview() { - {/* Wear & Lifetime Section */} - {getWearIndicator(selectedDisk) && ( + {/* Wear & Lifetime — SMART test data takes priority over basic DiskInfo */} + {(loadingSmartJson || smartJsonData?.has_data) ? ( +
+

+ Wear & Lifetime + {smartJsonData?.has_data && ( + + Real Test + + )} +

+ {loadingSmartJson ? ( +
+
+ Loading SMART test data... +
+ ) : smartJsonData?.has_data && smartJsonData.data ? ( +
+ {(() => { + const data = smartJsonData.data as Record + const ataAttrs = data?.ata_smart_attributes as { table?: Array<{ id: number; name: string; value: number; raw?: { value: number } }> } + const table = ataAttrs?.table || [] + + const wearAttr = table.find(a => + a.name?.toLowerCase().includes('wear_leveling') || + a.name?.toLowerCase().includes('media_wearout') || + a.name?.toLowerCase().includes('percent_lifetime') || + a.name?.toLowerCase().includes('ssd_life_left') || + a.id === 177 || a.id === 231 + ) + + const lbasAttr = table.find(a => + a.name?.toLowerCase().includes('total_lbas_written') || + a.name?.toLowerCase().includes('writes_gib') || + a.name?.toLowerCase().includes('lifetime_writes') || + a.id === 241 + ) + + const pohAttr = table.find(a => + a.name?.toLowerCase().includes('power_on_hours') || + a.id === 9 + ) + + const nvmeHealth = data?.nvme_smart_health_information_log as Record + + // Data written + let dataWrittenLabel = '' + if (lbasAttr && lbasAttr.raw?.value) { + const attrName = (lbasAttr.name || '').toLowerCase() + let tb = 0 + if (attrName.includes('gib') || attrName.includes('_gb') || attrName.includes('writes_gib')) { + tb = lbasAttr.raw.value / 1024 + } else { + tb = (lbasAttr.raw.value * 512) / (1024 ** 4) + } + dataWrittenLabel = tb >= 1 ? `${tb.toFixed(2)} TB` : `${(tb * 1024).toFixed(2)} GB` + } else if (nvmeHealth?.data_units_written) { + const tb = ((nvmeHealth.data_units_written as number) * 512000) / (1024 ** 4) + dataWrittenLabel = tb >= 1 ? `${tb.toFixed(2)} TB` : `${(tb * 1024).toFixed(2)} GB` + } + + // Life remaining % + let wearPercent: number | null = null + if (wearAttr) { + wearPercent = (wearAttr.id === 230) ? (100 - wearAttr.value) : wearAttr.value + } else if (nvmeHealth?.percentage_used !== undefined) { + wearPercent = 100 - (nvmeHealth.percentage_used as number) + } + + // Estimated life + let estimatedLife = '' + const powerOnHrs = pohAttr?.raw?.value || selectedDisk.power_on_hours || 0 + if (wearPercent !== null && wearPercent > 0 && wearPercent < 100 && powerOnHrs > 0) { + const usedPct = 100 - wearPercent + if (usedPct > 0) { + const remYears = ((powerOnHrs / (usedPct / 100)) - powerOnHrs) / (24 * 365) + estimatedLife = remYears >= 1 ? `~${remYears.toFixed(1)} years` : `~${(remYears * 12).toFixed(0)} months` + } + } + + const availableSpare = nvmeHealth?.available_spare as number | undefined + + if (wearPercent !== null || dataWrittenLabel) { + return ( + <> + {wearPercent !== null && ( +
+
+

Life Remaining

+

{wearPercent}%

+
+ div]:bg-red-500' : '[&>div]:bg-blue-500'}`} + /> +
+ )} +
+ {estimatedLife && ( +
+

Estimated Life Remaining

+

{estimatedLife}

+
+ )} + {dataWrittenLabel && ( +
+

Total Data Written

+

{dataWrittenLabel}

+
+ )} + {availableSpare !== undefined && ( +
+

Available Spare

+

{availableSpare}%

+
+ )} +
+ + ) + } + return null + })()} +
+ ) : ( +

Run a SMART test to get detailed wear data.

+ )} +
+ ) : getWearIndicator(selectedDisk) ? (

Wear & Lifetime

@@ -1372,7 +1498,7 @@ export function StorageOverview() { )}
- )} + ) : null}

SMART Attributes

@@ -1436,8 +1562,8 @@ export function StorageOverview() {
- {/* SMART Test Data Section (from real test JSON) - Uniform style with Wear & Lifetime */} - {(loadingSmartJson || smartJsonData?.has_data) && ( + {/* OLD SMART Test Data section removed — now unified in Wear & Lifetime above */} + {false && (

@@ -1595,21 +1721,6 @@ export function StorageOverview() { return null })()} - {/* Last Test Info */} -
-
-

Last Test Date

-

- {smartJsonData.timestamp - ? new Date(smartJsonData.timestamp).toLocaleString() - : 'Unknown'} -

-
-
-

Test Type

-

{smartJsonData.test_type || 'Unknown'}

-
-

) : (