v1.9.1: PNG Material Design icons — 28 icons, dark/light theme, HiDPI, graceful Unicode fallback

- 56 PNG icons (28 unique × 2 color variants) from Material Design Icons (round style, 96×96px)
- core/icons.py: ctk_icon(), make_icon_button(), reconfigure_icon_button() with CTkImage cache
- Updated 15 GUI files: app.py, sidebar.py, server_dialog.py, all tabs
- build.py: auto-include assets/icons/ in PyInstaller bundle, patch rollover at 99→minor+1
- tools/download_icons.py: icon download script
- Automatic dark↔light theme switching via CTkImage dual-image support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chrome-storm-c442
2026-03-03 07:27:49 -05:00
parent 9b0e4c76a3
commit 1e729fcf3a
76 changed files with 397 additions and 148 deletions

View File

@@ -36,7 +36,13 @@ def auto_bump_version() -> str:
sys.exit(1)
major, minor, patch = int(match.group(1)), int(match.group(2)), int(match.group(3))
new_patch = patch + 1
# Patch grows up to 99, then minor+1 and patch resets to 1
if patch >= 99:
minor += 1
new_patch = 1
else:
new_patch = patch + 1
new_version = f"{major}.{minor}.{new_patch}"
content = re.sub(
@@ -111,6 +117,13 @@ def build():
"--add-data", f"core/encryption.py{os.pathsep}core",
]
# PNG icons for GUI (Material Design)
icons_dir = os.path.join(PROJECT_DIR, "assets", "icons")
if os.path.isdir(icons_dir):
cmd_parts.extend(["--add-data", f"assets/icons{os.pathsep}assets/icons"])
else:
print("WARNING: assets/icons/ not found, building without PNG icons")
# Icon
icon_path = os.path.join(PROJECT_DIR, "assets", "icon.ico")
if os.path.exists(icon_path):
@@ -194,6 +207,47 @@ def _get_gitea_auth() -> dict:
_GITEA_API = "https://git.sensey24.ru/api/v1/repos/aibot777/server-manager"
def _generate_changelog() -> str:
"""Generate changelog from git commits since previous tag."""
try:
# Get all tags sorted by semver
raw = subprocess.check_output(
["git", "tag", "--list", "v*"],
text=True, stderr=subprocess.DEVNULL,
).strip()
tags = [t for t in raw.splitlines() if re.match(r'^v\d+\.\d+\.\d+$', t)]
tags.sort(key=lambda t: tuple(int(x) for x in t[1:].split(".")))
current_tag = f"v{__version__}"
# Find previous tag (exclude current if it exists)
prev_tags = [t for t in tags if t != current_tag]
if prev_tags:
prev_tag = prev_tags[-1]
log_range = f"{prev_tag}..HEAD"
else:
log_range = "HEAD~20..HEAD"
# Get commits
raw_log = subprocess.check_output(
["git", "log", log_range, "--oneline", "--no-merges"],
text=True, stderr=subprocess.DEVNULL,
).strip()
if not raw_log:
return f"Release {current_tag}"
# Format: strip commit hash, keep message
lines = []
for line in raw_log.splitlines():
parts = line.split(" ", 1)
if len(parts) == 2:
lines.append(f"- {parts[1]}")
return f"## What's New in {current_tag}\n\n" + "\n".join(lines)
except Exception as exc:
print(f"Changelog generation failed: {exc}")
return f"Release v{__version__}"
def publish_gitea_release(exe_path: str):
"""Create a Gitea release and upload the exe as asset."""
auth = _get_gitea_auth()
@@ -203,13 +257,14 @@ def publish_gitea_release(exe_path: str):
tag = f"v{__version__}"
filename = os.path.basename(exe_path)
changelog = _generate_changelog()
# Create release
try:
data = json.dumps({
"tag_name": tag,
"name": tag,
"body": f"Release {tag}",
"body": changelog,
}).encode()
req = urllib.request.Request(
f"{_GITEA_API}/releases",