Final ExpandedPlayer Layout

This commit is contained in:
tr1x_em committed 2025-08-06 20:18:53 +05:30
1 parent 209df5d91a
commit f1993ef473
3 files changed
+106 -51

No files matched your search

+68 -22
View File
@@ -12,7 +12,6 @@ import urllib.parse
import urllib.request
from typing import List
import threading
import weakref # For memory-efficient references
from fabric.utils import bulk_connect, invoke_repeater, cooldown
from fabric.widgets.image import Image
@@ -28,6 +27,7 @@ CACHE_DIR = f"{data.CACHE_DIR}/media"
# Shared MPRIS manager to reduce memory usage
_shared_mpris_manager = None
def get_shared_mpris_manager():
"""Get shared MPRIS manager instance to reduce memory usage."""
global _shared_mpris_manager
@@ -208,10 +208,10 @@ class PlayerBoxStack(Box):
from gi.repository import GdkPixbuf
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
fallback_cover_path, 60, 60, True
fallback_cover_path, 70, 70, True
)
album_cover_image.set_from_pixbuf(pixbuf)
album_cover_image.set_size_request(60, 60)
album_cover_image.set_size_request(70, 70)
except Exception as e:
logger.warning(f"Failed to load fallback image in no-media box: {e}")
@@ -219,7 +219,7 @@ class PlayerBoxStack(Box):
name="macos-album-image",
children=[album_cover_image],
)
album_cover.set_size_request(60, 60)
album_cover.set_size_request(70, 70)
image_stack = Box(h_align="start", v_align="center", name="player-image-stack")
image_stack.children = [album_cover]
@@ -354,7 +354,6 @@ class PlayerBoxStack(Box):
self._update_all_player_buttons()
def on_new_player(self, mpris_manager, player):
player_name = player.props.player_name
# if player_name in self.config.get("ignore", []):
# return
@@ -494,7 +493,7 @@ class PlayerBox(Box):
self.player_stack = player_stack
self.fallback_cover_path = f"{data.HOME_DIR}/.current.wall"
self.image_size = 60 # Smaller album art for compact layout
self.image_size = 70 # Medium album art size for expanded player
self.icon_size = 15
# State
@@ -523,7 +522,7 @@ class PlayerBox(Box):
label="No Title",
name="macos-player-title",
justification="left",
max_chars_width=25,
max_chars_width=30,
ellipsization="end",
h_align="start",
h_expand=True,
@@ -539,6 +538,15 @@ class PlayerBox(Box):
h_expand=True,
visible=True,
)
self.track_album = Label(
label="No Album",
name="macos-player-album",
justification="left",
max_chars_width=25,
ellipsization="end",
h_align="start",
visible=True, # Hide artist and album when no media
)
# Use Image widget instead of CSS background for more reliable image display
self.album_cover_image = Image(
@@ -551,10 +559,10 @@ class PlayerBox(Box):
from gi.repository import GdkPixbuf
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
self.fallback_cover_path, 60, 60, True
self.fallback_cover_path, 70, 70, True
)
self.album_cover_image.set_from_pixbuf(pixbuf)
self.album_cover_image.set_size_request(60, 60)
self.album_cover_image.set_size_request(70, 70)
except Exception as e:
logger.warning(f"Failed to load fallback image: {e}")
@@ -563,7 +571,7 @@ class PlayerBox(Box):
name="macos-album-image",
children=[self.album_cover_image],
)
self.album_cover.set_size_request(60, 60)
self.album_cover.set_size_request(70, 70)
self.image_stack = Box(
h_align="start",
@@ -573,6 +581,20 @@ class PlayerBox(Box):
)
self.image_stack.children = [*self.image_stack.children, self.album_cover]
self.app_icon = Box(
children=Image(
icon_name=self.player.player_name, name="player-app-icon", icon_size=20
),
h_align="end",
v_align="end",
tooltip_text=self.player.player_name, # type: ignore
)
self.image = Overlay(
child=self.image_stack,
overlays=[
self.app_icon,
],
)
# Seek bar should not update automatically during user interaction
self._user_seeking = False
@@ -657,8 +679,7 @@ class PlayerBox(Box):
children=[
self.track_title,
self.track_artist,
self.seek_box,
self.controls_box, # Controls now inline with track info
self.track_album,
],
)
@@ -681,6 +702,15 @@ class PlayerBox(Box):
re.sub(r"\r?\n", " ", x) if x != "" and x is not None else "No Artist"
), # type: ignore
)
self.player.bind_property(
"album",
self.track_album,
"label",
GObject.BindingFlags.DEFAULT,
lambda _, x: (
re.sub(r"\r?\n", " ", x) if x != "" and x is not None else "No Album"
), # type: ignore
)
# Player switcher buttons box (compact, minimal space)
self.stack_buttons_box = Box(
@@ -690,7 +720,7 @@ class PlayerBox(Box):
spacing=4, # Reduced spacing
orientation="v", # Vertical layout for compactness
h_align="end",
v_align="start",
v_align="center",
)
self.stack_buttons_box.hide() # Initially hidden
@@ -725,18 +755,34 @@ class PlayerBox(Box):
self.next_button,
)
self.box = Box(
orientation="horizontal",
children=[
self.image, # Album art on left (fixed width)
self.track_info, # Contains title, artist, seek bar AND controls (expands)
],
)
self.inner_box = Box(
orientation="v",
h_expand=True,
h_align="fill", # Fill available space
children=[
self.box, # Track info and album art
self.seek_box, # Seek bar with position labels
self.controls_box, # Controls now inline with track info
],
)
# Compact macOS layout: album art on left, expanded track info+controls, minimal switcher
self.outer_box = Box(
name="macos-outer-player-box",
orientation="horizontal",
orientation="h",
spacing=10, # Reduced spacing between elements
h_expand=True,
v_expand=True,
v_align="center",
h_align="fill", # Fill available space
children=[
self.image_stack, # Album art on left (fixed width)
self.track_info, # Contains title, artist, seek bar AND controls (expands)
self.inner_box, # Track info and controls
self.stack_buttons_box, # Compact switcher in corner (fixed width)
],
)
@@ -759,7 +805,7 @@ class PlayerBox(Box):
"""Clean up all resources when the widget is destroyed."""
# Cancel any ongoing downloads immediately
self._download_cancelled = True
# Wait for download thread to finish (with timeout)
if self.current_download_thread and self.current_download_thread.is_alive():
try:
@@ -777,9 +823,9 @@ class PlayerBox(Box):
# Clean up temp files aggressively
self._cleanup_temp_files()
# Clear image references
if hasattr(self, 'album_cover_image'):
if hasattr(self, "album_cover_image"):
try:
self.album_cover_image.set_from_pixbuf(None)
except Exception:
@@ -917,7 +963,7 @@ class PlayerBox(Box):
if image_path and os.path.isfile(image_path):
# Create scaled pixbuf to ensure proper size
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
image_path, 60, 60, True
image_path, 70, 70, True
)
self.album_cover_image.set_from_pixbuf(pixbuf)
# Explicitly clear pixbuf reference to help GC
@@ -925,7 +971,7 @@ class PlayerBox(Box):
else:
# Use fallback image with scaling
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
self.fallback_cover_path, 60, 60, True
self.fallback_cover_path, 70, 70, True
)
self.album_cover_image.set_from_pixbuf(pixbuf)
# Explicitly clear pixbuf reference to help GC
@@ -935,7 +981,7 @@ class PlayerBox(Box):
# Try simple file setting as last resort
try:
self.album_cover_image.set_from_file(self.fallback_cover_path)
self.album_cover_image.set_size_request(60, 60)
self.album_cover_image.set_size_request(70, 70)
except Exception as e2:
logger.error(f"Failed to set fallback image: {e2}")
+29 -20
View File
@@ -556,7 +556,7 @@
/* macOS-style expanded player - more compact */
#macos-outer-player-box {
min-height: 110px; /* Reduced height */
min-width: 420px; /* Slightly wider to accommodate expanded track info */
min-width: 420px; /* Slightly wider to accommodate expanded track info */
border-radius: 12px;
margin: 10px;
padding: 15px; /* Reduced padding */
@@ -571,20 +571,21 @@
}
#macos-album-image {
min-width: 80px;
min-height: 80px;
border-radius: 8px;
min-width: 70px;
min-height: 70px;
border-radius: 9px;
box-shadow: 0 2px 8px alpha(#000, 0.3);
}
#macos-album-cover-image {
min-width: 80px;
min-height: 80px;
border-radius: 8px;
min-width: 70px;
min-height: 70px;
border-radius: 9px;
}
/* Track info container that expands to fill available space */
#macos-track-info {
margin-top: 5px;
margin-left: 15px;
margin-right: 15px;
}
@@ -598,11 +599,18 @@
#macos-player-artist {
font-weight: 400;
margin-top: -2px;
font-size: 13px;
color: alpha(#fff, 0.8);
margin-bottom: 8px;
color: alpha(#999, 0.8);
}
#macos-player-album {
font-weight: 400;
margin-top: -4px;
font-size: 13px;
color: alpha(#999, 0.8);
margin-bottom: 8px;
}
/* macOS seek bar styling */
#macos-seek-bar {
background-color: transparent;
@@ -612,6 +620,7 @@
#macos-seek-bar trough {
min-width: 200px;
min-height: 2px;
border-radius: 2px;
background-color: alpha(#fff, 0.25);
@@ -627,16 +636,16 @@
#macos-seek-bar slider {
background: #ffffff;
border: none;
border-radius: 50%;
min-width: 12px;
min-height: 12px;
margin: -4px;
border-radius: 20%;
min-width: 1px;
min-height: 8px;
margin: -3px;
box-shadow: 0 1px 3px alpha(#000, 0.3);
transition: all 0.1s ease;
}
#macos-seek-bar slider:hover {
min-width: 14px;
min-width: 4px;
min-height: 14px;
margin: -5px;
box-shadow: 0 2px 6px alpha(#000, 0.4);
@@ -645,13 +654,13 @@
#macos-position-label,
#macos-length-label {
font-size: 11px;
color: alpha(#fff, 0.7);
color: alpha(#999, 0.9);
font-weight: 400;
}
/* macOS control buttons - more compact */
#macos-button-box {
margin-top: 6px; /* Reduced top margin */
margin-top: -1px; /* Reduced top margin */
}
#macos-control-button {
@@ -693,12 +702,12 @@
.macos-switcher-dot {
background: alpha(#fff, 0.3);
border: none;
/* border: none; */
border-radius: 50%;
min-width: 6px; /* Smaller dots */
min-height: 6px;
min-width: 12px; /* Smaller dots */
min-height: 12px;
margin: 2px; /* Reduced margins */
transition: all 0.2s ease;
/* transition: all 0.2s ease; */
}
.macos-switcher-dot:hover {
+9 -9
View File
@@ -1,8 +1,8 @@
#player-stack-button {
/* border-radius: 5px; */
/* min-width: 7px; */
/* min-height: 7px; */
/* margin: 10px 3px; */
border-radius: 5px;
min-width: 7px;
min-height: 7px;
margin: 10px 3px;
}
#button-box-c {
@@ -22,8 +22,8 @@
}
#outer-player-box {
min-height: 100px;
min-width: 300px;
min-height: 110px;
min-width: 320px;
border-radius: 10px;
margin: 0 6px;
background-color: alpha(#000, 0.3);
@@ -32,7 +32,7 @@
#outer-player-box-c {
min-height: 55px;
min-width: 220px;
min-width: 260px;
border-radius: 8px;
/* margin: 0 6px; */
/* background-color: alpha(#000, 0.3); */
@@ -126,12 +126,12 @@
border-radius: 5px;
}
.album-image {
min-width: 75px;
min-width: 70px;
min-height: 70px;
background-position: center;
background-size: cover;
margin-left: 12px;
border-radius: 5px;
border-radius: 9px;
}
#seek-bar slider {