NCAssistantTask.swift 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. //
  2. // NCAssistantModel.swift
  3. // Nextcloud
  4. //
  5. // Created by Milen on 08.04.24.
  6. // Copyright © 2024 Marino Faggiana. All rights reserved.
  7. //
  8. import Foundation
  9. import NextcloudKit
  10. import SwiftUI
  11. class NCAssistantTask: ObservableObject {
  12. @Published var types: [NKTextProcessingTaskType] = []
  13. @Published var filteredTasks: [NKTextProcessingTask] = []
  14. @Published var selectedType: NKTextProcessingTaskType?
  15. @Published var selectedTask: NKTextProcessingTask?
  16. @Published var hasError: Bool = false
  17. @Published var isLoading: Bool = false
  18. private var tasks: [NKTextProcessingTask] = []
  19. private let excludedTypeIds = ["OCA\\ContextChat\\TextProcessing\\ContextChatTaskType"]
  20. init() {
  21. load()
  22. }
  23. func load() {
  24. loadAllTypes()
  25. }
  26. func filterTasks(ofType type: NKTextProcessingTaskType?) {
  27. if let type {
  28. self.filteredTasks = tasks.filter({ $0.type == type.id })
  29. } else {
  30. self.filteredTasks = tasks
  31. }
  32. self.filteredTasks = filteredTasks.sorted(by: { $0.completionExpectedAt ?? 0 > $1.completionExpectedAt ?? 0 })
  33. }
  34. func selectTaskType(_ type: NKTextProcessingTaskType?) {
  35. selectedType = type
  36. filterTasks(ofType: self.selectedType)
  37. }
  38. func selectTask(_ task: NKTextProcessingTask) {
  39. selectedTask = task
  40. guard let id = task.id else { return }
  41. isLoading = true
  42. NextcloudKit.shared.textProcessingGetTask(taskId: id) { _, task, _, error in
  43. self.isLoading = false
  44. if error != .success {
  45. self.hasError = true
  46. return
  47. }
  48. self.selectedTask = task
  49. }
  50. }
  51. func scheduleTask(input: String) {
  52. isLoading = true
  53. NextcloudKit.shared.textProcessingSchedule(input: input, typeId: selectedType?.id ?? "", identifier: "assistant") { _, task, _, error in
  54. self.isLoading = false
  55. if error != .success {
  56. self.hasError = true
  57. return
  58. }
  59. guard let task else { return }
  60. withAnimation {
  61. self.tasks.insert(task, at: 0)
  62. self.filteredTasks.insert(task, at: 0)
  63. }
  64. }
  65. }
  66. func deleteTask(_ task: NKTextProcessingTask) {
  67. guard let id = task.id else { return }
  68. isLoading = true
  69. NextcloudKit.shared.textProcessingDeleteTask(taskId: id) { _, task, _, error in
  70. self.isLoading = false
  71. if error != .success {
  72. self.hasError = true
  73. return
  74. }
  75. withAnimation {
  76. self.tasks.removeAll(where: { $0.id == task?.id })
  77. self.filteredTasks.removeAll(where: { $0.id == task?.id })
  78. }
  79. }
  80. }
  81. private func loadAllTypes() {
  82. isLoading = true
  83. NextcloudKit.shared.textProcessingGetTypes { _, types, _, error in
  84. self.isLoading = false
  85. if error != .success {
  86. self.hasError = true
  87. return
  88. }
  89. guard let filteredTypes = types?.filter({ !self.excludedTypeIds.contains($0.id ?? "")}), !filteredTypes.isEmpty else { return }
  90. withAnimation {
  91. self.types = filteredTypes
  92. }
  93. if self.selectedType == nil {
  94. self.selectTaskType(filteredTypes.first)
  95. }
  96. self.loadAllTasks()
  97. }
  98. }
  99. private func loadAllTasks(appId: String = "assistant") {
  100. isLoading = true
  101. NextcloudKit.shared.textProcessingTaskList(appId: appId) { _, tasks, _, error in
  102. self.isLoading = false
  103. if error != .success {
  104. self.hasError = true
  105. return
  106. }
  107. guard let tasks = tasks else { return }
  108. self.tasks = tasks
  109. self.filterTasks(ofType: self.selectedType)
  110. }
  111. }
  112. }
  113. extension NCAssistantTask {
  114. public func loadDummyData() {
  115. let loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
  116. var tasks: [NKTextProcessingTask] = []
  117. for index in 1...10 {
  118. tasks.append(NKTextProcessingTask(id: index, type: "OCP\\TextProcessing\\FreePromptTaskType", status: index, userId: "christine", appId: "assistant", input: loremIpsum, output: loremIpsum, identifier: "", completionExpectedAt: 1712666412))
  119. }
  120. self.types = [
  121. NKTextProcessingTaskType(id: "1", name: "Free Prompt", description: ""),
  122. NKTextProcessingTaskType(id: "2", name: "Summarize", description: ""),
  123. NKTextProcessingTaskType(id: "3", name: "Generate headline", description: ""),
  124. NKTextProcessingTaskType(id: "4", name: "Reformulate", description: "")
  125. ]
  126. self.tasks = tasks
  127. self.filteredTasks = tasks
  128. self.selectedType = types[0]
  129. self.selectedTask = filteredTasks[0]
  130. }
  131. }
  132. extension NKTextProcessingTask {
  133. struct StatusInfo {
  134. let stringKey, imageSystemName: String
  135. }
  136. var statusInfo: StatusInfo {
  137. return switch status {
  138. case 1: StatusInfo(stringKey: "_assistant_task_scheduled_", imageSystemName: "clock")
  139. case 2: StatusInfo(stringKey: "_assistant_task_in_progress_", imageSystemName: "clock.badge")
  140. case 3: StatusInfo(stringKey: "_assistant_task_completed_", imageSystemName: "checkmark.circle")
  141. case 4: StatusInfo(stringKey: "_assistant_task_failed_", imageSystemName: "exclamationmark.circle")
  142. default: StatusInfo(stringKey: "_assistant_task_unknown_", imageSystemName: "questionmark.circle")
  143. }
  144. }
  145. }