feat: Kisani UI overhaul — brand identity, gallery, visual polish

- Rename app to Kisani (CFBundleDisplayName, xcodeproj → Kisani.xcodeproj)
- BackupView: kisani. wordmark + SwiftUI-drawn server logo mark (no asset,
  adaptive ink/bg), 206pt progress ring with active-state glow, 4-page
  swipeable ring (progress/pending/failed/uploaded), 4-metric stats strip,
  friendly NAS card (Home Server label), hamburger → AppMenuView sheet
- GalleryView: new NAS + local photo grid with source picker chip, 3-col
  lazy grid, ThumbnailCache, sync-status dots (green = backed up)
- MainTabView: Browse tab → Gallery tab; tab bar uses ultraThinMaterial
  blur background (systemGray3 icons, 9.5pt labels)
- All app icon sizes regenerated from 1024pt source via sips
- LANMonitor: nasReachable Bool?, checkNASReachability(host:port:) TCP ping
- project.yml: photo library usage description updated to Kisani branding

Co-Authored-By: Kutesir <kutesir@provoc.ug>
Co-Authored-By: Sentry <sentry@provoc.ug>
This commit is contained in:
Robin Kutesa
2026-05-17 11:17:13 +03:00
parent 6cad8d9d6c
commit 59bdad803f
32 changed files with 983 additions and 227 deletions

View File

@@ -174,11 +174,13 @@ struct SyncView: View {
Spacer()
HStack(spacing: 5) {
Circle()
.fill(lanMonitor.nasReachable == true ? AppTheme.positive : AppTheme.inkQuaternary)
.fill(reachableColor)
.frame(width: 6, height: 6)
Text(lanMonitor.nasReachable == true ? "Available" : "Offline")
.animation(.spring(response: 0.3, dampingFraction: 0.8), value: lanMonitor.nasReachable)
Text(reachableLabel)
.font(AppTheme.micro())
.foregroundStyle(lanMonitor.nasReachable == true ? AppTheme.positive : AppTheme.inkTertiary)
.foregroundStyle(reachableColor)
.animation(.spring(response: 0.3, dampingFraction: 0.8), value: lanMonitor.nasReachable)
}
}
}
@@ -274,6 +276,22 @@ struct SyncView: View {
}
}
private var reachableColor: Color {
switch lanMonitor.nasReachable {
case true: return AppTheme.positive
case false: return AppTheme.destructive.opacity(0.7)
case nil: return AppTheme.inkQuaternary
}
}
private var reachableLabel: String {
switch lanMonitor.nasReachable {
case true: return "Online"
case false: return "Offline"
case nil: return "Checking…"
}
}
// MARK: Toolbar chip
private var nasStatusChip: some View {
@@ -281,14 +299,11 @@ struct SyncView: View {
Circle()
.fill(lanMonitor.nasReachable == true ? AppTheme.positive : AppTheme.inkQuaternary)
.frame(width: 5, height: 5)
Text(connection?.displayName ?? "NAS")
.animation(.spring(response: 0.3, dampingFraction: 0.8), value: lanMonitor.nasReachable)
Text(connection?.host ?? "NAS")
.font(.system(size: 12, weight: .medium))
.foregroundStyle(AppTheme.inkSecondary)
}
.padding(.horizontal, 10)
.padding(.vertical, 5)
.background(AppTheme.surfaceSunken)
.clipShape(Capsule(style: .continuous))
}
// MARK: Data