@@ -409,9 +409,8 @@ struct MeasurementChartView: View {
|
||
| 409 | 409 |
let condensedLayout = compactLayout || verticalSizeClass == .compact |
| 410 | 410 |
let sectionSpacing: CGFloat = condensedLayout ? 8 : (isLargeDisplay ? 12 : 10) |
| 411 | 411 |
|
| 412 |
- let controlsPanel = VStack(alignment: .leading, spacing: sectionSpacing) {
|
|
| 412 |
+ let controlsPanel = HStack(alignment: .center, spacing: sectionSpacing) {
|
|
| 413 | 413 |
seriesToggleRow(condensedLayout: condensedLayout) |
| 414 |
- smoothingControlsRow(condensedLayout: condensedLayout) |
|
| 415 | 414 |
} |
| 416 | 415 |
.padding(.horizontal, condensedLayout ? 10 : (isLargeDisplay ? 14 : 12)) |
| 417 | 416 |
.padding(.vertical, condensedLayout ? 8 : (isLargeDisplay ? 12 : 10)) |
@@ -581,65 +580,77 @@ struct MeasurementChartView: View {
|
||
| 581 | 580 |
} |
| 582 | 581 |
} |
| 583 | 582 |
|
| 583 |
+ smoothingControlChip( |
|
| 584 |
+ condensedLayout: condensedLayout, |
|
| 585 |
+ showsLabel: showsLabel |
|
| 586 |
+ ) |
|
| 587 |
+ |
|
| 584 | 588 |
} |
| 585 | 589 |
} |
| 586 | 590 |
|
| 587 |
- private func smoothingControlsRow(condensedLayout: Bool) -> some View {
|
|
| 588 |
- HStack(spacing: condensedLayout ? 8 : 10) {
|
|
| 589 |
- Text("Smoothing")
|
|
| 590 |
- .font((condensedLayout ? Font.caption : .footnote).weight(.semibold)) |
|
| 591 |
- .foregroundColor(.secondary) |
|
| 592 |
- |
|
| 593 |
- Menu {
|
|
| 594 |
- ForEach(SmoothingLevel.allCases, id: \.self) { level in
|
|
| 595 |
- Button {
|
|
| 596 |
- smoothingLevel = level |
|
| 597 |
- } label: {
|
|
| 598 |
- if smoothingLevel == level {
|
|
| 599 |
- Label(level.label, systemImage: "checkmark") |
|
| 600 |
- } else {
|
|
| 601 |
- Text(level.label) |
|
| 602 |
- } |
|
| 591 |
+ private func smoothingControlChip( |
|
| 592 |
+ condensedLayout: Bool, |
|
| 593 |
+ showsLabel: Bool |
|
| 594 |
+ ) -> some View {
|
|
| 595 |
+ Menu {
|
|
| 596 |
+ ForEach(SmoothingLevel.allCases, id: \.self) { level in
|
|
| 597 |
+ Button {
|
|
| 598 |
+ smoothingLevel = level |
|
| 599 |
+ } label: {
|
|
| 600 |
+ if smoothingLevel == level {
|
|
| 601 |
+ Label(level.label, systemImage: "checkmark") |
|
| 602 |
+ } else {
|
|
| 603 |
+ Text(level.label) |
|
| 603 | 604 |
} |
| 604 | 605 |
} |
| 605 |
- } label: {
|
|
| 606 |
- Label( |
|
| 607 |
- condensedLayout ? smoothingLevel.shortLabel : smoothingLevel.label, |
|
| 608 |
- systemImage: "waveform.path" |
|
| 609 |
- ) |
|
| 610 |
- .font(controlChipFont(condensedLayout: condensedLayout)) |
|
| 611 |
- .foregroundColor(smoothingLevel == .off ? .primary : .blue) |
|
| 612 |
- .padding(.horizontal, condensedLayout ? 10 : 12) |
|
| 613 |
- .padding(.vertical, condensedLayout ? 7 : (isLargeDisplay ? 9 : 8)) |
|
| 614 |
- .background( |
|
| 615 |
- Capsule(style: .continuous) |
|
| 616 |
- .fill( |
|
| 617 |
- smoothingLevel == .off |
|
| 618 |
- ? Color.secondary.opacity(0.10) |
|
| 619 |
- : Color.blue.opacity(0.12) |
|
| 620 |
- ) |
|
| 621 |
- ) |
|
| 622 |
- .overlay( |
|
| 623 |
- Capsule(style: .continuous) |
|
| 624 |
- .stroke( |
|
| 606 |
+ } |
|
| 607 |
+ } label: {
|
|
| 608 |
+ Group {
|
|
| 609 |
+ if showsLabel {
|
|
| 610 |
+ VStack(alignment: .leading, spacing: 2) {
|
|
| 611 |
+ Label("Smoothing", systemImage: "waveform.path")
|
|
| 612 |
+ .font(controlChipFont(condensedLayout: condensedLayout)) |
|
| 613 |
+ |
|
| 614 |
+ Text( |
|
| 625 | 615 |
smoothingLevel == .off |
| 626 |
- ? Color.secondary.opacity(0.18) |
|
| 627 |
- : Color.blue.opacity(0.28), |
|
| 628 |
- lineWidth: 1 |
|
| 616 |
+ ? "Off" |
|
| 617 |
+ : "MA \(smoothingLevel.movingAverageWindowSize)" |
|
| 629 | 618 |
) |
| 630 |
- ) |
|
| 631 |
- } |
|
| 632 |
- .fixedSize(horizontal: true, vertical: false) |
|
| 619 |
+ .font((condensedLayout ? Font.caption2 : .caption).weight(.semibold)) |
|
| 620 |
+ .foregroundColor(.secondary) |
|
| 621 |
+ .monospacedDigit() |
|
| 622 |
+ } |
|
| 623 |
+ .padding(.horizontal, usesCompactLandscapeOriginControls ? 8 : (condensedLayout ? 10 : 12)) |
|
| 624 |
+ .padding(.vertical, usesCompactLandscapeOriginControls ? 6 : (condensedLayout ? 7 : (isLargeDisplay ? 9 : 8))) |
|
| 625 |
+ } else {
|
|
| 626 |
+ VStack(spacing: 1) {
|
|
| 627 |
+ Image(systemName: "waveform.path") |
|
| 628 |
+ .font(.system(size: usesCompactLandscapeOriginControls ? 13 : (condensedLayout ? 15 : (isLargeDisplay ? 18 : 16)), weight: .semibold)) |
|
| 633 | 629 |
|
| 634 |
- if smoothingLevel != .off {
|
|
| 635 |
- Text("MA \(smoothingLevel.movingAverageWindowSize)")
|
|
| 636 |
- .font((condensedLayout ? Font.caption2 : .caption).weight(.semibold)) |
|
| 637 |
- .foregroundColor(.secondary) |
|
| 638 |
- .monospacedDigit() |
|
| 630 |
+ Text(smoothingLevel.shortLabel) |
|
| 631 |
+ .font(.system(size: usesCompactLandscapeOriginControls ? 8 : 9, weight: .bold)) |
|
| 632 |
+ .monospacedDigit() |
|
| 633 |
+ } |
|
| 634 |
+ .frame( |
|
| 635 |
+ width: usesCompactLandscapeOriginControls ? 36 : (condensedLayout ? 42 : (isLargeDisplay ? 50 : 44)), |
|
| 636 |
+ height: usesCompactLandscapeOriginControls ? 34 : (condensedLayout ? 38 : (isLargeDisplay ? 48 : 42)) |
|
| 637 |
+ ) |
|
| 638 |
+ } |
|
| 639 | 639 |
} |
| 640 |
- |
|
| 641 |
- Spacer(minLength: 0) |
|
| 640 |
+ .background( |
|
| 641 |
+ Capsule(style: .continuous) |
|
| 642 |
+ .fill(smoothingLevel == .off ? Color.secondary.opacity(0.10) : Color.blue.opacity(0.14)) |
|
| 643 |
+ ) |
|
| 644 |
+ .overlay( |
|
| 645 |
+ Capsule(style: .continuous) |
|
| 646 |
+ .stroke( |
|
| 647 |
+ smoothingLevel == .off ? Color.secondary.opacity(0.18) : Color.blue.opacity(0.24), |
|
| 648 |
+ lineWidth: 1 |
|
| 649 |
+ ) |
|
| 650 |
+ ) |
|
| 642 | 651 |
} |
| 652 |
+ .buttonStyle(.plain) |
|
| 653 |
+ .foregroundColor(smoothingLevel == .off ? .primary : .blue) |
|
| 643 | 654 |
} |
| 644 | 655 |
|
| 645 | 656 |
private func seriesToggleButton( |