top | item 43960696

(no title)

bound008 | 9 months ago

I might do that at some point... this is the main part of it, just a swift data model and one file of views. Plus a bunch of example code for making widgets work.

``` import Foundation import SwiftData

@Model final class FocusItem { let created: Date = Date() var completed: Date? var theFocus: String = "New Focus" var details: String?

    init(completed: Date? = nil, theFocus: String, details: String? = nil) {
        self.completed = completed
        self.theFocus = theFocus
        self.details = details
    }
}

struct FocusItemDescriptors { static let currentFocusPredicate = #Predicate<FocusItem> { $0.completed == nil }

    static let sortDescriptor = SortDescriptor(\FocusItem.created, order: .reverse)

    static let currentFocusFetchDescriptor = FetchDescriptor(
        predicate: currentFocusPredicate, sortBy: [sortDescriptor])
} ```

``` import SwiftData import SwiftUI import WidgetKit

struct ContentView: View { @Query( filter: FocusItemDescriptors.currentFocusPredicate, sort: [FocusItemDescriptors.sortDescriptor]) private var items: [FocusItem] @Environment(\.modelContext) private var modelContext

  @State private var isAddingNewItem = false
  @State private var newFocusText = ""

  var body: some View {
    NavigationStack {
      List {
        ForEach(items) { item in
          NavigationLink {
            FocusItemDetailView(item: item)
          } label: {
            Text(item.theFocus)
          }
        }
        .onDelete(perform: deleteItems)
      }
      .navigationTitle("Focus")
      .toolbar {
        #if os(iOS)
          ToolbarItem(placement: .navigationBarTrailing) {
            EditButton()
          }
        #endif
        ToolbarItem {
          Button(action: addItem) {
            Label("Add Item", systemImage: "plus")
          }
        }
      }
    }
    .sheet(isPresented: $isAddingNewItem) {
      AddFocusItemView(isPresented: $isAddingNewItem, addItem: addNewItemWithFocus)
    }
  }

  private func addItem() {
    isAddingNewItem = true
  }

  private func addNewItemWithFocus(_ focus: String) {
    withAnimation {
      let newItem = FocusItem(theFocus: focus)
      modelContext.insert(newItem)
      DataManager.shared.reloadWidgets()
    }
  }

  private func deleteItems(offsets: IndexSet) {
    withAnimation {
      for index in offsets {
        modelContext.delete(items[index])
      }
      DataManager.shared.reloadWidgets()
    }
  }
}

struct FocusItemDetailView: View { @Environment(\.dismiss) private var dismiss let item: FocusItem

  var body: some View {
    VStack {
      Text(item.theFocus)
      if let details = item.details {
        Text(details)
      }
      Text(
        "\(item.created, format: Date.FormatStyle(date: .numeric, time: .standard))"
      )
      Button {
        item.completed = Date()
        DataManager.shared.reloadWidgets()
        dismiss()
      } label: {
        Text("Mark as Complete")
      }
    }
  }
} struct AddFocusItemView: View { @Binding var isPresented: Bool let addItem: (String) -> Void @State private var newFocusText = ""

  var body: some View {
    NavigationView {
      Form {
        TextField("What is your focus?", text: $newFocusText, axis: .vertical)
          .lineLimit(3...10)
      }
      .navigationTitle("New Focus")
      .toolbar {
        ToolbarItem(placement: .cancellationAction) {
          Button("Cancel") {
            isPresented = false
          }
        }
        ToolbarItem(placement: .confirmationAction) {
          Button("Add") {
            addItem(newFocusText)
            isPresented = false
          }
          .disabled(newFocusText.isEmpty)
        }
      }
    }
  }
```

discuss

order