mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-09-04 16:23:22 +00:00
ENH - update SMS branch from dev
This commit is contained in:
@@ -1,16 +1,20 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { PHONE_APPS } from './apps'
|
||||
import { isPhoneAppId, PHONE_APPS } from './apps'
|
||||
describe('app registry', () => {
|
||||
it('has unique ids and routes with the reference dock order', () => {
|
||||
expect(new Set(PHONE_APPS.map((app) => app.id)).size).toBe(
|
||||
PHONE_APPS.length,
|
||||
)
|
||||
expect(PHONE_APPS.every((app) => app.route === `/apps/${app.id}`)).toBe(
|
||||
true,
|
||||
)
|
||||
expect(PHONE_APPS.every((app) => app.iconImage.endsWith('.webp'))).toBe(
|
||||
true,
|
||||
)
|
||||
expect(
|
||||
PHONE_APPS.every(
|
||||
(app) => app.route === null || app.route === `/apps/${app.id}`,
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
PHONE_APPS.every(
|
||||
(app) => typeof app.iconImage === 'string' && app.iconImage.length > 0,
|
||||
),
|
||||
).toBe(true)
|
||||
expect(PHONE_APPS.find((app) => app.id === 'phone')).toMatchObject({
|
||||
dockOrder: 0,
|
||||
labelKey: 'Apps.phone.name',
|
||||
@@ -26,10 +30,72 @@ describe('app registry', () => {
|
||||
labelKey: 'Apps.weather.name',
|
||||
route: '/apps/weather',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'calendar')).toMatchObject({
|
||||
gridOrder: 21,
|
||||
labelKey: 'Apps.calendar.name',
|
||||
route: '/apps/calendar',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'snake')).toMatchObject({
|
||||
dockOrder: null,
|
||||
gridOrder: 12,
|
||||
labelKey: 'Apps.snake.name',
|
||||
route: '/apps/snake',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'memory')).toMatchObject({
|
||||
dockOrder: null,
|
||||
gridOrder: 13,
|
||||
labelKey: 'Apps.memory.name',
|
||||
route: '/apps/memory',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'number-merge')).toMatchObject({
|
||||
dockOrder: null,
|
||||
gridOrder: 14,
|
||||
labelKey: 'Apps.numberMerge.name',
|
||||
route: '/apps/number-merge',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'minesweeper')).toMatchObject({
|
||||
dockOrder: null,
|
||||
gridOrder: 15,
|
||||
labelKey: 'Apps.minesweeper.name',
|
||||
route: '/apps/minesweeper',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'tower-stack')).toMatchObject({
|
||||
dockOrder: null,
|
||||
gridOrder: 16,
|
||||
labelKey: 'Apps.towerStack.name',
|
||||
route: '/apps/tower-stack',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'sky-flappy')).toMatchObject({
|
||||
dockOrder: null,
|
||||
gridOrder: 17,
|
||||
labelKey: 'Apps.skyFlappy.name',
|
||||
route: '/apps/sky-flappy',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'neon-drop')).toMatchObject({
|
||||
dockOrder: null,
|
||||
gridOrder: 18,
|
||||
labelKey: 'Apps.neonDrop.name',
|
||||
route: '/apps/neon-drop',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'citymarkt')).toMatchObject({
|
||||
dockOrder: null,
|
||||
gridOrder: 19,
|
||||
labelKey: 'Apps.citymarkt.name',
|
||||
route: '/apps/citymarkt',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'camera')).toMatchObject({
|
||||
route: '/apps/camera',
|
||||
})
|
||||
expect(PHONE_APPS.find((app) => app.id === 'photos')).toMatchObject({
|
||||
route: '/apps/photos',
|
||||
})
|
||||
expect(isPhoneAppId('camera')).toBe(true)
|
||||
expect(isPhoneAppId('photos')).toBe(true)
|
||||
expect(isPhoneAppId('clock')).toBe(true)
|
||||
expect(
|
||||
PHONE_APPS.filter((app) => app.dockOrder !== null)
|
||||
.sort((a, b) => (a.dockOrder ?? 0) - (b.dockOrder ?? 0))
|
||||
.map((app) => app.id),
|
||||
).toEqual(['phone', 'messages', 'calculator'])
|
||||
).toEqual(['phone', 'messages', 'camera', 'clock'])
|
||||
})
|
||||
})
|
||||
|
||||
+182
-6
@@ -1,7 +1,15 @@
|
||||
import {
|
||||
Calculator,
|
||||
Bomb,
|
||||
Blocks,
|
||||
Camera,
|
||||
CalendarDays,
|
||||
Clock3,
|
||||
Gamepad2,
|
||||
Grid2X2,
|
||||
Brain,
|
||||
Images,
|
||||
Layers3,
|
||||
Mail,
|
||||
MapPinned,
|
||||
MessageCircle,
|
||||
@@ -10,12 +18,17 @@ import {
|
||||
Settings,
|
||||
ShoppingBag,
|
||||
CloudSun,
|
||||
Wind,
|
||||
Tag,
|
||||
MapPinHouse,
|
||||
} from 'lucide-vue-next'
|
||||
import { defineAsyncComponent, markRaw } from 'vue'
|
||||
|
||||
import appStoreIcon from '@/assets/img/app-icons/apps.webp'
|
||||
import calculatorIcon from '@/assets/img/app-icons/calculator.webp'
|
||||
import cameraIcon from '@/assets/img/app-icons/camera.webp'
|
||||
import clockIcon from '@/assets/img/app-icons/clock.webp'
|
||||
import calendarIcon from '@/assets/img/app-icons/calendar.svg'
|
||||
import mailIcon from '@/assets/img/app-icons/mail.webp'
|
||||
import mapIcon from '@/assets/img/app-icons/map.webp'
|
||||
import messagesIcon from '@/assets/img/app-icons/sms.webp'
|
||||
@@ -23,10 +36,49 @@ import notesIcon from '@/assets/img/app-icons/notes.webp'
|
||||
import photosIcon from '@/assets/img/app-icons/gallery.webp'
|
||||
import phoneIcon from '@/assets/img/app-icons/phone.webp'
|
||||
import settingsIcon from '@/assets/img/app-icons/settings.webp'
|
||||
import snakeIcon from '@/assets/img/app-icons/snake.webp'
|
||||
import memoryIcon from '@/assets/img/app-icons/memory.webp'
|
||||
import numberMergeIcon from '@/assets/img/app-icons/number-merge.webp'
|
||||
import minesweeperIcon from '@/assets/img/app-icons/minesweeper.webp'
|
||||
import towerStackIcon from '@/assets/img/app-icons/tower-stack.webp'
|
||||
import skyFlappyIcon from '@/assets/img/app-icons/sky-flappy.webp'
|
||||
import neonDropIcon from '@/assets/img/app-icons/neon-drop.webp'
|
||||
import weatherIcon from '@/assets/img/app-icons/weather.webp'
|
||||
import type { PhoneAppDefinition, PhoneAppId } from '@/types/apps'
|
||||
import citymarktIcon from '@/assets/img/app-icons/citymarkt.webp'
|
||||
import localPagesIcon from '@/assets/img/app-icons/local-pages.webp'
|
||||
import type {
|
||||
LaunchablePhoneAppDefinition,
|
||||
LaunchablePhoneAppId,
|
||||
PhoneAppDefinition,
|
||||
} from '@/types/apps'
|
||||
|
||||
export const PHONE_APPS: PhoneAppDefinition[] = [
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/CalendarApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 21,
|
||||
icon: markRaw(CalendarDays),
|
||||
iconClass: 'app-icon--calendar',
|
||||
iconImage: calendarIcon,
|
||||
id: 'calendar',
|
||||
labelKey: 'Apps.calendar.name',
|
||||
route: '/apps/calendar',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/LocalPagesApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 20,
|
||||
icon: markRaw(MapPinHouse),
|
||||
iconClass: 'app-icon--local-pages',
|
||||
iconImage: localPagesIcon,
|
||||
id: 'local-pages',
|
||||
labelKey: 'Apps.localPages.name',
|
||||
route: '/apps/local-pages',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/PhoneApp.vue')),
|
||||
@@ -96,7 +148,7 @@ export const PHONE_APPS: PhoneAppDefinition[] = [
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/CalculatorApp.vue')),
|
||||
),
|
||||
dockOrder: 2,
|
||||
dockOrder: null,
|
||||
gridOrder: 2,
|
||||
icon: markRaw(Calculator),
|
||||
iconClass: 'app-icon--calculator',
|
||||
@@ -105,11 +157,24 @@ export const PHONE_APPS: PhoneAppDefinition[] = [
|
||||
labelKey: 'Apps.calculator.name',
|
||||
route: '/apps/calculator',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/CameraApp.vue')),
|
||||
),
|
||||
dockOrder: 2,
|
||||
gridOrder: 3,
|
||||
icon: markRaw(Camera),
|
||||
iconClass: 'app-icon--camera',
|
||||
iconImage: cameraIcon,
|
||||
id: 'camera',
|
||||
labelKey: 'Apps.camera.name',
|
||||
route: '/apps/camera',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/ClockApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
dockOrder: 3,
|
||||
gridOrder: 4,
|
||||
icon: markRaw(Clock3),
|
||||
iconClass: 'app-icon--clock',
|
||||
@@ -133,7 +198,7 @@ export const PHONE_APPS: PhoneAppDefinition[] = [
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/PhotosApp.vue')),
|
||||
defineAsyncComponent(() => import('@/views/apps/GalleryApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 8,
|
||||
@@ -170,6 +235,110 @@ export const PHONE_APPS: PhoneAppDefinition[] = [
|
||||
labelKey: 'Apps.settings.name',
|
||||
route: '/apps/settings',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/SnakeApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 12,
|
||||
icon: markRaw(Gamepad2),
|
||||
iconClass: 'app-icon--snake',
|
||||
iconImage: snakeIcon,
|
||||
id: 'snake',
|
||||
labelKey: 'Apps.snake.name',
|
||||
route: '/apps/snake',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/MemoryApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 13,
|
||||
icon: markRaw(Brain),
|
||||
iconClass: 'app-icon--memory',
|
||||
iconImage: memoryIcon,
|
||||
id: 'memory',
|
||||
labelKey: 'Apps.memory.name',
|
||||
route: '/apps/memory',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/NumberMergeApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 14,
|
||||
icon: markRaw(Grid2X2),
|
||||
iconClass: 'app-icon--number-merge',
|
||||
iconImage: numberMergeIcon,
|
||||
id: 'number-merge',
|
||||
labelKey: 'Apps.numberMerge.name',
|
||||
route: '/apps/number-merge',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/MinesweeperApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 15,
|
||||
icon: markRaw(Bomb),
|
||||
iconClass: 'app-icon--minesweeper',
|
||||
iconImage: minesweeperIcon,
|
||||
id: 'minesweeper',
|
||||
labelKey: 'Apps.minesweeper.name',
|
||||
route: '/apps/minesweeper',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/TowerStackApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 16,
|
||||
icon: markRaw(Layers3),
|
||||
iconClass: 'app-icon--tower-stack',
|
||||
iconImage: towerStackIcon,
|
||||
id: 'tower-stack',
|
||||
labelKey: 'Apps.towerStack.name',
|
||||
route: '/apps/tower-stack',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/SkyFlappyApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 17,
|
||||
icon: markRaw(Wind),
|
||||
iconClass: 'app-icon--sky-flappy',
|
||||
iconImage: skyFlappyIcon,
|
||||
id: 'sky-flappy',
|
||||
labelKey: 'Apps.skyFlappy.name',
|
||||
route: '/apps/sky-flappy',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/CityMarktApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 19,
|
||||
icon: markRaw(Tag),
|
||||
iconClass: 'app-icon--citymarkt',
|
||||
iconImage: citymarktIcon,
|
||||
id: 'citymarkt',
|
||||
labelKey: 'Apps.citymarkt.name',
|
||||
route: '/apps/citymarkt',
|
||||
},
|
||||
{
|
||||
component: markRaw(
|
||||
defineAsyncComponent(() => import('@/views/apps/NeonDropApp.vue')),
|
||||
),
|
||||
dockOrder: null,
|
||||
gridOrder: 18,
|
||||
icon: markRaw(Blocks),
|
||||
iconClass: 'app-icon--neon-drop',
|
||||
iconImage: neonDropIcon,
|
||||
id: 'neon-drop',
|
||||
labelKey: 'Apps.neonDrop.name',
|
||||
route: '/apps/neon-drop',
|
||||
},
|
||||
]
|
||||
|
||||
export const PHONE_APP_IDS = PHONE_APPS.map((app) => app.id)
|
||||
@@ -181,6 +350,13 @@ export function getPhoneApp(
|
||||
return PHONE_APPS.find((app) => app.id === appId)
|
||||
}
|
||||
|
||||
export function isPhoneAppId(value: string): value is PhoneAppId {
|
||||
return PHONE_APP_IDS.includes(value as PhoneAppId)
|
||||
export function isPhoneAppId(value: string): value is LaunchablePhoneAppId {
|
||||
const app = getPhoneApp(value)
|
||||
return !!app && isLaunchablePhoneApp(app)
|
||||
}
|
||||
|
||||
export function isLaunchablePhoneApp(
|
||||
app: PhoneAppDefinition,
|
||||
): app is LaunchablePhoneAppDefinition {
|
||||
return app.component !== null && app.route !== null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user