diff --git a/bitchat/Services/MeshPlaintextNoticeSettings.swift b/bitchat/Services/MeshPlaintextNoticeSettings.swift index 8988e65d..43aca303 100644 --- a/bitchat/Services/MeshPlaintextNoticeSettings.swift +++ b/bitchat/Services/MeshPlaintextNoticeSettings.swift @@ -32,6 +32,12 @@ enum MeshPlaintextNoticeSettings { defaults.removeObject(forKey: dismissedKey) NotificationCenter.default.post(name: .meshPlaintextNoticeSettingsChanged, object: nil) } + + /// Visible on the public mesh composer once there is a live timeline. + /// An empty mesh already has the empty-state hint; don't stack both. + static func shouldShow(dismissed: Bool, isPublicMesh: Bool, timelineEmpty: Bool) -> Bool { + !dismissed && isPublicMesh && !timelineEmpty + } } extension Notification.Name { diff --git a/bitchat/Views/ContentComposerView.swift b/bitchat/Views/ContentComposerView.swift index 6157457c..aa340032 100644 --- a/bitchat/Views/ContentComposerView.swift +++ b/bitchat/Views/ContentComposerView.swift @@ -10,6 +10,7 @@ struct ContentComposerView: View { @EnvironmentObject private var conversationUIModel: ConversationUIModel @EnvironmentObject private var privateConversationModel: PrivateConversationModel @EnvironmentObject private var locationChannelsModel: LocationChannelsModel + @EnvironmentObject private var publicChatModel: PublicChatModel @ObservedObject private var bridgeService = BridgeService.shared @Environment(\.appTheme) private var theme @ThemedPalette private var palette @@ -162,12 +163,18 @@ struct ContentComposerView: View { private extension ContentComposerView { var showsMeshPlaintextNotice: Bool { - guard !meshPlaintextNoticeDismissed, - privateConversationModel.selectedHeaderState == nil, - case .mesh = locationChannelsModel.selectedChannel else { - return false + let onPublicMesh: Bool + if privateConversationModel.selectedHeaderState == nil, + case .mesh = locationChannelsModel.selectedChannel { + onPublicMesh = true + } else { + onPublicMesh = false } - return true + return MeshPlaintextNoticeSettings.shouldShow( + dismissed: meshPlaintextNoticeDismissed, + isPublicMesh: onPublicMesh, + timelineEmpty: publicChatModel.messages.isEmpty + ) } /// The nearby-only scope toggle appears only where it means something: diff --git a/bitchatTests/Services/MeshPlaintextNoticeSettingsTests.swift b/bitchatTests/Services/MeshPlaintextNoticeSettingsTests.swift index bf44682e..e4fd57ea 100644 --- a/bitchatTests/Services/MeshPlaintextNoticeSettingsTests.swift +++ b/bitchatTests/Services/MeshPlaintextNoticeSettingsTests.swift @@ -42,4 +42,11 @@ struct MeshPlaintextNoticeSettingsTests { #expect(received) #expect(!MeshPlaintextNoticeSettings.isDismissed(in: defaults)) } + + @Test func hiddenOnAnEmptyMeshTimeline() { + #expect(MeshPlaintextNoticeSettings.shouldShow(dismissed: false, isPublicMesh: true, timelineEmpty: true) == false) + #expect(MeshPlaintextNoticeSettings.shouldShow(dismissed: false, isPublicMesh: true, timelineEmpty: false) == true) + #expect(MeshPlaintextNoticeSettings.shouldShow(dismissed: true, isPublicMesh: true, timelineEmpty: false) == false) + #expect(MeshPlaintextNoticeSettings.shouldShow(dismissed: false, isPublicMesh: false, timelineEmpty: false) == false) + } }