ADD - support home screen app folders

This commit is contained in:
smx.pusha
2026-08-13 13:15:25 +02:00
parent 90909e41f2
commit bc4b439eb6
15 changed files with 1976 additions and 194 deletions
+38 -1
View File
@@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { NON_REMOVABLE_PHONE_APP_IDS } from '@/config/apps'
import { useAppStoreStore } from '@/stores/app-store'
import { removeHomeApp } from '@/utils/homeLayout'
import { getHomeFolder, removeHomeApp } from '@/utils/homeLayout'
const mocks = vi.hoisted(() => ({
phone: {
@@ -160,6 +160,43 @@ describe('app store', () => {
})
})
it('persists the complete folder lifecycle through store actions', () => {
const apps = useAppStoreStore()
apps.hydrate(null)
mocks.phone.saveDeviceNamespace.mockClear()
const notesIndex = apps.homeLayout.grid.indexOf('notes')
const clockIndex = apps.homeLayout.grid.indexOf('clock')
const mailIndex = apps.homeLayout.grid.indexOf('mail')
const folderId = apps.createHomeFolder(
'grid',
notesIndex,
'grid',
clockIndex,
'Utilities',
)
expect(folderId).toBeTruthy()
expect(getHomeFolder(apps.homeLayout, folderId!)?.apps).toEqual([
'clock',
'notes',
])
expect(apps.addHomeAppToFolder('grid', mailIndex, folderId!)).toBe(true)
apps.moveHomeFolderApp(folderId!, 2, 0)
apps.renameHomeFolder(folderId!, 'Work')
expect(getHomeFolder(apps.homeLayout, folderId!)).toMatchObject({
apps: ['mail', 'notes', 'clock'],
name: 'Work',
})
const emptyIndex = apps.homeLayout.grid.indexOf(null)
expect(
apps.extractHomeFolderApp(folderId!, 0, 'grid', emptyIndex),
).toBe(true)
expect(apps.homeLayout.grid[emptyIndex]).toBe('mail')
expect(mocks.phone.saveDeviceNamespace).toHaveBeenCalledTimes(5)
})
it('does not commit an installation to a different phone', () => {
vi.useFakeTimers()
const apps = useAppStoreStore()
+90 -2
View File
@@ -12,11 +12,16 @@ import {
import { usePhoneStore } from '@/stores/phone'
import type { LaunchablePhoneAppId } from '@/types/apps'
import {
addHomeAppToFolder,
addHomePage,
createHomeFolder,
createDefaultHomeLayout,
deleteHomePage,
extractHomeFolderApp,
moveHomeFolderApp,
moveHomeApp,
parseHomeLayout,
renameHomeFolder,
removeHomeApp,
restoreHomeApp,
type HomeArea,
@@ -192,7 +197,10 @@ export const useAppStoreStore = defineStore('app-store', {
(id): id is LaunchablePhoneAppId =>
typeof id === 'string' &&
(isPhoneAppId(id) ||
(layoutVersion === 3 && isValidExternalPhoneAppId(id))),
((layoutVersion === 3 ||
layoutVersion === 4 ||
layoutVersion === 5) &&
isValidExternalPhoneAppId(id))),
)
: []
const installedIds = [
@@ -218,7 +226,10 @@ export const useAppStoreStore = defineStore('app-store', {
for (const [appId, count] of Object.entries(data.launchCounts)) {
if (
(isPhoneAppId(appId) ||
(layoutVersion === 3 && isValidExternalPhoneAppId(appId))) &&
((layoutVersion === 3 ||
layoutVersion === 4 ||
layoutVersion === 5) &&
isValidExternalPhoneAppId(appId))) &&
typeof count === 'number' &&
Number.isFinite(count) &&
count > 0
@@ -279,6 +290,83 @@ export const useAppStoreStore = defineStore('app-store', {
)
this.persist()
},
createHomeFolder(
from: HomeArea,
sourceIndex: number,
to: HomeArea,
targetIndex: number,
name: string,
): string | null {
const folderId = `folder-${globalThis.crypto.randomUUID()}`
const next = createHomeFolder(
this.homeLayout,
from,
sourceIndex,
to,
targetIndex,
folderId,
name,
)
if (next === this.homeLayout) return null
this.homeLayout = next
this.persist()
return folderId
},
addHomeAppToFolder(
from: HomeArea,
sourceIndex: number,
folderId: string,
): boolean {
const next = addHomeAppToFolder(
this.homeLayout,
from,
sourceIndex,
folderId,
)
if (next === this.homeLayout) return false
this.homeLayout = next
this.persist()
return true
},
renameHomeFolder(folderId: string, name: string): void {
const next = renameHomeFolder(this.homeLayout, folderId, name)
if (next === this.homeLayout) return
this.homeLayout = next
this.persist()
},
moveHomeFolderApp(
folderId: string,
sourceIndex: number,
targetIndex: number,
): void {
const next = moveHomeFolderApp(
this.homeLayout,
folderId,
sourceIndex,
targetIndex,
)
if (next === this.homeLayout) return
this.homeLayout = next
this.persist()
},
extractHomeFolderApp(
folderId: string,
sourceIndex: number,
to: HomeArea,
targetIndex: number,
): boolean {
const next = extractHomeFolderApp(
this.homeLayout,
folderId,
sourceIndex,
to,
targetIndex,
)
if (next === this.homeLayout) return false
this.homeLayout = next
this.persist()
return true
},
removeHomeApp(appId: LaunchablePhoneAppId): void {
if (isProtectedHomeApp(appId)) return
+7
View File
@@ -3765,6 +3765,13 @@ const defaultLocales: LocaleTree = {
removedFromHome: 'Removed from Home Screen',
page: 'Page',
pages: 'Home screen pages',
folders: {
defaultName: 'Folder',
close: 'Close folder',
rename: 'Rename Folder',
name: 'Folder name',
pages: 'Folder pages',
},
groups: {
suggestions: 'Suggestions',
recentlyAdded: 'Recently Added',