Internal tooling for Mac utility for storage management.
Swift
98.7%
JSON
1.1%
Markdown
0.2%
//
// DisksView.swift
// MUA
//
// Created by Mitchel Volkering on 21/12/2025.
//
import SwiftUI
/// Shows all connected disks with detailed info
struct DisksView: View {
@State private var disks: [DiskInfo] = []
@State private var selectedDisk: DiskInfo?
var body: some View {
ScrollView {
LazyVStack(spacing: 16) {
ForEach(disks) { disk in
DiskCardView(
disk: disk,
isSelected: selectedDisk?.id == disk.id
)
.onTapGesture {
withAnimation(.spring(response: 0.3)) {
selectedDisk = disk
}
}
}
}
.padding()
}
.background(Color(nsColor: .windowBackgroundColor))
.onAppear {
refreshDisks()
}
.toolbar {
ToolbarItem {
Button {
refreshDisks()
} label: {
Label("Refresh", systemImage: "arrow.clockwise")
}
}
}
}
private func refreshDisks() {
disks = DiskInfo.getAllDisks()
}
}
struct DiskCardView: View {
let disk: DiskInfo
let isSelected: Bool
@State private var isHovered = false
var body: some View {
HStack(spacing: 20) {
// Disk icon with glass effect
ZStack {
RoundedRectangle(cornerRadius: 16)
.fill(
.linearGradient(
colors: [
iconColor.opacity(0.6),
iconColor.opacity(0.3)
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
.frame(width: 72, height: 72)
.overlay(
RoundedRectangle(cornerRadius: 16)
.fill(
.linearGradient(
colors: [.white.opacity(0.3), .clear],
startPoint: .topLeading,
endPoint: .center
)
)
)
.overlay(
RoundedRectangle(cornerRadius: 16)
.strokeBorder(.white.opacity(0.3), lineWidth: 1)
)
.shadow(color: iconColor.opacity(0.3), radius: isHovered ? 12 : 6)
Image(systemName: disk.icon)
.font(.system(size: 32))
.foregroundStyle(.white)
}
VStack(alignment: .leading, spacing: 8) {
HStack {
Text(disk.name)
.font(.title3)
.fontWeight(.semibold)
if disk.isRemovable {
Text("Removable")
.font(.caption2)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(.quaternary, in: Capsule())
}
}
Text(disk.mountPoint.path)
.font(.caption)
.foregroundStyle(.tertiary)
// Usage bar
GeometryReader { geo in
ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: 4)
.fill(.quaternary)
RoundedRectangle(cornerRadius: 4)
.fill(usageGradient)
.frame(width: geo.size.width * CGFloat(disk.usedPercentage / 100))
}
}
.frame(height: 10)
HStack {
Text("\(disk.formattedUsedSpace) used")
.foregroundStyle(.secondary)
Text("•")
.foregroundStyle(.quaternary)
Text("\(disk.formattedFreeSpace) free")
.foregroundStyle(.secondary)
Spacer()
Text(disk.formattedTotalSpace)
.foregroundStyle(.tertiary)
}
.font(.caption)
}
Spacer()
// Usage percentage
VStack {
Text("\(Int(disk.usedPercentage))%")
.font(.system(size: 24, weight: .semibold, design: .rounded))
.foregroundStyle(usageColor)
Text("used")
.font(.caption2)
.foregroundStyle(.tertiary)
}
}
.padding()
.background(
RoundedRectangle(cornerRadius: 16)
.fill(.regularMaterial)
.overlay(
RoundedRectangle(cornerRadius: 16)
.strokeBorder(
isSelected ? Color.accentColor.opacity(0.5) : Color.clear,
lineWidth: 2
)
)
)
.shadow(color: .black.opacity(0.05), radius: 8, y: 4)
.scaleEffect(isHovered ? 1.01 : 1.0)
.animation(.spring(response: 0.3), value: isHovered)
.onHover { hovering in
isHovered = hovering
}
}
private var iconColor: Color {
if disk.isRemovable { return .orange }
if disk.isInternal { return .blue }
return .purple
}
private var usageColor: Color {
let percentage = disk.usedPercentage
if percentage > 90 { return .red }
if percentage > 75 { return .orange }
return .green
}
private var usageGradient: LinearGradient {
let color = usageColor
return .linearGradient(
colors: [color.opacity(0.8), color],
startPoint: .leading,
endPoint: .trailing
)
}
}
#Preview {
DisksView()
.frame(width: 700, height: 500)
}
About
Internal tooling for Mac utility for storage management.
0 stars
0 forks