- scripts/release.py: Version (patch/minor/major) automatisch hochzaehlen, CHANGELOG abschliessen, committen, taggen; --build baut alle Pakete in Docker - docker-build/: Build-Container fuer Windows (Wine + PyInstaller + Inno Setup), Linux und Android; Server-Image als docker-save-Archiv - Versionsanzeige im Desktop-Client und in der Android-App - Feste Android-Release-Signatur aus secrets/ (nicht im Git) - Windows-Icon im Repo, damit der Wine-Build ohne Qt-Fenster auskommt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
121 lines
3.9 KiB
Python
121 lines
3.9 KiB
Python
"""NetClip-Desktop-Client.
|
|
|
|
netclip starten (Tray-Icon)
|
|
netclip --minimized ohne Verlaufsfenster starten (Autostart)
|
|
netclip --show Verlauf der laufenden Instanz öffnen (fuer ein Tastenkuerzel)
|
|
netclip --import datei.netclip Verbindungsdaten importieren
|
|
netclip --server URL --token T [--server-key K] [--insecure] [--autostart]
|
|
Einstellungen setzen (fuer automatisches Ausrollen)
|
|
"""
|
|
import argparse
|
|
import sys
|
|
|
|
from PySide6.QtCore import QTimer
|
|
from PySide6.QtNetwork import QLocalServer, QLocalSocket
|
|
from PySide6.QtWidgets import QApplication, QMessageBox, QSystemTrayIcon
|
|
|
|
from . import __version__, autostart, config, connection
|
|
|
|
INSTANCE = "netclip-instance"
|
|
|
|
|
|
def parse_args():
|
|
p = argparse.ArgumentParser(prog="netclip", description="Netzwerk-Zwischenablage")
|
|
p.add_argument("--version", action="version", version=f"NetClip {__version__}")
|
|
p.add_argument("--minimized", action="store_true")
|
|
p.add_argument("--show", action="store_true")
|
|
p.add_argument("--import", dest="import_file")
|
|
p.add_argument("--server")
|
|
p.add_argument("--token")
|
|
p.add_argument("--server-key")
|
|
p.add_argument("--device-name")
|
|
p.add_argument("--insecure", action="store_true", help="TLS-Zertifikat nicht prüfen")
|
|
p.add_argument("--autostart", action="store_true")
|
|
p.add_argument("--configure-only", action="store_true", help="nur Einstellungen schreiben, nicht starten")
|
|
return p.parse_args()
|
|
|
|
|
|
def apply_args(args) -> bool:
|
|
cfg = config.load()
|
|
changed = False
|
|
if args.import_file:
|
|
with open(args.import_file, encoding="utf-8") as f:
|
|
for k, v in connection.parse(f.read()).items():
|
|
setattr(cfg, k, v)
|
|
changed = True
|
|
for attr in ("server", "token", "server_key", "device_name"):
|
|
value = getattr(args, attr)
|
|
if value is not None:
|
|
setattr(cfg, attr, value)
|
|
changed = True
|
|
if args.insecure:
|
|
cfg.verify_tls = False
|
|
changed = True
|
|
if args.autostart:
|
|
cfg.autostart = True
|
|
autostart.set_enabled(True)
|
|
changed = True
|
|
if changed:
|
|
config.save(cfg)
|
|
return changed
|
|
|
|
|
|
def main():
|
|
args = parse_args()
|
|
changed = apply_args(args)
|
|
if args.configure_only:
|
|
print(f"Konfiguration gespeichert: {config.config_file()}")
|
|
return
|
|
|
|
app = QApplication(sys.argv)
|
|
app.setApplicationName("NetClip")
|
|
app.setApplicationVersion(__version__)
|
|
app.setQuitOnLastWindowClosed(False)
|
|
|
|
# Einzelinstanz: laeuft schon eine, dort ggf. Verlauf öffnen bzw. neu laden und beenden
|
|
sock = QLocalSocket()
|
|
sock.connectToServer(INSTANCE)
|
|
if sock.waitForConnected(300):
|
|
sock.write(b"reload\n" if changed else b"show\n")
|
|
sock.waitForBytesWritten(300)
|
|
sock.disconnectFromServer()
|
|
return
|
|
|
|
if not QSystemTrayIcon.isSystemTrayAvailable():
|
|
QMessageBox.warning(None, "NetClip", "Kein System-Tray gefunden. Der Verlauf ist über das Fenster erreichbar.")
|
|
|
|
from .controller import Controller
|
|
from .ui import HistoryWindow, Tray, app_icon
|
|
|
|
app.setWindowIcon(app_icon())
|
|
ctl = Controller()
|
|
window = HistoryWindow(ctl)
|
|
tray = Tray(ctl, window)
|
|
|
|
server = QLocalServer()
|
|
QLocalServer.removeServer(INSTANCE)
|
|
server.listen(INSTANCE)
|
|
|
|
def on_connection():
|
|
conn = server.nextPendingConnection()
|
|
|
|
def read():
|
|
cmd = bytes(conn.readAll()).decode().strip()
|
|
if cmd == "reload":
|
|
ctl.apply_config(config.load())
|
|
window.show_raise()
|
|
conn.readyRead.connect(read)
|
|
server.newConnection.connect(on_connection)
|
|
|
|
if not ctl.cfg.configured:
|
|
QTimer.singleShot(200, tray.open_settings)
|
|
elif not args.minimized:
|
|
window.show_raise()
|
|
|
|
app.aboutToQuit.connect(ctl.shutdown)
|
|
sys.exit(app.exec())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|