aboutsummaryrefslogtreecommitdiff
path: root/Sources/NorgUI/Views/NorgTaskView.swift
blob: cfe48c098b16cac5c1ba5090a9961ace1c7ebd8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import NorgKit
import SwiftUI

public struct NorgTaskView: View {
  @Environment(\.norgTheme) private var theme

  let status: TaskStatus
  let text: AttributedString
  var font: Font
  let onToggle: () -> Void
  let onSetStatus: (TaskStatus) -> Void

  public init(
    status: TaskStatus,
    text: AttributedString,
    font: Font = .body,
    onToggle: @escaping () -> Void,
    onSetStatus: @escaping (TaskStatus) -> Void
  ) {
    self.status = status
    self.text = text
    self.font = font
    self.onToggle = onToggle
    self.onSetStatus = onSetStatus
  }

  public var body: some View {
    HStack(alignment: .firstTextBaseline, spacing: 8) {
      statusButton
      Text(text)
        .font(font)
        .strikethrough(isResolved, color: .secondary)
        .foregroundStyle(isResolved ? .secondary : .primary)
    }
  }

  private var statusButton: some View {
    Button(action: onToggle) {
      Image(systemName: theme.statusSymbol(status))
        .font(font)
        .foregroundStyle(theme.statusTint(status))
    }
    .buttonStyle(.plain)
    .contextMenu {
      ForEach(TaskStatus.allCases) { option in
        Button {
          onSetStatus(option)
        } label: {
          Label {
            Text(theme.statusLabel(option))
          } icon: {
            Image(systemName: theme.statusSymbol(option))
          }
        }
      }
    }
    .accessibilityLabel(Text("Task status: \(Text(theme.statusLabel(status)))", bundle: .module))
  }

  private var isResolved: Bool {
    status == .done || status == .cancelled
  }
}