mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Working Lyrics and adjusted height
This commit is contained in:
parent
dc90b8cbb0
commit
4f82ce417e
6 changed files with 116 additions and 34 deletions
|
|
@ -383,6 +383,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
AUTOMATION_APPLE_EVENTS = NO;
|
||||
CODE_SIGN_ENTITLEMENTS = DynamicIsland/DynamicIsland.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||
|
|
@ -394,6 +395,12 @@
|
|||
ENABLE_APP_SANDBOX = NO;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = YES;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = YES;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = YES;
|
||||
ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
|
|
@ -423,6 +430,12 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = com.Ebullioscopic.Atoll;
|
||||
PRODUCT_NAME = Atoll;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO;
|
||||
RUNTIME_EXCEPTION_ALLOW_JIT = NO;
|
||||
RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY = NO;
|
||||
RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO;
|
||||
RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO;
|
||||
RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
SYSTEM_FRAMEWORK_SEARCH_PATHS = (
|
||||
|
|
@ -437,6 +450,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
AUTOMATION_APPLE_EVENTS = NO;
|
||||
CODE_SIGN_ENTITLEMENTS = DynamicIsland/DynamicIsland.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||
|
|
@ -448,6 +462,12 @@
|
|||
ENABLE_APP_SANDBOX = NO;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
|
||||
ENABLE_RESOURCE_ACCESS_CALENDARS = YES;
|
||||
ENABLE_RESOURCE_ACCESS_CAMERA = YES;
|
||||
ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
|
||||
ENABLE_RESOURCE_ACCESS_LOCATION = YES;
|
||||
ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
|
|
@ -477,6 +497,12 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = com.Ebullioscopic.Atoll;
|
||||
PRODUCT_NAME = Atoll;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO;
|
||||
RUNTIME_EXCEPTION_ALLOW_JIT = NO;
|
||||
RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY = NO;
|
||||
RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO;
|
||||
RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO;
|
||||
RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
SYSTEM_FRAMEWORK_SEARCH_PATHS = (
|
||||
|
|
|
|||
|
|
@ -52,15 +52,7 @@ struct MinimalisticMusicView: View {
|
|||
|
||||
// Lyrics under the author name (same font size as author)
|
||||
if enableLyrics {
|
||||
Text(musicManager.currentLyrics)
|
||||
.font(.system(size: 10, weight: .regular))
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.padding(.horizontal, 4)
|
||||
.transition(.opacity)
|
||||
.animation(.easeInOut(duration: 0.3), value: musicManager.currentLyrics)
|
||||
lyricsLineView
|
||||
}
|
||||
}
|
||||
.frame(width: geo.size.width, height: geo.size.height, alignment: .center)
|
||||
|
|
@ -75,7 +67,7 @@ struct MinimalisticMusicView: View {
|
|||
// (lyrics are displayed inline under the artist name)
|
||||
}
|
||||
// reserve extra height when lyrics are enabled
|
||||
.frame(height: vm.effectiveClosedNotchHeight + (isHovering ? 8 : 0) + (enableLyrics ? 22 : 0), alignment: .center)
|
||||
.frame(height: vm.effectiveClosedNotchHeight + (isHovering ? 8 : 0), alignment: .center)
|
||||
.onHover { hovering in
|
||||
isHovering = hovering
|
||||
}
|
||||
|
|
@ -118,3 +110,33 @@ struct MinimalisticMusicView: View {
|
|||
height: max(0, vm.effectiveClosedNotchHeight - (isHovering ? 0 : 12)), alignment: .center)
|
||||
}
|
||||
}
|
||||
|
||||
private extension MinimalisticMusicView {
|
||||
var lyricsLineView: some View {
|
||||
let line = musicManager.currentLyrics.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
return HStack(spacing: 6) {
|
||||
if !line.isEmpty {
|
||||
Image(systemName: "music.note")
|
||||
.font(.system(size: 11, weight: .semibold))
|
||||
.foregroundColor(.white.opacity(0.7))
|
||||
.symbolRenderingMode(.monochrome)
|
||||
|
||||
Text(line)
|
||||
.font(.system(size: 11, weight: .semibold))
|
||||
.foregroundColor(.white.opacity(0.88))
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.padding(.horizontal, 6)
|
||||
.id(line)
|
||||
.transition(.asymmetric(
|
||||
insertion: .move(edge: .bottom).combined(with: .opacity),
|
||||
removal: .move(edge: .top).combined(with: .opacity)
|
||||
))
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.animation(.smooth(duration: 0.32), value: line)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,18 +50,6 @@ struct MinimalisticMusicPlayerView: View {
|
|||
.foregroundColor(Defaults[.playerColorTinting] ? Color(nsColor: musicManager.avgColor).ensureMinimumBrightness(factor: 0.6) : .gray)
|
||||
.lineLimit(1)
|
||||
|
||||
// Lyrics shown under the author name, same font size as author
|
||||
if enableLyrics {
|
||||
Text(musicManager.currentLyrics)
|
||||
.font(.system(size: 10, weight: .regular))
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.leading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.top, 4)
|
||||
.transition(.opacity)
|
||||
.animation(.easeInOut(duration: 0.3), value: musicManager.currentLyrics)
|
||||
}
|
||||
}
|
||||
.frame(width: textWidth, alignment: .leading)
|
||||
|
||||
|
|
@ -81,7 +69,10 @@ struct MinimalisticMusicPlayerView: View {
|
|||
playbackControls
|
||||
.padding(.top, 4)
|
||||
|
||||
// Lyrics are displayed inline under the artist name (see header area)
|
||||
if enableLyrics {
|
||||
lyricsView
|
||||
.padding(.top, 10)
|
||||
}
|
||||
|
||||
reminderList
|
||||
}
|
||||
|
|
@ -90,7 +81,6 @@ struct MinimalisticMusicPlayerView: View {
|
|||
.padding(.bottom, shouldShowReminderList ? ReminderLiveActivityManager.listBottomPadding : ReminderLiveActivityManager.baselineMinimalisticBottomPadding)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: calculateDynamicHeight(), alignment: .center)
|
||||
.animation(.easeInOut(duration: 0.3), value: musicManager.currentLyrics)
|
||||
}
|
||||
|
||||
// MARK: - TypingLyricView
|
||||
|
|
@ -174,8 +164,10 @@ struct MinimalisticMusicPlayerView: View {
|
|||
height += 40 + 2 // controls + top padding
|
||||
|
||||
// Add lyrics height if enabled in settings (reserve space even while loading)
|
||||
if Defaults[.enableLyrics] {
|
||||
height += 20 + 4 // lyrics + top padding
|
||||
if enableLyrics {
|
||||
let lyricsTopPadding: CGFloat = 10
|
||||
let lyricsEstimatedHeight: CGFloat = 30
|
||||
height += lyricsTopPadding + lyricsEstimatedHeight
|
||||
}
|
||||
|
||||
// Add reminder list height if showing
|
||||
|
|
@ -199,6 +191,36 @@ struct MinimalisticMusicPlayerView: View {
|
|||
.environmentObject(vm)
|
||||
}
|
||||
|
||||
private var lyricsView: some View {
|
||||
let line = musicManager.currentLyrics.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let transition: AnyTransition = .asymmetric(
|
||||
insertion: .move(edge: .bottom).combined(with: .opacity),
|
||||
removal: .move(edge: .top).combined(with: .opacity)
|
||||
)
|
||||
|
||||
return HStack(spacing: 6) {
|
||||
if !line.isEmpty {
|
||||
Image(systemName: "music.note")
|
||||
.font(.system(size: 12, weight: .semibold))
|
||||
.foregroundColor(.white.opacity(0.7))
|
||||
.symbolRenderingMode(.monochrome)
|
||||
|
||||
Text(line)
|
||||
.font(.system(size: 12, weight: .semibold))
|
||||
.foregroundColor(.white.opacity(0.88))
|
||||
.lineLimit(2)
|
||||
.multilineTextAlignment(.leading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.trailing, 6)
|
||||
.id(line)
|
||||
.transition(transition)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 6)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.animation(.smooth(duration: 0.32), value: line)
|
||||
}
|
||||
|
||||
|
||||
private struct MinimalisticReminderEventListView: View {
|
||||
let reminders: [ReminderLiveActivityManager.ReminderEntry]
|
||||
|
|
|
|||
|
|
@ -157,6 +157,11 @@ struct MusicControlsView: View {
|
|||
.fontWeight(.medium)
|
||||
// Lyrics shown under the author name (same font size as author) when enabled in settings
|
||||
if Defaults[.enableLyrics] {
|
||||
let transition = AnyTransition.asymmetric(
|
||||
insertion: .move(edge: .bottom).combined(with: .opacity),
|
||||
removal: .move(edge: .top).combined(with: .opacity)
|
||||
)
|
||||
|
||||
Text(musicManager.currentLyrics)
|
||||
.font(.headline)
|
||||
.foregroundColor(.white.opacity(0.8))
|
||||
|
|
@ -164,8 +169,9 @@ struct MusicControlsView: View {
|
|||
.multilineTextAlignment(.leading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.top, 2)
|
||||
.transition(.opacity)
|
||||
.animation(.easeInOut(duration: 0.3), value: musicManager.currentLyrics)
|
||||
.id(musicManager.currentLyrics)
|
||||
.transition(transition)
|
||||
.animation(.easeInOut(duration: 0.32), value: musicManager.currentLyrics)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,11 +198,6 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
|||
if Defaults[.enableMinimalisticUI] {
|
||||
let extraHeight = ReminderLiveActivityManager.additionalHeight(forRowCount: minimalisticReminderRowCount)
|
||||
baseSize.height += extraHeight
|
||||
|
||||
// Add extra height for lyrics if enabled in settings
|
||||
if Defaults[.enableLyrics] {
|
||||
baseSize.height += 24 // Additional height for lyrics display
|
||||
}
|
||||
}
|
||||
|
||||
// Only apply dynamic sizing when on stats tab and stats are enabled
|
||||
|
|
|
|||
|
|
@ -15,7 +15,18 @@ let downloadSneakSize: CGSize = .init(width: 65, height: 1)
|
|||
let batterySneakSize: CGSize = .init(width: 160, height: 1)
|
||||
|
||||
let openNotchSize: CGSize = .init(width: 640, height: 190)
|
||||
let minimalisticOpenNotchSize: CGSize = .init(width: 420, height: 200)
|
||||
private let minimalisticBaseOpenNotchSize: CGSize = .init(width: 420, height: 180)
|
||||
private let minimalisticLyricsExtraHeight: CGFloat = 30
|
||||
|
||||
var minimalisticOpenNotchSize: CGSize {
|
||||
var size = minimalisticBaseOpenNotchSize
|
||||
|
||||
if Defaults[.enableLyrics] {
|
||||
size.height += minimalisticLyricsExtraHeight
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
let cornerRadiusInsets: (opened: (top: CGFloat, bottom: CGFloat), closed: (top: CGFloat, bottom: CGFloat)) = (opened: (top: 19, bottom: 24), closed: (top: 6, bottom: 14))
|
||||
let minimalisticCornerRadiusInsets: (opened: (top: CGFloat, bottom: CGFloat), closed: (top: CGFloat, bottom: CGFloat)) = (opened: (top: 35, bottom: 35), closed: cornerRadiusInsets.closed)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue