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',