v1.9.0: S3 server type — bucket/object browser, drag-and-drop upload, resilient transfers
New server type: S3 (MinIO, AWS, any S3-compatible storage) - core/s3_client.py: boto3 client with auto-reconnect, 10 retries, exponential backoff, multipart upload/download, tcp_keepalive - gui/tabs/s3_tab.py: object browser (Treeview), bucket selector, folder navigation, drag-and-drop upload from Explorer (windnd), progress bar with %, multi-file upload - CLI: --s3-buckets, --s3-ls, --s3-upload, --s3-download, --s3-delete with retry - ServerDialog: access_key, secret_key, bucket fields - Registration: server_store, connection_factory, status_checker, icons, app, i18n (EN/RU/ZH) - Fix: build.py cleanup_old_releases now sorts by semver (was lexicographic, broke v1.8.100+) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ FIELD_MAP = {
|
||||
"prometheus": ["use_ssl"],
|
||||
"rdp": ["user", "password", "rdp_resolution", "rdp_quality", "rdp_clipboard", "rdp_drives", "rdp_printers"],
|
||||
"vnc": ["password"],
|
||||
"s3": ["access_key", "secret_key", "bucket", "use_ssl"],
|
||||
}
|
||||
|
||||
|
||||
@@ -242,6 +243,27 @@ class ServerDialog(ctk.CTkToplevel):
|
||||
ctk.CTkCheckBox(f, text=t("rdp_printers"), variable=self._rdp_printers_var).pack(fill="x", padx=20, pady=(4, 2))
|
||||
self._field_frames["rdp_printers"] = f
|
||||
|
||||
# --- access_key ---
|
||||
f = ctk.CTkFrame(self, fg_color="transparent")
|
||||
ctk.CTkLabel(f, text=t("access_key"), anchor="w").pack(fill="x", **pad)
|
||||
self.access_key_entry = ctk.CTkEntry(f, placeholder_text="AKIAIOSFODNN7EXAMPLE")
|
||||
self.access_key_entry.pack(fill="x", **entry_pad)
|
||||
self._field_frames["access_key"] = f
|
||||
|
||||
# --- secret_key ---
|
||||
f = ctk.CTkFrame(self, fg_color="transparent")
|
||||
ctk.CTkLabel(f, text=t("secret_key"), anchor="w").pack(fill="x", **pad)
|
||||
self.secret_key_entry = ctk.CTkEntry(f, show="*", placeholder_text=t("placeholder_secret_key"))
|
||||
self.secret_key_entry.pack(fill="x", **entry_pad)
|
||||
self._field_frames["secret_key"] = f
|
||||
|
||||
# --- bucket ---
|
||||
f = ctk.CTkFrame(self, fg_color="transparent")
|
||||
ctk.CTkLabel(f, text=t("bucket"), anchor="w").pack(fill="x", **pad)
|
||||
self.bucket_entry = ctk.CTkEntry(f, placeholder_text="my-bucket")
|
||||
self.bucket_entry.pack(fill="x", **entry_pad)
|
||||
self._field_frames["bucket"] = f
|
||||
|
||||
# --- use_ssl ---
|
||||
f = ctk.CTkFrame(self, fg_color="transparent")
|
||||
self.use_ssl_var = ctk.BooleanVar(value=False)
|
||||
@@ -282,6 +304,9 @@ class ServerDialog(ctk.CTkToplevel):
|
||||
self.db_index_entry.insert(0, str(server.get("db_index", "")))
|
||||
self.api_token_entry.insert(0, server.get("api_token", ""))
|
||||
self.use_ssl_var.set(server.get("use_ssl", False))
|
||||
self.access_key_entry.insert(0, server.get("access_key", ""))
|
||||
self.secret_key_entry.insert(0, server.get("secret_key", ""))
|
||||
self.bucket_entry.insert(0, server.get("bucket", ""))
|
||||
|
||||
# RDP settings
|
||||
res_raw = server.get("rdp_resolution", "auto")
|
||||
@@ -411,6 +436,21 @@ class ServerDialog(ctk.CTkToplevel):
|
||||
if token:
|
||||
server_data["api_token"] = token
|
||||
|
||||
if "access_key" in visible:
|
||||
ak = self.access_key_entry.get().strip()
|
||||
if ak:
|
||||
server_data["access_key"] = ak
|
||||
|
||||
if "secret_key" in visible:
|
||||
sk = self.secret_key_entry.get()
|
||||
if sk:
|
||||
server_data["secret_key"] = sk
|
||||
|
||||
if "bucket" in visible:
|
||||
bkt = self.bucket_entry.get().strip()
|
||||
if bkt:
|
||||
server_data["bucket"] = bkt
|
||||
|
||||
if "use_ssl" in visible:
|
||||
if self.use_ssl_var.get():
|
||||
server_data["use_ssl"] = True
|
||||
|
||||
Reference in New Issue
Block a user