mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-11 03:59:09 +00:00
fix(downloads): harden queue drag and reorder behavior
This commit is contained in:
@@ -1826,6 +1826,40 @@ describe('useDownloadStore', () => {
|
||||
expect(useDownloadStore.getState().downloads.find(item => item.id === 'staged')?.queuePosition).toBe(2);
|
||||
});
|
||||
|
||||
it('keeps a drag anchored when the queue changes before its serialized operation runs', async () => {
|
||||
useDownloadStore.setState({
|
||||
downloads: [
|
||||
{ id: 'a', status: 'queued', queueId: 'concurrent-drag-queue', queuePosition: 0 },
|
||||
{ id: 'b', status: 'queued', queueId: 'concurrent-drag-queue', queuePosition: 1 },
|
||||
{ id: 'c', status: 'queued', queueId: 'concurrent-drag-queue', queuePosition: 2 }
|
||||
] as any[],
|
||||
backendRegisteredIds: new Set()
|
||||
});
|
||||
|
||||
const operation = useDownloadStore.getState().moveManyInQueueToPosition(
|
||||
'b',
|
||||
'concurrent-drag-queue',
|
||||
2,
|
||||
'c'
|
||||
);
|
||||
useDownloadStore.setState({
|
||||
downloads: [
|
||||
{ id: 'a', status: 'queued', queueId: 'concurrent-drag-queue', queuePosition: 0 },
|
||||
{ id: 'b', status: 'queued', queueId: 'concurrent-drag-queue', queuePosition: 1 },
|
||||
{ id: 'new', status: 'queued', queueId: 'concurrent-drag-queue', queuePosition: 2 },
|
||||
{ id: 'c', status: 'queued', queueId: 'concurrent-drag-queue', queuePosition: 3 }
|
||||
] as any[]
|
||||
});
|
||||
|
||||
await operation;
|
||||
|
||||
expect(useDownloadStore.getState().downloads
|
||||
.filter(item => item.queueId === 'concurrent-drag-queue')
|
||||
.sort((left, right) => (left.queuePosition ?? 0) - (right.queuePosition ?? 0))
|
||||
.map(item => item.id)
|
||||
).toEqual(['a', 'new', 'b', 'c']);
|
||||
});
|
||||
|
||||
it('rolls back a failed drag move and rejects so the UI can report the failure', async () => {
|
||||
useDownloadStore.setState({
|
||||
downloads: [
|
||||
|
||||
@@ -707,7 +707,12 @@ interface DownloadState {
|
||||
unregisterBackendIds: (ids: string[]) => void;
|
||||
applyProperties: (id: string, updates: Partial<DownloadItem>) => Promise<void>;
|
||||
moveInQueue: (ids: string | string[], direction: 'up' | 'down') => Promise<void>;
|
||||
moveManyInQueueToPosition: (ids: string | string[], queueId: string, targetIndex: number) => Promise<void>;
|
||||
moveManyInQueueToPosition: (
|
||||
ids: string | string[],
|
||||
queueId: string,
|
||||
targetIndex: number,
|
||||
beforeId?: string | null
|
||||
) => Promise<void>;
|
||||
removeFromQueue: (id: string) => Promise<void>;
|
||||
isAddModalOpen: boolean;
|
||||
pendingAddUrls: string;
|
||||
@@ -959,7 +964,7 @@ export const useDownloadStore = create<DownloadState>((set, get) => {
|
||||
queueReorderPromises.set(queueId, trackedOperation);
|
||||
return trackedOperation;
|
||||
},
|
||||
moveManyInQueueToPosition: (idOrIds, queueId, targetIndex) => {
|
||||
moveManyInQueueToPosition: (idOrIds, queueId, targetIndex, beforeId) => {
|
||||
const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds];
|
||||
if (ids.length === 0) return Promise.resolve();
|
||||
|
||||
@@ -978,7 +983,14 @@ export const useDownloadStore = create<DownloadState>((set, get) => {
|
||||
...activeQueueItems(allDownloads, queueId),
|
||||
...queueItems
|
||||
].map(item => [item.id, item.queuePosition]));
|
||||
const reordered = moveSelectedBlockToIndex(queueItems, selectedIds, targetIndex);
|
||||
const unselectedItems = queueItems.filter(item => !selectedIds.has(item.id));
|
||||
const anchoredTargetIndex = beforeId
|
||||
? unselectedItems.findIndex(item => item.id === beforeId)
|
||||
: -1;
|
||||
const resolvedTargetIndex = anchoredTargetIndex >= 0
|
||||
? anchoredTargetIndex
|
||||
: Math.max(0, Math.min(targetIndex, unselectedItems.length));
|
||||
const reordered = moveSelectedBlockToIndex(queueItems, selectedIds, resolvedTargetIndex);
|
||||
set(state => ({ downloads: applyQueueOrder(state.downloads, queueId, reordered) }));
|
||||
|
||||
const registeredIdsToMove = selectedItems
|
||||
|
||||
Reference in New Issue
Block a user