Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LyricFever/Views/KaraokeView/FloatingPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class FloatingPanel<Content: View>: NSPanel {
standardWindowButton(.miniaturizeButton)?.isHidden = true
standardWindowButton(.zoomButton)?.isHidden = true
contentView = NSHostingView(rootView: view()
.preferredColorScheme(.dark)
// .preferredColorScheme(.dark)
.environment(\.floatingPanel, self))
hasShadow = false
}
Expand Down
130 changes: 70 additions & 60 deletions LyricFever/Views/KaraokeView/KaraokeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,15 @@ import SDWebImage
import ColorKit
import Combine

struct VisualEffectView: NSViewRepresentable {
func makeNSView(context: Context) -> NSVisualEffectView {
let view = NSVisualEffectView()

view.blendingMode = .behindWindow
view.state = .active
view.material = .hudWindow
return view
}

func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
//
nsView.material = .hudWindow
nsView.blendingMode = .behindWindow
}
}

struct KaraokeView: View {
@Environment(ViewModel.self) var viewmodel
@AppStorage("karaokeTransparency") var karaokeTransparency: Double = 50


// Adjust threshold here
private var useForcedWhiteText: Bool {
karaokeTransparency / 100 > 0.35
}

func currentWords(for currentlyPlayingLyricsIndex: Int) -> String {
if !viewmodel.romanizedLyrics.isEmpty {
return viewmodel.romanizedLyrics[currentlyPlayingLyricsIndex]
Expand All @@ -40,32 +28,29 @@ struct KaraokeView: View {
return viewmodel.currentlyPlayingLyrics[currentlyPlayingLyricsIndex].words
}
}

func multilingualView(_ currentlyPlayingLyricsIndex: Int) -> some View {
VStack(spacing: 6) {
Text(verbatim: currentWords(for: currentlyPlayingLyricsIndex))

// Text(verbatim: viewmodel.romanizedLyrics.isEmpty ? viewmodel.currentlyPlayingLyrics[currentlyPlayingLyricsIndex].words : viewmodel.romanizedLyrics[currentlyPlayingLyricsIndex])
Text(verbatim: viewmodel.translatedLyric[currentlyPlayingLyricsIndex])
.font(.custom(viewmodel.karaokeFont.fontName, size: 0.9*(viewmodel.karaokeFont.pointSize)))
.font(.custom(viewmodel.karaokeFont.fontName, size: 0.9 * (viewmodel.karaokeFont.pointSize)))
.opacity(0.85)
}
}

func originalAndTranslationAreDifferent(for currentlyPlayingLyricsIndex: Int) -> Bool {
viewmodel.currentlyPlayingLyrics[currentlyPlayingLyricsIndex].words != viewmodel.translatedLyric[currentlyPlayingLyricsIndex]
}

@ViewBuilder
func lyricsView() -> some View {
if let currentlyPlayingLyricsIndex = viewmodel.currentlyPlayingLyricsIndex {
if viewmodel.translationExists {
if viewmodel.userDefaultStorage.karaokeShowMultilingual, originalAndTranslationAreDifferent(for: currentlyPlayingLyricsIndex) {
if viewmodel.userDefaultStorage.karaokeShowMultilingual,
originalAndTranslationAreDifferent(for: currentlyPlayingLyricsIndex) {
multilingualView(currentlyPlayingLyricsIndex)
// .id(currentlyPlayingLyricsIndex)
// .compositingGroup()
}
else {
.compositingGroup()
} else {
Text(verbatim: viewmodel.translatedLyric[currentlyPlayingLyricsIndex])
}
} else {
Expand All @@ -81,37 +66,62 @@ struct KaraokeView: View {
Text("")
}
}

@ViewBuilder
var finalKaraokeView: some View {
lyricsView()
.id(viewmodel.currentlyPlayingLyricsIndex)
.lineLimit(2)
.foregroundStyle(.white)
.minimumScaleFactor(0.9)
.font(.custom(viewmodel.karaokeFont.fontName, size: viewmodel.karaokeFont.pointSize))
.padding(10)
.padding(.horizontal, 10)
.background {
viewmodel.currentAlbumArt
.transition(.opacity)
.opacity(karaokeTransparency/100)
}
// .drawingGroup()
.background(
VisualEffectView().ignoresSafeArea()
)
.cornerRadius(16)
.onHover { hover in
if viewmodel.userDefaultStorage.karaokeModeHoveringSetting {
viewmodel.karaokeModeHovering = hover
}
}
.multilineTextAlignment(.center)
.frame(minWidth: 800, maxWidth: 800, minHeight: 100, maxHeight: 100, alignment: .center)
}


var body: some View {
finalKaraokeView
if #available(macOS 26.0, *) {
lyricsView()
.lineLimit(2)
.foregroundStyle(useForcedWhiteText ? Color.white : Color.primary)
.minimumScaleFactor(0.9)
.font(.custom(viewmodel.karaokeFont.fontName, size: viewmodel.karaokeFont.pointSize))
.padding(10)
.padding(.horizontal, 10)
.background {
if viewmodel.userDefaultStorage.karaokeUseAlbumColor, karaokeTransparency > 0 {
viewmodel.currentAlbumArt
.opacity(karaokeTransparency / 100)
}
}
.glassEffect(in: .rect(cornerRadius: 16))
.cornerRadius(16)
.onHover { hover in
if viewmodel.userDefaultStorage.karaokeModeHoveringSetting {
viewmodel.karaokeModeHovering = hover
}
}
.multilineTextAlignment(.center)
.frame(minWidth: 800, maxWidth: 800, minHeight: 100, maxHeight: 100, alignment: .center)
} else {
// fall back
lyricsView()
.lineLimit(2)
.foregroundStyle(useForcedWhiteText ? Color.white : Color.primary)
.minimumScaleFactor(0.9)
.font(.custom(viewmodel.karaokeFont.fontName, size: viewmodel.karaokeFont.pointSize))
.padding(10)
.padding(.horizontal, 10)
.background {
// Material + optional album overlay
Rectangle()
.fill(Material.regular)
.overlay(
Group {
if viewmodel.userDefaultStorage.karaokeUseAlbumColor, karaokeTransparency > 0 {
viewmodel.currentAlbumArt
.opacity(karaokeTransparency / 100)
}
}
)
.cornerRadius(16)
.ignoresSafeArea()
}
.onHover { hover in
if viewmodel.userDefaultStorage.karaokeModeHoveringSetting {
viewmodel.karaokeModeHovering = hover
}
}
.multilineTextAlignment(.center)
.frame(minWidth: 800, maxWidth: 800, minHeight: 100, maxHeight: 100, alignment: .center)
}
}
}