Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Threema/ThreemaFramework/Notification/   (Social Medium ©)  Datei vom 26.9.2026 mit Größe 9 kB image not shown  

Quelle  PushSetting.swift   Sprache: JAVA

 

import Foundation
import ThreemaEssentials
import ThreemaMacros

public struct PushSetting: Codable, Sendable {
    private enum CodingKeys: String, CodingKey {
        case identity, groupIdentity, _type, muted, mentioned, periodOffTillDate
    }

    public enum PushSettingType: Int, Codable, Sendable {
        /// Notifications are on (i.e. DND is off)
        case on = 0
        /// Notifications are disabled indefinitely (i.e. DND is on)
        case off = 1
        /// Notifications are disabled for a certain period
        case offPeriod = 2
    }

    /// Set of possible off-periods
    ///
    /// Identical on all platforms supported by Threema.
    public enum PeriodOffTime: Int, CaseIterable, Codable, Equatable {
        case time1Hour = 0
        case time2Hours = 1
        case time3Hours = 2
        case time4Hours = 3
        case time8Hours = 4
        case time1Day = 5
        case time1Week = 6

        public var localizedString: String {
            switch self {
            case .time1Hour:
                #localize("doNotDisturb_onPeriod_1Hour")
            case .time2Hours:
                #localize("doNotDisturb_onPeriod_2Hours")
            case .time3Hours:
                #localize("doNotDisturb_onPeriod_3Hours")
            case .time4Hours:
                #localize("doNotDisturb_onPeriod_4Hours")
            case .time8Hours:
                #localize("doNotDisturb_onPeriod_8Hours")
            case .time1Day:
                #localize("doNotDisturb_onPeriod_1Day")
            case .time1Week:
                #localize("doNotDisturb_onPeriod_1Week")
            }
        }
    }

    init(identity: ThreemaIdentity) {
        self.init(identity: identity, groupIdentity: nil)
    }

    init(groupIdentity: GroupIdentity) {
        self.init(identity: nil, groupIdentity: groupIdentity)
    }

    init(
        identity: ThreemaIdentity?,
        groupIdentity: GroupIdentity?,
        _type: PushSettingType = .on,
        periodOffTillDate: Date? = nil,
        muted: Bool = false,
        mentioned: Bool = false
    ) {
        self.identity = identity
        self.groupIdentity = groupIdentity
        self._type = _type
        self.periodOffTillDate = periodOffTillDate
        self.muted = muted
        self.mentioned = mentioned
    }

    public private(set) var identity: ThreemaIdentity?

    public private(set) var groupIdentity: GroupIdentity?

    private var _type: PushSettingType

    /// "State" of this setting
    ///
    /// If it is `PushSettingType.offPeriod`, but `periodOffTillDate` is `nil` or in the past it will automatically
    /// reset to `PushSettingType.on` on reading.
    ///
    /// When setting this to `PushSettingType.offPeriod` always set `setPeriodOffTime` before reading this value.
    /// (Otherwise it will reset to `PushSettingType.on`.)
    public var type: PushSettingType {
        mutating get {
            updatePeriodOffTillDateIsExpired()

            return _type
        }

        mutating set {
            _type = newValue
        }
    }

    /// Period of off-time
    ///
    /// When set automatically sets `periodOffTillDate` to the date in the future with this period.
    /// - Parameter duration: Duration who long notifying is off
    public mutating func setPeriodOffTime(_ duration: PeriodOffTime) {
        // Automatically set expiration date
        switch duration {
        case .time1Hour:
            periodOffTillDate = Calendar.current.date(byAdding: .hour, value: 1, to: Date())
        case .time2Hours:
            periodOffTillDate = Calendar.current.date(byAdding: .hour, value: 2, to: Date())
        case .time3Hours:
            periodOffTillDate = Calendar.current.date(byAdding: .hour, value: 3, to: Date())
        case .time4Hours:
            periodOffTillDate = Calendar.current.date(byAdding: .hour, value: 4, to: Date())
        case .time8Hours:
            periodOffTillDate = Calendar.current.date(byAdding: .hour, value: 8, to: Date())
        case .time1Day:
            periodOffTillDate = Calendar.current.date(byAdding: .day, value: 1, to: Date())
        case .time1Week:
            periodOffTillDate = Calendar.current.date(byAdding: .day, value: 7, to: Date())
        }
    }

    /// When does the current off-period end?
    public var periodOffTillDate: Date? = nil

