Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 76 additions & 76 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,92 +4,92 @@ name: Build and Package
# Velopack on each platform. Produces one artifact per platform.

on:
workflow_call:
inputs:
version:
description: "Version string for the package"
required: true
type: string
channel:
description: "Velopack channel base (stable or dev)"
required: true
type: string
workflow_call:
inputs:
version:
description: "Version string for the package"
required: true
type: string
channel:
description: "Velopack channel base (stable or dev)"
required: true
type: string

env:
VELOPACK_APP_ID: synodic
VELOPACK_APP_TITLE: Synodic Client
VELOPACK_APP_ID: synodic
VELOPACK_APP_TITLE: Synodic Client

jobs:
build-and-package:
if: github.repository_owner == 'synodic'
runs-on: ${{ matrix.runner }}
strategy:
matrix:
include:
- runner: windows-latest
main_exe: synodic.exe
platform: win
- runner: ubuntu-latest
main_exe: synodic
platform: linux
- runner: macos-latest
main_exe: synodic
platform: osx
steps:
- name: Checkout
uses: actions/checkout@v6
build-and-package:
if: github.repository_owner == 'synodic'
runs-on: ${{ matrix.runner }}
strategy:
matrix:
include:
- runner: windows-latest
main_exe: synodic.exe
platform: win
- runner: ubuntu-latest
main_exe: synodic
platform: linux
- runner: macos-latest
main_exe: synodic
platform: osx
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install system dependencies
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libxcb-cursor0 libxkbcommon-x11-0 libfuse2
- name: Install system dependencies
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libxcb-cursor0 libxkbcommon-x11-0 libfuse2

- name: Install PDM
uses: pdm-project/setup-pdm@v4
with:
python-version: "3.14"
cache: true
- name: Install PDM
uses: pdm-project/setup-pdm@v4
with:
python-version: "3.14"
cache: true

- name: Install dependencies
run: pdm install -G build
- name: Install dependencies
run: pdm install -G build

- name: Build executable
run: pdm run pyinstaller tool/pyinstaller/synodic.spec --distpath dist
- name: Build executable
run: pdm run pyinstaller tool/pyinstaller/synodic.spec --distpath dist

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "9.0"
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "9.0"

- name: Install Velopack CLI
run: dotnet tool install -g vpk
- name: Install Velopack CLI
run: dotnet tool install -g vpk

- name: Download previous release (for delta packages)
continue-on-error: true
shell: bash
run: |
vpk download github \
--repoUrl https://github.com/${{ github.repository }} \
--channel ${{ inputs.channel }}-${{ matrix.platform }} \
--token ${{ secrets.GITHUB_TOKEN }} \
${{ inputs.channel == 'dev' && '--pre' || '' }}
- name: Download previous release (for delta packages)
continue-on-error: true
shell: bash
run: |
vpk download github \
--repoUrl https://github.com/${{ github.repository }} \
--channel ${{ inputs.channel }}-${{ matrix.platform }} \
--token ${{ secrets.GITHUB_TOKEN }} \
${{ inputs.channel == 'dev' && '--pre' || '' }}

- name: Create Velopack package
shell: bash
run: |
vpk pack \
--packId ${{ env.VELOPACK_APP_ID }} \
--packVersion ${{ inputs.version }} \
--packDir dist/synodic \
--mainExe ${{ matrix.main_exe }} \
--packTitle "${{ env.VELOPACK_APP_TITLE }}" \
--channel ${{ inputs.channel }}-${{ matrix.platform }} \
--shortcutLocations StartMenuRoot \
--outputDir releases
- name: Create Velopack package
shell: bash
run: |
vpk pack \
--packId ${{ env.VELOPACK_APP_ID }} \
--packVersion ${{ inputs.version }} \
--packDir dist/synodic \
--mainExe ${{ matrix.main_exe }} \
--packTitle "${{ env.VELOPACK_APP_TITLE }}" \
--channel ${{ inputs.channel }}-${{ matrix.platform }} \
${{ matrix.platform == 'win' && '--shortcuts StartMenuRoot' || '' }} \
--outputDir releases

- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:
name: velopack-release-${{ matrix.platform }}
path: releases/*
- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:
name: velopack-release-${{ matrix.platform }}
path: releases/*
90 changes: 45 additions & 45 deletions pdm.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dynamic = ["version"]
requires-python = ">=3.14, <3.15"

dependencies = [
"pyside6>=6.10.2",
"pyside6>=6.11.0",
"packaging>=26.0",
"porringer>=0.2.1.dev88",
"qasync>=0.28.0",
Expand All @@ -30,7 +30,7 @@ build = [
]
lint = [
"ruff>=0.15.7",
"pyrefly>=0.57.1",
"pyrefly>=0.58.0",
]
test = [
"pytest>=9.0.2",
Expand Down
25 changes: 21 additions & 4 deletions synodic_client/application/screen/tray.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import TYPE_CHECKING

from PySide6.QtCore import QTimer
from PySide6.QtGui import QAction
from PySide6.QtGui import QAction, QCursor
from PySide6.QtWidgets import (
QApplication,
QMainWindow,
Expand Down Expand Up @@ -126,10 +126,10 @@ def _build_menu(self, app: QApplication, window: MainWindow) -> None:
self._menu.addSeparator()

self._quit_action = QAction('Quit', self._menu)
self._quit_action.triggered.connect(app.quit)
self._quit_action.triggered.connect(self._on_quit_triggered)
self._menu.addAction(self._quit_action)

self.tray.setContextMenu(self._menu)
self._menu.aboutToShow.connect(lambda: logger.debug('Tray context menu about to show'))

# Maximum number of tray-visibility retries at startup.
_TRAY_MAX_RETRIES = 5
Expand Down Expand Up @@ -162,12 +162,29 @@ def _show_tray_icon(self) -> None:
)
self.tray.setVisible(True)

# Delay before showing the context menu, in milliseconds.
# Absorbs residual mouse-up events from touchpad two-finger taps
# that would otherwise land on a menu item (typically "Quit").
_MENU_POPUP_DELAY_MS = 80

def _on_tray_activated(self, reason: QSystemTrayIcon.ActivationReason) -> None:
"""Handle tray icon activation (e.g. double-click)."""
"""Handle tray icon activation."""
logger.debug('Tray activated: reason=%s', reason.name)
if reason == QSystemTrayIcon.ActivationReason.DoubleClick:
self._window.show()
self._window.raise_()
self._window.activateWindow()
elif reason == QSystemTrayIcon.ActivationReason.Context:
QTimer.singleShot(self._MENU_POPUP_DELAY_MS, self._show_tray_menu)

def _show_tray_menu(self) -> None:
"""Show the tray context menu at the current cursor position."""
self._menu.exec(QCursor.pos())

def _on_quit_triggered(self) -> None:
"""Handle the Quit menu action."""
logger.info('Quit requested via tray menu')
self._app.quit()

def _show_settings(self) -> None:
"""Show the settings window."""
Expand Down
Loading
Loading