feat: File Lock beim Oeffnen + Entsperren per Rechtsklick
Beim Oeffnen einer .cloud-Datei: - Download + Datei bleibt lokal (wie bisher) - Lock wird auf dem Server gesetzt (andere sehen "gesperrt von X") - Kein Auto-Unlock - Datei bleibt gesperrt bis manuell entsperrt Rechtsklick im Datei-Browser auf Offline-Dateien: - "Entsperren (Freigeben fuer andere)" - hebt den Lock auf - "Nicht mehr offline" - .cloud zurueck + automatisch unlock So bleiben Dateien gesperrt solange man daran arbeitet. Wenn fertig: Rechtsklick -> Entsperren. Einfach und explizit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -256,11 +256,17 @@ async fn open_cloud_file(state: State<'_, AppState>, cloud_path: String) -> Resu
|
||||
}
|
||||
eprintln!("[OpenCloud] Downloaded {} bytes", std::fs::metadata(&real_path).map(|m| m.len()).unwrap_or(0));
|
||||
|
||||
// Remove .cloud placeholder - file stays as real file (like "offline markieren")
|
||||
// Remove .cloud placeholder - file stays as real file
|
||||
// Changes will be synced automatically by the file watcher
|
||||
// User can manually "unmark offline" via right-click to get .cloud back
|
||||
// User can "unmark offline" or "unlock" via right-click
|
||||
std::fs::remove_file(&path).ok();
|
||||
|
||||
// Lock on server (prevents others from editing)
|
||||
match api.lock_file(file_id, "Desktop Sync Client").await {
|
||||
Ok(_) => eprintln!("[OpenCloud] Locked on server"),
|
||||
Err(e) => eprintln!("[OpenCloud] Lock failed (file may be locked by someone else): {}", e),
|
||||
}
|
||||
|
||||
// Open with default application for this file type
|
||||
eprintln!("[OpenCloud] Opening with default app: {}", real_path.display());
|
||||
open::that(&real_path)
|
||||
@@ -269,6 +275,13 @@ async fn open_cloud_file(state: State<'_, AppState>, cloud_path: String) -> Resu
|
||||
Ok(real_path.to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn unlock_file_cmd(state: State<'_, AppState>, file_id: i64) -> Result<String, String> {
|
||||
let api = state.api.lock().unwrap().clone().ok_or("Nicht eingeloggt")?;
|
||||
api.unlock_file(file_id).await?;
|
||||
Ok("Datei entsperrt".to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_file_tree(state: State<'_, AppState>) -> Result<serde_json::Value, String> {
|
||||
let api = state.api.lock().unwrap().clone().ok_or("Nicht eingeloggt")?;
|
||||
@@ -726,6 +739,7 @@ pub fn run() {
|
||||
open_cloud_file,
|
||||
get_file_tree,
|
||||
get_status,
|
||||
unlock_file_cmd,
|
||||
browse_sync_folder,
|
||||
mark_offline,
|
||||
unmark_offline,
|
||||
|
||||
@@ -84,6 +84,33 @@ async function doMarkOffline(file) {
|
||||
}
|
||||
}
|
||||
|
||||
async function doUnlockFile(file) {
|
||||
hideContextMenu();
|
||||
// Find file ID from server tree
|
||||
const serverFile = findFileInTree(fileTree.value, file.name);
|
||||
if (!serverFile) {
|
||||
syncLog.value = [`[${ts()}] Fehler: Datei nicht auf Server gefunden`, ...syncLog.value];
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await invoke("unlock_file_cmd", { fileId: serverFile.id });
|
||||
syncLog.value = [`[${ts()}] Entsperrt: ${file.name}`, ...syncLog.value].slice(0, 200);
|
||||
} catch (err) {
|
||||
syncLog.value = [`[${ts()}] Fehler: ${err}`, ...syncLog.value].slice(0, 200);
|
||||
}
|
||||
}
|
||||
|
||||
function findFileInTree(entries, name) {
|
||||
for (const e of entries) {
|
||||
if (e.name === name) return e;
|
||||
if (e.children) {
|
||||
const found = findFileInTree(e.children, name);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function doUnmarkOffline(file) {
|
||||
hideContextMenu();
|
||||
try {
|
||||
@@ -429,6 +456,9 @@ onUnmounted(() => { unlistenStatus?.(); unlistenLog?.(); unlistenError?.(); unli
|
||||
<div v-if="contextMenu.file?.is_offline" class="cm-item" @click="doUnmarkOffline(contextMenu.file)">
|
||||
☁ Nicht mehr offline (Platzhalter)
|
||||
</div>
|
||||
<div v-if="contextMenu.file?.is_offline" class="cm-item" @click="doUnlockFile(contextMenu.file)">
|
||||
🔓 Entsperren (Freigeben fuer andere)
|
||||
</div>
|
||||
<div class="cm-item" @click="hideContextMenu">Abbrechen</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user