Disable Animations + Lots of bugfixes and Polish (#1561)

* Fixed inputs not showing inline validation due to a missing class

* Fixed some checks

* Increased the button size on manga reader (develop)

* Migrated a type cast to a pure pipe

* Sped up the check for if SendTo should render on the menu

* Don't allow user to bookmark in bookmark mode

* Fixed a bug where Scan Series would skip over Specials due to how new scan loop works.

* Fixed scroll to top button persisting when navigating between pages

* Edit Series modal now doesn't have a lock field for Series, which can't be locked as it is inheritently locked.

Added some validation to ensure Name and SortName are required.

* Fixed up some spacing

* Fixed actionable menu not opening submenu on mobile

* Cleaned up the layout of cover image on series detail

* Show all volume or chapters (if only one volume) for cover selection on series

* Don't open submenu to right if there is no space

* Fixed up cover image not allowing custom saves of existing series/chapter/volume images.

Fixed up logging so console output matches log file.

* Implemented the ability to turn off css transitions in the UI.

* Updated a note internally

* Code smells

* Added InstallId when pinging the email service to allow throughput tracking
This commit is contained in:
Joe Milazzo 2022-09-26 12:40:25 -05:00 committed by GitHub
parent ee7d109170
commit 28ab34c66d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 2103 additions and 444 deletions

View file

@ -4,6 +4,7 @@ import { Chapter } from '../_models/chapter';
import { CollectionTag } from '../_models/collection-tag';
import { Device } from '../_models/device/device';
import { Library } from '../_models/library';
import { MangaFormat } from '../_models/manga-format';
import { ReadingList } from '../_models/reading-list';
import { Series } from '../_models/series';
import { Volume } from '../_models/volume';
@ -92,6 +93,10 @@ export interface ActionItem<T> {
callback: (action: ActionItem<T>, data: T) => void;
requiresAdmin: boolean;
children: Array<ActionItem<T>>;
/**
* An optional class which applies to an item. ie) danger on a delete action
*/
class?: string;
/**
* Indicates that there exists a separate list will be loaded from an API.
* Rule: If using this, only one child should exist in children with the Action for dynamicList.
@ -168,7 +173,15 @@ export class ActionFactoryService {
dummyCallback(action: ActionItem<any>, data: any) {}
_resetActions() {
filterSendToAction(actions: Array<ActionItem<Chapter>>, chapter: Chapter) {
if (chapter.files.filter(f => f.format === MangaFormat.EPUB || f.format === MangaFormat.PDF).length !== chapter.files.length) {
// Remove Send To as it doesn't apply
return actions.filter(item => item.title !== 'Send To');
}
return actions;
}
private _resetActions() {
this.libraryActions = [
{
action: Action.Scan,
@ -226,6 +239,13 @@ export class ActionFactoryService {
requiresAdmin: false,
children: [],
},
{
action: Action.Scan,
title: 'Scan Series',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
},
{
action: Action.Submenu,
title: 'Add to',
@ -263,18 +283,22 @@ export class ActionFactoryService {
],
},
{
action: Action.Scan,
title: 'Scan Series',
action: Action.Submenu,
title: 'Send To',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
},
{
action: Action.Edit,
title: 'Edit',
callback: this.dummyCallback,
requiresAdmin: true,
children: [],
children: [
{
action: Action.SendTo,
title: '',
callback: this.dummyCallback,
requiresAdmin: false,
dynamicList: this.deviceService.devices$.pipe(map((devices: Array<Device>) => devices.map(d => {
return {'title': d.name, 'data': d};
}), shareReplay())),
children: []
}
],
},
{
action: Action.Submenu,
@ -301,10 +325,25 @@ export class ActionFactoryService {
title: 'Delete',
callback: this.dummyCallback,
requiresAdmin: true,
class: 'danger',
children: [],
},
],
},
{
action: Action.Download,
title: 'Download',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
},
{
action: Action.Edit,
title: 'Edit',
callback: this.dummyCallback,
requiresAdmin: true,
children: [],
},
];
this.volumeActions = [
@ -345,15 +384,15 @@ export class ActionFactoryService {
]
},
{
action: Action.Edit,
title: 'Details',
action: Action.Download,
title: 'Download',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
},
{
action: Action.Download,
title: 'Download',
action: Action.Edit,
title: 'Details',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
@ -397,29 +436,11 @@ export class ActionFactoryService {
}
]
},
{
action: Action.Edit,
title: 'Details',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
},
// RBS will handle rendering this, so non-admins with download are appicable
{
action: Action.Download,
title: 'Download',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
},
{
action: Action.Submenu,
title: 'Send To',
callback: this.dummyCallback,
requiresAdmin: false,
// dynamicList: this.deviceService.devices$.pipe(map((devices: Array<Device>) => devices.map(d => {
// return {'title': d.name, 'data': d};
// }), shareReplay())),
children: [
{
action: Action.SendTo,
@ -433,6 +454,21 @@ export class ActionFactoryService {
}
],
},
// RBS will handle rendering this, so non-admins with download are appicable
{
action: Action.Download,
title: 'Download',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
},
{
action: Action.Edit,
title: 'Details',
callback: this.dummyCallback,
requiresAdmin: false,
children: [],
},
];
this.readingListActions = [
@ -448,6 +484,7 @@ export class ActionFactoryService {
title: 'Delete',
callback: this.dummyCallback,
requiresAdmin: false,
class: 'danger',
children: [],
},
];
@ -471,6 +508,7 @@ export class ActionFactoryService {
action: Action.Delete,
title: 'Clear',
callback: this.dummyCallback,
class: 'danger',
requiresAdmin: false,
children: [],
},
@ -494,4 +532,5 @@ export class ActionFactoryService {
actions.forEach((action) => this.applyCallback(action, callback));
return actions;
}
}

View file

@ -3,11 +3,12 @@ import { HttpClient } from '@angular/common/http';
import { Inject, Injectable, OnDestroy, Renderer2, RendererFactory2, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { ToastrService } from 'ngx-toastr';
import { map, ReplaySubject, Subject, takeUntil, take } from 'rxjs';
import { map, ReplaySubject, Subject, takeUntil, take, distinctUntilChanged, Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { ConfirmService } from '../shared/confirm.service';
import { NotificationProgressEvent } from '../_models/events/notification-progress-event';
import { SiteTheme, ThemeProvider } from '../_models/preferences/site-theme';
import { AccountService } from './account.service';
import { EVENTS, MessageHubService } from './message-hub.service';
@ -24,7 +25,7 @@ export class ThemeService implements OnDestroy {
private themesSource = new ReplaySubject<SiteTheme[]>(1);
public themes$ = this.themesSource.asObservable();
/**
* Maintain a cache of themes. SignalR will inform us if we need to refresh cache
*/