AINewConfigWindowController.swift 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. //
  2. // AINewConfigWindowController.swift
  3. // PDF Reader Pro Edition
  4. //
  5. // Created by Niehaoyu on 2024/4/16.
  6. //
  7. import Cocoa
  8. protocol AIConfigWindowDelegate: AnyObject {
  9. func ai_InputViewDidChooseCurFile(aiConfigWindow: AINewConfigWindowController)
  10. }
  11. @objcMembers class AINewConfigWindowController: NSWindowController, NSWindowDelegate, AIInfoInputViewDelegate {
  12. static var currentWindowController: AINewConfigWindowController!
  13. @IBOutlet weak var contendBox: NSBox!
  14. var aiHeaderView: AIHeaderView!
  15. var aiChatView: AIChatView!
  16. var aiTypeItemView: AITypeItemChooseView!
  17. var aiInfoInputView: AIInfoInputView!
  18. var inputStringHeight: CGFloat = 40
  19. var didSetOriginFrame: Bool = false
  20. var eventLabel: String = "AITools_Start"
  21. weak var aiDelegate: AIConfigWindowDelegate?
  22. var chooseCurFileHandle: ((_ windowVC: AINewConfigWindowController) -> Void)?
  23. deinit {
  24. DistributedNotificationCenter.default.removeObserver(self)
  25. }
  26. @objc static func currentWC() -> AINewConfigWindowController {
  27. if currentWindowController != nil {
  28. return currentWindowController
  29. } else {
  30. let configWC: AINewConfigWindowController = AINewConfigWindowController.init(windowNibName: "AINewConfigWindowController")
  31. currentWindowController = configWC;
  32. return currentWindowController
  33. }
  34. }
  35. override func showWindow(_ sender: Any?) {
  36. super.showWindow(sender)
  37. self.window?.center()
  38. self.window?.delegate = self
  39. self.aiInfoInputView.setUpTranslateUI()
  40. self.aiChatView.reloadData()
  41. self.aiTypeItemView.refreshUI()
  42. self.refreshViewUI()
  43. }
  44. override func windowDidLoad() {
  45. super.windowDidLoad()
  46. // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
  47. self.window?.title = KMLocalizedString("AI Tools", comment: "")
  48. self.loadAIHeaderView()
  49. self.loadAIChatView()
  50. self.loadAIInputView()
  51. self.loadAITypeItemView()
  52. self.refreshViewUI()
  53. self.refreshViewColor()
  54. DistributedNotificationCenter.default().addObserver(self, selector: #selector(themeChange), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
  55. }
  56. func refreshViewColor() {
  57. if KMAppearance.isDarkMode() {
  58. self.contendBox.fillColor = NSColor(red: 33/255, green: 33/255, blue: 33/255, alpha: 1)
  59. } else {
  60. self.contendBox.fillColor = NSColor.white
  61. }
  62. self.aiHeaderView.refreshViewColor()
  63. self.aiInfoInputView.refreshUI()
  64. self.aiChatView.reloadData()
  65. self.aiTypeItemView.refreshViewColor()
  66. }
  67. func loadAIHeaderView() {
  68. self.aiHeaderView = AIHeaderView.createFromNib()
  69. self.aiHeaderView.frame = NSMakeRect(0, NSHeight(self.contendBox.frame)-58, NSWidth(self.contendBox.frame), 28)
  70. self.aiHeaderView.autoresizingMask = [.minXMargin, .maxXMargin, .width, .minYMargin]
  71. self.contendBox.addSubview(self.aiHeaderView)
  72. }
  73. func loadAIChatView() {
  74. self.aiChatView = AIChatView.createFromNib()
  75. self.aiChatView.wantsLayer = true
  76. self.aiChatView.layer?.backgroundColor = NSColor.clear.cgColor
  77. self.aiChatView.frame = NSMakeRect(0, 300, NSWidth(self.contendBox.frame), NSHeight(self.contendBox.frame)-400)
  78. self.aiChatView.autoresizingMask = [.width, .height]
  79. self.contendBox.addSubview(self.aiChatView)
  80. self.aiChatView.chooseConfigHandle = {[weak self] view, configType in
  81. DispatchQueue.main.async {
  82. self?.chooseAIFunctionWithType(configType)
  83. }
  84. }
  85. self.aiChatView.cancelAIHandle = {[weak self] view, chatInfoModel in
  86. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.05) {
  87. chatInfoModel.chatInfoState = .stateCancel
  88. self?.aiChatView.reloadData()
  89. }
  90. }
  91. self.aiChatView.continueAITranslateHandle = {[weak self] view, chatInfoModel in
  92. DispatchQueue.main.async {
  93. chatInfoModel.chatInfoState = .stateLoading
  94. self?.aiChatView.reloadData()
  95. self?.continueAiTranslate(chatInfoModel)
  96. }
  97. }
  98. self.aiChatView.redoHandle = {[weak self] view, chatInfoModel in
  99. DispatchQueue.main.async {
  100. let newChatModel = AIChatInfoModel.init()
  101. newChatModel.aiConfigType = chatInfoModel.aiConfigType
  102. newChatModel.infoType = chatInfoModel.infoType
  103. newChatModel.filePath = chatInfoModel.filePath
  104. newChatModel.chatInfoState = .stateLoading
  105. newChatModel.uploadContent = chatInfoModel.uploadContent
  106. newChatModel.translateFromLanguage = chatInfoModel.translateFromLanguage
  107. newChatModel.translateToLanguage = chatInfoModel.translateToLanguage
  108. AIChatInfoManager.defaultManager.modelsArrM.append(newChatModel)
  109. self?.aiChatView.reloadData()
  110. if newChatModel.aiConfigType == .summarize {
  111. self?.aiSummarizeWithModel(newChatModel)
  112. } else if newChatModel.aiConfigType == .reWriting {
  113. self?.aiReWritingWithModel(newChatModel)
  114. } else if newChatModel.aiConfigType == .proofreading {
  115. self?.aiProofreadingWithModel(newChatModel)
  116. } else if newChatModel.aiConfigType == .translate {
  117. self?.startAiTranslateWithModel(newChatModel)
  118. } else if newChatModel.aiConfigType == .ponder {
  119. self?.aiPonderWithModel(newChatModel)
  120. }
  121. }
  122. }
  123. }
  124. func loadAIInputView() {
  125. self.aiInfoInputView = AIInfoInputView.createFromNib()
  126. self.aiInfoInputView.frame = NSMakeRect((NSWidth(self.contendBox.frame)-248)/2.0, 20, 248, 86)
  127. self.aiInfoInputView.autoresizingMask = [.minXMargin, .maxXMargin, .width, .maxYMargin]
  128. self.contendBox.addSubview(self.aiInfoInputView)
  129. self.aiInfoInputView.aiConfigType = .none
  130. self.aiInfoInputView.aiDelegate = self
  131. self.aiInfoInputView.reloadData()
  132. self.aiInfoInputView.startAIHandle = {[unowned self] view in
  133. if view.aiConfigType == .summarize {
  134. let chatModel = AIChatInfoModel.init()
  135. chatModel.aiConfigType = .summarize
  136. chatModel.infoType = .chatFileUpload
  137. chatModel.filePath = self.aiInfoInputView.filePath
  138. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  139. self.aiChatView.reloadData()
  140. self.aiSummarize()
  141. } else if view.aiConfigType == .reWriting {
  142. let chatModel = AIChatInfoModel.init()
  143. chatModel.aiConfigType = .reWriting
  144. chatModel.infoType = .chatStringUpload
  145. chatModel.uploadContent = self.aiInfoInputView.fileEmptyTextView.string
  146. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  147. self.aiChatView.reloadData()
  148. self.aiReWriting()
  149. } else if view.aiConfigType == .proofreading {
  150. let chatModel = AIChatInfoModel.init()
  151. chatModel.aiConfigType = .proofreading
  152. chatModel.infoType = .chatStringUpload
  153. chatModel.uploadContent = self.aiInfoInputView.fileEmptyTextView.string
  154. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  155. self.aiChatView.reloadData()
  156. self.aiProofreading()
  157. } else if view.aiConfigType == .translate {
  158. let chatModel = AIChatInfoModel.init()
  159. chatModel.aiConfigType = .translate
  160. if self.aiInfoInputView.filePath.isEmpty == false {
  161. //文件
  162. chatModel.filePath = self.aiInfoInputView.filePath
  163. chatModel.infoType = .chatFileUpload
  164. } else {
  165. //文字
  166. chatModel.uploadContent = self.aiInfoInputView.fileEmptyTextView.string
  167. chatModel.infoType = .chatStringUpload
  168. }
  169. chatModel.translateFromLanguage = self.aiInfoInputView.fromLanguage
  170. chatModel.translateToLanguage = self.aiInfoInputView.toLanguage
  171. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  172. self.aiChatView.reloadData()
  173. self.startAiTranslate()
  174. } else if view.aiConfigType == .ponder {
  175. let chatModel = AIChatInfoModel.init()
  176. chatModel.aiConfigType = .ponder
  177. chatModel.infoType = .chatStringUpload
  178. chatModel.uploadContent = self.aiInfoInputView.fileEmptyTextView.string
  179. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  180. self.aiChatView.reloadData()
  181. self.ponderReWriting()
  182. }
  183. self.refreshViewUI()
  184. self.aiTypeItemView.reloadData()
  185. }
  186. self.aiInfoInputView.inputFrameUpdateHandle = {[weak self] view, stringSize in
  187. if view.aiConfigType == .summarize {
  188. self?.inputStringHeight = max(stringSize.height, 40)
  189. } else if view.aiConfigType == .reWriting {
  190. self?.inputStringHeight = max(stringSize.height, 40)
  191. } else if view.aiConfigType == .proofreading {
  192. self?.inputStringHeight = max(stringSize.height, 40)
  193. } else if view.aiConfigType == .translate {
  194. if view.filePath.isEmpty {
  195. self?.inputStringHeight = max(stringSize.height, 40)
  196. } else {
  197. self?.inputStringHeight = 40
  198. }
  199. } else if view.aiConfigType == .ponder {
  200. self?.inputStringHeight = max(stringSize.height, 40)
  201. }
  202. self?.refreshViewUI()
  203. }
  204. self.aiInfoInputView.refreshUI()
  205. }
  206. func loadAITypeItemView() {
  207. self.aiTypeItemView = AITypeItemChooseView.createFromNib()
  208. self.aiTypeItemView.wantsLayer = true
  209. self.aiTypeItemView.frameCallback = {[weak self] in
  210. self?.refreshViewUI()
  211. }
  212. self.aiTypeItemView.layer?.backgroundColor = NSColor.clear.cgColor
  213. self.aiTypeItemView.frame = NSMakeRect((NSWidth(self.contendBox.frame)-246)/2, NSMaxY(self.aiInfoInputView.frame)+13, 246, 52)
  214. self.aiTypeItemView.autoresizingMask = [.minXMargin, .maxXMargin, .width, .maxYMargin]
  215. self.contendBox.addSubview(self.aiTypeItemView)
  216. self.aiTypeItemView.chooseTypeHandle = {[weak self] itemView, aiConfigtype in
  217. self?.chooseAIFunctionWithType(aiConfigtype)
  218. }
  219. self.aiTypeItemView.clearHandle = {[weak self] itemView in
  220. if AIChatInfoManager.defaultManager.modelsArrM.count < 1 {
  221. return
  222. }
  223. let alert = NSAlert()
  224. alert.alertStyle = .critical
  225. alert.informativeText = KMLocalizedString("All the AI content will be removed. Are you sure you want to clear the session?", comment: "")
  226. alert.messageText = KMLocalizedString("Clear session", comment: "")
  227. alert.addButton(withTitle: KMLocalizedString("Clear", comment: ""))
  228. alert.addButton(withTitle: KMLocalizedString("Cancel", comment: ""))
  229. let response = alert.runModal()
  230. if response.rawValue == 1000 {
  231. DispatchQueue.main.async {
  232. AIChatInfoManager.defaultManager.clearData()
  233. self?.aiChatView.reloadData()
  234. }
  235. }
  236. }
  237. }
  238. func chooseAIFunctionWithType(_ aiConfigType: AIConfigType) -> Void {
  239. if KMMemberInfo.shared.aiNewSubscription(aiConfigType) == false {
  240. return
  241. }
  242. if KMMemberInfo.shared.aiPoint == 0 &&
  243. (AIInfoManager.default().aiInfo.totalToken - AIInfoManager.default().aiInfo.usedTimes) < 1 {
  244. let alert = NSAlert()
  245. alert.alertStyle = .critical
  246. alert.informativeText = KMLocalizedString("No Value Present", comment: "")
  247. alert.addButton(withTitle: KMLocalizedString("OK", comment: ""))
  248. alert.runModal()
  249. return
  250. }
  251. if self.eventLabel.isEmpty {
  252. self.eventLabel = "AITools_Start"
  253. }
  254. if aiConfigType == .summarize {
  255. FMTrackEventManager.defaultManager.trackOnceEvent(event: "AITools", withProperties: [self.eventLabel:"AISum"])
  256. } else if aiConfigType == .reWriting {
  257. FMTrackEventManager.defaultManager.trackOnceEvent(event: "AITools", withProperties: [self.eventLabel:"AIRewrite"])
  258. } else if aiConfigType == .proofreading {
  259. FMTrackEventManager.defaultManager.trackOnceEvent(event: "AITools", withProperties: [self.eventLabel:"AIProofread"])
  260. } else if aiConfigType == .translate {
  261. FMTrackEventManager.defaultManager.trackOnceEvent(event: "AITools", withProperties: [self.eventLabel:"AITranslate"])
  262. } else if aiConfigType == .ponder {
  263. FMTrackEventManager.defaultManager.trackOnceEvent(event: "AITools", withProperties: [self.eventLabel:"AIDeepThink_Click"])
  264. }
  265. self.aiInfoInputView.aiConfigType = aiConfigType
  266. self.aiInfoInputView.reloadData()
  267. self.aiInfoInputView.aiFunctionTypeChanged()
  268. if self.aiInfoInputView.fileEmptyTextView.string.isEmpty == false {
  269. self.aiInfoInputView.updateCountLabelInfo()
  270. self.aiInfoInputView.refreshStringSize()
  271. }
  272. self.refreshViewUI()
  273. }
  274. func setCurrentPDFSelection(_ string: String) -> Void {
  275. self.aiInfoInputView.fileEmptyTextView.string = string
  276. }
  277. func refreshViewUI() {
  278. self.aiHeaderView.frame = NSMakeRect(0, NSHeight(self.contendBox.frame)-58, NSWidth(self.contendBox.frame), 28)
  279. if self.aiInfoInputView.aiConfigType == .none {
  280. self.aiInfoInputView.frame = NSMakeRect(13, 17, 240, 86)
  281. } else if self.aiInfoInputView.aiConfigType == .summarize {
  282. self.aiInfoInputView.frame = NSMakeRect(13, 17, 240, min(96+self.inputStringHeight, 500))
  283. } else if self.aiInfoInputView.aiConfigType == .reWriting {
  284. self.aiInfoInputView.frame = NSMakeRect(13, 17, 240, min(72+self.inputStringHeight, 500))
  285. } else if self.aiInfoInputView.aiConfigType == .proofreading {
  286. self.aiInfoInputView.frame = NSMakeRect(13, 17, 240, min(72+self.inputStringHeight, 500))
  287. } else if self.aiInfoInputView.aiConfigType == .translate {
  288. self.aiInfoInputView.frame = NSMakeRect(13, 17, 240, min(125+self.inputStringHeight, 500))
  289. } else if self.aiInfoInputView.aiConfigType == .ponder {
  290. self.aiInfoInputView.frame = NSMakeRect(13, 17, 240, min(72+self.inputStringHeight, 500))
  291. }
  292. self.aiTypeItemView.frame = NSMakeRect(13, NSMaxY(self.aiInfoInputView.frame)+8, 240, self.aiTypeItemView.viewHeight)
  293. self.aiChatView.frame = NSMakeRect(0, NSMaxY(self.aiTypeItemView.frame)+8, NSWidth(self.contendBox.frame), NSHeight(self.contendBox.frame) - NSMaxY(self.aiTypeItemView.frame) - 16 - 58)
  294. }
  295. //MARK: AI-Action
  296. func aiSummarize() -> Void {
  297. if FileManager.default.fileExists(atPath: self.aiInfoInputView.filePath) {
  298. let chatModel = AIChatInfoModel.init()
  299. chatModel.aiConfigType = .summarize
  300. chatModel.infoType = .chatStringResult
  301. chatModel.filePath = self.aiInfoInputView.filePath
  302. chatModel.chatInfoState = .stateLoading
  303. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  304. self.aiChatView.reloadData()
  305. self.aiSummarizeWithModel(chatModel)
  306. }
  307. }
  308. func aiSummarizeWithModel(_ chatModel: AIChatInfoModel) -> Void {
  309. if FileManager.default.fileExists(atPath: chatModel.filePath) {
  310. AIChatInfoManager.defaultManager.isAILoading = true
  311. //MARK: TestData
  312. // DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
  313. // DispatchQueue.main.async {
  314. // AIChatInfoManager.defaultManager.isAILoading = false
  315. // chatModel.chatResult = "AI Summary 返回的结果\nAI Summary 返回的结果\nAI Summary 返回的结果\nAI Summary 返回的结果\nAI Summary 返回的结果\nAI Summary 返回的结果\nAI Summary 返回的结果\nAI Summary 返回的结果"
  316. // chatModel.chatInfoState = .stateSuccess
  317. // self.aiChatView.reloadData()
  318. // self.aiTypeItemView.reloadData()
  319. // self.aiInfoInputView.reloadData()
  320. //
  321. // DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 4) {
  322. // DispatchQueue.main.async {
  323. // chatModel.chatInfoState = .stateFailed
  324. // chatModel.chatResult = "Unknown error"
  325. //
  326. // self.aiChatView.reloadData()
  327. // self.aiTypeItemView.reloadData()
  328. // self.aiInfoInputView.reloadData()
  329. // }
  330. // }
  331. // }
  332. // }
  333. //MARK: 正式数据
  334. KMAIRequestServerManager.defaultManager.aiAction(content: chatModel.filePath, state: .extractSummaryFile) { wrapper in
  335. DispatchQueue.main.async {
  336. AIChatInfoManager.defaultManager.isAILoading = false
  337. let resultStr = wrapper.content
  338. chatModel.chatResult = resultStr
  339. chatModel.chatInfoState = wrapper.success ? .stateSuccess : .stateFailed
  340. self.aiChatView.reloadData()
  341. self.aiTypeItemView.reloadData()
  342. self.aiInfoInputView.reloadData()
  343. }
  344. }
  345. } else {
  346. DispatchQueue.main.async {
  347. AIChatInfoManager.defaultManager.isAILoading = false
  348. let resultStr = KMLocalizedString("File Not Exist", comment: "")
  349. chatModel.chatResult = resultStr
  350. chatModel.chatInfoState = .stateFailed
  351. self.aiChatView.reloadData()
  352. self.aiTypeItemView.reloadData()
  353. self.aiInfoInputView.reloadData()
  354. }
  355. }
  356. }
  357. func aiReWriting() -> Void {
  358. //Loading(28+155)->Finish(实际大小)
  359. let chatModel = AIChatInfoModel.init()
  360. chatModel.aiConfigType = .reWriting
  361. chatModel.infoType = .chatStringResult
  362. chatModel.uploadContent = self.aiInfoInputView.fileEmptyTextView.string
  363. chatModel.chatInfoState = .stateLoading
  364. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  365. self.aiChatView.reloadData()
  366. self.aiReWritingWithModel(chatModel)
  367. }
  368. func ponderReWriting() -> Void {
  369. //Loading(28+155)->Finish(实际大小)
  370. let chatModel = AIChatInfoModel.init()
  371. chatModel.aiConfigType = .ponder
  372. chatModel.infoType = .chatStringResult
  373. chatModel.uploadContent = self.aiInfoInputView.fileEmptyTextView.string
  374. chatModel.chatInfoState = .stateLoading
  375. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  376. self.aiChatView.reloadData()
  377. self.aiPonderWithModel(chatModel)
  378. FMTrackEventManager.defaultManager.trackOnceEvent(event: "AITools", withProperties: ["AITools_Start":"AIDeepThink_Start"])
  379. }
  380. func aiReWritingWithModel(_ chatModel: AIChatInfoModel) -> Void {
  381. AIChatInfoManager.defaultManager.isAILoading = true
  382. //MARK: TestData
  383. // DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
  384. // DispatchQueue.main.async {
  385. // AIChatInfoManager.defaultManager.isAILoading = false
  386. // chatModel.chatInfoState = .stateSuccess
  387. // chatModel.chatResult = "AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果AI Rewrite返回的结果"
  388. // self.aiChatView.reloadData()
  389. // self.aiTypeItemView.reloadData()
  390. // self.aiInfoInputView.reloadData()
  391. // }
  392. // }
  393. //MARK: 正式数据
  394. KMAIRequestServerManager.defaultManager.aiAction(content: chatModel.uploadContent,
  395. state: .rewrite) { wrapper in
  396. DispatchQueue.main.async {
  397. AIChatInfoManager.defaultManager.isAILoading = false
  398. let resultStr = wrapper.content
  399. chatModel.chatResult = resultStr
  400. chatModel.chatInfoState = wrapper.success ? .stateSuccess : .stateFailed
  401. self.aiChatView.reloadData()
  402. self.aiTypeItemView.reloadData()
  403. self.aiInfoInputView.reloadData()
  404. }
  405. }
  406. }
  407. func aiPonderWithModel(_ chatModel: AIChatInfoModel) -> Void {
  408. AIChatInfoManager.defaultManager.isAILoading = true
  409. //MARK: 正式数据
  410. KMAIRequestServerManager.defaultManager.aiAction(content: chatModel.uploadContent,
  411. state: .aiPonder) { wrapper in
  412. DispatchQueue.main.async {
  413. AIChatInfoManager.defaultManager.isAILoading = false
  414. let resultStr = wrapper.content
  415. chatModel.chatResult = resultStr
  416. chatModel.chatInfoState = wrapper.success ? .stateSuccess : .stateFailed
  417. self.aiChatView.reloadData()
  418. self.aiTypeItemView.reloadData()
  419. self.aiInfoInputView.reloadData()
  420. }
  421. }
  422. }
  423. func aiProofreading() -> Void {
  424. let chatModel = AIChatInfoModel.init()
  425. chatModel.aiConfigType = .proofreading
  426. chatModel.infoType = .chatStringResult
  427. chatModel.uploadContent = self.aiInfoInputView.fileEmptyTextView.string
  428. chatModel.chatInfoState = .stateLoading
  429. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  430. self.aiChatView.reloadData()
  431. self.aiProofreadingWithModel(chatModel)
  432. }
  433. func aiProofreadingWithModel(_ chatModel: AIChatInfoModel) -> Void {
  434. AIChatInfoManager.defaultManager.isAILoading = true
  435. //MARK: TestData
  436. // DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
  437. // DispatchQueue.main.async {
  438. // chatModel.chatInfoState = .stateSuccess
  439. // AIChatInfoManager.defaultManager.isAILoading = false
  440. // chatModel.chatResult = "AI Proofreading 返回的结果"
  441. // self.aiChatView.reloadData()
  442. // self.aiTypeItemView.reloadData()
  443. // self.aiInfoInputView.reloadData()
  444. //
  445. // }
  446. // }
  447. //MARK: 正式数据
  448. KMAIRequestServerManager.defaultManager.aiAction(content: chatModel.uploadContent,
  449. state: .correctTypos) { wrapper in
  450. DispatchQueue.main.async {
  451. AIChatInfoManager.defaultManager.isAILoading = false
  452. let resultStr = wrapper.content
  453. chatModel.chatResult = resultStr
  454. chatModel.chatInfoState = wrapper.success ? .stateSuccess : .stateFailed
  455. self.aiChatView.reloadData()
  456. self.aiTypeItemView.reloadData()
  457. self.aiInfoInputView.reloadData()
  458. }
  459. }
  460. }
  461. func startAiTranslate() -> Void {
  462. let chatModel = AIChatInfoModel.init()
  463. chatModel.aiConfigType = .translate
  464. if self.aiInfoInputView.filePath.isEmpty {
  465. //文字
  466. chatModel.infoType = .chatTranslateResult
  467. chatModel.uploadContent = self.aiInfoInputView.fileEmptyTextView.string
  468. chatModel.filePath = ""
  469. } else {
  470. //文件
  471. chatModel.infoType = .chatTranslateResult
  472. chatModel.filePath = self.aiInfoInputView.filePath
  473. chatModel.uploadContent = ""
  474. }
  475. chatModel.translateFromLanguage = self.aiInfoInputView.fromLanguage
  476. chatModel.translateToLanguage = self.aiInfoInputView.toLanguage
  477. chatModel.chatInfoState = .stateLoading
  478. AIChatInfoManager.defaultManager.modelsArrM.append(chatModel)
  479. self.aiChatView.reloadData()
  480. self.startAiTranslateWithModel(chatModel)
  481. }
  482. func startAiTranslateWithModel(_ chatModel: AIChatInfoModel) -> Void {
  483. //MARK: TestData
  484. // DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
  485. // DispatchQueue.main.async {
  486. // chatModel.chatInfoState = .stateInfoConfirm
  487. // chatModel.chatResult = "当前翻译需要的内容:"
  488. // self.aiChatView.reloadData()
  489. //
  490. // }
  491. // }
  492. //MARK: Data
  493. if chatModel.filePath.isEmpty == true {
  494. //文字
  495. AIChatInfoManager.defaultManager.isAILoading = true
  496. KMAIRequestServerManager.defaultManager.aiAction(content: chatModel.uploadContent,
  497. state: .textTranslate,
  498. from: chatModel.translateFromLanguage,
  499. to: chatModel.translateToLanguage) { wrapper in
  500. DispatchQueue.main.async {
  501. AIChatInfoManager.defaultManager.isAILoading = false
  502. let resultStr = wrapper.content
  503. chatModel.chatResult = resultStr
  504. chatModel.chatInfoState = wrapper.success ? .stateSuccess : .stateFailed
  505. self.aiChatView.reloadData()
  506. self.aiTypeItemView.reloadData()
  507. self.aiInfoInputView.reloadData()
  508. }
  509. };
  510. } else {
  511. //文件
  512. AIChatInfoManager.defaultManager.isAILoading = true
  513. KMAIRequestServerManager.defaultManager.aiAction(content: chatModel.filePath,
  514. state: .fileTranslate,
  515. from: chatModel.translateFromLanguage,
  516. to: chatModel.translateToLanguage) { wrapper in
  517. DispatchQueue.main.async {
  518. AIChatInfoManager.defaultManager.isAILoading = false
  519. var success = wrapper.success
  520. let resultStr = wrapper.content
  521. if success == false && resultStr == "501" {
  522. success = true
  523. }
  524. if success {
  525. let infoDict: NSDictionary = wrapper.result
  526. var credit: Int = 0
  527. if infoDict["credit"] != nil {
  528. credit = (infoDict["credit"] ?? "0") as! Int
  529. }
  530. var charCount: Int = 0
  531. if infoDict["charCount"] != nil {
  532. charCount = (infoDict["charCount"] ?? "0") as! Int
  533. if credit == 0 {
  534. if charCount < 10000 {
  535. credit = 2
  536. } else {
  537. credit = charCount/5000 + 1
  538. }
  539. }
  540. }
  541. chatModel.creditsValid = true
  542. if resultStr == "501" {
  543. chatModel.creditsValid = false
  544. }
  545. chatModel.costCredits = credit
  546. chatModel.totalChart = charCount
  547. chatModel.chatInfoState = .stateInfoConfirm
  548. chatModel.chatResult = resultStr
  549. self.aiChatView.reloadData()
  550. self.aiTypeItemView.reloadData()
  551. self.aiInfoInputView.reloadData()
  552. } else {
  553. chatModel.chatResult = resultStr
  554. chatModel.chatInfoState = .stateFailed
  555. self.aiChatView.reloadData()
  556. self.aiTypeItemView.reloadData()
  557. self.aiInfoInputView.reloadData()
  558. }
  559. }
  560. };
  561. }
  562. }
  563. func continueAiTranslate(_ chatModel: AIChatInfoModel) -> Void {
  564. //MARK: TestData
  565. // DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
  566. // DispatchQueue.main.async {
  567. // chatModel.chatInfoState = .stateSuccess
  568. // chatModel.chatResult = "/Users/kdanmobile/Desktop/Quick Start Guide v1.3.0.pdf"
  569. // self.aiChatView.reloadData()
  570. // self.aiTypeItemView.reloadData()
  571. // self.aiInfoInputView.reloadData()
  572. //
  573. // }
  574. // }
  575. KMAIRequestServerManager.defaultManager.aiTranslationFileTranslateHandle(fileKey: chatModel.chatResult,
  576. from: chatModel.translateFromLanguage,
  577. to: chatModel.translateToLanguage) { wrapper in
  578. DispatchQueue.main.async {
  579. AIChatInfoManager.defaultManager.isAILoading = false
  580. let resultStr = wrapper.content
  581. chatModel.chatResult = resultStr
  582. chatModel.chatInfoState = wrapper.success ? .stateSuccess : .stateFailed
  583. self.aiChatView.reloadData()
  584. self.aiTypeItemView.reloadData()
  585. self.aiInfoInputView.reloadData()
  586. }
  587. }
  588. }
  589. //MARK: AIInfoInputViewDelegate
  590. func ai_InputViewDidChooseCurFile(aiInputView: AIInfoInputView) {
  591. guard let callBack = self.chooseCurFileHandle else {
  592. return
  593. }
  594. callBack(self)
  595. }
  596. //MARK: NSWindowDelegate
  597. func windowDidBecomeMain(_ notification: Notification) {
  598. self.aiInfoInputView.reloadData()
  599. }
  600. func windowWillClose(_ notification: Notification) {
  601. AINewConfigWindowController.currentWindowController = nil
  602. }
  603. @objc func themeChange() {
  604. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  605. self.refreshViewColor()
  606. }
  607. }
  608. }