diff --git a/ui/app/assets/css/tailwind.css b/ui/app/assets/css/tailwind.css index 856a63ed..b8f550b5 100644 --- a/ui/app/assets/css/tailwind.css +++ b/ui/app/assets/css/tailwind.css @@ -33,6 +33,22 @@ } @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 { background: radial-gradient(circle at top left, rgb(99 102 241 / 0.1), transparent 28%), diff --git a/ui/app/components/Simple.vue b/ui/app/components/Simple.vue index 40b7b521..3629ea2c 100644 --- a/ui/app/components/Simple.vue +++ b/ui/app/components/Simple.vue @@ -714,6 +714,7 @@ const { loadHistory, reloadHistory, deleteHistoryItems, + historyMoveHandler, } = useHistoryState(); const embedUrl = ref(''); @@ -1271,19 +1272,9 @@ const deleteHistoryItem = async (item: StoreItem): Promise => { toast.info('Removed from history queue.'); }; -const handleHistoryItemMoved = (payload: { data: { to: 'queue' | 'history' } }): void => { - if (!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 handleHistoryItemMoved = historyMoveHandler( + () => simpleMode.value && historyInitialized.value, +); const showMessage = (item: StoreItem): boolean => { if (!item?.msg || item.msg === item?.error) { diff --git a/ui/app/composables/useHistoryState.ts b/ui/app/composables/useHistoryState.ts index 55413ea6..82dae5cb 100644 --- a/ui/app/composables/useHistoryState.ts +++ b/ui/app/composables/useHistoryState.ts @@ -1,6 +1,7 @@ import { computed, ref } from 'vue'; import { useNotification } from '~/composables/useNotification'; +import type { WSEP } from '~/types/sockets'; import { useYtpConfig } from '~/composables/useYtpConfig'; import { parse_api_error, parse_list_response, request } from '~/utils'; import type { Pagination } from '~/types/responses'; @@ -168,6 +169,44 @@ const resetHistory = (): void => { 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 = () => { return { items, @@ -180,5 +219,7 @@ export const useHistoryState = () => { reloadHistory, deleteHistoryItems, resetHistory, + upsertHistoryItem: addHistoryItem, + historyMoveHandler, }; }; diff --git a/ui/app/pages/conditions.vue b/ui/app/pages/conditions.vue index 7c5b1b07..3a78c340 100644 --- a/ui/app/pages/conditions.vue +++ b/ui/app/pages/conditions.vue @@ -309,57 +309,48 @@ - +
+ -
- -
+ +
-
+
- +
+ + + -
- -