mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-06-23 15:30:34 -04:00
OPDS Rework (#1164)
* Fixed a bug where the bottom of the page could be cut off * Adjusted all the headings to h2, which looks better * Refactored GetSeriesDetail to actually map the names inside the code so the UI just displays. * Put in some basic improvements to OPDS by using Series Detail type layout, but this only reduces one click. * Fixed a bug where offset from scrollbar fix causes readers to be cutoff. * Ensure the hamburger menu icon is aligned with side nav * Disable the image splitting dropdown in webtoon mode * Fixed broken progress/scroll code as we scroll on the body instead of window now * Fixed phone-hidden class not working due to a bad media query * Lots of changes to OPDS to provide a richer text experience. Uses Issues or Books based on library type. Cleans up the experience by providing Storyline from the get-go. * Updated OPDS-SE search description to include collections and reading lists. * Fixed up some title stuff * If a volume only has one file underneath it, flatten it and send a chapter as if it were the volume. * Code cleanup
This commit is contained in:
parent
50306a62ad
commit
fb29d78c3b
@ -317,18 +317,7 @@ public class OpdsController : BaseApiController
|
|||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
feed.Entries.Add(CreateChapter(apiKey, $"{item.SeriesName} Chapter {item.ChapterNumber}", item.ChapterId, item.VolumeId, item.SeriesId));
|
feed.Entries.Add(CreateChapter(apiKey, $"{item.SeriesName} Chapter {item.ChapterNumber}", item.ChapterId, item.VolumeId, item.SeriesId));
|
||||||
// new FeedEntry()
|
|
||||||
// {
|
|
||||||
// Id = item.ChapterId.ToString(),
|
|
||||||
// Title = $"{item.SeriesName} Chapter {item.ChapterNumber}",
|
|
||||||
// Links = new List<FeedLink>()
|
|
||||||
// {
|
|
||||||
// CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{item.SeriesId}/volume/{item.VolumeId}/chapter/{item.ChapterId}"),
|
|
||||||
// CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={item.ChapterId}")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateXmlResult(SerializeXml(feed));
|
return CreateXmlResult(SerializeXml(feed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,7 +491,7 @@ public class OpdsController : BaseApiController
|
|||||||
var feed = new OpenSearchDescription()
|
var feed = new OpenSearchDescription()
|
||||||
{
|
{
|
||||||
ShortName = "Search",
|
ShortName = "Search",
|
||||||
Description = "Search for Series",
|
Description = "Search for Series, Collections, or Reading Lists",
|
||||||
Url = new SearchLink()
|
Url = new SearchLink()
|
||||||
{
|
{
|
||||||
Type = FeedLinkType.AtomAcquisition,
|
Type = FeedLinkType.AtomAcquisition,
|
||||||
@ -529,11 +518,22 @@ public class OpdsController : BaseApiController
|
|||||||
SetFeedId(feed, $"series-{series.Id}");
|
SetFeedId(feed, $"series-{series.Id}");
|
||||||
feed.Links.Add(CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/series-cover?seriesId={seriesId}"));
|
feed.Links.Add(CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/series-cover?seriesId={seriesId}"));
|
||||||
|
|
||||||
// NOTE: I want to try and use ReaderService to get SeriesDetails.
|
|
||||||
var seriesDetail = await _seriesService.GetSeriesDetail(seriesId, userId);
|
var seriesDetail = await _seriesService.GetSeriesDetail(seriesId, userId);
|
||||||
foreach (var volume in seriesDetail.Volumes)
|
foreach (var volume in seriesDetail.Volumes)
|
||||||
{
|
{
|
||||||
feed.Entries.Add(CreateVolume(volume, seriesId, apiKey)); // We might want to emulate a volume but make this a chapter
|
// If there is only one chapter to the Volume, we will emulate a volume to flatten the amount of hops a user must go through
|
||||||
|
if (volume.Chapters.Count == 1)
|
||||||
|
{
|
||||||
|
var firstChapter = volume.Chapters.First();
|
||||||
|
var chapter = CreateChapter(apiKey, volume.Name, firstChapter.Id, volume.Id, seriesId);
|
||||||
|
chapter.Id = firstChapter.Id.ToString();
|
||||||
|
feed.Entries.Add(chapter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
feed.Entries.Add(CreateVolume(volume, seriesId, apiKey));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var storylineChapter in seriesDetail.StorylineChapters.Where(c => !c.IsSpecial))
|
foreach (var storylineChapter in seriesDetail.StorylineChapters.Where(c => !c.IsSpecial))
|
||||||
@ -546,8 +546,6 @@ public class OpdsController : BaseApiController
|
|||||||
feed.Entries.Add(CreateChapter(apiKey, special.Title, special.Id, special.VolumeId, seriesId));
|
feed.Entries.Add(CreateChapter(apiKey, special.Title, special.Id, special.VolumeId, seriesId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return CreateXmlResult(SerializeXml(feed));
|
return CreateXmlResult(SerializeXml(feed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,19 +557,20 @@ public class OpdsController : BaseApiController
|
|||||||
return BadRequest("OPDS is not enabled on this server");
|
return BadRequest("OPDS is not enabled on this server");
|
||||||
var userId = await GetUser(apiKey);
|
var userId = await GetUser(apiKey);
|
||||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||||
|
var libraryType = await _unitOfWork.LibraryRepository.GetLibraryTypeAsync(series.LibraryId);
|
||||||
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(volumeId);
|
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(volumeId);
|
||||||
var chapters =
|
var chapters =
|
||||||
(await _unitOfWork.ChapterRepository.GetChaptersAsync(volumeId)).OrderBy(x => double.Parse(x.Number),
|
(await _unitOfWork.ChapterRepository.GetChaptersAsync(volumeId)).OrderBy(x => double.Parse(x.Number),
|
||||||
_chapterSortComparer);
|
_chapterSortComparer);
|
||||||
|
|
||||||
var feed = CreateFeed(series.Name + " - Volume " + volume.Name + " - Chapters ", $"{apiKey}/series/{seriesId}/volume/{volumeId}", apiKey);
|
var feed = CreateFeed(series.Name + " - Volume " + volume.Name + $" - {SeriesService.FormatChapterName(libraryType)}s ", $"{apiKey}/series/{seriesId}/volume/{volumeId}", apiKey);
|
||||||
SetFeedId(feed, $"series-{series.Id}-volume-{volume.Id}-chapters");
|
SetFeedId(feed, $"series-{series.Id}-volume-{volume.Id}-{SeriesService.FormatChapterName(libraryType)}s");
|
||||||
foreach (var chapter in chapters)
|
foreach (var chapter in chapters)
|
||||||
{
|
{
|
||||||
feed.Entries.Add(new FeedEntry()
|
feed.Entries.Add(new FeedEntry()
|
||||||
{
|
{
|
||||||
Id = chapter.Id.ToString(),
|
Id = chapter.Id.ToString(),
|
||||||
Title = "Chapter " + chapter.Number,
|
Title = SeriesService.FormatChapterTitle(chapter, libraryType),
|
||||||
Links = new List<FeedLink>()
|
Links = new List<FeedLink>()
|
||||||
{
|
{
|
||||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapter.Id}"),
|
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapter.Id}"),
|
||||||
@ -591,15 +590,16 @@ public class OpdsController : BaseApiController
|
|||||||
return BadRequest("OPDS is not enabled on this server");
|
return BadRequest("OPDS is not enabled on this server");
|
||||||
var userId = await GetUser(apiKey);
|
var userId = await GetUser(apiKey);
|
||||||
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId);
|
||||||
|
var libraryType = await _unitOfWork.LibraryRepository.GetLibraryTypeAsync(series.LibraryId);
|
||||||
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(volumeId);
|
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(volumeId);
|
||||||
var chapter = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(chapterId);
|
var chapter = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(chapterId);
|
||||||
var files = await _unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapterId);
|
var files = await _unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapterId);
|
||||||
|
|
||||||
var feed = CreateFeed(series.Name + " - Volume " + volume.Name + " - Chapters ", $"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}", apiKey);
|
var feed = CreateFeed(series.Name + " - Volume " + volume.Name + $" - {SeriesService.FormatChapterName(libraryType)}s", $"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}", apiKey);
|
||||||
SetFeedId(feed, $"series-{series.Id}-volume-{volume.Id}-chapter-{chapter.Id}-files");
|
SetFeedId(feed, $"series-{series.Id}-volume-{volumeId}-{SeriesService.FormatChapterName(libraryType)}-{chapterId}-files");
|
||||||
foreach (var mangaFile in files)
|
foreach (var mangaFile in files)
|
||||||
{
|
{
|
||||||
feed.Entries.Add(CreateChapter(seriesId, volumeId, chapterId, mangaFile, series, volume, chapter, apiKey));
|
feed.Entries.Add(await CreateChapterWithFile(seriesId, volumeId, chapterId, mangaFile, series, chapter, apiKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateXmlResult(SerializeXml(feed));
|
return CreateXmlResult(SerializeXml(feed));
|
||||||
@ -706,19 +706,21 @@ public class OpdsController : BaseApiController
|
|||||||
return new FeedEntry()
|
return new FeedEntry()
|
||||||
{
|
{
|
||||||
Id = volumeDto.Id.ToString(),
|
Id = volumeDto.Id.ToString(),
|
||||||
Title = "Volume " + volumeDto.Name,
|
Title = volumeDto.Name,
|
||||||
Links = new List<FeedLink>()
|
Links = new List<FeedLink>()
|
||||||
{
|
{
|
||||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, Prefix + $"{apiKey}/series/{seriesId}/volume/{volumeDto.Id}"),
|
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
||||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/volume-cover?volumeId={volumeDto.Id}"),
|
Prefix + $"{apiKey}/series/{seriesId}/volume/{volumeDto.Id}"),
|
||||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"/api/image/volume-cover?volumeId={volumeDto.Id}")
|
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image,
|
||||||
|
$"/api/image/volume-cover?volumeId={volumeDto.Id}"),
|
||||||
|
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image,
|
||||||
|
$"/api/image/volume-cover?volumeId={volumeDto.Id}")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FeedEntry CreateChapter(string apiKey, string title, int chapterId, int volumeId, int seriesId)
|
private static FeedEntry CreateChapter(string apiKey, string title, int chapterId, int volumeId, int seriesId)
|
||||||
{
|
{
|
||||||
|
|
||||||
return new FeedEntry()
|
return new FeedEntry()
|
||||||
{
|
{
|
||||||
Id = chapterId.ToString(),
|
Id = chapterId.ToString(),
|
||||||
@ -728,22 +730,36 @@ public class OpdsController : BaseApiController
|
|||||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
||||||
Prefix + $"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}"),
|
Prefix + $"{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}"),
|
||||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image,
|
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image,
|
||||||
|
$"/api/image/chapter-cover?chapterId={chapterId}"),
|
||||||
|
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image,
|
||||||
$"/api/image/chapter-cover?chapterId={chapterId}")
|
$"/api/image/chapter-cover?chapterId={chapterId}")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private FeedEntry CreateChapter(int seriesId, int volumeId, int chapterId, MangaFile mangaFile, SeriesDto series, Volume volume, ChapterDto chapter, string apiKey)
|
private async Task<FeedEntry> CreateChapterWithFile(int seriesId, int volumeId, int chapterId, MangaFile mangaFile, SeriesDto series, ChapterDto chapter, string apiKey)
|
||||||
{
|
{
|
||||||
var fileSize =
|
var fileSize =
|
||||||
DirectoryService.GetHumanReadableBytes(_directoryService.GetTotalSize(new List<string>()
|
DirectoryService.GetHumanReadableBytes(_directoryService.GetTotalSize(new List<string>()
|
||||||
{mangaFile.FilePath}));
|
{mangaFile.FilePath}));
|
||||||
var fileType = _downloadService.GetContentTypeFromFile(mangaFile.FilePath);
|
var fileType = _downloadService.GetContentTypeFromFile(mangaFile.FilePath);
|
||||||
var filename = Uri.EscapeDataString(Path.GetFileName(mangaFile.FilePath) ?? string.Empty);
|
var filename = Uri.EscapeDataString(Path.GetFileName(mangaFile.FilePath) ?? string.Empty);
|
||||||
|
var libraryType = await _unitOfWork.LibraryRepository.GetLibraryTypeAsync(series.LibraryId);
|
||||||
|
|
||||||
|
|
||||||
|
var title = $"{series.Name} - {SeriesService.FormatChapterTitle(chapter, libraryType)}";
|
||||||
|
|
||||||
|
// Chunky requires a file at the end. Our API ignores this
|
||||||
|
var accLink =
|
||||||
|
CreateLink(FeedLinkRelation.Acquisition, fileType,
|
||||||
|
$"{Prefix}{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}/download/{filename}",
|
||||||
|
filename);
|
||||||
|
accLink.TotalPages = chapter.Pages;
|
||||||
|
|
||||||
return new FeedEntry()
|
return new FeedEntry()
|
||||||
{
|
{
|
||||||
Id = mangaFile.Id.ToString(),
|
Id = mangaFile.Id.ToString(),
|
||||||
Title = $"{series.Name} - Volume {volume.Name} - Chapter {chapter.Number}",
|
Title = title,
|
||||||
Extent = fileSize,
|
Extent = fileSize,
|
||||||
Summary = $"{fileType.Split("/")[1]} - {fileSize}",
|
Summary = $"{fileType.Split("/")[1]} - {fileSize}",
|
||||||
Format = mangaFile.Format.ToString(),
|
Format = mangaFile.Format.ToString(),
|
||||||
@ -751,8 +767,7 @@ public class OpdsController : BaseApiController
|
|||||||
{
|
{
|
||||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={chapterId}"),
|
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={chapterId}"),
|
||||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={chapterId}"),
|
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"/api/image/chapter-cover?chapterId={chapterId}"),
|
||||||
// Chunky requires a file at the end. Our API ignores this
|
accLink,
|
||||||
CreateLink(FeedLinkRelation.Acquisition, fileType, $"{Prefix}{apiKey}/series/{seriesId}/volume/{volumeId}/chapter/{chapterId}/download/{filename}"),
|
|
||||||
CreatePageStreamLink(seriesId, volumeId, chapterId, mangaFile, apiKey)
|
CreatePageStreamLink(seriesId, volumeId, chapterId, mangaFile, apiKey)
|
||||||
},
|
},
|
||||||
Content = new FeedEntryContent()
|
Content = new FeedEntryContent()
|
||||||
@ -839,13 +854,14 @@ public class OpdsController : BaseApiController
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FeedLink CreateLink(string rel, string type, string href)
|
private static FeedLink CreateLink(string rel, string type, string href, string title = null)
|
||||||
{
|
{
|
||||||
return new FeedLink()
|
return new FeedLink()
|
||||||
{
|
{
|
||||||
Rel = rel,
|
Rel = rel,
|
||||||
Href = href,
|
Href = href,
|
||||||
Type = type
|
Type = type,
|
||||||
|
Title = string.IsNullOrEmpty(title) ? string.Empty : title
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,23 +472,11 @@ public class SeriesService : ISeriesService
|
|||||||
var specials = new List<ChapterDto>();
|
var specials = new List<ChapterDto>();
|
||||||
foreach (var chapter in chapters)
|
foreach (var chapter in chapters)
|
||||||
{
|
{
|
||||||
|
chapter.Title = FormatChapterTitle(chapter, libraryType);
|
||||||
if (chapter.IsSpecial)
|
if (chapter.IsSpecial)
|
||||||
{
|
{
|
||||||
chapter.Title = Parser.Parser.CleanSpecialTitle(chapter.Title);
|
|
||||||
specials.Add(chapter);
|
specials.Add(chapter);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var title = libraryType switch
|
|
||||||
{
|
|
||||||
LibraryType.Book => $"Book {chapter.Title}",
|
|
||||||
LibraryType.Comic => $"Issue #{chapter.Title}",
|
|
||||||
LibraryType.Manga => $"Chapter {chapter.Title}",
|
|
||||||
_ => "Chapter "
|
|
||||||
};
|
|
||||||
chapter.Title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -528,4 +516,49 @@ public class SeriesService : ISeriesService
|
|||||||
{
|
{
|
||||||
return !c.IsSpecial && !c.Number.Equals(Parser.Parser.DefaultChapter);
|
return !c.IsSpecial && !c.Number.Equals(Parser.Parser.DefaultChapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string FormatChapterTitle(ChapterDto chapter, LibraryType libraryType)
|
||||||
|
{
|
||||||
|
if (chapter.IsSpecial)
|
||||||
|
{
|
||||||
|
return Parser.Parser.CleanSpecialTitle(chapter.Title);
|
||||||
|
}
|
||||||
|
return libraryType switch
|
||||||
|
{
|
||||||
|
LibraryType.Book => $"Book {chapter.Title}",
|
||||||
|
LibraryType.Comic => $"Issue #{chapter.Title}",
|
||||||
|
LibraryType.Manga => $"Chapter {chapter.Title}",
|
||||||
|
_ => "Chapter "
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatChapterTitle(Chapter chapter, LibraryType libraryType)
|
||||||
|
{
|
||||||
|
if (chapter.IsSpecial)
|
||||||
|
{
|
||||||
|
return Parser.Parser.CleanSpecialTitle(chapter.Title);
|
||||||
|
}
|
||||||
|
return libraryType switch
|
||||||
|
{
|
||||||
|
LibraryType.Book => $"Book {chapter.Title}",
|
||||||
|
LibraryType.Comic => $"Issue #{chapter.Title}",
|
||||||
|
LibraryType.Manga => $"Chapter {chapter.Title}",
|
||||||
|
_ => "Chapter "
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FormatChapterName(LibraryType libraryType, bool withHash = false)
|
||||||
|
{
|
||||||
|
switch (libraryType)
|
||||||
|
{
|
||||||
|
case LibraryType.Manga:
|
||||||
|
return "Chapter";
|
||||||
|
case LibraryType.Comic:
|
||||||
|
return withHash ? "Issue #" : "Issue";
|
||||||
|
case LibraryType.Book:
|
||||||
|
return "Book";
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(libraryType), libraryType, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, Renderer2, SimpleChanges } from '@angular/core';
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { Component, ElementRef, EventEmitter, Inject, Input, OnChanges, OnDestroy, OnInit, Output, Renderer2, SimpleChanges } from '@angular/core';
|
||||||
import { BehaviorSubject, fromEvent, merge, ReplaySubject, Subject } from 'rxjs';
|
import { BehaviorSubject, fromEvent, merge, ReplaySubject, Subject } from 'rxjs';
|
||||||
import { debounceTime, take, takeUntil } from 'rxjs/operators';
|
import { debounceTime, take, takeUntil } from 'rxjs/operators';
|
||||||
import { ReaderService } from '../../_services/reader.service';
|
import { ReaderService } from '../../_services/reader.service';
|
||||||
@ -92,7 +93,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* The minimum width of images in webtoon. On image loading, this is checked and updated. All images will get this assigned to them for rendering.
|
* The minimum width of images in webtoon. On image loading, this is checked and updated. All images will get this assigned to them for rendering.
|
||||||
*/
|
*/
|
||||||
webtoonImageWidth: number = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
webtoonImageWidth: number = window.innerWidth || this.document.documentElement.clientWidth || this.document.body.clientWidth;
|
||||||
/**
|
/**
|
||||||
* Used to tell if a scrollTo() operation is in progress
|
* Used to tell if a scrollTo() operation is in progress
|
||||||
*/
|
*/
|
||||||
@ -152,7 +153,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
private readonly onDestroy = new Subject<void>();
|
private readonly onDestroy = new Subject<void>();
|
||||||
|
|
||||||
constructor(private readerService: ReaderService, private renderer: Renderer2) {
|
constructor(private readerService: ReaderService, private renderer: Renderer2, @Inject(DOCUMENT) private document: Document) {
|
||||||
// This will always exist at this point in time since this is used within manga reader
|
// This will always exist at this point in time since this is used within manga reader
|
||||||
const reader = document.querySelector('.reader');
|
const reader = document.querySelector('.reader');
|
||||||
if (reader !== null) {
|
if (reader !== null) {
|
||||||
@ -174,11 +175,11 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for binding the scroll handler to the correct event. On non-fullscreen, window is correct. However, on fullscreen, we must use the reader as that is what
|
* Responsible for binding the scroll handler to the correct event. On non-fullscreen, body is correct. However, on fullscreen, we must use the reader as that is what
|
||||||
* gets promoted to fullscreen.
|
* gets promoted to fullscreen.
|
||||||
*/
|
*/
|
||||||
initScrollHandler() {
|
initScrollHandler() {
|
||||||
fromEvent(this.isFullscreenMode ? this.readerElemRef.nativeElement : window, 'scroll')
|
fromEvent(this.isFullscreenMode ? this.readerElemRef.nativeElement : this.document.body, 'scroll')
|
||||||
.pipe(debounceTime(20), takeUntil(this.onDestroy))
|
.pipe(debounceTime(20), takeUntil(this.onDestroy))
|
||||||
.subscribe((event) => this.handleScrollEvent(event));
|
.subscribe((event) => this.handleScrollEvent(event));
|
||||||
}
|
}
|
||||||
@ -233,7 +234,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getVerticalOffset() {
|
getVerticalOffset() {
|
||||||
const reader = this.isFullscreenMode ? this.readerElemRef.nativeElement : window;
|
const reader = this.isFullscreenMode ? this.readerElemRef.nativeElement : this.document.body;
|
||||||
|
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
if (reader instanceof Window) {
|
if (reader instanceof Window) {
|
||||||
|
@ -1213,6 +1213,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
updateForm() {
|
updateForm() {
|
||||||
|
|
||||||
if ( this.readerMode === ReaderMode.Webtoon) {
|
if ( this.readerMode === ReaderMode.Webtoon) {
|
||||||
|
this.generalSettingsForm.get('pageSplitOption')?.disable()
|
||||||
this.generalSettingsForm.get('fittingOption')?.disable()
|
this.generalSettingsForm.get('fittingOption')?.disable()
|
||||||
this.generalSettingsForm.get('pageSplitOption')?.disable();
|
this.generalSettingsForm.get('pageSplitOption')?.disable();
|
||||||
this.generalSettingsForm.get('layoutMode')?.disable();
|
this.generalSettingsForm.get('layoutMode')?.disable();
|
||||||
@ -1220,6 +1221,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
this.generalSettingsForm.get('fittingOption')?.enable()
|
this.generalSettingsForm.get('fittingOption')?.enable()
|
||||||
this.generalSettingsForm.get('pageSplitOption')?.enable();
|
this.generalSettingsForm.get('pageSplitOption')?.enable();
|
||||||
this.generalSettingsForm.get('layoutMode')?.enable();
|
this.generalSettingsForm.get('layoutMode')?.enable();
|
||||||
|
this.generalSettingsForm.get('pageSplitOption')?.enable()
|
||||||
|
|
||||||
if (this.layoutMode !== LayoutMode.Single) {
|
if (this.layoutMode !== LayoutMode.Single) {
|
||||||
this.generalSettingsForm.get('pageSplitOption')?.disable();
|
this.generalSettingsForm.get('pageSplitOption')?.disable();
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
.side-nav-toggle {
|
.side-nav-toggle {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
margin-left: 13px;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
i {
|
i {
|
||||||
color: var(--navbar-fa-icon-color);
|
color: var(--navbar-fa-icon-color);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@media(max-width: $grid-breakpoints-xs) {
|
@media(max-width: $grid-breakpoints-sm) {
|
||||||
.phone-hidden {
|
.phone-hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user