mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-18 05:15:16 -04:00
refactor: remove RegisterOnly and redesign sync setup UX
Replace confusing RegisterOnly action with clearer ShareLocalLibrary and JoinRemoteLibrary actions. Add placeholder for future MergeLibraries. - Remove RegisterOnly from LibrarySyncAction enum - Add ShareLocalLibrary (share your library to remote device) - Add JoinRemoteLibrary (join existing remote library) - Add MergeLibraries stub for future implementation - Update CLI with three-option menu instead of two - Simplify CLI arg parsing for new actions The new UX is clearer: users choose to either share their library or join a remote one, instead of the ambiguous "register only" concept.
This commit is contained in:
@@ -161,21 +161,45 @@ impl SetupArgs {
|
||||
};
|
||||
|
||||
// Parse action
|
||||
let action_str = self.action.as_deref().unwrap_or("register-only");
|
||||
let action_str = self.action.as_deref().unwrap_or("share-local");
|
||||
let action = match action_str {
|
||||
"register-only" => LibrarySyncAction::RegisterOnly,
|
||||
"create-shared" => {
|
||||
"share-local" => {
|
||||
let name = self
|
||||
.name
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow::anyhow!("--name is required for create-shared action"))?;
|
||||
LibrarySyncAction::CreateShared {
|
||||
leader_device_id,
|
||||
name,
|
||||
.ok_or_else(|| anyhow::anyhow!("--name is required for share-local action"))?;
|
||||
LibrarySyncAction::ShareLocalLibrary { library_name: name }
|
||||
}
|
||||
"join-remote" => {
|
||||
let remote_library_id = self
|
||||
.remote_library
|
||||
.ok_or_else(|| anyhow::anyhow!("--remote-library is required for join-remote action"))?;
|
||||
let name = self
|
||||
.name
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow::anyhow!("--name is required for join-remote action"))?;
|
||||
LibrarySyncAction::JoinRemoteLibrary {
|
||||
remote_library_id,
|
||||
remote_library_name: name,
|
||||
}
|
||||
}
|
||||
"merge" => {
|
||||
let local_library_id = local_library;
|
||||
let remote_library_id = self
|
||||
.remote_library
|
||||
.ok_or_else(|| anyhow::anyhow!("--remote-library is required for merge action"))?;
|
||||
let name = self
|
||||
.name
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow::anyhow!("--name is required for merge action"))?;
|
||||
LibrarySyncAction::MergeLibraries {
|
||||
local_library_id,
|
||||
remote_library_id,
|
||||
merged_name: name,
|
||||
}
|
||||
}
|
||||
_ => anyhow::bail!(
|
||||
"Invalid action '{}'. Supported: register-only, create-shared",
|
||||
"Invalid action '{}'. Supported: share-local, join-remote, merge",
|
||||
action_str
|
||||
),
|
||||
};
|
||||
|
||||
@@ -326,16 +326,31 @@ async fn run_interactive_sync_setup(ctx: &Context) -> Result<LibrarySyncSetupInp
|
||||
let action_idx = select(
|
||||
"Select sync action",
|
||||
&[
|
||||
"Register existing library (sync with existing library on remote device)".to_string(),
|
||||
"Create shared library (create new shared library on both devices)".to_string(),
|
||||
"Share my library to remote device (create shared library from local)".to_string(),
|
||||
"Join remote library (use their existing library)".to_string(),
|
||||
"Merge libraries (combine two libraries) [NOT YET IMPLEMENTED]".to_string(),
|
||||
],
|
||||
)?;
|
||||
|
||||
let action = match action_idx {
|
||||
0 => {
|
||||
// Register existing library
|
||||
// Share local library
|
||||
let name = libraries[library_idx].name.clone();
|
||||
|
||||
println!(
|
||||
"\n✓ Will share library '{}' to remote device '{}'\n",
|
||||
name, remote_device.name
|
||||
);
|
||||
|
||||
(
|
||||
LibrarySyncAction::ShareLocalLibrary { library_name: name },
|
||||
None,
|
||||
)
|
||||
}
|
||||
1 => {
|
||||
// Join remote library
|
||||
if discovery_out.libraries.is_empty() {
|
||||
anyhow::bail!("No libraries found on remote device. Use 'Create shared library' instead.");
|
||||
anyhow::bail!("No libraries found on remote device. Use 'Share my library' instead.");
|
||||
}
|
||||
|
||||
let remote_lib_choices: Vec<String> = discovery_out
|
||||
@@ -349,42 +364,30 @@ async fn run_interactive_sync_setup(ctx: &Context) -> Result<LibrarySyncSetupInp
|
||||
})
|
||||
.collect();
|
||||
|
||||
let remote_lib_idx = select("Select remote library to sync with", &remote_lib_choices)?;
|
||||
let remote_library_id = discovery_out.libraries[remote_lib_idx].id;
|
||||
let remote_lib_idx = select("Select remote library to join", &remote_lib_choices)?;
|
||||
let remote_library = &discovery_out.libraries[remote_lib_idx];
|
||||
|
||||
println!(
|
||||
"\n✓ Will sync with remote library: {}\n",
|
||||
discovery_out.libraries[remote_lib_idx].name
|
||||
);
|
||||
|
||||
(LibrarySyncAction::RegisterOnly, Some(remote_library_id))
|
||||
}
|
||||
1 => {
|
||||
// Create shared library - the local library selected earlier will be shared to the remote device
|
||||
let name = libraries[library_idx].name.clone();
|
||||
|
||||
println!(
|
||||
"\n✓ Will share library '{}' to remote device '{}'\n",
|
||||
name, remote_device.name
|
||||
"\n✓ Will join remote library: {}\n",
|
||||
remote_library.name
|
||||
);
|
||||
|
||||
(
|
||||
LibrarySyncAction::CreateShared {
|
||||
leader_device_id: local_device_id,
|
||||
name,
|
||||
LibrarySyncAction::JoinRemoteLibrary {
|
||||
remote_library_id: remote_library.id,
|
||||
remote_library_name: remote_library.name.clone(),
|
||||
},
|
||||
None,
|
||||
Some(remote_library.id),
|
||||
)
|
||||
}
|
||||
2 => {
|
||||
anyhow::bail!("Library merging is not yet implemented");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let leader_device_id = match &action.0 {
|
||||
LibrarySyncAction::CreateShared {
|
||||
leader_device_id, ..
|
||||
} => *leader_device_id,
|
||||
_ => local_device_id,
|
||||
};
|
||||
// Leader device is always local for now (deprecated concept but still in input struct)
|
||||
let leader_device_id = local_device_id;
|
||||
|
||||
Ok(LibrarySyncSetupInput {
|
||||
local_device_id,
|
||||
|
||||
@@ -8,23 +8,26 @@ use uuid::Uuid;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
pub enum LibrarySyncAction {
|
||||
/// Keep libraries separate, only register devices in each other's libraries
|
||||
/// This allows Spacedrop and future selective sync without full library merge
|
||||
RegisterOnly,
|
||||
|
||||
/// Future: Merge remote library into local (local becomes leader)
|
||||
/// Share local library to remote device (creates same library with same UUID on remote)
|
||||
/// This is the primary way to create a shared library
|
||||
#[serde(rename_all = "camelCase")]
|
||||
MergeIntoLocal { remote_library_id: Uuid },
|
||||
ShareLocalLibrary { library_name: String },
|
||||
|
||||
/// Future: Merge local library into remote (remote becomes leader)
|
||||
/// Join an existing remote library (creates same library with same UUID locally)
|
||||
/// Use this when the other device has already shared their library
|
||||
#[serde(rename_all = "camelCase")]
|
||||
MergeIntoRemote { local_library_id: Uuid },
|
||||
JoinRemoteLibrary {
|
||||
remote_library_id: Uuid,
|
||||
remote_library_name: String,
|
||||
},
|
||||
|
||||
/// Future: Create new shared library (choose leader)
|
||||
/// Future: Merge two different libraries into one (combines data from both)
|
||||
/// Not yet implemented - requires full sync system
|
||||
#[serde(rename_all = "camelCase")]
|
||||
CreateShared {
|
||||
leader_device_id: Uuid,
|
||||
name: String,
|
||||
MergeLibraries {
|
||||
local_library_id: Uuid,
|
||||
remote_library_id: Uuid,
|
||||
merged_name: String,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user