ApplyTempPresetIntent.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import AppIntents
  2. import Foundation
  3. /// An App Intent that allows users to apply a temporary target preset through the Shortcuts app.
  4. struct ApplyTempPresetIntent: AppIntent {
  5. /// The title displayed for this action in the Shortcuts app.
  6. static var title: LocalizedStringResource = "Apply a Temporary Target"
  7. /// The description displayed for this action in the Shortcuts app.
  8. static var description = IntentDescription("Enable a Temporary Target")
  9. /// The temporary target preset to be applied.
  10. @Parameter(
  11. title: "Preset",
  12. description: "the preset to apply",
  13. requestValueDialog: IntentDialog(stringLiteral: String(localized: "Which preset to apply?"))
  14. ) var preset: TempPreset?
  15. /// A boolean parameter that determines whether confirmation is required before applying the temporary target.
  16. @Parameter(
  17. title: "Confirm Before applying",
  18. description: "If toggled, you will need to confirm before applying",
  19. default: true
  20. ) var confirmBeforeApplying: Bool
  21. /// Defines the summary format shown in the Shortcuts app when configuring this intent.
  22. static var parameterSummary: some ParameterSummary {
  23. When(\ApplyTempPresetIntent.$confirmBeforeApplying, .equalTo, true, {
  24. Summary("Applying \(\.$preset)") {
  25. \.$confirmBeforeApplying
  26. }
  27. }, otherwise: {
  28. Summary("Immediately applying \(\.$preset)") {
  29. \.$confirmBeforeApplying
  30. }
  31. })
  32. }
  33. /// Converts a decimal duration value into a formatted time string.
  34. ///
  35. /// - Parameter decimal: The duration value in decimal format.
  36. /// - Returns: A string representing the formatted time in hours and minutes.
  37. private func decimalToTimeFormattedString(decimal: Decimal) -> String {
  38. let timeInterval = TimeInterval(decimal * 60) // Convert minutes to seconds
  39. let formatter = DateComponentsFormatter()
  40. formatter.allowedUnits = [.hour, .minute]
  41. formatter.unitsStyle = .brief // Example: "1h 10m"
  42. return formatter.string(from: timeInterval) ?? ""
  43. }
  44. /// Executes the intent to apply the selected temporary target preset.
  45. ///
  46. /// - Returns: A dialog indicating whether the temporary target was successfully applied or failed.
  47. /// - Throws: An error if an issue occurs during execution.
  48. @MainActor func perform() async throws -> some ProvidesDialog {
  49. do {
  50. let intentRequest = TempPresetsIntentRequest()
  51. let presetToApply: TempPreset
  52. // Determine which preset to apply
  53. if let preset = preset {
  54. presetToApply = preset
  55. } else {
  56. // Request user selection if no preset is provided
  57. presetToApply = try await $preset.requestDisambiguation(
  58. among: intentRequest.fetchAndProcessTempTargets(),
  59. dialog: "Select Temporary Target"
  60. )
  61. }
  62. let displayName: String = presetToApply.name
  63. // Request confirmation before applying if required
  64. if confirmBeforeApplying {
  65. try await requestConfirmation(
  66. result: .result(
  67. dialog: IntentDialog(
  68. stringLiteral: String(localized: "Confirm to apply Temporary Target '\(displayName)'")
  69. )
  70. )
  71. )
  72. }
  73. // Apply the temporary target and return the appropriate dialog message
  74. if await intentRequest.enactTempTarget(presetToApply) {
  75. return .result(
  76. dialog: IntentDialog(
  77. stringLiteral: String(
  78. localized:
  79. "Temporary Target '\(presetToApply.name)' applied"
  80. )
  81. )
  82. )
  83. } else {
  84. return .result(
  85. dialog: IntentDialog(
  86. stringLiteral: String(
  87. localized:
  88. "Temporary Target '\(presetToApply.name)' failed"
  89. )
  90. )
  91. )
  92. }
  93. } catch {
  94. throw error
  95. }
  96. }
  97. }