AppPhase.swift 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /// A phase of an app's lifecycle.
  2. ///
  3. /// # Backend Developer Notes
  4. ///
  5. /// Usually ``EnvironmentValues/appPhase`` returns ``AppPhase/active`` if
  6. /// and only if any of the app's windows are active, but on platforms such
  7. /// as macOS it can also return `active` if the app doesn't have any open
  8. /// windows but still appears in the menu bar.
  9. ///
  10. /// Generally speaking, if the app is in the ``AppPhase/inactive`` or
  11. /// ``AppPhase/background`` phases, all of its windows should be in the
  12. /// ``ScenePhase/inactive`` phase.
  13. public struct AppPhase: Hashable, Sendable {
  14. // TODO: Figure out how .background could work on desktops
  15. private enum Phase: Hashable, Sendable {
  16. case active
  17. case inactive
  18. case background
  19. }
  20. private var phase: Phase
  21. /// The app is currently active.
  22. ///
  23. /// This indicates that one of the app's windows has focus and can recieve
  24. /// input events.
  25. ///
  26. /// The `active` phase requires no special handling, as it is the "default"
  27. /// phase where normal interaction occurs.
  28. public static let active = Self(phase: .active)
  29. /// The app is currently inactive, but is still in the foreground.
  30. ///
  31. /// On desktop backends, this indicates that another app currently has
  32. /// focus -- i.e. none of this app's windows are active, and (in the case of
  33. /// macOS) it does not own the menu bar. Usually the app's windows are still
  34. /// visible on the screen with dimmed title bars.
  35. ///
  36. /// An app can be `inactive` on mobile backends if it is being obscured by
  37. /// system UI (such as the iOS Control Center or Android notification shade)
  38. /// but is still considered "in the foreground" by the system. The exact
  39. /// details can vary between backends; we recommend against special
  40. /// treatment of the `inactive` phase on mobile for this reason.
  41. public static let inactive = Self(phase: .inactive)
  42. /// The app is in the background.
  43. ///
  44. /// On mobile backends, apps reach the `background` phase when the user or
  45. /// system moves another app or the home screen into the foreground (such as
  46. /// by swiping on the gesture bar / Home indicator).
  47. ///
  48. /// - Important: Be aware that, on mobile backends, the system may choose to
  49. /// cleanly terminate the app at any time when it is in the `background`
  50. /// phase due to memory pressure or other reasons.
  51. ///
  52. /// This phase is currently never reached on desktop backends.
  53. public static let background = Self(phase: .background)
  54. }
  55. extension AppPhase: CustomStringConvertible {
  56. public var description: String {
  57. String(describing: phase)
  58. }
  59. }