Initial scaffold — NASBackup iOS app

Full project scaffold: XcodeGen project.yml, Core models/protocols/errors,
SMBService (kishikawakatsumi/SMBClient), SFTPService (Citadel 0.9.2),
PhotoLibraryService, LANMonitor, BackupEngine, BackgroundTaskManager,
all feature UIs (Login, Connect, Browse, Backup, History, Settings),
Shared components and theme. Builds clean with zero errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Robin Kutesa
2026-05-15 17:05:04 +03:00
commit b96711c535
44 changed files with 3412 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
import SwiftUI
struct FolderRow: View {
let item: NASItem
let isSelected: Bool
let onTap: () -> Void
var body: some View {
Button(action: onTap) {
HStack(spacing: 12) {
Image(systemName: item.isDirectory ? "folder.fill" : "doc.fill")
.font(.system(size: 18))
.foregroundColor(isSelected ? .white : (item.isDirectory ? AppTheme.blue : AppTheme.textSecondary))
Text(item.name)
.font(AppTheme.bodyFont)
.fontWeight(isSelected ? .semibold : .regular)
.foregroundColor(isSelected ? .white : AppTheme.textPrimary)
Spacer()
if isSelected {
Image(systemName: "checkmark")
.font(.system(size: 13, weight: .bold))
.foregroundColor(.white)
} else if item.isDirectory {
Image(systemName: "chevron.right")
.font(.system(size: 13, weight: .medium))
.foregroundColor(AppTheme.textTertiary)
}
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
.background(isSelected ? AppTheme.blue : Color.clear)
}
.buttonStyle(.plain)
}
}

View File

@@ -0,0 +1,26 @@
import SwiftUI
struct ProgressRing: View {
let progress: Double
var lineWidth: CGFloat = 14
var size: CGFloat = 200
var color: Color = AppTheme.blue
var backgroundColor: Color = Color(hex: "#E5E7EB")
var body: some View {
ZStack {
Circle()
.stroke(backgroundColor, lineWidth: lineWidth)
Circle()
.trim(from: 0, to: CGFloat(min(progress, 1.0)))
.stroke(
color,
style: StrokeStyle(lineWidth: lineWidth, lineCap: .round)
)
.rotationEffect(.degrees(-90))
.animation(.easeInOut(duration: 0.4), value: progress)
}
.frame(width: size, height: size)
}
}

View File

@@ -0,0 +1,35 @@
import SwiftUI
struct ToggleRow: View {
let icon: String
let title: String
var subtitle: String? = nil
@Binding var isOn: Bool
var body: some View {
HStack(spacing: 12) {
Image(systemName: icon)
.font(.system(size: 16, weight: .medium))
.foregroundColor(AppTheme.blue)
.frame(width: 24)
VStack(alignment: .leading, spacing: 2) {
Text(title)
.font(AppTheme.bodyFont)
.foregroundColor(AppTheme.textPrimary)
if let subtitle {
Text(subtitle)
.font(AppTheme.captionFont)
.foregroundColor(AppTheme.textSecondary)
}
}
Spacer()
Toggle("", isOn: $isOn)
.labelsHidden()
.tint(AppTheme.blue)
}
.padding(.vertical, 4)
}
}