|
|
@@ -19,6 +19,8 @@ struct HomeView: View {
|
|
|
@State private var dismissedWarnings: Set<String> = []
|
|
|
@State private var showRecordingSourcePicker = false
|
|
|
@State private var pendingRecordingSource: RecordingSourceChoice?
|
|
|
+ @State private var showAuthentication = false
|
|
|
+ @State private var pendingProtectedAction: ProtectedRecordingAction?
|
|
|
|
|
|
var onRecordingFinished: ((CelestiaSession) -> Void)? = nil
|
|
|
|
|
|
@@ -59,6 +61,20 @@ struct HomeView: View {
|
|
|
detector.checkEnvironment()
|
|
|
restoreActiveRecordingIfNeeded()
|
|
|
}
|
|
|
+ .onChange(of: authManager.currentUser?.id) { _, userID in
|
|
|
+ guard userID != nil, let action = pendingProtectedAction else { return }
|
|
|
+ pendingProtectedAction = nil
|
|
|
+
|
|
|
+ switch action {
|
|
|
+ case .startNew:
|
|
|
+ beginNewRecording()
|
|
|
+ case .restore(let sessionID, let recordingAction):
|
|
|
+ restoreActiveRecordingIfNeeded(
|
|
|
+ sessionID: sessionID,
|
|
|
+ action: recordingAction
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
.onOpenURL(perform: handleRecordingURL)
|
|
|
.fullScreenCover(item: $activeRecording, onDismiss: {
|
|
|
if let session = completedRecordingSession {
|
|
|
@@ -85,6 +101,15 @@ struct HomeView: View {
|
|
|
showRecordingSourcePicker = false
|
|
|
}
|
|
|
}
|
|
|
+ .sheet(isPresented: $showAuthentication, onDismiss: {
|
|
|
+ if !authManager.isLoggedIn {
|
|
|
+ pendingProtectedAction = nil
|
|
|
+ }
|
|
|
+ }) {
|
|
|
+ AuthModalView(
|
|
|
+ guidanceMessage: "登录或注册后,才能开始和继续现场记录"
|
|
|
+ )
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -156,6 +181,11 @@ struct HomeView: View {
|
|
|
// MARK: - Actions
|
|
|
|
|
|
private func beginNewRecording() {
|
|
|
+ guard authManager.isLoggedIn else {
|
|
|
+ requestAuthentication(for: .startNew)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
if connectedSparkDevices.isEmpty {
|
|
|
createSessionAndNavigate(source: .iPhone)
|
|
|
} else {
|
|
|
@@ -164,6 +194,11 @@ struct HomeView: View {
|
|
|
}
|
|
|
|
|
|
private func createSessionAndNavigate(source: RecordingSourceChoice) {
|
|
|
+ guard authManager.isLoggedIn else {
|
|
|
+ requestAuthentication(for: .startNew)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
let formatter = DateFormatter()
|
|
|
formatter.dateFormat = "yyyyMMdd_HHmm"
|
|
|
let title = "\(formatter.string(from: Date()))_现场记录"
|
|
|
@@ -186,7 +221,7 @@ struct HomeView: View {
|
|
|
sessionID requestedSessionID: UUID? = nil,
|
|
|
action: RecordingLiveActivityAction? = nil
|
|
|
) {
|
|
|
- guard activeRecording == nil else { return }
|
|
|
+ guard authManager.isLoggedIn, activeRecording == nil else { return }
|
|
|
|
|
|
let persistedID = RecordingRecoveryStore.activeSessionID
|
|
|
let activityID = RecordingLiveActivityManager.shared.recoverableSessionID
|
|
|
@@ -267,12 +302,23 @@ struct HomeView: View {
|
|
|
|
|
|
private func handleRecordingURL(_ url: URL) {
|
|
|
guard let route = RecordingLiveActivityRoute(url: url) else { return }
|
|
|
+ guard authManager.isLoggedIn else {
|
|
|
+ requestAuthentication(
|
|
|
+ for: .restore(sessionID: route.sessionID, action: route.action)
|
|
|
+ )
|
|
|
+ return
|
|
|
+ }
|
|
|
restoreActiveRecordingIfNeeded(
|
|
|
sessionID: route.sessionID,
|
|
|
action: route.action
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+ private func requestAuthentication(for action: ProtectedRecordingAction) {
|
|
|
+ pendingProtectedAction = action
|
|
|
+ showAuthentication = true
|
|
|
+ }
|
|
|
+
|
|
|
private var connectedSparkDevices: [BoundDevice] {
|
|
|
guard let userID = authManager.currentUser?.id else { return [] }
|
|
|
return bleManager.connectedDevices(forUserId: userID)
|
|
|
@@ -289,6 +335,11 @@ struct HomeView: View {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+private enum ProtectedRecordingAction {
|
|
|
+ case startNew
|
|
|
+ case restore(sessionID: UUID?, action: RecordingLiveActivityAction?)
|
|
|
+}
|
|
|
+
|
|
|
private struct ActiveRecordingPresentation: Identifiable {
|
|
|
let id = UUID()
|
|
|
let session: CelestiaSession
|