fix(ios): address App Store review requirements

Use compliant permission prompts, align cloud ASR privacy disclosures, and default Flow sessions to a shorter inactivity window for safer resubmission.
This commit is contained in:
Rocky
2026-07-23 15:37:38 +08:00
parent c0c9dad149
commit e6f99d2744
18 changed files with 178 additions and 83 deletions
@@ -33,7 +33,7 @@ final class AppGroupConfigurationTests: XCTestCase {
XCTAssertEqual(config.polishIntensity, .default)
XCTAssertTrue(config.personalDictionary.entries.isEmpty)
XCTAssertTrue(config.flowSkipAppSwitch)
XCTAssertEqual(config.flowInactivityDuration, .thirtyMinutes)
XCTAssertEqual(config.flowInactivityDuration, .fiveMinutes)
}
func testSaveAndLoadRoundTrip() {
@@ -84,33 +84,50 @@ final class AppGroupConfigurationTests: XCTestCase {
XCTAssertEqual(loaded.flowInactivityDuration, .threeHours)
}
/// Existing installs (onboarding completed, no explicit engineMode key)
/// ran on the old "cloud"/12h defaults a silent flip to the new
/// privacy defaults would change their engine under them AND propagate
/// through settings sync as a fake fresh edit to their other devices.
func testDefaultMigrationPreservesExistingInstallBehavior() {
/// Existing installs retain their legacy engine, but an unset inactivity
/// duration adopts the current privacy-safe default.
func testDefaultMigrationUsesPrivacySafeInactivityDuration() {
let defaults = makeDefaults()
defaults.set(true, forKey: AppGroupConfiguration.Keys.hasCompletedOnboarding)
let config = AppGroupConfiguration.load(fromAvailable: defaults)
XCTAssertEqual(config.engineMode, "cloud", "pre-picker installs stay on their old default")
XCTAssertEqual(config.flowInactivityDuration, .twelveHours)
XCTAssertEqual(config.flowInactivityDuration, .fiveMinutes)
// The resolution is persisted so it is stable and sync-invisible.
XCTAssertEqual(defaults.string(forKey: AppGroupConfiguration.Keys.engineMode), "cloud")
XCTAssertEqual(
defaults.string(forKey: AppGroupConfiguration.Keys.flowInactivityDuration),
FlowInactivityDuration.twelveHours.rawValue
FlowInactivityDuration.fiveMinutes.rawValue
)
}
func testPreviousDefaultInactivityIsMigratedToFiveMinutesOnce() {
let defaults = makeDefaults()
defaults.set(FlowInactivityDuration.thirtyMinutes.rawValue,
forKey: AppGroupConfiguration.Keys.flowInactivityDuration)
let first = AppGroupConfiguration.load(fromAvailable: defaults)
XCTAssertEqual(first.flowInactivityDuration, .fiveMinutes)
XCTAssertTrue(defaults.bool(
forKey: AppGroupConfiguration.Keys.flowInactivityMigratedToFiveMinuteDefault
))
// After migration, an explicit 30-minute choice sticks.
var updated = first
updated.flowInactivityDuration = .thirtyMinutes
updated.save(to: defaults)
let second = AppGroupConfiguration.load(fromAvailable: defaults)
XCTAssertEqual(second.flowInactivityDuration, .thirtyMinutes)
}
func testDefaultMigrationGivesFreshInstallPrivacyDefaults() {
let defaults = makeDefaults()
let config = AppGroupConfiguration.load(fromAvailable: defaults)
XCTAssertEqual(config.engineMode, "local")
XCTAssertEqual(config.flowInactivityDuration, .thirtyMinutes)
XCTAssertEqual(config.flowInactivityDuration, .fiveMinutes)
XCTAssertEqual(defaults.string(forKey: AppGroupConfiguration.Keys.engineMode), "local")
}