feat(apple): collect transfers held for this device

Adds the opt-in foreground check and an explicit Check now, the waiting-to-
be-delivered list on the sender side, and honest reporting when a send could
not be delivered: a closed app is a delay, not a success nobody received.

The setting is off by default and its footer states that checking reveals
app-open times to remembered devices, since that is the reason it is a
setting at all.

Records in the design doc that this shipped as one global toggle rather than
the per-contact opt-in originally specified.
This commit is contained in:
2026-08-06 19:00:04 +02:00
parent 94a8ba2103
commit 0f70663263
52 changed files with 492 additions and 21 deletions

View File

@@ -127,6 +127,9 @@ struct AppPreferences: Equatable {
/// Devices the user declined to remember. Persisted so a repeat transfer
/// with the same device does not re-ask forever.
var declinedPairingSuggestions: Set<String>
/// Whether opening the app asks remembered devices for waiting transfers.
/// Off by default: it reveals app-open times to every contact.
var checkForOffersOnOpen: Bool
}
struct AppPreferencesDefaults {
@@ -152,6 +155,7 @@ final class AppPreferencesRepository: ObservableObject {
static let relayConfiguration = "relay_configuration"
static let grantLifetime = "grant_lifetime"
static let declinedPairingSuggestions = "declined_pairing_suggestions"
static let checkForOffersOnOpen = "check_for_offers_on_open"
}
init(defaults: UserDefaults = .standard, fallback: AppPreferencesDefaults) {
@@ -175,7 +179,8 @@ final class AppPreferencesRepository: ObservableObject {
diagnosticsInstallId: installId,
relayConfiguration: resolveRelayConfiguration(defaults),
grantLifetime: grantLifetime,
declinedPairingSuggestions: declined
declinedPairingSuggestions: declined,
checkForOffersOnOpen: defaults.bool(forKey: Key.checkForOffersOnOpen)
)
}
@@ -237,6 +242,11 @@ final class AppPreferencesRepository: ObservableObject {
reload()
}
func setCheckForOffersOnOpen(_ enabled: Bool) {
defaults.set(enabled, forKey: Key.checkForOffersOnOpen)
reload()
}
func setGrantLifetime(_ lifetime: GrantLifetimeOption) {
defaults.set(lifetime.rawValue, forKey: Key.grantLifetime)
reload()