mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Misc Bugs (#510)
* Don't show bookmark context actionable for books * Fixed an issue where when adding a collection tag, the logic wouldn't assume the tag already existed in DB and would reset it. * After editing a series on library page, ensure we refresh collection tags. * Reload recently added section after changing a series * Moved all Stat logger events to Debug * Refactored scroll logic into a single service to keep the code consistent.
This commit is contained in:
parent
914c6f9349
commit
786fa146fb
@ -116,6 +116,8 @@ namespace API.Controllers
|
|||||||
_unitOfWork.CollectionTagRepository.Update(tag);
|
_unitOfWork.CollectionTagRepository.Update(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tag.CoverImageLocked = updateSeriesForTagDto.Tag.CoverImageLocked;
|
||||||
|
|
||||||
if (!updateSeriesForTagDto.Tag.CoverImageLocked)
|
if (!updateSeriesForTagDto.Tag.CoverImageLocked)
|
||||||
{
|
{
|
||||||
tag.CoverImageLocked = false;
|
tag.CoverImageLocked = false;
|
||||||
|
@ -242,6 +242,7 @@ namespace API.Controllers
|
|||||||
{
|
{
|
||||||
var seriesId = updateSeriesMetadataDto.SeriesMetadata.SeriesId;
|
var seriesId = updateSeriesMetadataDto.SeriesMetadata.SeriesId;
|
||||||
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(seriesId);
|
var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(seriesId);
|
||||||
|
var allTags = (await _unitOfWork.CollectionTagRepository.GetAllTagsAsync()).ToList();
|
||||||
if (series.Metadata == null)
|
if (series.Metadata == null)
|
||||||
{
|
{
|
||||||
series.Metadata = DbFactory.SeriesMetadata(updateSeriesMetadataDto.Tags
|
series.Metadata = DbFactory.SeriesMetadata(updateSeriesMetadataDto.Tags
|
||||||
@ -266,13 +267,13 @@ namespace API.Controllers
|
|||||||
// At this point, all tags that aren't in dto have been removed.
|
// At this point, all tags that aren't in dto have been removed.
|
||||||
foreach (var tag in updateSeriesMetadataDto.Tags)
|
foreach (var tag in updateSeriesMetadataDto.Tags)
|
||||||
{
|
{
|
||||||
var existingTag = series.Metadata.CollectionTags.SingleOrDefault(t => t.Title == tag.Title);
|
var existingTag = allTags.SingleOrDefault(t => t.Title == tag.Title);
|
||||||
if (existingTag != null)
|
if (existingTag != null)
|
||||||
{
|
{
|
||||||
// Update existingTag
|
if (!series.Metadata.CollectionTags.Any(t => t.Title == tag.Title))
|
||||||
existingTag.Promoted = tag.Promoted;
|
{
|
||||||
existingTag.Title = tag.Title;
|
newTags.Add(existingTag);
|
||||||
existingTag.NormalizedTitle = Parser.Parser.Normalize(tag.Title).ToUpper();
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,14 @@ namespace API.Data
|
|||||||
return await _context.SaveChangesAsync();
|
return await _context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<CollectionTag>> GetAllTagsAsync()
|
||||||
|
{
|
||||||
|
return await _context.CollectionTag
|
||||||
|
.Select(c => c)
|
||||||
|
.OrderBy(c => c.NormalizedTitle)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<CollectionTagDto>> GetAllTagDtosAsync()
|
public async Task<IEnumerable<CollectionTagDto>> GetAllTagDtosAsync()
|
||||||
{
|
{
|
||||||
return await _context.CollectionTag
|
return await _context.CollectionTag
|
||||||
|
@ -16,5 +16,6 @@ namespace API.Interfaces
|
|||||||
Task<CollectionTag> GetFullTagAsync(int tagId);
|
Task<CollectionTag> GetFullTagAsync(int tagId);
|
||||||
void Update(CollectionTag tag);
|
void Update(CollectionTag tag);
|
||||||
Task<int> RemoveTagsWithoutSeries();
|
Task<int> RemoveTagsWithoutSeries();
|
||||||
|
Task<IEnumerable<CollectionTag>> GetAllTagsAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ namespace API.Services.Tasks
|
|||||||
|
|
||||||
public async Task PathData(ClientInfoDto clientInfoDto)
|
public async Task PathData(ClientInfoDto clientInfoDto)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Pathing client data to the file");
|
_logger.LogDebug("Pathing client data to the file");
|
||||||
|
|
||||||
var statisticsDto = await GetData();
|
var statisticsDto = await GetData();
|
||||||
|
|
||||||
@ -52,12 +52,12 @@ namespace API.Services.Tasks
|
|||||||
|
|
||||||
public async Task CollectRelevantData()
|
public async Task CollectRelevantData()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Collecting data from the server and database");
|
_logger.LogDebug("Collecting data from the server and database");
|
||||||
|
|
||||||
_logger.LogInformation("Collecting usage info");
|
_logger.LogDebug("Collecting usage info");
|
||||||
var usageInfo = await GetUsageInfo();
|
var usageInfo = await GetUsageInfo();
|
||||||
|
|
||||||
_logger.LogInformation("Collecting server info");
|
_logger.LogDebug("Collecting server info");
|
||||||
var serverInfo = GetServerInfo();
|
var serverInfo = GetServerInfo();
|
||||||
|
|
||||||
await PathData(serverInfo, usageInfo);
|
await PathData(serverInfo, usageInfo);
|
||||||
@ -67,14 +67,14 @@ namespace API.Services.Tasks
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Finalizing Stats collection flow");
|
_logger.LogDebug("Finalizing Stats collection flow");
|
||||||
|
|
||||||
var data = await GetExistingData<UsageStatisticsDto>();
|
var data = await GetExistingData<UsageStatisticsDto>();
|
||||||
|
|
||||||
_logger.LogInformation("Sending data to the Stats server");
|
_logger.LogDebug("Sending data to the Stats server");
|
||||||
await _client.SendDataToStatsServer(data);
|
await _client.SendDataToStatsServer(data);
|
||||||
|
|
||||||
_logger.LogInformation("Deleting the file from disk");
|
_logger.LogDebug("Deleting the file from disk");
|
||||||
if (FileExists) File.Delete(FinalPath);
|
if (FileExists) File.Delete(FinalPath);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -92,7 +92,7 @@ namespace API.Services.Tasks
|
|||||||
|
|
||||||
private async Task PathData(ServerInfoDto serverInfoDto, UsageInfoDto usageInfoDto)
|
private async Task PathData(ServerInfoDto serverInfoDto, UsageInfoDto usageInfoDto)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Pathing server and usage info to the file");
|
_logger.LogDebug("Pathing server and usage info to the file");
|
||||||
|
|
||||||
var data = await GetData();
|
var data = await GetData();
|
||||||
|
|
||||||
@ -169,19 +169,19 @@ namespace API.Services.Tasks
|
|||||||
|
|
||||||
private async Task SaveFile(UsageStatisticsDto statisticsDto)
|
private async Task SaveFile(UsageStatisticsDto statisticsDto)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Saving file");
|
_logger.LogDebug("Saving file");
|
||||||
|
|
||||||
var finalDirectory = FinalPath.Replace(TempFileName, string.Empty);
|
var finalDirectory = FinalPath.Replace(TempFileName, string.Empty);
|
||||||
if (!Directory.Exists(finalDirectory))
|
if (!Directory.Exists(finalDirectory))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Creating tmp directory");
|
_logger.LogDebug("Creating tmp directory");
|
||||||
Directory.CreateDirectory(finalDirectory);
|
Directory.CreateDirectory(finalDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Serializing data to write");
|
_logger.LogDebug("Serializing data to write");
|
||||||
var dataJson = JsonSerializer.Serialize(statisticsDto);
|
var dataJson = JsonSerializer.Serialize(statisticsDto);
|
||||||
|
|
||||||
_logger.LogInformation("Writing file to the disk");
|
_logger.LogDebug("Writing file to the disk");
|
||||||
await File.WriteAllTextAsync(FinalPath, dataJson);
|
await File.WriteAllTextAsync(FinalPath, dataJson);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { Chapter } from '../_models/chapter';
|
import { Chapter } from '../_models/chapter';
|
||||||
import { CollectionTag } from '../_models/collection-tag';
|
import { CollectionTag } from '../_models/collection-tag';
|
||||||
import { Library } from '../_models/library';
|
import { Library } from '../_models/library';
|
||||||
|
import { MangaFormat } from '../_models/manga-format';
|
||||||
import { Series } from '../_models/series';
|
import { Series } from '../_models/series';
|
||||||
import { Volume } from '../_models/volume';
|
import { Volume } from '../_models/volume';
|
||||||
import { AccountService } from './account.service';
|
import { AccountService } from './account.service';
|
||||||
@ -156,6 +157,11 @@ export class ActionFactoryService {
|
|||||||
return this.collectionTagActions;
|
return this.collectionTagActions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filterBookmarksForFormat(action: ActionItem<Series>, series: Series) {
|
||||||
|
if (action.action === Action.Bookmarks && series?.format === MangaFormat.EPUB) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
dummyCallback(action: Action, data: any) {}
|
dummyCallback(action: Action, data: any) {}
|
||||||
|
|
||||||
_resetActions() {
|
_resetActions() {
|
||||||
|
@ -21,6 +21,7 @@ import { Stack } from 'src/app/shared/data-structures/stack';
|
|||||||
import { Preferences } from 'src/app/_models/preferences/preferences';
|
import { Preferences } from 'src/app/_models/preferences/preferences';
|
||||||
import { MemberService } from 'src/app/_services/member.service';
|
import { MemberService } from 'src/app/_services/member.service';
|
||||||
import { ReadingDirection } from 'src/app/_models/preferences/reading-direction';
|
import { ReadingDirection } from 'src/app/_models/preferences/reading-direction';
|
||||||
|
import { ScrollService } from 'src/app/scroll.service';
|
||||||
|
|
||||||
|
|
||||||
interface PageStyle {
|
interface PageStyle {
|
||||||
@ -149,7 +150,8 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
constructor(private route: ActivatedRoute, private router: Router, private accountService: AccountService,
|
constructor(private route: ActivatedRoute, private router: Router, private accountService: AccountService,
|
||||||
private seriesService: SeriesService, private readerService: ReaderService, private location: Location,
|
private seriesService: SeriesService, private readerService: ReaderService, private location: Location,
|
||||||
private renderer: Renderer2, private navService: NavService, private toastr: ToastrService,
|
private renderer: Renderer2, private navService: NavService, private toastr: ToastrService,
|
||||||
private domSanitizer: DomSanitizer, private bookService: BookService, private memberService: MemberService) {
|
private domSanitizer: DomSanitizer, private bookService: BookService, private memberService: MemberService,
|
||||||
|
private scrollService: ScrollService) {
|
||||||
this.navService.hideNavBar();
|
this.navService.hideNavBar();
|
||||||
|
|
||||||
this.darkModeStyleElem = this.renderer.createElement('style');
|
this.darkModeStyleElem = this.renderer.createElement('style');
|
||||||
@ -207,9 +209,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
if (this.isLoading) return;
|
if (this.isLoading) return;
|
||||||
if (Object.keys(this.pageAnchors).length !== 0) {
|
if (Object.keys(this.pageAnchors).length !== 0) {
|
||||||
// get the height of the document so we can capture markers that are halfway on the document viewport
|
// get the height of the document so we can capture markers that are halfway on the document viewport
|
||||||
const verticalOffset = (window.pageYOffset
|
const verticalOffset = this.scrollService.scrollPosition + (document.body.offsetHeight / 2);
|
||||||
|| document.documentElement.scrollTop
|
|
||||||
|| document.body.scrollTop || 0) + (document.body.offsetHeight / 2);
|
|
||||||
|
|
||||||
const alreadyReached = Object.values(this.pageAnchors).filter((i: number) => i <= verticalOffset);
|
const alreadyReached = Object.values(this.pageAnchors).filter((i: number) => i <= verticalOffset);
|
||||||
if (alreadyReached.length > 0) {
|
if (alreadyReached.length > 0) {
|
||||||
@ -518,15 +518,9 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
if (part !== undefined && part !== '') {
|
if (part !== undefined && part !== '') {
|
||||||
this.scrollTo(part);
|
this.scrollTo(part);
|
||||||
} else if (scrollTop !== undefined && scrollTop !== 0) {
|
} else if (scrollTop !== undefined && scrollTop !== 0) {
|
||||||
window.scroll({
|
this.scrollService.scrollTo(scrollTop);
|
||||||
top: scrollTop,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
window.scroll({
|
this.scrollService.scrollTo(0);
|
||||||
top: 0,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,10 +748,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
|
|
||||||
if (element === null) return;
|
if (element === null) return;
|
||||||
|
|
||||||
window.scroll({
|
this.scrollService.scrollTo(element.getBoundingClientRect().top + window.pageYOffset + TOP_OFFSET);
|
||||||
top: element.getBoundingClientRect().top + window.pageYOffset + TOP_OFFSET,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleClickToPaginate() {
|
toggleClickToPaginate() {
|
||||||
|
@ -18,7 +18,7 @@ import { EditSeriesModalComponent } from '../_modals/edit-series-modal/edit-seri
|
|||||||
styleUrls: ['./series-card.component.scss']
|
styleUrls: ['./series-card.component.scss']
|
||||||
})
|
})
|
||||||
export class SeriesCardComponent implements OnInit, OnChanges {
|
export class SeriesCardComponent implements OnInit, OnChanges {
|
||||||
@Input() data: Series | undefined;
|
@Input() data!: Series;
|
||||||
@Input() libraryId = 0;
|
@Input() libraryId = 0;
|
||||||
@Input() suppressLibraryLink = false;
|
@Input() suppressLibraryLink = false;
|
||||||
@Output() clicked = new EventEmitter<Series>();
|
@Output() clicked = new EventEmitter<Series>();
|
||||||
@ -50,7 +50,7 @@ export class SeriesCardComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
ngOnChanges(changes: any) {
|
ngOnChanges(changes: any) {
|
||||||
if (this.data) {
|
if (this.data) {
|
||||||
this.actions = this.actionFactoryService.getSeriesActions((action: Action, series: Series) => this.handleSeriesActionCallback(action, series));
|
this.actions = this.actionFactoryService.getSeriesActions((action: Action, series: Series) => this.handleSeriesActionCallback(action, series)).filter(action => this.actionFactoryService.filterBookmarksForFormat(action, this.data));
|
||||||
this.imageUrl = this.imageService.randomize(this.imageService.getSeriesCoverImage(this.data.id));
|
this.imageUrl = this.imageService.randomize(this.imageService.getSeriesCoverImage(this.data.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<app-carousel-reel [items]="recentlyAdded" title="Recently Added" (sectionClick)="handleSectionClick($event)">
|
<app-carousel-reel [items]="recentlyAdded" title="Recently Added" (sectionClick)="handleSectionClick($event)">
|
||||||
<ng-template #carouselItem let-item let-position="idx">
|
<ng-template #carouselItem let-item let-position="idx">
|
||||||
<app-series-card [data]="item" [libraryId]="item.libraryId"></app-series-card>
|
<app-series-card [data]="item" [libraryId]="item.libraryId" (reload)="reloadTags()" (dataChanged)="loadRecentlyAdded()"></app-series-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</app-carousel-reel>
|
</app-carousel-reel>
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
|||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { take, takeUntil } from 'rxjs/operators';
|
import { take, takeUntil } from 'rxjs/operators';
|
||||||
import { EditCollectionTagsComponent } from '../cards/_modals/edit-collection-tags/edit-collection-tags.component';
|
import { EditCollectionTagsComponent } from '../cards/_modals/edit-collection-tags/edit-collection-tags.component';
|
||||||
|
import { ScrollService } from '../scroll.service';
|
||||||
import { CollectionTag } from '../_models/collection-tag';
|
import { CollectionTag } from '../_models/collection-tag';
|
||||||
import { InProgressChapter } from '../_models/in-progress-chapter';
|
import { InProgressChapter } from '../_models/in-progress-chapter';
|
||||||
import { Library } from '../_models/library';
|
import { Library } from '../_models/library';
|
||||||
@ -42,7 +43,8 @@ export class LibraryComponent implements OnInit, OnDestroy {
|
|||||||
constructor(public accountService: AccountService, private libraryService: LibraryService,
|
constructor(public accountService: AccountService, private libraryService: LibraryService,
|
||||||
private seriesService: SeriesService, private actionFactoryService: ActionFactoryService,
|
private seriesService: SeriesService, private actionFactoryService: ActionFactoryService,
|
||||||
private collectionService: CollectionTagService, private router: Router,
|
private collectionService: CollectionTagService, private router: Router,
|
||||||
private modalService: NgbModal, private titleService: Title, public imageService: ImageService) { }
|
private modalService: NgbModal, private titleService: Title, public imageService: ImageService,
|
||||||
|
private scrollService: ScrollService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.titleService.setTitle('Kavita - Dashboard');
|
this.titleService.setTitle('Kavita - Dashboard');
|
||||||
@ -67,13 +69,9 @@ export class LibraryComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reloadSeries() {
|
reloadSeries() {
|
||||||
this.seriesService.getRecentlyAdded(0, 0, 20).pipe(takeUntil(this.onDestroy)).subscribe(updatedSeries => {
|
this.loadRecentlyAdded();
|
||||||
this.recentlyAdded = updatedSeries.result;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.seriesService.getInProgress().pipe(takeUntil(this.onDestroy)).subscribe((updatedSeries) => {
|
this.loadInProgress();
|
||||||
this.inProgress = updatedSeries.result;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.reloadTags();
|
this.reloadTags();
|
||||||
}
|
}
|
||||||
@ -88,11 +86,20 @@ export class LibraryComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.loadInProgress();
|
||||||
|
this.reloadTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadInProgress() {
|
||||||
this.seriesService.getInProgress().pipe(takeUntil(this.onDestroy)).subscribe((updatedSeries) => {
|
this.seriesService.getInProgress().pipe(takeUntil(this.onDestroy)).subscribe((updatedSeries) => {
|
||||||
this.inProgress = updatedSeries.result;
|
this.inProgress = updatedSeries.result;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.reloadTags();
|
loadRecentlyAdded() {
|
||||||
|
this.seriesService.getRecentlyAdded(0, 0, 20).pipe(takeUntil(this.onDestroy)).subscribe(updatedSeries => {
|
||||||
|
this.recentlyAdded = updatedSeries.result;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadTags() {
|
reloadTags() {
|
||||||
|
@ -3,6 +3,7 @@ import { Component, HostListener, Inject, OnDestroy, OnInit, ViewChild } from '@
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { ScrollService } from '../scroll.service';
|
||||||
import { UtilityService } from '../shared/_services/utility.service';
|
import { UtilityService } from '../shared/_services/utility.service';
|
||||||
import { SearchResult } from '../_models/search-result';
|
import { SearchResult } from '../_models/search-result';
|
||||||
import { AccountService } from '../_services/account.service';
|
import { AccountService } from '../_services/account.service';
|
||||||
@ -30,7 +31,7 @@ export class NavHeaderComponent implements OnInit, OnDestroy {
|
|||||||
private readonly onDestroy = new Subject<void>();
|
private readonly onDestroy = new Subject<void>();
|
||||||
|
|
||||||
constructor(public accountService: AccountService, private router: Router, public navService: NavService,
|
constructor(public accountService: AccountService, private router: Router, public navService: NavService,
|
||||||
private libraryService: LibraryService, public imageService: ImageService, @Inject(DOCUMENT) private document: Document) { }
|
private libraryService: LibraryService, public imageService: ImageService, @Inject(DOCUMENT) private document: Document, private scrollService: ScrollService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.navService.darkMode$.pipe(takeUntil(this.onDestroy)).subscribe(res => {
|
this.navService.darkMode$.pipe(takeUntil(this.onDestroy)).subscribe(res => {
|
||||||
@ -46,7 +47,7 @@ export class NavHeaderComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
@HostListener("window:scroll", [])
|
@HostListener("window:scroll", [])
|
||||||
checkBackToTopNeeded() {
|
checkBackToTopNeeded() {
|
||||||
const offset = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
|
const offset = this.scrollService.scrollPosition;
|
||||||
if (offset > 100) {
|
if (offset > 100) {
|
||||||
this.backToTopNeeded = true;
|
this.backToTopNeeded = true;
|
||||||
} else if (offset < 40) {
|
} else if (offset < 40) {
|
||||||
|
22
UI/Web/src/app/scroll.service.ts
Normal file
22
UI/Web/src/app/scroll.service.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ScrollService {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
get scrollPosition() {
|
||||||
|
return (window.pageYOffset
|
||||||
|
|| document.documentElement.scrollTop
|
||||||
|
|| document.body.scrollTop || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollTo(top: number) {
|
||||||
|
window.scroll({
|
||||||
|
top: top,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -116,11 +116,6 @@ export class SeriesDetailComponent implements OnInit {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.seriesActions = this.actionFactoryService.getSeriesActions(this.handleSeriesActionCallback.bind(this)).filter(action => action.action !== Action.Edit);
|
|
||||||
this.volumeActions = this.actionFactoryService.getVolumeActions(this.handleVolumeActionCallback.bind(this));
|
|
||||||
this.chapterActions = this.actionFactoryService.getChapterActions(this.handleChapterActionCallback.bind(this));
|
|
||||||
|
|
||||||
|
|
||||||
const seriesId = parseInt(routeId, 10);
|
const seriesId = parseInt(routeId, 10);
|
||||||
this.libraryId = parseInt(libraryId, 10);
|
this.libraryId = parseInt(libraryId, 10);
|
||||||
this.seriesImage = this.imageService.getSeriesCoverImage(seriesId);
|
this.seriesImage = this.imageService.getSeriesCoverImage(seriesId);
|
||||||
@ -244,6 +239,12 @@ export class SeriesDetailComponent implements OnInit {
|
|||||||
|
|
||||||
this.titleService.setTitle('Kavita - ' + this.series.name + ' Details');
|
this.titleService.setTitle('Kavita - ' + this.series.name + ' Details');
|
||||||
|
|
||||||
|
this.seriesActions = this.actionFactoryService.getSeriesActions(this.handleSeriesActionCallback.bind(this))
|
||||||
|
.filter(action => action.action !== Action.Edit)
|
||||||
|
.filter(action => this.actionFactoryService.filterBookmarksForFormat(action, this.series));
|
||||||
|
this.volumeActions = this.actionFactoryService.getVolumeActions(this.handleVolumeActionCallback.bind(this));
|
||||||
|
this.chapterActions = this.actionFactoryService.getChapterActions(this.handleChapterActionCallback.bind(this));
|
||||||
|
|
||||||
|
|
||||||
this.seriesService.getVolumes(this.series.id).subscribe(volumes => {
|
this.seriesService.getVolumes(this.series.id).subscribe(volumes => {
|
||||||
this.chapters = volumes.filter(v => v.number === 0).map(v => v.chapters || []).flat().sort(this.utilityService.sortChapters);
|
this.chapters = volumes.filter(v => v.number === 0).map(v => v.chapters || []).flat().sort(this.utilityService.sortChapters);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user