Prepare Apple App Store distribution (#59)

This commit is contained in:
hugo committed 2026-08-16 17:55:59 +02:00
1 parent b50e47ab73
commit f894d43eb6
46 files changed
+20694 -166

No files matched your search

+131 -19
View File
@@ -13,7 +13,8 @@ use crate::{
config::{Config, ConfigError, GitRemote},
git::{
FetchOutcome, GitChangeKind, GitCommitActivity, GitDivergence, GitError,
GitOperationControl, GitProgressPhase, GitRepository, PullOutcome, PushOutcome,
GitOperationControl, GitProgressPhase, GitRepository, GitSnapshot, PullOutcome,
PushOutcome,
},
mobile_authentication::{
MobileAuthentication, MobileRepositoryOperation, MobileRepositoryOperationError,
@@ -219,6 +220,7 @@ impl MobileHomeNotice {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MobileHomePage {
remote_configured: bool,
freshness: MobileHomeFreshness,
refreshed_at: Option<i64>,
summaries: Vec<MobileHomeSummaryRow>,
@@ -230,6 +232,10 @@ pub struct MobileHomePage {
}
impl MobileHomePage {
pub fn remote_configured(&self) -> bool {
self.remote_configured
}
pub fn freshness(&self) -> MobileHomeFreshness {
self.freshness
}
@@ -364,6 +370,9 @@ impl MobileHomeOperation {
pub fn refresh_if_stale(&self) -> Result<MobileHomePage, MobileHomeError> {
let storage = MobileHomeStorage::load()?;
let now = unix_seconds()?;
if storage.remote.is_none() {
return storage.page(MobileHomeFreshness::Current, Some(now), None);
}
if !is_stale(storage.config.mobile_home_refreshed_at(), now) {
return storage.page(
MobileHomeFreshness::Cached,
@@ -429,7 +438,7 @@ impl MobileHomeOperation {
struct MobileHomeStorage {
config: Config,
git: GitRepository,
remote: GitRemote,
remote: Option<GitRemote>,
}
impl MobileHomeStorage {
@@ -439,10 +448,7 @@ impl MobileHomeStorage {
Repository::open(config.vault()).map_err(MobileHomeError::from_repository)?;
let git = GitRepository::open(&repository, config.git_identity().clone())
.map_err(MobileHomeError::from_git)?;
let remote = config
.git_remote(None)
.cloned()
.ok_or_else(MobileHomeError::missing_remote)?;
let remote = config.git_remote(None).cloned();
Ok(Self {
config,
git,
@@ -478,9 +484,10 @@ impl MobileHomeStorage {
now: i64,
control: &GitOperationControl,
) -> Result<MobileHomePage, MobileHomeError> {
let remote = self.remote()?;
let store = self.credentials()?;
let fetched = self.git.fetch_with_transport_controlled(
&self.remote,
remote,
&store,
&crate::git::EmbeddedFetchTransport,
control,
@@ -501,9 +508,10 @@ impl MobileHomeStorage {
now: i64,
control: &GitOperationControl,
) -> Result<MobileHomePage, MobileHomeError> {
let remote = self.remote()?;
let store = self.credentials()?;
let pulled = self.git.pull_with_transport_controlled(
&self.remote,
remote,
None,
&store,
&crate::git::EmbeddedFetchTransport,
@@ -526,9 +534,10 @@ impl MobileHomeStorage {
now: i64,
control: &GitOperationControl,
) -> Result<MobileHomePage, MobileHomeError> {
let remote = self.remote()?;
let store = self.credentials()?;
let pushed = self.git.push_with_transport_controlled(
&self.remote,
remote,
None,
&store,
&crate::git::ReqwestGitTransport,
@@ -556,6 +565,12 @@ impl MobileHomeStorage {
Ok(store)
}
fn remote(&self) -> Result<&GitRemote, MobileHomeError> {
self.remote
.as_ref()
.ok_or_else(MobileHomeError::missing_remote)
}
fn current_page(
&self,
now: i64,
@@ -585,16 +600,29 @@ impl MobileHomeStorage {
refreshed_at: Option<i64>,
notice: Option<MobileHomeNotice>,
) -> Result<MobileHomePage, MobileHomeError> {
let divergence = self
.git
.divergence(&self.remote, ACTIVITY_LIMIT)
.map_err(MobileHomeError::from_git)?;
Ok(page_from_divergence(
&divergence,
freshness,
refreshed_at,
notice,
))
if let Some(remote) = self.remote.as_ref() {
let divergence = self
.git
.divergence(remote, ACTIVITY_LIMIT)
.map_err(MobileHomeError::from_git)?;
Ok(page_from_divergence(
&divergence,
freshness,
refreshed_at,
notice,
))
} else {
let snapshot = self
.git
.snapshot(None, ACTIVITY_LIMIT)
.map_err(MobileHomeError::from_git)?;
Ok(page_from_local_snapshot(
&snapshot,
freshness,
refreshed_at,
notice,
))
}
}
}
@@ -931,6 +959,7 @@ fn page_from_divergence(
},
];
MobileHomePage {
remote_configured: true,
freshness,
refreshed_at,
summaries,
@@ -950,6 +979,89 @@ fn page_from_divergence(
}
}
fn page_from_local_snapshot(
snapshot: &GitSnapshot,
freshness: MobileHomeFreshness,
refreshed_at: Option<i64>,
notice: Option<MobileHomeNotice>,
) -> MobileHomePage {
let local_paths = snapshot
.status()
.staged()
.iter()
.chain(snapshot.status().unstaged())
.map(|change| change.path().to_owned())
.collect::<BTreeSet<_>>();
let commit_count = snapshot.recent().len();
let latest = snapshot
.recent()
.first()
.and_then(|commit| {
commit
.message()
.lines()
.find(|line| !line.trim().is_empty())
})
.map(|line| display_text(line.trim(), 160));
MobileHomePage {
remote_configured: false,
freshness,
refreshed_at,
summaries: vec![
MobileHomeSummaryRow {
id: "local-branch".to_owned(),
title: snapshot.branch().to_owned(),
detail: "Local Git branch · no sync remote configured".to_owned(),
system_image: "externaldrive.fill".to_owned(),
actions: Vec::new(),
},
MobileHomeSummaryRow {
id: "local-history".to_owned(),
title: format!(
"{} Local Commit{}",
commit_count,
if commit_count == 1 { "" } else { "s" }
),
detail: latest.unwrap_or_else(|| "No local history yet".to_owned()),
system_image: "clock.arrow.circlepath".to_owned(),
actions: Vec::new(),
},
working_tree_summary(local_paths.len()),
],
incoming: Vec::new(),
outgoing: Vec::new(),
incoming_total: 0,
outgoing_total: 0,
notice,
}
}
fn working_tree_summary(local_count: usize) -> MobileHomeSummaryRow {
MobileHomeSummaryRow {
id: "working-tree".to_owned(),
title: if local_count == 0 {
"Working Tree Clean".to_owned()
} else {
format!("{} Local", change_count(local_count))
},
detail: if local_count == 0 {
"No uncommitted password-store changes".to_owned()
} else {
"Commit these local password-store changes".to_owned()
},
system_image: if local_count == 0 {
"checkmark.shield".to_owned()
} else {
"exclamationmark.triangle".to_owned()
},
actions: if local_count > 0 {
vec![mobile_action(MobileHomeActionKind::Commit)]
} else {
Vec::new()
},
}
}
fn mobile_commit(activity: &GitCommitActivity, incoming: bool) -> MobileHomeCommit {
let commit = activity.commit();
let title = commit