Skip to content

Commit

Permalink
Implement a dynamic tray icon status picture
Browse files Browse the repository at this point in the history
  • Loading branch information
DevilXD committed Jul 1, 2024
1 parent 14a9154 commit 35c46c2
Show file tree
Hide file tree
Showing 10 changed files with 35 additions and 8 deletions.
2 changes: 1 addition & 1 deletion appimage/AppImageBuilder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ script:

# Package the app.
- mkdir -p "$TARGET_APPDIR"/usr/{src,share/icons/hicolor/128x128/apps}
- cp -r "$SOURCE_DIR/../lang" "$SOURCE_DIR/../pickaxe.ico" "$SOURCE_DIR"/../*.py "$TARGET_APPDIR/usr/src"
- cp -r "$SOURCE_DIR/../lang" "$SOURCE_DIR/../icons" "$SOURCE_DIR"/../*.py "$TARGET_APPDIR/usr/src"
- cp "$SOURCE_DIR/pickaxe.png" "$TARGET_APPDIR/usr/share/icons/hicolor/128x128/apps/io.github.devilxd.twitchdropsminer.png"

# Install requirements.
Expand Down
9 changes: 7 additions & 2 deletions build.spec
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ if TYPE_CHECKING:

# (source_path, dest_path, required)
to_add: list[tuple[Path, str, bool]] = [
(Path("pickaxe.ico"), '.', True), # icon file
# icon files
(Path("icons/pickaxe.ico"), "./icons", True),
(Path("icons/active.ico"), "./icons", True),
(Path("icons/idle.ico"), "./icons", True),
(Path("icons/error.ico"), "./icons", True),
(Path("icons/maint.ico"), "./icons", True),
# SeleniumWire HTTPS/SSL cert file and key
(Path(SITE_PACKAGES_PATH, "seleniumwire/ca.crt"), "./seleniumwire", False),
(Path(SITE_PACKAGES_PATH, "seleniumwire/ca.key"), "./seleniumwire", False),
Expand Down Expand Up @@ -99,10 +104,10 @@ exe = EXE(
console=False,
upx_exclude=[],
target_arch=None,
icon="pickaxe.ico",
runtime_tmpdir=None,
codesign_identity=None,
entitlements_file=None,
icon="icons/pickaxe.ico",
bootloader_ignore_signals=False,
disable_windowed_traceback=False,
name="Twitch Drops Miner (by DevilXD)",
Expand Down
25 changes: 21 additions & 4 deletions gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1044,13 +1044,21 @@ class TrayIcon:
def __init__(self, manager: GUIManager, master: ttk.Widget):
self._manager = manager
self.icon: pystray.Icon | None = None
self.icon_image = Image_module.open(resource_path("pickaxe.ico"))
self._icon_images: dict[str, Image_module.Image] = {
"pickaxe": Image_module.open(resource_path("icons/pickaxe.ico")),
"active": Image_module.open(resource_path("icons/active.ico")),
"idle": Image_module.open(resource_path("icons/idle.ico")),
"error": Image_module.open(resource_path("icons/error.ico")),
"maint": Image_module.open(resource_path("icons/maint.ico")),
}
self._icon_state: str = "pickaxe"
self._button = ttk.Button(master, command=self.minimize, text=_("gui", "tray", "minimize"))
self._button.grid(column=0, row=0, sticky="ne")

def __del__(self) -> None:
self.stop()
self.icon_image.close()
for icon_image in self._icon_images.values():
icon_image.close()

def _shorten(self, text: str, by_len: int, min_len: int) -> str:
if (text_len := len(text)) <= min_len + 3 or by_len <= 0:
Expand Down Expand Up @@ -1096,7 +1104,9 @@ def bridge(func):
pystray.Menu.SEPARATOR,
pystray.MenuItem(_("gui", "tray", "quit"), bridge(self.quit)),
)
self.icon = pystray.Icon("twitch_miner", self.icon_image, self.get_title(drop), menu)
self.icon = pystray.Icon(
"twitch_miner", self._icon_images[self._icon_state], self.get_title(drop), menu
)
# self.icon.run_detached()
loop.run_in_executor(None, self.icon.run)

Expand Down Expand Up @@ -1142,6 +1152,13 @@ def update_title(self, drop: TimedDrop | None):
if self.icon is not None:
self.icon.title = self.get_title(drop)

def change_icon(self, state: str):
if state not in self._icon_images:
raise ValueError("Invalid icon state")
self._icon_state = state
if self.icon is not None:
self.icon.icon = self._icon_images[state]


class Notebook:
def __init__(self, manager: GUIManager, master: ttk.Widget):
Expand Down Expand Up @@ -1937,7 +1954,7 @@ def __init__(self, twitch: Twitch):
# withdraw immediately to prevent the window from flashing
self._root.withdraw()
# root.resizable(False, True)
set_root_icon(root, resource_path("pickaxe.ico"))
set_root_icon(root, resource_path("icons/pickaxe.ico"))
root.title(WINDOW_TITLE) # window title
root.bind_all("<KeyPress-Escape>", self.unfocus) # pressing ESC unfocuses selection
# Image cache for displaying images
Expand Down
Binary file added icons/active.ico
Binary file not shown.
Binary file added icons/error.ico
Binary file not shown.
Binary file added icons/idle.ico
Binary file not shown.
Binary file added icons/maint.ico
Binary file not shown.
File renamed without changes.
3 changes: 2 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def debug_gql(self) -> int:
root = tk.Tk()
root.overrideredirect(True)
root.withdraw()
set_root_icon(root, resource_path("pickaxe.ico"))
set_root_icon(root, resource_path("icons/pickaxe.ico"))
root.update()
parser = Parser(
SELF_PATH.name,
Expand Down Expand Up @@ -168,6 +168,7 @@ async def main():
await client.shutdown()
if not client.gui.close_requested:
# user didn't request the closure
client.gui.tray.change_icon("error")
client.print(_("status", "terminated"))
client.gui.status.update(_("gui", "status", "terminated"))
# notify the user about the closure
Expand Down
4 changes: 4 additions & 0 deletions twitch.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,11 +608,13 @@ async def _run(self):
if self.settings.dump:
self.gui.close()
continue
self.gui.tray.change_icon("idle")
self.gui.status.update(_("gui", "status", "idle"))
self.stop_watching()
# clear the flag and wait until it's set again
self._state_change.clear()
elif self._state is State.INVENTORY_FETCH:
self.gui.tray.change_icon("maint")
# ensure the websocket is running
await self.websocket.start()
await self.fetch_inventory()
Expand Down Expand Up @@ -835,6 +837,7 @@ async def _run(self):
self.change_state(State.IDLE)
del new_watching, selected_channel, watching_channel
elif self._state is State.EXIT:
self.gui.tray.change_icon("pickaxe")
self.gui.status.update(_("gui", "status", "exiting"))
# we've been requested to exit the application
break
Expand Down Expand Up @@ -982,6 +985,7 @@ def should_switch(self, channel: Channel) -> bool:
)

def watch(self, channel: Channel, *, update_status: bool = True):
self.gui.tray.change_icon("active")
self.gui.channels.set_watching(channel)
self.watching_channel.set(channel)
if update_status:
Expand Down

0 comments on commit 35c46c2

Please sign in to comment.