From d64283e33d009864ea63033a0506ae1e247bde97 Mon Sep 17 00:00:00 2001 From: 4gray Date: Wed, 4 Feb 2026 00:41:03 +0100 Subject: [PATCH] style: enhance favorites and recently viewed UI with improved layout and functionality --- .../favorites-layout.component.html | 68 ++++----- .../favorites-layout.component.scss | 121 ++++++++++------ .../recently-viewed.component.html | 96 +++++++------ .../recently-viewed.component.scss | 134 ++++++++++-------- .../recently-viewed.component.ts | 8 +- 5 files changed, 243 insertions(+), 184 deletions(-) diff --git a/apps/web/src/app/shared/components/favorites-layout/favorites-layout.component.html b/apps/web/src/app/shared/components/favorites-layout/favorites-layout.component.html index fab280587..74ebad294 100644 --- a/apps/web/src/app/shared/components/favorites-layout/favorites-layout.component.html +++ b/apps/web/src/app/shared/components/favorites-layout/favorites-layout.component.html @@ -38,46 +38,40 @@ @if (favorites().length) {
@for (item of favorites(); track $index) { - - +
+ + - -

- {{ item?.title || item?.details?.info?.name }} -

+ " + (error)=" + $event.target.src = + './assets/images/default-poster.png' + " + [alt]="item.title" + class="poster" + /> + + {{ item.type }} + +
+
+

{{ item?.title || item?.details?.info?.name }}

- Added: - {{ item?.added_at | date: 'd MMMM, y, HH:MM' }} + {{ item?.added_at | date: 'd MMM, HH:mm' }}

- - - +
+
} } @else { diff --git a/apps/web/src/app/shared/components/favorites-layout/favorites-layout.component.scss b/apps/web/src/app/shared/components/favorites-layout/favorites-layout.component.scss index 790580d65..32ecc6b24 100644 --- a/apps/web/src/app/shared/components/favorites-layout/favorites-layout.component.scss +++ b/apps/web/src/app/shared/components/favorites-layout/favorites-layout.component.scss @@ -48,8 +48,8 @@ .items-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 16px; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 20px; padding: 16px; width: 100%; box-sizing: border-box; @@ -57,54 +57,95 @@ } .item-card { - position: relative; cursor: pointer; - transition: transform 0.2s; - height: 100%; - display: flex; - flex-direction: column; + border-radius: 8px; + overflow: hidden; + transition: transform 0.2s ease, box-shadow 0.2s ease; &:hover { - transform: scale(1.02); + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12); } -} -.item-image { - width: 100%; - aspect-ratio: 2/3; - object-fit: cover; -} + .thumbnail-wrapper { + position: relative; -.favorite-button { - position: absolute; - top: 8px; - right: 8px; - z-index: 1; -} + .poster { + width: 100%; + aspect-ratio: 2/3; + object-fit: cover; + display: block; + } -mat-card-content { - padding: 12px; - flex-grow: 1; + .remove-button { + position: absolute; + top: 4px; + right: 4px; + z-index: 1; + background: rgba(0, 0, 0, 0.5); + width: 28px; + height: 28px; + padding: 0; - h3 { - margin: 0; - font-weight: normal; - font-size: 14px; - line-height: 1.2; - max-height: 2.4em; - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - white-space: normal; + &:hover { + background: rgba(0, 0, 0, 0.8); + } + + mat-icon { + color: white; + font-size: 18px; + width: 18px; + height: 18px; + } + } + + .type-badge { + position: absolute; + top: 6px; + left: 6px; + padding: 3px 6px; + border-radius: 4px; + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + background: rgba(0, 0, 0, 0.6); + color: #fff; + + &.live { + color: #ef5350; + } + &.movie { + color: #42a5f5; + } + &.series { + color: #66bb6a; + } + } } -} -.added-date { - font-size: 12px; - color: rgba(255, 255, 255, 0.7); - margin: 4px 0 0 0; + .item-info { + padding: 8px 10px; + + h3 { + margin: 0; + font-size: 0.8rem; + font-weight: 500; + line-height: 1.3; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + + .added-date { + margin: 4px 0 0; + font-size: 0.7rem; + opacity: 0.6; + } + } } .no-items { diff --git a/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.html b/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.html index f5b5b6dcd..6e3da045b 100644 --- a/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.html +++ b/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.html @@ -32,36 +32,39 @@
@for (item of $any(group).value; track item.id) { - - - +
+ + + " + (error)=" + $event.target.src = + './assets/images/default-poster.png' + " + [alt]="item.title" + class="poster" + /> + + {{ item.type }} + +

{{ item.title }}

-

- {{ item.type | titlecase }} -

- {{ item.viewed_at | date : 'd MMMM, y, HH:mm' }} + {{ item.viewed_at | date : 'd MMM, HH:mm' }}

-
+
} @@ -70,32 +73,35 @@ } @else {
@for (item of recentItems(); track item.id) { - - - +
+
+ + + + {{ item.type }} + +

{{ item.title }}

-

- {{ item.type | titlecase }} -

- {{ item.viewed_at | date : 'd MMMM, y, hh:mm' }} + {{ item.viewed_at | date : 'd MMM, HH:mm' }}

- +
}
} } @else { diff --git a/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.scss b/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.scss index 20eac9cf4..b2a151909 100644 --- a/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.scss +++ b/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.scss @@ -25,59 +25,99 @@ .items-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 20px; } .item-card { cursor: pointer; - transition: transform 0.2s; - position: relative; + border-radius: 8px; + overflow: hidden; + transition: transform 0.2s ease, box-shadow 0.2s ease; &:hover { - transform: scale(1.02); + transform: translateY(-3px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12); } - .remove-button { - position: absolute; - top: 5px; - right: 5px; - z-index: 1; - background: rgba(0, 0, 0, 0.5); - - &:hover { - background: rgba(0, 0, 0, 0.7); + .thumbnail-wrapper { + position: relative; + + .poster { + width: 100%; + aspect-ratio: 2/3; + object-fit: cover; + display: block; } - mat-icon { - color: white; + .remove-button { + position: absolute; + top: 4px; + right: 4px; + z-index: 1; + background: rgba(0, 0, 0, 0.5); + width: 28px; + height: 28px; + padding: 0; + + &:hover { + background: rgba(0, 0, 0, 0.8); + } + + mat-icon { + color: white; + font-size: 18px; + width: 18px; + height: 18px; + } + } + + .type-badge { + position: absolute; + top: 6px; + left: 6px; + padding: 3px 6px; + border-radius: 4px; + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + background: rgba(0, 0, 0, 0.6); + color: #fff; + + &.live { + color: #ef5350; + } + &.movie { + color: #42a5f5; + } + &.series { + color: #66bb6a; + } } } -} -.poster { - width: 100%; - height: 280px; - object-fit: cover; -} + .item-info { + padding: 8px 10px; -.item-info { - padding: 16px; + h3 { + margin: 0; + font-size: 0.8rem; + font-weight: 500; + line-height: 1.3; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } - h3 { - margin: 0; - font-size: 16px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - p { - margin: 8px 0; - } - - .viewed-at { - font-size: 12px; + .viewed-at { + margin: 4px 0 0; + font-size: 0.7rem; + opacity: 0.6; + } } } @@ -93,26 +133,6 @@ } } -.type-badge { - display: inline-block; - padding: 0.25rem 0.5rem; - border-radius: 4px; - font-size: 0.8rem; - text-transform: uppercase; - &.live { - background: #e53935; - color: white; - } - &.movie { - background: #1e88e5; - color: white; - } - &.series { - background: #43a047; - color: white; - } -} - .playlist-section { .section-title { margin: 0 0 1.5rem; diff --git a/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.ts b/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.ts index 3a336e64d..5a8bc51f6 100644 --- a/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.ts +++ b/apps/web/src/app/xtream-tauri/recently-viewed/recently-viewed.component.ts @@ -1,9 +1,9 @@ -import { DatePipe, KeyValuePipe, TitleCasePipe } from '@angular/common'; +import { DatePipe, KeyValuePipe } from '@angular/common'; import { Component, computed, inject, Optional } from '@angular/core'; import { MatButton, MatIconButton } from '@angular/material/button'; -import { MatCard } from '@angular/material/card'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MatIcon } from '@angular/material/icon'; +import { MatTooltip } from '@angular/material/tooltip'; import { ActivatedRoute, Router } from '@angular/router'; import groupBy from 'lodash/groupBy'; import { XtreamStore } from '../stores/xtream.store'; @@ -14,11 +14,9 @@ import { XtreamStore } from '../stores/xtream.store'; DatePipe, KeyValuePipe, MatButton, - MatCard, MatIcon, MatIconButton, - MatIconButton, - TitleCasePipe, + MatTooltip, ], providers: [], templateUrl: './recently-viewed.component.html',