mirror of
https://github.com/xpltdco/media-rip.git
synced 2026-04-03 02:53:58 -06:00
Mobile queue badge + fix paste-then-download race condition
Mobile: - Queue tab shows badge with active job count (queued/downloading) - Badge hidden when user is already on Queue tab - Styled as accent-colored pill with count (caps at 9+) Paste race fix: - Set isAnalyzing=true immediately on paste event, not after 50ms timeout - Prevents Download button from being briefly clickable between paste and analysis start - Handles edge case where URL is cleared before timeout fires
This commit is contained in:
parent
1b5f24f796
commit
f72b649acf
2 changed files with 44 additions and 2 deletions
|
|
@ -1,13 +1,26 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useThemeStore } from '@/stores/theme'
|
import { useThemeStore } from '@/stores/theme'
|
||||||
|
import { useDownloadsStore } from '@/stores/downloads'
|
||||||
import WireframeBackground from './WireframeBackground.vue'
|
import WireframeBackground from './WireframeBackground.vue'
|
||||||
|
|
||||||
const themeStore = useThemeStore()
|
const themeStore = useThemeStore()
|
||||||
|
const downloadsStore = useDownloadsStore()
|
||||||
const showWireframe = computed(() => themeStore.currentTheme === 'cyberpunk')
|
const showWireframe = computed(() => themeStore.currentTheme === 'cyberpunk')
|
||||||
|
|
||||||
type MobileTab = 'submit' | 'queue'
|
type MobileTab = 'submit' | 'queue'
|
||||||
const activeTab = ref<MobileTab>('submit')
|
const activeTab = ref<MobileTab>('submit')
|
||||||
|
|
||||||
|
/** Number of active (non-terminal) jobs — shown as badge on Queue tab */
|
||||||
|
const queueBadge = computed(() => {
|
||||||
|
let count = 0
|
||||||
|
for (const job of downloadsStore.jobs.values()) {
|
||||||
|
if (job.status === 'queued' || job.status === 'downloading' || job.status === 'extracting') {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -41,7 +54,10 @@ const activeTab = ref<MobileTab>('submit')
|
||||||
:class="{ active: activeTab === 'queue' }"
|
:class="{ active: activeTab === 'queue' }"
|
||||||
@click="activeTab = 'queue'"
|
@click="activeTab = 'queue'"
|
||||||
>
|
>
|
||||||
<span class="nav-icon">☰</span>
|
<span class="nav-icon-wrap">
|
||||||
|
<span class="nav-icon">☰</span>
|
||||||
|
<span v-if="queueBadge > 0 && activeTab !== 'queue'" class="nav-badge">{{ queueBadge > 9 ? '9+' : queueBadge }}</span>
|
||||||
|
</span>
|
||||||
<span class="nav-label">Queue</span>
|
<span class="nav-label">Queue</span>
|
||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
@ -136,5 +152,26 @@ const activeTab = ref<MobileTab>('submit')
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-icon-wrap {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
right: -10px;
|
||||||
|
background: var(--color-accent);
|
||||||
|
color: var(--color-bg);
|
||||||
|
font-size: 0.6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
min-width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
line-height: 16px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: var(--radius-full);
|
||||||
|
padding: 0 3px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -184,10 +184,12 @@ function onFormatSelect(formatId: string | null): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePaste(): void {
|
function handlePaste(): void {
|
||||||
|
// Immediately signal that analysis is starting — prevents the Download
|
||||||
|
// button from being briefly clickable between paste and analysis.
|
||||||
|
isAnalyzing.value = true
|
||||||
// Auto-extract on paste — unified loading state
|
// Auto-extract on paste — unified loading state
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
if (url.value.trim()) {
|
if (url.value.trim()) {
|
||||||
isAnalyzing.value = true
|
|
||||||
analyzeError.value = null
|
analyzeError.value = null
|
||||||
startAnalyzePhase()
|
startAnalyzePhase()
|
||||||
try {
|
try {
|
||||||
|
|
@ -204,6 +206,9 @@ function handlePaste(): void {
|
||||||
isAnalyzing.value = false
|
isAnalyzing.value = false
|
||||||
stopAnalyzePhase()
|
stopAnalyzePhase()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// URL was cleared before timeout — cancel analysis state
|
||||||
|
isAnalyzing.value = false
|
||||||
}
|
}
|
||||||
}, 50)
|
}, 50)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue