Preserve open DMs across Bluetooth settings

This commit is contained in:
jack
2026-07-26 01:46:12 +02:00
committed by jack
parent cbb77701c1
commit c516f0f020
2 changed files with 90 additions and 3 deletions
+41
View File
@@ -11,6 +11,7 @@ struct ContentPeopleSheetView: View {
@EnvironmentObject private var privateConversationModel: PrivateConversationModel @EnvironmentObject private var privateConversationModel: PrivateConversationModel
@EnvironmentObject private var verificationModel: VerificationModel @EnvironmentObject private var verificationModel: VerificationModel
@EnvironmentObject private var conversationUIModel: ConversationUIModel @EnvironmentObject private var conversationUIModel: ConversationUIModel
@Environment(\.scenePhase) private var scenePhase
@Binding var showSidebar: Bool @Binding var showSidebar: Bool
@Binding var messageText: String @Binding var messageText: String
@@ -35,6 +36,35 @@ struct ContentPeopleSheetView: View {
@Binding var showMacImagePicker: Bool @Binding var showMacImagePicker: Bool
#endif #endif
private var hasModalPresentation: Bool {
if imagePreviewURL != nil {
return true
}
#if os(iOS)
return showImagePicker
#else
return showMacImagePicker
#endif
}
private var bluetoothAlertBinding: Binding<Bool> {
Binding(
get: {
scenePhase == .active
&& appChromeModel.showBluetoothAlert
&& !hasModalPresentation
},
set: { isPresented in
guard !isPresented,
scenePhase == .active,
!hasModalPresentation else {
return
}
appChromeModel.showBluetoothAlert = false
}
)
}
var body: some View { var body: some View {
let legacyConsentRequest = conversationUIModel.legacyPrivateMediaConsentRequest let legacyConsentRequest = conversationUIModel.legacyPrivateMediaConsentRequest
NavigationStack { NavigationStack {
@@ -182,6 +212,17 @@ struct ContentPeopleSheetView: View {
} }
} }
#endif #endif
.alert(
"content.alert.bluetooth_required.title",
isPresented: bluetoothAlertBinding
) {
Button("content.alert.bluetooth_required.settings") {
SystemSettings.bluetooth.open()
}
Button("common.ok", role: .cancel) {}
} message: {
Text(appChromeModel.bluetoothAlertMessage)
}
} }
} }
+48 -2
View File
@@ -42,6 +42,7 @@ struct ContentView: View {
@FocusState private var isTextFieldFocused: Bool @FocusState private var isTextFieldFocused: Bool
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@Environment(\.appTheme) private var appTheme @Environment(\.appTheme) private var appTheme
@Environment(\.scenePhase) private var scenePhase
@State private var showSidebar = false @State private var showSidebar = false
@State private var selectedMessageSender: String? @State private var selectedMessageSender: String?
@State private var selectedMessageSenderID: PeerID? @State private var selectedMessageSenderID: PeerID?
@@ -71,6 +72,44 @@ struct ContentView: View {
private var usesGlassLayout: Bool { appTheme.usesGlassChrome } private var usesGlassLayout: Bool { appTheme.usesGlassChrome }
private var isPeopleSheetPresented: Bool {
showSidebar || selectedPrivatePeerID != nil
}
private var hasRootModalPresentation: Bool {
if isPeopleSheetPresented
|| appChromeModel.isAppInfoPresented
|| appChromeModel.showingFingerprintFor != nil
|| imagePreviewURL != nil
|| showVerifySheet
|| voiceRecordingVM.showAlert {
return true
}
#if os(iOS)
return showImagePicker
#else
return showMacImagePicker
#endif
}
private var rootBluetoothAlertBinding: Binding<Bool> {
Binding(
get: {
scenePhase == .active
&& appChromeModel.showBluetoothAlert
&& !hasRootModalPresentation
},
set: { isPresented in
guard !isPresented,
scenePhase == .active,
!hasRootModalPresentation else {
return
}
appChromeModel.showBluetoothAlert = false
}
)
}
var body: some View { var body: some View {
mainContent mainContent
.onAppear { .onAppear {
@@ -107,13 +146,20 @@ struct ContentView: View {
} }
.sheet( .sheet(
isPresented: Binding( isPresented: Binding(
get: { showSidebar || selectedPrivatePeerID != nil }, get: { isPeopleSheetPresented },
set: { isPresented in set: { isPresented in
if !isPresented { if !isPresented {
showSidebar = false showSidebar = false
// Scene/background and Bluetooth-alert presentation
// reconciliation are not user requests to leave the
// conversation. Keep the selected DM so the sheet
// remains live when the app returns from Settings.
if scenePhase == .active,
!appChromeModel.showBluetoothAlert {
privateConversationModel.endConversation() privateConversationModel.endConversation()
} }
} }
}
) )
) { ) {
#if os(iOS) #if os(iOS)
@@ -222,7 +268,7 @@ struct ContentView: View {
}, message: { }, message: {
Text(voiceRecordingVM.state.alertMessage) Text(voiceRecordingVM.state.alertMessage)
}) })
.alert("content.alert.bluetooth_required.title", isPresented: $appChromeModel.showBluetoothAlert) { .alert("content.alert.bluetooth_required.title", isPresented: rootBluetoothAlertBinding) {
Button("content.alert.bluetooth_required.settings") { Button("content.alert.bluetooth_required.settings") {
SystemSettings.bluetooth.open() SystemSettings.bluetooth.open()
} }