diff --git a/client/src/app/torrent-table/torrent-table.component.html b/client/src/app/torrent-table/torrent-table.component.html
index 7c170d8..7674e0c 100644
--- a/client/src/app/torrent-table/torrent-table.component.html
+++ b/client/src/app/torrent-table/torrent-table.component.html
@@ -24,68 +24,99 @@
}
-
-
-
- |
- 0 && selectedTorrents.length === torrents.length"
- />
- |
- Name |
- Category |
- Priority |
- Seeders |
- Files |
- Downloads |
- Size |
- Requested |
- Status |
-
-
-
- @for (torrent of torrents | sort: sortProperty : sortDirection; track torrent.torrentId) {
+ @if (!isMobile) {
+
+ } @else {
+
+ @for (torrent of torrents | sort: sortProperty : sortDirection; track torrent.torrentId) {
+
+
-
-
- {{ torrent.rdName }}
- |
-
- {{ torrent.category }}
- |
-
- {{ torrent.priority }}
- |
-
- {{ torrent.rdSeeders }}
- |
-
- {{ torrent.files.length | number }}
- |
-
- {{ torrent.downloads.length | number }}
- |
-
- {{ torrent.rdSize | filesize }}
- |
-
- {{ torrent.added | date: "medium" }}
- |
-
- {{ torrent | status }}
- |
-
+
+
+
{{ torrent.rdName }}
+
+ {{ torrent | status }}
+ @if (torrent.category) {
+ {{ torrent.category }}
+ }
+
+
+ Size {{ torrent.rdSize | filesize }}
+ Seeders {{ torrent.rdSeeders }}
+ Files {{ torrent.files.length | number }}
+ Downloads {{ torrent.downloads.length | number }}
+
+
+
}
-
-
+
+ }
@if (torrents.length > 0) {
diff --git a/client/src/app/torrent-table/torrent-table.component.scss b/client/src/app/torrent-table/torrent-table.component.scss
index 071fdc9..f741d20 100644
--- a/client/src/app/torrent-table/torrent-table.component.scss
+++ b/client/src/app/torrent-table/torrent-table.component.scss
@@ -5,12 +5,74 @@ table {
word-break: break-all;
}
}
- // Make table horizontally scrollable on small screens
- @media screen and (max-width: 768px) {
- display: block;
- overflow-x: auto;
- white-space: nowrap;
- }
+}
+
+.mobile-cards {
+ display: block;
+}
+
+.mobile-card {
+ display: flex;
+ align-items: flex-start;
+ gap: 0.75rem;
+ padding: 0.875rem 0.75rem !important;
+ margin-bottom: 0.5rem !important;
+ cursor: pointer;
+
+ &.is-selected {
+ border-left: 3px solid hsl(217, 71%, 53%);
+ }
+
+ &:active {
+ background-color: hsl(0, 0%, 96%);
+ }
+}
+
+.mobile-card-checkbox {
+ flex-shrink: 0;
+ padding-top: 0.125rem;
+
+ input[type='checkbox'] {
+ width: 1.1rem;
+ height: 1.1rem;
+ cursor: pointer;
+ }
+}
+
+.mobile-card-body {
+ flex: 1;
+ min-width: 0;
+}
+
+.mobile-card-name {
+ font-weight: 600;
+ font-size: 0.9rem;
+ line-height: 1.3;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-bottom: 0.375rem;
+ color: hsl(0, 0%, 21%);
+}
+
+.mobile-card-details {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.25rem 1rem;
+}
+
+.mobile-card-detail {
+ font-size: 0.8rem;
+ color: hsl(0, 0%, 29%);
+ white-space: nowrap;
+
+ .detail-label {
+ color: hsl(0, 0%, 48%);
+ font-size: 0.72rem;
+ text-transform: uppercase;
+ letter-spacing: 0.03em;
+ margin-right: 0.2em;
+ }
}
.flex-container {
@@ -18,6 +80,7 @@ table {
flex: 1 1 0;
gap: 20px;
flex-direction: row;
+ margin-top: 1rem;
@media screen and (max-width: 1279px) {
flex-direction: column;
diff --git a/client/src/app/torrent-table/torrent-table.component.ts b/client/src/app/torrent-table/torrent-table.component.ts
index 4b5100e..44d9bbd 100644
--- a/client/src/app/torrent-table/torrent-table.component.ts
+++ b/client/src/app/torrent-table/torrent-table.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Torrent } from '../models/torrent.model';
import { DiskSpaceStatus } from '../models/disk-space-status.model';
@@ -18,7 +18,7 @@ import { FileSizePipe } from '../filesize.pipe';
imports: [FormsModule, NgClass, DecimalPipe, DatePipe, TorrentStatusPipe, SortPipe, FileSizePipe],
standalone: true,
})
-export class TorrentTableComponent implements OnInit {
+export class TorrentTableComponent implements OnInit, OnDestroy {
public torrents: Torrent[] = [];
public selectedTorrents: string[] = [];
public error: string;
@@ -53,12 +53,23 @@ export class TorrentTableComponent implements OnInit {
public diskSpaceStatus: DiskSpaceStatus | null = null;
public rateLimitStatus: RateLimitStatus | null = null;
+ public isMobile = false;
+ private mobileQuery: MediaQueryList;
+ private mobileQueryListener: (e: MediaQueryListEvent) => void;
+
constructor(
private router: Router,
private torrentService: TorrentService,
) {}
ngOnInit(): void {
+ this.mobileQuery = window.matchMedia('(max-width: 768px)');
+ this.isMobile = this.mobileQuery.matches;
+ this.mobileQueryListener = (e: MediaQueryListEvent) => {
+ this.isMobile = e.matches;
+ };
+ this.mobileQuery.addEventListener('change', this.mobileQueryListener);
+
// Load persisted sort settings (if any)
try {
const sp = localStorage.getItem('torrentTable.sortProperty');
@@ -320,4 +331,8 @@ export class TorrentTableComponent implements OnInit {
updateDeleteSelectAll() {
this.deleteSelectAll = this.deleteData && this.deleteRdTorrent && this.deleteLocalFiles;
}
+
+ ngOnDestroy(): void {
+ this.mobileQuery?.removeEventListener('change', this.mobileQueryListener);
+ }
}