KMPreferenceManager.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. //
  2. // KMPreferenceManager.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2023/2/3.
  6. //
  7. import Cocoa
  8. enum KMPreferenceGroup: String {
  9. case general, display, markup, infomation, other
  10. }
  11. private let KMPreferenceInfoKey: String = "KMPreferenceInfoKey"
  12. typealias KMPreferenceKey = String
  13. /// general
  14. /// files
  15. private let KMOpenLastUnclosedDocumentWhenAppStartKey: KMPreferenceKey = "KMOpenLastUnclosedDocumentWhenAppStartKey"
  16. private let KMOpenLastUnlockedDocumentWhenAppStartKey: KMPreferenceKey = "KMOpenLastUnlockedDocumentWhenAppStartKey"
  17. private let KMDocumentMaximunDisplayNumberKey: KMPreferenceKey = "KMDocumentMaximunDisplayNumberKey"
  18. private let KMAutoSaveKey: KMPreferenceKey = "KMAutoSaveKey"
  19. private let KMAutoSavePerNumberMinuteKey: KMPreferenceKey = "KMAutoSavePerNumberMinuteKey"
  20. private let KMCloseFilePromptTypeKey: KMPreferenceKey = "KMCloseFilePromptTypeKey"
  21. /// open image file
  22. private let KMOpenImageFileTypeKey: KMPreferenceKey = "KMOpenImageFileTypeKey"
  23. private let KMSetDefaultPDFReaderKey: KMPreferenceKey = "KMSetDefaultPDFReaderKey"
  24. /// save password
  25. private let KMSavePasswordTypeKey: KMPreferenceKey = "KMSavePasswordTypeKey"
  26. private let KMGeneralAuthorNameKey: KMPreferenceKey = "KMGeneralAuthorNameKey"
  27. /// 偏好设置已改变
  28. private let KMPreferenceDidChangeNotificationName = "KMPreferenceDidChangeNotificationName"
  29. private let KMDefaultFontName = "Helvetica-Oblique"
  30. var TeXEditors: [[String : Any]] = []
  31. let NAME_KEY = "name"
  32. var INITIALUSERDEFAULTS_KEY = "InitialUserDefaults"
  33. var TEXEDITORS_KEY = "TeXEditors"
  34. var COMMAND_KEY = "command"
  35. var ARGUMENTS_KEY = "arguments"
  36. typealias KMPreference = KMPreferenceManager
  37. @objcMembers class KMPreferenceManager: NSObject {
  38. static let shared = KMPreferenceManager()
  39. private var generalGroupKeys: Array<KMPreferenceKey> = []
  40. private var displayGroupKeys: Array<KMPreferenceKey> = []
  41. private var markupGroupKeys: Array<KMPreferenceKey> = []
  42. public static let didChangeNotification = Notification.Name(KMPreferenceDidChangeNotificationName)
  43. /// general
  44. /// files
  45. public static let openLastUnclosedDocumentWhenAppStartKey = KMOpenLastUnclosedDocumentWhenAppStartKey
  46. public static let openLastUnlockedDocumentWhenAppStartKey = KMOpenLastUnlockedDocumentWhenAppStartKey
  47. public static let documentMaximunDisplayNumberKey = KMDocumentMaximunDisplayNumberKey
  48. public static let autoSaveKey = KMAutoSaveKey
  49. public static let autoSavePerNumberMinuteKey = KMAutoSavePerNumberMinuteKey
  50. public static let closeFilePromptTypeKey = KMCloseFilePromptTypeKey
  51. /// open image file
  52. public static let openImageFileTypeKey = KMOpenImageFileTypeKey
  53. public static let setDefaultPDFReaderKey = KMSetDefaultPDFReaderKey
  54. /// save password
  55. public static let savePasswordTypeKey = KMSavePasswordTypeKey
  56. public static let generalAuthorNameKey = KMGeneralAuthorNameKey
  57. override init() {
  58. super.init()
  59. }
  60. // MARK: 保存/获取数据
  61. public func setData(data: Any,forKey key: KMPreferenceKey) -> Bool {
  62. return self.setData(data: data, forKey: key, in: findGroup(forKey: key))
  63. }
  64. public func setData(data: Any,forKey key: KMPreferenceKey, in group: KMPreferenceGroup) -> Bool {
  65. return true
  66. }
  67. public func getData(forKey key: KMPreferenceKey) -> Any {
  68. var info: [String : Any]?
  69. let groupInfo: [String : Any] = info?[findGroup(forKey: key).rawValue] as? [String : Any] ?? [:]
  70. return groupInfo[key] as Any
  71. }
  72. public func resetData(_ group: KMPreferenceGroup) {
  73. }
  74. // MARK: 注册 key
  75. public func register(_ key: KMPreferenceKey, to group: KMPreferenceGroup) -> Bool {
  76. if (group == .general) {
  77. if (self.generalGroupKeys.contains(key)) {
  78. return false
  79. }
  80. self.generalGroupKeys.append(key)
  81. }
  82. return true
  83. }
  84. // MARK: -
  85. // MARK: 发布通知
  86. private func postNotification(object: [KMPreferenceGroup]?, userInfo: [KMPreferenceKey : Any]?) {
  87. DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
  88. NotificationCenter.default.post(name: KMPreferenceManager.didChangeNotification, object: object, userInfo: userInfo)
  89. }
  90. }
  91. // MARK: 获取信息
  92. private func findGroup(forKey key: KMPreferenceKey) -> KMPreferenceGroup {
  93. if (self.generalGroupKeys.contains(key)) {
  94. return .general
  95. } else if (self.displayGroupKeys.contains(key)) {
  96. return .display
  97. } else if (self.markupGroupKeys.contains(key)) {
  98. return .markup
  99. }
  100. return .other
  101. }
  102. }
  103. // MARK: - 默认值
  104. extension KMPreferenceManager {
  105. // General
  106. var openDocumentTypeDefaultValue: KMPreferenceOpenDocumentType {
  107. get {
  108. return .inSameWindow
  109. }
  110. }
  111. }
  112. // MARK: 扩展 General
  113. extension KMPreferenceManager {
  114. var openLastUnclosedDocumentWhenAppStart: Bool {
  115. get {
  116. return KMDataManager.ud_bool(forKey: KMReopenLastOpenFilesKey)
  117. }
  118. set {
  119. let pKey = KMPreference.openLastUnclosedDocumentWhenAppStartKey
  120. _ = self.setData(data: newValue, forKey: pKey)
  121. }
  122. }
  123. var openLastUnlockedDocumentWhenAppStart: Bool {
  124. get {
  125. return self.getData(forKey: KMOpenLastUnlockedDocumentWhenAppStartKey) as? Bool ?? true
  126. }
  127. set {
  128. let _ = self.setData(data: newValue, forKey: KMOpenLastUnlockedDocumentWhenAppStartKey)
  129. }
  130. }
  131. var documentMaximunDisplayNumber: Int {
  132. get {
  133. return self.getData(forKey: KMDocumentMaximunDisplayNumberKey) as? Int ?? 10
  134. }
  135. set {
  136. let _ = self.setData(data: newValue, forKey: KMDocumentMaximunDisplayNumberKey)
  137. }
  138. }
  139. var autoSave: Bool {
  140. get {
  141. return self.getData(forKey: KMAutoSaveKey) as? Bool ?? true
  142. }
  143. set {
  144. let _ = self.setData(data: newValue, forKey: KMAutoSaveKey)
  145. }
  146. }
  147. var autoSavePerNumberMinute: Int {
  148. get {
  149. return self.getData(forKey: KMAutoSavePerNumberMinuteKey) as? Int ?? 5
  150. }
  151. set {
  152. let _ = self.setData(data: newValue, forKey: KMAutoSavePerNumberMinuteKey)
  153. }
  154. }
  155. var closeFilePromptType: KMPreferenceCloseFilePromptType {
  156. get {
  157. if let type = self.getData(forKey: KMCloseFilePromptTypeKey) as? Int {
  158. if type == 1 { // 无提示,直接保存
  159. return .noPromp
  160. }
  161. }
  162. return .promp
  163. }
  164. set {
  165. if (newValue == .promp || newValue == .noPromp) {
  166. let _ = self.setData(data: newValue.rawValue, forKey: KMCloseFilePromptTypeKey)
  167. }
  168. }
  169. }
  170. var openImageFileType: Int {
  171. get {
  172. return self.getData(forKey: KMOpenImageFileTypeKey) as? Int ?? 0
  173. }
  174. set {
  175. let _ = self.setData(data: newValue, forKey: KMOpenImageFileTypeKey)
  176. }
  177. }
  178. var author: String {
  179. get {
  180. return KMDataManager.ud_string(forKey: KMUserNameKey) ?? NSFullUserName()
  181. }
  182. set {
  183. let _ = self.setData(data: newValue, forKey: KMGeneralAuthorNameKey)
  184. }
  185. }
  186. var setDefaultPDFReader: Bool {
  187. get {
  188. return self.getData(forKey: KMSetDefaultPDFReaderKey) as? Bool ?? true
  189. }
  190. set {
  191. let result = KMTools.setDefaultPDFReader(newValue)
  192. if (result) {
  193. let _ = self.setData(data: newValue, forKey: KMSetDefaultPDFReaderKey)
  194. }
  195. }
  196. }
  197. var savePasswordType: KMPreferenceSavePasswordType {
  198. get {
  199. let type = KMDataManager.ud_integer(forKey: KMSavePasswordOptionKey)
  200. if type == -1 {
  201. return .ask
  202. } else if type == 1 {
  203. return .always
  204. }
  205. return .never
  206. }
  207. set {
  208. if (newValue == .always || newValue == .never || newValue == .ask) {
  209. var data: Int = 0
  210. if newValue == .always {
  211. data = 1
  212. } else if newValue == .ask {
  213. data = -1
  214. }
  215. let _ = self.setData(data: newValue.rawValue, forKey: KMSavePasswordTypeKey)
  216. }
  217. }
  218. }
  219. var openDocumentType: KMPreferenceOpenDocumentType { // KMOpenDocumentInTab
  220. get {
  221. guard let num = KMDataManager.ud_object(forKey: KMOpenDocumentInTabKey) as? NSNumber else {
  222. return self.openDocumentTypeDefaultValue
  223. }
  224. if num.intValue == 1 {
  225. return .newWindow
  226. }
  227. return .inSameWindow
  228. }
  229. set {
  230. if (newValue == .inSameWindow || newValue == .newWindow) {
  231. }
  232. }
  233. }
  234. var openFileType: KMPreferenceOpenFileType {
  235. get {
  236. // 数据兼容
  237. let value = KMDataManager.ud_integer(forKey: KMInitialWindowSizeOptionKey)
  238. if let type = KMPreferenceOpenFileType(rawValue: value) {
  239. return type
  240. }
  241. return .default
  242. }
  243. set {
  244. if (newValue == .default || newValue == .maxim || newValue == .fit) {
  245. // 数据兼容
  246. }
  247. }
  248. }
  249. var keepSnapshotWindowToTop: Bool {
  250. get {
  251. return KMDataManager.ud_bool(forKey: KMSnapshotsOnTopKey)
  252. }
  253. set {
  254. // 数据兼容
  255. }
  256. }
  257. }
  258. // MARK: UserDefaults
  259. fileprivate let kKMLastOpenFilepathKey = "lastOpenFilepath"
  260. fileprivate let kKMLastOpenFilepathKeys = "lastOpenFilepaths"
  261. fileprivate let kKMViewSettingKey = "viewSetting"
  262. fileprivate let kKMPageNumberKey = "pageNumber"
  263. fileprivate let kKMPageScaleKey = "pageScale"
  264. extension KMPreferenceManager {
  265. var lastOpenFilepath: String? {
  266. get {
  267. return UserDefaults.standard.value(forKey: kKMLastOpenFilepathKey) as? String
  268. }
  269. set {
  270. UserDefaults.standard.set(newValue, forKey: kKMLastOpenFilepathKey)
  271. UserDefaults.standard.synchronize()
  272. }
  273. }
  274. var lastOpenFilepaths: [String]? {
  275. get {
  276. return UserDefaults.standard.value(forKey: kKMLastOpenFilepathKeys) as? [String]
  277. }
  278. set {
  279. UserDefaults.standard.set(newValue, forKey: kKMLastOpenFilepathKeys)
  280. UserDefaults.standard.synchronize()
  281. }
  282. }
  283. func setPageNumber(_ number: Int, forKey key: String) {
  284. UserDefaults.standard.set(number, forKey: "\(key)+\(kKMPageNumberKey)")
  285. UserDefaults.standard.synchronize()
  286. }
  287. func getPageNumber(forKey key: String) -> Int? {
  288. return UserDefaults.standard.value(forKey: "\(key)+\(kKMPageNumberKey)") as? Int
  289. }
  290. func setPageScale(_ scale: Float, forKey key: String) {
  291. UserDefaults.standard.set(scale, forKey: "\(key)+\(kKMPageScaleKey)")
  292. UserDefaults.standard.synchronize()
  293. }
  294. func getPageScale(forKey key: String) -> Float? {
  295. return UserDefaults.standard.value(forKey: "\(key)+\(kKMPageScaleKey)") as? Float
  296. }
  297. }
  298. // MARK: Qiuck
  299. extension KMPreferenceManager {
  300. internal func closeFileIsPrompt() -> Bool {
  301. return self.closeFilePromptType == .promp
  302. }
  303. // 单位: 秒
  304. var autoSaveTimeInterval: TimeInterval {
  305. get {
  306. var minute = KMPreferenceManager.shared.autoSavePerNumberMinute
  307. if (minute < 5) {
  308. minute = 5
  309. } else if (minute > 99) {
  310. minute = 99
  311. }
  312. let interval: TimeInterval = Double(minute) * 60.0
  313. return interval
  314. }
  315. }
  316. }
  317. // MARK: - Grouping
  318. extension KMPreferenceManager {
  319. var grouping: Bool {
  320. get {
  321. return false
  322. }
  323. }
  324. private static var _groupingInfosKey = "KMGroupingInfosKey"
  325. private var _grouping_infos: [KMPreferenceKey : Any] {
  326. get {
  327. return (objc_getAssociatedObject(self, &Self._groupingInfosKey) as? [KMPreferenceKey : Any]) ?? [:]
  328. }
  329. set {
  330. objc_setAssociatedObject(self, &Self._groupingInfosKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  331. }
  332. }
  333. private static var _groupingObjectsKey = "KMGroupingObjectsKey"
  334. private var _grouping_objects: Set<KMPreferenceGroup> {
  335. get {
  336. return (objc_getAssociatedObject(self, &Self._groupingObjectsKey) as? Set) ?? []
  337. }
  338. set {
  339. objc_setAssociatedObject(self, &Self._groupingObjectsKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  340. }
  341. }
  342. private static var _groupingKey = "KMGroupingKey"
  343. private var _grouping: Bool {
  344. get {
  345. return (objc_getAssociatedObject(self, &Self._groupingKey) as? Bool) ?? false
  346. }
  347. set {
  348. objc_setAssociatedObject(self, &Self._groupingKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
  349. }
  350. }
  351. func beginGrouping() {
  352. self._grouping = true
  353. self._grouping_objects = []
  354. self._grouping_infos = [:]
  355. }
  356. func endGrouping() {
  357. self._grouping = false
  358. if self._grouping_objects.isEmpty == false { // 发送通知
  359. var objects: [KMPreferenceGroup] = []
  360. for data in self._grouping_objects {
  361. objects.append(data)
  362. }
  363. self.postNotification(object: objects, userInfo: self._grouping_infos)
  364. }
  365. self._grouping_objects = []
  366. self._grouping_infos = [:]
  367. }
  368. }