v2.2.4: implement auto_overtime + overtime_unit + notif_before_minutes; remove 3 dead settings

Implemented (previously UI-only with no business effect):
- auto_overtime: when OFF, prompt user on clock-out before banking
- overtime_unit: 15/30/60-min truncation choice now actually applied
- notification_before_minutes: 30-min hardcode -> user-configurable 1~120

Removed dead keys (no readers in business logic):
- auto_detect_boot, notification_enabled, annual_leave_used

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
KINDNICK
2026-04-30 17:29:44 +09:00
co-authored by Claude Opus 4.7
parent b91b229731
commit 14d88656fe
10 changed files with 172 additions and 42 deletions
+28 -10
View File
@@ -77,37 +77,55 @@ def is_newer(remote: str, local: str) -> bool:
return _parse_version(remote) > _parse_version(local)
def check_for_update(current_version: str, timeout: int = 5) -> Optional[ReleaseInfo]:
"""GitHub Releases API 조회. 새 버전 있으면 ReleaseInfo, 없으면 None.
# 업데이트 체크 결과 상수 (info=None 일 때 reason 식별)
UP_TO_DATE = 'up_to_date'
NETWORK_ERROR = 'network_error'
NO_RELEASE = 'no_release' # latest 응답 자체가 없음 (404 등)
NO_ASSET = 'no_asset' # release는 있으나 main.exe 자산 없음
네트워크 오류 시 None 반환 (앱 시작을 막지 않음).
def check_for_update(current_version: str, timeout: int = 5):
"""Releases API 조회.
Returns:
(ReleaseInfo, None) — 새 버전 있음
(None, UP_TO_DATE) — 이미 최신
(None, NETWORK_ERROR) — 네트워크/타임아웃 실패
(None, NO_RELEASE) — 저장소 비공개/리소스 없음 (404)
(None, NO_ASSET) — 새 버전이지만 main.exe 자산 미첨부
"""
try:
req = urllib.request.Request(RELEASES_API, headers={'User-Agent': USER_AGENT})
with urllib.request.urlopen(req, timeout=timeout) as resp:
data = json.loads(resp.read())
except (urllib.error.URLError, json.JSONDecodeError, TimeoutError):
return None
except urllib.error.HTTPError as e:
if e.code == 404:
return None, NO_RELEASE
return None, NETWORK_ERROR
except (urllib.error.URLError, json.JSONDecodeError, TimeoutError, OSError):
return None, NETWORK_ERROR
tag = data.get('tag_name', '')
if not tag or not is_newer(tag, current_version):
return None
if not tag:
return None, NO_RELEASE
if not is_newer(tag, current_version):
return None, UP_TO_DATE
asset_url = None
for asset in data.get('assets', []):
if asset.get('name') == ASSET_NAME:
asset_url = asset.get('browser_download_url')
break
if not asset_url:
return None
return None, NO_ASSET
return ReleaseInfo(
info = ReleaseInfo(
version=tag,
asset_url=asset_url,
notes=data.get('body', ''),
published_at=data.get('published_at', ''),
)
return info, None
def download_update(asset_url: str, dest_dir: Optional[Path] = None,