mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +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 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};
|
||||
|
||||
/// Fixed keyring account name for the single stored session blob.
|
||||
@@ -53,7 +53,14 @@ impl StoredSession {
|
||||
}
|
||||
|
||||
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> {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use directories::ProjectDirs;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
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`].
|
||||
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.
|
||||
pub struct AppDirs {
|
||||
dirs: ProjectDirs,
|
||||
@@ -30,6 +47,30 @@ impl AppDirs {
|
||||
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.
|
||||
pub fn state_dir(&self) -> PathBuf {
|
||||
// `state_dir` is Linux-only in `directories`; fall back to data dir.
|
||||
@@ -59,6 +100,11 @@ impl AppDirs {
|
||||
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.
|
||||
pub fn default_mountpoint(&self) -> PathBuf {
|
||||
directories::UserDirs::new()
|
||||
@@ -70,6 +116,31 @@ impl AppDirs {
|
||||
pub fn ensure(&self) -> Result<()> {
|
||||
std::fs::create_dir_all(self.state_dir())?;
|
||||
std::fs::create_dir_all(self.cache_dir())?;
|
||||
let _ = std::fs::create_dir_all(self.dirs.config_dir());
|
||||
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();
|
||||
|
||||
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.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
|
||||
/// purple, app-wide. Named-colour overrides recolour the stock widgets (switch,
|
||||
/// buttons, progress fill) without per-widget styling.
|
||||
|
||||
@@ -180,6 +180,17 @@ fn main() -> Result<()> {
|
||||
.init();
|
||||
|
||||
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 default_mountpoint = dirs.default_mountpoint();
|
||||
|
||||
|
||||
+3
-1
@@ -20,7 +20,7 @@ provides=('pdfs')
|
||||
# Files-on-demand mount + keyring need these at runtime.
|
||||
optdepends=('gnome-keyring: credential storage via Secret Service'
|
||||
'xdg-utils: "Open folder" action from the tray')
|
||||
options=('!lto')
|
||||
options=('!lto' '!debug')
|
||||
|
||||
# Built in place from the checkout; nothing to fetch or checksum.
|
||||
source=()
|
||||
@@ -56,6 +56,8 @@ package() {
|
||||
|
||||
install -Dm644 "packaging/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" \
|
||||
"$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 -->
|
||||
<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) -->
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 733 B After Width: | Height: | Size: 718 B |
Reference in new issue
Block a user