Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ project-specific; CI remains the authority for mechanical formatting rules.
minimum width. On launch, fit the window height to its content when the screen
allows it; show a scrollbar only when the available display height requires
one.
- Preserve tray behavior: left click opens the main window, right click opens
the control menu. Hidden-window polling follows the user's preference; the
independent watchdog remains responsible for background health monitoring.
- Preserve tray behavior: left click toggles the main window between visible
and hidden, right click opens the control menu. Hidden-window polling follows
the user's preference; the independent watchdog remains responsible for
background health monitoring.
- Prefer explanation at the point of confusion. Overview cards should lead to
the relevant detail section, advertise clickability through pointer, hover,
pressed and keyboard-focus states, and distinguish protected pending uploads
Expand Down Expand Up @@ -134,6 +135,25 @@ project-specific; CI remains the authority for mechanical formatting rules.
limiter fixes. The updater must keep that reviewed build until the project
publishes a replacement; never overwrite it with an official binary that
lacks the backend command.
- Proton has deprecated the share-scoped Drive routes
(`/drive/shares/{shareId}/links*`, `events*`, `folders*`, `files/*`) used
throughout the pinned build's go-proton-api and Proton-API-Bridge dependency
stack and announced removal within roughly twelve months (Proton engineer
notice, September 2026). Migrating that stack to the volume-scoped
`/drive/volumes/{volumeId}` and `/drive/v2` routes is a hard prerequisite for
public packaging. Until then keep PDrive API-friendly by design: no component
may poll Proton's events endpoints more than once per 30 seconds once
event-based invalidation exists, and the guarded metadata refresh must remain
a manual, user-initiated path that is never automated into a polling loop.
The public route reference is the official Proton Drive SDK
(`ProtonDriveApps/sdk`, TypeScript): `client/js/src/internal/apiService/
driveTypes.ts` holds the generated OpenAPI contract. Semantics to preserve:
routes are volume-scoped (`volumeID` replaces `shareID`; node identity is
`volumeId:linkId`), children listings return link IDs only with
`More`/`AnchorID` pagination and a `FoldersOnly` filter, metadata is fetched
in batches of up to 100 IDs via `POST /drive/v2/volumes/{volumeID}/links`,
and the SDK's event pollers run at 30 s for the own volume and 60 s for
others with jitter and Fibonacci backoff.
- Avoid new runtime dependencies when Python's standard library, GTK 3, and the
installed GI stack are sufficient. Do not add WebKit merely to render local
documentation.
Expand Down Expand Up @@ -175,6 +195,8 @@ project-specific; CI remains the authority for mechanical formatting rules.
- `docs/EVERYDAY_USE.md`: task-oriented normal operation in Nemo and the GUI.
- `docs/OPERATIONS.md`: complete operational reference.
- `docs/TROUBLESHOOTING.md`: symptom-led diagnosis and recovery.
- `docs/PROTON_API_V2_MIGRATION.md`: engineering reference for the Proton
Drive volume-scoped v2 route migration of the pinned rclone stack.

## Verification

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.8.3
0.9.0
4 changes: 2 additions & 2 deletions bin/pdrive-prerequisites
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ umask 077
readonly target_rclone="${PDRIVE_REAL_RCLONE:-${HOME}/.local/libexec/rclone-bin}"
readonly minimum_safe_rclone='v1.76.0'
readonly minimum_safe_beta_build=10204
readonly pdrive_rclone_release='pdrive-v1.76.0-beta.10204.2'
readonly pdrive_rclone_release='pdrive-v1.76.0-beta.10204.3'
readonly pdrive_rclone_url="${PDRIVE_RCLONE_URL:-https://github.com/oss-singularity/rclone/releases/download/${pdrive_rclone_release}/rclone-pdrive-linux-amd64}"
readonly pdrive_rclone_sha256="${PDRIVE_RCLONE_SHA256:-85da18d19fd5e4a0969ed0fcc1ec43d00a90dfa7a06ce5483fd681c619db390d}"
readonly pdrive_rclone_sha256="${PDRIVE_RCLONE_SHA256:-a5dcbd149533520e376eeed15ed0bfcb3adaba1f5e17291c3d1e178c73252bf6}"
readonly curl_bin="${PDRIVE_CURL_BIN:-$(command -v curl || true)}"

