adding browser extension and some QoL
This commit is contained in:
378
gui.py
378
gui.py
@@ -13,6 +13,17 @@ import re
|
||||
import shutil
|
||||
import socket
|
||||
import ssl
|
||||
import threading
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
|
||||
from PySide6.QtCore import Qt, QThread, QObject, Signal, QUrl, QFile, QIODevice, QTimer, QMimeData, QProcess
|
||||
from PySide6.QtGui import QIcon, QAction, QPixmap, QPainter, QColor, QFont, QPen, QImage, QDesktopServices, QDrag, QClipboard
|
||||
from PySide6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QHttpMultiPart, QHttpPart, QNetworkReply, QLocalServer, QLocalSocket
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication, QSystemTrayIcon, QMenu, QDialog, QVBoxLayout, QHBoxLayout,
|
||||
QLabel, QLineEdit, QComboBox, QCheckBox, QPushButton, QGroupBox,
|
||||
QFormLayout, QMessageBox, QFileDialog, QSlider, QScrollArea, QFrame, QGridLayout, QWidget, QSizePolicy, QInputDialog
|
||||
)
|
||||
|
||||
def normalize_file_path(path_str: str) -> str:
|
||||
if not path_str:
|
||||
@@ -26,6 +37,90 @@ def normalize_file_path(path_str: str) -> str:
|
||||
path_str = urllib.parse.unquote(path_str[7:])
|
||||
return os.path.abspath(path_str)
|
||||
|
||||
def parse_upload_target(arg: str) -> tuple[str, bool]:
|
||||
if not arg:
|
||||
return ("", False)
|
||||
|
||||
arg = arg.strip().strip("'\"")
|
||||
|
||||
if arg.startswith("f0ckm://") or arg.startswith("f0ckm-uploader://"):
|
||||
parsed = urllib.parse.urlparse(arg)
|
||||
query_params = urllib.parse.parse_qs(parsed.query)
|
||||
target_url = ""
|
||||
if "url" in query_params and query_params["url"]:
|
||||
target_url = query_params["url"][0]
|
||||
else:
|
||||
raw_path = parsed.netloc + parsed.path
|
||||
if parsed.query:
|
||||
raw_path += "?" + parsed.query
|
||||
raw_path = raw_path.lstrip("/")
|
||||
if raw_path.startswith("upload/"):
|
||||
raw_path = raw_path[7:]
|
||||
elif raw_path.startswith("upload?"):
|
||||
raw_path = raw_path[7:]
|
||||
target_url = raw_path
|
||||
|
||||
target_url = urllib.parse.unquote(target_url)
|
||||
if target_url.startswith("http://") or target_url.startswith("https://"):
|
||||
print(f"[f0ckm-gui] [PARSE] Protocol URL parsed: '{arg}' -> target='{target_url}' (is_url=True)", flush=True)
|
||||
return (target_url, True)
|
||||
|
||||
if arg.startswith("http://") or arg.startswith("https://"):
|
||||
print(f"[f0ckm-gui] [PARSE] Direct URL parsed: '{arg}' (is_url=True)", flush=True)
|
||||
return (arg, True)
|
||||
|
||||
norm = normalize_file_path(arg)
|
||||
print(f"[f0ckm-gui] [PARSE] File path parsed: '{arg}' -> norm='{norm}' (is_url=False)", flush=True)
|
||||
return (norm, False)
|
||||
|
||||
class LocalHTTPBridge(QObject):
|
||||
request_upload = Signal(str)
|
||||
|
||||
local_http_bridge = LocalHTTPBridge()
|
||||
|
||||
class LocalHTTPHandler(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
try:
|
||||
parsed = urllib.parse.urlparse(self.path)
|
||||
query = urllib.parse.parse_qs(parsed.query)
|
||||
if parsed.path in ("/upload", "/upload/") and "url" in query:
|
||||
target_url = query["url"][0]
|
||||
print(f"[f0ckm-gui] [LOCAL HTTP API] Received direct upload request for URL: {target_url}", flush=True)
|
||||
local_http_bridge.request_upload.emit(target_url)
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
self.wfile.write(b'{"success": true, "msg": "Queued upload"}')
|
||||
elif parsed.path in ("/ping", "/ping/"):
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
self.wfile.write(b'{"status": "ok", "app": "f0ckm-uploader"}')
|
||||
else:
|
||||
self.send_response(404)
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
self.wfile.write(b'{"error": "Not Found"}')
|
||||
except Exception as e:
|
||||
print(f"[f0ckm-gui] [LOCAL HTTP ERROR] {e}", flush=True)
|
||||
|
||||
def log_message(self, format, *args):
|
||||
pass
|
||||
|
||||
def start_local_http_server(tray_app, port=18739):
|
||||
try:
|
||||
server = HTTPServer(("127.0.0.1", port), LocalHTTPHandler)
|
||||
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
||||
thread.start()
|
||||
print(f"[f0ckm-gui] [LOCAL HTTP API] Started loopback server on http://127.0.0.1:{port}", flush=True)
|
||||
return server
|
||||
except Exception as e:
|
||||
print(f"[f0ckm-gui] [LOCAL HTTP API WARNING] Could not start HTTP server on port {port}: {e}", flush=True)
|
||||
return None
|
||||
|
||||
|
||||
def copy_to_clipboard(text: str):
|
||||
if not text:
|
||||
return
|
||||
@@ -53,14 +148,6 @@ def copy_to_clipboard(text: str):
|
||||
subprocess.run(["xsel", "--clipboard", "--input"], input=text.encode("utf-8"), check=False)
|
||||
except Exception as e:
|
||||
print(f"xsel error: {e}")
|
||||
from PySide6.QtCore import Qt, QThread, QObject, Signal, QUrl, QFile, QIODevice, QTimer, QMimeData, QProcess
|
||||
from PySide6.QtGui import QIcon, QAction, QPixmap, QPainter, QColor, QFont, QPen, QImage, QDesktopServices, QDrag, QClipboard
|
||||
from PySide6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QHttpMultiPart, QHttpPart, QNetworkReply, QLocalServer, QLocalSocket
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication, QSystemTrayIcon, QMenu, QDialog, QVBoxLayout, QHBoxLayout,
|
||||
QLabel, QLineEdit, QComboBox, QCheckBox, QPushButton, QGroupBox,
|
||||
QFormLayout, QMessageBox, QFileDialog, QSlider, QScrollArea, QFrame, QGridLayout, QWidget, QSizePolicy
|
||||
)
|
||||
|
||||
# Configuration paths
|
||||
CONFIG_DIR = os.path.expanduser("~/.config/f0ckm-uploader")
|
||||
@@ -1047,6 +1134,117 @@ class StreamingMultipartEncoder:
|
||||
self.total_size = len(self.header_bytes) + self.file_size + len(self.footer_bytes)
|
||||
self.content_type = f"multipart/form-data; boundary={self.boundary}"
|
||||
|
||||
class URLPostThread(QThread):
|
||||
finished = Signal(bool, str) # success, response_text_or_error
|
||||
|
||||
def __init__(self, api_url, api_key, url_param, rating, tags, visibility, is_oc, parent=None):
|
||||
super().__init__(parent)
|
||||
self.api_url = api_url
|
||||
self.api_key = api_key
|
||||
self.url_param = url_param
|
||||
self.rating = rating
|
||||
self.tags = tags
|
||||
self.visibility = visibility
|
||||
self.is_oc = is_oc
|
||||
|
||||
def run(self):
|
||||
print(f"[f0ckm-gui] [URL POST START] Sending JSON URL payload '{self.url_param}' to '{self.api_url}'", flush=True)
|
||||
try:
|
||||
payload = {
|
||||
"url": self.url_param,
|
||||
"tags": self.tags if self.tags else "url,upload",
|
||||
"visibility": str(self.visibility) if self.visibility is not None else "0"
|
||||
}
|
||||
if self.rating and str(self.rating).lower() not in ["", "default", "none"]:
|
||||
rating_map = {"s": "sfw", "q": "nsfw", "e": "nsfl", "sfw": "sfw", "nsfw": "nsfw", "nsfl": "nsfl"}
|
||||
payload["rating"] = rating_map.get(str(self.rating).lower(), str(self.rating).lower())
|
||||
if self.is_oc:
|
||||
payload["is_oc"] = "1"
|
||||
|
||||
json_bytes = json.dumps(payload).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
self.api_url,
|
||||
data=json_bytes,
|
||||
headers={
|
||||
"User-Agent": "f0ckm-uploader/2.0",
|
||||
"X-Api-Key": self.api_key,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
method="POST"
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
resp_text = resp.read().decode("utf-8")
|
||||
print(f"[f0ckm-gui] [URL POST OK] Server Response: {resp_text}", flush=True)
|
||||
self.finished.emit(True, resp_text)
|
||||
except Exception as e:
|
||||
print(f"[f0ckm-gui] [URL POST ERROR] {e}", flush=True)
|
||||
self.finished.emit(False, str(e))
|
||||
|
||||
class StreamingDownloadThread(QThread):
|
||||
progress = Signal(int, int) # bytes_received, total_bytes
|
||||
finished = Signal(bool, str) # success, file_path_or_error_msg
|
||||
|
||||
def __init__(self, url, parent=None):
|
||||
super().__init__(parent)
|
||||
self.url = url
|
||||
self.aborted = False
|
||||
|
||||
def abort(self):
|
||||
self.aborted = True
|
||||
|
||||
def run(self):
|
||||
print(f"[f0ckm-gui] [DOWNLOAD START] Requesting remote URL: {self.url}", flush=True)
|
||||
try:
|
||||
req = urllib.request.Request(
|
||||
self.url,
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
}
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
total_size = int(resp.headers.get("Content-Length", 0))
|
||||
content_type = resp.headers.get("Content-Type", "")
|
||||
print(f"[f0ckm-gui] [DOWNLOAD HTTP OK] Content-Type: '{content_type}', Length: {total_size} bytes", flush=True)
|
||||
|
||||
url_path = urllib.parse.urlparse(self.url).path
|
||||
ext = os.path.splitext(url_path)[1].lower()
|
||||
if not ext or len(ext) > 6:
|
||||
mime_base = content_type.split(";")[0].strip() if content_type else ""
|
||||
ext = mimetypes.guess_extension(mime_base) or ".png"
|
||||
if ext == ".jpe":
|
||||
ext = ".jpg"
|
||||
|
||||
clean_name = os.path.basename(url_path) or f"remote_{int(time.time())}"
|
||||
if not os.path.splitext(clean_name)[1]:
|
||||
clean_name += ext
|
||||
|
||||
temp_dir = tempfile.gettempdir()
|
||||
temp_path = os.path.join(temp_dir, f"f0ckm_remote_{int(time.time())}_{clean_name}")
|
||||
|
||||
received = 0
|
||||
chunk_size = 32768
|
||||
with open(temp_path, "wb") as f:
|
||||
while True:
|
||||
if self.aborted:
|
||||
print("[f0ckm-gui] [DOWNLOAD ABORTED]", flush=True)
|
||||
self.finished.emit(False, "ABORTED")
|
||||
return
|
||||
chunk = resp.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
f.write(chunk)
|
||||
received += len(chunk)
|
||||
self.progress.emit(received, total_size)
|
||||
|
||||
print(f"[f0ckm-gui] [DOWNLOAD COMPLETE] Saved remote file to: {temp_path} ({received} bytes)", flush=True)
|
||||
self.finished.emit(True, temp_path)
|
||||
except Exception as e:
|
||||
print(f"[f0ckm-gui] [DOWNLOAD ERROR] Failed to fetch {self.url}: {e}", flush=True)
|
||||
if self.aborted:
|
||||
self.finished.emit(False, "ABORTED")
|
||||
else:
|
||||
self.finished.emit(False, str(e))
|
||||
|
||||
class StreamingUploadThread(QThread):
|
||||
progress = Signal(int, int) # bytes_sent, bytes_total
|
||||
finished = Signal(bool, str) # success, response_or_error_msg
|
||||
@@ -1072,6 +1270,7 @@ class StreamingUploadThread(QThread):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
print(f"[f0ckm-gui] [UPLOAD START] File: '{self.file_path}' -> Target API: '{self.api_url}'", flush=True)
|
||||
fields = {
|
||||
"rating": self.rating,
|
||||
"tags": self.tags,
|
||||
@@ -1232,6 +1431,10 @@ class SystemTrayApp(QObject):
|
||||
upload_action.triggered.connect(self.on_upload_file)
|
||||
self.menu.addAction(upload_action)
|
||||
|
||||
upload_url_action = QAction("Upload URL...", self.menu)
|
||||
upload_url_action.triggered.connect(self.on_upload_url)
|
||||
self.menu.addAction(upload_url_action)
|
||||
|
||||
clipboard_action = QAction("Upload from Clipboard", self.menu)
|
||||
clipboard_action.triggered.connect(self.on_upload_clipboard)
|
||||
self.menu.addAction(clipboard_action)
|
||||
@@ -1257,10 +1460,18 @@ class SystemTrayApp(QObject):
|
||||
|
||||
self.tray.setContextMenu(self.menu)
|
||||
self.tray.activated.connect(self.on_tray_activated)
|
||||
self.last_uploaded_url = ""
|
||||
self.tray.messageClicked.connect(self.on_notification_clicked)
|
||||
|
||||
self.settings_dialog = None
|
||||
self.gallery_window = None
|
||||
|
||||
def on_notification_clicked(self):
|
||||
url = getattr(self, "last_uploaded_url", "")
|
||||
if url:
|
||||
print(f"[f0ckm-gui] Notification clicked -> Opening URL in browser: '{url}'", flush=True)
|
||||
QDesktopServices.openUrl(QUrl(url))
|
||||
|
||||
def on_open_gallery(self):
|
||||
if self.gallery_window is None:
|
||||
self.gallery_window = GalleryWindow()
|
||||
@@ -1327,11 +1538,114 @@ class SystemTrayApp(QObject):
|
||||
self.upload_file_direct(save_path)
|
||||
|
||||
def on_abort_upload(self):
|
||||
if hasattr(self, "download_thread") and self.download_thread and self.download_thread.isRunning():
|
||||
self.download_thread.abort()
|
||||
if self.current_reply and self.current_reply.isRunning():
|
||||
self.current_reply.abort()
|
||||
elif hasattr(self, "upload_thread") and self.upload_thread:
|
||||
elif hasattr(self, "upload_thread") and self.upload_thread and self.upload_thread.isRunning():
|
||||
self.upload_thread.abort()
|
||||
|
||||
def upload_target_direct(self, target):
|
||||
target_str, is_url = parse_upload_target(target)
|
||||
print(f"[f0ckm-gui] [TRAY ACTION] Received target: '{target}' -> target_str='{target_str}', is_url={is_url}", flush=True)
|
||||
if not target_str:
|
||||
return
|
||||
if is_url:
|
||||
self.download_and_upload_url(target_str)
|
||||
else:
|
||||
self.upload_file_direct(target_str)
|
||||
|
||||
def download_and_upload_url(self, url):
|
||||
config = get_env_config()
|
||||
api_url = config.get("api_url", "")
|
||||
api_key = config.get("api_key", "")
|
||||
rating = config.get("default_rating", "")
|
||||
tags = config.get("default_tags", "")
|
||||
visibility = config.get("default_visibility", "0")
|
||||
is_oc = config.get("default_is_oc", False)
|
||||
|
||||
print(f"[f0ckm-gui] [URL UPLOAD] Initiating URL upload: '{url}' (API URL: '{api_url}')", flush=True)
|
||||
if not api_url or not api_key:
|
||||
print(f"[f0ckm-gui] [CONFIG ERROR] API URL or API Key missing in configuration!", flush=True)
|
||||
self.show_message("Upload Error", "API URL and API Key must be set in Settings.", QSystemTrayIcon.Critical)
|
||||
return
|
||||
|
||||
self.download_url = url
|
||||
self.download_start_time = time.time()
|
||||
self.tray.setIcon(create_digit_icon(50))
|
||||
self.tray.setToolTip(f"Uploading URL to f0ckm...\n{url[:45]}")
|
||||
|
||||
self.url_post_thread = URLPostThread(api_url, api_key, url, rating, tags, visibility, is_oc)
|
||||
self.url_post_thread.finished.connect(lambda ok, res: self.on_url_post_finished(ok, res, url))
|
||||
self.url_post_thread.start()
|
||||
self.abort_action.setEnabled(True)
|
||||
|
||||
def on_url_post_finished(self, ok, result, url):
|
||||
if ok:
|
||||
try:
|
||||
data = json.loads(result)
|
||||
if data.get("success") and (data.get("url") or data.get("file_url") or data.get("direct_url") or data.get("post_url") or data.get("file")):
|
||||
post_url = data.get("url") or data.get("post_url") or ""
|
||||
direct_url = data.get("file_url") or data.get("direct_url") or data.get("file") or ""
|
||||
config = get_env_config()
|
||||
url_type = config.get("clipboard_url_type", "post").lower()
|
||||
final_url = direct_url if (url_type == "direct" and direct_url) else (post_url or direct_url)
|
||||
|
||||
copy_to_clipboard(final_url)
|
||||
play_success_sound(config.get("sound_file"), config.get("sound_volume"))
|
||||
|
||||
entry = {
|
||||
"timestamp": int(time.time()),
|
||||
"file_path": url,
|
||||
"file_name": url.split("/")[-1] or "url_upload",
|
||||
"file_size": 0,
|
||||
"url": final_url,
|
||||
"post_url": post_url,
|
||||
"file_url": direct_url
|
||||
}
|
||||
add_history_entry(entry)
|
||||
|
||||
self.abort_action.setEnabled(False)
|
||||
self.tray.setIcon(self.default_icon)
|
||||
self.tray.setToolTip("f0ckm Uploader (Click to capture & upload)")
|
||||
self.last_uploaded_url = final_url
|
||||
self.show_success_notification(url, final_url)
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"[f0ckm-gui] JSON parse notice: {e}", flush=True)
|
||||
|
||||
print(f"[f0ckm-gui] Direct URL API notice: Falling back to local download of '{url}'", flush=True)
|
||||
self.download_thread = StreamingDownloadThread(url)
|
||||
self.download_thread.progress.connect(self.on_download_progress)
|
||||
self.download_thread.finished.connect(lambda ok_dl, res_dl: self.on_download_finished(ok_dl, res_dl, url))
|
||||
self.download_thread.start()
|
||||
|
||||
def on_download_progress(self, bytes_received, bytes_total):
|
||||
if bytes_total > 0:
|
||||
pct = min(99, max(0, int((bytes_received / bytes_total) * 100)))
|
||||
self.tray.setIcon(create_digit_icon(pct))
|
||||
rec_str = format_size(bytes_received)
|
||||
tot_str = format_size(bytes_total)
|
||||
url_str = getattr(self, "download_url", "")
|
||||
short_url = (url_str[:35] + "...") if len(url_str) > 35 else url_str
|
||||
self.tray.setToolTip(f"Downloading: {short_url}\n{pct}% ({rec_str} / {tot_str})")
|
||||
else:
|
||||
rec_str = format_size(bytes_received)
|
||||
self.tray.setToolTip(f"Downloading remote file...\n{rec_str}")
|
||||
|
||||
def on_download_finished(self, success, result, url):
|
||||
if not success:
|
||||
self.abort_action.setEnabled(False)
|
||||
self.tray.setIcon(self.default_icon)
|
||||
self.tray.setToolTip("f0ckm Uploader (Click to capture & upload)")
|
||||
if result == "ABORTED":
|
||||
self.show_message("Download Aborted", "Remote URL download was canceled.", QSystemTrayIcon.Information)
|
||||
else:
|
||||
self.show_message("Download Failed", f"Failed to download remote URL: {result}", QSystemTrayIcon.Critical)
|
||||
return
|
||||
|
||||
self.upload_file_direct(result)
|
||||
|
||||
def upload_file_direct(self, file_path):
|
||||
file_path = normalize_file_path(file_path)
|
||||
if not file_path or not os.path.exists(file_path):
|
||||
@@ -1464,6 +1778,7 @@ class SystemTrayApp(QObject):
|
||||
self.show_message("Upload Error", f"Error parsing response: {e}\nResponse: {response_text}", QSystemTrayIcon.Critical)
|
||||
|
||||
def show_success_notification(self, file_path, item_url):
|
||||
self.last_uploaded_url = item_url
|
||||
config = get_env_config()
|
||||
if config.get("play_success_sound", False) or config.get("success_audio_path"):
|
||||
audio_path = config.get("success_audio_path", "")
|
||||
@@ -1525,6 +1840,11 @@ class SystemTrayApp(QObject):
|
||||
)
|
||||
if file_path:
|
||||
self.upload_file_direct(file_path)
|
||||
|
||||
def on_upload_url(self):
|
||||
url, ok = QInputDialog.getText(None, "Upload URL", "Enter image or file URL:")
|
||||
if ok and url.strip():
|
||||
self.upload_target_direct(url.strip())
|
||||
|
||||
def on_upload_clipboard(self):
|
||||
clipboard = QApplication.clipboard()
|
||||
@@ -1586,14 +1906,19 @@ class SingleInstanceApp:
|
||||
if arg in ("--spectacle", "-s"):
|
||||
msg = "spectacle"
|
||||
elif arg.startswith("--upload="):
|
||||
msg = f"upload:{arg[9:]}"
|
||||
target, _ = parse_upload_target(arg[9:])
|
||||
msg = f"upload:{target}"
|
||||
elif arg.startswith("--upload"):
|
||||
if len(sys.argv) > 2:
|
||||
msg = f"upload:{sys.argv[2]}"
|
||||
target, _ = parse_upload_target(sys.argv[2])
|
||||
msg = f"upload:{target}"
|
||||
else:
|
||||
msg = "show"
|
||||
else:
|
||||
norm = normalize_file_path(arg)
|
||||
if os.path.exists(norm):
|
||||
msg = f"upload:{norm}"
|
||||
target, _ = parse_upload_target(arg)
|
||||
if target:
|
||||
msg = f"upload:{target}"
|
||||
print(f"[f0ckm-gui] [IPC CLIENT] Daemon running. Forwarding message via socket: '{msg}'", flush=True)
|
||||
socket.write(msg.encode("utf-8"))
|
||||
socket.waitForBytesWritten(500)
|
||||
socket.disconnectFromServer()
|
||||
@@ -1603,6 +1928,7 @@ class SingleInstanceApp:
|
||||
if not self.server.listen(self.name):
|
||||
return False
|
||||
|
||||
print(f"[f0ckm-gui] [IPC SERVER] Started single-instance IPC listener socket server: '{self.name}'", flush=True)
|
||||
self.server.newConnection.connect(lambda: self._handle_connection(callback_on_message))
|
||||
return True
|
||||
|
||||
@@ -1613,6 +1939,7 @@ class SingleInstanceApp:
|
||||
|
||||
def _read_message(self, socket, callback):
|
||||
data = socket.readAll().data().decode("utf-8").strip()
|
||||
print(f"[f0ckm-gui] [IPC SERVER] Received message from socket: '{data}'", flush=True)
|
||||
callback(data)
|
||||
socket.disconnectFromServer()
|
||||
|
||||
@@ -1637,11 +1964,8 @@ def main():
|
||||
if msg_str == "spectacle":
|
||||
tray_app.on_capture_and_upload()
|
||||
elif msg_str.startswith("upload:"):
|
||||
file_path = normalize_file_path(msg_str[7:])
|
||||
if os.path.exists(file_path):
|
||||
tray_app.upload_file_direct(file_path)
|
||||
else:
|
||||
tray_app.show_message("Upload Error", f"File not found: {file_path}", QSystemTrayIcon.Critical)
|
||||
target = msg_str[7:]
|
||||
tray_app.upload_target_direct(target)
|
||||
else:
|
||||
tray_app.on_open_settings()
|
||||
|
||||
@@ -1652,7 +1976,9 @@ def main():
|
||||
save_config(DEFAULT_CONFIG)
|
||||
|
||||
tray_app = SystemTrayApp()
|
||||
local_http_bridge.request_upload.connect(tray_app.upload_target_direct)
|
||||
tray_app.show()
|
||||
start_local_http_server(tray_app)
|
||||
|
||||
# Check if started with action argument
|
||||
if len(sys.argv) > 1:
|
||||
@@ -1660,16 +1986,16 @@ def main():
|
||||
if arg in ("--spectacle", "-s"):
|
||||
tray_app.on_capture_and_upload()
|
||||
elif arg.startswith("--upload="):
|
||||
file_path = normalize_file_path(arg[9:])
|
||||
tray_app.upload_file_direct(file_path)
|
||||
target, _ = parse_upload_target(arg[9:])
|
||||
tray_app.upload_target_direct(target)
|
||||
elif arg.startswith("--upload"):
|
||||
if len(sys.argv) > 2:
|
||||
file_path = normalize_file_path(sys.argv[2])
|
||||
tray_app.upload_file_direct(file_path)
|
||||
target, _ = parse_upload_target(sys.argv[2])
|
||||
tray_app.upload_target_direct(target)
|
||||
else:
|
||||
norm = normalize_file_path(arg)
|
||||
if os.path.exists(norm):
|
||||
tray_app.upload_file_direct(norm)
|
||||
target, _ = parse_upload_target(arg)
|
||||
if target:
|
||||
tray_app.upload_target_direct(target)
|
||||
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user