Implement confirmed Android tree mutation workflows (#108)
Android ARM verification / rust (push) Failing after 49m2s
Android ARM verification / android (push) Failing after 8s
Dependency security audit / rustsec (push) Successful in 2m40s

This commit is contained in:
hugo committed 2026-10-12 13:06:22 +02:00
1 parent 6a864a8d7f
commit 316a875d63
22 files changed
+2170 -220

No files matched your search

+110
View File
@@ -932,6 +932,69 @@ impl From<StorageMutationPlan> for MobileMutationPlan {
}
}
#[derive(Clone, uniffi::Record)]
pub struct MobileTreeMutationDestination {
pub path: String,
pub title: String,
pub detail: String,
pub requires_overwrite: bool,
pub depth: u32,
pub unavailable: Option<String>,
pub collision_targets: Vec<String>,
}
#[derive(Clone, uniffi::Record)]
pub struct MobileTreeMutationPlan {
pub action: MobileMutationAction,
pub source: String,
pub source_title: String,
pub kind: MobilePasswordRowKind,
pub revision: String,
pub entries: u32,
pub destinations: Vec<MobileTreeMutationDestination>,
pub has_open_editor: bool,
pub has_dirty_editor: bool,
}
impl From<StorageMutationPlan> for MobileTreeMutationPlan {
fn from(plan: StorageMutationPlan) -> Self {
Self {
action: plan.action().into(),
source: plan.source().to_owned(),
source_title: plan.source_title().to_owned(),
kind: if plan.is_directory() {
MobilePasswordRowKind::Directory
} else {
MobilePasswordRowKind::Entry
},
revision: plan.revision().to_owned(),
entries: plan.entries(),
destinations: plan
.destinations()
.iter()
.map(|destination| MobileTreeMutationDestination {
path: destination.path().to_owned(),
title: destination.title().to_owned(),
detail: destination.detail().to_owned(),
requires_overwrite: destination.requires_overwrite(),
depth: destination.depth(),
unavailable: destination.unavailable().map(str::to_owned),
collision_targets: destination.collision_targets().to_vec(),
})
.collect(),
has_open_editor: plan.has_open_editor(),
has_dirty_editor: plan.has_dirty_editor(),
}
}
}
#[derive(Clone, uniffi::Record)]
pub struct MobileNavigationMutationOutcome {
pub result: MobileMutationOutcome,
pub navigation: MobilePasswordNavigation,
pub discarded_editors: Vec<u64>,
}
#[derive(Clone, uniffi::Record)]
pub struct MobileMutationRequest {
pub action: MobileMutationAction,
@@ -2103,6 +2166,53 @@ impl MobileAuthentication {
.map_err(Into::into)
}
pub fn prepare_navigation_mutation(
&self,
id: String,
revision: String,
action: MobileMutationAction,
) -> Result<MobileTreeMutationPlan, MobileAuthenticationFfiError> {
self.authentication
.prepare_navigation_mutation(&id, &revision, action.into())
.map(Into::into)
.map_err(Into::into)
}
pub fn unlock_mutation(
&self,
source: String,
revision: String,
passphrase: Option<String>,
) -> Result<MobileAuthenticationState, MobileAuthenticationFfiError> {
self.authentication
.unlock_mutation(
&source,
&revision,
passphrase
.map(|value| ironstorage::repository::SecretBytes::new(value.into_bytes())),
)
.map(Into::into)
.map_err(Into::into)
}
pub fn perform_navigation_mutation(
&self,
request: MobileMutationRequest,
return_path: String,
) -> Result<MobileNavigationMutationOutcome, MobileAuthenticationFfiError> {
self.authentication
.perform_navigation_mutation(request.into(), &return_path)
.map(|outcome| {
let discarded_editors = outcome.result.discarded_editors().to_vec();
MobileNavigationMutationOutcome {
result: outcome.result.into(),
navigation: outcome.navigation.into(),
discarded_editors,
}
})
.map_err(Into::into)
}
pub fn prepare_presented_entry_mutation(
&self,
path: String,