Updated the TaskListView.Content view in the app target to support user reordering.
This commit is contained in:
@@ -5,42 +5,82 @@ extension TaskListView {
|
|||||||
|
|
||||||
/// Internal content view that manages the dynamic SwiftData query for tasks.
|
/// Internal content view that manages the dynamic SwiftData query for tasks.
|
||||||
///
|
///
|
||||||
/// This view is responsible for querying and displaying the list of tasks based on
|
/// This view is responsible for querying and displaying the list of tasks based on the specified
|
||||||
/// the specified group and completion status filter. It exists as a separate view
|
/// group and completion status filter. It exists as a separate view to enable dynamic query
|
||||||
/// to enable dynamic query updates when filter parameters change.
|
/// updates when filter parameters change.
|
||||||
|
///
|
||||||
|
/// Task reordering is enabled based on the ``TodoGroup/canReorder`` property.
|
||||||
|
/// Groups that support reordering (``TodoGroup/today``, ``TodoGroup/upcoming``,
|
||||||
|
/// ``TodoGroup/overdue``) allow users to drag and drop tasks to change their order.
|
||||||
|
/// The ``TodoGroup/completed`` group does not support reordering as tasks are
|
||||||
|
/// displayed in chronological order by completion date.
|
||||||
struct Content: View {
|
struct Content: View {
|
||||||
|
|
||||||
|
// MARK: Type aliases
|
||||||
|
|
||||||
|
/// Closure type for handling task reorder operations.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - tasks: The current array of tasks.
|
||||||
|
/// - source: The index set of items being moved.
|
||||||
|
/// - destination: The destination index for the moved items.
|
||||||
|
typealias ReorderClosure = ([Todo], IndexSet, Int) -> Void
|
||||||
|
|
||||||
// MARK: Properties
|
// MARK: Properties
|
||||||
|
|
||||||
/// Query to fetch todos filtered by group and completion status.
|
/// Query to fetch todos filtered by group and completion status.
|
||||||
///
|
///
|
||||||
/// This query is initialized with a `FetchDescriptor` that applies predicates
|
/// This query is initialized with a todo fetch descriptor that applies predicates
|
||||||
/// based on the group type and completion filter. SwiftData automatically
|
/// based on the group type and completion filter. SwiftData automatically
|
||||||
/// monitors changes and updates the view when the underlying data changes.
|
/// monitors changes and updates the view when the underlying data changes.
|
||||||
|
///
|
||||||
|
/// Tasks are sorted by their `order` property first, then by date-based criteria
|
||||||
|
/// specific to each group, enabling both manual and automatic ordering.
|
||||||
@Query
|
@Query
|
||||||
private var tasks: [Todo]
|
private var tasks: [Todo]
|
||||||
|
|
||||||
|
/// Indicates whether tasks in this view can be reordered through drag and drop.
|
||||||
|
///
|
||||||
|
/// This value is derived from the ``TodoGroup/canReorder`` property and
|
||||||
|
/// determines whether the `.onMove` modifier is applied to the task list.
|
||||||
|
private let canReorder: Bool
|
||||||
|
|
||||||
|
/// Closure called when tasks are reordered through drag and drop.
|
||||||
|
///
|
||||||
|
/// This closure is invoked by the `.onMove` modifier and is responsible for
|
||||||
|
/// updating the `order` property of affected tasks to reflect their new positions.
|
||||||
|
private let onReorder: ReorderClosure
|
||||||
|
|
||||||
// MARK: Initializers
|
// MARK: Initializers
|
||||||
|
|
||||||
/// Creates a content view with a configured task query.
|
/// Creates a content view with a configured task query and reorder handler.
|
||||||
///
|
///
|
||||||
/// This initializer sets up the `@Query` with a fetch descriptor that filters
|
/// This initializer sets up a query with a fetch descriptor that filters
|
||||||
/// tasks based on the specified group and completion status. When these parameters
|
/// tasks based on the specified group and completion status. When these parameters
|
||||||
/// change, SwiftUI recreates the view with new values, causing the query to update.
|
/// change, SwiftUI recreates the view with new values, causing the query to update.
|
||||||
///
|
///
|
||||||
|
/// The reordering capability is automatically determined based on the
|
||||||
|
/// ``TodoGroup/canReorder`` property. For groups that support reordering,
|
||||||
|
/// the provided closure will be called when users drag and drop tasks to new positions.
|
||||||
|
///
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - group: The todo group category to filter by (today, upcoming, overdue, or completed).
|
/// - group: The todo group category to filter by (today, upcoming, overdue, or completed).
|
||||||
/// - showCompleted: Whether to include completed tasks in the results. Only applies to groups other than `.completed`.
|
/// - showCompleted: Whether to include completed tasks in the results. Only applies to groups other than `.completed`.
|
||||||
|
/// - onReorder: A closure called when tasks are reordered.
|
||||||
init(
|
init(
|
||||||
group: TodoGroup,
|
group: TodoGroup,
|
||||||
showCompleted: Bool
|
showCompleted: Bool,
|
||||||
|
onReorder: @escaping ReorderClosure
|
||||||
) {
|
) {
|
||||||
_tasks = .init(
|
self._tasks = .init(
|
||||||
FetchDescriptor<Todo>(
|
FetchDescriptor<Todo>(
|
||||||
group: group,
|
group: group,
|
||||||
showCompleted: showCompleted
|
showCompleted: showCompleted
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.canReorder = group.canReorder
|
||||||
|
self.onReorder = onReorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Body
|
// MARK: Body
|
||||||
@@ -49,6 +89,12 @@ extension TaskListView {
|
|||||||
///
|
///
|
||||||
/// Displays either a content unavailable state or a list of tasks
|
/// Displays either a content unavailable state or a list of tasks
|
||||||
/// based on whether any tasks match the current filters.
|
/// based on whether any tasks match the current filters.
|
||||||
|
///
|
||||||
|
/// When tasks are present, displays them in a grouped list. The list supports
|
||||||
|
/// drag and drop reordering for groups where `canReorder` is true, allowing
|
||||||
|
/// users to manually prioritize tasks within the group. For groups where
|
||||||
|
/// reordering is disabled (such as completed tasks), the list is displayed
|
||||||
|
/// in read-only mode with chronological sorting.
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if tasks.isEmpty {
|
if tasks.isEmpty {
|
||||||
@@ -59,8 +105,18 @@ extension TaskListView {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
List {
|
List {
|
||||||
ForEach(tasks) { todo in
|
if canReorder {
|
||||||
TaskListView.Item(todo)
|
ForEach(tasks) {
|
||||||
|
TaskListView.Item($0)
|
||||||
|
}
|
||||||
|
.onMove { source, destination in
|
||||||
|
onReorder(tasks, source, destination)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ForEach(tasks) {
|
||||||
|
TaskListView.Item($0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.listStyle(.grouped)
|
.listStyle(.grouped)
|
||||||
@@ -80,7 +136,9 @@ extension TaskListView {
|
|||||||
TaskListView.Content(
|
TaskListView.Content(
|
||||||
group: .today,
|
group: .today,
|
||||||
showCompleted: .random()
|
showCompleted: .random()
|
||||||
)
|
) { _, _, _ in
|
||||||
|
// On reorder closure
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview(
|
#Preview(
|
||||||
@@ -90,7 +148,9 @@ extension TaskListView {
|
|||||||
TaskListView.Content(
|
TaskListView.Content(
|
||||||
group: .today,
|
group: .today,
|
||||||
showCompleted: false
|
showCompleted: false
|
||||||
)
|
) { _, _, _ in
|
||||||
|
// On reorder closure
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview(
|
#Preview(
|
||||||
@@ -100,5 +160,19 @@ extension TaskListView {
|
|||||||
TaskListView.Content(
|
TaskListView.Content(
|
||||||
group: .today,
|
group: .today,
|
||||||
showCompleted: true
|
showCompleted: true
|
||||||
)
|
) { _, _, _ in
|
||||||
|
// On reorder closure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview(
|
||||||
|
"Task list content when only completed tasks shown",
|
||||||
|
traits: .sampleTasks
|
||||||
|
) {
|
||||||
|
TaskListView.Content(
|
||||||
|
group: .completed,
|
||||||
|
showCompleted: .random()
|
||||||
|
) { _, _, _ in
|
||||||
|
// On reorder closure
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user