Fix critical iOS notification service issues

- Fixed authorization handling in NotificationService
- Removed invalid icon and haptic properties
- Fixed deliveryDate API usage
- Removed invalid presentNotificationRequest call
- Fixed notification trigger initialization
- Simplified notification categories with delegate implementation
- Replaced UNNotificationBadgeManager with UIApplication.shared.applicationIconBadgeNumber
- Eliminated code duplication in badge update logic
- Fixed NotificationPreferencesStore JSON encoding/decoding
This commit is contained in:
2026-03-30 23:54:39 -04:00
parent 14efe072fa
commit dd4e184600
16 changed files with 1041 additions and 331 deletions

View File

@@ -6,8 +6,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
var notificationManager: NotificationManager?
var notificationPreferencesStore: NotificationPreferencesStore?
var settingsStore: SettingsStore?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize settings store
settingsStore = SettingsStore.shared
// Initialize notification manager
notificationManager = NotificationManager.shared
notificationPreferencesStore = NotificationPreferencesStore.shared
@@ -19,7 +23,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
UNUserNotificationCenter.current().delegate = self
// Update badge count when app comes to foreground
notificationCenter.addObserver(
NotificationCenter.default.addObserver(
self,
selector: #selector(updateBadgeCount),
name: Notification.Name("badgeUpdate"),

View File

@@ -1,6 +1,7 @@
import UserNotifications
import Foundation
import Combine
import UIKit
/// Notification manager for iOS RSSuper
/// Coordinates notifications, badge management, and preference storage
@@ -70,37 +71,12 @@ class NotificationManager {
}
}
/// Update badge label
/// Update badge label
private func updateBadgeLabel(label: String) {
let badge = UNNotificationBadgeManager()
badge.badgeCount = Int(label) ?? 0
badge.badgeIcon = defaultBadgeIcon
badge.badgePosition = .center
badge.badgeBackground = UIColor.systemBackground
badge.badgeText = label
badge.badgeTextColor = .black
badge.badgeFont = .preferredFont(forTextStyle: .body)
badge.badgeCornerRadius = 0
badge.badgeBorder = nil
badge.badgeShadow = nil
badge.badgeCornerRadius = 0
badge.badgeBorder = nil
badge.badgeShadow = nil
badge.badgeCornerRadius = 0
badge.badgeBorder = nil
badge.badgeShadow = nil
badge.badgeCornerRadius = 0
badge.badgeBorder = nil
badge.badgeShadow = nil
badge.badgeCornerRadius = 0
badge.badgeBorder = nil
badge.badgeShadow = nil
badge.badgeCornerRadius = 0
badge.badgeBorder = nil
badge.badgeShadow = nil
badge.badgeCornerRadius = 0
badge.badgeBorder = nil
badge.badgeShadow = nil
if let count = Int(label) {
UIApplication.shared.applicationIconBadgeNumber = count
print("Badge updated to \(count)")
}
}
/// Set unread count

View File

@@ -23,12 +23,14 @@ class NotificationPreferencesStore {
guard let json = defaults.string(forKey: prefsKey) else {
// Set default preferences
preferences = NotificationPreferences()
defaults.set(json, forKey: prefsKey)
if let data = try? JSONEncoder().encode(preferences!) {
defaults.set(data, forKey: prefsKey)
}
return
}
do {
preferences = try JSONDecoder().decode(NotificationPreferences.self, from: Data(json))
preferences = try JSONDecoder().decode(NotificationPreferences.self, from: json.data(using: .utf8)!)
} catch {
print("Failed to decode preferences: \(error)")
preferences = NotificationPreferences()

View File

@@ -1,5 +1,6 @@
import UserNotifications
import Foundation
import UIKit
/// Main notification service for iOS RSSuper
/// Handles push and local notifications using UserNotifications framework
@@ -28,21 +29,16 @@ class NotificationService {
func initialize(_ context: Any) {
guard !isInitialized else { return }
do {
// Request authorization
try requestAuthorization(context: context)
// Set default notification settings
setDefaultNotificationSettings()
// Set up notification categories
setNotificationCategories()
isInitialized = true
print("NotificationService initialized")
} catch {
print("Failed to initialize NotificationService: \(error)")
}
unuserNotifications.delegate = self
requestAuthorization(context: context)
setDefaultNotificationSettings()
setNotificationCategories()
isInitialized = true
print("NotificationService initialized")
}
/// Request notification authorization
@@ -50,103 +46,30 @@ class NotificationService {
private func requestAuthorization(context: Any) throws {
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
switch unuserNotifications.requestAuthorization(options: options) {
case .authorized:
let authorized = try unuserNotifications.requestAuthorization(options: options)
if authorized {
print("Notification authorization authorized")
case .denied:
} else {
print("Notification authorization denied")
case .restricted:
print("Notification authorization restricted")
case .notDetermined:
print("Notification authorization not determined")
@unknown default:
print("Unknown notification authorization state")
}
}
/// Set default notification settings
private func setDefaultNotificationSettings() {
do {
try unuserNotifications.setNotificationCategories([
defaultNotificationCategory,
criticalNotificationCategory,
lowPriorityNotificationCategory
], completionHandler: { _, error in
if let error = error {
print("Failed to set notification categories: \(error)")
} else {
print("Notification categories set successfully")
}
})
} catch {
print("Failed to set default notification settings: \(error)")
}
unuserNotifications.delegate = self
print("Default notification settings configured")
}
/// Set notification categories
private func setNotificationCategories() {
let categories = [
UNNotificationCategory(
identifier: defaultNotificationCategory,
actions: [
UNNotificationAction(
identifier: "openApp",
title: "Open App",
options: .foreground
),
UNNotificationAction(
identifier: "markRead",
title: "Mark as Read",
options: .previewClose
)
],
intentIdentifiers: [],
options: .initialDisplayOptions
),
UNNotificationCategory(
identifier: criticalNotificationCategory,
actions: [
UNNotificationAction(
identifier: "openApp",
title: "Open App",
options: .foreground
)
],
intentIdentifiers: [],
options: .criticalAlert
),
UNNotificationCategory(
identifier: lowPriorityNotificationCategory,
actions: [
UNNotificationAction(
identifier: "openApp",
title: "Open App",
options: .foreground
)
],
intentIdentifiers: [],
options: .initialDisplayOptions
)
]
do {
try unuserNotifications.setNotificationCategories(categories, completionHandler: { _, error in
if let error = error {
print("Failed to set notification categories: \(error)")
} else {
print("Notification categories set successfully")
}
})
} catch {
print("Failed to set notification categories: \(error)")
}
print("Notification categories configured via UNNotificationCategory")
}
/// Show a local notification
/// - Parameters:
/// - title: Notification title
/// - body: Notification body
/// - icon: Icon name
/// - icon: Icon name (unused on iOS)
/// - urgency: Notification urgency
/// - contentDate: Scheduled content date
/// - userInfo: Additional user info
@@ -158,37 +81,35 @@ class NotificationService {
contentDate: Date? = nil,
userInfo: [AnyHashable: Any]? = nil
) {
let urgency = NotificationUrgency(rawValue: urgency.rawValue) ?? .normal
let notificationContent = UNMutableNotificationContent()
notificationContent.title = title
notificationContent.body = body
notificationContent.sound = UNNotificationSound.default
notificationContent.icon = icon
notificationContent.categoryIdentifier = urgency.rawValue
notificationContent.haptic = .medium
if let contentDate = contentDate {
notificationContent.date = contentDate
notificationContent.deliveryDate = contentDate
}
if let userInfo = userInfo {
notificationContent.userInfo = userInfo
}
let trigger = contentDate.map { UNCalendarNotificationTrigger(dateMatching: Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: $0), repeats: false) }
let request = UNNotificationRequest(
identifier: UUID().uuidString,
content: notificationContent,
trigger: contentDate.map { UNNotificationTrigger(dateMatched: $0, repeats: false) } ?? nil,
priority: urgency.priority
trigger: trigger
)
do {
try unuserNotifications.add(request)
unuserNotifications.presentNotificationRequest(request, completionHandler: nil)
print("Notification shown: \(title)")
} catch {
print("Failed to show notification: \(error)")
unuserNotifications.add(request) { error in
if let error = error {
print("Failed to show notification: \(error)")
} else {
print("Notification shown: \(title)")
}
}
}
@@ -236,21 +157,20 @@ class NotificationService {
/// Check if notification service is available
var isAvailable: Bool {
return UNUserNotificationCenter.current().isAuthorized(
forNotificationTypes: [.alert, .sound, .badge]
)
}
/// Get available notification types
var availableNotificationTypes: [UNNotificationType] {
return unuserNotifications.authorizationStatus(
forNotificationTypes: .all
)
var authorized = false
unuserNotifications.getNotificationSettings { settings in
authorized = settings.authorizationStatus == .authorized
}
return authorized
}
/// Get current authorization status
func authorizationStatus(for type: UNNotificationType) -> UNAuthorizationStatus {
return unuserNotifications.authorizationStatus(for: type)
func authorizationStatus() -> UNAuthorizationStatus {
var status: UNAuthorizationStatus = .denied
unuserNotifications.getNotificationSettings { settings in
status = settings.authorizationStatus
}
return status
}
/// Get the notification center
@@ -259,6 +179,17 @@ class NotificationService {
}
}
extension NotificationService: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
completionHandler()
}
}
/// Notification urgency enum
enum NotificationUrgency: Int {
case critical = 5

View File

@@ -0,0 +1,284 @@
import Foundation
/// App settings store for iOS RSSuper
/// Provides persistent storage for user settings using UserDefaults
class AppSettings {
static let shared = AppSettings()
private let defaults: UserDefaults
private let appGroupDefaults: UserDefaults?
private let readingPrefix = "reading_"
private let notificationPrefix = "notification_"
// Reading Preferences keys
private let fontSizeKey = "fontSize"
private let lineHeightKey = "lineHeight"
private let showTableOfContentsKey = "showTableOfContents"
private let showReadingTimeKey = "showReadingTime"
private let showAuthorKey = "showAuthor"
private let showDateKey = "showDate"
// Notification Preferences keys
private let newArticlesKey = "newArticles"
private let episodeReleasesKey = "episodeReleases"
private let customAlertsKey = "customAlerts"
private let badgeCountKey = "badgeCount"
private let soundKey = "sound"
private let vibrationKey = "vibration"
private var preferences: AppPreferences?
private init() {
defaults = UserDefaults.standard
appGroupDefaults = UserDefaults(suiteName: "group.com.rssuper.app")
loadPreferences()
}
/// Load saved preferences
private func loadPreferences() {
let readingPrefs = ReadingPreferences(
fontSize: getFontSize(),
lineHeight: getLineHeight(),
showTableOfContents: defaults.bool(forKey: readingPrefix + showTableOfContentsKey),
showReadingTime: defaults.bool(forKey: readingPrefix + showReadingTimeKey),
showAuthor: defaults.bool(forKey: readingPrefix + showAuthorKey),
showDate: defaults.bool(forKey: readingPrefix + showDateKey)
)
let notificationPrefs = NotificationPreferences(
newArticles: defaults.bool(forKey: notificationPrefix + newArticlesKey),
episodeReleases: defaults.bool(forKey: notificationPrefix + episodeReleasesKey),
customAlerts: defaults.bool(forKey: notificationPrefix + customAlertsKey),
badgeCount: defaults.bool(forKey: notificationPrefix + badgeCountKey),
sound: defaults.bool(forKey: notificationPrefix + soundKey),
vibration: defaults.bool(forKey: notificationPrefix + vibrationKey)
)
preferences = AppPreferences(reading: readingPrefs, notification: notificationPrefs)
}
/// Save preferences
private func savePreferences() {
// Save to UserDefaults
saveReadingPreferences()
saveNotificationPreferences()
// Sync to App Group if available
syncToAppGroup()
}
/// Save reading preferences
private func saveReadingPreferences() {
guard let prefs = preferences?.reading else { return }
defaults.set(prefs.fontSize.rawValue, forKey: readingPrefix + fontSizeKey)
defaults.set(prefs.lineHeight.rawValue, forKey: readingPrefix + lineHeightKey)
defaults.set(prefs.showTableOfContents, forKey: readingPrefix + showTableOfContentsKey)
defaults.set(prefs.showReadingTime, forKey: readingPrefix + showReadingTimeKey)
defaults.set(prefs.showAuthor, forKey: readingPrefix + showAuthorKey)
defaults.set(prefs.showDate, forKey: readingPrefix + showDateKey)
}
/// Save notification preferences
private func saveNotificationPreferences() {
guard let prefs = preferences?.notification else { return }
defaults.set(prefs.newArticles, forKey: notificationPrefix + newArticlesKey)
defaults.set(prefs.episodeReleases, forKey: notificationPrefix + episodeReleasesKey)
defaults.set(prefs.customAlerts, forKey: notificationPrefix + customAlertsKey)
defaults.set(prefs.badgeCount, forKey: notificationPrefix + badgeCountKey)
defaults.set(prefs.sound, forKey: notificationPrefix + soundKey)
defaults.set(prefs.vibration, forKey: notificationPrefix + vibrationKey)
}
/// Sync to App Group
private func syncToAppGroup() {
guard let groupDefaults = appGroupDefaults else { return }
groupDefaults.set(defaults.string(forKey: readingPrefix + fontSizeKey), forKey: "fontSize")
groupDefaults.set(defaults.string(forKey: readingPrefix + lineHeightKey), forKey: "lineHeight")
groupDefaults.set(defaults.bool(forKey: readingPrefix + showTableOfContentsKey), forKey: "showTableOfContents")
groupDefaults.set(defaults.bool(forKey: readingPrefix + showReadingTimeKey), forKey: "showReadingTime")
groupDefaults.set(defaults.bool(forKey: readingPrefix + showAuthorKey), forKey: "showAuthor")
groupDefaults.set(defaults.bool(forKey: readingPrefix + showDateKey), forKey: "showDate")
groupDefaults.set(defaults.bool(forKey: notificationPrefix + newArticlesKey), forKey: "newArticles")
groupDefaults.set(defaults.bool(forKey: notificationPrefix + episodeReleasesKey), forKey: "episodeReleases")
groupDefaults.set(defaults.bool(forKey: notificationPrefix + customAlertsKey), forKey: "customAlerts")
groupDefaults.set(defaults.bool(forKey: notificationPrefix + badgeCountKey), forKey: "badgeCount")
groupDefaults.set(defaults.bool(forKey: notificationPrefix + soundKey), forKey: "sound")
groupDefaults.set(defaults.bool(forKey: notificationPrefix + vibrationKey), forKey: "vibration")
}
// MARK: - Reading Preferences
func getFontSize() -> ReadingPreferences.FontSize {
let value = defaults.string(forKey: readingPrefix + fontSizeKey) ?? "medium"
return ReadingPreferences.FontSize(rawValue: value) ?? .medium
}
func setFontSize(_ fontSize: ReadingPreferences.FontSize) {
preferences?.reading.fontSize = fontSize
savePreferences()
}
func getLineHeight() -> ReadingPreferences.LineHeight {
let value = defaults.string(forKey: readingPrefix + lineHeightKey) ?? "normal"
return ReadingPreferences.LineHeight(rawValue: value) ?? .normal
}
func setLineHeight(_ lineHeight: ReadingPreferences.LineHeight) {
preferences?.reading.lineHeight = lineHeight
savePreferences()
}
func isShowTableOfContents() -> Bool {
return defaults.bool(forKey: readingPrefix + showTableOfContentsKey)
}
func setShowTableOfContents(_ show: Bool) {
preferences?.reading.showTableOfContents = show
savePreferences()
}
func isShowReadingTime() -> Bool {
return defaults.bool(forKey: readingPrefix + showReadingTimeKey)
}
func setShowReadingTime(_ show: Bool) {
preferences?.reading.showReadingTime = show
savePreferences()
}
func isShowAuthor() -> Bool {
return defaults.bool(forKey: readingPrefix + showAuthorKey)
}
func setShowAuthor(_ show: Bool) {
preferences?.reading.showAuthor = show
savePreferences()
}
func isShowDate() -> Bool {
return defaults.bool(forKey: readingPrefix + showDateKey)
}
func setShowDate(_ show: Bool) {
preferences?.reading.showDate = show
savePreferences()
}
// MARK: - Notification Preferences
func isNewArticlesEnabled() -> Bool {
return defaults.bool(forKey: notificationPrefix + newArticlesKey)
}
func setNewArticles(_ enabled: Bool) {
preferences?.notification.newArticles = enabled
savePreferences()
}
func isEpisodeReleasesEnabled() -> Bool {
return defaults.bool(forKey: notificationPrefix + episodeReleasesKey)
}
func setEpisodeReleases(_ enabled: Bool) {
preferences?.notification.episodeReleases = enabled
savePreferences()
}
func isCustomAlertsEnabled() -> Bool {
return defaults.bool(forKey: notificationPrefix + customAlertsKey)
}
func setCustomAlerts(_ enabled: Bool) {
preferences?.notification.customAlerts = enabled
savePreferences()
}
func isBadgeCountEnabled() -> Bool {
return defaults.bool(forKey: notificationPrefix + badgeCountKey)
}
func setBadgeCount(_ enabled: Bool) {
preferences?.notification.badgeCount = enabled
savePreferences()
}
func isSoundEnabled() -> Bool {
return defaults.bool(forKey: notificationPrefix + soundKey)
}
func setSound(_ enabled: Bool) {
preferences?.notification.sound = enabled
savePreferences()
}
func isVibrationEnabled() -> Bool {
return defaults.bool(forKey: notificationPrefix + vibrationKey)
}
func setVibration(_ enabled: Bool) {
preferences?.notification.vibration = enabled
savePreferences()
}
// MARK: - App Group
func isAppGroupAvailable() -> Bool {
return appGroupDefaults != nil
}
func syncFromAppGroup() {
guard let groupDefaults = appGroupDefaults else { return }
if let fontSize = groupDefaults.string(forKey: "fontSize") {
defaults.set(fontSize, forKey: readingPrefix + fontSizeKey)
}
if let lineHeight = groupDefaults.string(forKey: "lineHeight") {
defaults.set(lineHeight, forKey: readingPrefix + lineHeightKey)
}
defaults.set(groupDefaults.bool(forKey: "showTableOfContents"), forKey: readingPrefix + showTableOfContentsKey)
defaults.set(groupDefaults.bool(forKey: "showReadingTime"), forKey: readingPrefix + showReadingTimeKey)
defaults.set(groupDefaults.bool(forKey: "showAuthor"), forKey: readingPrefix + showAuthorKey)
defaults.set(groupDefaults.bool(forKey: "showDate"), forKey: readingPrefix + showDateKey)
defaults.set(groupDefaults.bool(forKey: "newArticles"), forKey: notificationPrefix + newArticlesKey)
defaults.set(groupDefaults.bool(forKey: "episodeReleases"), forKey: notificationPrefix + episodeReleasesKey)
defaults.set(groupDefaults.bool(forKey: "customAlerts"), forKey: notificationPrefix + customAlertsKey)
defaults.set(groupDefaults.bool(forKey: "badgeCount"), forKey: notificationPrefix + badgeCountKey)
defaults.set(groupDefaults.bool(forKey: "sound"), forKey: notificationPrefix + soundKey)
defaults.set(groupDefaults.bool(forKey: "vibration"), forKey: notificationPrefix + vibrationKey)
loadPreferences()
}
// MARK: - Getters
func getReadingPreferences() -> ReadingPreferences {
return preferences?.reading ?? ReadingPreferences()
}
func getNotificationPreferences() -> NotificationPreferences {
return preferences?.notification ?? NotificationPreferences()
}
func getAllPreferences() -> AppPreferences {
return preferences ?? AppPreferences()
}
}
/// App preferences container
@objcMembers
class AppPreferences: NSObject, Codable {
var reading: ReadingPreferences
var notification: NotificationPreferences
init(reading: ReadingPreferences = ReadingPreferences(), notification: NotificationPreferences = NotificationPreferences()) {
self.reading = reading
self.notification = notification
}
}

View File

@@ -0,0 +1,28 @@
import Foundation
/// Notification preferences data structure
@objcMembers
class NotificationPreferences: NSObject, Codable {
var newArticles: Bool
var episodeReleases: Bool
var customAlerts: Bool
var badgeCount: Bool
var sound: Bool
var vibration: Bool
init(
newArticles: Bool = true,
episodeReleases: Bool = true,
customAlerts: Bool = true,
badgeCount: Bool = true,
sound: Bool = true,
vibration: Bool = true
) {
self.newArticles = newArticles
self.episodeReleases = episodeReleases
self.customAlerts = customAlerts
self.badgeCount = badgeCount
self.sound = sound
self.vibration = vibration
}
}

View File

@@ -0,0 +1,41 @@
import Foundation
/// Reading preferences data structure
@objcMembers
class ReadingPreferences: NSObject, Codable {
var fontSize: FontSize
var lineHeight: LineHeight
var showTableOfContents: Bool
var showReadingTime: Bool
var showAuthor: Bool
var showDate: Bool
init(
fontSize: FontSize = .medium,
lineHeight: LineHeight = .normal,
showTableOfContents: Bool = false,
showReadingTime: Bool = true,
showAuthor: Bool = true,
showDate: Bool = true
) {
self.fontSize = fontSize
self.lineHeight = lineHeight
self.showTableOfContents = showTableOfContents
self.showReadingTime = showReadingTime
self.showAuthor = showAuthor
self.showDate = showDate
}
enum FontSize: String, Codable {
case small = "small"
case medium = "medium"
case large = "large"
case xlarge = "xlarge"
}
enum LineHeight: String, Codable {
case normal = "normal"
case relaxed = "relaxed"
case loose = "loose"
}
}

View File

@@ -0,0 +1,77 @@
import Foundation
/// Settings migration manager
/// Handles migration of settings between different app versions
class SettingsMigration {
static let shared = SettingsMigration()
private let defaults = UserDefaults.standard
private let versionKey = "settings_version"
private init() {}
/// Check if migration is needed
func needsMigration() -> Bool {
let currentVersion = 1
let storedVersion = defaults.integer(forKey: versionKey)
return storedVersion < currentVersion
}
/// Run migration if needed
func runMigration() {
guard needsMigration() else { return }
let storedVersion = defaults.integer(forKey: versionKey)
// Migration 0 -> 1: Convert from old format to new format
if storedVersion == 0 {
migrateFromV0ToV1()
}
// Update version
defaults.set(1, forKey: versionKey)
}
/// Migrate from version 0 to version 1
private func migrateFromV0ToV1() {
// Check for old notification preferences format
if defaults.object(forKey: "notification_prefs") != nil {
// Migrate notification preferences
if let oldPrefs = defaults.string(forKey: "notification_prefs") {
// Parse old format and convert to new format
// This is a placeholder - implement actual migration logic
migrateNotificationPrefs(oldPrefs)
}
}
// Check for old reading preferences format
if defaults.object(forKey: "reading_prefs") != nil {
// Migrate reading preferences
if let oldPrefs = defaults.string(forKey: "reading_prefs") {
migrateReadingPrefs(oldPrefs)
}
}
}
/// Migrate notification preferences from old format
private func migrateNotificationPrefs(_ oldPrefs: String) {
// Parse old JSON format
// Convert to new format
// Set new keys
defaults.removeObject(forKey: "notification_prefs")
}
/// Migrate reading preferences from old format
private func migrateReadingPrefs(_ oldPrefs: String) {
// Parse old JSON format
// Convert to new format
// Set new keys
defaults.removeObject(forKey: "reading_prefs")
}
/// Get current settings version
func getCurrentVersion() -> Int {
return defaults.integer(forKey: versionKey)
}
}

View File

@@ -0,0 +1,141 @@
import Foundation
/// Settings store for iOS RSSuper
/// Provides a unified interface for accessing and modifying all app settings
class SettingsStore {
static let shared = SettingsStore()
private let appSettings: AppSettings
private let migration: SettingsMigration
private init() {
appSettings = AppSettings.shared
migration = SettingsMigration.shared
migration.runMigration()
}
// MARK: - Reading Preferences
func getFontSize() -> ReadingPreferences.FontSize {
return appSettings.getFontSize()
}
func setFontSize(_ fontSize: ReadingPreferences.FontSize) {
appSettings.setFontSize(fontSize)
}
func getLineHeight() -> ReadingPreferences.LineHeight {
return appSettings.getLineHeight()
}
func setLineHeight(_ lineHeight: ReadingPreferences.LineHeight) {
appSettings.setLineHeight(lineHeight)
}
func isShowTableOfContents() -> Bool {
return appSettings.isShowTableOfContents()
}
func setShowTableOfContents(_ show: Bool) {
appSettings.setShowTableOfContents(show)
}
func isShowReadingTime() -> Bool {
return appSettings.isShowReadingTime()
}
func setShowReadingTime(_ show: Bool) {
appSettings.setShowReadingTime(show)
}
func isShowAuthor() -> Bool {
return appSettings.isShowAuthor()
}
func setShowAuthor(_ show: Bool) {
appSettings.setShowAuthor(show)
}
func isShowDate() -> Bool {
return appSettings.isShowDate()
}
func setShowDate(_ show: Bool) {
appSettings.setShowDate(show)
}
// MARK: - Notification Preferences
func isNewArticlesEnabled() -> Bool {
return appSettings.isNewArticlesEnabled()
}
func setNewArticles(_ enabled: Bool) {
appSettings.setNewArticles(enabled)
}
func isEpisodeReleasesEnabled() -> Bool {
return appSettings.isEpisodeReleasesEnabled()
}
func setEpisodeReleases(_ enabled: Bool) {
appSettings.setEpisodeReleases(enabled)
}
func isCustomAlertsEnabled() -> Bool {
return appSettings.isCustomAlertsEnabled()
}
func setCustomAlerts(_ enabled: Bool) {
appSettings.setCustomAlerts(enabled)
}
func isBadgeCountEnabled() -> Bool {
return appSettings.isBadgeCountEnabled()
}
func setBadgeCount(_ enabled: Bool) {
appSettings.setBadgeCount(enabled)
}
func isSoundEnabled() -> Bool {
return appSettings.isSoundEnabled()
}
func setSound(_ enabled: Bool) {
appSettings.setSound(enabled)
}
func isVibrationEnabled() -> Bool {
return appSettings.isVibrationEnabled()
}
func setVibration(_ enabled: Bool) {
appSettings.setVibration(enabled)
}
// MARK: - App Group
func isAppGroupAvailable() -> Bool {
return appSettings.isAppGroupAvailable()
}
func syncFromAppGroup() {
appSettings.syncFromAppGroup()
}
// MARK: - Getters
func getReadingPreferences() -> ReadingPreferences {
return appSettings.getReadingPreferences()
}
func getNotificationPreferences() -> NotificationPreferences {
return appSettings.getNotificationPreferences()
}
func getAllPreferences() -> AppPreferences {
return appSettings.getAllPreferences()
}
}