From 0ff3803059ab355c9a40404b4105e659e0febf75 Mon Sep 17 00:00:00 2001 From: pboulch Date: Thu, 13 Jul 2023 13:02:39 +0200 Subject: [PATCH] :sparkles: Add description field --- Luto.xcodeproj/project.pbxproj | 12 ++++++ Luto/LutoApp.swift | 6 +-- Luto/Models/Task.swift | 13 +++++++ Luto/UI/MainView.swift | 68 ++++++++++++++++++++-------------- 4 files changed, 68 insertions(+), 31 deletions(-) create mode 100644 Luto/Models/Task.swift diff --git a/Luto.xcodeproj/project.pbxproj b/Luto.xcodeproj/project.pbxproj index d530874..5ed34fe 100644 --- a/Luto.xcodeproj/project.pbxproj +++ b/Luto.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 680A62122A5F475D004C21A4 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 680A62112A5F475D004C21A4 /* ViewExtensions.swift */; }; + 680A62182A600F81004C21A4 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 680A62172A600F81004C21A4 /* Task.swift */; }; 682D06A62A5487D200EA4745 /* LutoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682D06A52A5487D200EA4745 /* LutoApp.swift */; }; 682D06A82A5487D200EA4745 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682D06A72A5487D200EA4745 /* MainView.swift */; }; 682D06AA2A5487D500EA4745 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 682D06A92A5487D500EA4745 /* Assets.xcassets */; }; @@ -37,6 +38,7 @@ /* Begin PBXFileReference section */ 680A62112A5F475D004C21A4 /* ViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtensions.swift; sourceTree = ""; }; + 680A62172A600F81004C21A4 /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; }; 682D06A22A5487D200EA4745 /* Luto.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Luto.app; sourceTree = BUILT_PRODUCTS_DIR; }; 682D06A52A5487D200EA4745 /* LutoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LutoApp.swift; sourceTree = ""; }; 682D06A72A5487D200EA4745 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = ""; }; @@ -85,6 +87,14 @@ path = Utils; sourceTree = ""; }; + 680A62162A600F75004C21A4 /* Models */ = { + isa = PBXGroup; + children = ( + 680A62172A600F81004C21A4 /* Task.swift */, + ); + path = Models; + sourceTree = ""; + }; 682D06992A5487D200EA4745 = { isa = PBXGroup; children = ( @@ -108,6 +118,7 @@ 682D06A42A5487D200EA4745 /* Luto */ = { isa = PBXGroup; children = ( + 680A62162A600F75004C21A4 /* Models */, 683805182A57354900CEF29C /* UI */, 682D06A52A5487D200EA4745 /* LutoApp.swift */, 682D06A92A5487D500EA4745 /* Assets.xcassets */, @@ -283,6 +294,7 @@ files = ( 682D06A82A5487D200EA4745 /* MainView.swift in Sources */, 6838051A2A57356700CEF29C /* TextFieldExtensions.swift in Sources */, + 680A62182A600F81004C21A4 /* Task.swift in Sources */, 680A62122A5F475D004C21A4 /* ViewExtensions.swift in Sources */, 682D06A62A5487D200EA4745 /* LutoApp.swift in Sources */, ); diff --git a/Luto/LutoApp.swift b/Luto/LutoApp.swift index 6c85115..5073df9 100644 --- a/Luto/LutoApp.swift +++ b/Luto/LutoApp.swift @@ -14,7 +14,7 @@ struct LutoApp: App { var body: some Scene { WindowGroup(id: "MainWindow") { - MainView(taskTitle: "", taskDescription: "", listTask: []) + MainView() } } } @@ -33,14 +33,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) if let statusButton = statusItem.button { - statusButton.image = NSImage(systemSymbolName: "brain", accessibilityDescription: "Chart Line") + statusButton.image = NSImage(systemSymbolName: "brain", accessibilityDescription: "A brain") statusButton.action = #selector(togglePopover) } self.popover = NSPopover() self.popover.contentSize = NSSize(width: 500, height: 500) self.popover.behavior = .transient - self.popover.contentViewController = NSHostingController(rootView: MainView(taskTitle: "", taskDescription: "", listTask: []) + self.popover.contentViewController = NSHostingController(rootView: MainView() ) } diff --git a/Luto/Models/Task.swift b/Luto/Models/Task.swift new file mode 100644 index 0000000..63ea18b --- /dev/null +++ b/Luto/Models/Task.swift @@ -0,0 +1,13 @@ +// +// Task.swift +// Luto +// +// Created by Pierre Boulc'h on 13/07/2023. +// + +import Foundation + +struct Task { + var title: String + var description: String +} diff --git a/Luto/UI/MainView.swift b/Luto/UI/MainView.swift index 084c537..165444d 100644 --- a/Luto/UI/MainView.swift +++ b/Luto/UI/MainView.swift @@ -10,39 +10,52 @@ import AppKit struct MainView: View { + private enum FocusStateField: Hashable{ + case titleField + case descriptionField + } + @State var taskTitle = "" @State var taskDescription = "" - @State var listTask: [String] = [] + @State var listTask: [Task] = [] @State var showAdditionnalFields = false - @FocusState private var titleFieldInFocus: Bool - @FocusState private var descriptionFieldInFocus: Bool - + + @FocusState private var focusState: FocusStateField? var body: some View { VStack { Text("Mes tâches") - LazyVStack(alignment: .leading) { - ForEach(Array(listTask.enumerated()), id: \.offset) { index, task in - HStack { - Text("\(task)") - .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 8)) - Spacer() - Button(action: { - removeTask(index: index) - }, label: { - Image(systemName: "trash") - }).buttonStyle(PlainButtonStyle()).padding(12) - .foregroundColor(.accentColor) - }.border(width: 5, edges: [.leading], color: .accentColor) + ScrollView { + LazyVStack(alignment: .leading) { + ForEach(Array(listTask.enumerated()), id: \.offset) { index, task in + HStack { + VStack(alignment: .leading) { + Text("\(task.title)").font(.system(size: 16)) + if !task.description.isEmpty { + Text("\(task.description)") + } + } + .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 8)) + Spacer() + Button(action: { + removeTask(index: index) + }, label: { + Image(systemName: "trash") + }).buttonStyle(PlainButtonStyle()).padding(12) + .foregroundColor(.accentColor) + }.border(width: 5, edges: [.leading], color: .accentColor) + } } } Spacer() + Divider() HStack { - TextField("Titre de la tâche ...", text: $taskTitle).focused($titleFieldInFocus).onChange(of: titleFieldInFocus) { isFocused in - if !isFocused { + TextField("Titre de la tâche ...", text: $taskTitle).focused($focusState, equals: .titleField).onChange(of: focusState) { newFocusState in + if newFocusState != .titleField { withAnimation { showAdditionnalFields = true + focusState = .descriptionField } } }.onSubmit { @@ -58,7 +71,9 @@ struct MainView: View { .cornerRadius(24) }.textFieldStyle(OvalTextFieldStyle()) if showAdditionnalFields { - TextField("Description", text: $taskDescription).focused($descriptionFieldInFocus) + TextField("Description ...", text: $taskDescription).focused($focusState, equals: .descriptionField).textFieldStyle(OvalTextFieldStyle()).padding(EdgeInsets(top: 8, leading: 0, bottom: 0, trailing: 0)).onSubmit { + addTask() + } } } .padding() @@ -68,9 +83,12 @@ struct MainView: View { func addTask() { if !taskTitle.isEmpty { withAnimation { - listTask.append(taskTitle) + listTask.append(Task(title: taskTitle, description: taskDescription)) } taskTitle = "" + taskDescription = "" + showAdditionnalFields = false + focusState = .titleField } } @@ -79,16 +97,10 @@ struct MainView: View { listTask.remove(at: index) } } - - init(taskTitle: String = "", taskDescription: String = "", listTask: [String]) { - self.taskTitle = taskTitle - self.taskDescription = taskDescription - self.listTask = listTask - } } struct MainView_Previews: PreviewProvider { static var previews: some View { - MainView(taskTitle: "", taskDescription: "", listTask: []) + MainView() } }