123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- //
- // NCAssistant.swift
- // Nextcloud
- //
- // Created by Milen on 03.04.24.
- // Copyright © 2024 Marino Faggiana. All rights reserved.
- //
- import SwiftUI
- import NextcloudKit
- import PopupView
- struct NCAssistant: View {
- @EnvironmentObject var model: NCAssistantTask
- @State var presentNewTaskDialog = false
- @State var input = ""
- @Environment(\.presentationMode) var presentationMode
- var body: some View {
- NavigationView {
- ZStack {
- TaskList()
- if model.types.isEmpty, !model.isLoading {
- NCAssistantEmptyView(titleKey: "_no_types_", subtitleKey: "_no_types_subtitle_")
- } else if model.filteredTasks.isEmpty, !model.isLoading {
- NCAssistantEmptyView(titleKey: "_no_tasks_", subtitleKey: "_create_task_subtitle_")
- }
- }
- .toolbar {
- ToolbarItem(placement: .topBarLeading) {
- Button(action: {
- presentationMode.wrappedValue.dismiss()
- }) {
- Image(systemName: "xmark")
- .font(Font.system(.body).weight(.light))
- .foregroundStyle(Color(NCBrandColor.shared.iconImageColor))
- }
- }
- ToolbarItem(placement: .topBarTrailing) {
- NavigationLink(destination: NCAssistantCreateNewTask()) {
- Image(systemName: "plus")
- .font(Font.system(.body).weight(.light))
- .foregroundStyle(Color(NCBrandColor.shared.iconImageColor))
- }
- .disabled(model.selectedType == nil)
- }
- }
- .navigationBarTitleDisplayMode(.inline)
- .navigationTitle(NSLocalizedString("_assistant_", comment: ""))
- .frame(maxWidth: .infinity, maxHeight: .infinity)
- .safeAreaInset(edge: .top, spacing: -10) {
- ScrollViewReader { scrollProxy in
- ScrollView(.horizontal, showsIndicators: false) {
- LazyHStack {
- ForEach(model.types, id: \.id) { type in
- TypeButton(taskType: type, scrollProxy: scrollProxy)
- }
- }
- .padding(20)
- .frame(height: 50)
- }
- }
- }
- }
- .navigationViewStyle(.stack)
- .popup(isPresented: $model.hasError) {
- Text(NSLocalizedString("_error_occurred_", comment: ""))
- .padding()
- .background(.red)
- .cornerRadius(30.0)
- } customize: {
- $0
- .type(.floater())
- .autohideIn(2)
- .position(.bottom)
- }
- .accentColor(Color(NCBrandColor.shared.iconImageColor))
- .environmentObject(model)
- }
- }
- #Preview {
- let model = NCAssistantTask(controller: nil)
- return NCAssistant()
- .environmentObject(model)
- .onAppear {
- model.loadDummyData()
- }
- }
- struct TaskList: View {
- @EnvironmentObject var model: NCAssistantTask
- var body: some View {
- List(model.filteredTasks, id: \.id) { task in
- TaskItem(task: task)
- }
- .if(!model.types.isEmpty) { view in
- view.refreshable {
- model.load()
- }
- }
- }
- }
- struct TypeButton: View {
- @EnvironmentObject var model: NCAssistantTask
- let taskType: NKTextProcessingTaskType?
- var scrollProxy: ScrollViewProxy
- var body: some View {
- Button {
- model.selectTaskType(taskType)
- withAnimation {
- scrollProxy.scrollTo(taskType?.id, anchor: .center)
- }
- } label: {
- Text(taskType?.name ?? "").font(.body)
- }
- .padding(.horizontal)
- .padding(.vertical, 7)
- .foregroundStyle(model.selectedType?.id == taskType?.id ? .white : .primary)
- .if(model.selectedType?.id == taskType?.id) { view in
- view.background(Color(NCBrandColor.shared.getElement(account: model.controller?.account)))
- }
- .if(model.selectedType?.id != taskType?.id) { view in
- view.background(.ultraThinMaterial)
- }
- .clipShape(.capsule)
- .overlay(
- RoundedRectangle(cornerRadius: 20, style: RoundedCornerStyle.continuous)
- .stroke(.tertiary.opacity(0.2), lineWidth: 1)
- )
- .id(taskType?.id)
- }
- }
- struct TaskItem: View {
- @EnvironmentObject var model: NCAssistantTask
- @State var showDeleteConfirmation = false
- let task: NKTextProcessingTask
- var body: some View {
- NavigationLink(destination: NCAssistantTaskDetail(task: task)) {
- VStack(alignment: .leading) {
- Text(task.input ?? "")
- .lineLimit(4)
- HStack {
- Label(
- title: {
- Text(NSLocalizedString(task.statusInfo.stringKey, comment: ""))
- },
- icon: {
- Image(systemName: task.statusInfo.imageSystemName)
- .renderingMode(.original)
- .font(Font.system(.body).weight(.light))
- }
- )
- .padding(.top, 1)
- .labelStyle(CustomLabelStyle())
- if let completionExpectedAt = task.completionExpectedAt {
- Text(NCUtility().dateDiff(.init(timeIntervalSince1970: TimeInterval(completionExpectedAt))))
- .frame(maxWidth: .infinity, alignment: .trailing)
- .foregroundStyle(.tertiary)
- }
- }
- }
- .swipeActions {
- Button(NSLocalizedString("_delete_", comment: "")) {
- showDeleteConfirmation = true
- }
- .tint(.red)
- }
- .confirmationDialog("", isPresented: $showDeleteConfirmation) {
- Button(NSLocalizedString("_delete_", comment: ""), role: .destructive) {
- withAnimation {
- model.deleteTask(task)
- }
- }
- }
- }
- }
- }
- private struct CustomLabelStyle: LabelStyle {
- var spacing: Double = 5
- func makeBody(configuration: Configuration) -> some View {
- HStack(spacing: spacing) {
- configuration.icon
- configuration.title
- }
- }
- }
|