broken changes
This commit is contained in:
@@ -12,7 +12,7 @@ struct DJLoopDrag {
|
||||
self.viewport = viewport;secondsPerPixel = span/max(1,width);anchor = viewport+x*secondsPerPixel;original = loop
|
||||
if create { mode = .create }
|
||||
else if let loop {
|
||||
let left = abs(anchor-loop.lowerBound),right = abs(anchor-loop.upperBound),tolerance = 8*secondsPerPixel
|
||||
let left = abs(anchor-loop.lowerBound),right = abs(anchor-loop.upperBound),tolerance = min(8*secondsPerPixel,(loop.upperBound-loop.lowerBound)/4)
|
||||
if min(left,right) <= tolerance { mode = left <= right ? .start : .end }
|
||||
else if loop.contains(anchor) { mode = .move }
|
||||
else { mode = .seek }
|
||||
|
||||
@@ -689,12 +689,7 @@ private enum DJStyle {
|
||||
}
|
||||
|
||||
struct DJConsole: View {
|
||||
@ObservedObject var model: AppModel
|
||||
@ObservedObject var system: DJSystem
|
||||
var expanded = false
|
||||
@State private var settingsModal = false
|
||||
@State private var routing = false
|
||||
@State private var mapping = false
|
||||
@State private var query = ""
|
||||
@State private var playlist: Int64?
|
||||
@State private var playlistIDs = [Int64]()
|
||||
@@ -712,14 +707,13 @@ struct DJConsole: View {
|
||||
private var pages: Int { max(1,(songs.count+49)/50) }
|
||||
private var visible: [Song] { Array(songs.dropFirst(min(page,pages-1)*50).prefix(50)) }
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(spacing:10) {
|
||||
header
|
||||
DJContinuousConsole(system:system,loadA:{loadSelected("A")},loadB:{loadSelected("B")})
|
||||
DJContinuousConsole(system:system,loadA:{loadSelected("A")},loadB:{loadSelected("B")}).fixedSize(horizontal:false,vertical:true)
|
||||
HStack(alignment:.top,spacing:12) {
|
||||
browser.frame(maxWidth:.infinity).frame(height:expanded ? 330 : 220)
|
||||
DJQueuePane(system:system,automix:system.automix).frame(width:310,height:expanded ? 330 : 220)
|
||||
}
|
||||
browser.frame(maxWidth:.infinity,maxHeight:.infinity)
|
||||
DJQueuePane(system:system,automix:system.automix).frame(width:310).frame(maxHeight:.infinity)
|
||||
}.frame(maxWidth:.infinity,maxHeight:.infinity)
|
||||
if let progress = system.importProgress {
|
||||
HStack {
|
||||
Text(progress.current).lineLimit(1);Text("\(progress.completed)/\(progress.total)").monospacedDigit()
|
||||
@@ -728,9 +722,8 @@ struct DJConsole: View {
|
||||
else { Button("Dismiss") { system.importProgress = nil } }
|
||||
}.font(.caption).controlSize(.mini)
|
||||
}
|
||||
HStack { Text(system.status).lineLimit(1);Spacer();Text("DJ master separate from karaoke").foregroundStyle(.secondary) }.font(.system(size:10))
|
||||
}.padding(14)
|
||||
}.background(DJStyle.background).foregroundStyle(.white)
|
||||
}.padding(14).frame(maxWidth:.infinity,maxHeight:.infinity,alignment:.top)
|
||||
.background(DJStyle.background).foregroundStyle(.white)
|
||||
.preferredColorScheme(.dark)
|
||||
.alert("Replace playing track?",isPresented:Binding(get:{system.pendingReplacement != nil},set:{if !$0 { system.pendingReplacement = nil }}),presenting:system.pendingReplacement) { request in
|
||||
Button("Cancel",role:.cancel) { system.cancelReplacement() }
|
||||
@@ -738,9 +731,6 @@ struct DJConsole: View {
|
||||
} message: { request in Text("Deck \(request.deck) is playing. Replacing it with \(request.title) stops the current track. Continue?") }
|
||||
.sheet(isPresented:$system.cueEditing) { DJCueEditor(system:system) }
|
||||
.sheet(isPresented:Binding(get:{system.loopEditor != nil},set:{if !$0 { system.loopEditor = nil }})) { let deck = system.channel(system.loopEditor ?? "A");DJLoopEditor(player:deck.player,letter:deck.letter) }
|
||||
.sheet(isPresented:$settingsModal) { StudioSettingsDialog(model:model,scope:"DJ") }
|
||||
.sheet(isPresented:$routing) { StudioSettingsDialog(model:model,scope:"DJ",category:"Devices") }
|
||||
.sheet(isPresented:$mapping) { StudioSettingsDialog(model:model,scope:"DJ",category:"MIDI") }
|
||||
.sheet(isPresented:$playlistEditor) { playlistSheet }
|
||||
.alert("DJ workstation",isPresented:Binding(get:{system.error != nil},set:{if !$0 { system.error = nil }})) { Button("OK") { system.error = nil } } message: { Text(system.error ?? "") }
|
||||
.onAppear { refreshPlaylist();connectMIDI() }
|
||||
@@ -757,9 +747,6 @@ struct DJConsole: View {
|
||||
Text("TWO DECKS").font(.system(size:9,weight:.medium)).foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
if system.previewDeck != nil { Button("Stop headphone preview") { system.stopPreview() }.tint(.green) }
|
||||
Button { settingsModal = true } label: { Label("DJ Settings",systemImage:"gearshape") }
|
||||
Button { routing = true } label: { Label("Audio Routing",systemImage:"hifispeaker.fill") }
|
||||
Button { mapping = true } label: { Label("MIDI",systemImage:"pianokeys") }
|
||||
}.controlSize(.small)
|
||||
}
|
||||
private var browser: some View {
|
||||
|
||||
@@ -513,10 +513,15 @@ private struct LibraryCommands {
|
||||
var play: () -> Void
|
||||
var next: () -> Void
|
||||
var video: () -> Void
|
||||
var settings: () -> Void
|
||||
}
|
||||
private struct StudioSettingsAction { var open: () -> Void }
|
||||
private struct StudioSettingsActionKey: FocusedValueKey { typealias Value = StudioSettingsAction }
|
||||
private struct LibraryCommandsKey: FocusedValueKey { typealias Value = LibraryCommands }
|
||||
private extension FocusedValues {
|
||||
var studioSettings: StudioSettingsAction? {
|
||||
get { self[StudioSettingsActionKey.self] }
|
||||
set { self[StudioSettingsActionKey.self] = newValue }
|
||||
}
|
||||
var libraryCommands: LibraryCommands? {
|
||||
get { self[LibraryCommandsKey.self] }
|
||||
set { self[LibraryCommandsKey.self] = newValue }
|
||||
@@ -526,6 +531,7 @@ private extension FocusedValues {
|
||||
@StateObject private var model = AppModel(storageURL:ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] == nil ? nil : FileManager.default.temporaryDirectory.appendingPathComponent("KJMix-TestHost-"+String(ProcessInfo.processInfo.processIdentifier)))
|
||||
@AppStorage("studioAppearance") private var appearance = "system"
|
||||
@FocusedValue(\.libraryCommands) private var actions
|
||||
@FocusedValue(\.studioSettings) private var settingsAction
|
||||
@FocusedValue(\.nameReinterpretation) private var nameActions
|
||||
var body: some Scene {
|
||||
Window("KJMix Pro", id: "main") {
|
||||
@@ -540,7 +546,7 @@ private extension FocusedValues {
|
||||
Button("New Venue…") { model.creating = .venue }.keyboardShortcut("n", modifiers: [.command, .option])
|
||||
}
|
||||
CommandGroup(replacing:.appSettings) {
|
||||
Button("Settings…") { actions?.settings() }.keyboardShortcut(",").disabled(actions == nil)
|
||||
Button("Settings…") { settingsAction?.open() }.keyboardShortcut(",").disabled(settingsAction == nil)
|
||||
}
|
||||
CommandMenu("Library") {
|
||||
Button("Song Info…") { actions?.songInfo() }.keyboardShortcut("i").disabled(actions?.canEdit != true)
|
||||
@@ -775,7 +781,7 @@ struct LibraryView: View {
|
||||
private var workspaceLayout: some View {
|
||||
TabView(selection:$workspaceTab) {
|
||||
libraryWorkspace.tabItem { Label("Karaoke",systemImage:"music.mic") }.tag("Karaoke")
|
||||
DJConsole(model:model,system:model.dj,expanded:true)
|
||||
DJConsole(system:model.dj)
|
||||
.tabItem { Label("DJ Studio",systemImage:"opticaldisc") }.tag("DJ Studio")
|
||||
}.accessibilityIdentifier("workspace.tabs")
|
||||
}
|
||||
@@ -784,7 +790,8 @@ struct LibraryView: View {
|
||||
.background(StudioTheme.frame)
|
||||
.tint(.accentColor)
|
||||
.focusedSceneValue(\.nameReinterpretation,NameReinterpretationCommands(perform:{beginReinterpretation()},enabled:workspaceTab == "Karaoke" && ["Library","Singer Songs"].contains(source) && (selectedSong != nil || !tableSelection.isEmpty)))
|
||||
.focusedSceneValue(\.libraryCommands,workspaceTab == "Karaoke" ? LibraryCommands(importMusic:{importing = true},songInfo:{editingSong = selectedSong},canEdit:selectedSong != nil,play:playSelected,next:playNext,video:{openWindow(id:"lyrics")},settings:{studioSettingsModal = true}) : nil)
|
||||
.focusedSceneValue(\.studioSettings,StudioSettingsAction(open:{studioSettingsModal = true}))
|
||||
.focusedSceneValue(\.libraryCommands,workspaceTab == "Karaoke" ? LibraryCommands(importMusic:{importing = true},songInfo:{editingSong = selectedSong},canEdit:selectedSong != nil,play:playSelected,next:playNext,video:{openWindow(id:"lyrics")}) : nil)
|
||||
.sheet(isPresented:$studioSettingsModal) { StudioSettingsDialog(model:model,scope:workspaceTab == "DJ Studio" ? "DJ" : "Karaoke") }
|
||||
.navigationTitle(workspaceTab == "DJ Studio" ? "DJ Studio" : source == "Singer Songs" ? (model.singers.first { $0.id == model.selectedSinger }?.name ?? "Singer") : source)
|
||||
.navigationSubtitle(model.currentVenueName)
|
||||
|
||||
Reference in New Issue
Block a user