Updates WOrking

This commit is contained in:
Hariharan Mudaliar 2025-08-13 23:37:44 +05:30
commit ab13b91d20
3 changed files with 72 additions and 18 deletions

View file

@ -125,7 +125,15 @@ struct ContentView: View {
// Only close if mouse leaves and the notch is open and no popovers are active // Only close if mouse leaves and the notch is open and no popovers are active
if !hovering && vm.notchState == .open && !vm.isBatteryPopoverActive { if !hovering && vm.notchState == .open && !vm.isBatteryPopoverActive {
vm.close() // Add slight delay for stats tab to prevent accidental closure during layout changes
let delay: Double = (coordinator.currentView == .stats) ? 0.2 : 0.0
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
// Double-check conditions after delay
if !isHovering && vm.notchState == .open && !vm.isBatteryPopoverActive {
vm.close()
}
}
} }
} }
.onTapGesture { .onTapGesture {

View file

@ -118,25 +118,71 @@ struct NotchStatsView: View {
return graphs return graphs
} }
// Simplified and more consistent layout system // Smart grid layout system for different graph counts
@ViewBuilder @ViewBuilder
var statsGridLayout: some View { var statsGridLayout: some View {
let graphCount = availableGraphs.count let graphCount = availableGraphs.count
// Use LazyVGrid for all cases - more predictable layout behavior if graphCount <= 3 {
LazyVGrid( // 1-3 graphs: Single row with equal spacing
columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: min(graphCount, 3)), LazyVGrid(
spacing: 12 columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: graphCount),
) { spacing: 12
ForEach(0..<graphCount, id: \.self) { index in ) {
UnifiedStatsCard(graphData: availableGraphs[index]) ForEach(0..<graphCount, id: \.self) { index in
.transition(.asymmetric( UnifiedStatsCard(graphData: availableGraphs[index])
insertion: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4)), .transition(.asymmetric(
removal: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4)) insertion: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4)),
)) removal: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4))
))
}
}
} else if graphCount == 4 {
// 4 graphs: 2x2 grid
LazyVGrid(
columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 2),
spacing: 12
) {
ForEach(0..<graphCount, id: \.self) { index in
UnifiedStatsCard(graphData: availableGraphs[index])
.transition(.asymmetric(
insertion: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4)),
removal: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4))
))
}
}
} else {
// 5 graphs: First row 3 graphs, second row 2 graphs (half-width each)
VStack(spacing: 12) {
// First row: 3 graphs
LazyVGrid(
columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 3),
spacing: 8
) {
ForEach(0..<3, id: \.self) { index in
UnifiedStatsCard(graphData: availableGraphs[index])
.transition(.asymmetric(
insertion: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4)),
removal: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4))
))
}
}
// Second row: 2 graphs (half-width each)
LazyVGrid(
columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 2),
spacing: 8
) {
ForEach(3..<graphCount, id: \.self) { index in
UnifiedStatsCard(graphData: availableGraphs[index])
.transition(.asymmetric(
insertion: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4)),
removal: .scale.combined(with: .opacity).animation(.easeInOut(duration: 0.4))
))
}
}
} }
} }
.animation(.easeInOut(duration: 0.4), value: graphCount)
} }
// Helper function to create graph views using unified component // Helper function to create graph views using unified component

View file

@ -120,8 +120,8 @@ class StatsManager: ObservableObject {
var downloadSpeed: Double = 0.0 var downloadSpeed: Double = 0.0
var uploadSpeed: Double = 0.0 var uploadSpeed: Double = 0.0
// Only calculate speeds if we have a reasonable time interval and previous data // Only calculate speeds if we have a reasonable time interval and this isn't the first run
if timeInterval > 0.1 && previousNetworkStats.bytesIn > 0 && previousNetworkStats.bytesOut > 0 { if timeInterval > 0.1 && (previousNetworkStats.bytesIn > 0 || previousNetworkStats.bytesOut > 0) {
let bytesDownloaded = currentNetworkStats.bytesIn > previousNetworkStats.bytesIn ? let bytesDownloaded = currentNetworkStats.bytesIn > previousNetworkStats.bytesIn ?
currentNetworkStats.bytesIn - previousNetworkStats.bytesIn : 0 currentNetworkStats.bytesIn - previousNetworkStats.bytesIn : 0
let bytesUploaded = currentNetworkStats.bytesOut > previousNetworkStats.bytesOut ? let bytesUploaded = currentNetworkStats.bytesOut > previousNetworkStats.bytesOut ?
@ -136,8 +136,8 @@ class StatsManager: ObservableObject {
var readSpeed: Double = 0.0 var readSpeed: Double = 0.0
var writeSpeed: Double = 0.0 var writeSpeed: Double = 0.0
// Only calculate speeds if we have a reasonable time interval and previous data // Only calculate speeds if we have a reasonable time interval and this isn't the first run
if timeInterval > 0.1 && previousDiskStats.bytesRead > 0 && previousDiskStats.bytesWritten > 0 { if timeInterval > 0.1 && (previousDiskStats.bytesRead > 0 || previousDiskStats.bytesWritten > 0) {
let bytesRead = currentDiskStats.bytesRead > previousDiskStats.bytesRead ? let bytesRead = currentDiskStats.bytesRead > previousDiskStats.bytesRead ?
currentDiskStats.bytesRead - previousDiskStats.bytesRead : 0 currentDiskStats.bytesRead - previousDiskStats.bytesRead : 0
let bytesWritten = currentDiskStats.bytesWritten > previousDiskStats.bytesWritten ? let bytesWritten = currentDiskStats.bytesWritten > previousDiskStats.bytesWritten ?