Skip to content

Commit

Permalink
web app: Fix scrolling issues
Browse files Browse the repository at this point in the history
Fix display jumping when scrolling up or down in large lists of
recordings, videos or upcoming.

Allow left-right scrolling of pages on small screens or narrow windows.
  • Loading branch information
bennettpeter committed Sep 15, 2024
1 parent fc1f8dd commit 6f9fdcb
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 46 deletions.
2 changes: 1 addition & 1 deletion mythtv/html/apps/backend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/3rdParty/primeicons-5.0.0/primeicons.css">
<link id="app-theme" rel="stylesheet" type="text/css" href="assets/themes/md-light-indigo.css">
<link id="app-theme" rel="stylesheet" type="text/css" href="assets/themes/bootstrap4-light-blue.css">
<link rel="stylesheet" type="text/css" href="/assets/guidecolors.css">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<style>html,body{height:100%}body{margin:0;height:100%;overflow-x:hidden;overflow-y:auto;background-color:var(--surface-a);font-family:var(--font-family);font-weight:400;color:var(--text-color);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@layer primeng{}</style><link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.css"></noscript></head>
Expand Down
2 changes: 1 addition & 1 deletion mythtv/html/apps/backend/main.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,14 @@
border: 2px solid;
left: 10%;
top: 2em;
}
}

.mycell {
position: relative;
}

