Compare commits

..
2 Commits
Author SHA1 Message Date
nvrl f4d6580cd3 chore(version) bumped to 1.10.1 2026-09-15 15:13:22 +02:00
nvrl b2f62f70e1 chore(deps,core,gui): upgrade dependencies to latest
- keyring 3 -> keyring-core 1 + dbus-secret-service-keyring-store 1
  (crypto-rust). Same libdbus Secret Service backend; with no target the
  store matches items keyring 3 wrote, so stored sessions survive.
- ksni 0.2 -> 0.3 via the blocking API, with assume_sni_available so a
  tray that starts before the SNI watcher waits instead of failing. Drops
  the clap 2 / atty chain (Dependabot atty advisory).
- gtk4 0.11, libadwaita 0.9, webkit6 0.6, rusqlite 0.40, fuser 0.18,
  directories 6, sha1/sha2 0.11, base64 0.23.
2026-09-15 15:07:00 +02:00
10 changed files with 571 additions and 822 deletions

No files matched your search

Generated
+512 -793
View File
File diff suppressed because it is too large. Load diff
+14 -10
View File
@@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/pdfs-core", "crates/pdfs-fuse", "crates/pdfs-cli", "crates/pdfs-gui"]
[workspace.package]
version = "1.10.0"
version = "1.10.1"
edition = "2024"
license = "MIT"
authors = ["Nils Pukropp <contact@narl.io>"]
@@ -15,8 +15,8 @@ keywords = ["proton", "drive", "fuse", "sync", "linux"]
categories = ["filesystem", "command-line-utilities"]
[workspace.dependencies]
proton-sdk = { version = "0.6.3" }
proton-drive-rs = { version = "0.6.3" }
proton-sdk = { version = "0.6.4" }
proton-drive-rs = { version = "0.6.4" }
# Internal crates.
pdfs-core = { path = "crates/pdfs-core" }
@@ -25,7 +25,7 @@ pdfs-fuse = { path = "crates/pdfs-fuse" }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "fs", "io-util", "time", "signal"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
base64 = "0.22"
base64 = "0.23"
thiserror = "2"
anyhow = "1"
# Non-poisoning mutexes. A handler that panics while holding a lock must not
@@ -35,24 +35,28 @@ anyhow = "1"
parking_lot = "0.12"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
directories = "5"
directories = "6"
ignore = "0.4"
sha2 = "0.10"
sha2 = "0.11"
# Google Takeout exports are zip sets; the importer reads their central
# directories and streams entries out without extracting to disk first.
zip = { version = "8", default-features = false, features = ["deflate"] }
# Proton's photo duplicate detection is keyed on the plaintext SHA-1, so an
# import has to speak SHA-1 whatever its age.
sha1 = "0.10"
sha1 = "0.11"
# Thumbnail generation for photos the server has none for. Decoders only for the
# formats a camera or phone actually produces — the rest of the crate's codecs
# would be dead weight in the daemon.
image = { version = "0.25", default-features = false, features = ["jpeg", "png", "webp", "gif", "tiff", "bmp", "rayon"] }
rusqlite = { version = "0.32", features = ["bundled"] }
keyring = { version = "3", features = ["sync-secret-service", "crypto-rust"] }
rusqlite = { version = "0.40", features = ["bundled"] }
# keyring 4 split into `keyring-core` plus per-platform stores. The libdbus
# Secret Service store is the one keyring 3's `sync-secret-service` wrapped, and
# with no `target` it matches items v3 wrote, so existing logins survive.
keyring-core = "1"
dbus-secret-service-keyring-store = { version = "1", features = ["crypto-rust"] }
clap = { version = "4", features = ["derive"] }
rpassword = "7"
async-trait = "0.1"
futures = "0.3"
fuser = "0.17"
fuser = "0.18"
libc = "0.2"
+2 -1
View File
@@ -23,7 +23,8 @@ sha2.workspace = true
sha1.workspace = true
zip.workspace = true
rusqlite.workspace = true
keyring.workspace = true
keyring-core.workspace = true
dbus-secret-service-keyring-store.workspace = true
parking_lot.workspace = true
async-trait.workspace = true
libc.workspace = true
+8 -3
View File
@@ -6,7 +6,7 @@
//! interactive step; the refresh token auto-renews via the HTTP client's 401
//! path, so no fresh 2FA is required until the refresh token itself expires.
use keyring::Entry;
use keyring_core::Entry;
use proton_drive_rs::{KeySalt, ProtonDriveClient};
use proton_sdk::api::{HumanVerification, HumanVerificationCredential};
use proton_sdk::cache::EncryptedCacheRepository;
@@ -81,6 +81,11 @@ fn client_config() -> ProtonClientConfiguration {
}
fn keyring_entry() -> Result<Entry> {
// Installed lazily rather than once at startup so a session bus that was not
// up yet on the first attempt is retried on the next one.
if keyring_core::get_default_store().is_none() {
keyring_core::set_default_store(dbus_secret_service_keyring_store::Store::new()?);
}
Ok(Entry::new(KEYRING_SERVICE, KEYRING_USER)?)
}
@@ -215,7 +220,7 @@ pub fn load() -> Result<StoredSession> {
let entry = keyring_entry()?;
match entry.get_password() {
Ok(json) => Ok(serde_json::from_str(&json)?),
Err(keyring::Error::NoEntry) => Err(Error::NotLoggedIn),
Err(keyring_core::Error::NoEntry) => Err(Error::NotLoggedIn),
Err(e) => Err(e.into()),
}
}
@@ -238,7 +243,7 @@ pub fn logout() -> Result<()> {
}
}
match keyring_entry()?.delete_credential() {
Ok(()) | Err(keyring::Error::NoEntry) => Ok(()),
Ok(()) | Err(keyring_core::Error::NoEntry) => Ok(()),
Err(e) => Err(e.into()),
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ pub enum Error {
Proton(#[from] proton_sdk::ProtonError),
#[error("keyring: {0}")]
Keyring(#[from] keyring::Error),
Keyring(#[from] keyring_core::Error),
#[error("serialization: {0}")]
Serde(#[from] serde_json::Error),
+4 -4
View File
@@ -29,9 +29,9 @@ anyhow.workspace = true
tokio.workspace = true
serde.workspace = true
serde_json.workspace = true
ksni = "0.2"
gtk4 = { version = "0.9", features = ["v4_12"] }
adw = { package = "libadwaita", version = "0.7", features = ["v1_5"] }
ksni = { version = "0.3", features = ["blocking"] }
gtk4 = { version = "0.11", features = ["v4_12"] }
adw = { package = "libadwaita", version = "0.9", features = ["v1_5"] }
async-channel = "2"
exif = { version = "0.6", package = "kamadak-exif" }
webkit6 = "0.4"
webkit6 = "0.6"
+9 -8
View File
@@ -14,8 +14,9 @@ use std::process::Command;
use std::time::Duration;
use anyhow::{Context, Result};
use ksni::blocking::TrayMethods;
use ksni::menu::StandardItem;
use ksni::{MenuItem, Tray, TrayService};
use ksni::{MenuItem, Tray};
use pdfs_core::auth;
use pdfs_core::config::AppDirs;
use pdfs_core::control::{
@@ -282,13 +283,13 @@ fn main() -> Result<()> {
state: poll_state(&socket, &default_mountpoint),
};
let service = TrayService::new(tray);
let handle = service.handle();
std::thread::spawn(move || {
if let Err(e) = service.run() {
tracing::error!("tray service stopped: {e:?}");
}
});
// The tray autostarts with the session and can beat the desktop's SNI
// watcher onto the bus. Without `assume_sni_available` that race is a hard
// spawn error; with it the item waits and registers once the watcher shows.
let handle = tray
.assume_sni_available(true)
.spawn()
.context("start tray service")?;
// Poll the daemon forever, pushing each fresh snapshot into the tray so the
// menu reflects mount/login changes made elsewhere (e.g. via the CLI).
+1 -1
View File
@@ -1364,7 +1364,7 @@ fn icon_for(name: &str, is_dir: bool) -> gio::Icon {
if is_dir {
return gio::ThemedIcon::new("folder").upcast();
}
let (content_type, _uncertain) = gio::functions::content_type_guess(Some(name), &[]);
let (content_type, _uncertain) = gio::functions::content_type_guess(Some(name), None);
gio::functions::content_type_get_icon(&content_type)
}
+19
View File
@@ -13,6 +13,25 @@ scratch (user data in `staging/` and `recovery/` is never touched by this).
Nothing yet.
## [1.10.1] — 2026-09-15
Dependency upgrade release, clearing both open Dependabot advisories. No schema change.
Schema: **28**; SDK bumped to `proton-sdk` / `proton-drive-rs` **0.6.4**.
### Security
- **`lru` IterMut Stacked Borrows advisory.** The SDK now depends on `lru` 0.18.
- **`atty` unaligned read advisory.** The tray moved to `ksni` 0.3, which no longer pulls
`dbus-codegen` → `clap` 2 → `atty`.
### Changed
- **Keyring backend is `keyring-core` + `dbus-secret-service-keyring-store`** (keyring 4's split).
Same libdbus Secret Service as before; stored sessions written by earlier releases are still
found, so no re-login is needed.
- **The tray waits for a late StatusNotifierWatcher** instead of failing to start when it beats
the desktop's tray host onto the session bus.
- Upgraded `gtk4` 0.11, `libadwaita` 0.9, `webkit6` 0.6, `rusqlite` 0.40 (bundled SQLite),
`fuser` 0.18, `directories` 6, `sha1`/`sha2` 0.11, `base64` 0.23.
## [1.10.0] — 2026-09-15
One-request move-and-rename in the drain, and who shared an item with you. No schema change.
+1 -1
View File
@@ -9,7 +9,7 @@
# Build + install: cd packaging && makepkg -fi
pkgname=proton-drive-linux
pkgver=1.10.0
pkgver=1.10.1
pkgrel=1
pkgdesc="Unofficial Proton Drive client for Linux: files-on-demand FUSE mount, CLI, GTK4 app + tray"
arch=('x86_64')