Add residence sharing via .casera files
- Add SharedResidence model and package type detection for .casera files - Add generateSharePackage API endpoint integration - Create ResidenceSharingManager for iOS and Android - Add share button to residence detail screens (owner only) - Add residence import handling with confirmation dialogs - Update Quick Look extensions to show house icon for residence packages - Route .casera imports by type (contractor vs residence) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -32,7 +32,10 @@ struct ResidenceDetailView: View {
|
||||
@State private var showDeleteConfirmation = false
|
||||
@State private var isDeleting = false
|
||||
@State private var showingUpgradePrompt = false
|
||||
@State private var showShareSheet = false
|
||||
@State private var shareFileURL: URL?
|
||||
@StateObject private var subscriptionCache = SubscriptionCacheWrapper.shared
|
||||
@StateObject private var sharingManager = ResidenceSharingManager.shared
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@@ -146,6 +149,22 @@ struct ResidenceDetailView: View {
|
||||
.sheet(isPresented: $showingUpgradePrompt) {
|
||||
UpgradePromptView(triggerKey: "add_11th_task", isPresented: $showingUpgradePrompt)
|
||||
}
|
||||
.sheet(isPresented: $showShareSheet) {
|
||||
if let url = shareFileURL {
|
||||
ShareSheet(activityItems: [url])
|
||||
}
|
||||
}
|
||||
// Share error alert
|
||||
.alert("Share Failed", isPresented: .init(
|
||||
get: { sharingManager.errorMessage != nil },
|
||||
set: { if !$0 { sharingManager.resetState() } }
|
||||
)) {
|
||||
Button("OK") {
|
||||
sharingManager.resetState()
|
||||
}
|
||||
} message: {
|
||||
Text(sharingManager.errorMessage ?? "Failed to create share link.")
|
||||
}
|
||||
|
||||
// MARK: onChange & lifecycle
|
||||
.onChange(of: viewModel.reportMessage) { message in
|
||||
@@ -336,15 +355,21 @@ private extension ResidenceDetailView {
|
||||
}
|
||||
.disabled(viewModel.isGeneratingReport)
|
||||
}
|
||||
|
||||
|
||||
// Share Residence button (owner only)
|
||||
if let residence = viewModel.selectedResidence, isCurrentUserOwner(of: residence) {
|
||||
Button {
|
||||
showManageUsers = true
|
||||
shareResidence(residence)
|
||||
} label: {
|
||||
Image(systemName: "person.2")
|
||||
if sharingManager.isGeneratingPackage {
|
||||
ProgressView()
|
||||
} else {
|
||||
Image(systemName: "square.and.arrow.up")
|
||||
}
|
||||
}
|
||||
.disabled(sharingManager.isGeneratingPackage)
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
// Check LIVE task count before adding
|
||||
let totalTasks = tasksResponse?.columns.reduce(0) { $0 + $1.tasks.count } ?? 0
|
||||
@@ -357,7 +382,7 @@ private extension ResidenceDetailView {
|
||||
Image(systemName: "plus")
|
||||
}
|
||||
.accessibilityIdentifier(AccessibilityIdentifiers.Task.addButton)
|
||||
|
||||
|
||||
if let residence = viewModel.selectedResidence, isCurrentUserOwner(of: residence) {
|
||||
Button {
|
||||
showDeleteConfirmation = true
|
||||
@@ -369,6 +394,15 @@ private extension ResidenceDetailView {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func shareResidence(_ residence: ResidenceResponse) {
|
||||
Task {
|
||||
if let url = await sharingManager.createShareableFile(residence: residence) {
|
||||
shareFileURL = url
|
||||
showShareSheet = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Data Loading
|
||||
|
||||
Reference in New Issue
Block a user