AIPurchaseWindowController.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. //
  2. // AIPurchaseWindowController.swift
  3. // PDF Reader Pro Edition
  4. //
  5. // Created by Niehaoyu on 2024/1/18.
  6. //
  7. import Cocoa
  8. class AIPurchaseWindowController: NSWindowController, NSWindowDelegate {
  9. @IBOutlet weak var contendBox: NSBox!
  10. @IBOutlet weak var tipImage: NSImageView!
  11. @IBOutlet weak var titleLabel: NSTextField!
  12. @IBOutlet weak var subTitleLabel: NSTextField!
  13. @IBOutlet weak var purchaseBox: NSBox!
  14. @IBOutlet weak var purchaseButton: KMButton!
  15. @IBOutlet weak var priceLabel: NSTextField!
  16. @IBOutlet weak var priceDesLabel: NSTextField!
  17. @IBOutlet weak var restoreButton: HyperLinkButton!
  18. @IBOutlet weak var privacyButton: HyperLinkButton!
  19. @IBOutlet weak var termOfButton: HyperLinkButton!
  20. static var currentWindowController: AIPurchaseWindowController!
  21. public var isAIPurchase = false
  22. @objc static func currentWC() -> AIPurchaseWindowController {
  23. if currentWindowController != nil {
  24. return currentWindowController
  25. } else {
  26. let guideInfoWC: AIPurchaseWindowController = AIPurchaseWindowController.init(windowNibName: "AIPurchaseWindowController")
  27. currentWindowController = guideInfoWC;
  28. return guideInfoWC
  29. }
  30. }
  31. override func showWindow(_ sender: Any?) {
  32. super.showWindow(sender)
  33. self.window?.center()
  34. isAIPurchase = false
  35. if let window = self.window {
  36. window.center()
  37. self.reloadData()
  38. }
  39. }
  40. deinit {
  41. NotificationCenter.default.removeObserver(self)
  42. }
  43. override func windowDidLoad() {
  44. super.windowDidLoad()
  45. // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
  46. self.titleLabel.font = NSFont.UbuntuBoldFontWithSize(20)
  47. self.subTitleLabel.font = NSFont.SFProTextRegularFont(14)
  48. self.priceLabel.font = NSFont.UbuntuBoldFontWithSize(20)
  49. self.priceDesLabel.font = NSFont.SFProTextSemiboldFont(13)
  50. self.restoreButton.font = NSFont.SFProTextRegularFont(14)
  51. self.privacyButton.font = NSFont.SFProTextRegularFont(14)
  52. self.termOfButton.font = NSFont.SFProTextRegularFont(14)
  53. self.titleLabel.stringValue = KMLocalizedString("Purchase AI Tools", comment: "")
  54. self.subTitleLabel.stringValue = KMLocalizedString("Level up your PDF workflow with AI assistant. Unlock advanced features like AI Summarize, AI Translate, AI Rewrite, AI Proofread. ", comment: "")
  55. self.priceDesLabel.stringValue = KMLocalizedString("Auto-renewal | 50 credits/month | Cancel anytime", comment: "")
  56. self.restoreButton.title = KMLocalizedString("Restore", comment: "")
  57. self.privacyButton.title = KMLocalizedString("Privacy Policy", comment: "")
  58. self.termOfButton.title = KMLocalizedString("Terms of Service", comment: "")
  59. self.purchaseBox.wantsLayer = true
  60. self.purchaseBox.layer?.cornerRadius = NSHeight(self.purchaseBox.frame)/2
  61. self.purchaseBox.layer?.masksToBounds = true
  62. self.purchaseButton.wantsLayer = true
  63. self.purchaseButton.mouseMoveCallback = {[unowned self] mouseEntered in
  64. if self.purchaseButton.isEnabled == false {
  65. return
  66. }
  67. if mouseEntered {
  68. self.purchaseButton.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.2).cgColor
  69. } else {
  70. self.purchaseButton.layer?.backgroundColor = NSColor.clear.cgColor
  71. }
  72. }
  73. self.restoreButton.mouseMoveCallback = {[weak self] mouseEntered in
  74. if mouseEntered {
  75. if KMAppearance.isDarkMode() {
  76. self?.restoreButton.setTitleColor(NSColor(red: 1, green: 1, blue: 1, alpha: 0.7))
  77. } else {
  78. self?.restoreButton.setTitleColor(NSColor(red: 0, green: 0, blue: 0, alpha: 0.7))
  79. }
  80. } else {
  81. self?.restoreButton.setTitleColor(KMAppearance.KMColor_Layout_H2())
  82. }
  83. }
  84. self.privacyButton.mouseMoveCallback = {[weak self] mouseEntered in
  85. if mouseEntered {
  86. if KMAppearance.isDarkMode() {
  87. self?.privacyButton.setTitleColor(NSColor(red: 1, green: 1, blue: 1, alpha: 0.7))
  88. } else {
  89. self?.privacyButton.setTitleColor(NSColor(red: 0, green: 0, blue: 0, alpha: 0.7))
  90. }
  91. } else {
  92. self?.privacyButton.setTitleColor(KMAppearance.KMColor_Layout_H2())
  93. }
  94. }
  95. self.termOfButton.mouseMoveCallback = {[weak self] mouseEntered in
  96. if mouseEntered {
  97. if KMAppearance.isDarkMode() {
  98. self?.termOfButton.setTitleColor(NSColor(red: 1, green: 1, blue: 1, alpha: 0.7))
  99. } else {
  100. self?.termOfButton.setTitleColor(NSColor(red: 0, green: 0, blue: 0, alpha: 0.7))
  101. }
  102. } else {
  103. self?.termOfButton.setTitleColor(KMAppearance.KMColor_Layout_H2())
  104. }
  105. }
  106. self.refreshUI()
  107. self.addNotiObserver()
  108. }
  109. func addNotiObserver() -> Void {
  110. NotificationCenter.default.addObserver(self, selector: #selector(IAPProductLoadedNotification), name: NSNotification.Name(rawValue: NSNotification.Name.KMIAPProductLoaded.rawValue), object: nil)
  111. NotificationCenter.default.addObserver(self, selector: #selector(IAPSubscriptionLoadedNotification), name: NSNotification.Name(rawValue: NSNotification.Name.KMIAPSubscriptionLoaded.rawValue), object: nil)
  112. NotificationCenter.default.addObserver(self, selector: #selector(IAPProductPurchasedNotification), name: NSNotification.Name(rawValue: NSNotification.Name.KMIAPProductPurchased.rawValue), object: nil)
  113. NotificationCenter.default.addObserver(self, selector: #selector(IAPProductFailedNotification), name: NSNotification.Name(rawValue: NSNotification.Name.KMIAPProductFailed.rawValue), object: nil)
  114. NotificationCenter.default.addObserver(self, selector: #selector(IAPProductRestoreFinishedNotification), name: NSNotification.Name(rawValue: NSNotification.Name.KMIAPProductRestoreFinished.rawValue), object: nil)
  115. NotificationCenter.default.addObserver(self, selector: #selector(IAPProductRestoreFailedNotification), name: NSNotification.Name(rawValue: NSNotification.Name.KMIAPProductRestoreFailed.rawValue), object: nil)
  116. NotificationCenter.default.addObserver(self, selector: #selector(AIDeviceStatusChangeNotification), name: NSNotification.Name(rawValue: "kDeviceAIStatusChangeNotification"), object: nil)
  117. }
  118. func refreshUI() -> Void {
  119. if KMAppearance.isDarkMode() {
  120. self.contendBox.fillColor = NSColor(red: 24/255, green: 22/255, blue: 31/255, alpha: 1)
  121. } else {
  122. self.contendBox.fillColor = NSColor(red: 247/255, green: 245/255, blue: 1, alpha: 1)
  123. }
  124. }
  125. func reloadData() -> Void {
  126. self.purchaseButton.isEnabled = true
  127. var priceLabel = ""
  128. #if VERSION_FREE
  129. #if VERSION_DMG
  130. priceLabel = IAPProductsManager.default().dmgpdfReaderProAI_Monthly.price()
  131. #else
  132. priceLabel = IAPProductsManager.default().aiAllAccessPack1month_lite.price()
  133. #endif
  134. #else
  135. priceLabel = IAPProductsManager.default().aiAllAccessPack1month_pro.price()
  136. #endif
  137. let allowPurchaseAI = KMMemberInfo.shared.allowPurchaseAI
  138. if allowPurchaseAI {
  139. self.purchaseButton.isEnabled = true
  140. self.purchaseButton.layer?.backgroundColor = NSColor.clear.cgColor
  141. } else {
  142. self.purchaseButton.isEnabled = false
  143. self.purchaseButton.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.2).cgColor
  144. }
  145. self.priceLabel.stringValue = priceLabel
  146. }
  147. func appStoreRestoreFinish() -> Void {
  148. var didPurchased: Bool = false
  149. #if VERSION_FREE
  150. didPurchased = IAPProductsManager.default().aiAllAccessPack1month_lite.isSubscribed
  151. #else
  152. didPurchased = IAPProductsManager.default().aiAllAccessPack1month_pro.isSubscribed
  153. #endif
  154. if didPurchased {
  155. AIInfoManager.default().restoreAI(withInfo: ["receipt_str":IAPProductsManager.default().temptransactioReceipt as Any]) { dict, error in
  156. if AIInfoManager.default().aiInfo.infoDict.keys.count > 0 {
  157. let alert = NSAlert.init()
  158. alert.messageText = KMLocalizedString("Restore successfully", comment: "")
  159. alert.addButton(withTitle: KMLocalizedString("OK", comment: ""))
  160. alert.runModal()
  161. }
  162. self.removeWaitingView((self.window?.contentView)!)
  163. }
  164. }
  165. }
  166. func addWaingView(_ view: NSView) -> Void {
  167. self.removeWaitingView(view)
  168. let wView = WaitingView.init(frame: view.bounds)
  169. wView.autoresizingMask = [.width, .height]
  170. view.addSubview(wView)
  171. wView.startAnimation()
  172. }
  173. func removeWaitingView(_ view: NSView) -> Void {
  174. for view in view.subviews {
  175. if view.className == WaitingView.className() {
  176. view.removeFromSuperview()
  177. break
  178. }
  179. }
  180. }
  181. //MARK: - IBAction
  182. @IBAction func purchaseAction(_ sender: KMButton) {
  183. if KMMemberInfo.shared.isLogin && KMMemberInfo.shared.validFlag == "5" {
  184. KMMemberPromptWC.shared.showWindow(nil)
  185. KMMemberPromptWC.shared.tipType = .signouting
  186. } else {
  187. #if VERSION_FREE
  188. IAPProductsManager.default().make(IAPProductsManager.default().aiAllAccessPack1month_lite)
  189. #else
  190. IAPProductsManager.default().make(IAPProductsManager.default().aiAllAccessPack1month_pro)
  191. #endif
  192. self.addWaingView((self.window?.contentView)!)
  193. FMTrackEventManager.defaultManager.trackOnceEvent(event: "PUW", withProperties: ["PUW_Btn":"PUW_Btn_BuyAITools"])
  194. }
  195. }
  196. @IBAction func restoreAction(_ sender: Any) {
  197. IAPProductsManager.default().restoreSubscriptions()
  198. self.addWaingView((self.window?.contentView)!)
  199. }
  200. @IBAction func privacyAction(_ sender: Any) {
  201. var url = URL(string:"https://www.pdfreaderpro.com/privacy-policy")!
  202. NSWorkspace.shared.open(url)
  203. }
  204. @IBAction func termOfAction(_ sender: Any) {
  205. var url = URL(string:"https://www.pdfreaderpro.com/terms_of_service")!
  206. NSWorkspace.shared.open(url)
  207. }
  208. //MARK: - Notification
  209. func windowWillClose(_ notification: Notification) {
  210. FMTrackEventManager.defaultManager.trackOnceEvent(event: "PUW", withProperties: ["PUW_Btn":"PUW_Btn_BuyAITools_Cancel"])
  211. AIPurchaseWindowController.currentWindowController = nil
  212. }
  213. @objc func IAPProductLoadedNotification() {
  214. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  215. self.reloadData()
  216. }
  217. }
  218. @objc func IAPSubscriptionLoadedNotification() {
  219. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  220. self.removeWaitingView((self.window?.contentView)!)
  221. self.reloadData()
  222. }
  223. }
  224. @objc func IAPProductPurchasedNotification() {
  225. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  226. self.removeWaitingView((self.window?.contentView)!)
  227. self.reloadData()
  228. if (self.isAIPurchase == true) {
  229. self.trackEvent(eventName: self.kEventName, params: self.kEventParams, platform: .firebase)
  230. }
  231. //Appstore购买结束后绑定票据信息
  232. }
  233. }
  234. @objc func IAPProductFailedNotification() {
  235. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  236. self.removeWaitingView((self.window?.contentView)!)
  237. }
  238. }
  239. @objc func IAPProductRestoreFinishedNotification() {
  240. self.reloadData()
  241. self.appStoreRestoreFinish()
  242. }
  243. @objc func IAPProductRestoreFailedNotification() {
  244. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  245. self.removeWaitingView((self.window?.contentView)!)
  246. }
  247. }
  248. @objc func AIDeviceStatusChangeNotification() {
  249. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  250. self.reloadData()
  251. if KMMemberInfo.shared.isPermitAI {
  252. self.close()
  253. }
  254. }
  255. }
  256. }