    /// Housekeeping: Ensure that `type` is only `PushSettingType.offPeriod` if a `periodOffTillDate`
    /// is set and it is in the future
    ///
    /// - Returns: True when `PushSetting` has changed
    @discardableResult mutating func updatePeriodOffTillDateIsExpired() -> Bool {
        if _type == .offPeriod {
            if periodOffTillDate == nil {
                _type = .on

                return true
            }
            // This should be the only needed date comparison in all of this struct
            else if periodOffTillDate?.compare(.now) == .orderedAscending {
                _type = .on
                periodOffTillDate = nil

                return true
            }
        }

        return false
    }

    /// Update `periodOffTillDate`
    ///
    /// - Parameter date: Date is till date or `nil` for `on` and `off`
    mutating func updatePeriodOffTillDate(_ date: Date?) {
        periodOffTillDate = date
    }

    /// Should a notification sound be played?
    public var muted: Bool

    /// Should notifications always be shown if I mentioned?
    public var mentioned: Bool

    /// Localized description of current state to show in UI
    public var localizedDescription: String {
        let formatString = #localize("doNotDisturb_on_until_date_and_time")

        return localizedDescription(offPeriodFormatString: formatString)
    }

    /// Longer localized description of current state to show in UI
    public var localizedLongDescription: String {
        let formatString = #localize("doNotDisturb_on_until_date_and_time_long")

        return localizedDescription(offPeriodFormatString: formatString)
    }

    /// Helper for the previous two getters
    /// This method should always be internal and a caller has to ensure that `offPeriodFormatString` is
    /// not controllable by the user or any remote user, because it is a format string.
    private func localizedDescription(offPeriodFormatString: String) -> String {
        var pushSetting = self
        switch pushSetting.type {
        case .offPeriod:
            if let periodOffTillDate {
                let formattedDateAndTime = DateFormatter.relativeLongStyleDateShortStyleTime(periodOffTillDate)
                return String(format: offPeriodFormatString, formattedDateAndTime)
            }
            else {
                return ""
            }
        case .off:
            return #localize("doNotDisturb_on")
        case .on:
            return #localize("doNotDisturb_off")
        }
    }

    /// SF Symbol name for current push setting
    public var sfSymbolNameForPushSetting: String {
        guard let sfSymbolName = sfSymbolNameForEditedPushSetting else {
            return "bell.fill"
        }
        return sfSymbolName
    }

    /// SF Symbol name for current push setting if setting is not set to the defaults
    var sfSymbolNameForEditedPushSetting: String? {
        var sfSymbolName: String? = nil

        var pushSetting = self
        if !mentioned, pushSetting.type == .offPeriod || pushSetting.type == .off {
            sfSymbolName = "minus.circle.fill"
        }
        else if mentioned, pushSetting.type == .offPeriod || pushSetting.type == .off {
            sfSymbolName = "at.circle.fill"
        }
        else if muted, pushSetting.type == .on {
            sfSymbolName = "bell.slash.fill"
        }

        return sfSymbolName
    }

    /// Should we show a notification for this GroupCallStartMessage message?
    func canSendPushGroupCallStartMessage(for message: AbstractMessage?) -> Bool {
        var pushSetting = self
        if pushSetting.type == .offPeriod || pushSetting.type == .off {
            if !mentioned, message is GroupCallStartMessage {
                return false
            }
        }
        return true
    }

    /// Should a notification be shown according to this setting?
    public func canSendPush() -> Bool {
        var pushSetting = self
        if pushSetting.type == .offPeriod || pushSetting.type == .off {
            return false
        }
        return true
    }

    /// Icon to represent the current setting
    func imageForPushSetting() -> UIImage? {
        guard let pushSettingIcon = imageForEditedPushSetting() else {
            return UIImage(named: "bell.fill")
        }
        return pushSettingIcon
    }

    /// Icon to display if setting is not set to the defaults
    public func imageForEditedPushSetting(with config: UIImage.Configuration? = nil) -> UIImage? {
        var pushSettingIcon: UIImage? = nil

        var pushSetting = self
        if !mentioned, pushSetting.type == .offPeriod || pushSetting.type == .off {
            pushSettingIcon = UIImage(systemName: "minus.circle.fill", withConfiguration: config)
        }
        else if mentioned, pushSetting.type == .offPeriod || pushSetting.type == .off {
            pushSettingIcon = UIImage(systemName: "at.circle.fill", withConfiguration: config)
        }
        else if pushSetting.type == .on, muted {
            pushSettingIcon = UIImage(systemName: "bell.slash.circle.fill", withConfiguration: config)
        }

        return pushSettingIcon
    }
}

Messung
CHZG
829810093

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© 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.