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:
34
App/AppDelegate.swift
Normal file
34
App/AppDelegate.swift
Normal file
@@ -0,0 +1,34 @@
|
||||
import UIKit
|
||||
import BackgroundTasks
|
||||
import UserNotifications
|
||||
|
||||
final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
BackgroundTaskManager.registerTasks()
|
||||
requestNotificationPermission()
|
||||
setupLANMonitor()
|
||||
return true
|
||||
}
|
||||
|
||||
private func requestNotificationPermission() {
|
||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { _, _ in }
|
||||
}
|
||||
|
||||
private func setupLANMonitor() {
|
||||
let monitor = LANMonitor.shared
|
||||
monitor.onTrustedNetworkJoined = { ssid in
|
||||
let store = ConnectionStore.shared
|
||||
guard store.lanTriggerEnabled, !store.isInQuietHours else { return }
|
||||
let delay = TimeInterval(store.startDelaySeconds)
|
||||
BackgroundTaskManager.scheduleBackup(delay: delay)
|
||||
}
|
||||
monitor.start()
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
BackgroundTaskManager.scheduleAppRefresh()
|
||||
}
|
||||
}
|
||||
72
App/Info.plist
Normal file
72
App/Info.plist
Normal file
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||
<array>
|
||||
<string>com.albert.nasbackup.backup</string>
|
||||
<string>com.albert.nasbackup.refresh</string>
|
||||
</array>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>NASBackup</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>Sign in quickly with Face ID.</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Used to detect your home Wi-Fi network name for automatic backup.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>NASBackup needs access to your photos to back them up to your NAS.</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<true/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>processing</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string></string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
31
App/NASBackupApp.swift
Normal file
31
App/NASBackupApp.swift
Normal file
@@ -0,0 +1,31 @@
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct NASBackupApp: App {
|
||||
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||
|
||||
@StateObject private var store = ConnectionStore.shared
|
||||
@StateObject private var engine = BackupEngine.shared
|
||||
@StateObject private var lanMonitor = LANMonitor.shared
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
RootView()
|
||||
.environmentObject(store)
|
||||
.environmentObject(engine)
|
||||
.environmentObject(lanMonitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RootView: View {
|
||||
@EnvironmentObject var store: ConnectionStore
|
||||
|
||||
var body: some View {
|
||||
if store.savedConnection != nil {
|
||||
LoginView()
|
||||
} else {
|
||||
ConnectView()
|
||||
}
|
||||
}
|
||||
}
|
||||
14
App/SceneDelegate.swift
Normal file
14
App/SceneDelegate.swift
Normal file
@@ -0,0 +1,14 @@
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
final class SceneDelegate: NSObject, UIWindowSceneDelegate {
|
||||
var window: UIWindow?
|
||||
|
||||
func scene(
|
||||
_ scene: UIScene,
|
||||
willConnectTo session: UISceneSession,
|
||||
options connectionOptions: UIScene.ConnectionOptions
|
||||
) {
|
||||
// SwiftUI lifecycle handles window setup via NASBackupApp.swift
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user