Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  PushSettingManager.swift   Sprache: JAVA

 

import CocoaLumberjackSwift
import Foundation
import ThreemaEssentials

public protocol PushSettingManagerProtocol {
    func find(forContact identity: ThreemaIdentity) -> PushSetting
    func find(forGroup groupIdentity: GroupIdentity) -> PushSetting
    func pushSetting(for pendingUserNotification: PendingUserNotification) -> PushSetting?
    func save(pushSetting: PushSetting, sync: Bool) async
    func delete(forContact identity: ThreemaIdentity) async
    func canSendPush(for message: BaseMessageEntity) -> Bool
    func canMasterDndSendPush() -> Bool
}

public actor PushSettingManager: PushSettingManagerProtocol {

    enum PushSettingManagerError: Error {
        case decodingFailed
    }

    private typealias TimeOfDay = (hour: Int, minute: Int)

    private let userSettings: UserSettingsProtocol
    private let groupManager: GroupManagerProtocol
    private let entityManager: EntityManager
    private let markupParser: MarkupParser
    private let taskManager: TaskManagerProtocol
    private let isWorkApp: Bool

    init(
        userSettings: UserSettingsProtocol,
        groupManager: GroupManagerProtocol,
        entityManager: EntityManager,
        markupParser: MarkupParser,
        taskManager: TaskManagerProtocol,
        isWorkApp: Bool
    ) {
        self.userSettings = userSettings
        self.groupManager = groupManager
        self.entityManager = entityManager
        self.markupParser = markupParser
        self.taskManager = taskManager
        self.isWorkApp = isWorkApp
    }

    init(
        entityManager: EntityManager = PersistenceManager(
            appGroupID: AppGroup.groupID(),
            userDefaults: AppGroup.userDefaults(),
            remoteSecretManager: RemoteSecretProvider.remoteSecretManager
        ).entityManager,
        markupParser: MarkupParser = MarkupParser(),
        taskManager: TaskManagerProtocol = TaskManager()
    ) {
        self.init(
            userSettings: UserSettings.shared(),
            groupManager: GroupManager(entityManager: entityManager, taskManager: taskManager),
            entityManager: entityManager,
            markupParser: markupParser,
            taskManager: taskManager,
            isWorkApp: TargetManager.isBusinessApp
        )
    }

    /// Get stored or default push setting for contact
    public nonisolated func find(forContact identity: ThreemaIdentity) -> PushSetting {
        var pushSetting: PushSetting?

        do {
            let pushSettings = try decode()
            pushSetting = pushSettings.first(where: { $0.identity == identity })
            if pushSetting?.updatePeriodOffTillDateIsExpired() ?? false {
                if let pushSetting {
                    Task {
                        await save(pushSetting: pushSetting, sync: false)
                    }
                }
            }
        }
        catch {
            DDLogError("Error while looking push settings for '\(identity)': \(error)")
        }

        return pushSetting ?? PushSetting(identity: identity)
    }

    /// Get stored or default push setting for group
    public nonisolated func find(forGroup groupIdentity: GroupIdentity) -> PushSetting {
        var pushSetting: PushSetting?

        do {
            let pushSettings = try decode()
            pushSetting = pushSettings.first(where: { $0.groupIdentity == groupIdentity })
            if pushSetting?.updatePeriodOffTillDateIsExpired() ?? false {
                if let pushSetting {
                    Task {
                        await save(pushSetting: pushSetting, sync: false)
                    }
                }
            }
        }
        catch {
            DDLogError("Error while looking push settings for '\(groupIdentity)': \(error)")
        }

        return pushSetting ?? PushSetting(groupIdentity: groupIdentity)
    }
    
    /// Computes the `PushSetting` for a given `PendingUserNotification`
    /// - Parameter pendingUserNotification: `PendingUserNotification` to find `PushSetting` for
    /// - Returns: `PushSetting1
    public nonisolated func pushSetting(for pendingUserNotification: PendingUserNotification) -> PushSetting? {
        
        if let isGroupMessage = pendingUserNotification.isGroupMessage, isGroupMessage,
           let baseMessage = pendingUserNotification.baseMessage,
           let group = entityManager.entityFetcher.groupEntity(for: baseMessage.conversation) {
            let creator = group.groupCreator ?? MyIdentityStore.shared().identity
            return find(forGroup: GroupIdentity(id: group.groupID, creator: ThreemaIdentity(creator!)))
        }
        
        else if let groupCallMessage = pendingUserNotification.abstractMessage as? GroupCallStartMessage {
            return find(forGroup: GroupIdentity(
                id: groupCallMessage.groupID,
                creator: ThreemaIdentity(groupCallMessage.groupCreator)
            ))
        }
        
        else if let senderIdentity = pendingUserNotification.senderIdentity {
            return find(forContact: ThreemaIdentity(senderIdentity))
        }
        
        assertionFailure("This should not happen.")
        return nil
    }

    /// Save push setting
    ///
    /// - Parameters:
    /// - pushSetting: Setting to save
    /// - sync: If true setting will be synced if multi device enabled
    public func save(pushSetting: PushSetting, sync: Bool) async {
        do {
            var pushSettings = try decode()
            pushSettings.removeAll { item in
                if let identity = pushSetting.identity {
                    return item.identity == identity
                }
                else if let groupIdentity = pushSetting.groupIdentity {
                    return item.groupIdentity == groupIdentity
                }
                return false
            }
            pushSettings.append(pushSetting)
            try encode(pushSettings)

            if sync {
                if let identity = pushSetting.identity {
                    var pushSetting = pushSetting
                    let mediatorSyncableContacts = MediatorSyncableContacts(
                        userSettings: userSettings,
                        pushSettingManager: self,
                        taskManager: TaskManager(),
                        entityManager: entityManager
                    )
                    mediatorSyncableContacts.updateNotificationTrigger(
                        identity: identity.rawValue,
                        type: pushSetting.type,
                        expiresAt: pushSetting.periodOffTillDate
                    )
                    mediatorSyncableContacts.syncAsync()
                }
                else if let groupIdentity = pushSetting.groupIdentity {
                    let mediatorSyncableGroup = MediatorSyncableGroup(
                        userSettings: userSettings,
                        pushSettingManager: self,
                        taskManager: taskManager,
                        groupManager: groupManager
                    )
                    var pushSetting = pushSetting
                    await mediatorSyncableGroup.updateNotificationTrigger(
                        identity: groupIdentity,
                        type: pushSetting.type,
                        expiresAt: pushSetting.periodOffTillDate,
                        mentioned: pushSetting.mentioned
                    )
                    await mediatorSyncableGroup.sync(syncAction: .update)
                }
            }

            NotificationCenter.default.post(
                name: NSNotification.Name(rawValue: kNotificationChangedPushSetting),
                object: pushSetting,
                userInfo: nil
            )
        }
        catch {
            DDLogError("Saving of push settings failed: \(error)")
        }
    }

    public func delete(forContact identity: ThreemaIdentity) async {
        do {
            var pushSettings = try decode()
            if !pushSettings.filter({ $0.identity == identity }).isEmpty {
                pushSettings.removeAll { item in
                    item.identity == identity
                }
                try encode(pushSettings)
            }
        }
        catch {
            DDLogError("Deleting of push settings failed: \(error)")
        }
    }

    /// Should we show a notification for this base message?
    public nonisolated func canSendPush(for message: BaseMessageEntity) -> Bool {
        entityManager.performAndWait { [weak self] in
            guard let self, !message.isOwnMessage else {
                return false
            }

            if message.isGroupMessage {
                guard let group = groupManager.getGroup(conversation: message.conversation) else {
                    return false
                }

                var pushSetting = find(forGroup: group.groupIdentity)
                if pushSetting.type == .offPeriod || pushSetting.type == .off {
                    if pushSetting.mentioned {
                        if !markupParser.isMeOrAllMention(in: message.contentToCheckForMentions() ?? "") {
                            return false
                        }
                    }
                    else {
                        return false
                    }
                }
            }
            else {
                if let sender = message.sender ?? message.conversation.contact {
                    var pushSetting = find(forContact: ThreemaIdentity(sender.identity))
                    return !(pushSetting.type == .offPeriod || pushSetting.type == .off)
                }
            }

            return true
        }
    }

    public nonisolated func canMasterDndSendPush() -> Bool {
        if isWorkApp {
            if userSettings.enableMasterDnd {
                let calendar = Calendar.current
                let currentDate = Date()
                let currentWeekDay = calendar.component(.weekday, from: currentDate)

                if let selectedWorkingDays = userSettings.masterDndWorkingDays,
                   selectedWorkingDays.contains(currentWeekDay) {

                    let currentTime = TimeOfDay(
                        hour: calendar.component(.hour, from: currentDate),
                        minute: calendar.component(.minute, from: currentDate)
                    )
                    let startTime = timeOfDayFromTimeString(timeString: userSettings.masterDndStartTime)
                    let endTime = timeOfDayFromTimeString(timeString: userSettings.masterDndEndTime)

                    if currentTime >= startTime, currentTime <= endTime {
                        return true
                    }
                }
                return false
            }
        }

        return true
    }

    // MARK: private functions

    private nonisolated func timeOfDayFromTimeString(timeString: String) -> TimeOfDay {
        let components: [String] = timeString.components(separatedBy: ":")
        return TimeOfDay(hour: Int(components[0])!, minute: Int(components[1])!)
    }

    private nonisolated func decode() throws -> [PushSetting] {
        let decoder = JSONDecoder()

        return try userSettings.pushSettings.map { item in
            guard let data = item as? Data else {
                throw PushSettingManagerError.decodingFailed
            }

            return try decoder.decode(PushSetting.self, from: data)
        }
    }

    private func encode(_ pushSettings: [PushSetting]) throws {
        let encoder = JSONEncoder()
        
        // TODO: (IOS-5620) Replace with injected encoder
        // Get constant ordering for tests
        #if DEBUG
            encoder.outputFormatting = [.sortedKeys]
        #endif

        let items = try pushSettings.map { item in
            try encoder.encode(item)
        }
        userSettings.pushSettings = items
    }
}

Messung
CHZG
83928786

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104856
#Domains=417288