// // NRNovelReadSetManager.swift // ReaderHive // // Created by 澜声世纪 on 2025/11/27. // import UIKit class NRNovelReadSetManager: NSObject { static let manager = NRNovelReadSetManager() private(set) var readSet: NRNovelReadSet = UserDefaults.nr_object(forKey: kNRNovelReadSetDefaultsKey, as: NRNovelReadSet.self) ?? NRNovelReadSet() ///动画时间 let animateDuration = 0.2 let topViewHeight: CGFloat = UIScreen.navBarHeight let bottomViewHeight: CGFloat = UIScreen.safeBottom + 105 + 52 let contentTopViewHeight: CGFloat = UIScreen.navBarHeight let contentBottomViewHeight: CGFloat = UIScreen.safeBottom + 30 ///阅读区域 var readRect: CGRect { return .init(x: 16, y: 0, width: UIScreen.width - 32, height: UIScreen.height - contentTopViewHeight - contentBottomViewHeight) } var currentTheme: NRReadTheme { if isNight { return nightTheme } else { return NRReadTheme.theme(for: readSet.theme) } } ///夜间模式主题 lazy var nightTheme: NRReadTheme = { return NRReadTheme(type: .theme1, backgroundColor: ._24232_B, textColor: ._9_D_9_CA_8, statusBarStyle: .default) }() ///行间距 var lineSpacing: CGFloat { switch self.readSet.lineSpacingType { case .small: return 8 case .standard: return 10 case .large: return 12 } } ///段落间距 var paragraphSpacing: CGFloat { switch self.readSet.paragraphSpacingType { case .small: return 15 case .standard: return 17 case .large: return 19 } } var textColor: UIColor { return currentTheme.textColor } var textFont: UIFont { return UIFont.font(ofSize: self.readSet.fontSize, weight: .regular) } var titleFont: UIFont { return UIFont.font(ofSize: self.readSet.fontSize + 10, weight: .semibold) } let miniFontSize: CGFloat = 12 let maxFontSize: CGFloat = 24 var isNight: Bool { return readSet.isNight } var brightness: CGFloat { if let brightness = self.readSet.brightness { return brightness } else { return UIScreen.main.brightness } } func updateTheme(type: NRReadThemeType) { readSet.theme = type readSet.isNight = false UserDefaults.nr_setObject(readSet, forKey: kNRNovelReadSetDefaultsKey) NotificationCenter.default.post(name: NRNovelReadSetManager.didChangedThemeNotification, object: nil) } func updateIsNight(isNight: Bool) { readSet.isNight = isNight UserDefaults.nr_setObject(readSet, forKey: kNRNovelReadSetDefaultsKey) NotificationCenter.default.post(name: NRNovelReadSetManager.didChangedThemeNotification, object: nil) } func updateLineSpacing(type: NRNovelReadSet.SpacingType) { readSet.lineSpacingType = type UserDefaults.nr_setObject(readSet, forKey: kNRNovelReadSetDefaultsKey) NotificationCenter.default.post(name: NRNovelReadSetManager.didChangedTextLayoutNotification, object: nil) } func updateParagraphSpacing(type: NRNovelReadSet.SpacingType) { readSet.paragraphSpacingType = type UserDefaults.nr_setObject(readSet, forKey: kNRNovelReadSetDefaultsKey) NotificationCenter.default.post(name: NRNovelReadSetManager.didChangedTextLayoutNotification, object: nil) } func updateFontSize(size: CGFloat) { readSet.fontSize = size UserDefaults.nr_setObject(readSet, forKey: kNRNovelReadSetDefaultsKey) NotificationCenter.default.post(name: NRNovelReadSetManager.didChangedTextLayoutNotification, object: nil) } func updateBrightness(value: CGFloat) { readSet.brightness = value UIScreen.main.brightness = value UserDefaults.nr_setObject(readSet, forKey: kNRNovelReadSetDefaultsKey) } /// 字体属性 /// isPaging: 为YES的时候只需要返回跟分页相关的属性即可 (原因:包含UIColor,小数点相关的...不可返回,因为无法进行比较) func attributes(isTitle:Bool, isPageing:Bool = false) ->[NSAttributedString.Key:Any] { // 段落配置 let paragraphStyle = NSMutableParagraphStyle() // 当前行间距(lineSpacing)的倍数(可根据字体大小变化修改倍数) paragraphStyle.lineHeightMultiple = 1.0 if isTitle { // 行间距 paragraphStyle.lineSpacing = 0 // 段间距 paragraphStyle.paragraphSpacing = 0 // 对其 paragraphStyle.alignment = .center }else{ // 行间距 paragraphStyle.lineSpacing = lineSpacing // 换行模式(避免每页尾部留空白) // paragraphStyle.lineBreakMode = .byCharWrapping paragraphStyle.lineBreakMode = .byWordWrapping // 段间距 paragraphStyle.paragraphSpacing = paragraphSpacing // 对其 paragraphStyle.alignment = .justified } let font: UIFont if isTitle { font = self.titleFont } else { font = self.textFont } if isPageing { return [.font: font, .paragraphStyle: paragraphStyle] }else{ return [.foregroundColor: textColor, .font: font, .paragraphStyle: paragraphStyle] } } func emptyAttributes() -> [NSAttributedString.Key:Any] { // 段落配置 let paragraphStyle = NSMutableParagraphStyle() // 当前行间距(lineSpacing)的倍数(可根据字体大小变化修改倍数) paragraphStyle.lineHeightMultiple = 1.0 // 行间距 paragraphStyle.lineSpacing = 0 // 段间距 paragraphStyle.paragraphSpacing = 0 // 对其 paragraphStyle.alignment = .center return [.font: self.textFont, .paragraphStyle: paragraphStyle] } } extension NRNovelReadSetManager { ///主题色发生变化 static let didChangedThemeNotification = Notification.Name(rawValue: "NRNovelReadSetManager.didChangedThemeNotification") ///文本布局发生变化 (字体,行间距,段落间距等) static let didChangedTextLayoutNotification = Notification.Name(rawValue: "NRNovelReadSetManager.didChangedTextLayoutNotification") }