diff --git a/frontend/src/views/Home/Home.js b/frontend/src/views/Home/Home.js index a1c3102..91eb7b1 100644 --- a/frontend/src/views/Home/Home.js +++ b/frontend/src/views/Home/Home.js @@ -35,22 +35,23 @@ export function useHome() { const message = ref('') const error = ref('') let eventSource = null + let refreshTimer = null + let refreshGeneration = 0 const isLoggedIn = computed(() => Boolean(user.value && session.value)) const canUpload = computed(() => user.value?.role === 'developer' || user.value?.role === 'admin') const isAdmin = computed(() => user.value?.role === 'admin') const isScoutPackage = computed(() => uploadForm.value.file?.name.toLowerCase().endsWith('.scout')) const platformOptions = ['windows', 'macos', 'linux', 'android', 'any'] - const architectureOptions = computed(() => { - const platform = filters.value.platform || uploadForm.value.platform - const options = { - windows: ['amd64', 'arm64', '386'], - macos: ['amd64', 'arm64'], - linux: ['amd64', 'arm64', '386', 'armv7'], - android: ['arm64', 'armv7', '386'], - } - return options[platform] || ['amd64', 'arm64', '386', 'armv7', 'universal'] - }) + const architectureOptionsByPlatform = { + windows: ['amd64', 'arm64', '386'], + macos: ['amd64', 'arm64'], + linux: ['amd64', 'arm64', '386', 'armv7'], + android: ['arm64', 'armv7', '386'], + } + const universalArchitectureOptions = ['amd64', 'arm64', '386', 'armv7', 'universal'] + const filterArchitectureOptions = computed(() => architectureOptionsByPlatform[filters.value.platform] || universalArchitectureOptions) + const uploadArchitectureOptions = computed(() => architectureOptionsByPlatform[uploadForm.value.platform] || universalArchitectureOptions) const channelOptions = ['stable', 'beta', 'dev'] function roleText(role) { @@ -110,6 +111,41 @@ export function useHome() { } } + async function refreshPackages() { + if (refreshTimer) { + clearTimeout(refreshTimer) + refreshTimer = null + } + const generation = ++refreshGeneration + await loadPackages() + if (generation === refreshGeneration) { + startNotifications() + } + } + + function scheduleRefresh() { + if (refreshTimer) { + clearTimeout(refreshTimer) + } + refreshTimer = setTimeout(() => { + refreshTimer = null + void refreshPackages() + }, 180) + } + + function normalizeFilterArchitecture() { + if (filters.value.architecture && !filterArchitectureOptions.value.includes(filters.value.architecture)) { + filters.value.architecture = '' + } + scheduleRefresh() + } + + function normalizeUploadArchitecture() { + if (uploadForm.value.architecture && !uploadArchitectureOptions.value.includes(uploadForm.value.architecture)) { + uploadForm.value.architecture = '' + } + } + async function selectPackage(item) { selectedPackage.value = item error.value = '' @@ -168,7 +204,7 @@ export function useHome() { uploadForm.value.file = null const fileInput = document.querySelector('#package-file') if (fileInput) fileInput.value = '' - await loadPackages() + await refreshPackages() } catch (reason) { error.value = reason.message } finally { @@ -321,6 +357,10 @@ export function useHome() { function stopNotifications() { eventSource?.close() eventSource = null + if (refreshTimer) { + clearTimeout(refreshTimer) + refreshTimer = null + } } return { @@ -348,10 +388,15 @@ export function useHome() { isAdmin, isScoutPackage, platformOptions, - architectureOptions, + filterArchitectureOptions, + uploadArchitectureOptions, channelOptions, roleText, loadPackages, + refreshPackages, + scheduleRefresh, + normalizeFilterArchitecture, + normalizeUploadArchitecture, selectPackage, onFileChange, uploadPackage, @@ -367,4 +412,3 @@ export function useHome() { stopNotifications, } } - diff --git a/frontend/src/views/Home/Home.vue b/frontend/src/views/Home/Home.vue index ea97436..bbd9d58 100644 --- a/frontend/src/views/Home/Home.vue +++ b/frontend/src/views/Home/Home.vue @@ -1,5 +1,5 @@ @@ -80,16 +85,16 @@ onUnmounted(stopNotifications) - +