.mytext {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<form name="recsform" #recsform="ngForm">
<form name="recsform" #recsform="ngForm" style="min-width: 960px;">

<div style="white-space: 'pre-line';">
<p-toast position="center"></p-toast>
Expand All @@ -20,8 +20,8 @@ <h2>{{ 'dashboard.recordings.heading' | translate }}</h2>
<span class="p-input-icon-right">
<i class="pi pi-times" (click)="resetSearch()" *ngIf="searchValue"></i>
<input type="text" pInputText id="searchValue" [(ngModel)]="searchValue" name="searchValue"
class="text-xl" placeholder="{{ 'common.search_placeholder' | translate }}" pTooltip="{{ 'dashboard.recordings.regex' | translate }}"
tooltipPosition="top" />
class="text-xl" placeholder="{{ 'common.search_placeholder' | translate }}"
pTooltip="{{ 'dashboard.recordings.regex' | translate }}" tooltipPosition="top" />
</span>

<button pButton pRipple icon="pi pi-search" class="p-button-text w-2rem" (click)="onFilter()"
Expand Down Expand Up @@ -85,35 +85,59 @@ <h2>{{ 'dashboard.recordings.heading' | translate }}</h2>
</ng-template>
<ng-template pTemplate="body" let-program let-rowIndex="rowIndex">
<tr [ngClass]="{'line-through' : program.Recording.RecGroup == 'Deleted'}" [pSelectableRow]="program"
[pSelectableRowIndex]="rowIndex" (contextmenu)="onContextMenu(program,$event)">
[pSelectableRowIndex]="rowIndex" (contextmenu)="onContextMenu(program,$event)" style="height: 42px">
<td class="p-1 overflow-hidden">
<i class="pi pi-exclamation-triangle p-1" *ngIf="program.VideoPropNames.indexOf('DAMAGED') > -1"
pTooltip="{{ 'dashboard.recordings.damaged' | translate }}" tooltipPosition="top"></i>
{{program.Title}}
<div class="mycell">
<div class="mytext">
<i class="pi pi-exclamation-triangle p-1"
*ngIf="program.VideoPropNames.indexOf('DAMAGED') > -1"
pTooltip="{{ 'dashboard.recordings.damaged' | translate }}"
tooltipPosition="top"></i>
{{program.Title}}
</div>
</div>
</td>
<td class="p-1">
<i class="pi pi-eye" *ngIf="program.ProgramFlagNames.indexOf('WATCHED') > -1"
pTooltip="{{ 'dashboard.recordings.watched' | translate }}" tooltipPosition="top"></i>
</td>
<td class="p-1 overflow-hidden" pTooltip="{{program.Description}}" tooltipPosition="top">
{{program.SubTitle}}</td>
<div class="mycell">
<div class="mytext">{{program.SubTitle}}</div>
</div>
</td>
<td class="p-1">
<div *ngIf="program.Season>0 || program.Episode>0"> {{program.Season}}x{{program.Episode}}
</div>
</td>
<td class="justify-content-end p-1">
<div [innerHTML]="utility.formatDate(program.Airdate,true)"></div>
<td class="justify-content-end p-1 overflow-hidden">
<div class="mycell">
<div class="mytext" [innerHTML]="utility.formatDate(program.Airdate,true)"></div>
</div>
</td>
<td class="justify-content-end p-1">
<div [innerHTML]="utility.formatDate(program.StartTime,true)"></div>
<td class="justify-content-end p-1 overflow-hidden">
<div class="mycell">
<div class="mytext" [innerHTML]="utility.formatDate(program.StartTime,true)"></div>
</div>
</td>
<td class="p-1">
{{program.Channel.ChanNum}} {{program.Channel.CallSign}}</td>
<div class="mycell">
<div class="mytext">{{program.Channel.ChanNum}} {{program.Channel.CallSign}}
</div>
</div>
</td>
<td class="p-1">{{program.Recording.RecGroup}}</td>
<td class="justify-content-end p-1">{{ getDuration(program) |
number:'1.0-0' }} min</td>
<td class="justify-content-end p-1">
{{program.Recording.FileSize / 1000000 | number:'1.0-0'}} MB</td>
<div class="mycell">
<div class="mytext">{{ getDuration(program) | number:'1.0-0' }} min
</div>
</div>
</td>
<td class="justify-content-end p-1">
<div class="mycell">
<div class="mytext">{{program.Recording.FileSize / 1000000 | number:'1.0-0'}} MB</div>
</div>
</td>
<td class="pt-1 pb-0" style="background: var(--surface-card); white-space: nowrap;">
<a href="{{URLencode('/Content/GetRecording?RecordedId=' + program.Recording.RecordedId)
+ '&Download=' + getDownload(program)}}"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h2>{{ 'dashboard.recrules.heading' | translate }}</h2>
<div class="block card w-full" style="height: 90vh" *ngIf="rulesLoaded else loading">
<div class="block card w-full" style="height: 90vh; min-width: 960px;" *ngIf="rulesLoaded else loading">
<p-table [value]="recRules" scrollHeight="flex" [scrollable]="true" styleClass="p-datatable-striped p-datatable-sm"
[rowHover]="true" responsiveLayout="scroll" sortField="Title">
<ng-template pTemplate="caption">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

.mycell {
position: relative;
}

