Version 1.1
Part 2/2
// V1.1 Matching support for visionOS, watchOS and tvOS
/// A value that defines the visibility priority of a toolbar item after iOS 27/iPadOS27 and visionOS 27.
/// The value is ignored on previous versions.
///
/// When a toolbar runs out of space, it moves items into an overflow
/// menu. Visibility priority controls the order in which that happens:
/// items with a lower priority move first, keeping higher-priority
/// items visible longer as the window shrinks.
///
/// Use values of this type with the
/// ``ToolbarContent/visibilityPriorityIfAvailable(_:)`` modifier. For example,
/// to keep a share button visible longer than an archive button:
///
/// struct RootView: View {
/// var body: some View {
/// ContentView()
/// .toolbar {
/// ToolbarItem {
/// SecondaryControl()
/// }
/// ToolbarItem {
/// PrimaryControl()
/// }
/// .visibilityPriorityIfAvailable(.high)
/// }
/// }
/// }
struct ToolbarItemVisibilityPriorityIfAvailable : Hashable, Sendable {
fileprivate let level: VisibilityPriorityIfAvailable
/// The default priority that lets the system determine the item's
/// visibility in the toolbar.
static let automatic = ToolbarItemVisibilityPriorityIfAvailable(.automatic)
/// A priority that moves the item to the overflow menu before
/// items with the default or high priority.
///
/// Use for secondary actions, such as archive or delete, that
/// don't need persistent visibility in the toolbar.
/// > Warning : Prior to OS 27, it is ignored.
@available(watchOS, unavailable)
@available(tvOS, unavailable)
@available(visionOS, unavailable)
static let low = ToolbarItemVisibilityPriorityIfAvailable(.low)
/// A priority that keeps the item in the toolbar longer than
/// items with the default or low priority.
///
/// Use for frequently used actions that need to stay visible as
/// the toolbar shrinks.
/// > Warning : Prior to OS 27, it is ignored.
@available(watchOS, unavailable)
@available(tvOS, unavailable)
@available(visionOS, unavailable)
static let high = ToolbarItemVisibilityPriorityIfAvailable(.high)
/// Internal initializer.
/// - Parameter level: <#level description#>
private init(_ level: VisibilityPriorityIfAvailable) {
self.level = level
}
/// Creates a priority lower than the specified value.
///
/// The priority is lower than `other` but doesn't cross below
/// the next lower system priority. For example,
/// `ToolbarItemVisibilityPriorityIfAvailable(lowerThan: .high)` returns a value
/// that is less than `.high` but greater than `.automatic`.
///
/// Priorities created with the same base value are equal:
///
/// let x = ToolbarItemVisibilityPriorityIfAvailable(lowerThan: .high)
/// let y = ToolbarItemVisibilityPriorityIfAvailable(lowerThan: .high)
/// x == y // true
///
/// > Warning : calling this initializer with a value different from .low .automatic or .high returns the same
/// other value. This is a limitation of this transitional code.
@available(watchOS, unavailable)
@available(tvOS, unavailable)
@available(visionOS, unavailable)
init(lowerThan other: ToolbarItemVisibilityPriorityIfAvailable) {
switch other.level {
case .low:
self.level = .lowerThanLow
case .automatic:
self.level = .lowerThanAutomatic
case .high:
self.level = .lowerThanHigh
default: // We don't manage other complex cases, we let them at the same level
self.level = other.level
}
}
/// Creates a priority higher than the specified value.
///
/// The priority is higher than `other` but doesn't cross above
/// the next higher system priority. For example,
/// `ToolbarItemVisibilityPriorityIfAvailable(higherThan: .high)` returns a
/// value that is greater than `.high`.
///
/// Priorities created with the same base value are equal:
///
/// let x = ToolbarItemVisibilityPriorityIfAvailable(higherThan: .high)
/// let y = ToolbarItemVisibilityPriorityIfAvailable(higherThan: .high)
/// x == y // true
///
/// > Warning : calling this initializer with a value different from .low .automatic or .high returns the same
/// other value. This is a limitation of this transitional code.
@available(watchOS, unavailable)
@available(tvOS, unavailable)
@available(visionOS, unavailable)
init(higherThan other: ToolbarItemVisibilityPriorityIfAvailable) {
switch other.level {
case .low:
self.level = .higherThanLow
case .automatic:
self.level = .higherThanAutomatic
case .high:
self.level = .higherThanHigh
default: // We don't manage other complex cases, we let them at the same level
self.level = other.level
}
}
/// Returns a Boolean value indicating whether two values are equal.
///
/// Equality is the inverse of inequality. For any values `a` and `b`,
/// `a == b` implies that `a != b` is `false`.
///
/// - Parameters:
/// - lhs: A value to compare.
/// - rhs: Another value to compare.
public static func == (a: ToolbarItemVisibilityPriorityIfAvailable, b: ToolbarItemVisibilityPriorityIfAvailable) -> Bool {
return a.level == b.level
}
}
/// Enumeration of the managed level values for simpler code.
fileprivate enum VisibilityPriorityIfAvailable: Int {
case low = 100
case automatic = 200
case high = 300
case lowerThanLow = 99
case higherThanLow = 101
case lowerThanAutomatic = 199
case higherThanAutomatic = 201
case lowerThanHigh = 299
case higherThanHigh = 301
}