iOS: drop Master fader, roomier static Duo stem rows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5a7a36b898
commit
ae5eead73b
1 file changed
+18
-16
@@ -681,8 +681,10 @@ private struct MixerPanel: View {
|
|||||||
let names = pm.stemNames
|
let names = pm.stemNames
|
||||||
let stems = pm.source == .Stems
|
let stems = pm.source == .Stems
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
// Spread spare height across the rows (stems + master) instead of leaving it all at the bottom.
|
// Spread spare height across the stem rows instead of leaving it all at the bottom.
|
||||||
let rowH = roomy ? Self.roomyRow : min(62, max(46, (geo.size.height - 80) / CGFloat(names.count + 1)))
|
let count = CGFloat(max(names.count, 1))
|
||||||
|
let rowH = roomy ? min(80, max(Self.roomyRow, (geo.size.height - Self.roomyChrome) / count))
|
||||||
|
: min(62, max(46, (geo.size.height - 64) / count))
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
if pm.source == .Original {
|
if pm.source == .Original {
|
||||||
@@ -750,11 +752,7 @@ private struct MixerPanel: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.separator.frame(height: 0.5).padding(.vertical, 6)
|
Spacer(minLength: roomy ? 8 : 16)
|
||||||
FaderRow(dot: nil, label: "Master", percent: Int(pm.master * 100), dim: false, height: rowH, stacked: roomy) {
|
|
||||||
FaderSlider(value: pm.master, fill: p.label, thumb: roomy ? 30 : 24, onChange: pm.setMaster)
|
|
||||||
} trailing: { EmptyView() }
|
|
||||||
Spacer(minLength: 16)
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 24)
|
.padding(.horizontal, 24)
|
||||||
}
|
}
|
||||||
@@ -766,9 +764,11 @@ private struct MixerPanel: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension MixerPanel {
|
extension MixerPanel {
|
||||||
static let roomyRow: CGFloat = 60
|
static let roomyRow: CGFloat = 66
|
||||||
/// Height that shows the presets, every stem and the master without scrolling, roomy rows.
|
/// Preset chips plus the bottom gap.
|
||||||
static func roomyHeight(_ stems: Int) -> CGFloat { 48 + CGFloat(stems + 1) * roomyRow + 13 + 16 }
|
static let roomyChrome: CGFloat = 56
|
||||||
|
/// Height that shows the presets and every stem without scrolling, roomy rows.
|
||||||
|
static func roomyHeight(_ stems: Int) -> CGFloat { roomyChrome + CGFloat(stems) * roomyRow }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [Chip] in the sheet's own colours: selected is the label colour, so it reads on any tint.
|
/// [Chip] in the sheet's own colours: selected is the label colour, so it reads on any tint.
|
||||||
@@ -807,7 +807,7 @@ private struct StemFader: View {
|
|||||||
let color = Color(hex: Stems.color(name))
|
let color = Color(hex: Stems.color(name))
|
||||||
FaderRow(dot: setting.muted ? p.label3 : color, label: Stems.label(name), percent: Int(stemTaper(setting.level) * 100), dim: setting.muted, height: height, stacked: roomy) {
|
FaderRow(dot: setting.muted ? p.label3 : color, label: Stems.label(name), percent: Int(stemTaper(setting.level) * 100), dim: setting.muted, height: height, stacked: roomy) {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
FaderSlider(value: setting.level, fill: setting.muted ? p.label3 : color, detent: StemSetting.unity, enabled: enabled, thumb: roomy ? 30 : 24) {
|
FaderSlider(value: setting.level, fill: setting.muted ? p.label3 : color, detent: StemSetting.unity, enabled: enabled, thumb: roomy ? 26 : 24) {
|
||||||
pm.setStemLevel(name, $0)
|
pm.setStemLevel(name, $0)
|
||||||
}
|
}
|
||||||
// Live level under the fader, -48..0 dBFS.
|
// Live level under the fader, -48..0 dBFS.
|
||||||
@@ -845,7 +845,8 @@ struct FaderRow<Fader: View, Trailing: View>: View {
|
|||||||
@Environment(\.palette) private var p
|
@Environment(\.palette) private var p
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if stacked {
|
if stacked {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
// Bottom-aligned with a gap under, so each name sits clear of the meter above it.
|
||||||
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
HStack(spacing: 6) {
|
HStack(spacing: 6) {
|
||||||
if let dot { Circle().fill(dot).frame(width: 8, height: 8) }
|
if let dot { Circle().fill(dot).frame(width: 8, height: 8) }
|
||||||
Text(label).font(.subheadline.weight(.semibold)).foregroundStyle(dim ? p.label2 : p.label).lineLimit(1)
|
Text(label).font(.subheadline.weight(.semibold)).foregroundStyle(dim ? p.label2 : p.label).lineLimit(1)
|
||||||
@@ -855,7 +856,8 @@ struct FaderRow<Fader: View, Trailing: View>: View {
|
|||||||
.frame(height: 18)
|
.frame(height: 18)
|
||||||
HStack(spacing: 8) { fader; trailing }
|
HStack(spacing: 8) { fader; trailing }
|
||||||
}
|
}
|
||||||
.frame(height: height)
|
.padding(.bottom, 4)
|
||||||
|
.frame(height: height, alignment: .bottom)
|
||||||
} else {
|
} else {
|
||||||
row
|
row
|
||||||
}
|
}
|
||||||
@@ -888,7 +890,7 @@ struct ToggleBox: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
Text(text).font(.footnote.bold()).foregroundStyle(on ? .black : p.label2)
|
Text(text).font(.footnote.bold()).foregroundStyle(on ? .black : p.label2)
|
||||||
.frame(width: big ? 38 : 30, height: big ? 32 : 26)
|
.frame(width: big ? 34 : 30, height: big ? 28 : 26)
|
||||||
.background(on ? onColor : p.fill, in: RoundedRectangle(cornerRadius: 7, style: .continuous))
|
.background(on ? onColor : p.fill, in: RoundedRectangle(cornerRadius: 7, style: .continuous))
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
@@ -913,7 +915,7 @@ struct FaderSlider: View {
|
|||||||
self.value = value; self.fill = fill; self.detent = detent; self.enabled = enabled; self.thumb = thumb; self.onChange = onChange
|
self.value = value; self.fill = fill; self.detent = detent; self.enabled = enabled; self.thumb = thumb; self.onChange = onChange
|
||||||
}
|
}
|
||||||
|
|
||||||
private var bar: CGFloat { thumb >= 28 ? 6 : 4 }
|
private var bar: CGFloat { thumb >= 26 ? 5 : 4 }
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
@@ -966,7 +968,7 @@ struct NowPlayingDeck: View {
|
|||||||
Text("Stems").font(.headline).foregroundStyle(c.label)
|
Text("Stems").font(.headline).foregroundStyle(c.label)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading).padding(.horizontal, 24)
|
.frame(maxWidth: .infinity, alignment: .leading).padding(.horizontal, 24)
|
||||||
// As much as the stems need to show without scrolling, leaving the queue a few rows.
|
// As much as the stems need to show without scrolling, leaving the queue a few rows.
|
||||||
MixerPanel(roomy: true).frame(height: min(MixerPanel.roomyHeight(max(g.playback.stemNames.count, 4)), geo.size.height * 0.68))
|
MixerPanel(roomy: true).frame(height: min(MixerPanel.roomyHeight(max(g.playback.stemNames.count, 4)), geo.size.height * 0.72))
|
||||||
Rectangle().fill(c.label3.opacity(0.35)).frame(height: 0.5).padding(.horizontal, 24).padding(.bottom, 8)
|
Rectangle().fill(c.label3.opacity(0.35)).frame(height: 0.5).padding(.horizontal, 24).padding(.bottom, 8)
|
||||||
QueuePanel()
|
QueuePanel()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user