Final ExpandedPlayer Layout
This commit is contained in:
1 parent
209df5d91a
commit
f1993ef473
3 files changed
+106
-51
No files matched your search
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user