add queue functionality to upload many items and update readme to include basic installation guide
This commit is contained in:
317
gui.py
317
gui.py
@@ -73,6 +73,34 @@ def parse_upload_target(arg: str) -> tuple[str, bool]:
|
||||
print(f"[f0ckm-gui] [PARSE] File path parsed: '{arg}' -> norm='{norm}' (is_url=False)", flush=True)
|
||||
return (norm, False)
|
||||
|
||||
def parse_cli_args(args: list[str]) -> tuple[str, list[str]]:
|
||||
if not args:
|
||||
return ("show", [])
|
||||
|
||||
targets = []
|
||||
action = "show"
|
||||
|
||||
for arg in args:
|
||||
arg_str = arg.strip()
|
||||
if not arg_str:
|
||||
continue
|
||||
if arg_str in ("--spectacle", "-s"):
|
||||
action = "spectacle"
|
||||
elif arg_str.startswith("--upload="):
|
||||
action = "upload"
|
||||
t, _ = parse_upload_target(arg_str[9:])
|
||||
if t:
|
||||
targets.append(t)
|
||||
elif arg_str == "--upload":
|
||||
action = "upload"
|
||||
else:
|
||||
t, _ = parse_upload_target(arg_str)
|
||||
if t:
|
||||
action = "upload"
|
||||
targets.append(t)
|
||||
|
||||
return (action, targets)
|
||||
|
||||
class LocalHTTPBridge(QObject):
|
||||
request_upload = Signal(str)
|
||||
|
||||
@@ -1417,6 +1445,14 @@ class SystemTrayApp(QObject):
|
||||
self.network_manager = QNetworkAccessManager(self)
|
||||
self.current_reply = None
|
||||
|
||||
# Queue system state
|
||||
self.upload_queue = [] # List of tuples: (target_str, is_url)
|
||||
self.is_uploading = False
|
||||
self.active_thread = None
|
||||
self.current_target = None
|
||||
self.total_queue_count = 0
|
||||
self.current_item_index = 0
|
||||
|
||||
self.menu = QMenu()
|
||||
|
||||
# Header entry
|
||||
@@ -1469,6 +1505,63 @@ class SystemTrayApp(QObject):
|
||||
self.settings_dialog = None
|
||||
self.gallery_window = None
|
||||
|
||||
def enqueue_targets(self, targets):
|
||||
if isinstance(targets, str):
|
||||
targets = [targets]
|
||||
valid_targets = []
|
||||
for t in targets:
|
||||
target_str, is_url = parse_upload_target(t)
|
||||
if target_str:
|
||||
valid_targets.append((target_str, is_url))
|
||||
|
||||
if not valid_targets:
|
||||
return
|
||||
|
||||
if not self.is_uploading and len(self.upload_queue) == 0:
|
||||
self.total_queue_count = len(valid_targets)
|
||||
self.current_item_index = 0
|
||||
self.upload_queue.extend(valid_targets)
|
||||
self.process_next_in_queue()
|
||||
else:
|
||||
self.upload_queue.extend(valid_targets)
|
||||
self.total_queue_count += len(valid_targets)
|
||||
print(f"[f0ckm-gui] [QUEUE] Enqueued {len(valid_targets)} items. Total in queue: {len(self.upload_queue)} (Batch total: {self.total_queue_count})", flush=True)
|
||||
|
||||
def process_next_in_queue(self):
|
||||
if len(self.upload_queue) == 0:
|
||||
self.is_uploading = False
|
||||
self.current_target = None
|
||||
self.active_thread = None
|
||||
self.total_queue_count = 0
|
||||
self.current_item_index = 0
|
||||
self.abort_action.setEnabled(False)
|
||||
self.tray.setIcon(self.default_icon)
|
||||
self.tray.setToolTip("f0ckm Uploader (Click to capture & upload)")
|
||||
return
|
||||
|
||||
target_tuple = self.upload_queue.pop(0)
|
||||
target_str, is_url = target_tuple
|
||||
self.is_uploading = True
|
||||
self.current_target = target_str
|
||||
self.current_item_index += 1
|
||||
self.abort_action.setEnabled(True)
|
||||
|
||||
print(f"[f0ckm-gui] [QUEUE ITEM {self.current_item_index}/{self.total_queue_count}] Processing target: '{target_str}' (is_url={is_url})", flush=True)
|
||||
|
||||
if is_url:
|
||||
self.download_and_upload_url(target_str)
|
||||
else:
|
||||
self.upload_file_direct(target_str)
|
||||
|
||||
def _on_single_task_complete(self):
|
||||
if self.active_thread:
|
||||
try:
|
||||
self.active_thread.deleteLater()
|
||||
except Exception:
|
||||
pass
|
||||
self.active_thread = None
|
||||
QTimer.singleShot(50, self.process_next_in_queue)
|
||||
|
||||
def on_notification_clicked(self):
|
||||
url = getattr(self, "last_uploaded_url", "")
|
||||
if url:
|
||||
@@ -1527,36 +1620,34 @@ class SystemTrayApp(QObject):
|
||||
def on_capture_and_upload(self):
|
||||
screenshot_dir = os.path.expanduser("~/Pictures/Screenshots")
|
||||
os.makedirs(screenshot_dir, exist_ok=True)
|
||||
save_path = os.path.join(screenshot_dir, f"screenshot_{time.strftime('%Y%m%d_%H%M%S')}.png")
|
||||
ts = time.strftime('%Y%m%d_%H%M%S')
|
||||
ms = int(time.time() * 1000) % 1000
|
||||
save_path = os.path.join(screenshot_dir, f"screenshot_{ts}_{ms:03d}.png")
|
||||
|
||||
try:
|
||||
self.spectacle_proc = QProcess(self)
|
||||
self.spectacle_proc.finished.connect(lambda exit_code, exit_status: self._on_spectacle_finished(save_path, exit_code))
|
||||
self.spectacle_proc.start("spectacle", ["-r", "-b", "-n", "-o", save_path])
|
||||
proc = QProcess(self)
|
||||
proc.finished.connect(lambda exit_code, exit_status, p=proc, sp=save_path: self._on_spectacle_finished(p, sp, exit_code))
|
||||
proc.start("spectacle", ["-r", "-b", "-n", "-o", save_path])
|
||||
except Exception as e:
|
||||
self.show_message("Upload Error", f"Failed to capture screenshot: {e}", QSystemTrayIcon.Critical)
|
||||
|
||||
def _on_spectacle_finished(self, save_path, exit_code):
|
||||
def _on_spectacle_finished(self, proc, save_path, exit_code):
|
||||
proc.deleteLater()
|
||||
if os.path.exists(save_path) and os.path.getsize(save_path) > 0:
|
||||
self.upload_file_direct(save_path)
|
||||
self.enqueue_targets([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()
|
||||
print(f"[f0ckm-gui] [QUEUE] Abort requested. Clearing queue ({len(self.upload_queue)} remaining items) and stopping active upload.", flush=True)
|
||||
self.upload_queue.clear()
|
||||
self.total_queue_count = 0
|
||||
self.current_item_index = 0
|
||||
if self.active_thread and hasattr(self.active_thread, "abort"):
|
||||
self.active_thread.abort()
|
||||
if self.current_reply and self.current_reply.isRunning():
|
||||
self.current_reply.abort()
|
||||
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)
|
||||
self.enqueue_targets([target])
|
||||
|
||||
def download_and_upload_url(self, url):
|
||||
config = get_env_config()
|
||||
@@ -1571,17 +1662,20 @@ class SystemTrayApp(QObject):
|
||||
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)
|
||||
QTimer.singleShot(100, self._on_single_task_complete)
|
||||
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)
|
||||
batch_prefix = f"[{self.current_item_index}/{self.total_queue_count}] " if self.total_queue_count > 1 else ""
|
||||
rem_str = f"\n({len(self.upload_queue)} waiting in queue)" if self.upload_queue else ""
|
||||
self.tray.setToolTip(f"Uploading URL {batch_prefix}to f0ckm...\n{url[:45]}{rem_str}")
|
||||
|
||||
self.active_thread = URLPostThread(api_url, api_key, url, rating, tags, visibility, is_oc)
|
||||
self.active_thread.finished.connect(lambda ok, res: self.on_url_post_finished(ok, res, url))
|
||||
self.active_thread.start()
|
||||
|
||||
def on_url_post_finished(self, ok, result, url):
|
||||
if ok:
|
||||
@@ -1608,22 +1702,22 @@ class SystemTrayApp(QObject):
|
||||
}
|
||||
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)
|
||||
self._on_single_task_complete()
|
||||
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()
|
||||
self.active_thread = StreamingDownloadThread(url)
|
||||
self.active_thread.progress.connect(self.on_download_progress)
|
||||
self.active_thread.finished.connect(lambda ok_dl, res_dl: self.on_download_finished(ok_dl, res_dl, url))
|
||||
self.active_thread.start()
|
||||
|
||||
def on_download_progress(self, bytes_received, bytes_total):
|
||||
batch_prefix = f"[{self.current_item_index}/{self.total_queue_count}] " if self.total_queue_count > 1 else ""
|
||||
rem_str = f"\n({len(self.upload_queue)} waiting in queue)" if self.upload_queue else ""
|
||||
if bytes_total > 0:
|
||||
pct = min(99, max(0, int((bytes_received / bytes_total) * 100)))
|
||||
self.tray.setIcon(create_digit_icon(pct))
|
||||
@@ -1631,20 +1725,18 @@ class SystemTrayApp(QObject):
|
||||
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})")
|
||||
self.tray.setToolTip(f"Downloading {batch_prefix}: {short_url}\n{pct}% ({rec_str} / {tot_str}){rem_str}")
|
||||
else:
|
||||
rec_str = format_size(bytes_received)
|
||||
self.tray.setToolTip(f"Downloading remote file...\n{rec_str}")
|
||||
self.tray.setToolTip(f"Downloading remote file {batch_prefix}...\n{rec_str}{rem_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)
|
||||
self._on_single_task_complete()
|
||||
return
|
||||
|
||||
self.upload_file_direct(result)
|
||||
@@ -1653,6 +1745,7 @@ class SystemTrayApp(QObject):
|
||||
file_path = normalize_file_path(file_path)
|
||||
if not file_path or not os.path.exists(file_path):
|
||||
self.show_message("Upload Error", f"File not found: {file_path}", QSystemTrayIcon.Critical)
|
||||
QTimer.singleShot(100, self._on_single_task_complete)
|
||||
return
|
||||
|
||||
config = get_env_config()
|
||||
@@ -1660,6 +1753,7 @@ class SystemTrayApp(QObject):
|
||||
api_key = config.get("api_key", "")
|
||||
if not api_url or not api_key:
|
||||
self.show_message("Upload Error", "API URL and API Key must be set in Settings.", QSystemTrayIcon.Critical)
|
||||
QTimer.singleShot(100, self._on_single_task_complete)
|
||||
return
|
||||
|
||||
rating = config.get("default_rating", "")
|
||||
@@ -1676,29 +1770,15 @@ class SystemTrayApp(QObject):
|
||||
self.upload_start_time = time.time()
|
||||
|
||||
self.tray.setIcon(create_digit_icon(0))
|
||||
self.tray.setToolTip(f"Uploading {filename}...\n0% (0 B)")
|
||||
|
||||
self.upload_thread = StreamingUploadThread(api_url, api_key, file_path, rating, tags, visibility, is_oc)
|
||||
self.upload_thread.progress.connect(self.on_upload_progress)
|
||||
self.upload_thread.finished.connect(lambda ok, resp: self.on_upload_finished(ok, resp, file_path))
|
||||
self.upload_thread.start()
|
||||
batch_prefix = f"[{self.current_item_index}/{self.total_queue_count}] " if self.total_queue_count > 1 else ""
|
||||
rem_str = f"\n({len(self.upload_queue)} waiting in queue)" if self.upload_queue else ""
|
||||
self.tray.setToolTip(f"Uploading {batch_prefix}{filename}...\n0% (0 B){rem_str}")
|
||||
|
||||
self.abort_action.setEnabled(True)
|
||||
|
||||
def _on_qt_reply_finished(self, reply, file_path):
|
||||
self.current_reply = None
|
||||
err = reply.error()
|
||||
if err == QNetworkReply.NetworkError.NoError:
|
||||
resp_bytes = reply.readAll().data()
|
||||
resp_str = resp_bytes.decode('utf-8', errors='replace')
|
||||
self.on_upload_finished(True, resp_str, file_path)
|
||||
else:
|
||||
if err == QNetworkReply.NetworkError.OperationCanceledError:
|
||||
self.on_upload_finished(False, "ABORTED", file_path)
|
||||
else:
|
||||
resp_bytes = reply.readAll().data()
|
||||
resp_str = resp_bytes.decode('utf-8', errors='replace') if resp_bytes else reply.errorString()
|
||||
self.on_upload_finished(False, resp_str, file_path)
|
||||
self.active_thread = StreamingUploadThread(api_url, api_key, file_path, rating, tags, visibility, is_oc)
|
||||
self.active_thread.progress.connect(self.on_upload_progress)
|
||||
self.active_thread.finished.connect(lambda ok, resp: self.on_upload_finished(ok, resp, file_path))
|
||||
self.active_thread.start()
|
||||
|
||||
def on_upload_progress(self, bytes_sent, bytes_total):
|
||||
if bytes_total > 0:
|
||||
@@ -1712,8 +1792,12 @@ class SystemTrayApp(QObject):
|
||||
total_str = format_size(bytes_total)
|
||||
filename = getattr(self, "upload_filename", "file")
|
||||
|
||||
batch_prefix = f"[{self.current_item_index}/{self.total_queue_count}] " if self.total_queue_count > 1 else ""
|
||||
remaining = len(self.upload_queue)
|
||||
rem_str = f"\n({remaining} waiting in queue)" if remaining > 0 else ""
|
||||
|
||||
if pct >= 99:
|
||||
tooltip = f"Uploading: {filename}\n99% ({total_str})\nProcessing upload on server..."
|
||||
tooltip = f"Uploading {batch_prefix}: {filename}\n99% ({total_str})\nProcessing upload on server...{rem_str}"
|
||||
else:
|
||||
speed_str = format_speed(speed)
|
||||
remaining_bytes = bytes_total - bytes_sent
|
||||
@@ -1725,24 +1809,17 @@ class SystemTrayApp(QObject):
|
||||
else:
|
||||
eta_str = f"{eta_sec // 3600}h {(eta_sec % 3600) // 60}m"
|
||||
|
||||
tooltip = f"Uploading: {filename}\n{pct}% ({sent_str} / {total_str})\nSpeed: {speed_str} | ETA: {eta_str}"
|
||||
tooltip = f"Uploading {batch_prefix}: {filename}\n{pct}% ({sent_str} / {total_str})\nSpeed: {speed_str} | ETA: {eta_str}{rem_str}"
|
||||
|
||||
self.tray.setToolTip(tooltip)
|
||||
|
||||
def on_abort_upload(self):
|
||||
if hasattr(self, "upload_thread") and self.upload_thread:
|
||||
self.upload_thread.abort()
|
||||
|
||||
def on_upload_finished(self, success, response_text, file_path):
|
||||
self.abort_action.setEnabled(False)
|
||||
self.tray.setIcon(self.default_icon)
|
||||
self.tray.setToolTip("f0ckm Uploader (Click to capture & upload)")
|
||||
|
||||
if not success:
|
||||
if response_text == "ABORTED":
|
||||
self.show_message("Upload Aborted", "The active upload was canceled.", QSystemTrayIcon.Information)
|
||||
else:
|
||||
self.show_message("Upload Failed", response_text, QSystemTrayIcon.Critical)
|
||||
self._on_single_task_complete()
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -1779,6 +1856,8 @@ class SystemTrayApp(QObject):
|
||||
self.show_message("Upload Failed", msg, QSystemTrayIcon.Critical)
|
||||
except Exception as e:
|
||||
self.show_message("Upload Error", f"Error parsing response: {e}\nResponse: {response_text}", QSystemTrayIcon.Critical)
|
||||
finally:
|
||||
self._on_single_task_complete()
|
||||
|
||||
def show_success_notification(self, file_path, item_url):
|
||||
self.last_uploaded_url = item_url
|
||||
@@ -1838,16 +1917,16 @@ class SystemTrayApp(QObject):
|
||||
print(f"Notification error: {e}")
|
||||
|
||||
def on_upload_file(self):
|
||||
file_path, _ = QFileDialog.getOpenFileName(
|
||||
None, "Select File to Upload", "", "All Files (*)"
|
||||
file_paths, _ = QFileDialog.getOpenFileNames(
|
||||
None, "Select Files to Upload", "", "All Files (*)"
|
||||
)
|
||||
if file_path:
|
||||
self.upload_file_direct(file_path)
|
||||
if file_paths:
|
||||
self.enqueue_targets(file_paths)
|
||||
|
||||
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())
|
||||
self.enqueue_targets([url.strip()])
|
||||
|
||||
def on_upload_clipboard(self):
|
||||
clipboard = QApplication.clipboard()
|
||||
@@ -1856,36 +1935,41 @@ class SystemTrayApp(QObject):
|
||||
if mime_data.hasImage():
|
||||
image = clipboard.image()
|
||||
temp_dir = tempfile.gettempdir()
|
||||
temp_path = os.path.join(temp_dir, f"f0ckm_clipboard_{int(time.time())}.png")
|
||||
ts = time.strftime('%Y%m%d_%H%M%S')
|
||||
ms = int(time.time() * 1000) % 1000
|
||||
temp_path = os.path.join(temp_dir, f"f0ckm_clipboard_{ts}_{ms:03d}.png")
|
||||
if image.save(temp_path, "PNG"):
|
||||
self.upload_file_direct(temp_path)
|
||||
self.enqueue_targets([temp_path])
|
||||
else:
|
||||
self.show_message("Upload Error", "Failed to save clipboard image to temporary file.", QSystemTrayIcon.Critical)
|
||||
elif mime_data.hasUrls():
|
||||
urls = mime_data.urls()
|
||||
uploaded_any = False
|
||||
valid_paths = []
|
||||
for url in urls:
|
||||
if url.isLocalFile():
|
||||
path = url.toLocalFile()
|
||||
if os.path.exists(path):
|
||||
self.upload_file_direct(path)
|
||||
uploaded_any = True
|
||||
if not uploaded_any:
|
||||
valid_paths.append(path)
|
||||
if valid_paths:
|
||||
self.enqueue_targets(valid_paths)
|
||||
else:
|
||||
self.show_message("Upload Error", "No valid local files in clipboard.", QSystemTrayIcon.Warning)
|
||||
elif mime_data.hasText():
|
||||
text = mime_data.text().strip()
|
||||
lines = [l.strip() for l in text.split('\n') if l.strip()]
|
||||
uploaded_any = False
|
||||
valid_targets = []
|
||||
for line in lines:
|
||||
if line.startswith("file://"):
|
||||
line = line[7:]
|
||||
if os.path.exists(line):
|
||||
self.upload_file_direct(line)
|
||||
uploaded_any = True
|
||||
if not uploaded_any:
|
||||
self.show_message("Upload Error", "Clipboard text is not a valid local file path.", QSystemTrayIcon.Warning)
|
||||
t, _ = parse_upload_target(line)
|
||||
if t:
|
||||
valid_targets.append(t)
|
||||
if valid_targets:
|
||||
self.enqueue_targets(valid_targets)
|
||||
else:
|
||||
self.show_message("Upload Error", "Clipboard text does not contain valid file paths or URLs.", QSystemTrayIcon.Warning)
|
||||
else:
|
||||
self.show_message("Upload Error", "Clipboard does not contain an image or file paths.", QSystemTrayIcon.Warning)
|
||||
self.show_message("Upload Error", "Clipboard does not contain an image, files, or URLs.", QSystemTrayIcon.Warning)
|
||||
|
||||
def show_message(self, title, message, icon=QSystemTrayIcon.Information):
|
||||
self.tray.showMessage(title, message, icon, 5000)
|
||||
@@ -1903,26 +1987,10 @@ class SingleInstanceApp:
|
||||
socket = QLocalSocket()
|
||||
socket.connectToServer(self.name)
|
||||
if socket.waitForConnected(500):
|
||||
msg = "show"
|
||||
if len(sys.argv) > 1:
|
||||
arg = sys.argv[1]
|
||||
if arg in ("--spectacle", "-s"):
|
||||
msg = "spectacle"
|
||||
elif arg.startswith("--upload="):
|
||||
target, _ = parse_upload_target(arg[9:])
|
||||
msg = f"upload:{target}"
|
||||
elif arg.startswith("--upload"):
|
||||
if len(sys.argv) > 2:
|
||||
target, _ = parse_upload_target(sys.argv[2])
|
||||
msg = f"upload:{target}"
|
||||
else:
|
||||
msg = "show"
|
||||
else:
|
||||
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"))
|
||||
action, targets = parse_cli_args(sys.argv[1:])
|
||||
payload = json.dumps({"action": action, "targets": targets})
|
||||
print(f"[f0ckm-gui] [IPC CLIENT] Daemon running. Forwarding payload via socket: '{payload}'", flush=True)
|
||||
socket.write(payload.encode("utf-8"))
|
||||
socket.waitForBytesWritten(500)
|
||||
socket.disconnectFromServer()
|
||||
return False
|
||||
@@ -1964,11 +2032,26 @@ def main():
|
||||
def on_activate(msg_str):
|
||||
nonlocal tray_app
|
||||
if tray_app:
|
||||
if msg_str.startswith("{"):
|
||||
try:
|
||||
data = json.loads(msg_str)
|
||||
act = data.get("action", "show")
|
||||
targets = data.get("targets", [])
|
||||
if act == "spectacle":
|
||||
tray_app.on_capture_and_upload()
|
||||
elif act == "upload" and targets:
|
||||
tray_app.enqueue_targets(targets)
|
||||
else:
|
||||
tray_app.on_open_settings()
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"[f0ckm-gui] IPC JSON parse notice: {e}", flush=True)
|
||||
|
||||
if msg_str == "spectacle":
|
||||
tray_app.on_capture_and_upload()
|
||||
elif msg_str.startswith("upload:"):
|
||||
target = msg_str[7:]
|
||||
tray_app.upload_target_direct(target)
|
||||
tray_app.enqueue_targets([target])
|
||||
else:
|
||||
tray_app.on_open_settings()
|
||||
|
||||
@@ -1982,28 +2065,24 @@ def main():
|
||||
set_autostart(cfg.get("autostart", False))
|
||||
|
||||
tray_app = SystemTrayApp()
|
||||
local_http_bridge.request_upload.connect(tray_app.upload_target_direct)
|
||||
local_http_bridge.request_upload.connect(lambda url: tray_app.enqueue_targets([url]))
|
||||
tray_app.show()
|
||||
start_local_http_server(tray_app)
|
||||
|
||||
# Check if started with action argument
|
||||
if len(sys.argv) > 1:
|
||||
arg = sys.argv[1]
|
||||
if arg in ("--spectacle", "-s"):
|
||||
action, targets = parse_cli_args(sys.argv[1:])
|
||||
if action == "spectacle":
|
||||
tray_app.on_capture_and_upload()
|
||||
elif arg.startswith("--upload="):
|
||||
target, _ = parse_upload_target(arg[9:])
|
||||
tray_app.upload_target_direct(target)
|
||||
elif arg.startswith("--upload"):
|
||||
if len(sys.argv) > 2:
|
||||
target, _ = parse_upload_target(sys.argv[2])
|
||||
tray_app.upload_target_direct(target)
|
||||
else:
|
||||
target, _ = parse_upload_target(arg)
|
||||
if target:
|
||||
tray_app.upload_target_direct(target)
|
||||
elif action == "upload" and targets:
|
||||
tray_app.enqueue_targets(targets)
|
||||
else:
|
||||
if not cfg.get("api_url") or not cfg.get("api_key"):
|
||||
print("[f0ckm-gui] First launch detected (missing API credentials). Opening settings dialog...", flush=True)
|
||||
QTimer.singleShot(400, tray_app.on_open_settings)
|
||||
|
||||
sys.exit(app.exec())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user