Prevent Bluetooth alerts from interrupting modal warnings

This commit is contained in:
jack
2026-07-25 23:49:42 +02:00
parent 62cccc1c78
commit c056a46299
3 changed files with 94 additions and 4 deletions
+4
View File
@@ -9,11 +9,13 @@ import AppKit
struct ContentPeopleSheetModalPresentationState {
var isImagePreviewPresented = false
var isVerificationSheetPresented = false
var legacyPrivateMediaConsentRequest: LegacyPrivateMediaConsentRequest? = nil
var isMediaPickerPresented = false
var hasPresentation: Bool {
isImagePreviewPresented
|| isVerificationSheetPresented
|| legacyPrivateMediaConsentRequest != nil
|| isMediaPickerPresented
}
}
@@ -59,6 +61,8 @@ struct ContentPeopleSheetView: View {
return ContentPeopleSheetModalPresentationState(
isImagePreviewPresented: imagePreviewURL != nil,
isVerificationSheetPresented: showVerifySheet,
legacyPrivateMediaConsentRequest:
conversationUIModel.legacyPrivateMediaConsentRequest,
isMediaPickerPresented: isMediaPickerPresented
).hasPresentation
}
+32 -4
View File
@@ -23,6 +23,7 @@ struct ContentRootModalPresentationState {
var isImagePreviewPresented = false
var isVerificationSheetPresented = false
var isVoiceAlertPresented = false
var isScreenshotPrivacyAlertPresented = false
var isMediaPickerPresented = false
var hasPresentation: Bool {
@@ -34,10 +35,40 @@ struct ContentRootModalPresentationState {
|| isImagePreviewPresented
|| isVerificationSheetPresented
|| isVoiceAlertPresented
|| isScreenshotPrivacyAlertPresented
|| isMediaPickerPresented
}
}
extension ContentRootModalPresentationState {
@MainActor
init(
appChromeModel: AppChromeModel,
isPeopleSheetPresented: Bool = false,
isImagePreviewPresented: Bool = false,
isVerificationSheetPresented: Bool = false,
isVoiceAlertPresented: Bool = false,
isMediaPickerPresented: Bool = false
) {
self.init(
isPeopleSheetPresented: isPeopleSheetPresented,
isAppInfoPresented: appChromeModel.isAppInfoPresented,
isFingerprintPresented:
appChromeModel.showingFingerprintFor != nil,
isLocationChannelsSheetPresented:
appChromeModel.isLocationChannelsSheetPresented,
isNoticesSheetPresented:
appChromeModel.isNoticesSheetPresented,
isImagePreviewPresented: isImagePreviewPresented,
isVerificationSheetPresented: isVerificationSheetPresented,
isVoiceAlertPresented: isVoiceAlertPresented,
isScreenshotPrivacyAlertPresented:
appChromeModel.showScreenshotPrivacyWarning,
isMediaPickerPresented: isMediaPickerPresented
)
}
}
/// On macOS 14+, disables the default system focus ring on TextFields.
/// On earlier macOS versions and on iOS this is a no-op.
struct FocusEffectDisabledModifier: ViewModifier {
@@ -108,11 +139,8 @@ struct ContentView: View {
#endif
return ContentRootModalPresentationState(
appChromeModel: appChromeModel,
isPeopleSheetPresented: isPeopleSheetPresented,
isAppInfoPresented: appChromeModel.isAppInfoPresented,
isFingerprintPresented: appChromeModel.showingFingerprintFor != nil,
isLocationChannelsSheetPresented: appChromeModel.isLocationChannelsSheetPresented,
isNoticesSheetPresented: appChromeModel.isNoticesSheetPresented,
isImagePreviewPresented: imagePreviewURL != nil,
isVerificationSheetPresented: showVerifySheet,
isVoiceAlertPresented: voiceRecordingVM.showAlert,
+58
View File
@@ -576,6 +576,64 @@ struct ViewSmokeTests {
)
}
@Test("Root Bluetooth alert waits for screenshot privacy alert")
@MainActor
func rootBluetoothAlertGuard_tracksScreenshotPrivacyState() {
let (viewModel, _, _) = makeSmokeViewModel()
let featureModels = makeSmokeFeatureModels(for: viewModel)
#expect(
!ContentRootModalPresentationState(
appChromeModel: featureModels.appChromeModel
).hasPresentation
)
featureModels.appChromeModel.showScreenshotPrivacyWarning = true
#expect(
ContentRootModalPresentationState(
appChromeModel: featureModels.appChromeModel
).hasPresentation
)
}
@Test("People-sheet Bluetooth alert waits for legacy media consent")
@MainActor
func peopleSheetBluetoothAlertGuard_tracksLegacyConsentState() async {
let (viewModel, _, _) = makeSmokeViewModel()
let featureModels = makeSmokeFeatureModels(for: viewModel)
#expect(
!ContentPeopleSheetModalPresentationState(
legacyPrivateMediaConsentRequest:
featureModels.conversationUIModel
.legacyPrivateMediaConsentRequest
).hasPresentation
)
viewModel.enqueueLegacyPrivateMediaConsent(
for: PeerID(str: "5152535455565758"),
transferId: "legacy-consent-transfer",
messageID: "legacy-consent-message"
) { _ in }
defer { viewModel.cancelAllLegacyPrivateMediaConsents() }
let consentPropagated = await TestHelpers.waitUntil {
featureModels.conversationUIModel
.legacyPrivateMediaConsentRequest != nil
}
#expect(
consentPropagated
)
#expect(
ContentPeopleSheetModalPresentationState(
legacyPrivateMediaConsentRequest:
featureModels.conversationUIModel
.legacyPrivateMediaConsentRequest
).hasPresentation
)
}
@Test
func geohashAndTextMessageViews_renderCoreBranches() {
let (viewModel, _, _) = makeSmokeViewModel()