diff --git a/NucleicRemote/NucleicRemote/Views/SessionDetailView.swift b/NucleicRemote/NucleicRemote/Views/SessionDetailView.swift index 0684919..1fd2c07 100644 --- a/NucleicRemote/NucleicRemote/Views/SessionDetailView.swift +++ b/NucleicRemote/NucleicRemote/Views/SessionDetailView.swift @@ -210,6 +210,56 @@ struct SessionDetailView: View { .padding() } } + + /// A queued follow-up shown above the composer: its text (or attachment names) with the + /// attachments as chips, and — at control scope — a ✕ that cancels just this message. + @ViewBuilder + private func queuedMessageRow(_ message: QueuedMessage) -> some View { + VStack(alignment: .leading, spacing: 4) { + HStack(spacing: 6) { + Image(systemName: "clock").foregroundStyle(.secondary) + Text(queuedRowText(message)).lineLimit(1).truncationMode(.tail) + .foregroundStyle(.secondary) + Spacer(minLength: 8) + if store.canControl { + Button { + // Refill the composer for editing (text only — the phone can't stage the + // host's files) unless the user has already started typing; then drop it. + if draft.trimmingCharacters(in: .whitespaces).isEmpty { draft = message.text } + store.cancelQueuedMessage(sessionID, message.id) + } label: { + Image(systemName: "xmark.circle.fill").foregroundStyle(.secondary) + } + .buttonStyle(.plain) + .disabled(!store.connectivity.isLive) + } + } + .font(.footnote) + if !message.attachments.isEmpty { + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 6) { + ForEach(message.attachments) { attachment in + Label(attachment.filename, systemImage: "doc") + .font(.caption2) + .lineLimit(1) + .padding(.horizontal, 7).padding(.vertical, 3) + .background(.quaternary, in: .capsule) + } + } + } + } + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 8).padding(.vertical, 6) + .background(.quaternary.opacity(0.4), in: .rect(cornerRadius: 10)) + } + + /// The one-line label for a queued pill: the message text, or — for an attachment-only + /// message — the attachment names (the chips below repeat them), so it's never blank. + private func queuedRowText(_ message: QueuedMessage) -> String { + if !message.text.isEmpty { return message.text } + return message.attachments.map(\.filename).joined(separator: ", ") + } } struct TranscriptList: View {