usage() {
Expand Down
2 changes: 1 addition & 1 deletion bin/pdrive-state
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ from typing import Any


SCHEMA_VERSION = 1
TOOL_VERSION = "0.8.3"
TOOL_VERSION = "0.9.0"
RECENT_TRANSFER_WINDOW_SECONDS = 24 * 60 * 60
RECENT_TRANSFER_LIMIT = 24
MOUNT_LOG_TAIL_BYTES = 512 * 1024
Expand Down
13 changes: 11 additions & 2 deletions bin/pdrive-ui
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ PLATFORM_ADAPTER = load_platform_adapter()


APP_ID = "io.github.claudiuschuster.PDriveControl"
VERSION = "0.8.3"
VERSION = "0.9.0"
REFRESH_INTERVAL_SECONDS = 2
REFRESH_INTERVAL_OPTIONS = (1, 2, 5, 10)
CAPACITY_REFRESH_INTERVAL_SECONDS = 5 * 60
Expand Down Expand Up @@ -6689,6 +6689,15 @@ class PDriveApplication(Gtk.Application):
self.window.schedule_content_fit()
self.window.request_refresh()

def toggle_window(self, *_args: Any) -> None:
if self.window is None:
self.activate()
return
if self.window.get_visible():
self.window.hide()
else:
self.show_window()

def on_window_delete(self, window: Gtk.Window, _event: Gdk.Event) -> bool:
if not self.force_quit and self.preferences["close_to_tray"] and not self.demo:
window.hide()
Expand Down Expand Up @@ -6717,7 +6726,7 @@ class PDriveApplication(Gtk.Application):
if tray_supports_distinct_clicks() or AyatanaAppIndicator3 is None:
self.status_icon = Gtk.StatusIcon.new_from_icon_name(APP_ID)
self.status_icon.set_title("PDrive Control Center")
self.status_icon.connect("activate", self.show_window)
self.status_icon.connect("activate", self.toggle_window)
self.status_icon.connect("popup-menu", self.popup_status_menu, menu)
else:
self.indicator = AyatanaAppIndicator3.Indicator.new(
Expand Down
19 changes: 13 additions & 6 deletions docs/OPERATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,12 +489,13 @@ fit runs. Each opening can request at most one growth resize after the first
dashboard state arrives, so an allocation that has not caught up cannot add the
same overflow repeatedly. Smaller screens retain normal scrolling.

On X11 Cinnamon the tray uses GTK StatusIcon so a left click opens/focuses the
Control Center and a right click opens the existing Open, Open `/pdrive`, and
Quit menu. Ayatana AppIndicator remains the compatibility backend on displays
that cannot provide distinct primary/context clicks. Hiding or quitting the UI
never stops the mount; monitoring, recovery and desktop error notifications
remain the responsibility of `pdrive-watch.timer`.
On X11 Cinnamon the tray uses GTK StatusIcon so a left click toggles the Control
Center between the visible window and the hidden tray state, and a right click
opens the existing Open, Open `/pdrive`, and Quit menu. Ayatana AppIndicator
remains the compatibility backend on displays that cannot provide distinct
primary/context clicks. Hiding or quitting the UI never stops the mount;
monitoring, recovery and desktop error notifications remain the responsibility
of `pdrive-watch.timer`.

## Runtime bandwidth

Expand Down Expand Up @@ -604,6 +605,12 @@ rclone's `vfs/forget` only clears the upper directory cache. A new process is
required to guarantee that the Proton backend's deeper in-memory metadata maps
are empty.

Keep this refresh a deliberate, occasional operation. Never wrap
`pdrive-refresh --refresh` in a cron job or timer: Proton has warned that
clients rescanning folders or polling aggressively face progressively harder
throttling, and the confirmation gates above exist exactly to make each
metadata rebuild an intentional act.

## Controlled restart and cooldown

```bash
Expand Down
Loading