mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-04 00:47:00 +01:00
updated app name + fixed missing icon in pkgbuild
This commit is contained in:
1 parent
aa70077ad0
commit
86fa8aef03
7 files changed
+118
-5
No files matched your search
@@ -12,7 +12,7 @@ use proton_sdk::config::ProtonClientConfiguration;
|
|||||||
use proton_sdk::session::{PasswordMode, ProtonApiSession, ResumeParameters};
|
use proton_sdk::session::{PasswordMode, ProtonApiSession, ResumeParameters};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::config::{APP_VERSION, KEYRING_SERVICE, USER_AGENT};
|
use crate::config::{AppDirs, APP_VERSION, KEYRING_SERVICE, USER_AGENT};
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
|
|
||||||
/// Fixed keyring account name for the single stored session blob.
|
/// Fixed keyring account name for the single stored session blob.
|
||||||
@@ -53,7 +53,14 @@ impl StoredSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn client_config() -> ProtonClientConfiguration {
|
fn client_config() -> ProtonClientConfiguration {
|
||||||
ProtonClientConfiguration::new(APP_VERSION).with_user_agent(USER_AGENT)
|
let (app_version, user_agent) = match AppDirs::new() {
|
||||||
|
Ok(dirs) => {
|
||||||
|
let config = dirs.load_config();
|
||||||
|
(config.app_version, config.user_agent)
|
||||||
|
}
|
||||||
|
Err(_) => (APP_VERSION.to_string(), USER_AGENT.to_string()),
|
||||||
|
};
|
||||||
|
ProtonClientConfiguration::new(app_version).with_user_agent(user_agent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyring_entry() -> Result<Entry> {
|
fn keyring_entry() -> Result<Entry> {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
|
|
||||||
@@ -18,6 +19,22 @@ pub const KEYRING_SERVICE: &str = "proton-drive-linux";
|
|||||||
/// blobs back under this; pinned files are exempt. See [`crate::cache`].
|
/// blobs back under this; pinned files are exempt. See [`crate::cache`].
|
||||||
pub const DEFAULT_CACHE_BUDGET_BYTES: u64 = 5 * 1024 * 1024 * 1024;
|
pub const DEFAULT_CACHE_BUDGET_BYTES: u64 = 5 * 1024 * 1024 * 1024;
|
||||||
|
|
||||||
|
/// Configuration structure allowing the user to customize client identification headers.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct AppConfig {
|
||||||
|
pub app_version: String,
|
||||||
|
pub user_agent: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AppConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
app_version: APP_VERSION.to_string(),
|
||||||
|
user_agent: USER_AGENT.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolved XDG locations for state, cache, and the default mountpoint.
|
/// Resolved XDG locations for state, cache, and the default mountpoint.
|
||||||
pub struct AppDirs {
|
pub struct AppDirs {
|
||||||
dirs: ProjectDirs,
|
dirs: ProjectDirs,
|
||||||
@@ -30,6 +47,30 @@ impl AppDirs {
|
|||||||
Ok(Self { dirs })
|
Ok(Self { dirs })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration file path (e.g. ~/.config/proton-drive-linux/config.json).
|
||||||
|
pub fn config_path(&self) -> PathBuf {
|
||||||
|
self.dirs.config_dir().join("config.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load config from disk, creating default if missing.
|
||||||
|
pub fn load_config(&self) -> AppConfig {
|
||||||
|
let path = self.config_path();
|
||||||
|
if path.exists() {
|
||||||
|
if let Ok(content) = std::fs::read_to_string(&path) {
|
||||||
|
if let Ok(config) = serde_json::from_str::<AppConfig>(&content) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let default_config = AppConfig::default();
|
||||||
|
if let Ok(content) = serde_json::to_string_pretty(&default_config) {
|
||||||
|
let _ = std::fs::create_dir_all(self.dirs.config_dir());
|
||||||
|
let _ = std::fs::write(&path, content);
|
||||||
|
}
|
||||||
|
default_config
|
||||||
|
}
|
||||||
|
|
||||||
/// Persistent state: inode map / cache index DB lives here.
|
/// Persistent state: inode map / cache index DB lives here.
|
||||||
pub fn state_dir(&self) -> PathBuf {
|
pub fn state_dir(&self) -> PathBuf {
|
||||||
// `state_dir` is Linux-only in `directories`; fall back to data dir.
|
// `state_dir` is Linux-only in `directories`; fall back to data dir.
|
||||||
@@ -59,6 +100,11 @@ impl AppDirs {
|
|||||||
self.state_dir().join("control.sock")
|
self.state_dir().join("control.sock")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unix domain socket the tray uses to ensure single instance.
|
||||||
|
pub fn tray_socket(&self) -> PathBuf {
|
||||||
|
self.state_dir().join("tray.sock")
|
||||||
|
}
|
||||||
|
|
||||||
/// Default mountpoint when the user does not pass one explicitly.
|
/// Default mountpoint when the user does not pass one explicitly.
|
||||||
pub fn default_mountpoint(&self) -> PathBuf {
|
pub fn default_mountpoint(&self) -> PathBuf {
|
||||||
directories::UserDirs::new()
|
directories::UserDirs::new()
|
||||||
@@ -70,6 +116,31 @@ impl AppDirs {
|
|||||||
pub fn ensure(&self) -> Result<()> {
|
pub fn ensure(&self) -> Result<()> {
|
||||||
std::fs::create_dir_all(self.state_dir())?;
|
std::fs::create_dir_all(self.state_dir())?;
|
||||||
std::fs::create_dir_all(self.cache_dir())?;
|
std::fs::create_dir_all(self.cache_dir())?;
|
||||||
|
let _ = std::fs::create_dir_all(self.dirs.config_dir());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_app_config_serialization() {
|
||||||
|
let config = AppConfig {
|
||||||
|
app_version: "external-drive-test-client@1.0.0".to_string(),
|
||||||
|
user_agent: "test-agent/1.0".to_string(),
|
||||||
|
};
|
||||||
|
let json = serde_json::to_string(&config).unwrap();
|
||||||
|
let decoded: AppConfig = serde_json::from_str(&json).unwrap();
|
||||||
|
assert_eq!(decoded.app_version, "external-drive-test-client@1.0.0");
|
||||||
|
assert_eq!(decoded.user_agent, "test-agent/1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_default_app_config() {
|
||||||
|
let default_config = AppConfig::default();
|
||||||
|
assert_eq!(default_config.app_version, APP_VERSION);
|
||||||
|
assert_eq!(default_config.user_agent, USER_AGENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -93,11 +93,22 @@ fn main() -> glib::ExitCode {
|
|||||||
.init();
|
.init();
|
||||||
|
|
||||||
let app = adw::Application::builder().application_id(APP_ID).build();
|
let app = adw::Application::builder().application_id(APP_ID).build();
|
||||||
app.connect_startup(|_| load_proton_theme());
|
app.connect_startup(|_| {
|
||||||
|
load_proton_theme();
|
||||||
|
spawn_tray();
|
||||||
|
});
|
||||||
app.connect_activate(build_window);
|
app.connect_activate(build_window);
|
||||||
app.run()
|
app.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Spawn the tray icon process in the background.
|
||||||
|
fn spawn_tray() {
|
||||||
|
match Command::new("pdfs-tray").spawn() {
|
||||||
|
Ok(_) => tracing::info!("spawned `pdfs-tray`"),
|
||||||
|
Err(e) => tracing::error!("failed to spawn `pdfs-tray`: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Install a CSS provider that overrides libadwaita's accent colour with Proton
|
/// Install a CSS provider that overrides libadwaita's accent colour with Proton
|
||||||
/// purple, app-wide. Named-colour overrides recolour the stock widgets (switch,
|
/// purple, app-wide. Named-colour overrides recolour the stock widgets (switch,
|
||||||
/// buttons, progress fill) without per-widget styling.
|
/// buttons, progress fill) without per-widget styling.
|
||||||
|
|||||||
@@ -180,6 +180,17 @@ fn main() -> Result<()> {
|
|||||||
.init();
|
.init();
|
||||||
|
|
||||||
let dirs = AppDirs::new().context("resolve app dirs")?;
|
let dirs = AppDirs::new().context("resolve app dirs")?;
|
||||||
|
|
||||||
|
// Ensure only one instance of the tray runs.
|
||||||
|
let tray_sock = dirs.tray_socket();
|
||||||
|
if std::os::unix::net::UnixStream::connect(&tray_sock).is_ok() {
|
||||||
|
tracing::info!("Another instance of pdfs-tray is already running; exiting.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let _ = std::fs::remove_file(&tray_sock);
|
||||||
|
let _lock_socket = std::os::unix::net::UnixListener::bind(&tray_sock)
|
||||||
|
.context("failed to bind tray single-instance socket")?;
|
||||||
|
|
||||||
let socket = dirs.control_socket();
|
let socket = dirs.control_socket();
|
||||||
let default_mountpoint = dirs.default_mountpoint();
|
let default_mountpoint = dirs.default_mountpoint();
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -20,7 +20,7 @@ provides=('pdfs')
|
|||||||
# Files-on-demand mount + keyring need these at runtime.
|
# Files-on-demand mount + keyring need these at runtime.
|
||||||
optdepends=('gnome-keyring: credential storage via Secret Service'
|
optdepends=('gnome-keyring: credential storage via Secret Service'
|
||||||
'xdg-utils: "Open folder" action from the tray')
|
'xdg-utils: "Open folder" action from the tray')
|
||||||
options=('!lto')
|
options=('!lto' '!debug')
|
||||||
|
|
||||||
# Built in place from the checkout; nothing to fetch or checksum.
|
# Built in place from the checkout; nothing to fetch or checksum.
|
||||||
source=()
|
source=()
|
||||||
@@ -56,6 +56,8 @@ package() {
|
|||||||
|
|
||||||
install -Dm644 "packaging/io.narl.proton-drive-linux.desktop" \
|
install -Dm644 "packaging/io.narl.proton-drive-linux.desktop" \
|
||||||
"$pkgdir/usr/share/applications/io.narl.proton-drive-linux.desktop"
|
"$pkgdir/usr/share/applications/io.narl.proton-drive-linux.desktop"
|
||||||
|
install -Dm644 "packaging/io.narl.proton-drive-linux-tray.desktop" \
|
||||||
|
"$pkgdir/etc/xdg/autostart/io.narl.proton-drive-linux-tray.desktop"
|
||||||
install -Dm644 "packaging/io.narl.proton-drive-linux.svg" \
|
install -Dm644 "packaging/io.narl.proton-drive-linux.svg" \
|
||||||
"$pkgdir/usr/share/icons/hicolor/scalable/apps/io.narl.proton-drive-linux.svg"
|
"$pkgdir/usr/share/icons/hicolor/scalable/apps/io.narl.proton-drive-linux.svg"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=Proton Drive (Tray)
|
||||||
|
GenericName=Cloud Drive Tray
|
||||||
|
Comment=Proton Drive system tray icon
|
||||||
|
Exec=pdfs-tray
|
||||||
|
Icon=io.narl.proton-drive-linux
|
||||||
|
Terminal=false
|
||||||
|
Categories=Network;FileTransfer;GTK;
|
||||||
|
Keywords=proton;drive;cloud;sync;storage;
|
||||||
|
NoDisplay=true
|
||||||
@@ -10,5 +10,5 @@
|
|||||||
<!-- cloud -->
|
<!-- cloud -->
|
||||||
<path fill="#ffffff" d="M44 84c-11 0-20-9-20-20 0-10 7-18 17-20 3-11 13-19 25-19 13 0 24 10 26 23 9 1 16 9 16 18 0 10-8 18-18 18z"/>
|
<path fill="#ffffff" d="M44 84c-11 0-20-9-20-20 0-10 7-18 17-20 3-11 13-19 25-19 13 0 24 10 26 23 9 1 16 9 16 18 0 10-8 18-18 18z"/>
|
||||||
<!-- down arrow (on-demand pull) -->
|
<!-- down arrow (on-demand pull) -->
|
||||||
<path fill="#6d4aff" d="M64 50v22m0 0l-9-9m9 9l9-9" stroke="#6d4aff" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
<path d="M64 50v22m0 0l-9-9m9 9l9-9" stroke="#6d4aff" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 733 B After Width: | Height: | Size: 718 B |
Reference in new issue
Block a user