iOS: Duo split engages when flat (include inactive hinge), size fallback; 1.0 RC 4
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dfdd9a8ae5
commit
4f2dcb94f5
3 files changed
+17
-5
No files matched your search
@@ -29,3 +29,4 @@
|
|||||||
2026-11-06 iOS: Update Download on downloaded playlists, albums, artists and stem playlists (their menus and the Downloads tab), plus Update All Downloads. Pulls the current song list, downloads new songs, drops removed ones, retries failed ones. Downloads still sync on their own when the app opens.
|
2026-11-06 iOS: Update Download on downloaded playlists, albums, artists and stem playlists (their menus and the Downloads tab), plus Update All Downloads. Pulls the current song list, downloads new songs, drops removed ones, retries failed ones. Downloads still sync on their own when the app opens.
|
||||||
2026-11-06 iOS: crossfade, Off or 1-12 s in Settings > Listening. Equal-power fade, Sweet Fades skips it between songs of the same album. Seeking during a fade finishes it.
|
2026-11-06 iOS: crossfade, Off or 1-12 s in Settings > Listening. Equal-power fade, Sweet Fades skips it between songs of the same album. Seeking during a fade finishes it.
|
||||||
2026-11-09 iOS: iPhone Duo unfolded uses both sides of the hinge: library on one side, Now Playing docked on the other (no mini player while split). Folded and other iPhones unchanged. 1.0 RC 3 (build 23).
|
2026-11-09 iOS: iPhone Duo unfolded uses both sides of the hinge: library on one side, Now Playing docked on the other (no mini player while split). Folded and other iPhones unchanged. 1.0 RC 3 (build 23).
|
||||||
|
2026-11-09 iOS: Duo split now engages with the phone lying flat (hinge region reports inactive then), with a screen-size fallback if no region is reported. 1.0 RC 4 (build 24).
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import UIKit
|
||||||
|
|
||||||
/// The tab bar, a navigation stack per tab, the mini player and the Now Playing sheet.
|
/// The tab bar, a navigation stack per tab, the mini player and the Now Playing sheet.
|
||||||
/// On an unfolded iPhone Duo the library sits on one side of the hinge and Now Playing on the other.
|
/// On an unfolded iPhone Duo the library sits on one side of the hinge and Now Playing on the other.
|
||||||
@@ -171,13 +172,23 @@ private struct DuoSplit<Library: View, Docked: View>: View {
|
|||||||
private struct Cut { var vertical: Bool; var first: CGFloat; var gap: CGFloat; var second: CGFloat }
|
private struct Cut { var vertical: Bool; var first: CGFloat; var gap: CGFloat; var second: CGFloat }
|
||||||
|
|
||||||
private static func cut(_ geo: GeometryProxy) -> Cut? {
|
private static func cut(_ geo: GeometryProxy) -> Cut? {
|
||||||
guard #available(iOS 27.1, *),
|
|
||||||
let r = geo.reservedRegions(kind: .division).first(where: \.isActive)?.frame else { return nil }
|
|
||||||
let size = geo.size
|
let size = geo.size
|
||||||
|
var c: Cut?
|
||||||
|
// The hinge reports inactive while the phone lies flat, so ask for inactive regions too.
|
||||||
|
if #available(iOS 27.1, *),
|
||||||
|
let r = geo.reservedRegions(kind: .division, options: .includeInactive).first?.frame {
|
||||||
let vertical = r.height >= r.width
|
let vertical = r.height >= r.width
|
||||||
let c = vertical
|
c = vertical
|
||||||
? Cut(vertical: true, first: r.minX, gap: r.width, second: size.width - r.maxX)
|
? Cut(vertical: true, first: r.minX, gap: r.width, second: size.width - r.maxX)
|
||||||
: Cut(vertical: false, first: r.minY, gap: r.height, second: size.height - r.maxY)
|
: Cut(vertical: false, first: r.minY, gap: r.height, second: size.height - r.maxY)
|
||||||
|
} else if UIDevice.current.userInterfaceIdiom == .phone, size.width >= 760, size.height >= 560 {
|
||||||
|
// No region reported: only an unfolded Duo gives an iPhone this much room both ways.
|
||||||
|
// The hinge sits at the middle of the screen, not of the safe area, so place it from there.
|
||||||
|
let screenW = (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.screen.bounds.width
|
||||||
|
let half = ((screenW ?? size.width) / 2 - geo.frame(in: .global).minX).rounded()
|
||||||
|
c = Cut(vertical: true, first: half - 12, gap: 24, second: size.width - half - 12)
|
||||||
|
}
|
||||||
|
guard let c else { return nil }
|
||||||
// A region that doesn't leave usable room on both sides isn't a hinge worth splitting at.
|
// A region that doesn't leave usable room on both sides isn't a hinge worth splitting at.
|
||||||
return c.first > 200 && c.second > 200 ? c : nil
|
return c.first > 200 && c.second > 200 ? c : nil
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -8,8 +8,8 @@ settings:
|
|||||||
SWIFT_VERSION: "5.0"
|
SWIFT_VERSION: "5.0"
|
||||||
# iOS needs a plain number for the bundle version; the label is what the app and releases show.
|
# iOS needs a plain number for the bundle version; the label is what the app and releases show.
|
||||||
MARKETING_VERSION: "1.0"
|
MARKETING_VERSION: "1.0"
|
||||||
VERSION_LABEL: "1.0 RC 3"
|
VERSION_LABEL: "1.0 RC 4"
|
||||||
CURRENT_PROJECT_VERSION: "23"
|
CURRENT_PROJECT_VERSION: "24"
|
||||||
targets:
|
targets:
|
||||||
Stemify:
|
Stemify:
|
||||||
type: application
|
type: application
|
||||||
|
|||||||
Reference in new issue
Block a user