mirror of
https://github.com/pboulch/luto.git
synced 2025-12-19 12:52:47 +00:00
✨ Add description field
This commit is contained in:
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
680A62122A5F475D004C21A4 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 680A62112A5F475D004C21A4 /* ViewExtensions.swift */; };
|
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 */; };
|
682D06A62A5487D200EA4745 /* LutoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682D06A52A5487D200EA4745 /* LutoApp.swift */; };
|
||||||
682D06A82A5487D200EA4745 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682D06A72A5487D200EA4745 /* MainView.swift */; };
|
682D06A82A5487D200EA4745 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682D06A72A5487D200EA4745 /* MainView.swift */; };
|
||||||
682D06AA2A5487D500EA4745 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 682D06A92A5487D500EA4745 /* Assets.xcassets */; };
|
682D06AA2A5487D500EA4745 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 682D06A92A5487D500EA4745 /* Assets.xcassets */; };
|
||||||
@ -37,6 +38,7 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
680A62112A5F475D004C21A4 /* ViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtensions.swift; sourceTree = "<group>"; };
|
680A62112A5F475D004C21A4 /* ViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtensions.swift; sourceTree = "<group>"; };
|
||||||
|
680A62172A600F81004C21A4 /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; };
|
||||||
682D06A22A5487D200EA4745 /* Luto.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Luto.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
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 = "<group>"; };
|
682D06A52A5487D200EA4745 /* LutoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LutoApp.swift; sourceTree = "<group>"; };
|
||||||
682D06A72A5487D200EA4745 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
682D06A72A5487D200EA4745 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
||||||
@ -85,6 +87,14 @@
|
|||||||
path = Utils;
|
path = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
680A62162A600F75004C21A4 /* Models */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
680A62172A600F81004C21A4 /* Task.swift */,
|
||||||
|
);
|
||||||
|
path = Models;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
682D06992A5487D200EA4745 = {
|
682D06992A5487D200EA4745 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -108,6 +118,7 @@
|
|||||||
682D06A42A5487D200EA4745 /* Luto */ = {
|
682D06A42A5487D200EA4745 /* Luto */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
680A62162A600F75004C21A4 /* Models */,
|
||||||
683805182A57354900CEF29C /* UI */,
|
683805182A57354900CEF29C /* UI */,
|
||||||
682D06A52A5487D200EA4745 /* LutoApp.swift */,
|
682D06A52A5487D200EA4745 /* LutoApp.swift */,
|
||||||
682D06A92A5487D500EA4745 /* Assets.xcassets */,
|
682D06A92A5487D500EA4745 /* Assets.xcassets */,
|
||||||
@ -283,6 +294,7 @@
|
|||||||
files = (
|
files = (
|
||||||
682D06A82A5487D200EA4745 /* MainView.swift in Sources */,
|
682D06A82A5487D200EA4745 /* MainView.swift in Sources */,
|
||||||
6838051A2A57356700CEF29C /* TextFieldExtensions.swift in Sources */,
|
6838051A2A57356700CEF29C /* TextFieldExtensions.swift in Sources */,
|
||||||
|
680A62182A600F81004C21A4 /* Task.swift in Sources */,
|
||||||
680A62122A5F475D004C21A4 /* ViewExtensions.swift in Sources */,
|
680A62122A5F475D004C21A4 /* ViewExtensions.swift in Sources */,
|
||||||
682D06A62A5487D200EA4745 /* LutoApp.swift in Sources */,
|
682D06A62A5487D200EA4745 /* LutoApp.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,7 +14,7 @@ struct LutoApp: App {
|
|||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup(id: "MainWindow") {
|
WindowGroup(id: "MainWindow") {
|
||||||
MainView(taskTitle: "", taskDescription: "", listTask: [])
|
MainView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,14 +33,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
|
|||||||
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
||||||
|
|
||||||
if let statusButton = statusItem.button {
|
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)
|
statusButton.action = #selector(togglePopover)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.popover = NSPopover()
|
self.popover = NSPopover()
|
||||||
self.popover.contentSize = NSSize(width: 500, height: 500)
|
self.popover.contentSize = NSSize(width: 500, height: 500)
|
||||||
self.popover.behavior = .transient
|
self.popover.behavior = .transient
|
||||||
self.popover.contentViewController = NSHostingController(rootView: MainView(taskTitle: "", taskDescription: "", listTask: [])
|
self.popover.contentViewController = NSHostingController(rootView: MainView()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
Luto/Models/Task.swift
Normal file
13
Luto/Models/Task.swift
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -10,22 +10,32 @@ import AppKit
|
|||||||
|
|
||||||
struct MainView: View {
|
struct MainView: View {
|
||||||
|
|
||||||
|
private enum FocusStateField: Hashable{
|
||||||
|
case titleField
|
||||||
|
case descriptionField
|
||||||
|
}
|
||||||
|
|
||||||
@State var taskTitle = ""
|
@State var taskTitle = ""
|
||||||
@State var taskDescription = ""
|
@State var taskDescription = ""
|
||||||
@State var listTask: [String] = []
|
@State var listTask: [Task] = []
|
||||||
|
|
||||||
@State var showAdditionnalFields = false
|
@State var showAdditionnalFields = false
|
||||||
@FocusState private var titleFieldInFocus: Bool
|
|
||||||
@FocusState private var descriptionFieldInFocus: Bool
|
|
||||||
|
|
||||||
|
@FocusState private var focusState: FocusStateField?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Text("Mes tâches")
|
Text("Mes tâches")
|
||||||
|
ScrollView {
|
||||||
LazyVStack(alignment: .leading) {
|
LazyVStack(alignment: .leading) {
|
||||||
ForEach(Array(listTask.enumerated()), id: \.offset) { index, task in
|
ForEach(Array(listTask.enumerated()), id: \.offset) { index, task in
|
||||||
HStack {
|
HStack {
|
||||||
Text("\(task)")
|
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))
|
.padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 8))
|
||||||
Spacer()
|
Spacer()
|
||||||
Button(action: {
|
Button(action: {
|
||||||
@ -37,12 +47,15 @@ struct MainView: View {
|
|||||||
}.border(width: 5, edges: [.leading], color: .accentColor)
|
}.border(width: 5, edges: [.leading], color: .accentColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
|
Divider()
|
||||||
HStack {
|
HStack {
|
||||||
TextField("Titre de la tâche ...", text: $taskTitle).focused($titleFieldInFocus).onChange(of: titleFieldInFocus) { isFocused in
|
TextField("Titre de la tâche ...", text: $taskTitle).focused($focusState, equals: .titleField).onChange(of: focusState) { newFocusState in
|
||||||
if !isFocused {
|
if newFocusState != .titleField {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
showAdditionnalFields = true
|
showAdditionnalFields = true
|
||||||
|
focusState = .descriptionField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.onSubmit {
|
}.onSubmit {
|
||||||
@ -58,7 +71,9 @@ struct MainView: View {
|
|||||||
.cornerRadius(24)
|
.cornerRadius(24)
|
||||||
}.textFieldStyle(OvalTextFieldStyle())
|
}.textFieldStyle(OvalTextFieldStyle())
|
||||||
if showAdditionnalFields {
|
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()
|
.padding()
|
||||||
@ -68,9 +83,12 @@ struct MainView: View {
|
|||||||
func addTask() {
|
func addTask() {
|
||||||
if !taskTitle.isEmpty {
|
if !taskTitle.isEmpty {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
listTask.append(taskTitle)
|
listTask.append(Task(title: taskTitle, description: taskDescription))
|
||||||
}
|
}
|
||||||
taskTitle = ""
|
taskTitle = ""
|
||||||
|
taskDescription = ""
|
||||||
|
showAdditionnalFields = false
|
||||||
|
focusState = .titleField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,16 +97,10 @@ struct MainView: View {
|
|||||||
listTask.remove(at: index)
|
listTask.remove(at: index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(taskTitle: String = "", taskDescription: String = "", listTask: [String]) {
|
|
||||||
self.taskTitle = taskTitle
|
|
||||||
self.taskDescription = taskDescription
|
|
||||||
self.listTask = listTask
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MainView_Previews: PreviewProvider {
|
struct MainView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
MainView(taskTitle: "", taskDescription: "", listTask: [])
|
MainView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user