FIX - allow apps to move across the dock

This commit is contained in:
Eichenholz
2026-08-07 09:15:20 +02:00
parent e2ae3fe412
commit 3e2f2f72b3
6 changed files with 91 additions and 44 deletions
+42 -11
View File
@@ -76,8 +76,32 @@ describe('home layout', () => {
expect(layout.dock).toEqual(['messages', null, 'clock', null])
})
it('preserves independently positioned shortcuts for the same app', () => {
const grid: HomeLayout['grid'] = Array.from(
{ length: HOME_GRID_PAGE_SIZE },
() => null,
)
grid[0] = 'phone'
grid[5] = 'phone'
const layout = parseHomeLayout(
{
dock: ['phone', null, null, null],
grid,
hidden: [],
version: 2,
},
defaults,
[...installed],
)
expect(layout.grid[0]).toBe('phone')
expect(layout.grid[5]).toBe('phone')
expect(layout.dock[0]).toBe('phone')
})
it('moves to an exact empty slot without compacting other apps', () => {
const moved = moveHomeApp(defaults, 'mail', 'grid', 'grid', 12)
const moved = moveHomeApp(defaults, 'grid', 2, 'grid', 12)
expect(moved.grid[2]).toBeNull()
expect(moved.grid[12]).toBe('mail')
@@ -86,7 +110,7 @@ describe('home layout', () => {
})
it('shifts occupied grid slots instead of replacing their apps', () => {
const reordered = moveHomeApp(defaults, 'mail', 'grid', 'grid', 0)
const reordered = moveHomeApp(defaults, 'grid', 2, 'grid', 0)
expect(reordered.grid.slice(0, 5)).toEqual([
'mail',
'phone',
@@ -97,7 +121,7 @@ describe('home layout', () => {
})
it('shifts an occupied dock slot toward its gap', () => {
const docked = moveHomeApp(defaults, 'mail', 'grid', 'dock', 2)
const docked = moveHomeApp(defaults, 'grid', 2, 'dock', 2)
expect(docked.dock).toEqual(['phone', 'messages', 'mail', 'clock'])
expect(docked.grid[2]).toBeNull()
@@ -108,20 +132,27 @@ describe('home layout', () => {
...defaults,
dock: ['phone', 'messages', 'clock', 'notes'],
}
const docked = moveHomeApp(layout, 'mail', 'grid', 'dock', 1)
const docked = moveHomeApp(layout, 'grid', 2, 'dock', 1)
expect(docked.dock).toEqual(['phone', 'mail', 'messages', 'clock'])
expect(docked.grid[2]).toBe('notes')
})
it('moves shortcuts between the dock and grid independently', () => {
const movedToGrid = moveHomeApp(defaults, 'dock', 0, 'grid', 5)
expect(movedToGrid.dock[0]).toBeNull()
expect(movedToGrid.grid[0]).toBe('phone')
expect(movedToGrid.grid[5]).toBe('phone')
const movedToDock = moveHomeApp(movedToGrid, 'grid', 1, 'dock', 3)
expect(movedToDock.grid[1]).toBeNull()
expect(movedToDock.dock[1]).toBe('messages')
expect(movedToDock.dock[3]).toBe('messages')
})
it('removes shortcuts without closing gaps and restores the first gap', () => {
const layout: HomeLayout = moveHomeApp(
defaults,
'phone',
'grid',
'grid',
10,
)
const layout: HomeLayout = moveHomeApp(defaults, 'grid', 0, 'grid', 10)
const removed = removeHomeApp(layout, 'phone')
expect(removed.grid[0]).toBeNull()
expect(removed.grid[10]).toBeNull()
+11 -13
View File
@@ -52,16 +52,13 @@ function readSlots(
const slots = createSlots(length)
if (!Array.isArray(value)) return slots
const usedIds = new Set<LaunchablePhoneAppId>()
for (let index = 0; index < Math.min(value.length, length); index += 1) {
const valueId = value[index]
if (
typeof valueId === 'string' &&
availableIds.has(valueId as LaunchablePhoneAppId) &&
!usedIds.has(valueId as LaunchablePhoneAppId)
availableIds.has(valueId as LaunchablePhoneAppId)
) {
slots[index] = valueId as LaunchablePhoneAppId
usedIds.add(valueId as LaunchablePhoneAppId)
}
}
return slots
@@ -226,21 +223,27 @@ export function restoreHomeApp(
export function moveHomeApp(
layout: HomeLayout,
appId: LaunchablePhoneAppId,
from: HomeArea,
sourceIndex: number,
to: HomeArea,
targetIndex: number,
): HomeLayout {
const next: HomeLayout = {
dock: [...layout.dock],
grid: [...layout.grid],
hidden: layout.hidden.filter((id) => id !== appId),
hidden: [...layout.hidden],
version: 2,
}
const source = next[from]
const sourceIndex = source.indexOf(appId)
const target = next[to]
if (sourceIndex === -1 || targetIndex < 0 || targetIndex >= target.length) {
const appId = source[sourceIndex]
if (
!appId ||
sourceIndex < 0 ||
sourceIndex >= source.length ||
targetIndex < 0 ||
targetIndex >= target.length
) {
return layout
}
@@ -251,11 +254,6 @@ export function moveHomeApp(
return next
}
const duplicateIndex = target.indexOf(appId)
if (duplicateIndex !== -1) {
target[duplicateIndex] = null
}
source[sourceIndex] = insertIntoSlot(target, targetIndex, appId)
return next
}