Fix Expanded Player
This commit is contained in:
1 parent
6895b346cd
commit
cc5a116efb
5 files changed
+421
-193
No files matched your search
@@ -188,9 +188,27 @@ class PlayerBoxStack(Box):
|
||||
"""Create a placeholder box for when no media is playing."""
|
||||
fallback_cover_path = f"{data.HOME_DIR}/.current.wall"
|
||||
|
||||
# Album cover with fallback image
|
||||
album_cover = Box(style_classes="album-image")
|
||||
album_cover.set_style(f"background-image:url('{fallback_cover_path}')")
|
||||
# Album cover with fallback image using Image widget
|
||||
album_cover_image = Image(
|
||||
name="macos-album-cover-image",
|
||||
pixbuf=None,
|
||||
)
|
||||
|
||||
try:
|
||||
from gi.repository import GdkPixbuf
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||
fallback_cover_path, 80, 80, True
|
||||
)
|
||||
album_cover_image.set_from_pixbuf(pixbuf)
|
||||
album_cover_image.set_size_request(80, 80)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to load fallback image in no-media box: {e}")
|
||||
|
||||
album_cover = Box(
|
||||
name="macos-album-image",
|
||||
children=[album_cover_image],
|
||||
)
|
||||
album_cover.set_size_request(80, 80)
|
||||
|
||||
image_stack = Box(h_align="start", v_align="center", name="player-image-stack")
|
||||
image_stack.children = [album_cover]
|
||||
@@ -465,7 +483,7 @@ class PlayerBox(Box):
|
||||
self.player_stack = player_stack
|
||||
self.fallback_cover_path = f"{data.HOME_DIR}/.current.wall"
|
||||
|
||||
self.image_size = 100 # Smaller album art
|
||||
self.image_size = 80 # Large album art for macOS style
|
||||
self.icon_size = 15
|
||||
|
||||
# State
|
||||
@@ -479,7 +497,7 @@ class PlayerBox(Box):
|
||||
self._download_cancelled = False # Flag to cancel downloads
|
||||
self._signal_connections = [] # Track signal connections
|
||||
|
||||
self.album_cover = Box(style_classes="album-image")
|
||||
self.album_cover = Box(style_classes="macos-album-image")
|
||||
self.album_cover.set_style(
|
||||
f"background-image:url('{self.fallback_cover_path}')"
|
||||
)
|
||||
@@ -492,9 +510,9 @@ class PlayerBox(Box):
|
||||
# Track Info
|
||||
self.track_title = Label(
|
||||
label="No Title",
|
||||
name="player-title",
|
||||
name="macos-player-title",
|
||||
justification="left",
|
||||
max_chars_width=35,
|
||||
max_chars_width=30,
|
||||
ellipsization="end",
|
||||
h_align="start",
|
||||
h_expand=True,
|
||||
@@ -502,45 +520,43 @@ class PlayerBox(Box):
|
||||
|
||||
self.track_artist = Label(
|
||||
label="No Artist",
|
||||
name="player-artist",
|
||||
name="macos-player-artist",
|
||||
justification="left",
|
||||
max_chars_width=35,
|
||||
max_chars_width=30,
|
||||
ellipsization="end",
|
||||
h_align="start",
|
||||
h_expand=True,
|
||||
visible=True,
|
||||
)
|
||||
|
||||
self.track_album = Label(
|
||||
label="No Album",
|
||||
name="player-album",
|
||||
justification="left",
|
||||
max_chars_width=35,
|
||||
ellipsization="end",
|
||||
h_align="start",
|
||||
h_expand=True,
|
||||
visible=True,
|
||||
# Use Image widget instead of CSS background for more reliable image display
|
||||
self.album_cover_image = Image(
|
||||
name="macos-album-cover-image",
|
||||
pixbuf=None,
|
||||
)
|
||||
|
||||
# Set fallback image immediately with proper scaling
|
||||
try:
|
||||
from gi.repository import GdkPixbuf
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||
self.fallback_cover_path, 80, 80, True
|
||||
)
|
||||
self.album_cover_image.set_from_pixbuf(pixbuf)
|
||||
self.album_cover_image.set_size_request(80, 80)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to load fallback image: {e}")
|
||||
|
||||
# Container box for styling with fixed size
|
||||
self.album_cover = Box(
|
||||
name="macos-album-image",
|
||||
children=[self.album_cover_image],
|
||||
)
|
||||
self.album_cover.set_size_request(80, 80)
|
||||
|
||||
self.track_artist = Label(
|
||||
label="No Artist",
|
||||
name="player-artist",
|
||||
justification="left",
|
||||
max_chars_width=25,
|
||||
ellipsization="end",
|
||||
h_align="start",
|
||||
visible=True,
|
||||
)
|
||||
|
||||
self.track_album = Label(
|
||||
label="No Album",
|
||||
name="player-album",
|
||||
justification="left",
|
||||
max_chars_width=25,
|
||||
ellipsization="end",
|
||||
h_align="start",
|
||||
visible=True,
|
||||
self.image_stack = Box(
|
||||
h_align="start", v_align="start", name="macos-player-image-stack"
|
||||
)
|
||||
self.image_stack.children = [*self.image_stack.children, self.album_cover]
|
||||
|
||||
# Seek bar should not update automatically during user interaction
|
||||
self._user_seeking = False
|
||||
@@ -550,7 +566,7 @@ class PlayerBox(Box):
|
||||
min_value=0,
|
||||
max_value=100,
|
||||
increments=(1, 1),
|
||||
name="apple-seek-bar",
|
||||
name="macos-seek-bar",
|
||||
size=1,
|
||||
h_expand=True,
|
||||
)
|
||||
@@ -559,6 +575,76 @@ class PlayerBox(Box):
|
||||
self.seek_bar.connect("button-release-event", self._on_seek_end)
|
||||
self.player.bind("can-seek", "sensitive", self.seek_bar)
|
||||
|
||||
# Position and length labels for seek bar
|
||||
self.position_label = Label(
|
||||
label="0:00",
|
||||
name="macos-position-label",
|
||||
justification="left",
|
||||
h_align="start",
|
||||
)
|
||||
|
||||
self.length_label = Label(
|
||||
label="0:00",
|
||||
name="macos-length-label",
|
||||
justification="right",
|
||||
h_align="end",
|
||||
)
|
||||
|
||||
# Labels box for position and length below seek bar
|
||||
self.labels_box = Box(
|
||||
name="macos-labels-box",
|
||||
orientation="h",
|
||||
children=[
|
||||
self.position_label,
|
||||
Box(h_expand=True), # Spacer to push labels to ends
|
||||
self.length_label,
|
||||
],
|
||||
)
|
||||
|
||||
# Seek bar with position labels below
|
||||
self.seek_box = Box(
|
||||
name="macos-seek-box",
|
||||
orientation="v",
|
||||
spacing=2,
|
||||
children=[
|
||||
self.seek_bar,
|
||||
self.labels_box,
|
||||
],
|
||||
)
|
||||
|
||||
# Define buttons first
|
||||
self.button_box = Box(
|
||||
name="macos-button-box",
|
||||
h_align="center",
|
||||
spacing=15, # Wider spacing for macOS look
|
||||
)
|
||||
|
||||
# Define controls_box BEFORE using it in track_info
|
||||
self.controls_box = Box(
|
||||
name="macos-player-controls",
|
||||
orientation="v",
|
||||
spacing=8,
|
||||
h_align="center",
|
||||
children=[self.button_box],
|
||||
)
|
||||
|
||||
# Track info with inline controls - more compact layout
|
||||
self.track_info = Box(
|
||||
name="macos-track-info",
|
||||
spacing=6, # Reduced spacing
|
||||
orientation="v",
|
||||
v_align="start",
|
||||
h_align="start",
|
||||
h_expand=True,
|
||||
children=[
|
||||
self.track_title,
|
||||
self.track_artist,
|
||||
self.seek_box,
|
||||
self.controls_box, # Controls now inline with track info
|
||||
],
|
||||
)
|
||||
|
||||
# Bind player properties
|
||||
self.player.bind_property(
|
||||
"title",
|
||||
self.track_title,
|
||||
@@ -578,100 +664,25 @@ class PlayerBox(Box):
|
||||
), # 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
|
||||
)
|
||||
|
||||
# Position and length labels for seek bar
|
||||
self.position_label = Label(
|
||||
label="0:00",
|
||||
name="position-label",
|
||||
justification="left",
|
||||
h_align="start",
|
||||
)
|
||||
|
||||
self.length_label = Label(
|
||||
label="0:00",
|
||||
name="length-label",
|
||||
justification="right",
|
||||
h_align="end",
|
||||
)
|
||||
|
||||
# Labels box for position and length below seek bar
|
||||
self.labels_box = Box(
|
||||
name="labels-box",
|
||||
orientation="h",
|
||||
children=[
|
||||
self.position_label,
|
||||
Box(h_expand=True), # Spacer to push labels to ends
|
||||
self.length_label,
|
||||
],
|
||||
)
|
||||
|
||||
# Seek bar with position labels below
|
||||
self.seek_box = Box(
|
||||
name="seek-box",
|
||||
orientation="v",
|
||||
spacing=1,
|
||||
children=[
|
||||
self.seek_bar,
|
||||
self.labels_box,
|
||||
],
|
||||
)
|
||||
|
||||
self.track_info = Box(
|
||||
name="track-info",
|
||||
spacing=3,
|
||||
h_expand=True,
|
||||
orientation="v",
|
||||
v_align="start",
|
||||
h_align="fill",
|
||||
children=[
|
||||
self.track_title,
|
||||
self.track_artist,
|
||||
self.track_album,
|
||||
self.seek_box,
|
||||
],
|
||||
)
|
||||
|
||||
# Buttons
|
||||
self.button_box = Box(
|
||||
name="button-box",
|
||||
h_align="center",
|
||||
spacing=2,
|
||||
)
|
||||
|
||||
# Stack switcher buttons box
|
||||
# Player switcher buttons box (compact, minimal space)
|
||||
self.stack_buttons_box = Box(
|
||||
h_expand=False,
|
||||
v_expand=True,
|
||||
name="stack-buttons-box",
|
||||
spacing=4,
|
||||
orientation="v",
|
||||
h_align="center",
|
||||
v_align="center",
|
||||
v_expand=False,
|
||||
name="macos-stack-buttons-box",
|
||||
spacing=4, # Reduced spacing
|
||||
orientation="h", # Horizontal layout for compactness
|
||||
h_align="end",
|
||||
v_align="start",
|
||||
)
|
||||
self.stack_buttons_box.hide() # Initially hidden
|
||||
|
||||
self.controls_box = CenterBox(
|
||||
name="player-controls",
|
||||
h_expand=True,
|
||||
center_children=self.button_box,
|
||||
)
|
||||
|
||||
self.skip_next_icon = Image(icon_name="player_fwd")
|
||||
self.skip_prev_icon = Image(icon_name="player_rew")
|
||||
self.shuffle_icon = Image(icon_name="shuffle")
|
||||
self.play_pause_icon = Image(icon_name="player_pause")
|
||||
|
||||
self.play_pause_button = Button(
|
||||
name="player-button",
|
||||
name="macos-play-button",
|
||||
child=self.play_pause_icon,
|
||||
on_clicked=self.player.play_pause,
|
||||
)
|
||||
@@ -679,77 +690,52 @@ class PlayerBox(Box):
|
||||
self.player.bind_property("can_pause", self.play_pause_button, "sensitive")
|
||||
|
||||
self.next_button = Button(
|
||||
style_classes=["player-button"],
|
||||
name="macos-control-button",
|
||||
child=self.skip_next_icon,
|
||||
on_clicked=self._on_player_next,
|
||||
)
|
||||
self.player.bind_property("can_go_next", self.next_button, "sensitive")
|
||||
|
||||
self.prev_button = Button(
|
||||
style_classes=["player-button"],
|
||||
name="macos-control-button",
|
||||
child=self.skip_prev_icon,
|
||||
on_clicked=self._on_player_prev,
|
||||
)
|
||||
self.shuffle_button = Button(
|
||||
style_classes=["player-button"],
|
||||
child=self.shuffle_icon,
|
||||
on_clicked=self.player.toggle_shuffle,
|
||||
)
|
||||
self.player.bind_property("can_shuffle", self.shuffle_button, "sensitive")
|
||||
|
||||
self.button_box.children = (
|
||||
# self.shuffle_button,
|
||||
self.prev_button,
|
||||
self.play_pause_button,
|
||||
self.next_button,
|
||||
)
|
||||
self.player_info_box = Box(
|
||||
name="player-info-box",
|
||||
h_expand=True,
|
||||
v_align="center",
|
||||
h_align="fill",
|
||||
orientation="v",
|
||||
children=[self.track_info, self.controls_box],
|
||||
)
|
||||
|
||||
self.inner_box = Box(
|
||||
name="inner-player-box",
|
||||
v_align="center",
|
||||
h_align="start",
|
||||
)
|
||||
# resize the inner box
|
||||
# Compact macOS layout: album art on left, expanded track info+controls, minimal switcher
|
||||
self.outer_box = Box(
|
||||
name="outer-player-box",
|
||||
h_expand=True,
|
||||
name="macos-outer-player-box",
|
||||
orientation="horizontal",
|
||||
spacing=15,
|
||||
h_align="start",
|
||||
children=[
|
||||
self.image_stack,
|
||||
self.player_info_box,
|
||||
self.image_stack, # Album art on left
|
||||
Box(
|
||||
name="macos-main-section",
|
||||
orientation="v",
|
||||
spacing=0,
|
||||
h_expand=True,
|
||||
v_align="center",
|
||||
children=[
|
||||
# Header with player switcher in corner
|
||||
Box(
|
||||
children=Image(
|
||||
icon_name=self.player.player_name, icon_size=18
|
||||
),
|
||||
h_align="end",
|
||||
h_expand=False,
|
||||
v_align="start",
|
||||
style="margin-top: 5px; margin-right: 10px;",
|
||||
tooltip_text=self.player.player_name, # type: ignore
|
||||
),
|
||||
Box(
|
||||
children=self.stack_buttons_box,
|
||||
h_align="end",
|
||||
v_expand=True,
|
||||
v_align="center",
|
||||
h_expand=False,
|
||||
style="margin-right: 15px;",
|
||||
orientation="h",
|
||||
h_expand=True,
|
||||
children=[
|
||||
Box(h_expand=True), # Spacer
|
||||
self.stack_buttons_box, # Compact switcher in corner
|
||||
],
|
||||
),
|
||||
# Main content area
|
||||
self.track_info, # Contains title, artist, seek bar AND controls now
|
||||
],
|
||||
),
|
||||
],
|
||||
h_align="start",
|
||||
)
|
||||
|
||||
self.children = [*self.children, self.outer_box]
|
||||
@@ -794,9 +780,7 @@ class PlayerBox(Box):
|
||||
def update_buttons(self, player_buttons, show_buttons):
|
||||
"""Update the stack switcher buttons in this player box"""
|
||||
logger.info(
|
||||
f"[PlayerBox] update_buttons called: show_buttons={
|
||||
show_buttons
|
||||
}, num_buttons={len(player_buttons)}"
|
||||
f"[PlayerBox] update_buttons called: show_buttons={show_buttons}, num_buttons={len(player_buttons)}"
|
||||
)
|
||||
|
||||
# Clear existing buttons
|
||||
@@ -808,37 +792,28 @@ class PlayerBox(Box):
|
||||
|
||||
if show_buttons and len(player_buttons) > 1:
|
||||
logger.info(f"[PlayerBox] Creating {len(player_buttons)} stack buttons")
|
||||
# Create simple dot indicators for each player
|
||||
# Create macOS-style dot indicators for each player
|
||||
for i, button in enumerate(player_buttons):
|
||||
# Create a more visible dot button
|
||||
# Create a macOS-style dot button
|
||||
dot_button = Button(
|
||||
name="player-stack-button",
|
||||
style="min-width: 5px; min-height: 5px; border-radius: 8px; margin: 4px; background-color: #666; border: 1px solid #999;",
|
||||
name="macos-player-switcher-dot",
|
||||
style_classes=["macos-switcher-dot"],
|
||||
)
|
||||
|
||||
# Set active state based on original button
|
||||
if button.get_style_context().has_class("active"):
|
||||
dot_button.add_style_class("active")
|
||||
dot_button.set_style(
|
||||
"min-width: 5px; min-height: 5px; border-radius: 8px; margin: 4px; background-color: #fff; border: 1px solid #ccc;"
|
||||
)
|
||||
|
||||
# Connect click handler to switch to this player
|
||||
def make_click_handler(index):
|
||||
return lambda *_: self.player_stack.on_player_clicked_by_index(
|
||||
index
|
||||
)
|
||||
return lambda *_: self.player_stack.on_player_clicked_by_index(index)
|
||||
|
||||
dot_button.connect("clicked", make_click_handler(i))
|
||||
self.stack_buttons_box.children = [
|
||||
*self.stack_buttons_box.children,
|
||||
dot_button,
|
||||
]
|
||||
logger.info(
|
||||
f"[PlayerBox] Added dot button {i}, total children: {
|
||||
len(self.stack_buttons_box.get_children())
|
||||
}"
|
||||
)
|
||||
logger.info(f"[PlayerBox] Added dot button {i}")
|
||||
|
||||
self.stack_buttons_box.show_all()
|
||||
logger.info("[PlayerBox] Stack buttons box shown")
|
||||
@@ -917,15 +892,37 @@ class PlayerBox(Box):
|
||||
self.play_pause_icon.set_from_icon_name("player_pause")
|
||||
|
||||
def _update_image(self, image_path):
|
||||
if image_path and os.path.isfile(image_path):
|
||||
self.album_cover.set_style(f"background-image:url('{image_path}')")
|
||||
else:
|
||||
self.album_cover.set_style(
|
||||
f"background-image:url('{self.fallback_cover_path}')"
|
||||
)
|
||||
try:
|
||||
from gi.repository import GdkPixbuf
|
||||
|
||||
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, 80, 80, True
|
||||
)
|
||||
self.album_cover_image.set_from_pixbuf(pixbuf)
|
||||
else:
|
||||
# Use fallback image with scaling
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||
self.fallback_cover_path, 80, 80, True
|
||||
)
|
||||
self.album_cover_image.set_from_pixbuf(pixbuf)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to update album cover image: {e}")
|
||||
# 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(80, 80)
|
||||
except Exception as e2:
|
||||
logger.error(f"Failed to set fallback image: {e2}")
|
||||
|
||||
def _set_image(self, *_):
|
||||
art_url = self.player.arturl
|
||||
|
||||
# If no art URL or empty/None, use fallback
|
||||
if not art_url:
|
||||
self._update_image(None)
|
||||
return
|
||||
|
||||
parsed = urllib.parse.urlparse(art_url)
|
||||
if parsed.scheme == "file":
|
||||
|
||||
@@ -447,6 +447,9 @@ class PlayerBox(Box):
|
||||
self.control_center = control_center
|
||||
self.fallback_cover_path = f"{data.HOME_DIR}/.current.wall"
|
||||
|
||||
# Add controls_box attribute early for compatibility
|
||||
self.controls_box = Box(name="temp-controls-box") # Temporary placeholder
|
||||
|
||||
self.image_size = 50
|
||||
self.icon_size = 15
|
||||
|
||||
@@ -585,6 +588,10 @@ class PlayerBox(Box):
|
||||
self.play_pause_button,
|
||||
self.next_button,
|
||||
)
|
||||
|
||||
# Assign button_box to controls_box for compatibility
|
||||
self.controls_box = self.button_box
|
||||
|
||||
self.player_info_box = Box(
|
||||
name="player-info-box-c",
|
||||
v_align="center",
|
||||
@@ -693,6 +700,8 @@ class PlayerBox(Box):
|
||||
self.control_center.open_expanded_player()
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to handle outer box click: {e}")
|
||||
import traceback
|
||||
logger.error(f"Full traceback: {traceback.format_exc()}")
|
||||
|
||||
def update_buttons(self, player_buttons, show_buttons):
|
||||
# """Update the stack switcher buttons in this player box"""
|
||||
|
||||
@@ -429,6 +429,8 @@ class Dock(Window):
|
||||
button.connect("drag-data-get", self.on_drag_data_get)
|
||||
button.connect("drag-data-received", self.on_drag_data_received)
|
||||
button.connect("enter-notify-event", self._on_child_enter)
|
||||
button.connect("enter-notify-event", self._on_icon_hover_enter)
|
||||
button.connect("leave-notify-event", self._on_icon_hover_leave)
|
||||
overlay = Overlay(
|
||||
overlays=Label(
|
||||
label=workspace,
|
||||
@@ -480,6 +482,69 @@ class Dock(Window):
|
||||
f"hyprctl dispatch focuswindow address:{instance['address']}"
|
||||
)
|
||||
|
||||
def _on_icon_hover_enter(self, widget, event):
|
||||
"""Handle icon hover enter - enlarge the icon"""
|
||||
widget.add_style_class("dock-icon-hover")
|
||||
# Find the image widget inside the button and scale it
|
||||
dock_icon = self._find_dock_icon_image(widget)
|
||||
if dock_icon:
|
||||
# Create a larger version of the icon
|
||||
enlarged_size = int(self.icon_size * 1.3) # 30% larger
|
||||
if hasattr(widget, 'desktop_app') and widget.desktop_app:
|
||||
enlarged_pixbuf = widget.desktop_app.get_icon_pixbuf(size=enlarged_size)
|
||||
if enlarged_pixbuf:
|
||||
dock_icon.set_from_pixbuf(enlarged_pixbuf)
|
||||
elif hasattr(widget, 'app_identifier'):
|
||||
id_value = (
|
||||
widget.app_identifier["name"]
|
||||
if isinstance(widget.app_identifier, dict)
|
||||
else widget.app_identifier
|
||||
)
|
||||
enlarged_pixbuf = self.icon_resolver.get_icon_pixbuf(id_value, enlarged_size)
|
||||
if enlarged_pixbuf:
|
||||
dock_icon.set_from_pixbuf(enlarged_pixbuf)
|
||||
return False
|
||||
|
||||
def _on_icon_hover_leave(self, widget, event):
|
||||
"""Handle icon hover leave - restore original icon size"""
|
||||
widget.remove_style_class("dock-icon-hover")
|
||||
# Find the image widget inside the button and restore normal size
|
||||
dock_icon = self._find_dock_icon_image(widget)
|
||||
if dock_icon:
|
||||
# Restore original size icon
|
||||
if hasattr(widget, 'desktop_app') and widget.desktop_app:
|
||||
normal_pixbuf = widget.desktop_app.get_icon_pixbuf(size=self.icon_size)
|
||||
if normal_pixbuf:
|
||||
dock_icon.set_from_pixbuf(normal_pixbuf)
|
||||
elif hasattr(widget, 'app_identifier'):
|
||||
id_value = (
|
||||
widget.app_identifier["name"]
|
||||
if isinstance(widget.app_identifier, dict)
|
||||
else widget.app_identifier
|
||||
)
|
||||
normal_pixbuf = self.icon_resolver.get_icon_pixbuf(id_value, self.icon_size)
|
||||
if normal_pixbuf:
|
||||
dock_icon.set_from_pixbuf(normal_pixbuf)
|
||||
return False
|
||||
|
||||
def _find_dock_icon_image(self, button_widget):
|
||||
"""Find the Image widget inside a dock button"""
|
||||
def find_image_recursive(widget):
|
||||
if isinstance(widget, Image):
|
||||
return widget
|
||||
if hasattr(widget, 'get_children'):
|
||||
for child in widget.get_children():
|
||||
result = find_image_recursive(child)
|
||||
if result:
|
||||
return result
|
||||
elif hasattr(widget, 'get_child'):
|
||||
child = widget.get_child()
|
||||
if child:
|
||||
return find_image_recursive(child)
|
||||
return None
|
||||
|
||||
return find_image_recursive(button_widget)
|
||||
|
||||
def _on_child_enter(self, widget, event):
|
||||
self.is_mouse_over_dock_area = True
|
||||
if self.hide_id:
|
||||
|
||||
+152
-3
@@ -226,9 +226,7 @@
|
||||
border-radius: 16px;
|
||||
min-width: 16px;
|
||||
min-height: 8px;
|
||||
transition:
|
||||
background-color 0.1s cubic-bezier(0.5, 0.25, 0, 1.25),
|
||||
transform 0.25s cubic-bezier(0.5, 0.25, 0, 1.25);
|
||||
transition: background-color 0.1s cubic-bezier(0.5, 0.25, 0, 1.25);
|
||||
}
|
||||
|
||||
#toggle-button:checked {
|
||||
@@ -554,3 +552,154 @@
|
||||
0 1px 3px alpha(#000, 0.3),
|
||||
0 0 0 2px alpha(#007aff, 0.5);
|
||||
}
|
||||
|
||||
/* macOS-style expanded player - more compact */
|
||||
#macos-outer-player-box {
|
||||
min-height: 110px; /* Reduced height */
|
||||
min-width: 380px;
|
||||
border-radius: 12px;
|
||||
margin: 10px;
|
||||
padding: 15px; /* Reduced padding */
|
||||
background-color: alpha(#000, 0.4);
|
||||
box-shadow:
|
||||
0 4px 16px alpha(#000, 0.25),
|
||||
inset 0 0 0 1px alpha(#fff, 0.1);
|
||||
}
|
||||
|
||||
#macos-main-section {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#macos-album-image {
|
||||
min-width: 80px;
|
||||
min-height: 80px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px alpha(#000, 0.3);
|
||||
}
|
||||
|
||||
#macos-album-cover-image {
|
||||
min-width: 80px;
|
||||
min-height: 80px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
#macos-player-title {
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
#macos-player-artist {
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
color: alpha(#fff, 0.8);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* macOS seek bar styling */
|
||||
#macos-seek-bar {
|
||||
background-color: transparent;
|
||||
margin: 8px 0 4px 0;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
#macos-seek-bar trough {
|
||||
min-width: 200px;
|
||||
min-height: 4px;
|
||||
border-radius: 2px;
|
||||
background-color: alpha(#fff, 0.25);
|
||||
border: none;
|
||||
}
|
||||
|
||||
#macos-seek-bar highlight {
|
||||
background: #ffffff;
|
||||
border-radius: 2px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#macos-seek-bar slider {
|
||||
background: #ffffff;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
min-width: 12px;
|
||||
min-height: 12px;
|
||||
margin: -4px;
|
||||
box-shadow: 0 1px 3px alpha(#000, 0.3);
|
||||
transition: all 0.1s ease;
|
||||
}
|
||||
|
||||
#macos-seek-bar slider:hover {
|
||||
min-width: 14px;
|
||||
min-height: 14px;
|
||||
margin: -5px;
|
||||
box-shadow: 0 2px 6px alpha(#000, 0.4);
|
||||
}
|
||||
|
||||
#macos-position-label,
|
||||
#macos-length-label {
|
||||
font-size: 11px;
|
||||
color: alpha(#fff, 0.7);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* macOS control buttons - more compact */
|
||||
#macos-button-box {
|
||||
margin-top: 6px; /* Reduced top margin */
|
||||
}
|
||||
|
||||
#macos-control-button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
min-width: 28px; /* Slightly smaller */
|
||||
min-height: 28px;
|
||||
padding: 5px; /* Reduced padding */
|
||||
color: #ffffff;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
#macos-control-button:hover {
|
||||
background: alpha(#fff, 0.1);
|
||||
box-shadow: 0 0 0 1px alpha(#fff, 0.2);
|
||||
}
|
||||
|
||||
#macos-play-button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
min-width: 36px; /* Slightly smaller */
|
||||
min-height: 36px;
|
||||
padding: 7px; /* Reduced padding */
|
||||
color: #ffffff;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
#macos-play-button:hover {
|
||||
background: alpha(#fff, 0.15);
|
||||
box-shadow: 0 0 0 1px alpha(#fff, 0.25);
|
||||
}
|
||||
|
||||
/* macOS player switcher dots - compact horizontal layout */
|
||||
#macos-stack-buttons-box {
|
||||
margin: 2px 5px; /* Minimal margins */
|
||||
}
|
||||
|
||||
.macos-switcher-dot {
|
||||
background: alpha(#fff, 0.3);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
min-width: 6px; /* Smaller dots */
|
||||
min-height: 6px;
|
||||
margin: 2px; /* Reduced margins */
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.macos-switcher-dot:hover {
|
||||
background: alpha(#fff, 0.5);
|
||||
}
|
||||
|
||||
.macos-switcher-dot.active {
|
||||
background: #ffffff;
|
||||
box-shadow: 0 0 0 1px alpha(#fff, 0.3); /* Smaller glow */
|
||||
}
|
||||
+9
-1
@@ -39,12 +39,20 @@
|
||||
}
|
||||
|
||||
#dock-app-button {
|
||||
padding: 4px;
|
||||
padding: 6px;
|
||||
border-radius: 24px;
|
||||
transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
/* box-shadow: 0 0 4px alpha(var(--shadow), 0.5); */
|
||||
/* transition: all 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275); */
|
||||
}
|
||||
|
||||
#dock-app-button.dock-icon-hover {
|
||||
padding: 4px;
|
||||
border-radius: 28px;
|
||||
background-color: alpha(#fff, 0.15);
|
||||
box-shadow: 0 4px 12px alpha(#000, 0.2);
|
||||
}
|
||||
|
||||
#dock-app-button:hover {
|
||||
background-color: var(--surface-bright);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user