Made the Subsonic icons a lot better

This commit is contained in:
Sumner Evans
2020-05-23 01:21:02 -06:00
parent 61dc844000
commit 07076b110f
16 changed files with 102 additions and 78 deletions

View File

@@ -296,6 +296,18 @@ class Adapter(abc.ABC):
""" """
return True return True
@property
@abc.abstractmethod
def ping_status(self) -> bool:
"""
This function should return whether or not the server can be pinged, however it
must do it *instantly*. This function is called *very* often, and even a few
milliseconds delay stacks up quickly and can block the UI thread.
One option is to ping the server every few seconds and cache the result of the
ping and use that as the result of this function.
"""
# Availability Properties # Availability Properties
# These properties determine if what things the adapter can be used to do # These properties determine if what things the adapter can be used to do
# at the current moment. # at the current moment.
@@ -751,6 +763,8 @@ class CachingAdapter(Adapter):
:param is_cache: whether or not the adapter is being used as a cache. :param is_cache: whether or not the adapter is being used as a cache.
""" """
ping_status = True
# Data Ingestion Methods # Data Ingestion Methods
# ================================================================================== # ==================================================================================
class CachedDataKey(Enum): class CachedDataKey(Enum):

View File

@@ -206,6 +206,16 @@ class AdapterManager:
assert AdapterManager._instance assert AdapterManager._instance
return Result(AdapterManager._instance.ground_truth_adapter.initial_sync) return Result(AdapterManager._instance.ground_truth_adapter.initial_sync)
@staticmethod
def ground_truth_adapter_is_networked() -> bool:
assert AdapterManager._instance
return AdapterManager._instance.ground_truth_adapter.is_networked
@staticmethod
def get_ping_status() -> bool:
assert AdapterManager._instance
return AdapterManager._instance.ground_truth_adapter.ping_status
@staticmethod @staticmethod
def shutdown(): def shutdown():
logging.info("AdapterManager shutdown start") logging.info("AdapterManager shutdown start")

View File

@@ -160,6 +160,10 @@ class SubsonicAdapter(Adapter):
logging.exception(f"Could not connect to {self.hostname}") logging.exception(f"Could not connect to {self.hostname}")
self._server_available.value = False self._server_available.value = False
@property
def ping_status(self) -> bool:
return self._server_available.value
@property @property
def can_service_requests(self) -> bool: def can_service_requests(self) -> bool:
return self._server_available.value return self._server_available.value

View File

@@ -55,6 +55,7 @@ class SublimeMusicApp(Gtk.Application):
self.connect("shutdown", self.on_app_shutdown) self.connect("shutdown", self.on_app_shutdown)
player: Player player: Player
exiting: bool = False
def do_startup(self): def do_startup(self):
Gtk.Application.do_startup(self) Gtk.Application.do_startup(self)
@@ -254,6 +255,15 @@ class SublimeMusicApp(Gtk.Application):
inital_sync_result = AdapterManager.initial_sync() inital_sync_result = AdapterManager.initial_sync()
inital_sync_result.add_done_callback(lambda _: self.update_window()) inital_sync_result.add_done_callback(lambda _: self.update_window())
# Start a loop for testing the ping.
def ping_update():
if self.exiting:
return
self.update_window()
GLib.timeout_add(5000, ping_update)
GLib.timeout_add(5000, ping_update)
# Prompt to load the play queue from the server. # Prompt to load the play queue from the server.
if self.app_config.server.sync_enabled: if self.app_config.server.sync_enabled:
self.update_play_state_from_server(prompt_confirm=True) self.update_play_state_from_server(prompt_confirm=True)
@@ -494,7 +504,6 @@ class SublimeMusicApp(Gtk.Application):
): ):
if settings := state_updates.get("__settings__"): if settings := state_updates.get("__settings__"):
for k, v in settings.items(): for k, v in settings.items():
print("SET", k, v)
setattr(self.app_config, k, v) setattr(self.app_config, k, v)
del state_updates["__settings__"] del state_updates["__settings__"]
@@ -828,6 +837,7 @@ class SublimeMusicApp(Gtk.Application):
return False return False
def on_app_shutdown(self, app: "SublimeMusicApp"): def on_app_shutdown(self, app: "SublimeMusicApp"):
self.exiting = True
if glib_notify_exists: if glib_notify_exists:
Notify.uninit() Notify.uninit()

