Merge pull request #593 from arabcoders/dev
Some checks failed
native-build / build (amd64, ubuntu-latest) (push) Has been cancelled
native-build / build (amd64, windows-latest) (push) Has been cancelled
native-build / build (arm64, macos-latest) (push) Has been cancelled
native-build / build (arm64, ubuntu-latest) (push) Has been cancelled
native-build / build (arm64, windows-latest) (push) Has been cancelled

refactor: re-add the automatic history update after download
This commit is contained in:
Abdulmohsen 2026-04-26 20:26:51 +03:00 committed by GitHub
commit cb1c355e58
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 165 additions and 131 deletions

View file

@ -33,6 +33,22 @@
} }
@layer components { @layer components {
.feature-meta-grid {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 0.5rem;
}
@media (width >= 40rem) {
.feature-meta-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.feature-meta-grid > :last-child:nth-child(odd) {
grid-column: 1 / -1;
}
}
.shell-surface { .shell-surface {
background: background:
radial-gradient(circle at top left, rgb(99 102 241 / 0.1), transparent 28%), radial-gradient(circle at top left, rgb(99 102 241 / 0.1), transparent 28%),

View file

@ -714,6 +714,7 @@ const {
loadHistory, loadHistory,
reloadHistory, reloadHistory,
deleteHistoryItems, deleteHistoryItems,
historyMoveHandler,
} = useHistoryState(); } = useHistoryState();
const embedUrl = ref(''); const embedUrl = ref('');
@ -1271,19 +1272,9 @@ const deleteHistoryItem = async (item: StoreItem): Promise<void> => {
toast.info('Removed from history queue.'); toast.info('Removed from history queue.');
}; };
const handleHistoryItemMoved = (payload: { data: { to: 'queue' | 'history' } }): void => { const handleHistoryItemMoved = historyMoveHandler(
if (!simpleMode.value || !historyInitialized.value) { () => simpleMode.value && historyInitialized.value,
return; );
}
if ('history' !== payload.data.to || 1 !== pagination.value.page) {
return;
}
window.setTimeout(() => {
void reloadHistory({ order: 'DESC', perPage: configStore.app.default_pagination });
}, 1000);
};
const showMessage = (item: StoreItem): boolean => { const showMessage = (item: StoreItem): boolean => {
if (!item?.msg || item.msg === item?.error) { if (!item?.msg || item.msg === item?.error) {

View file

@ -1,6 +1,7 @@
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { useNotification } from '~/composables/useNotification'; import { useNotification } from '~/composables/useNotification';
import type { WSEP } from '~/types/sockets';
import { useYtpConfig } from '~/composables/useYtpConfig'; import { useYtpConfig } from '~/composables/useYtpConfig';
import { parse_api_error, parse_list_response, request } from '~/utils'; import { parse_api_error, parse_list_response, request } from '~/utils';
import type { Pagination } from '~/types/responses'; import type { Pagination } from '~/types/responses';
@ -168,6 +169,44 @@ const resetHistory = (): void => {
lastError.value = null; lastError.value = null;
}; };
const addHistoryItem = (item: StoreItem): void => {
const existingIndex = items.value.findIndex((existing) => existing._id === item._id);
if (existingIndex !== -1) {
items.value = [
item,
...items.value.slice(0, existingIndex),
...items.value.slice(existingIndex + 1),
];
return;
}
items.value = [item, ...items.value];
pagination.value.total++;
if (items.value.length > pagination.value.per_page) {
items.value = items.value.slice(0, pagination.value.per_page);
}
pagination.value.total_pages = Math.max(
1,
Math.ceil(pagination.value.total / pagination.value.per_page),
);
pagination.value.has_next = pagination.value.page < pagination.value.total_pages;
};
const historyMoveHandler = (
shouldHandle: () => boolean = () => isLoaded.value,
): ((payload: WSEP['item_moved']) => void) => {
return (payload: WSEP['item_moved']): void => {
if ('history' !== payload.data.to || !shouldHandle()) {
return;
}
addHistoryItem(payload.data.item);
};
};
export const useHistoryState = () => { export const useHistoryState = () => {
return { return {
items, items,
@ -180,5 +219,7 @@ export const useHistoryState = () => {
reloadHistory, reloadHistory,
deleteHistoryItems, deleteHistoryItems,
resetHistory, resetHistory,
upsertHistoryItem: addHistoryItem,
historyMoveHandler,
}; };
}; };

View file

@ -309,57 +309,48 @@
</span> </span>
</div> </div>
<button <div class="feature-meta-grid">
type="button" <button
class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left" type="button"
@click="toggleExpand(cond.id, 'filter')" class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
> @click="toggleExpand(cond.id, 'filter')"
<UIcon name="i-lucide-filter" class="mt-0.5 size-4 shrink-0 text-toned" /> >
<div class="min-w-0 flex-1"> <UIcon name="i-lucide-filter" class="mt-0.5 size-4 shrink-0 text-toned" />
<div class="text-xs font-medium text-toned">Filter</div> <div class="min-w-0 flex-1">
<span :class="['block', expandClass(cond.id, 'filter')]">{{ cond.filter }}</span> <div class="text-xs font-medium text-toned">Filter</div>
</div> <span :class="['block', expandClass(cond.id, 'filter')]">{{ cond.filter }}</span>
</button> </div>
</button>
<div v-if="cond.cli || cond.description" class="grid grid-cols-1 gap-2 sm:grid-cols-2">
<button <button
v-if="cond.cli" v-if="cond.cli"
type="button" type="button"
:class="[ class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
'flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left',
!cond.description && 'sm:col-span-2',
]"
@click="toggleExpand(cond.id, 'cli')" @click="toggleExpand(cond.id, 'cli')"
> >
<UIcon name="i-lucide-terminal" class="mt-0.5 size-4 shrink-0 text-toned" /> <UIcon name="i-lucide-terminal" class="mt-0.5 size-4 shrink-0 text-toned" />
<div class="min-w-0 flex-1"> <div class="min-w-0 flex-1">
<div class="text-xs font-medium text-toned">CLI</div> <div class="text-xs font-medium text-toned">CLI options</div>
<span :class="['block', expandClass(cond.id, 'cli')]">{{ cond.cli }}</span> <span :class="['block', expandClass(cond.id, 'cli')]">{{ cond.cli }}</span>
</div> </div>
</button> </button>
<button
v-if="cond.description"
type="button"
:class="[
'flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left',
!cond.cli && 'sm:col-span-2',
]"
@click="toggleExpand(cond.id, 'description')"
>
<UIcon
name="i-lucide-message-square-text"
class="mt-0.5 size-4 shrink-0 text-toned"
/>
<div class="min-w-0 flex-1">
<div class="text-xs font-medium text-toned">Description</div>
<span :class="['block', expandClass(cond.id, 'description')]">{{
cond.description
}}</span>
</div>
</button>
</div> </div>
<button
v-if="cond.description"
type="button"
class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
@click="toggleExpand(cond.id, 'description')"
>
<UIcon name="i-lucide-align-left" class="mt-0.5 size-4 shrink-0 text-toned" />
<div class="min-w-0 flex-1">
<div class="text-xs font-medium text-toned">Description</div>
<span :class="['block', expandClass(cond.id, 'description')]">{{
cond.description
}}</span>
</div>
</button>
<div <div
v-if="extrasEntries(cond.extras).length > 0" v-if="extrasEntries(cond.extras).length > 0"
class="rounded-md border border-default bg-muted/20 px-3 py-2" class="rounded-md border border-default bg-muted/20 px-3 py-2"

View file

@ -300,13 +300,10 @@
</span> </span>
</div> </div>
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2"> <div class="feature-meta-grid">
<button <button
type="button" type="button"
:class="[ class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
'flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left',
!field.description && 'sm:col-span-2',
]"
@click="toggleExpand(field.id, 'field')" @click="toggleExpand(field.id, 'field')"
> >
<UIcon name="i-lucide-terminal" class="mt-0.5 size-4 shrink-0 text-toned" /> <UIcon name="i-lucide-terminal" class="mt-0.5 size-4 shrink-0 text-toned" />

View file

@ -761,6 +761,7 @@ import moment from 'moment';
import { useStorage } from '@vueuse/core'; import { useStorage } from '@vueuse/core';
import { useConfirm } from '~/composables/useConfirm'; import { useConfirm } from '~/composables/useConfirm';
import { useDialog } from '~/composables/useDialog'; import { useDialog } from '~/composables/useDialog';
import { useAppSocket } from '~/composables/useAppSocket';
import { useExpandableMeta } from '~/composables/useExpandableMeta'; import { useExpandableMeta } from '~/composables/useExpandableMeta';
import { useHistoryState } from '~/composables/useHistoryState'; import { useHistoryState } from '~/composables/useHistoryState';
import { useMediaQuery } from '~/composables/useMediaQuery'; import { useMediaQuery } from '~/composables/useMediaQuery';
@ -782,6 +783,7 @@ import { requirePageShell } from '~/utils/topLevelNavigation';
const config = useYtpConfig(); const config = useYtpConfig();
const stateStore = useQueueState(); const stateStore = useQueueState();
const socketStore = useAppSocket();
const toast = useNotification(); const toast = useNotification();
const box = useConfirm(); const box = useConfirm();
const { confirmDialog } = useDialog(); const { confirmDialog } = useDialog();
@ -798,6 +800,7 @@ const {
loadHistory, loadHistory,
reloadHistory, reloadHistory,
deleteHistoryItems, deleteHistoryItems,
historyMoveHandler,
} = useHistoryState(); } = useHistoryState();
const show_thumbnail = useStorage<boolean>('show_thumbnail', true); const show_thumbnail = useStorage<boolean>('show_thumbnail', true);
@ -834,10 +837,17 @@ const paginationInfo = computed(() => ({
isLoaded: isLoaded.value, isLoaded: isLoaded.value,
})); }));
const handleHistoryItemMoved = historyMoveHandler();
onMounted(async () => { onMounted(async () => {
socketStore.on('item_moved', handleHistoryItemMoved);
await loadHistory(1, { order: 'DESC', perPage: config.app.default_pagination }); await loadHistory(1, { order: 'DESC', perPage: config.app.default_pagination });
}); });
onBeforeUnmount(() => {
socketStore.off('item_moved', handleHistoryItemMoved);
});
watch(showFilter, () => { watch(showFilter, () => {
if (!showFilter.value) { if (!showFilter.value) {
query.value = ''; query.value = '';

View file

@ -363,29 +363,44 @@
</span> </span>
</div> </div>
<button <div class="feature-meta-grid">
type="button" <button
class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left" type="button"
@click="toggleExpand(item.id, 'url')" class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
> @click="toggleExpand(item.id, 'url')"
<UIcon name="i-lucide-link" class="mt-0.5 size-4 shrink-0 text-toned" /> >
<div class="min-w-0 flex-1"> <UIcon name="i-lucide-link" class="mt-0.5 size-4 shrink-0 text-toned" />
<div class="text-xs font-medium text-toned">Target URL</div> <div class="min-w-0 flex-1">
<a <div class="text-xs font-medium text-toned">Target URL</div>
:href="item.request.url" <a
target="_blank" :href="item.request.url"
rel="noreferrer" target="_blank"
class="block text-highlighted hover:underline" rel="noreferrer"
@click.stop class="block text-highlighted hover:underline"
> @click.stop
<span :class="['block', expandClass(item.id, 'url')]"> >
{{ item.request.url }} <span :class="['block', expandClass(item.id, 'url')]">
</span> {{ item.request.url }}
</a> </span>
</div> </a>
</button> </div>
</button>
<button
v-if="headerKeys(item).length > 0"
type="button"
class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
@click="toggleExpand(item.id, 'headers')"
>
<UIcon name="i-lucide-key" class="mt-0.5 size-4 shrink-0 text-toned" />
<div class="min-w-0 flex-1">
<div class="text-xs font-medium text-toned">Headers</div>
<span :class="['block', expandClass(item.id, 'headers')]">
{{ headerKeys(item).join(', ') }}
</span>
</div>
</button>
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2">
<button <button
type="button" type="button"
class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left" class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
@ -417,21 +432,6 @@
</div> </div>
</button> </button>
</div> </div>
<button
v-if="headerKeys(item).length > 0"
type="button"
class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
@click="toggleExpand(item.id, 'headers')"
>
<UIcon name="i-lucide-key" class="mt-0.5 size-4 shrink-0 text-toned" />
<div class="min-w-0 flex-1">
<div class="text-xs font-medium text-toned">Headers</div>
<span :class="['block', expandClass(item.id, 'headers')]">
{{ headerKeys(item).join(', ') }}
</span>
</div>
</button>
</div> </div>
<template #footer> <template #footer>

View file

@ -306,29 +306,26 @@
</span> </span>
</div> </div>
<button <div v-if="item.folder || item.template || item.cli" class="feature-meta-grid">
v-if="item.folder" <button
type="button" v-if="item.folder"
class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left" type="button"
@click="toggleExpand(item.id, 'folder')" class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
> @click="toggleExpand(item.id, 'folder')"
<UIcon name="i-lucide-folder-output" class="mt-0.5 size-4 shrink-0 text-toned" /> >
<div class="min-w-0 flex-1"> <UIcon name="i-lucide-folder-output" class="mt-0.5 size-4 shrink-0 text-toned" />
<div class="text-xs font-medium text-toned">Download path</div> <div class="min-w-0 flex-1">
<span :class="['block', expandClass(item.id, 'folder')]">{{ <div class="text-xs font-medium text-toned">Download path</div>
calcPath(item.folder) <span :class="['block', expandClass(item.id, 'folder')]">{{
}}</span> calcPath(item.folder)
</div> }}</span>
</button> </div>
</button>
<div v-if="item.template || item.cli" class="grid grid-cols-1 gap-2 sm:grid-cols-2">
<button <button
v-if="item.template" v-if="item.template"
type="button" type="button"
:class="[ class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
'flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left',
!item.cli && 'sm:col-span-2',
]"
@click="toggleExpand(item.id, 'template')" @click="toggleExpand(item.id, 'template')"
> >
<UIcon name="i-lucide-file-code-2" class="mt-0.5 size-4 shrink-0 text-toned" /> <UIcon name="i-lucide-file-code-2" class="mt-0.5 size-4 shrink-0 text-toned" />
@ -343,10 +340,7 @@
<button <button
v-if="item.cli" v-if="item.cli"
type="button" type="button"
:class="[ class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
'flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left',
!item.template && 'sm:col-span-2',
]"
@click="toggleExpand(item.id, 'cli')" @click="toggleExpand(item.id, 'cli')"
> >
<UIcon name="i-lucide-terminal" class="mt-0.5 size-4 shrink-0 text-toned" /> <UIcon name="i-lucide-terminal" class="mt-0.5 size-4 shrink-0 text-toned" />

View file

@ -470,13 +470,15 @@
</button> </button>
</div> </div>
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2"> <div
v-if="
item.timer || item.folder || item.template || item.cli || willTaskBeProcessed(item)
"
class="feature-meta-grid"
>
<button <button
type="button" type="button"
:class="[ class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
'flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left',
!item.folder && 'sm:col-span-2',
]"
@click="toggleExpand(item.id, 'schedule')" @click="toggleExpand(item.id, 'schedule')"
> >
<UIcon <UIcon
@ -532,16 +534,11 @@
</span> </span>
</div> </div>
</button> </button>
</div>
<div v-if="item.template || item.cli" class="grid grid-cols-1 gap-2 sm:grid-cols-2">
<button <button
v-if="item.template" v-if="item.template"
type="button" type="button"
:class="[ class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
'flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left',
!item.cli && 'sm:col-span-2',
]"
@click="toggleExpand(item.id, 'template')" @click="toggleExpand(item.id, 'template')"
> >
<UIcon name="i-lucide-file-code-2" class="mt-0.5 size-4 shrink-0 text-toned" /> <UIcon name="i-lucide-file-code-2" class="mt-0.5 size-4 shrink-0 text-toned" />
@ -556,10 +553,7 @@
<button <button
v-if="item.cli" v-if="item.cli"
type="button" type="button"
:class="[ class="flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left"
'flex min-w-0 w-full items-start gap-2 rounded-md border border-default bg-muted/20 px-3 py-2 text-left',
!item.template && 'sm:col-span-2',
]"
@click="toggleExpand(item.id, 'cli')" @click="toggleExpand(item.id, 'cli')"
> >
<UIcon name="i-lucide-terminal" class="mt-0.5 size-4 shrink-0 text-toned" /> <UIcon name="i-lucide-terminal" class="mt-0.5 size-4 shrink-0 text-toned" />