diff --git a/AGENTS.md b/AGENTS.md index ee1c818a3..e5471392a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -605,7 +605,7 @@ editor when changing its schema. ## Cursor Cloud specific instructions -Cloud agent VMs run **Linux**, not macOS. This repo targets **iOS 26** with +Cloud agent VMs run **Linux**, not macOS. This repo targets **iOS 27** with **Xcode 27+** and **Tuist** (macOS-only). Treat Linux as a partial dev environment. Formatting and agent sync work on Linux. Builds, tests, and running the **Where** app require macOS (as in CI on the `xcode-27` runner image). diff --git a/Package.swift b/Package.swift index 933ad2e17..499006592 100644 --- a/Package.swift +++ b/Package.swift @@ -5,7 +5,7 @@ let package = Package( name: "Stuff", defaultLocalization: "en", platforms: [ - .iOS(.v26), + .iOS("27.0"), .macOS(.v26), ], products: [ diff --git a/Project.swift b/Project.swift index ac1988acc..2970f2738 100644 --- a/Project.swift +++ b/Project.swift @@ -1,7 +1,7 @@ import ProjectDescription let destinations: Destinations = [.iPhone, .iPad] -let deployment: DeploymentTargets = .iOS("26.0") +let deployment: DeploymentTargets = .iOS("27.0") /// The Ledger menu bar app is the only native-macOS target; everything else /// stays on the shared iOS destinations above. diff --git a/README.md b/README.md index 435a75936..2b372f489 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Random apps and stuff. ## Requirements - Xcode 27+ (a full Xcode.app, not the Command Line Tools) -- iOS 26.0+ +- iOS 27.0+ - [mise](https://mise.jdx.dev) pins Tuist, SwiftFormat, and Ruby. `./ide --bootstrap` installs it for you (see below). diff --git a/Shared/SnapshotKit/README.md b/Shared/SnapshotKit/README.md index aff3e1a5a..330349b6a 100644 --- a/Shared/SnapshotKit/README.md +++ b/Shared/SnapshotKit/README.md @@ -63,7 +63,7 @@ capture + comparison pipeline lives in the sibling layout pass (`.immediate` — skips the loop, so static content captures fast). `.settledAtLeast(minDuration:)` is `.settled` with a raised minimum window, for async appearance work that starts quiet and lands after the default floor - (the iOS 26 glass toolbar/tab bar material adaptation). + (the native glass toolbar/tab bar material adaptation). Intrinsic/full-content cases also have a `measurementReadiness` axis. Its default, `.sameAsCapture`, preserves the existing behavior for content whose loaded state changes its height. Deterministically sized fixtures may use diff --git a/Shared/SnapshotKit/Sources/SnapshotCase.swift b/Shared/SnapshotKit/Sources/SnapshotCase.swift index 038ca8e8b..b49c56e28 100644 --- a/Shared/SnapshotKit/Sources/SnapshotCase.swift +++ b/Shared/SnapshotKit/Sources/SnapshotCase.swift @@ -7,7 +7,7 @@ public enum SnapshotSettle: Equatable, Sendable { case settled /// ``settled`` with a raised minimum settle window. For content whose async /// appearance work starts *quiet* and lands after the default floor — the - /// iOS 26 glass toolbar/tab bar adapts its material to the content behind it + /// native glass toolbar/tab bar adapts its material to the content behind it /// a few hundred ms after hosting, which no pixel-stability check can /// anticipate before it starts. The floor is paid on every capture of the /// case, so reserve it for cases that host such chrome. diff --git a/Shared/SnapshotKitTesting/README.md b/Shared/SnapshotKitTesting/README.md index d6c8b3786..ac8d05efd 100644 --- a/Shared/SnapshotKitTesting/README.md +++ b/Shared/SnapshotKitTesting/README.md @@ -47,7 +47,7 @@ re-exports `SnapshotKit` and `SnapshotTesting`, so a test author needs a single `onReadyToSnapshot`). `.settledAtLeast(minDuration:)` raises the loop's minimum window for async appearance work that starts quiet and lands after the default floor (the - iOS 26 glass toolbar/tab bar material adaptation). `.immediate` skips the + native glass toolbar/tab bar material adaptation). `.immediate` skips the loop for content that's fully renderable after a layout pass. Intrinsic and full-content cases can independently set `measurementReadiness: .immediate` when their fixture's height is synchronous: only the sizing probe skips its diff --git a/Shared/SnapshotKitTesting/Sources/SnapshotRenderingSupport.swift b/Shared/SnapshotKitTesting/Sources/SnapshotRenderingSupport.swift index ae1b831df..c2a604d87 100644 --- a/Shared/SnapshotKitTesting/Sources/SnapshotRenderingSupport.swift +++ b/Shared/SnapshotKitTesting/Sources/SnapshotRenderingSupport.swift @@ -134,7 +134,7 @@ func settleForCapture( /// quiesces — e.g. a repeating pulse — doesn't hang the capture). /// /// `minDuration` also covers async appearance work that starts *quiet* and lands -/// late: the iOS 26 glass toolbar/tab bar adapts its material to the content +/// late: the native glass toolbar/tab bar adapts its material to the content /// behind it a few hundred ms after hosting, so a floor below that captures the /// pre-adaptation glass (seen on `primary`/`root` snapshots when the floor was /// 50ms). diff --git a/Where/WhereUI/README.md b/Where/WhereUI/README.md index 90ef8a0e8..cc20c5760 100644 --- a/Where/WhereUI/README.md +++ b/Where/WhereUI/README.md @@ -142,11 +142,10 @@ the feature [`Where/AGENTS.md`](../AGENTS.md) and this module's The scrim fades independently. Reduce Motion uses a short fade for both layers. Debug builds include **Reset Welcome Card** in Settings > Appearance beside the welcome-card toggle. The reset clears the saved region so the next foreground activation can show the card again. - `MainTabs` requests one bounded fix on each active-scene entry. On iOS 26.1 - and later, it shows a native tab-bar accessory after one second; denied or - restricted access and disabled Precise Location remain actionable there, - while transient or low-confidence failures disappear. iOS 26.0 still runs - the lookup and presents the welcome card, but does not show the accessory. + `MainTabs` requests one bounded fix on each active-scene entry. It shows a + native tab-bar accessory after one second; denied or restricted access and + disabled Precise Location remain actionable there, while transient or + low-confidence failures disappear. Welcome cards must be enabled, and the device must confidently resolve a tracked region with recording active. diff --git a/Where/WhereUI/Sources/MainTabs.swift b/Where/WhereUI/Sources/MainTabs.swift index 0c66cca2a..9a4a3769d 100644 --- a/Where/WhereUI/Sources/MainTabs.swift +++ b/Where/WhereUI/Sources/MainTabs.swift @@ -99,7 +99,11 @@ struct MainTabs: View { .badge(recordingWarning.isPresented ? 1 : 0) } .accessibilityHidden(welcomePresentation != nil) - .modifier(LocationWelcomeAccessoryModifier(accessory: welcomeAccessory)) + .tabViewBottomAccessory(isEnabled: welcomeAccessory != nil) { + if let welcomeAccessory { + LocationWelcomeStatusAccessory(accessory: welcomeAccessory) + } + } // Keep the tab bar fixed — don't minimize it as content scrolls. .tabBarMinimizeBehavior(.never) .overlay { diff --git a/Where/WhereUI/Sources/Primary/LocationWelcomeAccessoryModifier.swift b/Where/WhereUI/Sources/Primary/LocationWelcomeAccessoryModifier.swift deleted file mode 100644 index 90400e0df..000000000 --- a/Where/WhereUI/Sources/Primary/LocationWelcomeAccessoryModifier.swift +++ /dev/null @@ -1,18 +0,0 @@ -import SwiftUI - -/// Adds the system tab accessory only while live-region status is visible on iOS 26.1 and later. -struct LocationWelcomeAccessoryModifier: ViewModifier { - let accessory: LocationWelcomeModel.Accessory? - - func body(content: Content) -> some View { - if #available(iOS 26.1, *) { - content.tabViewBottomAccessory(isEnabled: accessory != nil) { - if let accessory { - LocationWelcomeStatusAccessory(accessory: accessory) - } - } - } else { - content - } - } -} diff --git a/Where/WhereUI/Sources/Primary/LocationsView.swift b/Where/WhereUI/Sources/Primary/LocationsView.swift index a57e99e7a..4b1a0f42a 100644 --- a/Where/WhereUI/Sources/Primary/LocationsView.swift +++ b/Where/WhereUI/Sources/Primary/LocationsView.swift @@ -334,7 +334,7 @@ private struct ResolveToolbarLabel: View { #if DEBUG extension LocationsView: SnapshotProviding { - /// The raised settle floor on `Loaded` outlasts the iOS 26 glass toolbar + /// The raised settle floor on `Loaded` outlasts the native glass toolbar /// material adaptation (seen pre-adaptation once on the equivalent /// pre-split screen) — same mechanism as `RootView.LoggedIn`. static var snapshots: [SnapshotCase] { diff --git a/Where/WhereUI/Sources/RootView.swift b/Where/WhereUI/Sources/RootView.swift index 6c41eaef1..ce08234ec 100644 --- a/Where/WhereUI/Sources/RootView.swift +++ b/Where/WhereUI/Sources/RootView.swift @@ -342,7 +342,7 @@ public struct RootView: View { /// idempotent and awaits the in-flight drive, a deterministic "reached /// `.ready`" signal — so the raised settle floor only has to outlast the /// post-ready tail: `MainTabs`' `.task` activation (empty-store re-pull + - /// Resolve badge) and the iOS 26 glass toolbar/tab bar material + /// Resolve badge) and the native glass toolbar/tab bar material /// adaptation, which starts quiet a few hundred ms after the chrome /// hosts. Those have no reachable completion signal (the scene's report /// model is private to `MainTabs`; the adaptation has no public diff --git a/Where/WhereUI/Sources/Shared/LocationNamer.swift b/Where/WhereUI/Sources/Shared/LocationNamer.swift index 048ab1e08..68e16f9a6 100644 --- a/Where/WhereUI/Sources/Shared/LocationNamer.swift +++ b/Where/WhereUI/Sources/Shared/LocationNamer.swift @@ -23,7 +23,7 @@ struct PlaceComponents: Equatable { } extension PlaceComponents { - /// iOS 26's MapKit geocoder folds the old `CLPlacemark` fields into + /// MapKit's geocoder folds the old `CLPlacemark` fields into /// formatted strings; `cityName` and `regionName` (the country) are the two /// pieces this compact teaser needs. init(_ representations: MKAddressRepresentations) {