Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions apps/web/src/components/Sidebar.logic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2235,6 +2235,34 @@ describe("Working shelf (beta)", () => {
expect(resolveSidebarDropVerb("active", "working")).toBeNull();
});

it("arranges the rows it can write when another row's server cannot store an order", () => {
// None of the rows has a key yet, so the drop needs keys for its
// neighbors too. "offline" sits on a server that cannot take them.
const plan = planSidebarThreadDrop({
activeKey: "a2",
activeSection: "active",
target: {
section: "active",
pinnedOrder: [],
activeOrder: ["offline", "a2", "a1"],
},
pinnedOrder: [],
pinnedKeysById: new Map(),
activeOrder: ["offline", "a1", "a2"],
activeKeysById: new Map([
["offline", null],
["a1", null],
["a2", null],
]),
activeReorderableKeys: new Set(["a1", "a2"]),
});
expect(plan.kind).toBe("move-active");
if (plan.kind !== "move-active") return;
expect(plan.assignments.map(({ id }) => id)).toEqual(["a2", "a1"]);
const [a2, a1] = plan.assignments.map(({ orderKey }) => orderKey);
expect(a2! < a1!).toBe(true);
});

it("only changes lifecycle when the inbox is time-ordered", () => {
const base = {
pinnedOrder: ["p1"],
Expand Down
35 changes: 19 additions & 16 deletions apps/web/src/components/Sidebar.logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,21 @@ export function planSidebarThreadDrop(input: {
if (input.supportsSettlement === false && (target.section === "settled" || activeSettled)) {
return { kind: "none" };
}
// Rows whose server cannot store an order (an older server, or a machine
// that is offline) keep their existing keys, and the drop arranges the rest. Before,
// one such row refused every drop that needed fresh keys for its neighbors.
const arrange = (
order: readonly string[],
keysById: ReadonlyMap<string, string | null | undefined>,
writable: ReadonlySet<string> | undefined,
) =>
writable && !writable.has(activeKey)
? null
: planPinnedReorder({
orderedIds: writable ? order.filter((key) => writable.has(key)) : order,
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
Outdated
keysById,
movedId: activeKey,
});
switch (target.section) {
case "active": {
// Like the settled tail: threads can enter a time-ordered inbox, but
Expand All @@ -360,14 +375,8 @@ export function planSidebarThreadDrop(input: {
) {
return { kind: "none" };
}
const assignments = planPinnedReorder({
orderedIds: order,
keysById: activeKeysById,
movedId: activeKey,
});
if (activeReorderableKeys && assignments.some(({ id }) => !activeReorderableKeys.has(id))) {
return { kind: "none" };
}
const assignments = arrange(order, activeKeysById, activeReorderableKeys);
if (assignments === null) return { kind: "none" };
return {
kind: "move-active",
order,
Expand All @@ -389,14 +398,8 @@ export function planSidebarThreadDrop(input: {
) {
return { kind: "none" };
}
const assignments = planPinnedReorder({
orderedIds: order,
keysById: pinnedKeysById,
movedId: activeKey,
});
if (reorderableKeys && assignments.some(({ id }) => !reorderableKeys.has(id))) {
return { kind: "none" };
}
const assignments = arrange(order, pinnedKeysById, reorderableKeys);
if (assignments === null) return { kind: "none" };
if (activeSection === "pinned") {
return assignments.length === 0
? { kind: "none" }
Expand Down
Loading