Skip to content

Commit 1eb82e6

Browse files
Sort reminders lists by drag-and-drop (#40)
* Proof-of-concept: manual list sorting. * wip * wip * wip --------- Co-authored-by: Stephen Celis <stephen@stephencelis.com>
1 parent 2afb042 commit 1eb82e6

2 files changed

Lines changed: 49 additions & 6 deletions

File tree

Examples/Reminders/RemindersLists.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ struct RemindersListsView: View {
55
@FetchAll(
66
RemindersList
77
.group(by: \.id)
8+
.order(by: \.position)
89
.leftJoin(Reminder.all) { $0.id.eq($1.remindersListID) && !$1.isCompleted }
910
.select {
1011
ReminderListState.Columns(remindersCount: $1.id.count(), remindersList: $0)
@@ -129,7 +130,10 @@ struct RemindersListsView: View {
129130
remindersCount: state.remindersCount,
130131
remindersList: state.remindersList
131132
)
132-
}
133+
}
134+
}
135+
.onMove { indexSet, index in
136+
move(from: indexSet, to: index)
133137
}
134138
} header: {
135139
Text("My Lists")
@@ -210,6 +214,27 @@ struct RemindersListsView: View {
210214
RemindersListDetailView(detailType: detailType)
211215
}
212216
}
217+
218+
func move(from source: IndexSet, to destination: Int) {
219+
withErrorReporting {
220+
try database.write { db in
221+
var ids = remindersLists.map(\.remindersList.id)
222+
ids.move(fromOffsets: source, toOffset: destination)
223+
try RemindersList
224+
.where { $0.id.in(ids) }
225+
.update {
226+
let ids = Array(ids.enumerated())
227+
let (first, rest) = (ids.first!, ids.dropFirst())
228+
$0.position = rest
229+
.reduce(Case($0.id).when(first.element, then: first.offset)) { cases, id in
230+
cases.when(id.element, then: id.offset)
231+
}
232+
.else($0.position)
233+
}
234+
.execute(db)
235+
}
236+
}
237+
}
213238
}
214239

215240
private struct ReminderGridCell: View {

Examples/Reminders/Schema.swift

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ struct RemindersList: Hashable, Identifiable {
99
var id: Int
1010
@Column(as: Color.HexRepresentation.self)
1111
var color = Color(red: 0x4a / 255, green: 0x99 / 255, blue: 0xef / 255)
12+
var position = 0
1213
var title = ""
1314
}
1415

@@ -107,7 +108,7 @@ func appDatabase() throws -> any DatabaseWriter {
107108
#if DEBUG
108109
migrator.eraseDatabaseOnSchemaChange = true
109110
#endif
110-
migrator.registerMigration("Add reminders lists table") { db in
111+
migrator.registerMigration("Create initial tables") { db in
111112
try #sql(
112113
"""
113114
CREATE TABLE "remindersLists" (
@@ -118,8 +119,6 @@ func appDatabase() throws -> any DatabaseWriter {
118119
"""
119120
)
120121
.execute(db)
121-
}
122-
migrator.registerMigration("Add reminders table") { db in
123122
try #sql(
124123
"""
125124
CREATE TABLE "reminders" (
@@ -137,8 +136,6 @@ func appDatabase() throws -> any DatabaseWriter {
137136
"""
138137
)
139138
.execute(db)
140-
}
141-
migrator.registerMigration("Add tags table") { db in
142139
try #sql(
143140
"""
144141
CREATE TABLE "tags" (
@@ -161,6 +158,27 @@ func appDatabase() throws -> any DatabaseWriter {
161158
)
162159
.execute(db)
163160
}
161+
migrator.registerMigration("Add 'position' column to 'remindersLists'") { db in
162+
try #sql(
163+
"""
164+
ALTER TABLE "remindersLists"
165+
ADD COLUMN "position" INTEGER NOT NULL DEFAULT 0
166+
"""
167+
)
168+
.execute(db)
169+
try #sql(
170+
"""
171+
CREATE TRIGGER "default_position_reminders_lists"
172+
AFTER INSERT ON "remindersLists"
173+
FOR EACH ROW BEGIN
174+
UPDATE "remindersLists"
175+
SET "position" = (SELECT max("position") + 1 FROM "remindersLists")
176+
WHERE "id" = NEW."id";
177+
END
178+
"""
179+
)
180+
.execute(db)
181+
}
164182
#if DEBUG && targetEnvironment(simulator)
165183
if context != .test {
166184
migrator.registerMigration("Seed sample data") { db in

0 commit comments

Comments
 (0)