fix: Server->Client Sync + File Locking repariert
Server->Client Sync: - Server sendet Timestamps ohne Timezone (2026-04-11T12:49:24.735436) - parse_from_rfc3339 braucht Timezone -> schlug still fehl - Client dachte IMMER er sei neuer -> Upload statt Download - Fix: parse_server_time() akzeptiert beides (mit/ohne Timezone) - Probiert RFC3339, dann NaiveDateTime mit Microseconds, dann ohne File Locking: - open_cloud_file nutzte API-Clone vom SyncEngine (evtl. alter Token) - Jetzt direkt state.api (immer aktueller Token nach Refresh) - Lock wird zuverlaessig gesetzt beim Oeffnen von .cloud Dateien Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -230,10 +230,8 @@ async fn run_sync_now(state: State<'_, AppState>) -> Result<Vec<String>, String>
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn open_cloud_file(state: State<'_, AppState>, cloud_path: String) -> Result<String, String> {
|
async fn open_cloud_file(state: State<'_, AppState>, cloud_path: String) -> Result<String, String> {
|
||||||
let engine = {
|
let engine = state.api.lock().unwrap().clone()
|
||||||
let guard = state.sync_engine.lock().unwrap();
|
.ok_or("Nicht eingeloggt")?;
|
||||||
guard.as_ref().ok_or("Sync nicht gestartet")?.api.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
let path = PathBuf::from(&cloud_path);
|
let path = PathBuf::from(&cloud_path);
|
||||||
let content = std::fs::read_to_string(&path).map_err(|e| e.to_string())?;
|
let content = std::fs::read_to_string(&path).map_err(|e| e.to_string())?;
|
||||||
|
|||||||
@@ -109,8 +109,7 @@ impl SyncEngine {
|
|||||||
let local_modified = std::fs::metadata(&local_path)
|
let local_modified = std::fs::metadata(&local_path)
|
||||||
.and_then(|m| m.modified()).ok();
|
.and_then(|m| m.modified()).ok();
|
||||||
let server_modified = entry.updated_at.as_deref()
|
let server_modified = entry.updated_at.as_deref()
|
||||||
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
|
.and_then(parse_server_time);
|
||||||
.map(|dt| std::time::SystemTime::from(dt));
|
|
||||||
|
|
||||||
let server_is_newer = match (local_modified, server_modified) {
|
let server_is_newer = match (local_modified, server_modified) {
|
||||||
(Some(lt), Some(st)) => st > lt,
|
(Some(lt), Some(st)) => st > lt,
|
||||||
@@ -344,8 +343,7 @@ impl SyncEngine {
|
|||||||
let local_modified = std::fs::metadata(&path)
|
let local_modified = std::fs::metadata(&path)
|
||||||
.and_then(|m| m.modified()).ok();
|
.and_then(|m| m.modified()).ok();
|
||||||
let server_modified = se.updated_at.as_deref()
|
let server_modified = se.updated_at.as_deref()
|
||||||
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
|
.and_then(parse_server_time);
|
||||||
.map(|dt| std::time::SystemTime::from(dt));
|
|
||||||
|
|
||||||
let server_is_newer = match (local_modified, server_modified) {
|
let server_is_newer = match (local_modified, server_modified) {
|
||||||
(Some(lt), Some(st)) => st > lt,
|
(Some(lt), Some(st)) => st > lt,
|
||||||
@@ -448,6 +446,24 @@ fn find_subtree(tree: &[FileEntry], folder_id: i64) -> Option<Vec<FileEntry>> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a server timestamp (may or may not have timezone)
|
||||||
|
fn parse_server_time(s: &str) -> Option<std::time::SystemTime> {
|
||||||
|
// Try with timezone first (RFC3339)
|
||||||
|
if let Ok(dt) = chrono::DateTime::parse_from_rfc3339(s) {
|
||||||
|
return Some(std::time::SystemTime::from(dt));
|
||||||
|
}
|
||||||
|
// Try without timezone (naive, assume UTC)
|
||||||
|
if let Ok(dt) = chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S%.f") {
|
||||||
|
let utc = dt.and_utc();
|
||||||
|
return Some(std::time::SystemTime::from(utc));
|
||||||
|
}
|
||||||
|
if let Ok(dt) = chrono::NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S") {
|
||||||
|
let utc = dt.and_utc();
|
||||||
|
return Some(std::time::SystemTime::from(utc));
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn compute_file_hash(path: &Path) -> String {
|
pub fn compute_file_hash(path: &Path) -> String {
|
||||||
let data = match std::fs::read(path) {
|
let data = match std::fs::read(path) {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
|
|||||||
Reference in New Issue
Block a user