mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-04-24 00:25:58 +02:00
171 lines
5.8 KiB
Swift
171 lines
5.8 KiB
Swift
import Foundation
|
|
|
|
/// GhostModeManager - Central manager for Ghost Mode privacy settings
|
|
/// Controls all privacy features: hide read receipts, typing indicator, online status, story views
|
|
public final class GhostModeManager {
|
|
|
|
// MARK: - Singleton
|
|
|
|
public static let shared = GhostModeManager()
|
|
|
|
// MARK: - UserDefaults Keys
|
|
|
|
private enum Keys {
|
|
static let isEnabled = "GhostMode.isEnabled"
|
|
static let hideReadReceipts = "GhostMode.hideReadReceipts"
|
|
static let hideStoryViews = "GhostMode.hideStoryViews"
|
|
static let hideOnlineStatus = "GhostMode.hideOnlineStatus"
|
|
static let hideTypingIndicator = "GhostMode.hideTypingIndicator"
|
|
static let forceOffline = "GhostMode.forceOffline"
|
|
}
|
|
|
|
// MARK: - Settings Storage
|
|
|
|
private let defaults = UserDefaults.standard
|
|
|
|
// MARK: - Properties
|
|
|
|
/// Master toggle for Ghost Mode.
|
|
/// Enabling Ghost Mode automatically disables Always Online in MiscSettingsManager.
|
|
public var isEnabled: Bool {
|
|
get { defaults.bool(forKey: Keys.isEnabled) }
|
|
set {
|
|
defaults.set(newValue, forKey: Keys.isEnabled)
|
|
if newValue {
|
|
// Ghost Mode ON → disable Always Online so they don't coexist in UI
|
|
MiscSettingsManager.shared.disableAlwaysOnlineForMutualExclusion()
|
|
}
|
|
notifySettingsChanged()
|
|
}
|
|
}
|
|
|
|
/// Don't send read receipts (blue checkmarks)
|
|
public var hideReadReceipts: Bool {
|
|
get { defaults.bool(forKey: Keys.hideReadReceipts) }
|
|
set {
|
|
defaults.set(newValue, forKey: Keys.hideReadReceipts)
|
|
notifySettingsChanged()
|
|
}
|
|
}
|
|
|
|
/// Don't send story view notifications
|
|
public var hideStoryViews: Bool {
|
|
get { defaults.bool(forKey: Keys.hideStoryViews) }
|
|
set {
|
|
defaults.set(newValue, forKey: Keys.hideStoryViews)
|
|
notifySettingsChanged()
|
|
}
|
|
}
|
|
|
|
/// Don't send online status
|
|
public var hideOnlineStatus: Bool {
|
|
get { defaults.bool(forKey: Keys.hideOnlineStatus) }
|
|
set {
|
|
defaults.set(newValue, forKey: Keys.hideOnlineStatus)
|
|
notifySettingsChanged()
|
|
}
|
|
}
|
|
|
|
/// Don't send typing indicator
|
|
public var hideTypingIndicator: Bool {
|
|
get { defaults.bool(forKey: Keys.hideTypingIndicator) }
|
|
set {
|
|
defaults.set(newValue, forKey: Keys.hideTypingIndicator)
|
|
notifySettingsChanged()
|
|
}
|
|
}
|
|
|
|
/// Always appear as offline
|
|
public var forceOffline: Bool {
|
|
get { defaults.bool(forKey: Keys.forceOffline) }
|
|
set {
|
|
defaults.set(newValue, forKey: Keys.forceOffline)
|
|
notifySettingsChanged()
|
|
}
|
|
}
|
|
|
|
// MARK: - Computed Properties
|
|
|
|
/// Returns true only when Ghost Mode is enabled AND the individual toggle is on.
|
|
/// NOTE: Always Online takes precedence — if Always Online is active, online status is never hidden.
|
|
public var shouldHideReadReceipts: Bool {
|
|
return isEnabled && hideReadReceipts
|
|
}
|
|
|
|
public var shouldHideStoryViews: Bool {
|
|
return isEnabled && hideStoryViews
|
|
}
|
|
|
|
/// Online status is hidden only when Ghost Mode is on AND Always Online is NOT active.
|
|
/// Checks alwaysOnline raw value (not shouldAlwaysBeOnline) so ghost mode works
|
|
/// even when the Misc master toggle is off.
|
|
public var shouldHideOnlineStatus: Bool {
|
|
guard isEnabled && hideOnlineStatus else { return false }
|
|
return !MiscSettingsManager.shared.alwaysOnline
|
|
}
|
|
|
|
public var shouldHideTypingIndicator: Bool {
|
|
return isEnabled && hideTypingIndicator
|
|
}
|
|
|
|
/// Force offline only when Ghost Mode is on AND Always Online is NOT active.
|
|
public var shouldForceOffline: Bool {
|
|
guard isEnabled && forceOffline else { return false }
|
|
return !MiscSettingsManager.shared.alwaysOnline
|
|
}
|
|
|
|
/// Count of active features (e.g., "5/5")
|
|
public var activeFeatureCount: Int {
|
|
var count = 0
|
|
if hideReadReceipts { count += 1 }
|
|
if hideStoryViews { count += 1 }
|
|
if hideOnlineStatus { count += 1 }
|
|
if hideTypingIndicator { count += 1 }
|
|
if forceOffline { count += 1 }
|
|
return count
|
|
}
|
|
|
|
/// Total number of features
|
|
public static let totalFeatureCount = 5
|
|
|
|
// MARK: - Initialization
|
|
|
|
private init() {
|
|
if !defaults.bool(forKey: "GhostMode.initialized") {
|
|
defaults.set(true, forKey: "GhostMode.initialized")
|
|
defaults.set(true, forKey: Keys.hideReadReceipts)
|
|
defaults.set(true, forKey: Keys.hideStoryViews)
|
|
defaults.set(true, forKey: Keys.hideOnlineStatus)
|
|
defaults.set(true, forKey: Keys.hideTypingIndicator)
|
|
defaults.set(true, forKey: Keys.forceOffline)
|
|
defaults.set(false, forKey: Keys.isEnabled)
|
|
}
|
|
}
|
|
|
|
// MARK: - Enable/Disable All
|
|
|
|
/// Enable all ghost mode features.
|
|
/// Also disables Always Online (mutual exclusion).
|
|
public func enableAll() {
|
|
hideReadReceipts = true
|
|
hideStoryViews = true
|
|
hideOnlineStatus = true
|
|
hideTypingIndicator = true
|
|
forceOffline = true
|
|
isEnabled = true // setter handles mutual exclusion
|
|
}
|
|
|
|
/// Disable all ghost mode features
|
|
public func disableAll() {
|
|
isEnabled = false
|
|
}
|
|
|
|
// MARK: - Notifications
|
|
|
|
public static let settingsChangedNotification = Notification.Name("GhostModeSettingsChanged")
|
|
|
|
private func notifySettingsChanged() {
|
|
NotificationCenter.default.post(name: GhostModeManager.settingsChangedNotification, object: nil)
|
|
}
|
|
}
|