Read App Intents Documentation
Nucleic-Session: 56C5F781-4444-466B-91CE-A7734A8E117F Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -131,15 +131,42 @@ private struct LockScreenView: View {
|
|||||||
private struct SessionRow: View {
|
private struct SessionRow: View {
|
||||||
let line: NucleicSessionAttributes.SessionLine
|
let line: NucleicSessionAttributes.SessionLine
|
||||||
|
|
||||||
|
/// An approval this row can resolve inline: it's blocked on an approval, carries that approval's
|
||||||
|
/// id, and isn't high-risk (§3.3 — high-risk keeps the plain tap-to-open row and is answered on
|
||||||
|
/// the app's guarded card). `nil` until the producer populates `approvalID` — an older host, or
|
||||||
|
/// today's summary that doesn't yet carry it, so the row stays a deep-link exactly as before.
|
||||||
|
private var inlineApprovalID: String? {
|
||||||
|
guard line.kind == .approval, (line.approvalIsHighRisk ?? false) == false else { return nil }
|
||||||
|
return line.approvalID
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let url = NucleicDeepLink.session(line.id) {
|
if let approvalID = inlineApprovalID {
|
||||||
|
actionableRow(approvalID: approvalID)
|
||||||
|
} else if let url = NucleicDeepLink.session(line.id) {
|
||||||
Link(destination: url) { rowContent }
|
Link(destination: url) { rowContent }
|
||||||
} else {
|
} else {
|
||||||
rowContent
|
rowContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var rowContent: some View {
|
/// An approval row with inline Allow/Deny. The identity still deep-links to the session; the
|
||||||
|
/// buttons fire `ApproveFromActivityIntent`, which the system performs in the app's background
|
||||||
|
/// process — allow/deny without unlocking (§4.1).
|
||||||
|
private func actionableRow(approvalID: String) -> some View {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
if let url = NucleicDeepLink.session(line.id) {
|
||||||
|
Link(destination: url) { rowIdentity }
|
||||||
|
} else {
|
||||||
|
rowIdentity
|
||||||
|
}
|
||||||
|
Spacer(minLength: 6)
|
||||||
|
ApprovalButtons(sessionID: line.id, approvalID: approvalID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The glyph + title + "project · Backend" — the row's identity, minus the trailing status.
|
||||||
|
private var rowIdentity: some View {
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
Image(systemName: ActivityPalette.glyph(line.kind))
|
Image(systemName: ActivityPalette.glyph(line.kind))
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
@@ -159,6 +186,12 @@ private struct SessionRow: View {
|
|||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var rowContent: some View {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
rowIdentity
|
||||||
Spacer(minLength: 6)
|
Spacer(minLength: 6)
|
||||||
Text(line.detail)
|
Text(line.detail)
|
||||||
.font(.caption2.weight(.medium))
|
.font(.caption2.weight(.medium))
|
||||||
@@ -169,6 +202,33 @@ private struct SessionRow: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The compact inline Allow/Deny pair for an actionable approval row. Each button fires
|
||||||
|
/// `ApproveFromActivityIntent` (a low/medium-risk decision — high-risk never reaches here).
|
||||||
|
private struct ApprovalButtons: View {
|
||||||
|
let sessionID: String
|
||||||
|
let approvalID: String
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack(spacing: 6) {
|
||||||
|
Button(intent: intent(allow: false)) {
|
||||||
|
Image(systemName: "xmark").font(.caption2.bold())
|
||||||
|
}
|
||||||
|
.tint(ActivityPalette.danger)
|
||||||
|
Button(intent: intent(allow: true)) {
|
||||||
|
Image(systemName: "checkmark").font(.caption2.bold())
|
||||||
|
}
|
||||||
|
.tint(ActivityPalette.success)
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderedProminent)
|
||||||
|
.controlSize(.small)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func intent(allow: Bool) -> ApproveFromActivityIntent {
|
||||||
|
ApproveFromActivityIntent(
|
||||||
|
approvalID: approvalID, sessionID: sessionID, isHighRisk: false, allow: allow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Headline count chips: running (blue), waiting (teal), approvals (amber). Only nonzero show.
|
/// Headline count chips: running (blue), waiting (teal), approvals (amber). Only nonzero show.
|
||||||
private struct CountChips: View {
|
private struct CountChips: View {
|
||||||
let state: NucleicSessionAttributes.ContentState
|
let state: NucleicSessionAttributes.ContentState
|
||||||
|
|||||||
Reference in New Issue
Block a user