.mytext {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div>
<div style="min-width: 960px;">
<div style="white-space: 'pre-line';">
<p-toast position="center"></p-toast>
</div>
Expand Down Expand Up @@ -30,7 +30,7 @@ <h2>{{ 'dashboard.upcoming.heading' | translate }}</h2>
<ng-template #refreshBn>
<button pButton pRipple icon="pi pi-refresh" class="p-button-text .p-button-success"
(click)="refresh()" pTooltip="{{ 'common.refresh' | translate }}"></button>
&nbsp;&nbsp;&nbsp;{{ programs.length }} {{ 'common.rows' | translate }}
&nbsp;&nbsp;&nbsp;{{ programs.length }} {{ 'common.rows' | translate }}
</ng-template>
</div>
</ng-template>
Expand Down Expand Up @@ -73,35 +73,59 @@ <h2>{{ 'dashboard.upcoming.heading' | translate }}</h2>
</ng-template>

<ng-template pTemplate="body" let-program let-rowIndex="rowIndex">
<tr>
<tr style="height: 42px">
<td class="p-1 overflow-hidden">
<div [innerHTML]="formatStartDate(program, rowIndex)"></div>
<div class="mycell">
<div class="mytext" [innerHTML]="formatStartDate(program, rowIndex)"></div>
</div>
</td>
<td class="justify-content-end p-1 overflow-hidden">
{{formatStartTime(program)}}
<div class="mycell">
<div class="mytext">{{formatStartTime(program)}} </div>
</div>
</td>
<td class="justify-content-end pl-1 pr-3 pt-1 pb-1 overflow-hidden">
{{ getDuration(program) | number:'1.0-0' }} min</td>
<td class="p-1">{{program.Recording.EncoderName}}
<div class="mycell">
<div class="mytext">{{ getDuration(program) | number:'1.0-0' }} min</div>
</div>
</td>
<td class="p-1">
<div class="mycell">
<div class="mytext">{{program.Recording.EncoderName}}</div>
</div>
</td>
<td class="p-1 overflow-hidden">
<div class="mycell">
<div class="mytext">{{program.Title}}</div>
</div>
</td>
<td class="p-1 overflow-hidden"> {{program.Title}}</td>
<td class="p-1 overflow-hidden" pTooltip="{{program.Description}}" tooltipPosition="top">
{{program.SubTitle.slice(0,50)}}</td>
<div class="mycell">
<div class="mytext">{{program.SubTitle.slice(0,50)}}</div>
</div>
</td>
<td class="p-1">
<div *ngIf="program.Season>0 || program.Episode>0">
{{program.Season}}x{{program.Episode}}
</div>
</td>
<td class="justify-content-end p-1">
<div [innerHTML]="formatAirDate(program)"></div>
<div class="mycell">
<div class="mytext" [innerHTML]="formatAirDate(program)"></div>
</div>
</td>
<td class="p-1">
{{program.Channel.ChanNum}} {{program.Channel.CallSign}}</td>
<div class="mycell">
<div class="mytext">{{program.Channel.ChanNum}} {{program.Channel.CallSign}}</div>
</div>
</td>
<td class="p-1">{{program.Recording.RecGroup}}</td>
<td class="p-1">
<div *ngIf="program.Recording" [ngClass]="['WillRecord','Recording','Recorded'].indexOf(program.Recording.StatusName)>-1 ?
<div class="mycell">
<div class="mytext" *ngIf="program.Recording" [ngClass]="['WillRecord','Recording','Recorded'].indexOf(program.Recording.StatusName)>-1 ?
'text-green-500' : 'text-pink-500'">
{{dataService.recStatusText[program.Recording.StatusName]}}
{{dataService.recStatusText[program.Recording.StatusName]}}
</div>
</div>
</td>
<td class="pt-1 pb-0" style="white-space: nowrap;">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.mycell {
position: relative;
}

.mytext {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
31 changes: 21 additions & 10 deletions mythtv/html/backend/src/app/dashboard/videos/videos.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div>
<div style="min-width: 960px;">
<div style="white-space: 'pre-line';">
<p-toast position="center"></p-toast>
</div>
Expand All @@ -8,7 +8,7 @@ <h2>{{ 'dashboard.videos.heading' | translate }}</h2>
<p-table *ngIf="showTable" #table name="table" [value]="videos" scrollHeight="flex" [scrollable]="true"
styleClass="p-datatable-striped p-datatable-sm" [virtualScroll]="true" [rows]="50" [lazy]="true"
[totalRecords]="totalRecords" (onLazyLoad)="loadLazy($event)" [rowHover]="true" responsiveLayout="scroll"
[virtualScrollItemSize]="41" sortField="Title">
[virtualScrollItemSize]="42" sortField="Title" [scrollable]="true">
<ng-template pTemplate="caption">
<!-- Top Buttons -->
<div class="flex align-items-center">
Expand All @@ -35,7 +35,7 @@ <h2>{{ 'dashboard.videos.heading' | translate }}</h2>
(click)="refreshing=true;reLoadVideos()"
pTooltip="{{ 'common.refresh' | translate }}"></button>
</ng-template>
&nbsp;&nbsp;&nbsp;{{ videos.length }} {{ 'common.rows' | translate }}
&nbsp;&nbsp;&nbsp;{{ videos.length }} {{ 'common.rows' | translate }}
</div>
</ng-template>
<ng-template pTemplate="header">
Expand Down Expand Up @@ -65,31 +65,42 @@ <h2>{{ 'dashboard.videos.heading' | translate }}</h2>
<ng-template pTemplate="body" let-video>

<!-- Directory Row -->
<tr *ngIf="video.ContentType == 'DIRECTORY'">
<tr *ngIf="video.ContentType == 'DIRECTORY'" style="height: 42px">
<td class="pt-1 pb-0" colspan="7">
<button pButton pRipple icon="pi pi-folder" class="p-button-text p-button-primary"
(click)="onDirectory(video.Title)" label="{{video.Title}}"></button>
</td>
</tr>

<!-- Video Row -->
<tr *ngIf="video.ContentType != 'DIRECTORY'">
<td class="p-1">
{{video.Title}}
<tr *ngIf="video.ContentType != 'DIRECTORY'" style="height: 42px">
<td class="p-1 overflow-hidden">
<div class="mycell">
<div class="mytext">{{video.Title}}</div>
</div>
</td>
<td class="pt-1 pb-0">
<i class="pi pi-eye" *ngIf="video.Watched"></i>
</td>
<td class="p-1 overflow-hidden" pTooltip="{{video.Description}}" tooltipPosition="top">
{{video.SubTitle}}</td>
<div class="mycell">
<div class="mytext">{{video.SubTitle}}</div>
</div>
</td>
<td class="p-1">
<div *ngIf="video.Season>0 || video.Episode>0"> {{video.Season}}x{{video.Episode}} </div>
</td>
<td class="justify-content-end p-1">
<div [innerHTML]="utility.formatDate(video.ReleaseDate,true)"></div>
<div class="mycell">
<div class="mytext" [innerHTML]="utility.formatDate(video.ReleaseDate,true)"></div>
</div>
</td>
<td class="justify-content-end p-1">
<div *ngIf="video.Length > 0"> {{ video.Length }} min </div>
<div *ngIf="video.Length > 0">
<div class="mycell">
<div class="mytext">{{ video.Length }} min </div>
</div>
</div>
</td>
<td class="pt-1 pb-0" style="white-space: nowrap;">
<div>
Expand Down
2 changes: 1 addition & 1 deletion mythtv/html/backend/src/app/guide/guide.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h2>{{ 'dashboard.programguide' | translate }} </h2>
<div *ngIf="loaded; else loading">
<div *ngIf="loaded; else loading" style="min-width: 960px;">
<div class="flex">

<div class="flex align-items-center pr-5" *ngIf="displayType == GRID">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class NavbarComponent implements OnInit {
private router: Router) {
this.themeService.getThemes().then((themes: Theme[]) => {
this.m_themes$ = themes;
this.m_selectedTheme = this.findThemeByName(localStorage.getItem('Theme') || 'Indigo Light');
this.m_selectedTheme = this.findThemeByName(localStorage.getItem('Theme') || 'Blue Light');
this.themeService.switchTheme(this.m_selectedTheme.CSS);
});

Expand Down
2 changes: 1 addition & 1 deletion mythtv/html/backend/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/3rdParty/primeicons-5.0.0/primeicons.css" />
<link id="app-theme" rel="stylesheet" type="text/css" href="assets/themes/md-light-indigo.css">
<link id="app-theme" rel="stylesheet" type="text/css" href="assets/themes/bootstrap4-light-blue.css">
<link rel="stylesheet" type="text/css" href="/assets/guidecolors.css" />
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
Expand Down

0 comments on commit 6f9fdcb

Please sign in to comment.