@@ -336,6 +336,24 @@ export function planSidebarThreadDrop(input: {
336336 if ( input . supportsSettlement === false && ( target . section === "settled" || activeSettled ) ) {
337337 return { kind : "none" } ;
338338 }
339+ // Rows whose server cannot store an order (an older server, or a machine
340+ // that is offline) are never written. Keyless ones sort outside the keyed
341+ // run, so they leave the plan; keyed ones stay as bounds. Before, one keyless row
342+ // refused every drop that needed fresh keys for its neighbors.
343+ const arrange = (
344+ order : readonly string [ ] ,
345+ keysById : ReadonlyMap < string , string | null | undefined > ,
346+ writable : ReadonlySet < string > | undefined ,
347+ ) => {
348+ if ( ! writable ) return planPinnedReorder ( { orderedIds : order , keysById, movedId : activeKey } ) ;
349+ if ( ! writable . has ( activeKey ) ) return null ;
350+ const assignments = planPinnedReorder ( {
351+ orderedIds : order . filter ( ( key ) => writable . has ( key ) || keysById . get ( key ) != null ) ,
352+ keysById,
353+ movedId : activeKey ,
354+ } ) ;
355+ return assignments . every ( ( { id } ) => writable . has ( id ) ) ? assignments : null ;
356+ } ;
339357 switch ( target . section ) {
340358 case "active" : {
341359 // Like the settled tail: threads can enter a time-ordered inbox, but
@@ -360,14 +378,8 @@ export function planSidebarThreadDrop(input: {
360378 ) {
361379 return { kind : "none" } ;
362380 }
363- const assignments = planPinnedReorder ( {
364- orderedIds : order ,
365- keysById : activeKeysById ,
366- movedId : activeKey ,
367- } ) ;
368- if ( activeReorderableKeys && assignments . some ( ( { id } ) => ! activeReorderableKeys . has ( id ) ) ) {
369- return { kind : "none" } ;
370- }
381+ const assignments = arrange ( order , activeKeysById , activeReorderableKeys ) ;
382+ if ( assignments === null ) return { kind : "none" } ;
371383 return {
372384 kind : "move-active" ,
373385 order,
@@ -389,14 +401,8 @@ export function planSidebarThreadDrop(input: {
389401 ) {
390402 return { kind : "none" } ;
391403 }
392- const assignments = planPinnedReorder ( {
393- orderedIds : order ,
394- keysById : pinnedKeysById ,
395- movedId : activeKey ,
396- } ) ;
397- if ( reorderableKeys && assignments . some ( ( { id } ) => ! reorderableKeys . has ( id ) ) ) {
398- return { kind : "none" } ;
399- }
404+ const assignments = arrange ( order , pinnedKeysById , reorderableKeys ) ;
405+ if ( assignments === null ) return { kind : "none" } ;
400406 if ( activeSection === "pinned" ) {
401407 return assignments . length === 0
402408 ? { kind : "none" }
0 commit comments