View File

@@ -30,6 +30,8 @@ class PlayerEvent:
PLAY_STATE_CHANGE = 0 PLAY_STATE_CHANGE = 0
VOLUME_CHANGE = 1 VOLUME_CHANGE = 1
STREAM_CACHE_PROGRESS_CHANGE = 2 STREAM_CACHE_PROGRESS_CHANGE = 2
CONNECTING = 3
CONNECTED = 4
type: Type type: Type
playing: Optional[bool] = False playing: Optional[bool] = False
@@ -320,6 +322,7 @@ class ChromecastPlayer(Player):
return ChromecastPlayer.executor.submit(do_get_chromecasts) return ChromecastPlayer.executor.submit(do_get_chromecasts)
def set_playing_chromecast(self, uuid: str): def set_playing_chromecast(self, uuid: str):
self.on_player_event(PlayerEvent(PlayerEvent.Type.CONNECTING))
self.chromecast = next( self.chromecast = next(
cc for cc in ChromecastPlayer.chromecasts if cc.device.uuid == UUID(uuid) cc for cc in ChromecastPlayer.chromecasts if cc.device.uuid == UUID(uuid)
) )
@@ -329,7 +332,8 @@ class ChromecastPlayer(Player):
) )
self.chromecast.register_status_listener(ChromecastPlayer.cast_status_listener) self.chromecast.register_status_listener(ChromecastPlayer.cast_status_listener)
self.chromecast.wait() self.chromecast.wait()
logging.info(f"Using: {self.chromecast.device.friendly_name}") logging.info(f"Connected to Chromecast: {self.chromecast.device.friendly_name}")
self.on_player_event(PlayerEvent(PlayerEvent.Type.CONNECTED))
def __init__( def __init__(
self, self,
@@ -455,7 +459,7 @@ class ChromecastPlayer(Player):
# If it's a local file, then see if we can serve it over the LAN. # If it's a local file, then see if we can serve it over the LAN.
if not stream_scheme: if not stream_scheme:
if self.serve_over_lan: if self.serve_over_lan:
token = base64.b64encode(os.urandom(64)).decode("ascii") token = base64.b64encode(os.urandom(8)).decode("ascii")
for r in (("+", "."), ("/", "-"), ("=", "_")): for r in (("+", "."), ("/", "-"), ("=", "_")):
token = token.replace(*r) token = token.replace(*r)
self.server_thread.set_song_and_token(song.id, token) self.server_thread.set_song_and_token(song.id, token)

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 7.937 7.937" height="30" width="30">
<circle class="success" r="3.385" cy="3.969" cx="3.969"/>
</svg>

After

Width:  |  Height:  |  Size: 157 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 7.937 7.937" height="30" width="30">
<circle class="error" r="3.385" cy="3.969" cx="3.969"/>
</svg>

After

Width:  |  Height:  |  Size: 155 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 7.937 7.937" height="30" width="30">
<circle class="warning" r="3.385" cy="3.969" cx="3.969"/>
</svg>

After

Width:  |  Height:  |  Size: 157 B

View File

@@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="server-online.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
id="svg8"
version="1.1"
viewBox="0 0 7.9374995 7.9374995"
height="30"
width="30">
<defs
id="defs2" />
<sodipodi:namedview
inkscape:window-maximized="1"
inkscape:window-y="44"
inkscape:window-x="0"
inkscape:window-height="1394"
inkscape:window-width="2556"
units="px"
showgrid="false"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="mm"
inkscape:cy="13.255986"
inkscape:cx="24.041419"
inkscape:zoom="22.4"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<circle
r="3.3851781"
cy="3.96875"
cx="3.96875"
id="path835"
style="fill:#18c918;fill-opacity:1;stroke-width:0.34228" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24">
<path d="M6.93 2.13v.04h-.08l-1.39.26c-.15.04-.22.2-.22.38l.22 4.39c0 .22.16.37.34.34l1.69-.57c.11-.03.19-.18.15-.37l-.49-4.17c0-.18-.11-.3-.22-.3zm4.65 4.54c-1.35 0-2.25 0-3.49.68l-2.32.82c-.15.04-.23.19-.27.34a3.6 3.6 0 00-.15 2.1 24 24 0 00-1.46.75c-.45-.71-1.87-.64-1.87.37-.08.5-.42 1.2.22 1.47.3.37-.53.75-.68 1.16-.15.37-.22.75-.7.68-.5.18-.72.63-.34 1.04.37.3 1 0 .9.68.07.49.4.97.6 1.35-.45.37-.38.98-.72 1.43-.26.56.15 1.27.83 1.12a4.73 4.73 0 002.02-.75c3 .82 6.03 1.75 9.13 1.92a6.1 6.1 0 01-.86-4.97l-.02-.21c0-1.02.19-1.62.83-2.25.26-.27.64-.43 1.04-.52a6.1 6.1 0 013.97-1.5 6.01 6.01 0 015.43 3.43 5.5 5.5 0 00-.36-1.94c-.52-1.42-1.87-2.51-3.15-3.26-.75-.38-1.72-.41-2.54-.53l-.27-1.27c.11-.68-.64-.6-1.12-.75l-2.03-.34c-.48-.67-1.87-1.05-2.62-1.05zM5.9 13.05c.38.03.57.67.57 1.83 0 1.1-.23 1.77-.75 2.25-.38.34-.6.3-.83-.18-.45-1.05-.22-2.89.41-3.57.23-.22.42-.37.6-.33zm3.72.22c.56 0 .86.6.93 1.77.04 1.3-.26 2.2-.97 2.73-.34.23-.75.34-.97.23-.3-.12-.64-.98-.68-1.7-.11-1.38.41-2.58 1.27-2.92.13-.06.27-.1.42-.1z" fill="#e4e4e4"/>
<path d="M18.2 13.17A5.23 5.23 0 0013 18.4a5.23 5.23 0 005.24 5.24 5.23 5.23 0 005.23-5.24 5.23 5.23 0 00-5.27-5.23z" fill="#c70e0e" class="success"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"> <path fill="#e4e4e4" d="M6.93 2.13v.04h-.08l-1.39.26c-.15.04-.22.2-.22.38l.22 4.39c0 .22.16.37.34.34l1.69-.57c.11-.03.19-.18.15-.37l-.49-4.17c0-.18-.11-.3-.22-.3zm4.65 4.54c-1.35 0-2.25 0-3.49.68l-2.32.82c-.15.04-.23.19-.27.34a3.6 3.6 0 00-.15 2.1 24 24 0 00-1.46.75c-.45-.71-1.87-.64-1.87.37-.08.5-.42 1.2.22 1.47.3.37-.53.75-.68 1.16-.15.37-.22.75-.7.68-.5.18-.72.63-.34 1.04.37.3 1 0 .9.68.07.49.4.97.6 1.35-.45.37-.38.98-.72 1.43-.26.56.15 1.27.83 1.12a4.73 4.73 0 002.02-.75c3 .82 6.03 1.75 9.13 1.92a6.1 6.1 0 01-.86-4.97l-.02-.21c0-1.02.19-1.62.83-2.25.26-.27.64-.43 1.04-.52a6.1 6.1 0 013.97-1.5 6.01 6.01 0 015.43 3.43 5.5 5.5 0 00-.36-1.94c-.52-1.42-1.87-2.51-3.15-3.26-.75-.38-1.72-.41-2.54-.53l-.27-1.27c.11-.68-.64-.6-1.12-.75l-2.03-.34c-.48-.67-1.87-1.05-2.62-1.05zM5.9 13.05c.38.03.57.67.57 1.83 0 1.1-.23 1.77-.75 2.25-.38.34-.6.3-.83-.18-.45-1.05-.22-2.89.41-3.57.23-.22.42-.37.6-.33zm3.72.22c.56 0 .86.6.93 1.77.04 1.3-.26 2.2-.97 2.73-.34.23-.75.34-.97.23-.3-.12-.64-.98-.68-1.7-.11-1.38.41-2.58 1.27-2.92.13-.06.27-.1.42-.1z"/> <path class="error" fill="#c70e0e" d="M18.2 13.17A5.23 5.23 0 0013 18.4a5.23 5.23 0 005.24 5.24 5.23 5.23 0 005.23-5.24 5.23 5.23 0 00-5.23-5.23 5.23 5.23 0 00-.04 0zM16 14.85l2.24 2.24 2.24-2.24 1.31 1.3-2.24 2.25 2.24 2.25-1.3 1.3-2.25-2.24L16 21.96l-1.31-1.31 2.24-2.25-2.24-2.24z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" height="24" width="24">
<path d="M6.93 2.13v.04h-.08l-1.39.26c-.15.04-.22.2-.22.38l.22 4.39c0 .22.16.37.34.34l1.69-.57c.11-.03.19-.18.15-.37l-.49-4.17c0-.18-.11-.3-.22-.3zm4.65 4.54c-1.35 0-2.25 0-3.49.68l-2.32.82c-.15.04-.23.19-.27.34a3.6 3.6 0 00-.15 2.1 24 24 0 00-1.46.75c-.45-.71-1.87-.64-1.87.37-.08.5-.42 1.2.22 1.47.3.37-.53.75-.68 1.16-.15.37-.22.75-.7.68-.5.18-.72.63-.34 1.04.37.3 1 0 .9.68.07.49.4.97.6 1.35-.45.37-.38.98-.72 1.43-.26.56.15 1.27.83 1.12a4.73 4.73 0 002.02-.75c3 .82 6.03 1.75 9.13 1.92a6.1 6.1 0 01-.86-4.97l-.02-.21c0-1.02.19-1.62.83-2.25.26-.27.64-.43 1.04-.52a6.1 6.1 0 013.97-1.5 6.01 6.01 0 015.43 3.43 5.5 5.5 0 00-.36-1.94c-.52-1.42-1.87-2.51-3.15-3.26-.75-.38-1.72-.41-2.54-.53l-.27-1.27c.11-.68-.64-.6-1.12-.75l-2.03-.34c-.48-.67-1.87-1.05-2.62-1.05zM5.9 13.05c.38.03.57.67.57 1.83 0 1.1-.23 1.77-.75 2.25-.38.34-.6.3-.83-.18-.45-1.05-.22-2.89.41-3.57.23-.22.42-.37.6-.33zm3.72.22c.56 0 .86.6.93 1.77.04 1.3-.26 2.2-.97 2.73-.34.23-.75.34-.97.23-.3-.12-.64-.98-.68-1.7-.11-1.38.41-2.58 1.27-2.92.13-.06.27-.1.42-.1z" fill="#e4e4e4"/>
<path d="M18.2 13.17A5.23 5.23 0 0013 18.4a5.23 5.23 0 005.24 5.24 5.23 5.23 0 005.23-5.24 5.23 5.23 0 00-5.27-5.23z" fill="#c70e0e" class="error"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24">
<path d="M6.93 2.13v.04h-.08l-1.39.26c-.15.04-.22.2-.22.38l.22 4.39c0 .22.16.37.34.34l1.69-.57c.11-.03.19-.18.15-.37l-.49-4.17c0-.18-.11-.3-.22-.3zm4.65 4.54c-1.35 0-2.25 0-3.49.68l-2.32.82c-.15.04-.23.19-.27.34a3.6 3.6 0 00-.15 2.1 24 24 0 00-1.46.75c-.45-.71-1.87-.64-1.87.37-.08.5-.42 1.2.22 1.47.3.37-.53.75-.68 1.16-.15.37-.22.75-.7.68-.5.18-.72.63-.34 1.04.37.3 1 0 .9.68.07.49.4.97.6 1.35-.45.37-.38.98-.72 1.43-.26.56.15 1.27.83 1.12a4.73 4.73 0 002.02-.75c3 .82 6.03 1.75 9.13 1.92a6.1 6.1 0 01-.86-4.97l-.02-.21c0-1.02.19-1.62.83-2.25.26-.27.64-.43 1.04-.52a6.1 6.1 0 013.97-1.5 6.01 6.01 0 015.43 3.43 5.5 5.5 0 00-.36-1.94c-.52-1.42-1.87-2.51-3.15-3.26-.75-.38-1.72-.41-2.54-.53l-.27-1.27c.11-.68-.64-.6-1.12-.75l-2.03-.34c-.48-.67-1.87-1.05-2.62-1.05zM5.9 13.05c.38.03.57.67.57 1.83 0 1.1-.23 1.77-.75 2.25-.38.34-.6.3-.83-.18-.45-1.05-.22-2.89.41-3.57.23-.22.42-.37.6-.33zm3.72.22c.56 0 .86.6.93 1.77.04 1.3-.26 2.2-.97 2.73-.34.23-.75.34-.97.23-.3-.12-.64-.98-.68-1.7-.11-1.38.41-2.58 1.27-2.92.13-.06.27-.1.42-.1z" fill="#e4e4e4"/>
<path d="M18.2 13.17A5.23 5.23 0 0013 18.4a5.23 5.23 0 005.24 5.24 5.23 5.23 0 005.23-5.24 5.23 5.23 0 00-5.27-5.23z" fill="#c70e0e" class="warning"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"> <path fill="#e4e4e4" d="M6.93 2.17h-.08l-1.39.26c-.15.04-.22.2-.22.38l.22 4.39c0 .22.15.37.34.33l1.69-.56c.11-.04.19-.19.15-.37l-.49-4.17c0-.18-.11-.3-.22-.3zm4.65 4.5c-1.35 0-2.25 0-3.49.68l-2.33.82c-.15.04-.22.19-.26.34a3.6 3.6 0 00-.15 2.1 24 24 0 00-1.46.75c-.45-.71-1.88-.64-1.88.37-.07.5-.4 1.2.23 1.47.3.37-.53.75-.68 1.16-.15.37-.22.75-.7.67-.5.2-.72.64-.35 1.05.38.3 1.02 0 .9.68.08.49.42.97.6 1.35-.45.37-.37.97-.7 1.42-.27.57.14 1.28.82 1.13a4.72 4.72 0 002.02-.75c3.83 1.05 7.69 2.29 11.7 1.87 2.78-.18 5.81-1.23 7.28-3.75.71-1.27.67-2.88.18-4.16-.52-1.42-1.87-2.51-3.15-3.26-.75-.38-1.72-.41-2.55-.53l-.26-1.27c.11-.68-.64-.6-1.12-.75l-2.03-.34c-.49-.67-1.87-1.05-2.62-1.05zM5.9 13.05c.38.03.57.67.57 1.83 0 1.1-.23 1.77-.75 2.25-.38.34-.6.3-.83-.18-.45-1.05-.22-2.9.41-3.57.23-.22.42-.37.6-.33zm3.72.22c.56 0 .86.6.93 1.76.04 1.32-.26 2.22-.97 2.74-.34.23-.75.34-.98.23-.3-.12-.63-.98-.67-1.7-.11-1.38.41-2.58 1.27-2.92a1.13 1.13 0 01.42-.1zm5.13.53c.6 0 1.17.18 1.47.63.3.57.41 1.8.22 2.48a3.41 3.41 0 01-1.16 1.72c-.6.38-1.65.45-2.1.12-.56-.45-.75-1.05-.79-2.1 0-1.02.19-1.62.83-2.25.37-.38.97-.57 1.53-.6z"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -116,6 +116,26 @@ class MainWindow(Gtk.ApplicationWindow):
else: else:
self.connected_to_label.set_markup("<i>No Music Source Selected</i>") self.connected_to_label.set_markup("<i>No Music Source Selected</i>")
if AdapterManager.ground_truth_adapter_is_networked:
status_label = ""
if app_config.offline_mode:
status_label = "Offline"
elif AdapterManager.get_ping_status():
status_label = "Connected"
else:
status_label = "Error"
self.server_connection_menu_button.set_icon(
f"server-subsonic-{status_label.lower()}-symbolic"
)
self.connection_status_icon.set_from_icon_name(
f"server-{status_label.lower()}-symbolic", Gtk.IconSize.BUTTON
)
self.connection_status_label.set_text(status_label)
self.connected_status_box.show_all()
else:
self.connected_status_box.hide()
self._updating_settings = True self._updating_settings = True
# Main Settings # Main Settings
@@ -213,7 +233,7 @@ class MainWindow(Gtk.ApplicationWindow):
# Server icon and change server dropdown # Server icon and change server dropdown
self.server_connection_popover = self._create_server_connection_popover() self.server_connection_popover = self._create_server_connection_popover()
self.server_connection_menu_button = IconMenuButton( self.server_connection_menu_button = IconMenuButton(
"server-subsonic-symbolic", "server-subsonic-offline-symbolic",
tooltip_text="Server connection settings", tooltip_text="Server connection settings",
popover=self.server_connection_popover, popover=self.server_connection_popover,
) )
@@ -346,24 +366,24 @@ class MainWindow(Gtk.ApplicationWindow):
) )
vbox.add(self.connected_to_label) vbox.add(self.connected_to_label)
connected_status_box = Gtk.Box( self.connected_status_box = Gtk.Box(
orientation=Gtk.Orientation.HORIZONTAL, name="connected-status-row" orientation=Gtk.Orientation.HORIZONTAL, name="connected-status-row"
) )
connected_status_box.pack_start(Gtk.Box(), True, True, 0) self.connected_status_box.pack_start(Gtk.Box(), True, True, 0)
self.connection_status_icon = Gtk.Image.new_from_icon_name( self.connection_status_icon = Gtk.Image.new_from_icon_name(
"server-online", Gtk.IconSize.BUTTON "server-online", Gtk.IconSize.BUTTON
) )
self.connection_status_icon.set_name("online-status-icon") self.connection_status_icon.set_name("online-status-icon")
connected_status_box.add(self.connection_status_icon) self.connected_status_box.add(self.connection_status_icon)
self.connection_status_label = Gtk.Label( self.connection_status_label = Gtk.Label(
label="Connected", name="connection-status-label" label="Connected", name="connection-status-label"
) )
connected_status_box.add(self.connection_status_label) self.connected_status_box.add(self.connection_status_label)
connected_status_box.pack_start(Gtk.Box(), True, True, 0) self.connected_status_box.pack_start(Gtk.Box(), True, True, 0)
vbox.add(connected_status_box) vbox.add(self.connected_status_box)
# Offline Mode # Offline Mode
offline_box, self.offline_mode_switch = self._create_toggle_menu_button( offline_box, self.offline_mode_switch = self._create_toggle_menu_button(

View File

@@ -115,6 +115,12 @@ class PlayerControls(Gtk.ActionBar):
self.play_button.set_sensitive(has_current_song) self.play_button.set_sensitive(has_current_song)
self.next_button.set_sensitive(has_current_song and has_next_song) self.next_button.set_sensitive(has_current_song and has_next_song)
self.device_button.set_icon(
"chromecast{}-symbolic".format(
"" if app_config.state.current_device == "this device" else "-connected"
)
)
# Volume button and slider # Volume button and slider
if app_config.state.is_muted: if app_config.state.is_muted:
icon_name = "muted" icon_name = "muted"
@@ -609,14 +615,14 @@ class PlayerControls(Gtk.ActionBar):
# Device button (for chromecast) # Device button (for chromecast)
self.device_button = IconButton( self.device_button = IconButton(
"chromecast-connected-symbolic", "chromecast-symbolic",
"Show available audio output devices", "Show available audio output devices",
icon_size=Gtk.IconSize.LARGE_TOOLBAR, icon_size=Gtk.IconSize.LARGE_TOOLBAR,
) )
self.device_button.connect("clicked", self.on_device_click) self.device_button.connect("clicked", self.on_device_click)
box.pack_start(self.device_button, False, True, 5) box.pack_start(self.device_button, False, True, 5)
self.device_popover = Gtk.PopoverMenu(modal=False, name="device-popover",) self.device_popover = Gtk.PopoverMenu(modal=False, name="device-popover")
self.device_popover.set_relative_to(self.device_button) self.device_popover.set_relative_to(self.device_button)
device_popover_box = Gtk.Box( device_popover_box = Gtk.Box(

View File

@@ -616,8 +616,7 @@ class PlaylistDetailPanel(Gtk.Overlay):
Gtk.ResponseType.CANCEL, Gtk.ResponseType.CANCEL,
) )
confirm_dialog.format_secondary_markup( confirm_dialog.format_secondary_markup(
"Are you sure you want to delete the " 'Are you sure you want to delete the "{playlist.name}" playlist?'
f'"{playlist.name}" playlist?'
) )
result = confirm_dialog.run() result = confirm_dialog.run()
confirm_dialog.destroy() confirm_dialog.destroy()