diff --git a/Meshtastic/Extensions/CoreData/ChannelEntityExtension.swift b/Meshtastic/Extensions/CoreData/ChannelEntityExtension.swift index dfa373be..e5a4d95a 100644 --- a/Meshtastic/Extensions/CoreData/ChannelEntityExtension.swift +++ b/Meshtastic/Extensions/CoreData/ChannelEntityExtension.swift @@ -18,4 +18,14 @@ extension ChannelEntity { let unreadMessages = allPrivateMessages.filter{ ($0 as AnyObject).read == false } return unreadMessages.count } + + var protoBuf: Channel { + var channel = Channel() + channel.index = self.index + channel.settings.name = self.name ?? "" + channel.settings.psk = self.psk ?? Data() + channel.role = Channel.Role(rawValue: Int(self.role)) ?? Channel.Role.secondary + channel.settings.moduleSettings.positionPrecision = UInt32(self.positionPrecision) + return channel + } } diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 892c81f5..c4003f26 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -160,12 +160,14 @@ func channelPacket (channel: Channel, fromNum: Int64, context: NSManagedObjectCo newChannel.name = channel.settings.name newChannel.role = Int32(channel.role.rawValue) newChannel.psk = channel.settings.psk - newChannel.positionPrecision = Int32(truncatingIfNeeded: channel.settings.moduleSettings.positionPrecision) + if channel.settings.hasModuleSettings { + newChannel.positionPrecision = Int32(truncatingIfNeeded: channel.settings.moduleSettings.positionPrecision) + newChannel.mute = channel.settings.moduleSettings.isClientMuted + } guard let mutableChannels = fetchedMyInfo[0].channels!.mutableCopy() as? NSMutableOrderedSet else { return } if let oldChannel = mutableChannels.first(where: {($0 as AnyObject).index == newChannel.index }) as? ChannelEntity { - newChannel.mute = oldChannel.mute let index = mutableChannels.index(of: oldChannel as Any) mutableChannels.replaceObject(at: index, with: newChannel) } else { @@ -841,26 +843,28 @@ func textMessageAppPacket(packet: MeshPacket, wantRangeTestPackets: Bool, connec return } let appState = AppState.shared - if newMessage.fromUser != nil && newMessage.toUser != nil && !(newMessage.fromUser?.mute ?? false) { + if newMessage.fromUser != nil && newMessage.toUser != nil { // Set Unread Message Indicators if packet.to == connectedNode { appState.unreadDirectMessages = newMessage.toUser?.unreadMessages ?? 0 UIApplication.shared.applicationIconBadgeNumber = appState.unreadChannelMessages + appState.unreadDirectMessages } - // Create an iOS Notification for the received DM message and schedule it immediately - let manager = LocalNotificationManager() - manager.notifications = [ - Notification( - id: ("notification.id.\(newMessage.messageId)"), - title: "\(newMessage.fromUser?.longName ?? "unknown".localized)", - subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")", - content: messageText!, - target: "message", - path: "meshtastic://open-dm?userid=\(newMessage.fromUser?.num ?? 0)&id=\(newMessage.messageId)" - ) - ] - manager.schedule() - print("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "unknown".localized)") + if !(newMessage.fromUser?.mute ?? false) { + // Create an iOS Notification for the received DM message and schedule it immediately + let manager = LocalNotificationManager() + manager.notifications = [ + Notification( + id: ("notification.id.\(newMessage.messageId)"), + title: "\(newMessage.fromUser?.longName ?? "unknown".localized)", + subtitle: "AKA \(newMessage.fromUser?.shortName ?? "?")", + content: messageText!, + target: "message", + path: "meshtastic://open-dm?userid=\(newMessage.fromUser?.num ?? 0)&id=\(newMessage.messageId)" + ) + ] + manager.schedule() + print("💬 iOS Notification Scheduled for text message from \(newMessage.fromUser?.longName ?? "unknown".localized)") + } } else if newMessage.fromUser != nil && newMessage.toUser == nil { let fetchMyInfoRequest: NSFetchRequest = NSFetchRequest.init(entityName: "MyInfoEntity") diff --git a/Meshtastic/Protobufs/meshtastic/channel.pb.swift b/Meshtastic/Protobufs/meshtastic/channel.pb.swift index 493230ba..992d8f4c 100644 --- a/Meshtastic/Protobufs/meshtastic/channel.pb.swift +++ b/Meshtastic/Protobufs/meshtastic/channel.pb.swift @@ -120,6 +120,11 @@ struct ModuleSettings { /// Bits of precision for the location sent in position packets. var positionPrecision: UInt32 = 0 + /// + /// Controls whether or not the phone / clients should mute the current channel + /// Useful for noisy public channels you don't necessarily want to disable + var isClientMuted: Bool = false + var unknownFields = SwiftProtobuf.UnknownStorage() init() {} @@ -311,6 +316,7 @@ extension ModuleSettings: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement static let protoMessageName: String = _protobuf_package + ".ModuleSettings" static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 1: .standard(proto: "position_precision"), + 2: .standard(proto: "is_client_muted"), ] mutating func decodeMessage(decoder: inout D) throws { @@ -320,6 +326,7 @@ extension ModuleSettings: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement // enabled. https://github.com/apple/swift-protobuf/issues/1034 switch fieldNumber { case 1: try { try decoder.decodeSingularUInt32Field(value: &self.positionPrecision) }() + case 2: try { try decoder.decodeSingularBoolField(value: &self.isClientMuted) }() default: break } } @@ -329,11 +336,15 @@ extension ModuleSettings: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement if self.positionPrecision != 0 { try visitor.visitSingularUInt32Field(value: self.positionPrecision, fieldNumber: 1) } + if self.isClientMuted != false { + try visitor.visitSingularBoolField(value: self.isClientMuted, fieldNumber: 2) + } try unknownFields.traverse(visitor: &visitor) } static func ==(lhs: ModuleSettings, rhs: ModuleSettings) -> Bool { if lhs.positionPrecision != rhs.positionPrecision {return false} + if lhs.isClientMuted != rhs.isClientMuted {return false} if lhs.unknownFields != rhs.unknownFields {return false} return true } diff --git a/Meshtastic/Views/Messages/ChannelList.swift b/Meshtastic/Views/Messages/ChannelList.swift index 2c3a83f4..d8a4e96d 100644 --- a/Meshtastic/Views/Messages/ChannelList.swift +++ b/Meshtastic/Views/Messages/ChannelList.swift @@ -109,6 +109,24 @@ struct ChannelList: View { Label("Delete Messages", systemImage: "trash") } } + Button { + channel.mute = !channel.mute + + do { + let adminMessageId = bleManager.saveChannel(channel: channel.protoBuf, fromUser: node!.user!, toUser: node!.user!) + if adminMessageId > 0 { + context.refresh(channel, mergeChanges: true) + } + + try context.save() + + } catch { + context.rollback() + print("💥 Save Channel Mute Error") + } + } label: { + Label(channel.mute ? "Show Alerts" : "Hide Alerts", systemImage: channel.mute ? "bell" : "bell.slash") + } } .confirmationDialog( "This conversation will be deleted.", diff --git a/protobufs b/protobufs index 86640f20..e21899aa 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 86640f20db7b9b5be42949d18e8d96ad10d47a68 +Subproject commit e21899aa6b2b49863cfa2758e5e3b6faacf04bba