mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-09-01 10:48:55 +00:00
ENH - paginate Gallery in batches of 30
This commit is contained in:
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
filterMedia,
|
||||
formatRecordingDuration,
|
||||
hasNextMediaPage,
|
||||
mediaErrorKey,
|
||||
mergeMedia,
|
||||
} from './media'
|
||||
@@ -32,6 +33,12 @@ describe('media utilities', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('loads another gallery page only after a full 30-item batch', () => {
|
||||
expect(hasNextMediaPage(30)).toBe(true)
|
||||
expect(hasNextMediaPage(29)).toBe(false)
|
||||
expect(hasNextMediaPage(0)).toBe(false)
|
||||
})
|
||||
|
||||
it('formats unlimited recording durations', () => {
|
||||
expect(formatRecordingDuration(0)).toBe('00:00')
|
||||
expect(formatRecordingDuration(3_725_000)).toBe('62:05')
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { GalleryFilter, MediaType, PhoneMedia } from '@/types/media'
|
||||
|
||||
export const MEDIA_PAGE_SIZE = 30
|
||||
|
||||
export function isMediaType(value: unknown): value is MediaType {
|
||||
return value === 'photo' || value === 'video'
|
||||
}
|
||||
@@ -24,6 +26,10 @@ export function mergeMedia(
|
||||
)
|
||||
}
|
||||
|
||||
export function hasNextMediaPage(pageLength: number): boolean {
|
||||
return pageLength === MEDIA_PAGE_SIZE
|
||||
}
|
||||
|
||||
export function formatRecordingDuration(elapsedMs: number): string {
|
||||
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1000))
|
||||
const minutes = Math.floor(totalSeconds / 60)
|
||||
|
||||
@@ -17,14 +17,18 @@ import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { usePhoneStore } from '@/stores/phone'
|
||||
import type { DeleteResult, GalleryFilter, PhoneMedia } from '@/types/media'
|
||||
import { mediaErrorKey, mergeMedia } from '@/utils/media'
|
||||
import {
|
||||
hasNextMediaPage,
|
||||
MEDIA_PAGE_SIZE,
|
||||
mediaErrorKey,
|
||||
mergeMedia,
|
||||
} from '@/utils/media'
|
||||
import { nuiCall } from '@/utils/nui'
|
||||
|
||||
const isDevelopment = import.meta.env.DEV
|
||||
const developmentGalleryState = isDevelopment
|
||||
? new URLSearchParams(window.location.search).get('galleryMock')
|
||||
: null
|
||||
const pageSize = 36
|
||||
const filterItems = [
|
||||
{ id: 'all', label: 'all' },
|
||||
{ id: 'photo', label: 'photos' },
|
||||
@@ -135,14 +139,14 @@ async function fetchMore(): Promise<void> {
|
||||
fetching.value = true
|
||||
const offset = media.value.length
|
||||
const response = await nuiCall<PhoneMedia[]>('gallery:list', {
|
||||
limit: pageSize,
|
||||
limit: MEDIA_PAGE_SIZE,
|
||||
mediaType: filter.value === 'all' ? undefined : filter.value,
|
||||
mockState: developmentGalleryState ?? undefined,
|
||||
offset,
|
||||
})
|
||||
if (response.success && Array.isArray(response.data)) {
|
||||
media.value = mergeMedia(media.value, response.data)
|
||||
hasMore.value = response.data.length === pageSize
|
||||
hasMore.value = hasNextMediaPage(response.data.length)
|
||||
} else if (
|
||||
isDevelopment &&
|
||||
developmentGalleryState !== 'error' &&
|
||||
|
||||
@@ -11,20 +11,18 @@ let authenticated = false
|
||||
let draft = null
|
||||
let linkedAccount = null
|
||||
let mockNotes = []
|
||||
let mockMedia = [
|
||||
{
|
||||
createdAt: Date.now() - 60_000,
|
||||
id: 1,
|
||||
mediaType: 'photo',
|
||||
url: 'https://picsum.photos/seed/sky-phone-1/600/800',
|
||||
},
|
||||
{
|
||||
createdAt: Date.now() - 120_000,
|
||||
id: 2,
|
||||
mediaType: 'video',
|
||||
url: 'https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4',
|
||||
},
|
||||
]
|
||||
let mockMedia = Array.from({ length: 65 }, (_, index) => {
|
||||
const id = index + 1
|
||||
const video = id % 10 === 0
|
||||
return {
|
||||
createdAt: Date.now() - id * 60_000,
|
||||
id,
|
||||
mediaType: video ? 'video' : 'photo',
|
||||
url: video
|
||||
? 'https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4'
|
||||
: `https://picsum.photos/seed/sky-phone-${id}/600/800`,
|
||||
}
|
||||
})
|
||||
const deviceData = {}
|
||||
const accountDevices = [
|
||||
{
|
||||
@@ -145,7 +143,7 @@ app.post('/api/:endpoint', (request, response) => {
|
||||
? mockMedia.filter((item) => item.mediaType === request.body.mediaType)
|
||||
: mockMedia
|
||||
const offset = Number(request.body.offset) || 0
|
||||
const limit = Number(request.body.limit) || 36
|
||||
const limit = Number(request.body.limit) || 30
|
||||
response.json({
|
||||
success: true,
|
||||
data: filtered.slice(offset, offset + limit),
|
||||
|
||||
@@ -13,5 +13,5 @@ Config.Media = {
|
||||
BitrateKbps = 1500,
|
||||
},
|
||||
UploadSessionTimeoutMs = 60000,
|
||||
PageSize = 36,
|
||||
PageSize = 30,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user