KeyboardViewController.swift 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. //
  2. // KeyboardViewController.swift
  3. // AiKeyboard
  4. //
  5. // Created by Destiny on 2025/4/23.
  6. //
  7. import UIKit
  8. import Lottie
  9. import SnapKit
  10. import MarqueeLabel
  11. enum KeyboardType: Int {
  12. case help = 0 // 帮聊
  13. case teach = 1 // 教你说
  14. case prologue = 2 // 开场白
  15. }
  16. class KeyboardViewController: UIInputViewController {
  17. struct UX {
  18. static let keyboardHeight = 292.0
  19. }
  20. // 选择的键盘类型
  21. var chooseType: KeyboardType = .help {
  22. didSet {
  23. self.updateMainViewUI()
  24. }
  25. }
  26. // 键盘列表
  27. var keyboardList: [KeyboardModel]?
  28. // 选择的键盘
  29. var chooseKeyboard: KeyboardModel?
  30. // 人设列表
  31. var characterList: [CharacterModel]?
  32. // 开场白列表
  33. var prologueList: [PrologueModel]?
  34. // 开始持续删除
  35. private var deleteTimer: Timer?
  36. private var deleteAcceleration: TimeInterval = 0.1
  37. var heightConstriaint: NSLayoutConstraint?
  38. lazy var bgImageView: UIImageView = {
  39. let imageView = UIImageView()
  40. imageView.image = UIImage(named: "keyboard_bg")
  41. return imageView
  42. }()
  43. lazy var menuBtn: UIButton = {
  44. let button = UIButton()
  45. button.setImage(UIImage(named: "keyboard_menu_btn"), for: .normal)
  46. button.addTarget(self, action: #selector(menuBtnClickAction), for: .touchUpInside)
  47. return button
  48. }()
  49. lazy var heartAnimation: LottieAnimationView = {
  50. let animate = LottieAnimationView(name: "heart")
  51. animate.loopMode = .loop
  52. animate.backgroundColor = .clear
  53. return animate
  54. }()
  55. lazy var heartLabel: UILabel = {
  56. let label = UILabel()
  57. label.text = "30%"
  58. label.font = .boldSystemFont(ofSize: 10)
  59. label.textColor = .white
  60. return label
  61. }()
  62. lazy var exchangeBtn: UIButton = {
  63. let button = UIButton()
  64. button.setImage(UIImage(named: "keyboard_exchange_btn"), for: .normal)
  65. return button
  66. }()
  67. lazy var chooseView: UIView = {
  68. let view = UIView()
  69. view.backgroundColor = .white
  70. view.layer.cornerRadius = 17
  71. return view
  72. }()
  73. lazy var functionView: UIView = {
  74. let view = UIView()
  75. view.backgroundColor = .hexStringColor(hexString: "#DDCFFD")
  76. view.layer.cornerRadius = 16
  77. view.isUserInteractionEnabled = true
  78. let tap = UITapGestureRecognizer(target: self, action: #selector(functionBtnClickAction))
  79. view.addGestureRecognizer(tap)
  80. return view
  81. }()
  82. lazy var functionLabel: UILabel = {
  83. let label = UILabel()
  84. label.text = "帮聊"
  85. label.font = .boldSystemFont(ofSize: 12)
  86. label.textColor = .hexStringColor(hexString: "#000000", alpha: 0.8)
  87. return label
  88. }()
  89. lazy var arrowIcon: UIImageView = {
  90. let imageView = UIImageView()
  91. imageView.image = UIImage(named: "icon_arrow_down")
  92. return imageView
  93. }()
  94. lazy var userChangeBtn: UIButton = {
  95. let btn = UIButton()
  96. btn.setTitle("小蕾", for: .normal)
  97. btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium)
  98. btn.setTitleColor(.hexStringColor(hexString: "#000000").withAlphaComponent(0.8), for: .normal)
  99. btn.setImage(UIImage(named: "keyboard_user_change_icon"), for: .normal)
  100. btn.setImageTitleLayout(.imgRight, spacing: 8)
  101. btn.addTarget(self, action: #selector(changeBtnClickAction), for: .touchUpInside)
  102. return btn
  103. }()
  104. lazy var userChangeView: UIView = {
  105. let view = UIView()
  106. let tap = UITapGestureRecognizer(target: self, action: #selector(changeBtnClickAction))
  107. view.addGestureRecognizer(tap)
  108. return view
  109. }()
  110. lazy var userChangeLabel: MarqueeLabel = {
  111. let label = MarqueeLabel(frame: .zero, duration: 3.0, fadeLength: 0)
  112. label.type = .leftRight
  113. label.text = "通用键盘"
  114. label.font = .systemFont(ofSize: 12)
  115. label.textColor = .hexStringColor(hexString: "#000000")
  116. label.textAlignment = .center
  117. return label
  118. }()
  119. lazy var userChangeIcon: UIImageView = {
  120. let icon = UIImageView()
  121. icon.image = UIImage(named: "keyboard_user_change_icon")
  122. return icon
  123. }()
  124. lazy var helpView: KeyboardHelpView = {
  125. let view = KeyboardHelpView()
  126. view.delegate = self
  127. view.helpDelegate = self
  128. return view
  129. }()
  130. lazy var teachView: KeyboardTeachView = {
  131. let view = KeyboardTeachView()
  132. view.delegate = self
  133. view.teachDelegate = self
  134. view.isHidden = true
  135. return view
  136. }()
  137. lazy var prologueView: KeyboardPrologueView = {
  138. let view = KeyboardPrologueView()
  139. view.delegate = self
  140. view.prologueDelegate = self
  141. view.isHidden = true
  142. return view
  143. }()
  144. lazy var exchangeView: KeyboardExchangeView = {
  145. let view = KeyboardExchangeView()
  146. view.isHidden = true
  147. view.delegate = self
  148. return view
  149. }()
  150. lazy var menuView: KeyboardMenuView = {
  151. let view = KeyboardMenuView()
  152. view.isHidden = true
  153. view.delegate = self
  154. return view
  155. }()
  156. lazy var loginView: KeyboardLoginTipView = {
  157. let view = KeyboardLoginTipView()
  158. view.isHidden = true
  159. view.loginBtnClosure = {
  160. self.navigateToLogin()
  161. }
  162. return view
  163. }()
  164. var nowShowView: UIView?
  165. override func viewWillAppear(_ animated: Bool) {
  166. super.viewWillAppear(animated)
  167. self.prepareHeightConstraint()
  168. }
  169. override func viewDidLoad() {
  170. super.viewDidLoad()
  171. setUI()
  172. KeyboardApi.initParams()
  173. requestKeyboardList()
  174. requestPrologueList()
  175. startMonitoringPasteboard()
  176. // self.nextKeyboardButton.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
  177. // self.nextKeyboardButton.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
  178. }
  179. override func viewWillLayoutSubviews() {
  180. super.viewWillLayoutSubviews()
  181. }
  182. override func updateViewConstraints() {
  183. super.updateViewConstraints()
  184. if self.view.frame.size.width == 0 && self.view.frame.size.height == 0 {
  185. return
  186. }
  187. self.prepareHeightConstraint()
  188. }
  189. override func textWillChange(_ textInput: UITextInput?) {
  190. // The app is about to change the document's contents. Perform any preparation here.
  191. }
  192. override func textDidChange(_ textInput: UITextInput?) {
  193. // The app has just changed the document's contents, the document context has been updated.
  194. var textColor: UIColor
  195. let proxy = self.textDocumentProxy
  196. if proxy.keyboardAppearance == UIKeyboardAppearance.dark {
  197. textColor = UIColor.white
  198. } else {
  199. textColor = UIColor.black
  200. }
  201. }
  202. func prepareHeightConstraint() {
  203. if self.heightConstriaint == nil {
  204. if let view = self.view {
  205. self.heightConstriaint = NSLayoutConstraint(item: view, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 0.0, constant: UX.keyboardHeight)
  206. self.heightConstriaint?.priority = UILayoutPriority(750)
  207. self.view.addConstraint(self.heightConstriaint!)
  208. }
  209. } else {
  210. self.heightConstriaint?.constant = UX.keyboardHeight
  211. }
  212. }
  213. }
  214. // MARK: - 网络请求
  215. extension KeyboardViewController {
  216. // 获取键盘列表
  217. func requestKeyboardList() {
  218. KeyboardNetworkManager.request(.keyboard_list(params: [:])) { response in
  219. if let keyboardInfos = try? response.mapArray(KeyboardModel.self, atKeyPath: "data.keyboardInfos") {
  220. self.keyboardList = keyboardInfos
  221. self.updateUserChangeBtnUI()
  222. self.requestCharacterList()
  223. print("成功解析数组,数量:\(keyboardInfos.count)")
  224. }
  225. } fail: { code, error in
  226. self.view.toast(text: error)
  227. print(error)
  228. }
  229. }
  230. // 获取键盘人设列表
  231. func requestCharacterList() {
  232. var params: [String: Any] = [String: Any]()
  233. if let chooseKeyboard = self.chooseKeyboard {
  234. params = ["keyboardId": chooseKeyboard.id ?? ""]
  235. }
  236. KeyboardNetworkManager.request(.character_list(params: params)) { response in
  237. if let characterInfos = try? response.mapArray(CharacterModel.self, atKeyPath: "data.characterInfos") {
  238. self.characterList = characterInfos
  239. self.updateCharacterUI()
  240. print("成功解析数组,数量:\(characterInfos.count)")
  241. }
  242. } fail: { code, error in
  243. self.view.toast(text: error)
  244. print(error)
  245. }
  246. }
  247. // 获取键盘人设列表
  248. func requestPrologueList() {
  249. KeyboardNetworkManager.request(.prologue_list(params: [:])) { response in
  250. if let prologueList = try? response.mapArray(PrologueModel.self, atKeyPath: "data.prologues") {
  251. self.prologueList = prologueList
  252. self.updatePrologueUI()
  253. }
  254. } fail: { code, error in
  255. self.view.toast(text: error)
  256. print(error)
  257. }
  258. }
  259. // 选择键盘
  260. func requestChooseKeyboard(keyboardId: String, success: @escaping (() -> Void)) {
  261. var params: [String: Any] = [String: Any]()
  262. params = ["keyboardId": keyboardId]
  263. KeyboardNetworkManager.request(.keyboard_choose(params: params)) { response in
  264. self.view.toast(text: "保存成功")
  265. success()
  266. } fail: { code, error in
  267. self.view.toast(text: error)
  268. print(error)
  269. }
  270. }
  271. // 请求获取超会回
  272. func requestSuperReply(characterId: String, content: String, complete: @escaping ((String) -> ())) {
  273. var params: [String: Any] = [String: Any]()
  274. params = ["keyboardId": self.chooseKeyboard?.id ?? "",
  275. "characterId": characterId,
  276. "content": content]
  277. KeyboardNetworkManager.request(.chat_super_reply(params: params)) { response in
  278. if let contentModel = try? response.mapObject(ReplyModel.self, atKeyPath: "data") {
  279. complete(contentModel.content ?? "")
  280. } else {
  281. complete("")
  282. }
  283. } fail: { code, error in
  284. self.view.toast(text: error)
  285. print(error)
  286. complete("")
  287. if code == 1006 {
  288. self.popLoginView()
  289. }
  290. }
  291. }
  292. // 请求获取超会说
  293. func requestSuperSpeak(characterId: String, content: String, complete: @escaping (([String]) -> ())) {
  294. var params: [String: Any] = [String: Any]()
  295. params = ["keyboardId": self.chooseKeyboard?.id ?? "",
  296. "characterId": characterId,
  297. "content": content]
  298. KeyboardNetworkManager.request(.chat_super_speak(params: params)) { response in
  299. if let contentModel = try? response.mapObject(SpeakModel.self, atKeyPath: "data"), let list = contentModel.list {
  300. complete(list)
  301. } else {
  302. complete([String]())
  303. }
  304. } fail: { code, error in
  305. self.view.toast(text: error)
  306. print(error)
  307. complete([String]())
  308. if code == 1006 {
  309. self.popLoginView()
  310. }
  311. }
  312. }
  313. // 请求获取超会说
  314. func requestSuperPrologue(name: String, complete: @escaping (([String]) -> ())) {
  315. var params: [String: Any] = [String: Any]()
  316. params = ["name": name]
  317. KeyboardNetworkManager.request(.chat_super_prologue(params: params)) { response in
  318. if let contentModel = try? response.mapObject(SpeakModel.self, atKeyPath: "data"), let list = contentModel.list {
  319. complete(list)
  320. } else {
  321. complete([String]())
  322. }
  323. } fail: { code, error in
  324. self.view.toast(text: error)
  325. print(error)
  326. complete([String]())
  327. if code == 1006 {
  328. self.popLoginView()
  329. }
  330. }
  331. }
  332. }
  333. // MARK: - 点击事件
  334. extension KeyboardViewController: KeyboardMenuViewDelegate, KeyboardExchangeViewDelegate {
  335. // 功能按钮选择点击
  336. @objc func functionBtnClickAction() {
  337. KeyboardFunctionPopView.show(view: self.view, selectType: self.chooseType) { type in
  338. self.chooseType = type
  339. }
  340. }
  341. // 菜单按钮点击
  342. @objc func menuBtnClickAction() {
  343. clearPopView()
  344. self.menuView.isHidden = false
  345. }
  346. // 菜单按钮返回
  347. func menuBackBtnClickAction() {
  348. clearPopView()
  349. self.nowShowView?.isHidden = false
  350. }
  351. // 会员按钮点击
  352. func vipBtnClickAction() {
  353. navigateToMembership()
  354. }
  355. // 跳转到主应用的登录页面
  356. @objc func navigateToLogin() {
  357. let url = URL(string: "com.qihuan.zhuiaijianpan:///login")!
  358. openURL(url)
  359. }
  360. // 跳转到主应用的会员页面
  361. @objc func navigateToMembership() {
  362. let url = URL(string: "com.qihuan.zhuiaijianpan:///member")!
  363. openURL(url)
  364. }
  365. // 通用的打开URL方法
  366. private func openURL(_ url: URL) {
  367. var responder = self as UIResponder?
  368. while (responder != nil && !(responder is UIApplication)) {
  369. responder = responder?.next
  370. }
  371. if responder != nil {
  372. let selectorOpenURL = sel_registerName("openURL:")
  373. if responder!.responds(to: selectorOpenURL) {
  374. responder?.perform(selectorOpenURL, with: url)
  375. }
  376. }
  377. // 不知道为什么无法使用
  378. // self.extensionContext?.open(url, completionHandler: nil)
  379. }
  380. // 选择键盘按钮点击
  381. @objc func changeBtnClickAction() {
  382. clearPopView()
  383. self.exchangeView.keyboardList = self.keyboardList
  384. self.exchangeView.isHidden = false
  385. }
  386. // 选择键盘后返回
  387. func exchangeViewBackClickAction() {
  388. clearPopView()
  389. self.nowShowView?.isHidden = false
  390. }
  391. // 点击保存按钮
  392. func exchangeViewSaveClickAction(keyboardList: [KeyboardModel], success: @escaping (() -> ())) {
  393. var keyboardId = ""
  394. for keyboard in keyboardList {
  395. if keyboard.isChoose == true {
  396. keyboardId = keyboard.id ?? ""
  397. break
  398. }
  399. }
  400. requestChooseKeyboard(keyboardId: keyboardId) {
  401. self.keyboardList = keyboardList
  402. for keyboard in keyboardList {
  403. if keyboard.isChoose == true {
  404. self.chooseKeyboard = keyboard
  405. break
  406. }
  407. }
  408. success()
  409. self.userChangeLabel.text = self.chooseKeyboard?.name
  410. self.clearPopView()
  411. self.nowShowView?.isHidden = false
  412. }
  413. }
  414. }
  415. extension KeyboardViewController: KeyboardHelpViewDelegate, KeyboardTeachViewDelegate, KeyboardPrologueViewDelegate {
  416. // 帮聊点击cell
  417. func helpCollectionViewDidSelectItem(characterId: String, content: String, complete: @escaping (() -> ())) {
  418. self.requestSuperReply(characterId: characterId, content: content) { text in
  419. self.insertText(text)
  420. complete()
  421. }
  422. }
  423. // 教你说点击cell
  424. func teachCollectionViewDidSelectItem(characterId: String, content: String, complete: @escaping (([String]) -> ())) {
  425. self.requestSuperSpeak(characterId: characterId, content: content) { list in
  426. complete(list)
  427. }
  428. }
  429. // 教你说点击 TableViewCell
  430. func teachTableViewDidSelectItem(content: String) {
  431. self.insertText(content)
  432. }
  433. // 开场白点击cell
  434. func prologueCollectionViewDidSelectItem(name: String, complete: @escaping (([String]) -> ())) {
  435. self.requestSuperPrologue(name: name) { list in
  436. complete(list)
  437. }
  438. }
  439. // 开场白点击 TableViewCell
  440. func prologueTableViewDidSelectItem(content: String) {
  441. self.insertText(content)
  442. }
  443. }
  444. // MARK: - 处理键盘操作
  445. extension KeyboardViewController: KeyboardBaseViewDelegate {
  446. // 插入文字
  447. func insertText(_ text: String) {
  448. self.textDocumentProxy.insertText(text)
  449. }
  450. // 点击粘贴按钮
  451. func pasteBtnClickAction() {
  452. detectPasteboardPermissionAlert { isShowing in
  453. if isShowing {
  454. print("系统正在显示剪贴板权限弹窗")
  455. self.view.toast(text: "请允许访问剪贴板")
  456. }
  457. if let content = self.getPasteboardContent() {
  458. print("获取到剪贴板内容: \(content)")
  459. self.view.toast(text: "获取到剪贴板内容")
  460. self.helpView.setPasteStr(content: content)
  461. self.teachView.setPasteStr(content: content)
  462. } else {
  463. print("无法获取剪贴板内容")
  464. self.view.toast(text: "无法获取剪贴板内容")
  465. }
  466. }
  467. }
  468. // 删除按钮
  469. func deleteBtnClickAction() {
  470. self.textDocumentProxy.deleteBackward()
  471. }
  472. // 清除按钮
  473. func clearBtnClickAction() {
  474. // 获取当前文本
  475. let proxy = self.textDocumentProxy
  476. // 清空所有文本
  477. for _ in 0..<100 {
  478. proxy.deleteBackward()
  479. }
  480. }
  481. // 发送按钮
  482. func sendBtnClickAction() {
  483. self.textDocumentProxy.insertText("\n")
  484. }
  485. func deleteBtnLongPressBegin() {
  486. // 停止已有的定时器
  487. stopContinuousDelete()
  488. // 创建新的定时器,初始间隔为0.5秒
  489. deleteTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(continuousDeleteAction), userInfo: nil, repeats: false)
  490. }
  491. func deleteBtnLongPressEnd() {
  492. stopContinuousDelete()
  493. }
  494. // 停止删除
  495. func stopContinuousDelete() {
  496. deleteTimer?.invalidate()
  497. deleteTimer = nil
  498. deleteAcceleration = 0.1 // 重置加速度
  499. }
  500. @objc func continuousDeleteAction() {
  501. // 执行删除操作
  502. self.textDocumentProxy.deleteBackward()
  503. // 停止当前定时器
  504. deleteTimer?.invalidate()
  505. // 加速删除(最快0.05秒一次)
  506. let newInterval = max(0.05, 0.5 - deleteAcceleration)
  507. deleteAcceleration += 0.05 // 每次加速0.05秒
  508. // 创建新的更快的定时器
  509. deleteTimer = Timer.scheduledTimer(timeInterval: newInterval, target: self, selector: #selector(continuousDeleteAction), userInfo: nil, repeats: false)
  510. }
  511. // 监听剪贴板变化
  512. func startMonitoringPasteboard() {
  513. // 记录当前剪贴板变化计数
  514. var initialChangeCount = UIPasteboard.general.changeCount
  515. // 记录上一次的剪贴板内容
  516. var lastPasteboardContent: String? = UIPasteboard.general.string
  517. // 创建定时器定期检查剪贴板变化
  518. Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] timer in
  519. guard let self = self else {
  520. timer.invalidate()
  521. return
  522. }
  523. let currentChangeCount = UIPasteboard.general.changeCount
  524. if currentChangeCount != initialChangeCount {
  525. // 剪贴板计数已变化,检查内容是否真的变化
  526. if let copiedString = UIPasteboard.general.string {
  527. // 只有当内容真的不同时才处理
  528. if !copiedString.isEmpty {
  529. print("检测到新复制的内容: \(copiedString)")
  530. // 更新记录的内容和计数
  531. lastPasteboardContent = copiedString
  532. initialChangeCount = currentChangeCount
  533. // 处理复制的内容
  534. self.handleCopiedContent(copiedString)
  535. } else {
  536. // 内容相同或为空,只更新计数
  537. initialChangeCount = currentChangeCount
  538. print("剪贴板计数变化但内容未变或为空")
  539. }
  540. } else {
  541. // 剪贴板内容为nil,更新计数
  542. initialChangeCount = currentChangeCount
  543. lastPasteboardContent = nil
  544. print("剪贴板内容被清空")
  545. }
  546. }
  547. }
  548. }
  549. // 处理复制的内容
  550. func handleCopiedContent(_ content: String) {
  551. self.helpView.setPasteStr(content: content)
  552. self.teachView.setPasteStr(content: content)
  553. }
  554. // 检查键盘权限
  555. func checkPasteboardPermission() -> Bool {
  556. var hasPasteboardPermission = false
  557. // iOS 14及以上版本需要检查权限
  558. if #available(iOS 14.0, *) {
  559. // 尝试读取剪贴板内容来检查权限
  560. let pasteboard = UIPasteboard.general
  561. if let _ = pasteboard.string {
  562. hasPasteboardPermission = true
  563. print("键盘扩展有剪贴板访问权限")
  564. } else {
  565. hasPasteboardPermission = false
  566. print("键盘扩展没有剪贴板访问权限")
  567. }
  568. } else {
  569. // iOS 14以下版本默认有权限
  570. hasPasteboardPermission = true
  571. }
  572. return hasPasteboardPermission
  573. }
  574. // 检测系统是否弹出剪贴板权限弹窗
  575. func detectPasteboardPermissionAlert(completion: @escaping (Bool) -> Void) {
  576. // 记录访问前的时间
  577. let startTime = Date()
  578. // 尝试访问剪贴板
  579. let _ = UIPasteboard.general.string
  580. // 检查访问后的时间延迟
  581. let timeDelay = Date().timeIntervalSince(startTime)
  582. // 如果访问剪贴板的时间超过一定阈值,可能是因为系统弹出了权限弹窗
  583. // 通常正常访问剪贴板的时间应该很短,如果超过100毫秒,可能是弹出了弹窗
  584. if timeDelay > 0.1 {
  585. completion(true)
  586. } else {
  587. completion(false)
  588. }
  589. }
  590. // 获取剪贴板内容
  591. func getPasteboardContent() -> String? {
  592. let pasteboard = UIPasteboard.general
  593. return pasteboard.string
  594. }
  595. }
  596. extension KeyboardViewController {
  597. // 跳转登录页
  598. func popLoginView() {
  599. self.clearPopView()
  600. self.loginView.isHidden = false
  601. }
  602. // 关闭其他弹出页
  603. func clearPopView() {
  604. self.menuView.isHidden = true
  605. self.exchangeView.isHidden = true
  606. self.helpView.isHidden = true
  607. self.teachView.isHidden = true
  608. self.prologueView.isHidden = true
  609. }
  610. // 更新主要界面
  611. func updateMainViewUI() {
  612. clearPopView()
  613. switch chooseType {
  614. case .help:
  615. // self.helpView.characterList = self.characterList
  616. self.helpView.isHidden = false
  617. self.nowShowView = self.helpView
  618. self.functionLabel.text = "帮聊"
  619. break
  620. case .teach:
  621. // self.teachView.characterList = self.characterList
  622. self.teachView.isHidden = false
  623. self.nowShowView = self.teachView
  624. self.functionLabel.text = "教你说"
  625. break
  626. case .prologue:
  627. self.prologueView.isHidden = false
  628. self.nowShowView = self.prologueView
  629. self.functionLabel.text = "开场白"
  630. break
  631. }
  632. }
  633. // 更新人设列表
  634. func updateCharacterUI() {
  635. self.helpView.characterList = self.characterList
  636. self.teachView.characterList = self.characterList
  637. }
  638. // 更新开场白
  639. func updatePrologueUI() {
  640. self.prologueView.prologueList = self.prologueList
  641. }
  642. // 更新键盘选择按钮
  643. func updateUserChangeBtnUI() {
  644. if self.keyboardList?.count == 1 {
  645. self.keyboardList?[0].isChoose = true
  646. self.chooseKeyboard = self.keyboardList?.first
  647. } else {
  648. if let keyboardList = self.keyboardList {
  649. for keyboard in keyboardList {
  650. if keyboard.isChoose == true {
  651. self.chooseKeyboard = keyboard
  652. }
  653. }
  654. }
  655. }
  656. if let chooseKeyboard = self.chooseKeyboard {
  657. self.userChangeLabel.text = chooseKeyboard.name
  658. }
  659. }
  660. func setUI() {
  661. self.view.addSubview(bgImageView)
  662. bgImageView.snp.makeConstraints { make in
  663. make.edges.equalToSuperview()
  664. }
  665. self.view.addSubview(menuBtn)
  666. menuBtn.snp.makeConstraints { make in
  667. make.size.equalTo(CGSize(width: 32, height: 32))
  668. make.left.equalTo(13)
  669. make.top.equalTo(17)
  670. }
  671. self.view.addSubview(heartAnimation)
  672. heartAnimation.snp.makeConstraints { make in
  673. make.size.equalTo(CGSize(width: 35, height: 30))
  674. make.right.equalTo(-10)
  675. make.centerY.equalTo(menuBtn.snp.centerY)
  676. }
  677. heartAnimation.play()
  678. self.view.addSubview(heartLabel)
  679. heartLabel.snp.makeConstraints { make in
  680. make.center.equalTo(heartAnimation.center)
  681. }
  682. self.view.addSubview(exchangeBtn)
  683. exchangeBtn.snp.makeConstraints { make in
  684. make.size.equalTo(CGSize(width: 34, height: 34))
  685. make.right.equalTo(heartAnimation.snp.left).offset(-10)
  686. make.centerY.equalTo(menuBtn.snp.centerY)
  687. }
  688. self.view.addSubview(teachView)
  689. teachView.snp.makeConstraints { make in
  690. make.left.right.bottom.equalTo(0)
  691. make.top.equalTo(60)
  692. }
  693. self.view.addSubview(helpView)
  694. helpView.snp.makeConstraints { make in
  695. make.left.right.bottom.equalTo(0)
  696. make.top.equalTo(60)
  697. }
  698. self.view.addSubview(prologueView)
  699. prologueView.snp.makeConstraints { make in
  700. make.left.right.bottom.equalTo(0)
  701. make.top.equalTo(menuBtn.snp.bottom)
  702. }
  703. self.view.addSubview(chooseView)
  704. chooseView.snp.makeConstraints { make in
  705. make.width.equalTo(147)
  706. make.height.equalTo(34)
  707. make.left.equalTo(menuBtn.snp.right).offset(9)
  708. make.centerY.equalTo(menuBtn.snp.centerY)
  709. }
  710. self.view.addSubview(exchangeView)
  711. exchangeView.snp.makeConstraints { make in
  712. make.top.equalTo(menuBtn.snp.bottom)
  713. make.left.right.bottom.equalTo(0)
  714. }
  715. self.view.addSubview(menuView)
  716. menuView.snp.makeConstraints { make in
  717. make.left.right.bottom.equalTo(0)
  718. make.top.equalTo(menuBtn.snp.bottom)
  719. }
  720. self.view.addSubview(loginView)
  721. loginView.snp.makeConstraints { make in
  722. make.top.left.right.bottom.equalTo(0)
  723. }
  724. chooseView.addSubview(functionView)
  725. functionView.snp.makeConstraints { make in
  726. make.top.left.equalTo(1)
  727. make.bottom.equalTo(-1)
  728. make.width.equalTo(85)
  729. }
  730. functionView.addSubview(functionLabel)
  731. functionLabel.snp.makeConstraints { make in
  732. make.left.equalTo(12)
  733. make.centerY.equalToSuperview()
  734. }
  735. functionView.addSubview(arrowIcon)
  736. arrowIcon.snp.makeConstraints { make in
  737. make.size.equalTo(CGSize(width: 18, height: 18))
  738. make.centerY.equalToSuperview()
  739. make.right.equalTo(-5)
  740. }
  741. chooseView.addSubview(userChangeView)
  742. userChangeView.snp.makeConstraints { make in
  743. make.left.equalTo(functionView.snp.right)
  744. make.right.equalToSuperview()
  745. make.top.bottom.equalTo(0)
  746. }
  747. userChangeView.addSubview(userChangeIcon)
  748. userChangeIcon.snp.makeConstraints { make in
  749. make.size.equalTo(CGSize(width: 12, height: 12))
  750. make.centerY.equalToSuperview()
  751. make.right.equalTo(-8)
  752. }
  753. userChangeView.addSubview(userChangeLabel)
  754. userChangeLabel.snp.makeConstraints { make in
  755. make.right.equalTo(userChangeIcon.snp.left).offset(-4)
  756. make.left.equalTo(4)
  757. make.centerY.equalToSuperview()
  758. }
  759. // chooseView.addSubview(userChangeBtn)
  760. // userChangeBtn.snp.makeConstraints { make in
  761. // make.left.equalTo(functionView.snp.right)
  762. // make.right.equalToSuperview()
  763. // make.top.bottom.equalTo(0)
  764. // }
  765. self.nowShowView = self.helpView
  766. }
  767. }