FIX - shift apps on occupied home drops

This commit is contained in:
Eichenholz
2026-08-07 09:11:08 +02:00
parent 4067f35d92
commit e2ae3fe412
3 changed files with 60 additions and 18 deletions
+19 -6
View File
@@ -85,20 +85,33 @@ describe('home layout', () => {
expect(moved.grid[4]).toBe('notes')
})
it('swaps occupied slots and avoids duplicate displaced shortcuts', () => {
it('shifts occupied grid slots instead of replacing their apps', () => {
const reordered = moveHomeApp(defaults, 'mail', 'grid', 'grid', 0)
expect(reordered.grid.slice(0, 5)).toEqual([
'mail',
'messages',
'phone',
'messages',
'clock',
'notes',
])
})
const docked = moveHomeApp(reordered, 'mail', 'grid', 'dock', 2)
expect(docked.dock).toEqual(['phone', 'messages', 'mail', null])
expect(docked.grid[0]).toBeNull()
expect(docked.grid.filter((id) => id === 'clock')).toHaveLength(1)
it('shifts an occupied dock slot toward its gap', () => {
const docked = moveHomeApp(defaults, 'mail', 'grid', 'dock', 2)
expect(docked.dock).toEqual(['phone', 'messages', 'mail', 'clock'])
expect(docked.grid[2]).toBeNull()
})
it('moves an app displaced from a full dock into the source slot', () => {
const layout: HomeLayout = {
...defaults,
dock: ['phone', 'messages', 'clock', 'notes'],
}
const docked = moveHomeApp(layout, 'mail', 'grid', 'dock', 1)
expect(docked.dock).toEqual(['phone', 'mail', 'messages', 'clock'])
expect(docked.grid[2]).toBe('notes')
})
it('removes shortcuts without closing gaps and restores the first gap', () => {
+40 -11
View File
@@ -81,6 +81,42 @@ function placeInFirstEmptySlot(
slots[slots.length - HOME_GRID_PAGE_SIZE] = appId
}
function insertIntoSlot(
slots: HomeSlot[],
targetIndex: number,
appId: LaunchablePhoneAppId,
): HomeSlot {
if (slots[targetIndex] === null) {
slots[targetIndex] = appId
return null
}
const emptyAfter = slots.indexOf(null, targetIndex + 1)
if (emptyAfter !== -1) {
for (let index = emptyAfter; index > targetIndex; index -= 1) {
slots[index] = slots[index - 1]
}
slots[targetIndex] = appId
return null
}
const emptyBefore = slots.lastIndexOf(null, targetIndex - 1)
if (emptyBefore !== -1) {
for (let index = emptyBefore; index < targetIndex; index += 1) {
slots[index] = slots[index + 1]
}
slots[targetIndex] = appId
return null
}
const displacedApp = slots.at(-1) ?? null
for (let index = slots.length - 1; index > targetIndex; index -= 1) {
slots[index] = slots[index - 1]
}
slots[targetIndex] = appId
return displacedApp
}
export function createDefaultHomeLayout(
installedIds: LaunchablePhoneAppId[],
defaultGridIds: LaunchablePhoneAppId[],
@@ -209,9 +245,9 @@ export function moveHomeApp(
}
if (from === to) {
const displacedApp = source[targetIndex]
source[targetIndex] = appId
source[sourceIndex] = displacedApp
if (sourceIndex === targetIndex) return layout
source[sourceIndex] = null
insertIntoSlot(source, targetIndex, appId)
return next
}
@@ -220,13 +256,6 @@ export function moveHomeApp(
target[duplicateIndex] = null
}
const displacedApp = target[targetIndex]
source[sourceIndex] =
displacedApp &&
displacedApp !== appId &&
!source.some((id, index) => id === displacedApp && index !== sourceIndex)
? displacedApp
: null
target[targetIndex] = appId
source[sourceIndex] = insertIntoSlot(target, targetIndex, appId)
return next
}
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sky Phone</title>
<script type="module" crossorigin src="./assets/sky-index-Bh38VieM.js"></script>
<script type="module" crossorigin src="./assets/sky-index-DqwmUbSx.js"></script>
<link rel="stylesheet" crossorigin href="./assets/sky-index-DXf7PPOf.css">
</head>
<body>