summaryrefslogtreecommitdiff
path: root/DomainDig/WorkflowsView.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-23 23:12:34 -0500
committerChristian Cleberg <[email protected]>2026-04-23 23:12:34 -0500
commitb35f1b432fc24fbab1fa05593c9a0bca7e4d95a6 (patch)
tree099cea2cc4324331a719ed2cad8c0815033b5471 /DomainDig/WorkflowsView.swift
parentf045a5d339a796f40a9e958436ebc6f5314bdab8 (diff)
downloaddomain-dig-b35f1b432fc24fbab1fa05593c9a0bca7e4d95a6.tar.gz
domain-dig-b35f1b432fc24fbab1fa05593c9a0bca7e4d95a6.tar.bz2
domain-dig-b35f1b432fc24fbab1fa05593c9a0bca7e4d95a6.zip
feat(v3.6.0): add iCloud sharing for workflows and tracked domains
- implement CloudKit sharing (CKShare) for TrackedDomain and DomainWorkflow - support read-only and editable permissions - add Share actions and shared state indicators in UI - handle shared record ownership and participant roles - implement deterministic conflict resolution to prevent duplication - ensure compatibility with existing iCloud sync layer - maintain local-first behavior with graceful offline handling - remove debug logging for domain availability/rdap messages notes: - no custom backend or accounts introduced - sharing is Apple ecosystem only (iCloud-based) - large history data remains local-only
Diffstat (limited to 'DomainDig/WorkflowsView.swift')
-rw-r--r--DomainDig/WorkflowsView.swift31
1 files changed, 31 insertions, 0 deletions
diff --git a/DomainDig/WorkflowsView.swift b/DomainDig/WorkflowsView.swift
index 5025a0b..06ae96b 100644
--- a/DomainDig/WorkflowsView.swift
+++ b/DomainDig/WorkflowsView.swift
@@ -129,6 +129,11 @@ private struct WorkflowRowView: View {
var body: some View {
VStack(alignment: .leading, spacing: appDensity.metrics.rowSpacing + 1) {
HStack(alignment: .firstTextBaseline, spacing: 8) {
+ if workflow.collaboration?.isShared == true {
+ Image(systemName: "person.2.fill")
+ .font(.caption2)
+ .foregroundStyle(.cyan)
+ }
Text(workflow.name)
.font(appDensity.font(.callout, design: .default, weight: .semibold))
.foregroundStyle(.primary)
@@ -143,6 +148,12 @@ private struct WorkflowRowView: View {
.font(appDensity.font(.caption2))
.foregroundStyle(.secondary)
+ if let collaboration = workflow.collaboration, collaboration.isShared {
+ Text("\(collaboration.ownership.title) • \(collaboration.permission.title)")
+ .font(appDensity.font(.caption2))
+ .foregroundStyle(.secondary)
+ }
+
if let notes = workflow.notes, !notes.isEmpty {
Text(notes)
.font(appDensity.font(.caption))
@@ -163,6 +174,7 @@ struct WorkflowDetailView: View {
@State private var showingEditor = false
@State private var draftDomain = ""
@State private var includeAllExports = false
+ @State private var shareEntity: ShareableEntity?
private var workflow: DomainWorkflow? {
viewModel.workflow(withID: workflowID)
@@ -186,6 +198,11 @@ struct WorkflowDetailView: View {
.font(appDensity.font(.caption))
.foregroundStyle(.secondary)
}
+ if let collaboration = workflow.collaboration, collaboration.isShared {
+ Text("\(collaboration.ownership.title) • \(collaboration.permission.title)")
+ .font(appDensity.font(.caption))
+ .foregroundStyle(.secondary)
+ }
}
Section("Actions") {
@@ -207,6 +224,13 @@ struct WorkflowDetailView: View {
} label: {
Label("Edit Workflow", systemImage: "pencil")
}
+ .disabled(!viewModel.canEdit(workflow))
+
+ Button {
+ shareEntity = .workflow(workflow.id)
+ } label: {
+ Label(workflow.collaboration?.isShared == true ? "Manage Share" : "Share Workflow", systemImage: "person.2")
+ }
if latestSummary != nil {
Toggle("Export all domains", isOn: $includeAllExports)
@@ -263,6 +287,7 @@ struct WorkflowDetailView: View {
viewModel.addDomains([draftDomain], to: workflow)
draftDomain = ""
}
+ .disabled(!viewModel.canEdit(workflow))
}
}
@@ -288,9 +313,11 @@ struct WorkflowDetailView: View {
.buttonStyle(.plain)
}
.onDelete { offsets in
+ guard viewModel.canEdit(workflow) else { return }
viewModel.removeWorkflowDomains(at: offsets, from: workflow)
}
.onMove { offsets, destination in
+ guard viewModel.canEdit(workflow) else { return }
viewModel.moveWorkflowDomains(from: offsets, to: destination, in: workflow)
}
}
@@ -302,6 +329,7 @@ struct WorkflowDetailView: View {
.toolbar {
if !workflow.domains.isEmpty {
EditButton()
+ .disabled(!viewModel.canEdit(workflow))
}
}
.sheet(isPresented: $showingEditor) {
@@ -310,6 +338,9 @@ struct WorkflowDetailView: View {
.sheet(item: workflowSummaryBinding) { summary in
WorkflowRunSummaryView(viewModel: viewModel, summary: summary)
}
+ .sheet(item: $shareEntity) { entity in
+ CloudSharingSheet(entity: entity, title: workflow.name)
+ }
} else {
Text("Workflow not found")
.font(appDensity.font(.callout))