{"version":3,"mappings":"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","names":["AdminGuard","constructor","accountService","toastr","this","canActivate","currentUser$","pipe","take","map","user","hasAdminRole","error","i0","factory","AuthGuard","router","toasts","filter","toast","message","length","localStorage","setItem","urlKey","window","location","pathname","navigateByUrl","LibraryAccessGuard","memberService","next","state","libraryId","parseInt","url","split","isNaN","of","hasLibraryAccess","LibraryType","MangaFormat","PersonRole","ThemeProvider","reset","libraries","series","collections","readingLists","persons","genres","tags","files","chapters","SortField","mangaFormatFilters","title","value","selected","AccountService","httpClient","messageHub","themeService","environment","ReplaySubject","currentUserSource","asObservable","Subject","ngOnDestroy","onDestroy","complete","roles","includes","hasChangePasswordRole","hasDownloadRole","getRoles","get","baseUrl","login","model","post","response","setCurrentUser","createHubConnection","takeUntil","getDecodedToken","token","role","Array","isArray","push","userKey","JSON","stringify","lastLoginKey","username","setTheme","b","preferences","theme","name","defaultTheme","currentUser","undefined","startRefreshTokenTimer","stopRefreshTokenTimer","logout","removeItem","stopHubConnection","register","migrateUser","responseType","confirmMigrationEmail","resendConfirmationEmail","userId","inviteUser","confirmEmail","parse","atob","requestResetPasswordEmail","email","encodeURIComponent","confirmResetPasswordEmail","resetPassword","password","update","getPreferences","pref","updatePreferences","userPreferences","settings","getUserFromLocalStorage","userString","getItem","resetApiKey","key","apiKey","refreshToken","refreshTokenTimeout","jwtToken","timeout","Date","exp","getTime","now","setTimeout","subscribe","clearTimeout","Action","ActionFactoryService","isAdmin","_resetActions","collectionTagActions","action","Edit","callback","dummyCallback","requiresAdmin","seriesActions","ScanLibrary","RefreshMetadata","Delete","AddToCollection","libraryActions","chapterActions","volumeActions","Download","getLibraryActions","actions","a","Object","forEach","getSeriesActions","getVolumeActions","getChapterActions","getCollectionTagActions","getReadingListActions","readingListActions","getBookmarkActions","bookmarkActions","filterBookmarksForFormat","Bookmarks","c","format","data","MarkAsRead","MarkAsUnread","AddToReadingList","IncognitoRead","ViewSeries","DownloadBookmark","P","ctx_r5","tmp_b_0","ctx_r10","BulkAddToCollectionComponent","modal","collectionService","FormGroup","listItem","toLowerCase","indexOf","listForm","filterQuery","ngOnInit","addControl","FormControl","loading","allTags","lists","ngAfterViewInit","inputElem","nativeElement","select","close","create","tagName","addByMultiple","seriesIds","success","addToCollection","tag","id","selectors","ctx","ADD_FLOW","AddToListModalComponent","readingListService","getReadingLists","result","createList","list","addToList","readingList","type","Multiple_Series","updateByMultipleSeries","seriesId","Series","updateBySeries","Volume","volumeId","updateByVolume","Chapter","chapterId","updateByChapter","Multiple","volumeIds","chapterIds","updateByMultiple","ctx_r6","ctx_r7","EditReadingListModalComponent","ngModal","utilityService","uploadService","imageService","disabled","tabs","Breakpoint","reviewGroup","Validators","summary","imageUrls","randomize","getReadingListCoverImage","dismiss","save","trim","readingListId","promoted","coverImageLocked","apis","selectedCover","updateReadingListCoverImage","forkJoin","results","togglePromotion","originalPromotion","res","err","updateSelectedIndex","index","coverImageIndex","updateSelectedImage","handleReset","ActionService","libraryService","seriesService","readerService","modalService","confirmService","scanLibrary","library","hasOwnProperty","scan","h","info","refreshMetadata","confirm","markSeriesAsRead","markRead","pagesRead","pages","markSeriesAsUnread","markUnread","scanSeries","refreshMetdata","markVolumeAsRead","volume","markVolumeRead","_a","markVolumeAsUnread","markVolumeUnread","markChapterAsRead","chapter","saveProgress","markChapterAsUnread","markMultipleAsRead","volumes","markMultipleRead","v","T","Y","markMultipleAsUnread","markMultipleUnread","markMultipleSeriesAsRead","markMultipleSeriesRead","s","markMultipleSeriesAsUnread","markMultipleSeriesUnread","addMultipleToReadingList","readingListModalRef","open","scrollable","size","componentInstance","closed","dismissed","addMultipleSeriesToReadingList","addMultipleSeriesToCollectionTag","collectionModalRef","windowClass","addSeriesToReadingList","addVolumeToReadingList","addChapterToReadingList","editReadingList","deleteMultipleSeries","deleteSeries","delete","CollectionTagService","coverImage","getCollectionCoverImage","search","query","updateTag","updateSeriesForTag","seriesIdsToRemove","tagId","tagTitle","collectionTagId","collectionTagTitle","ImageService","currentTheme$","isDarkTheme","placeholderImage","errorImage","getRecentlyAddedItem","item","getVolumeCoverImage","getChapterCoverImage","getEntityTypeFromUrl","part","equalIndex","substring","replace","getSeriesCoverImage","getBookmarkedImage","pageNum","getCoverUploadImage","filename","updateErroredImage","event","target","src","r","Math","round","random","LibraryService","getLibraryNames","libraryNames","l","lib","getLibraryName","listDirectories","rootPath","getLibraries","getLibrariesForMember","updateLibrariesForMember","selectedLibraries","getLibraryType","libraryTypes","term","SearchResultGroup","MemberService","getMembers","getMemberNames","adminExists","deleteMember","hasReadingProgress","librayId","getPendingInvites","EVENTS","MessageHubService","BehaviorSubject","messagesSource","onlineUsersSource","isEventType","eventType","NotificationProgress","payload","hubConnection","HubConnectionBuilder","withUrl","hubUrl","accessTokenFactory","withAutomaticReconnect","build","start","catch","console","on","OnlineUsers","usernames","ScanSeries","resp","body","ScanLibraryProgress","LibraryModified","SiteThemeProgress","SeriesAddedToCollection","UserProgressUpdate","Error","SeriesAdded","SeriesRemoved","CoverUpdate","UpdateAvailable","stop","sendMessage","methodName","invoke","NavService","document","rendererFactory","navbarVisibleSource","sideNavCollapseSource","sideNavVisibilitySource","renderer","createRenderer","showNavBar","sideNavState","localStorageSideNavKey","showSideNav","setStyle","querySelector","hideNavBar","removeStyle","hideSideNav","toggleSideNav","val","newVal","DOCUMENT","ReaderService","bookmark","page","unbookmark","getAllBookmarks","getBookmarks","getBookmarksForVolume","getBookmarksForSeries","clearBookmarks","getBookmarkInfo","getProgress","getPageUrl","getBookmarkPageUrl","getChapterInfo","bookScrollId","getNextChapter","currentChapterId","getPrevChapter","hasSeriesProgress","getCurrentChapter","setOverrideStyles","backgroundColor","bodyNode","originalBodyColor","style","background","setAttribute","resetOverrideStyles","imageUrlToPageNum","imageSrc","getNextChapterUrl","nextChapterId","incognitoMode","readingListMode","lastSlashIndex","lastIndexOf","newRoute","getQueryParams","getQueryParamsObject","params","enterFullscreen","el","fullscreenElement","requestFullscreen","then","exitFullscreen","checkFullscreenMode","ReadingListService","getReadingList","includePromoted","itemsPerPage","HttpParams","addPaginationIfExists","observe","createPaginatedResult","PaginatedResult","getReadingListsForSeries","getListItems","updatePosition","readingListItemId","fromPosition","toPosition","deleteItem","removeRead","actionListFilter","ScrollService","scrollPosition","pageYOffset","documentElement","scrollTop","scrollTo","top","scroll","behavior","scrollToX","left","SeriesService","getAllSeries","createSeriesFilter","paginatedResults","getSeriesForLibrary","getAllSeriesByIds","getSeries","getVolumes","getVolume","getChapter","getChapterMetadata","getSeriesForMangaFile","mangaFileId","getSeriesForChapter","updateRating","userRating","userReview","updateSeries","getRecentlyAdded","getRecentlyUpdatedSeries","getOnDeck","getMetadata","items","collectionTags","updateMetadata","seriesMetadata","getSeriesForTag","paginatedSeriesForTagsResults","getRelatedForSeries","updateRelationships","adaptations","characters","contains","others","prequels","sequels","sideStories","spinOffs","alternativeSettings","alternativeVersions","doujinshis","getSeriesDetail","formats","writers","artists","penciller","inker","colorist","letterer","coverArtist","editor","publisher","character","translators","rating","readStatus","read","inProgress","notRead","sortOptions","ageRating","languages","publicationStatus","seriesNameQuery","ThemeService","domSantizer","currentThemeSource","themesSource","getThemes","messages$","notificationEvent","getColorScheme","getComputedStyle","getPropertyValue","getCssVariable","variable","themes","themeCache","clearThemes","unsetThemes","setDefault","themeId","setBookTheme","selector","unsetBookThemes","addClass","clearBookTheme","themeName","find","t","provider","hasThemeInHead","fetchThemeContent","content","__awaiter","alert","styleElem","createElement","appendChild","createTextNode","head","from","children","encodedCss","sanitize","SecurityContext","classList","remove","cls","startsWith","UploadService","uploadByUrl","updateSeriesCoverImage","_cleanBase64Url","updateCollectionCoverImage","updateChapterCoverImage","resetChapterCoverLock","oxw","ctx_r8","CardActionablesComponent","EventEmitter","nonAdminActions","adminActions","preventClick","stopPropagation","preventDefault","performAction","actionHandler","emit","MetadataFilterModule","CommonModule","FormsModule","ReactiveFormsModule","NgbTooltipModule","NgbRatingModule","NgbCollapseModule","SharedModule","TypeaheadModule","CardsModule","RouterModule","PipeModule","NgbNavModule","NgbPaginationModule","NgbDropdownModule","NgbProgressbarModule","NgxFileDropModule","ctx_r11","B","ctx_r16","ctx_r18","CoverImageChooserComponent","fb","form","group","coverImageUrl","getBase64Image","img","canvas","width","height","getContext","alpha","drawImage","toDataURL","selectImage","selectedIndex","imageSelected","selectedBase64Url","loadImage","I","Image","crossOrigin","onload","e","handleUrlImageAdd","onerror","Q","setValue","D","changeMode","mode","setupEnterHandler","Z","focus","dropped","droppedFile","fileEntry","isFile","file","reader","FileReader","handleFileImageAdd","readAsDataURL","imageUrlsChange","fileOver","fileLeave","resetClicked","elem","fromEvent","takeWhile","evt","KEY_CODES","FilterPipe","transform","pure","SafeHtmlPipe","dom","SentenceCasePipe","charAt","toUpperCase","substr","SAVER","InjectionToken","saveAs","FilterQueryParam","FilterUtilitiesService","route","updateUrlFromFilter","pagination","currentPage","urlFromFilter","href","history","replaceState","replacePaginationOnUrl","updateUrlFromPagination","snapshot","queryParamMap","totalItems","totalPages","currentUrl","joinFilter","Format","Genres","AgeRating","PublicationStatus","Tags","Languages","CollectionTags","Libraries","Writers","Artists","Character","Colorist","CoverArtists","Editor","Inker","Letterer","Penciller","Publisher","Translator","ReadStatus","sortField","isAscending","SortBy","Rating","Name","filterProp","join","filterPresetsFromUrl","anyChanged","coverArtists","values","i","sortBy","Number","searchNameQuery","decodeURIComponent","UtilityService","number","parseFloat","mangaFormatToText","mangaFormatKeys","keys","formatChapterName","libraryType","includeHash","includeSpace","cleanSpecialTitle","cleaned","input","reg","mangaFormat","mangaFormatIcon","getLibraryTypeIcon","isVolume","d","isChapter","isSeries","asVolume","asChapter","asSeries","getActiveBreakpoint","innerWidth","Mobile","Tablet","Desktop","isInViewport","element","additionalTopOffset","rect","getBoundingClientRect","bottom","innerHeight","clientHeight","right","clientWidth","deepEqual","object1","object2","keys1","keys2","val1","val2","areObjects","isObject","object","append","paginatedVariable","pageHeader","f","headers","ctx_r2","ConfirmDialogComponent","config","buttons","sort","_button_sort","x","y","xIsSecondary","yIsSecondary","clickButton","button","ConfirmService","ConfirmConfig","defaultConfirm","text","defaultAlert","_type","header","Promise","resolve","reject","modalRef","ImageComponent","hubService","updateEvent","imageUrl","enityType","entityType","ngOnChanges","changes","imgElem","maxWidth","maxHeight","borderRadius","SeriesFormatComponent","NgCircleProgressModule","ctx_r1","UpdateNotificationModalComponent","SidenavModule","production","apiUrl","routes","path","loadChildren","m","AdminModule","CollectionsModule","UserSettingsModule","ReadingListModule","RegistrationModule","AnnouncementsModule","BookmarkModule","AllSeriesModule","DashboardModule","runGuardsAndResolvers","pathMatch","LibraryDetailModule","SeriesDetailModule","MangaReaderModule","BookReaderModule","DevOnlyModule","redirectTo","AppRoutingModule","scrollPositionRestoration","preloadingStrategy","PreloadAllModules","ctx_r21","ctx_r26","ctx_r31","ctx_r36","ctx_r41","ctx_r46","ctx_r51","ctx_r56","GroupedTypeaheadComponent","searchTerm","typeaheadForm","hasData","noResultsTemplate","grouppedData","handleDocumentClick","handleKeyPress","hasFocus","initialValue","valueChanges","debounceTime","change","minQueryLength","prevSearchTerm","inputChanged","onInputFocus","openDropdown","handleResultlick","resetField","clearField","focusChanged","clear","ctx_r35","ctx_r37","EventsWidgetComponent","progressEventsSource","singleUpdateSource","errorSource","processNotificationProgressEvent","getValue","activeEvents","mergeOrUpdate","max","findIndex","handleUpdateAvailableClick","updateNotificationModalRef","updateData","seeMoreError","subTitle","removeError","prettyPrintProgress","progress","trunc","PersonRolePipe","ctx_r4","ctx_r29","ctx_r45","ctx_r48","item_r47","ctx_r54","item_r53","ctx_r59","ctx_r62","ctx_r65","ctx_r67","ctx_r68","ctx_r71","ctx_r79","ctx_r81","NavHeaderComponent","navService","scrollService","normalizedQuery","normalizedSeriesName","normalizedOriginalName","originalName","normalizedLocalizedName","localizedName","checkBackToTopNeeded","offset","backToTopNeeded","moveFocus","getElementById","onChangeSearch","isLoading","searchResults","goTo","queryParamName","clearSearch","navigate","queryParams","goToPerson","searchViewRef","clickSeriesSearchResult","clickFileSearchResult","clickChapterSearchResult","clickLibraryResult","clickCollectionSearchResult","clickReadingListSearchResult","scrollToTop","focusUpdate","searchFocused","SideNavItemComponent","events","NavigationEnd","updateHightlight","link","endsWith","highlighted","comparisonMethod","SideNavComponent","actionFactoryService","actionService","handleAction","bind","sideNavCollapsed$","collapsed","AppComponent","ngbModal","ratingConfig","resettable","NavigationStart","hasOpenModals","dismissAll","onResize","setDocHeight","onOrientationChange","vh","setProperty","JwtInterceptor","intercept","request","clone","setHeaders","Authorization","handle","ErrorInterceptor","catchError","throwError","status","handleValidationError","handleAuthError","handleNotFound","handleServerException","previousToastMessage","modalStateErrors","details","issue","description","flat","errors","statusText","Blob","NavModule","NgbPopoverModule","AppModule","bootstrap","provide","HTTP_INTERCEPTORS","useClass","multi","Title","useFactory","getSaver","imports","HttpClientModule","BrowserModule","BrowserAnimationsModule","ToastrModule","positionClass","preventDuplicates","timeOut","countDuplicates","autoDismiss","enableProdMode","__NgCli_bootstrap_1","bootstrapModule"],"sources":["./src/app/_guards/admin.guard.ts","./src/app/_guards/auth.guard.ts","./src/app/_guards/library-access.guard.ts","./src/app/_models/library.ts","./src/app/_models/manga-format.ts","./src/app/_models/pagination.ts","./src/app/_models/person.ts","./src/app/_models/preferences/site-theme.ts","./src/app/_models/search/search-result-group.ts","./src/app/_models/series-filter.ts","./src/app/_services/account.service.ts","./src/app/_services/action-factory.service.ts","./src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.html","./src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.ts","./src/app/reading-list/_modals/add-to-list-modal/add-to-list-modal.component.html","./src/app/reading-list/_modals/add-to-list-modal/add-to-list-modal.component.ts","./src/app/reading-list/_modals/edit-reading-list-modal/edit-reading-list-modal.component.html","./src/app/reading-list/_modals/edit-reading-list-modal/edit-reading-list-modal.component.ts","./src/app/_services/action.service.ts","./src/app/_services/collection-tag.service.ts","./src/app/_services/image.service.ts","./src/app/_services/library.service.ts","./src/app/_services/member.service.ts","./src/app/_services/message-hub.service.ts","./src/app/_services/nav.service.ts","./src/app/_services/reader.service.ts","./src/app/_services/reading-list.service.ts","./src/app/_services/scroll.service.ts","./src/app/_services/series.service.ts","./src/app/_services/theme.service.ts","./src/app/_services/upload.service.ts","./src/app/cards/card-item/card-actionables/card-actionables.component.html","./src/app/cards/card-item/card-actionables/card-actionables.component.ts","./src/app/metadata-filter/metadata-filter.module.ts","./src/app/cards/cards.module.ts","./src/app/cards/cover-image-chooser/cover-image-chooser.component.html","./src/app/cards/cover-image-chooser/cover-image-chooser.component.ts","./src/app/pipe/filter.pipe.ts","./src/app/pipe/pipe.module.ts","./src/app/pipe/safe-html.pipe.ts","./src/app/pipe/sentence-case.pipe.ts","./src/app/shared/_providers/saver.provider.ts","./src/app/shared/_services/filter-utilities.service.ts","./src/app/shared/_services/utility.service.ts","./src/app/shared/confirm-dialog/_models/confirm-config.ts","./src/app/shared/confirm-dialog/confirm-dialog.component.html","./src/app/shared/confirm-dialog/confirm-dialog.component.ts","./src/app/shared/confirm.service.ts","./src/app/shared/image/image.component.ts","./src/app/shared/image/image.component.html","./src/app/shared/series-format/series-format.component.html","./src/app/shared/series-format/series-format.component.ts","./src/app/shared/shared.module.ts","./src/app/shared/update-notification/update-notification-modal.component.html","./src/app/shared/update-notification/update-notification-modal.component.ts","./src/app/sidenav/sidenav.module.ts","./src/app/typeahead/typeahead.module.ts","./src/environments/environment.prod.ts","./src/app/app-routing.module.ts","./src/app/nav/grouped-typeahead/grouped-typeahead.component.html","./src/app/nav/grouped-typeahead/grouped-typeahead.component.ts","./src/app/nav/events-widget/events-widget.component.html","./src/app/nav/events-widget/events-widget.component.ts","./src/app/pipe/person-role.pipe.ts","./src/app/nav/nav-header/nav-header.component.html","./src/app/nav/nav-header/nav-header.component.ts","./src/app/sidenav/side-nav-item/side-nav-item.component.html","./src/app/sidenav/side-nav-item/side-nav-item.component.ts","./src/app/sidenav/side-nav/side-nav.component.html","./src/app/sidenav/side-nav/side-nav.component.ts","./src/app/app.component.html","./src/app/app.component.ts","./src/app/_interceptors/jwt.interceptor.ts","./src/app/_interceptors/error.interceptor.ts","./src/app/nav/nav.module.ts","./src/app/app.module.ts","./src/main.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { CanActivate } from '@angular/router';\nimport { ToastrService } from 'ngx-toastr';\nimport { Observable } from 'rxjs';\nimport { map, take } from 'rxjs/operators';\nimport { AccountService } from '../_services/account.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class AdminGuard implements CanActivate {\n constructor(private accountService: AccountService, private toastr: ToastrService) {}\n\n canActivate(): Observable {\n // this automaticallys subs due to being router guard\n return this.accountService.currentUser$.pipe(take(1),\n map((user) => {\n if (user && this.accountService.hasAdminRole(user)) {\n return true;\n }\n \n this.toastr.error('You are not authorized to view this page.');\n return false;\n })\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { CanActivate, Router } from '@angular/router';\nimport { ToastrService } from 'ngx-toastr';\nimport { Observable } from 'rxjs';\nimport { map, take } from 'rxjs/operators';\nimport { AccountService } from '../_services/account.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class AuthGuard implements CanActivate {\n public urlKey: string = 'kavita--auth-intersection-url';\n constructor(private accountService: AccountService, private router: Router, private toastr: ToastrService) {}\n\n canActivate(): Observable {\n return this.accountService.currentUser$.pipe(take(1),\n map((user) => {\n if (user) {\n return true;\n }\n if (this.toastr.toasts.filter(toast => toast.message === 'Unauthorized' || toast.message === 'You are not authorized to view this page.').length === 0) {\n this.toastr.error('You are not authorized to view this page.');\n }\n localStorage.setItem(this.urlKey, window.location.pathname);\n this.router.navigateByUrl('/libraries');\n return false;\n })\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';\nimport { Observable, of } from 'rxjs';\nimport { MemberService } from '../_services/member.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class LibraryAccessGuard implements CanActivate {\n\n constructor(private memberService: MemberService) {}\n\n canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable {\n const libraryId = parseInt(state.url.split('library/')[1], 10);\n if (isNaN(libraryId)) return of(false);\n return this.memberService.hasLibraryAccess(libraryId);\n }\n}\n","export enum LibraryType {\n Manga = 0,\n Comic = 1,\n Book = 2,\n}\n\nexport interface Library {\n id: number;\n name: string;\n lastScanned: string;\n type: LibraryType;\n folders: string[];\n}","export enum MangaFormat {\n IMAGE = 0,\n ARCHIVE = 1,\n UNKNOWN = 2,\n EPUB = 3,\n PDF = 4\n}","export interface Pagination {\n currentPage: number;\n itemsPerPage: number;\n totalItems: number;\n totalPages: number;\n}\n\nexport class PaginatedResult {\n result!: T;\n pagination!: Pagination;\n}\n","export enum PersonRole {\n Other = 1,\n Artist = 2,\n Writer = 3,\n Penciller = 4,\n Inker = 5,\n Colorist = 6,\n Letterer = 7,\n CoverArtist = 8,\n Editor = 9,\n Publisher = 10,\n Character = 11,\n Translator = 12\n}\n\nexport interface Person {\n id: number;\n name: string;\n role: PersonRole;\n}","/**\n * Where does the theme come from\n */\n export enum ThemeProvider {\n System = 1,\n User = 2\n }\n \n /**\n * Theme for the whole instance\n */\n export interface SiteTheme {\n id: number;\n name: string;\n filePath: string;\n isDefault: boolean;\n provider: ThemeProvider;\n /**\n * The actual class the root is defined against. It is generated at the backend.\n */\n selector: string;\n }","import { Chapter } from \"../chapter\";\nimport { Library } from \"../library\";\nimport { MangaFile } from \"../manga-file\";\nimport { SearchResult } from \"../search-result\";\nimport { Tag } from \"../tag\";\n\nexport class SearchResultGroup {\n libraries: Array = [];\n series: Array = [];\n collections: Array = [];\n readingLists: Array = [];\n persons: Array = [];\n genres: Array = [];\n tags: Array = [];\n files: Array = [];\n chapters: Array = [];\n\n reset() {\n this.libraries = [];\n this.series = [];\n this.collections = [];\n this.readingLists = [];\n this.persons = [];\n this.genres = [];\n this.tags = [];\n this.files = [];\n this.chapters = []; \n }\n}","import { MangaFormat } from \"./manga-format\";\n\nexport interface FilterItem {\n title: string;\n value: T;\n selected: boolean;\n}\n\nexport interface SeriesFilter {\n formats: Array;\n libraries: Array,\n readStatus: ReadStatus;\n genres: Array;\n writers: Array;\n artists: Array;\n penciller: Array;\n inker: Array;\n colorist: Array;\n letterer: Array;\n coverArtist: Array;\n editor: Array;\n publisher: Array;\n character: Array;\n translators: Array;\n collectionTags: Array;\n rating: number;\n ageRating: Array;\n sortOptions: SortOptions | null;\n tags: Array;\n languages: Array;\n publicationStatus: Array;\n seriesNameQuery: string;\n}\n\nexport interface SortOptions {\n sortField: SortField;\n isAscending: boolean;\n}\n\nexport enum SortField {\n SortName = 1,\n Created = 2,\n LastModified = 3,\n LastChapterAdded = 4\n}\n\nexport interface ReadStatus {\n notRead: boolean,\n inProgress: boolean,\n read: boolean,\n}\n\nexport const mangaFormatFilters = [\n {\n title: 'Images',\n value: MangaFormat.IMAGE,\n selected: false\n },\n {\n title: 'EPUB',\n value: MangaFormat.EPUB,\n selected: false\n },\n {\n title: 'PDF',\n value: MangaFormat.PDF,\n selected: false\n },\n {\n title: 'ARCHIVE',\n value: MangaFormat.ARCHIVE,\n selected: false\n }\n];\n\nexport interface FilterEvent {\n filter: SeriesFilter;\n isFirst: boolean;\n}\n\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable, OnDestroy } from '@angular/core';\nimport { Observable, of, ReplaySubject, Subject } from 'rxjs';\nimport { map, takeUntil } from 'rxjs/operators';\nimport { environment } from 'src/environments/environment';\nimport { Preferences } from '../_models/preferences/preferences';\nimport { User } from '../_models/user';\nimport { Router } from '@angular/router';\nimport { MessageHubService } from './message-hub.service';\nimport { ThemeService } from './theme.service';\nimport { InviteUserResponse } from '../_models/invite-user-response';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class AccountService implements OnDestroy {\n\n baseUrl = environment.apiUrl;\n userKey = 'kavita-user';\n public lastLoginKey = 'kavita-lastlogin';\n currentUser: User | undefined;\n\n // Stores values, when someone subscribes gives (1) of last values seen.\n private currentUserSource = new ReplaySubject(1);\n currentUser$ = this.currentUserSource.asObservable();\n\n /**\n * SetTimeout handler for keeping track of refresh token call\n */\n private refreshTokenTimeout: ReturnType | undefined;\n\n private readonly onDestroy = new Subject();\n\n constructor(private httpClient: HttpClient, private router: Router, \n private messageHub: MessageHubService, private themeService: ThemeService) {}\n \n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n hasAdminRole(user: User) {\n return user && user.roles.includes('Admin');\n }\n\n hasChangePasswordRole(user: User) {\n return user && user.roles.includes('Change Password');\n }\n\n hasDownloadRole(user: User) {\n return user && user.roles.includes('Download');\n }\n\n getRoles() {\n return this.httpClient.get(this.baseUrl + 'account/roles');\n }\n\n login(model: {username: string, password: string}): Observable {\n return this.httpClient.post(this.baseUrl + 'account/login', model).pipe(\n map((response: User) => {\n const user = response;\n if (user) {\n this.setCurrentUser(user);\n this.messageHub.createHubConnection(user, this.hasAdminRole(user));\n }\n }),\n takeUntil(this.onDestroy)\n );\n }\n\n setCurrentUser(user?: User) {\n if (user) {\n user.roles = [];\n const roles = this.getDecodedToken(user.token).role;\n Array.isArray(roles) ? user.roles = roles : user.roles.push(roles);\n\n localStorage.setItem(this.userKey, JSON.stringify(user));\n localStorage.setItem(this.lastLoginKey, user.username);\n if (user.preferences && user.preferences.theme) {\n this.themeService.setTheme(user.preferences.theme.name);\n } else {\n this.themeService.setTheme(this.themeService.defaultTheme);\n }\n } else {\n this.themeService.setTheme(this.themeService.defaultTheme);\n }\n\n this.currentUserSource.next(user);\n this.currentUser = user;\n if (this.currentUser !== undefined) {\n this.startRefreshTokenTimer();\n } else {\n this.stopRefreshTokenTimer();\n }\n }\n\n logout() {\n localStorage.removeItem(this.userKey);\n this.currentUserSource.next(undefined);\n this.currentUser = undefined;\n this.stopRefreshTokenTimer();\n // Upon logout, perform redirection\n this.router.navigateByUrl('/login');\n this.messageHub.stopHubConnection();\n }\n\n\n /**\n * Registers the first admin on the account. Only used for that. All other registrations must occur through invite\n * @param model \n * @returns \n */\n register(model: {username: string, password: string, email: string}) {\n return this.httpClient.post(this.baseUrl + 'account/register', model).pipe(\n map((user: User) => {\n return user;\n }),\n takeUntil(this.onDestroy)\n );\n }\n\n migrateUser(model: {email: string, username: string, password: string, sendEmail: boolean}) {\n return this.httpClient.post(this.baseUrl + 'account/migrate-email', model, {responseType: 'text' as 'json'});\n }\n\n confirmMigrationEmail(model: {email: string, token: string}) {\n return this.httpClient.post(this.baseUrl + 'account/confirm-migration-email', model);\n }\n\n resendConfirmationEmail(userId: number) {\n return this.httpClient.post(this.baseUrl + 'account/resend-confirmation-email?userId=' + userId, {}, {responseType: 'text' as 'json'});\n }\n\n inviteUser(model: {email: string, roles: Array, libraries: Array}) {\n return this.httpClient.post(this.baseUrl + 'account/invite', model);\n }\n\n confirmEmail(model: {email: string, username: string, password: string, token: string}) {\n return this.httpClient.post(this.baseUrl + 'account/confirm-email', model);\n }\n\n getDecodedToken(token: string) {\n return JSON.parse(atob(token.split('.')[1]));\n }\n\n requestResetPasswordEmail(email: string) {\n return this.httpClient.post(this.baseUrl + 'account/forgot-password?email=' + encodeURIComponent(email), {}, {responseType: 'text' as 'json'});\n }\n\n confirmResetPasswordEmail(model: {email: string, token: string, password: string}) {\n return this.httpClient.post(this.baseUrl + 'account/confirm-password-reset', model);\n }\n\n resetPassword(username: string, password: string) {\n return this.httpClient.post(this.baseUrl + 'account/reset-password', {username, password}, {responseType: 'json' as 'text'});\n }\n\n update(model: {email: string, roles: Array, libraries: Array, userId: number}) {\n return this.httpClient.post(this.baseUrl + 'account/update', model);\n }\n\n /**\n * This will get latest preferences for a user and cache them into user store\n * @returns \n */\n getPreferences() {\n return this.httpClient.get(this.baseUrl + 'users/get-preferences').pipe(map(pref => {\n if (this.currentUser !== undefined || this.currentUser != null) {\n this.currentUser.preferences = pref;\n this.setCurrentUser(this.currentUser);\n }\n return pref;\n }), takeUntil(this.onDestroy));\n }\n\n updatePreferences(userPreferences: Preferences) {\n return this.httpClient.post(this.baseUrl + 'users/update-preferences', userPreferences).pipe(map(settings => {\n if (this.currentUser !== undefined || this.currentUser != null) {\n this.currentUser.preferences = settings;\n this.setCurrentUser(this.currentUser);\n }\n return settings;\n }), takeUntil(this.onDestroy));\n }\n\n getUserFromLocalStorage(): User | undefined {\n\n const userString = localStorage.getItem(this.userKey);\n \n if (userString) {\n return JSON.parse(userString)\n };\n\n return undefined;\n }\n\n resetApiKey() {\n return this.httpClient.post(this.baseUrl + 'account/reset-api-key', {}, {responseType: 'text' as 'json'}).pipe(map(key => {\n const user = this.getUserFromLocalStorage();\n if (user) {\n user.apiKey = key;\n\n localStorage.setItem(this.userKey, JSON.stringify(user));\n \n this.currentUserSource.next(user);\n this.currentUser = user;\n }\n return key;\n }));\n }\n\n private refreshToken() {\n if (this.currentUser === null || this.currentUser === undefined) return of();\n\n return this.httpClient.post<{token: string, refreshToken: string}>(this.baseUrl + 'account/refresh-token', {token: this.currentUser.token, refreshToken: this.currentUser.refreshToken}).pipe(map(user => {\n if (this.currentUser) {\n this.currentUser.token = user.token;\n this.currentUser.refreshToken = user.refreshToken;\n }\n \n this.currentUserSource.next(this.currentUser);\n this.startRefreshTokenTimer();\n return user;\n }));\n }\n\n private startRefreshTokenTimer() {\n if (this.currentUser === null || this.currentUser === undefined) return;\n\n if (this.refreshTokenTimeout !== undefined) {\n this.stopRefreshTokenTimer();\n }\n\n const jwtToken = JSON.parse(atob(this.currentUser.token.split('.')[1]));\n // set a timeout to refresh the token a minute before it expires\n const expires = new Date(jwtToken.exp * 1000);\n const timeout = expires.getTime() - Date.now() - (60 * 1000);\n this.refreshTokenTimeout = setTimeout(() => this.refreshToken().subscribe(() => {}), timeout);\n }\n\n private stopRefreshTokenTimer() {\n if (this.refreshTokenTimeout !== undefined) {\n clearTimeout(this.refreshTokenTimeout);\n }\n }\n\n\n\n}\n","import { Injectable } from '@angular/core';\nimport { Chapter } from '../_models/chapter';\nimport { CollectionTag } from '../_models/collection-tag';\nimport { Library } from '../_models/library';\nimport { MangaFormat } from '../_models/manga-format';\nimport { ReadingList } from '../_models/reading-list';\nimport { Series } from '../_models/series';\nimport { Volume } from '../_models/volume';\nimport { AccountService } from './account.service';\n\nexport enum Action {\n MarkAsRead = 0,\n MarkAsUnread = 1,\n ScanLibrary = 2,\n Delete = 3,\n Edit = 4,\n Info = 5,\n RefreshMetadata = 6,\n Download = 7,\n /**\n * @deprecated This is no longer supported. Use the dedicated page instead\n */\n Bookmarks = 8,\n IncognitoRead = 9,\n AddToReadingList = 10,\n AddToCollection = 11,\n /**\n * Essentially a download, but handled differently. Needed so card bubbles it up for handling\n */\n DownloadBookmark = 12,\n /**\n * Open Series detail page for said series\n */\n ViewSeries = 13\n}\n\nexport interface ActionItem {\n title: string;\n action: Action;\n callback: (action: Action, data: T) => void;\n requiresAdmin: boolean;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ActionFactoryService {\n\n libraryActions: Array> = [];\n\n seriesActions: Array> = [];\n\n volumeActions: Array> = [];\n\n chapterActions: Array> = [];\n\n collectionTagActions: Array> = [];\n\n readingListActions: Array> = [];\n\n bookmarkActions: Array> = [];\n\n isAdmin = false;\n hasDownloadRole = false;\n\n constructor(private accountService: AccountService) {\n this.accountService.currentUser$.subscribe(user => {\n if (user) {\n this.isAdmin = this.accountService.hasAdminRole(user);\n this.hasDownloadRole = this.accountService.hasDownloadRole(user);\n } else {\n this._resetActions();\n return; // If user is logged out, we don't need to do anything\n }\n\n this._resetActions();\n\n if (this.isAdmin) {\n this.collectionTagActions.push({\n action: Action.Edit,\n title: 'Edit',\n callback: this.dummyCallback,\n requiresAdmin: true\n });\n\n this.seriesActions.push({\n action: Action.ScanLibrary,\n title: 'Scan Series',\n callback: this.dummyCallback,\n requiresAdmin: true\n });\n\n this.seriesActions.push({\n action: Action.RefreshMetadata,\n title: 'Refresh Covers',\n callback: this.dummyCallback,\n requiresAdmin: true\n });\n\n this.seriesActions.push({\n action: Action.Delete,\n title: 'Delete',\n callback: this.dummyCallback,\n requiresAdmin: true\n });\n\n this.seriesActions.push({\n action: Action.AddToCollection,\n title: 'Add to Collection',\n callback: this.dummyCallback,\n requiresAdmin: true\n });\n\n this.seriesActions.push({\n action: Action.Edit,\n title: 'Edit',\n callback: this.dummyCallback,\n requiresAdmin: true\n });\n\n this.libraryActions.push({\n action: Action.ScanLibrary,\n title: 'Scan Library',\n callback: this.dummyCallback,\n requiresAdmin: true\n });\n\n this.libraryActions.push({\n action: Action.RefreshMetadata,\n title: 'Refresh Covers',\n callback: this.dummyCallback,\n requiresAdmin: true\n });\n \n this.chapterActions.push({\n action: Action.Edit,\n title: 'Details',\n callback: this.dummyCallback,\n requiresAdmin: false\n });\n }\n\n if (this.hasDownloadRole || this.isAdmin) {\n this.volumeActions.push({\n action: Action.Download,\n title: 'Download',\n callback: this.dummyCallback,\n requiresAdmin: false\n });\n\n this.chapterActions.push({\n action: Action.Download,\n title: 'Download',\n callback: this.dummyCallback,\n requiresAdmin: false\n });\n }\n });\n }\n\n getLibraryActions(callback: (action: Action, library: Library) => void) {\n const actions = this.libraryActions.map(a => {return {...a}});\n actions.forEach(action => action.callback = callback);\n return actions;\n }\n\n getSeriesActions(callback: (action: Action, series: Series) => void) {\n const actions = this.seriesActions.map(a => {return {...a}});\n actions.forEach(action => action.callback = callback);\n return actions;\n }\n\n getVolumeActions(callback: (action: Action, volume: Volume) => void) {\n const actions = this.volumeActions.map(a => {return {...a}});\n actions.forEach(action => action.callback = callback);\n return actions;\n }\n\n getChapterActions(callback: (action: Action, chapter: Chapter) => void) {\n const actions = this.chapterActions.map(a => {return {...a}});\n actions.forEach(action => action.callback = callback);\n return actions;\n }\n\n getCollectionTagActions(callback: (action: Action, collectionTag: CollectionTag) => void) {\n const actions = this.collectionTagActions.map(a => {return {...a}});\n actions.forEach(action => action.callback = callback);\n return actions;\n }\n\n getReadingListActions(callback: (action: Action, readingList: ReadingList) => void) {\n const actions = this.readingListActions.map(a => {return {...a}});\n actions.forEach(action => action.callback = callback);\n return actions;\n }\n\n getBookmarkActions(callback: (action: Action, series: Series) => void) {\n const actions = this.bookmarkActions.map(a => {return {...a}});\n actions.forEach(action => action.callback = callback);\n return actions;\n }\n\n filterBookmarksForFormat(action: ActionItem, series: Series) {\n if (action.action === Action.Bookmarks && series?.format === MangaFormat.EPUB) return false;\n return true;\n }\n\n dummyCallback(action: Action, data: any) {}\n\n _resetActions() {\n this.libraryActions = [];\n\n this.collectionTagActions = [];\n \n this.seriesActions = [\n {\n action: Action.MarkAsRead,\n title: 'Mark as Read',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.MarkAsUnread,\n title: 'Mark as Unread',\n callback: this.dummyCallback,\n requiresAdmin: false\n }, \n {\n action: Action.AddToReadingList,\n title: 'Add to Reading List',\n callback: this.dummyCallback,\n requiresAdmin: false\n }\n ];\n\n this.volumeActions = [\n {\n action: Action.MarkAsRead,\n title: 'Mark as Read',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.MarkAsUnread,\n title: 'Mark as Unread',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.AddToReadingList,\n title: 'Add to Reading List',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.IncognitoRead,\n title: 'Read Incognito',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.Edit,\n title: 'Details',\n callback: this.dummyCallback,\n requiresAdmin: false\n }\n ];\n\n this.chapterActions = [\n {\n action: Action.MarkAsRead,\n title: 'Mark as Read',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.MarkAsUnread,\n title: 'Mark as Unread',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.IncognitoRead,\n title: 'Read Incognito',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.AddToReadingList,\n title: 'Add to Reading List',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n ];\n\n this.readingListActions = [\n {\n action: Action.Edit,\n title: 'Edit',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.Delete,\n title: 'Delete',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n ];\n\n this.bookmarkActions = [\n {\n action: Action.ViewSeries,\n title: 'View Series',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.DownloadBookmark,\n title: 'Download',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n {\n action: Action.Delete,\n title: 'Clear',\n callback: this.dummyCallback,\n requiresAdmin: false\n },\n ]\n }\n}\n","\n
\n

Add to Collection

\n \n
\n
\n
\n
= 5\">\n \n
\n \n \n
\n
\n
    \n
  • \n {{collectionTag.title}} \n
  • \n
  • No collections created yet
  • \n
  • \n
    \n Loading...\n
    \n
  • \n
\n
\n
\n
\n
\n
\n \n \n
\n
\n \n
\n
\n
\n
\n
\n\n\n","import { Component, ElementRef, Input, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { FormGroup, FormControl } from '@angular/forms';\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\nimport { ToastrService } from 'ngx-toastr';\nimport { CollectionTag } from 'src/app/_models/collection-tag';\nimport { ReadingList } from 'src/app/_models/reading-list';\nimport { CollectionTagService } from 'src/app/_services/collection-tag.service';\n\n@Component({\n selector: 'app-bulk-add-to-collection',\n templateUrl: './bulk-add-to-collection.component.html',\n encapsulation: ViewEncapsulation.None, // This is needed as per the bootstrap modal documentation to get styles to work.\n styleUrls: ['./bulk-add-to-collection.component.scss']\n})\nexport class BulkAddToCollectionComponent implements OnInit {\n\n @Input() title!: string;\n /**\n * Series Ids to add to Collection Tag\n */\n @Input() seriesIds: Array = [];\n\n /**\n * All existing collections sorted by recent use date\n */\n lists: Array = [];\n loading: boolean = false;\n listForm: FormGroup = new FormGroup({});\n\n @ViewChild('title') inputElem!: ElementRef;\n\n\n constructor(private modal: NgbActiveModal, private collectionService: CollectionTagService, private toastr: ToastrService) { }\n\n ngOnInit(): void {\n\n this.listForm.addControl('title', new FormControl(this.title, []));\n this.listForm.addControl('filterQuery', new FormControl('', []));\n \n this.loading = true;\n this.collectionService.allTags().subscribe(tags => {\n this.lists = tags;\n this.loading = false;\n });\n }\n\n ngAfterViewInit() {\n // Shift focus to input\n if (this.inputElem) {\n this.inputElem.nativeElement.select();\n }\n }\n\n close() {\n this.modal.close();\n }\n\n create() {\n const tagName = this.listForm.value.title;\n this.collectionService.addByMultiple(0, this.seriesIds, tagName).subscribe(() => {\n this.toastr.success('Series added to ' + tagName + ' collection');\n this.modal.close();\n });\n }\n\n addToCollection(tag: CollectionTag) {\n if (this.seriesIds.length === 0) return;\n\n this.collectionService.addByMultiple(tag.id, this.seriesIds, '').subscribe(() => {\n this.toastr.success('Series added to ' + tag.title + ' collection');\n this.modal.close();\n });\n \n }\n\n filterList = (listItem: ReadingList) => {\n return listItem.title.toLowerCase().indexOf((this.listForm.value.filterQuery || '').toLowerCase()) >= 0;\n }\n\n}\n","\n
\n

Add to Reading List

\n \n
\n
\n
\n
= 5\">\n \n
\n \n \n
\n
\n
    \n
  • \n {{readingList.title}} \n
  • \n
  • No lists created yet
  • \n
  • \n
    \n Loading...\n
    \n
  • \n
\n
\n
\n
\n
\n
\n \n \n
\n
\n \n
\n
\n
\n
\n
\n\n\n","import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';\nimport { FormControl, FormGroup } from '@angular/forms';\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\nimport { ToastrService } from 'ngx-toastr';\nimport { ReadingList } from 'src/app/_models/reading-list';\nimport { ReadingListService } from 'src/app/_services/reading-list.service';\n\nexport enum ADD_FLOW {\n Series = 0,\n Volume = 1,\n Chapter = 2,\n Multiple = 3,\n Multiple_Series\n}\n\n@Component({\n selector: 'app-add-to-list-modal',\n templateUrl: './add-to-list-modal.component.html',\n styleUrls: ['./add-to-list-modal.component.scss']\n})\nexport class AddToListModalComponent implements OnInit, AfterViewInit {\n\n @Input() title!: string;\n /**\n * Only used in Series flow\n */\n @Input() seriesId?: number;\n /**\n * Only used in Volume flow\n */\n @Input() volumeId?: number;\n /**\n * Only used in Chapter flow\n */\n @Input() chapterId?: number;\n /**\n * Only used in Multiple flow\n */\n @Input() volumeIds?: Array;\n /**\n * Only used in Multiple flow\n */\n @Input() chapterIds?: Array;\n /**\n * Only used in Multiple_Series flow\n */\n @Input() seriesIds?: Array;\n\n /**\n * Determines which Input is required and which API is used to associate to the Reading List\n */\n @Input() type!: ADD_FLOW;\n\n /**\n * All existing reading lists sorted by recent use date\n */\n lists: Array = [];\n loading: boolean = false;\n listForm: FormGroup = new FormGroup({});\n\n @ViewChild('title') inputElem!: ElementRef;\n\n\n constructor(private modal: NgbActiveModal, private readingListService: ReadingListService, private toastr: ToastrService) { }\n\n ngOnInit(): void {\n\n this.listForm.addControl('title', new FormControl(this.title, []));\n this.listForm.addControl('filterQuery', new FormControl('', []));\n \n this.loading = true;\n this.readingListService.getReadingLists(false).subscribe(lists => {\n this.lists = lists.result;\n this.loading = false;\n });\n\n \n }\n\n ngAfterViewInit() {\n // Shift focus to input\n if (this.inputElem) {\n this.inputElem.nativeElement.select();\n }\n }\n\n close() {\n this.modal.close();\n }\n\n create() {\n this.readingListService.createList(this.listForm.value.title).subscribe(list => {\n this.addToList(list);\n });\n }\n\n addToList(readingList: ReadingList) {\n\n if (this.type === ADD_FLOW.Multiple_Series && this.seriesIds !== undefined) {\n this.readingListService.updateByMultipleSeries(readingList.id, this.seriesIds).subscribe(() => {\n this.toastr.success('Series added to reading list');\n this.modal.close();\n });\n }\n\n if (this.seriesId === undefined) return;\n\n if (this.type === ADD_FLOW.Series && this.seriesId !== undefined) {\n this.readingListService.updateBySeries(readingList.id, this.seriesId).subscribe(() => {\n this.toastr.success('Series added to reading list');\n this.modal.close();\n });\n } else if (this.type === ADD_FLOW.Volume && this.volumeId !== undefined) {\n this.readingListService.updateByVolume(readingList.id, this.seriesId, this.volumeId).subscribe(() => {\n this.toastr.success('Volumes added to reading list');\n this.modal.close();\n });\n } else if (this.type === ADD_FLOW.Chapter && this.chapterId !== undefined) {\n this.readingListService.updateByChapter(readingList.id, this.seriesId, this.chapterId).subscribe(() => {\n this.toastr.success('Chapter added to reading list');\n this.modal.close();\n });\n } else if (this.type === ADD_FLOW.Multiple && this.volumeIds !== undefined && this.chapterIds !== undefined) {\n this.readingListService.updateByMultiple(readingList.id, this.seriesId, this.volumeIds, this.chapterIds).subscribe(() => {\n this.toastr.success('Chapters and Volumes added to reading list');\n this.modal.close();\n });\n }\n \n }\n\n filterList = (listItem: ReadingList) => {\n return listItem.title.toLowerCase().indexOf((this.listForm.value.filterQuery || '').toLowerCase()) >= 0;\n }\n\n}\n","\n
\n

Edit {{readingList.title}} Reading List

\n \n
\n
\n
    \n
  • \n {{tabs[0].title}}\n \n

    \n This list is currently {{readingList?.promoted ? 'promoted' : 'not promoted'}} (). \n Promotion means that the list can be seen server-wide, not just for admin users. All series that are within this list will still have user-access restrictions placed on them.\n

    \n
    \n
    \n \n \n
    \n \n
    \n \n \n
    \n
    \n
    \n
  • \n
  • \n {{tabs[1].title}}\n \n

    \n Upload and choose a new cover image. Press Save to upload and override the cover.\n

    \n \n
    \n
  • \n
\n
\n
\n
\n \n \n \n
\n\n\n","import { Component, Input, OnInit } from '@angular/core';\nimport { FormGroup, FormControl, Validators } from '@angular/forms';\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\nimport { ToastrService } from 'ngx-toastr';\nimport { forkJoin } from 'rxjs';\nimport { Breakpoint, UtilityService } from 'src/app/shared/_services/utility.service';\nimport { ReadingList } from 'src/app/_models/reading-list';\nimport { ImageService } from 'src/app/_services/image.service';\nimport { ReadingListService } from 'src/app/_services/reading-list.service';\nimport { UploadService } from 'src/app/_services/upload.service';\n\n\n@Component({\n selector: 'app-edit-reading-list-modal',\n templateUrl: './edit-reading-list-modal.component.html',\n styleUrls: ['./edit-reading-list-modal.component.scss']\n})\nexport class EditReadingListModalComponent implements OnInit {\n\n @Input() readingList!: ReadingList;\n reviewGroup!: FormGroup;\n\n coverImageIndex: number = 0;\n /**\n * Url of the selected cover\n */\n selectedCover: string = '';\n coverImageLocked: boolean = false;\n\n imageUrls: Array = [];\n\n tabs = [{title: 'General', disabled: false}, {title: 'Cover', disabled: false}];\n active = this.tabs[0];\n\n get Breakpoint() {\n return Breakpoint;\n }\n\n constructor(private ngModal: NgbActiveModal, private readingListService: ReadingListService, \n public utilityService: UtilityService, private uploadService: UploadService, private toastr: ToastrService, \n private imageService: ImageService) { }\n\n ngOnInit(): void {\n this.reviewGroup = new FormGroup({\n title: new FormControl(this.readingList.title, [Validators.required]),\n summary: new FormControl(this.readingList.summary, [])\n });\n\n this.imageUrls.push(this.imageService.randomize(this.imageService.getReadingListCoverImage(this.readingList.id)));\n }\n\n close() {\n this.ngModal.dismiss(undefined);\n }\n\n save() {\n if (this.reviewGroup.value.title.trim() === '') return;\n\n\n const model = {...this.reviewGroup.value, readingListId: this.readingList.id, promoted: this.readingList.promoted, coverImageLocked: this.coverImageLocked};\n\n const apis = [this.readingListService.update(model)];\n \n if (this.selectedCover !== '') {\n apis.push(this.uploadService.updateReadingListCoverImage(this.readingList.id, this.selectedCover))\n }\n \n forkJoin(apis).subscribe(results => {\n this.readingList.title = model.title;\n this.readingList.summary = model.summary;\n this.readingList.coverImageLocked = this.coverImageLocked;\n this.ngModal.close(this.readingList);\n this.toastr.success('Reading List updated');\n });\n }\n\n togglePromotion() {\n const originalPromotion = this.readingList.promoted;\n this.readingList.promoted = !this.readingList.promoted;\n const model = {readingListId: this.readingList.id, promoted: this.readingList.promoted};\n this.readingListService.update(model).subscribe(res => {\n /* No Operation */\n }, err => {\n this.readingList.promoted = originalPromotion;\n });\n }\n\n updateSelectedIndex(index: number) {\n this.coverImageIndex = index;\n }\n\n updateSelectedImage(url: string) {\n this.selectedCover = url;\n }\n\n handleReset() {\n this.coverImageLocked = false;\n }\n\n}\n","import { Injectable, OnDestroy } from '@angular/core';\nimport { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';\nimport { ToastrService } from 'ngx-toastr';\nimport { Subject } from 'rxjs';\nimport { take } from 'rxjs/operators';\nimport { BulkAddToCollectionComponent } from '../cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component';\nimport { AddToListModalComponent, ADD_FLOW } from '../reading-list/_modals/add-to-list-modal/add-to-list-modal.component';\nimport { EditReadingListModalComponent } from '../reading-list/_modals/edit-reading-list-modal/edit-reading-list-modal.component';\nimport { ConfirmService } from '../shared/confirm.service';\nimport { Chapter } from '../_models/chapter';\nimport { Library } from '../_models/library';\nimport { ReadingList } from '../_models/reading-list';\nimport { Series } from '../_models/series';\nimport { Volume } from '../_models/volume';\nimport { LibraryService } from './library.service';\nimport { ReaderService } from './reader.service';\nimport { SeriesService } from './series.service';\n\nexport type LibraryActionCallback = (library: Partial) => void;\nexport type SeriesActionCallback = (series: Series) => void;\nexport type VolumeActionCallback = (volume: Volume) => void;\nexport type ChapterActionCallback = (chapter: Chapter) => void;\nexport type ReadingListActionCallback = (readingList: ReadingList) => void;\nexport type VoidActionCallback = () => void;\nexport type BooleanActionCallback = (result: boolean) => void;\n\n/**\n * Responsible for executing actions\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ActionService implements OnDestroy {\n\n private readonly onDestroy = new Subject();\n private bookmarkModalRef: NgbModalRef | null = null;\n private readingListModalRef: NgbModalRef | null = null;\n private collectionModalRef: NgbModalRef | null = null;\n\n constructor(private libraryService: LibraryService, private seriesService: SeriesService, \n private readerService: ReaderService, private toastr: ToastrService, private modalService: NgbModal,\n private confirmService: ConfirmService) { }\n\n ngOnDestroy() {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n /**\n * Request a file scan for a given Library\n * @param library Partial Library, must have id and name populated\n * @param callback Optional callback to perform actions after API completes\n * @returns \n */\n scanLibrary(library: Partial, callback?: LibraryActionCallback) {\n if (!library.hasOwnProperty('id') || library.id === undefined) {\n return;\n }\n this.libraryService.scan(library?.id).pipe(take(1)).subscribe((res: any) => {\n this.toastr.info('Scan queued for ' + library.name);\n if (callback) {\n callback(library);\n }\n });\n }\n\n /**\n * Request a refresh of Metadata for a given Library\n * @param library Partial Library, must have id and name populated\n * @param callback Optional callback to perform actions after API completes\n * @returns \n */\n async refreshMetadata(library: Partial, callback?: LibraryActionCallback) {\n if (!library.hasOwnProperty('id') || library.id === undefined) {\n return;\n }\n\n if (!await this.confirmService.confirm('Refresh covers will force all cover images to be recalculated. This is a heavy operation. Are you sure you don\\'t want to perform a Scan instead?')) {\n if (callback) {\n callback(library);\n }\n return;\n }\n\n this.libraryService.refreshMetadata(library?.id).pipe(take(1)).subscribe((res: any) => {\n this.toastr.info('Scan queued for ' + library.name);\n if (callback) {\n callback(library);\n }\n });\n }\n\n /**\n * Mark a series as read; updates the series pagesRead\n * @param series Series, must have id and name populated\n * @param callback Optional callback to perform actions after API completes\n */\n markSeriesAsRead(series: Series, callback?: SeriesActionCallback) {\n this.seriesService.markRead(series.id).pipe(take(1)).subscribe(res => {\n series.pagesRead = series.pages;\n this.toastr.success(series.name + ' is now read');\n if (callback) {\n callback(series);\n }\n });\n }\n\n /**\n * Mark a series as unread; updates the series pagesRead\n * @param series Series, must have id and name populated\n * @param callback Optional callback to perform actions after API completes\n */\n markSeriesAsUnread(series: Series, callback?: SeriesActionCallback) {\n this.seriesService.markUnread(series.id).pipe(take(1)).subscribe(res => {\n series.pagesRead = 0;\n this.toastr.success(series.name + ' is now unread');\n if (callback) {\n callback(series);\n }\n });\n }\n\n /**\n * Start a file scan for a Series (currently just does the library not the series directly)\n * @param series Series, must have libraryId and name populated\n * @param callback Optional callback to perform actions after API completes\n */\n scanSeries(series: Series, callback?: SeriesActionCallback) {\n this.seriesService.scan(series.libraryId, series.id).pipe(take(1)).subscribe((res: any) => {\n this.toastr.info('Scan queued for ' + series.name);\n if (callback) {\n callback(series);\n }\n });\n }\n\n /**\n * Start a metadata refresh for a Series\n * @param series Series, must have libraryId, id and name populated\n * @param callback Optional callback to perform actions after API completes\n */\n async refreshMetdata(series: Series, callback?: SeriesActionCallback) {\n if (!await this.confirmService.confirm('Refresh covers will force all cover images and metadata to be recalculated. This is a heavy operation. Are you sure you don\\'t want to perform a Scan instead?')) {\n if (callback) {\n callback(series);\n }\n return;\n }\n\n this.seriesService.refreshMetadata(series).pipe(take(1)).subscribe((res: any) => {\n this.toastr.info('Refresh covers queued for ' + series.name);\n if (callback) {\n callback(series);\n }\n });\n }\n\n /**\n * Mark all chapters and the volume as Read\n * @param seriesId Series Id\n * @param volume Volume, should have id, chapters and pagesRead populated\n * @param callback Optional callback to perform actions after API completes\n */\n markVolumeAsRead(seriesId: number, volume: Volume, callback?: VolumeActionCallback) {\n this.readerService.markVolumeRead(seriesId, volume.id).pipe(take(1)).subscribe(() => {\n volume.pagesRead = volume.pages;\n volume.chapters?.forEach(c => c.pagesRead = c.pages);\n this.toastr.success('Marked as Read');\n\n if (callback) {\n callback(volume);\n }\n });\n }\n\n /**\n * Mark all chapters and the volume as unread\n * @param seriesId Series Id\n * @param volume Volume, should have id, chapters and pagesRead populated\n * @param callback Optional callback to perform actions after API completes\n */\n markVolumeAsUnread(seriesId: number, volume: Volume, callback?: VolumeActionCallback) {\n this.readerService.markVolumeUnread(seriesId, volume.id).subscribe(() => {\n volume.pagesRead = 0;\n volume.chapters?.forEach(c => c.pagesRead = 0);\n this.toastr.success('Marked as Unread');\n if (callback) {\n callback(volume);\n }\n });\n }\n\n /**\n * Mark a chapter as read\n * @param seriesId Series Id\n * @param chapter Chapter, should have id, pages, volumeId populated\n * @param callback Optional callback to perform actions after API completes\n */\n markChapterAsRead(seriesId: number, chapter: Chapter, callback?: ChapterActionCallback) {\n this.readerService.saveProgress(seriesId, chapter.volumeId, chapter.id, chapter.pages).pipe(take(1)).subscribe(results => {\n chapter.pagesRead = chapter.pages;\n this.toastr.success('Marked as Read');\n if (callback) {\n callback(chapter);\n }\n });\n }\n\n /**\n * Mark a chapter as unread\n * @param seriesId Series Id\n * @param chapter Chapter, should have id, pages, volumeId populated\n * @param callback Optional callback to perform actions after API completes\n */\n markChapterAsUnread(seriesId: number, chapter: Chapter, callback?: ChapterActionCallback) {\n this.readerService.saveProgress(seriesId, chapter.volumeId, chapter.id, 0).pipe(take(1)).subscribe(results => {\n chapter.pagesRead = 0;\n this.toastr.success('Marked as unread');\n if (callback) {\n callback(chapter);\n }\n });\n }\n\n /**\n * Mark all chapters and the volumes as Read. All volumes and chapters must belong to a series\n * @param seriesId Series Id\n * @param volumes Volumes, should have id, chapters and pagesRead populated\n * @param chapters? Chapters, should have id\n * @param callback Optional callback to perform actions after API completes \n */\n markMultipleAsRead(seriesId: number, volumes: Array, chapters?: Array, callback?: VoidActionCallback) {\n this.readerService.markMultipleRead(seriesId, volumes.map(v => v.id), chapters?.map(c => c.id)).pipe(take(1)).subscribe(() => {\n volumes.forEach(volume => {\n volume.pagesRead = volume.pages;\n volume.chapters?.forEach(c => c.pagesRead = c.pages);\n });\n chapters?.forEach(c => c.pagesRead = c.pages);\n this.toastr.success('Marked as Read');\n\n if (callback) {\n callback();\n }\n });\n }\n\n /**\n * Mark all chapters and the volumes as Unread. All volumes must belong to a series\n * @param seriesId Series Id\n * @param volumes Volumes, should have id, chapters and pagesRead populated\n * @param callback Optional callback to perform actions after API completes \n */\n markMultipleAsUnread(seriesId: number, volumes: Array, chapters?: Array, callback?: VoidActionCallback) {\n this.readerService.markMultipleUnread(seriesId, volumes.map(v => v.id), chapters?.map(c => c.id)).pipe(take(1)).subscribe(() => {\n volumes.forEach(volume => {\n volume.pagesRead = 0;\n volume.chapters?.forEach(c => c.pagesRead = 0);\n });\n chapters?.forEach(c => c.pagesRead = 0);\n this.toastr.success('Marked as Read');\n\n if (callback) {\n callback();\n }\n });\n }\n\n /**\n * Mark all series as Read.\n * @param series Series, should have id, pagesRead populated\n * @param callback Optional callback to perform actions after API completes \n */\n markMultipleSeriesAsRead(series: Array, callback?: VoidActionCallback) {\n this.readerService.markMultipleSeriesRead(series.map(v => v.id)).pipe(take(1)).subscribe(() => {\n series.forEach(s => {\n s.pagesRead = s.pages;\n });\n this.toastr.success('Marked as Read');\n\n if (callback) {\n callback();\n }\n });\n }\n\n /**\n * Mark all series as Unread. \n * @param series Series, should have id, pagesRead populated\n * @param callback Optional callback to perform actions after API completes \n */\n markMultipleSeriesAsUnread(series: Array, callback?: VoidActionCallback) {\n this.readerService.markMultipleSeriesUnread(series.map(v => v.id)).pipe(take(1)).subscribe(() => {\n series.forEach(s => {\n s.pagesRead = s.pages;\n });\n this.toastr.success('Marked as Unread');\n\n if (callback) {\n callback();\n }\n });\n }\n\n addMultipleToReadingList(seriesId: number, volumes: Array, chapters?: Array, callback?: VoidActionCallback) {\n if (this.readingListModalRef != null) { return; }\n this.readingListModalRef = this.modalService.open(AddToListModalComponent, { scrollable: true, size: 'md' });\n this.readingListModalRef.componentInstance.seriesId = seriesId;\n this.readingListModalRef.componentInstance.volumeIds = volumes.map(v => v.id);\n this.readingListModalRef.componentInstance.chapterIds = chapters?.map(c => c.id);\n this.readingListModalRef.componentInstance.title = 'Multiple Selections';\n this.readingListModalRef.componentInstance.type = ADD_FLOW.Multiple;\n\n\n this.readingListModalRef.closed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback();\n }\n });\n this.readingListModalRef.dismissed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback();\n }\n });\n }\n\n addMultipleSeriesToReadingList(series: Array, callback?: VoidActionCallback) {\n if (this.readingListModalRef != null) { return; }\n this.readingListModalRef = this.modalService.open(AddToListModalComponent, { scrollable: true, size: 'md' });\n this.readingListModalRef.componentInstance.seriesIds = series.map(v => v.id);\n this.readingListModalRef.componentInstance.title = 'Multiple Selections';\n this.readingListModalRef.componentInstance.type = ADD_FLOW.Multiple_Series;\n\n\n this.readingListModalRef.closed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback();\n }\n });\n this.readingListModalRef.dismissed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback();\n }\n });\n }\n\n /**\n * Adds a set of series to a collection tag\n * @param series \n * @param callback \n * @returns \n */\n addMultipleSeriesToCollectionTag(series: Array, callback?: VoidActionCallback) {\n if (this.collectionModalRef != null) { return; }\n this.collectionModalRef = this.modalService.open(BulkAddToCollectionComponent, { scrollable: true, size: 'md', windowClass: 'collection' });\n this.collectionModalRef.componentInstance.seriesIds = series.map(v => v.id);\n this.collectionModalRef.componentInstance.title = 'New Collection';\n\n this.collectionModalRef.closed.pipe(take(1)).subscribe(() => {\n this.collectionModalRef = null;\n if (callback) {\n callback();\n }\n });\n this.collectionModalRef.dismissed.pipe(take(1)).subscribe(() => {\n this.collectionModalRef = null;\n if (callback) {\n callback();\n }\n });\n }\n\n addSeriesToReadingList(series: Series, callback?: SeriesActionCallback) {\n if (this.readingListModalRef != null) { return; }\n this.readingListModalRef = this.modalService.open(AddToListModalComponent, { scrollable: true, size: 'md' });\n this.readingListModalRef.componentInstance.seriesId = series.id; \n this.readingListModalRef.componentInstance.title = series.name;\n this.readingListModalRef.componentInstance.type = ADD_FLOW.Series;\n\n\n this.readingListModalRef.closed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback(series);\n }\n });\n this.readingListModalRef.dismissed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback(series);\n }\n });\n }\n\n addVolumeToReadingList(volume: Volume, seriesId: number, callback?: VolumeActionCallback) {\n if (this.readingListModalRef != null) { return; }\n this.readingListModalRef = this.modalService.open(AddToListModalComponent, { scrollable: true, size: 'md' });\n this.readingListModalRef.componentInstance.seriesId = seriesId; \n this.readingListModalRef.componentInstance.volumeId = volume.id;\n this.readingListModalRef.componentInstance.type = ADD_FLOW.Volume;\n\n\n this.readingListModalRef.closed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback(volume);\n }\n });\n this.readingListModalRef.dismissed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback(volume);\n }\n });\n }\n\n addChapterToReadingList(chapter: Chapter, seriesId: number, callback?: ChapterActionCallback) {\n if (this.readingListModalRef != null) { return; }\n this.readingListModalRef = this.modalService.open(AddToListModalComponent, { scrollable: true, size: 'md' });\n this.readingListModalRef.componentInstance.seriesId = seriesId; \n this.readingListModalRef.componentInstance.chapterId = chapter.id;\n this.readingListModalRef.componentInstance.type = ADD_FLOW.Chapter;\n\n\n this.readingListModalRef.closed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback(chapter);\n }\n });\n this.readingListModalRef.dismissed.pipe(take(1)).subscribe(() => {\n this.readingListModalRef = null;\n if (callback) {\n callback(chapter);\n }\n });\n }\n\n editReadingList(readingList: ReadingList, callback?: ReadingListActionCallback) {\n const readingListModalRef = this.modalService.open(EditReadingListModalComponent, { scrollable: true, size: 'lg' });\n readingListModalRef.componentInstance.readingList = readingList; \n readingListModalRef.closed.pipe(take(1)).subscribe((list) => {\n if (callback && list !== undefined) {\n callback(readingList);\n }\n });\n readingListModalRef.dismissed.pipe(take(1)).subscribe((list) => {\n if (callback && list !== undefined) {\n callback(readingList);\n }\n });\n }\n\n /**\n * Mark all chapters and the volumes as Read. All volumes and chapters must belong to a series\n * @param seriesId Series Id\n * @param volumes Volumes, should have id, chapters and pagesRead populated\n * @param chapters? Chapters, should have id\n * @param callback Optional callback to perform actions after API completes \n */\n deleteMultipleSeries(seriesIds: Array, callback?: VoidActionCallback) {\n this.seriesService.deleteMultipleSeries(seriesIds.map(s => s.id)).pipe(take(1)).subscribe(() => {\n this.toastr.success('Series deleted');\n\n if (callback) {\n callback();\n }\n });\n }\n\n async deleteSeries(series: Series, callback?: BooleanActionCallback) {\n if (!await this.confirmService.confirm('Are you sure you want to delete this series? It will not modify files on disk.')) {\n if (callback) {\n callback(false);\n }\n return;\n }\n\n this.seriesService.delete(series.id).subscribe((res: boolean) => {\n if (callback) {\n this.toastr.success('Series deleted');\n callback(res);\n }\n });\n }\n\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { map } from 'rxjs/operators';\nimport { environment } from 'src/environments/environment';\nimport { CollectionTag } from '../_models/collection-tag';\nimport { ImageService } from './image.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class CollectionTagService {\n\n baseUrl = environment.apiUrl;\n\n constructor(private httpClient: HttpClient, private imageService: ImageService) { }\n\n allTags() {\n return this.httpClient.get(this.baseUrl + 'collection/').pipe(map(tags => {\n tags.forEach(s => s.coverImage = this.imageService.randomize(this.imageService.getCollectionCoverImage(s.id)));\n return tags;\n }));\n }\n\n search(query: string) {\n return this.httpClient.get(this.baseUrl + 'collection/search?queryString=' + encodeURIComponent(query)).pipe(map(tags => {\n tags.forEach(s => s.coverImage = this.imageService.randomize(this.imageService.getCollectionCoverImage(s.id)));\n return tags;\n }));\n }\n\n updateTag(tag: CollectionTag) {\n return this.httpClient.post(this.baseUrl + 'collection/update', tag, {responseType: 'text' as 'json'});\n }\n\n updateSeriesForTag(tag: CollectionTag, seriesIdsToRemove: Array) {\n return this.httpClient.post(this.baseUrl + 'collection/update-series', {tag, seriesIdsToRemove}, {responseType: 'text' as 'json'});\n }\n\n addByMultiple(tagId: number, seriesIds: Array, tagTitle: string = '') {\n return this.httpClient.post(this.baseUrl + 'collection/update-for-series', {collectionTagId: tagId, collectionTagTitle: tagTitle, seriesIds}, {responseType: 'text' as 'json'});\n }\n}\n","import { Injectable, OnDestroy } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { environment } from 'src/environments/environment';\nimport { ThemeService } from './theme.service';\nimport { RecentlyAddedItem } from '../_models/recently-added-item';\nimport { AccountService } from './account.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ImageService implements OnDestroy {\n\n baseUrl = environment.apiUrl;\n apiKey: string = '';\n public placeholderImage = 'assets/images/image-placeholder-min.png';\n public errorImage = 'assets/images/error-placeholder2-min.png';\n public resetCoverImage = 'assets/images/image-reset-cover-min.png';\n\n private onDestroy: Subject = new Subject();\n\n constructor(private accountService: AccountService, private themeService: ThemeService) {\n this.themeService.currentTheme$.pipe(takeUntil(this.onDestroy)).subscribe(theme => {\n if (this.themeService.isDarkTheme()) {\n this.placeholderImage = 'assets/images/image-placeholder.dark-min.png';\n this.errorImage = 'assets/images/error-placeholder2.dark-min.png';\n } else {\n this.placeholderImage = 'assets/images/image-placeholder-min.png';\n this.errorImage = 'assets/images/error-placeholder2-min.png';\n }\n });\n\n this.accountService.currentUser$.pipe(takeUntil(this.onDestroy)).subscribe(user => {\n if (user) {\n this.apiKey = user.apiKey;\n }\n });\n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n getRecentlyAddedItem(item: RecentlyAddedItem) {\n if (item.chapterId === 0) {\n return this.getVolumeCoverImage(item.volumeId);\n }\n return this.getChapterCoverImage(item.chapterId);\n }\n\n /**\n * Returns the entity type from a cover image url. Undefied if not applicable\n * @param url \n * @returns \n */\n getEntityTypeFromUrl(url: string) {\n if (url.indexOf('?') < 0) return undefined;\n const part = url.split('?')[1];\n const equalIndex = part.indexOf('=');\n return part.substring(0, equalIndex).replace('Id', '');\n }\n\n getVolumeCoverImage(volumeId: number) {\n return this.baseUrl + 'image/volume-cover?volumeId=' + volumeId;\n }\n\n getSeriesCoverImage(seriesId: number) {\n return this.baseUrl + 'image/series-cover?seriesId=' + seriesId;\n }\n\n getCollectionCoverImage(collectionTagId: number) {\n return this.baseUrl + 'image/collection-cover?collectionTagId=' + collectionTagId;\n }\n\n getReadingListCoverImage(readingListId: number) {\n return this.baseUrl + 'image/readinglist-cover?readingListId=' + readingListId;\n }\n\n getChapterCoverImage(chapterId: number) {\n return this.baseUrl + 'image/chapter-cover?chapterId=' + chapterId;\n }\n\n getBookmarkedImage(chapterId: number, pageNum: number) {\n return this.baseUrl + 'image/bookmark?chapterId=' + chapterId + '&pageNum=' + pageNum + '&apiKey=' + encodeURIComponent(this.apiKey);\n }\n\n getCoverUploadImage(filename: string) {\n return this.baseUrl + 'image/cover-upload?filename=' + encodeURIComponent(filename);\n }\n\n updateErroredImage(event: any) {\n event.target.src = this.placeholderImage;\n }\n\n /**\n * Used to refresh an existing loaded image (lazysizes). If random already attached, will append another number onto it.\n * @param url Existing request url from ImageService only\n * @returns Url with a random parameter attached\n */\n randomize(url: string) {\n const r = Math.round(Math.random() * 100 + 1);\n if (url.indexOf('&random') >= 0) {\n return url + 1;\n }\n return url + '&random=' + r;\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { of } from 'rxjs';\nimport { map, take } from 'rxjs/operators';\nimport { environment } from 'src/environments/environment';\nimport { Library, LibraryType } from '../_models/library';\nimport { SearchResultGroup } from '../_models/search/search-result-group';\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class LibraryService {\n\n baseUrl = environment.apiUrl;\n\n private libraryNames: {[key:number]: string} | undefined = undefined;\n private libraryTypes: {[key: number]: LibraryType} | undefined = undefined;\n\n constructor(private httpClient: HttpClient) {}\n\n getLibraryNames() {\n if (this.libraryNames != undefined) {\n return of(this.libraryNames);\n }\n return this.httpClient.get(this.baseUrl + 'library').pipe(map(l => {\n this.libraryNames = {};\n l.forEach(lib => {\n if (this.libraryNames !== undefined) {\n this.libraryNames[lib.id] = lib.name;\n } \n });\n return this.libraryNames;\n }));\n }\n\n getLibraryName(libraryId: number) {\n if (this.libraryNames != undefined && this.libraryNames.hasOwnProperty(libraryId)) {\n return of(this.libraryNames[libraryId]);\n }\n return this.httpClient.get(this.baseUrl + 'library').pipe(map(l => {\n this.libraryNames = {};\n l.forEach(lib => {\n if (this.libraryNames !== undefined) {\n this.libraryNames[lib.id] = lib.name;\n } \n });\n return this.libraryNames[libraryId];\n }));\n }\n\n listDirectories(rootPath: string) {\n let query = '';\n if (rootPath !== undefined && rootPath.length > 0) {\n query = '?path=' + encodeURIComponent(rootPath);\n }\n\n return this.httpClient.get(this.baseUrl + 'library/list' + query);\n }\n\n getLibraries() {\n return this.httpClient.get(this.baseUrl + 'library');\n }\n\n getLibrariesForMember() {\n return this.httpClient.get(this.baseUrl + 'library/libraries');\n }\n\n updateLibrariesForMember(username: string, selectedLibraries: Library[]) {\n return this.httpClient.post(this.baseUrl + 'library/grant-access', {username, selectedLibraries});\n }\n\n scan(libraryId: number) {\n return this.httpClient.post(this.baseUrl + 'library/scan?libraryId=' + libraryId, {});\n }\n\n refreshMetadata(libraryId: number) {\n return this.httpClient.post(this.baseUrl + 'library/refresh-metadata?libraryId=' + libraryId, {});\n }\n\n create(model: {name: string, type: number, folders: string[]}) {\n return this.httpClient.post(this.baseUrl + 'library/create', model);\n }\n\n delete(libraryId: number) {\n return this.httpClient.delete(this.baseUrl + 'library/delete?libraryId=' + libraryId, {});\n }\n\n update(model: {name: string, folders: string[], id: number}) {\n return this.httpClient.post(this.baseUrl + 'library/update', model);\n }\n\n getLibraryType(libraryId: number) {\n if (this.libraryTypes != undefined && this.libraryTypes.hasOwnProperty(libraryId)) {\n return of(this.libraryTypes[libraryId]);\n }\n return this.httpClient.get(this.baseUrl + 'library/type?libraryId=' + libraryId).pipe(map(l => {\n if (this.libraryTypes === undefined) {\n this.libraryTypes = {};\n }\n\n this.libraryTypes[libraryId] = l;\n return this.libraryTypes[libraryId];\n }));\n }\n\n search(term: string) {\n if (term === '') {\n return of(new SearchResultGroup());\n }\n return this.httpClient.get(this.baseUrl + 'library/search?queryString=' + encodeURIComponent(term));\n }\n\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { environment } from 'src/environments/environment';\nimport { Member } from '../_models/member';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class MemberService {\n\n baseUrl = environment.apiUrl;\n\n constructor(private httpClient: HttpClient) { }\n\n getMembers() {\n return this.httpClient.get(this.baseUrl + 'users');\n }\n\n getMemberNames() {\n return this.httpClient.get(this.baseUrl + 'users/names');\n }\n\n adminExists() {\n return this.httpClient.get(this.baseUrl + 'admin/exists');\n }\n\n deleteMember(username: string) {\n return this.httpClient.delete(this.baseUrl + 'users/delete-user?username=' + encodeURIComponent(username));\n }\n\n hasLibraryAccess(libraryId: number) {\n return this.httpClient.get(this.baseUrl + 'users/has-library-access?libraryId=' + libraryId);\n }\n\n hasReadingProgress(librayId: number) {\n return this.httpClient.get(this.baseUrl + 'users/has-reading-progress?libraryId=' + librayId);\n }\n\n\n getPendingInvites() {\n return this.httpClient.get>(this.baseUrl + 'users/pending');\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { HubConnection, HubConnectionBuilder } from '@microsoft/signalr';\nimport { ToastrService } from 'ngx-toastr';\nimport { BehaviorSubject, ReplaySubject } from 'rxjs';\nimport { environment } from 'src/environments/environment';\nimport { LibraryModifiedEvent } from '../_models/events/library-modified-event';\nimport { NotificationProgressEvent } from '../_models/events/notification-progress-event';\nimport { ThemeProgressEvent } from '../_models/events/theme-progress-event';\nimport { User } from '../_models/user';\n\nexport enum EVENTS {\n UpdateAvailable = 'UpdateAvailable',\n ScanSeries = 'ScanSeries',\n SeriesAdded = 'SeriesAdded',\n SeriesRemoved = 'SeriesRemoved',\n ScanLibraryProgress = 'ScanLibraryProgress',\n OnlineUsers = 'OnlineUsers',\n SeriesAddedToCollection = 'SeriesAddedToCollection',\n /**\n * A generic error that occurs during operations on the server\n */\n Error = 'Error',\n BackupDatabaseProgress = 'BackupDatabaseProgress',\n /**\n * A subtype of NotificationProgress that represents maintenance cleanup on server-owned resources\n */\n CleanupProgress = 'CleanupProgress',\n /**\n * A subtype of NotificationProgress that represnts a user downloading a file or group of files\n */\n DownloadProgress = 'DownloadProgress',\n /**\n * A generic progress event \n */\n NotificationProgress = 'NotificationProgress',\n /**\n * A subtype of NotificationProgress that represents the underlying file being processed during a scan\n */\n FileScanProgress = 'FileScanProgress',\n /**\n * A custom user site theme is added or removed during a scan\n */\n SiteThemeProgress = 'SiteThemeProgress',\n /**\n * A cover is updated\n */\n CoverUpdate = 'CoverUpdate',\n /**\n * A subtype of NotificationProgress that represents a file being processed for cover image extraction\n */\n CoverUpdateProgress = 'CoverUpdateProgress',\n /**\n * A library is created or removed from the instance\n */\n LibraryModified = 'LibraryModified',\n /**\n * A user updates an entities read progress\n */\n UserProgressUpdate = 'UserProgressUpdate',\n}\n\nexport interface Message {\n event: EVENTS;\n payload: T;\n}\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class MessageHubService {\n hubUrl = environment.hubUrl;\n private hubConnection!: HubConnection;\n\n private messagesSource = new ReplaySubject>(1);\n private onlineUsersSource = new BehaviorSubject([]);\n\n /**\n * Any events that come from the backend\n */\n public messages$ = this.messagesSource.asObservable();\n /**\n * Users that are online\n */\n public onlineUsers$ = this.onlineUsersSource.asObservable();\n\n\n isAdmin: boolean = false;\n\n constructor(private toastr: ToastrService, private router: Router) {\n\n }\n\n /**\n * Tests that an event is of the type passed\n * @param event \n * @param eventType \n * @returns \n */\n public isEventType(event: Message, eventType: EVENTS) {\n if (event.event == EVENTS.NotificationProgress) {\n const notification = event.payload as NotificationProgressEvent;\n return notification.eventType.toLowerCase() == eventType.toLowerCase();\n } \n return event.event === eventType;\n }\n\n createHubConnection(user: User, isAdmin: boolean) {\n this.isAdmin = isAdmin;\n\n this.hubConnection = new HubConnectionBuilder()\n .withUrl(this.hubUrl + 'messages', {\n accessTokenFactory: () => user.token\n })\n .withAutomaticReconnect()\n .build();\n\n this.hubConnection\n .start()\n .catch(err => console.error(err));\n\n this.hubConnection.on(EVENTS.OnlineUsers, (usernames: string[]) => {\n this.onlineUsersSource.next(usernames);\n });\n\n\n this.hubConnection.on(EVENTS.ScanSeries, resp => {\n this.messagesSource.next({\n event: EVENTS.ScanSeries,\n payload: resp.body\n });\n });\n\n this.hubConnection.on(EVENTS.ScanLibraryProgress, resp => {\n this.messagesSource.next({\n event: EVENTS.ScanLibraryProgress,\n payload: resp.body\n });\n });\n\n this.hubConnection.on(EVENTS.LibraryModified, resp => {\n this.messagesSource.next({\n event: EVENTS.LibraryModified,\n payload: resp.body as LibraryModifiedEvent\n });\n });\n\n\n this.hubConnection.on(EVENTS.NotificationProgress, (resp: NotificationProgressEvent) => {\n this.messagesSource.next({\n event: EVENTS.NotificationProgress,\n payload: resp\n });\n });\n\n this.hubConnection.on(EVENTS.SiteThemeProgress, resp => {\n this.messagesSource.next({\n event: EVENTS.SiteThemeProgress,\n payload: resp.body as ThemeProgressEvent\n });\n });\n\n this.hubConnection.on(EVENTS.SeriesAddedToCollection, resp => {\n this.messagesSource.next({\n event: EVENTS.SeriesAddedToCollection,\n payload: resp.body\n });\n });\n\n this.hubConnection.on(EVENTS.UserProgressUpdate, resp => {\n this.messagesSource.next({\n event: EVENTS.UserProgressUpdate,\n payload: resp.body\n });\n });\n\n this.hubConnection.on(EVENTS.Error, resp => {\n this.messagesSource.next({\n event: EVENTS.Error,\n payload: resp.body\n });\n });\n\n this.hubConnection.on(EVENTS.SeriesAdded, resp => {\n this.messagesSource.next({\n event: EVENTS.SeriesAdded,\n payload: resp.body\n });\n });\n\n this.hubConnection.on(EVENTS.SeriesRemoved, resp => {\n this.messagesSource.next({\n event: EVENTS.SeriesRemoved,\n payload: resp.body\n });\n });\n\n this.hubConnection.on(EVENTS.CoverUpdate, resp => {\n this.messagesSource.next({\n event: EVENTS.CoverUpdate,\n payload: resp.body\n });\n });\n\n this.hubConnection.on(EVENTS.UpdateAvailable, resp => {\n this.messagesSource.next({\n event: EVENTS.UpdateAvailable,\n payload: resp.body\n });\n });\n }\n\n stopHubConnection() {\n if (this.hubConnection) {\n this.hubConnection.stop().catch(err => console.error(err));\n }\n }\n\n sendMessage(methodName: string, body?: any) {\n return this.hubConnection.invoke(methodName, body);\n }\n\n}\n","import { DOCUMENT } from '@angular/common';\nimport { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core';\nimport { ReplaySubject, take } from 'rxjs';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class NavService {\n public localStorageSideNavKey = 'kavita--sidenav--expanded';\n\n private navbarVisibleSource = new ReplaySubject(1);\n /**\n * If the top Nav bar is rendered or not\n */\n navbarVisible$ = this.navbarVisibleSource.asObservable();\n\n private sideNavCollapseSource = new ReplaySubject(1);\n /**\n * If the Side Nav is in a collapsed state or not.\n */\n sideNavCollapsed$ = this.sideNavCollapseSource.asObservable();\n\n private sideNavVisibilitySource = new ReplaySubject(1);\n /**\n * If the side nav is rendered or not into the DOM.\n */\n sideNavVisibility$ = this.sideNavVisibilitySource.asObservable();\n\n private renderer: Renderer2;\n\n constructor(@Inject(DOCUMENT) private document: Document, rendererFactory: RendererFactory2) {\n this.renderer = rendererFactory.createRenderer(null, null);\n this.showNavBar();\n const sideNavState = (localStorage.getItem(this.localStorageSideNavKey) === 'true') || false;\n this.sideNavCollapseSource.next(sideNavState);\n this.showSideNav();\n }\n \n /**\n * Shows the top nav bar. This should be visible on all pages except the reader.\n */\n showNavBar() {\n this.renderer.setStyle(this.document.querySelector('body'), 'margin-top', '56px');\n this.renderer.setStyle(this.document.querySelector('body'), 'height', 'calc(var(--vh)*100 - 56px)');\n this.renderer.setStyle(this.document.querySelector('html'), 'height', 'calc(var(--vh)*100 - 56px)');\n this.navbarVisibleSource.next(true);\n }\n\n /**\n * Hides the top nav bar. \n */\n hideNavBar() {\n this.renderer.setStyle(this.document.querySelector('body'), 'margin-top', '0px');\n this.renderer.removeStyle(this.document.querySelector('body'), 'height');\n this.renderer.removeStyle(this.document.querySelector('html'), 'height');\n this.navbarVisibleSource.next(false);\n }\n\n /**\n * Shows the side nav. When being visible, the side nav will automatically return to previous collapsed state.\n */\n showSideNav() {\n this.sideNavVisibilitySource.next(true);\n }\n\n /**\n * Hides the side nav. This is useful for the readers and login page.\n */\n hideSideNav() {\n this.sideNavVisibilitySource.next(false);\n }\n\n toggleSideNav() {\n this.sideNavCollapseSource.pipe(take(1)).subscribe(val => {\n if (val === undefined) val = false;\n const newVal = !(val || false);\n this.sideNavCollapseSource.next(newVal);\n localStorage.setItem(this.localStorageSideNavKey, newVal + '');\n });\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { environment } from 'src/environments/environment';\nimport { ChapterInfo } from '../manga-reader/_models/chapter-info';\nimport { UtilityService } from '../shared/_services/utility.service';\nimport { Chapter } from '../_models/chapter';\nimport { BookmarkInfo } from '../_models/manga-reader/bookmark-info';\nimport { PageBookmark } from '../_models/page-bookmark';\nimport { ProgressBookmark } from '../_models/progress-bookmark';\nimport { Volume } from '../_models/volume';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ReaderService {\n\n baseUrl = environment.apiUrl;\n\n // Override background color for reader and restore it onDestroy\n private originalBodyColor!: string;\n\n constructor(private httpClient: HttpClient, private utilityService: UtilityService) { }\n\n bookmark(seriesId: number, volumeId: number, chapterId: number, page: number) {\n return this.httpClient.post(this.baseUrl + 'reader/bookmark', {seriesId, volumeId, chapterId, page});\n }\n\n unbookmark(seriesId: number, volumeId: number, chapterId: number, page: number) {\n return this.httpClient.post(this.baseUrl + 'reader/unbookmark', {seriesId, volumeId, chapterId, page});\n }\n\n getAllBookmarks() {\n return this.httpClient.get(this.baseUrl + 'reader/get-all-bookmarks');\n }\n\n getBookmarks(chapterId: number) {\n return this.httpClient.get(this.baseUrl + 'reader/get-bookmarks?chapterId=' + chapterId);\n }\n\n getBookmarksForVolume(volumeId: number) {\n return this.httpClient.get(this.baseUrl + 'reader/get-volume-bookmarks?volumeId=' + volumeId);\n }\n\n getBookmarksForSeries(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'reader/get-series-bookmarks?seriesId=' + seriesId);\n }\n\n clearBookmarks(seriesId: number) {\n return this.httpClient.post(this.baseUrl + 'reader/remove-bookmarks', {seriesId});\n }\n\n /**\n * Used exclusively for reading multiple bookmarks from a series\n * @param seriesId \n */\n getBookmarkInfo(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'reader/bookmark-info?seriesId=' + seriesId);\n }\n\n getProgress(chapterId: number) {\n return this.httpClient.get(this.baseUrl + 'reader/get-progress?chapterId=' + chapterId);\n }\n\n getPageUrl(chapterId: number, page: number) {\n return this.baseUrl + 'reader/image?chapterId=' + chapterId + '&page=' + page;\n }\n\n getBookmarkPageUrl(seriesId: number, apiKey: string, page: number) {\n return this.baseUrl + 'reader/bookmark-image?seriesId=' + seriesId + '&page=' + page + '&apiKey=' + encodeURIComponent(apiKey);\n }\n\n getChapterInfo(chapterId: number) {\n return this.httpClient.get(this.baseUrl + 'reader/chapter-info?chapterId=' + chapterId);\n }\n\n saveProgress(seriesId: number, volumeId: number, chapterId: number, page: number, bookScrollId: string | null = null) {\n return this.httpClient.post(this.baseUrl + 'reader/progress', {seriesId, volumeId, chapterId, pageNum: page, bookScrollId});\n }\n\n markVolumeRead(seriesId: number, volumeId: number) {\n return this.httpClient.post(this.baseUrl + 'reader/mark-volume-read', {seriesId, volumeId});\n }\n\n markMultipleRead(seriesId: number, volumeIds: Array, chapterIds?: Array) {\n return this.httpClient.post(this.baseUrl + 'reader/mark-multiple-read', {seriesId, volumeIds, chapterIds});\n }\n\n markMultipleUnread(seriesId: number, volumeIds: Array, chapterIds?: Array) {\n return this.httpClient.post(this.baseUrl + 'reader/mark-multiple-unread', {seriesId, volumeIds, chapterIds});\n }\n\n markMultipleSeriesRead(seriesIds: Array) {\n return this.httpClient.post(this.baseUrl + 'reader/mark-multiple-series-read', {seriesIds});\n }\n\n markMultipleSeriesUnread(seriesIds: Array) {\n return this.httpClient.post(this.baseUrl + 'reader/mark-multiple-series-unread', {seriesIds});\n }\n\n markVolumeUnread(seriesId: number, volumeId: number) {\n return this.httpClient.post(this.baseUrl + 'reader/mark-volume-unread', {seriesId, volumeId});\n }\n \n\n getNextChapter(seriesId: number, volumeId: number, currentChapterId: number, readingListId: number = -1) {\n if (readingListId > 0) {\n return this.httpClient.get(this.baseUrl + 'readinglist/next-chapter?seriesId=' + seriesId + '¤tChapterId=' + currentChapterId + '&readingListId=' + readingListId);\n }\n return this.httpClient.get(this.baseUrl + 'reader/next-chapter?seriesId=' + seriesId + '&volumeId=' + volumeId + '¤tChapterId=' + currentChapterId);\n }\n\n getPrevChapter(seriesId: number, volumeId: number, currentChapterId: number, readingListId: number = -1) {\n if (readingListId > 0) {\n return this.httpClient.get(this.baseUrl + 'readinglist/prev-chapter?seriesId=' + seriesId + '¤tChapterId=' + currentChapterId + '&readingListId=' + readingListId);\n }\n return this.httpClient.get(this.baseUrl + 'reader/prev-chapter?seriesId=' + seriesId + '&volumeId=' + volumeId + '¤tChapterId=' + currentChapterId);\n }\n\n hasSeriesProgress(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'reader/has-progress?seriesId=' + seriesId);\n }\n\n getCurrentChapter(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'reader/continue-point?seriesId=' + seriesId);\n }\n\n /**\n * Captures current body color and forces background color to be black. Call @see resetOverrideStyles() on destroy of component to revert changes\n */\n setOverrideStyles(backgroundColor: string = 'black') {\n const bodyNode = document.querySelector('body');\n if (bodyNode !== undefined && bodyNode !== null) {\n this.originalBodyColor = bodyNode.style.background;\n bodyNode.setAttribute('style', 'background-color: ' + backgroundColor + ' !important');\n }\n }\n\n resetOverrideStyles() {\n const bodyNode = document.querySelector('body');\n if (bodyNode !== undefined && bodyNode !== null && this.originalBodyColor !== undefined) {\n bodyNode.style.background = this.originalBodyColor;\n }\n }\n\n /**\n * Parses out the page number from a Image src url\n * @param imageSrc Src attribute of Image\n * @returns \n */\n imageUrlToPageNum(imageSrc: string) {\n if (imageSrc === undefined || imageSrc === '') { return -1; }\n return parseInt(imageSrc.split('&page=')[1], 10);\n }\n\n getNextChapterUrl(url: string, nextChapterId: number, incognitoMode: boolean = false, readingListMode: boolean = false, readingListId: number = -1) {\n const lastSlashIndex = url.lastIndexOf('/');\n let newRoute = url.substring(0, lastSlashIndex + 1) + nextChapterId + '';\n newRoute += this.getQueryParams(incognitoMode, readingListMode, readingListId);\n return newRoute;\n }\n\n\n getQueryParamsObject(incognitoMode: boolean = false, readingListMode: boolean = false, readingListId: number = -1) {\n let params: {[key: string]: any} = {};\n if (incognitoMode) {\n params['incognitoMode'] = true;\n }\n if (readingListMode) {\n params['readingListId'] = readingListId;\n }\n return params;\n }\n\n getQueryParams(incognitoMode: boolean = false, readingListMode: boolean = false, readingListId: number = -1) {\n let params = '';\n if (incognitoMode) {\n params += '?incognitoMode=true';\n }\n if (readingListMode) {\n if (params.indexOf('?') > 0) {\n params += '&readingListId=' + readingListId;\n } else {\n params += '?readingListId=' + readingListId;\n }\n }\n return params;\n }\n\n enterFullscreen(el: Element, callback?: VoidFunction) {\n if (!document.fullscreenElement) { \n if (el.requestFullscreen) {\n el.requestFullscreen().then(() => {\n if (callback) {\n callback();\n }\n });\n }\n }\n }\n\n exitFullscreen(callback?: VoidFunction) {\n if (document.exitFullscreen && this.checkFullscreenMode()) {\n document.exitFullscreen().then(() => {\n if (callback) {\n callback();\n }\n });\n }\n }\n\n /**\n * \n * @returns If document is in fullscreen mode\n */\n checkFullscreenMode() {\n return document.fullscreenElement != null;\n }\n}\n","import { HttpClient, HttpParams } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { map } from 'rxjs/operators';\nimport { environment } from 'src/environments/environment';\nimport { UtilityService } from '../shared/_services/utility.service';\nimport { PaginatedResult } from '../_models/pagination';\nimport { ReadingList, ReadingListItem } from '../_models/reading-list';\nimport { ActionItem } from './action-factory.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ReadingListService {\n\n baseUrl = environment.apiUrl;\n\n constructor(private httpClient: HttpClient, private utilityService: UtilityService) { }\n\n getReadingList(readingListId: number) {\n return this.httpClient.get(this.baseUrl + 'readinglist?readingListId=' + readingListId);\n }\n\n getReadingLists(includePromoted: boolean = true, pageNum?: number, itemsPerPage?: number) {\n let params = new HttpParams();\n params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);\n\n return this.httpClient.post>(this.baseUrl + 'readinglist/lists?includePromoted=' + includePromoted, {}, {observe: 'response', params}).pipe(\n map((response: any) => {\n return this.utilityService.createPaginatedResult(response, new PaginatedResult());\n })\n );\n }\n\n getReadingListsForSeries(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'readinglist/lists-for-series?seriesId=' + seriesId);\n }\n\n getListItems(readingListId: number) {\n return this.httpClient.get(this.baseUrl + 'readinglist/items?readingListId=' + readingListId);\n }\n\n createList(title: string) {\n return this.httpClient.post(this.baseUrl + 'readinglist/create', {title});\n }\n\n update(model: {readingListId: number, title?: string, summary?: string, promoted: boolean}) {\n return this.httpClient.post(this.baseUrl + 'readinglist/update', model, { responseType: 'text' as 'json' });\n }\n\n updateByMultiple(readingListId: number, seriesId: number, volumeIds: Array, chapterIds?: Array) {\n return this.httpClient.post(this.baseUrl + 'readinglist/update-by-multiple', {readingListId, seriesId, volumeIds, chapterIds}, { responseType: 'text' as 'json' });\n }\n\n updateByMultipleSeries(readingListId: number, seriesIds: Array) {\n return this.httpClient.post(this.baseUrl + 'readinglist/update-by-multiple-series', {readingListId, seriesIds}, { responseType: 'text' as 'json' });\n }\n\n updateBySeries(readingListId: number, seriesId: number) {\n return this.httpClient.post(this.baseUrl + 'readinglist/update-by-series', {readingListId, seriesId}, { responseType: 'text' as 'json' });\n }\n\n updateByVolume(readingListId: number, seriesId: number, volumeId: number) {\n return this.httpClient.post(this.baseUrl + 'readinglist/update-by-volume', {readingListId, seriesId, volumeId}, { responseType: 'text' as 'json' });\n }\n\n updateByChapter(readingListId: number, seriesId: number, chapterId: number) {\n return this.httpClient.post(this.baseUrl + 'readinglist/update-by-chapter', {readingListId, seriesId, chapterId}, { responseType: 'text' as 'json' });\n }\n\n delete(readingListId: number) {\n return this.httpClient.delete(this.baseUrl + 'readinglist?readingListId=' + readingListId, { responseType: 'text' as 'json' });\n }\n\n updatePosition(readingListId: number, readingListItemId: number, fromPosition: number, toPosition: number) {\n return this.httpClient.post(this.baseUrl + 'readinglist/update-position', {readingListId, readingListItemId, fromPosition, toPosition}, { responseType: 'text' as 'json' });\n }\n\n deleteItem(readingListId: number, readingListItemId: number) {\n return this.httpClient.post(this.baseUrl + 'readinglist/delete-item', {readingListId, readingListItemId}, { responseType: 'text' as 'json' });\n }\n\n removeRead(readingListId: number) {\n return this.httpClient.post(this.baseUrl + 'readinglist/remove-read?readingListId=' + readingListId, {}, { responseType: 'text' as 'json' });\n }\n\n actionListFilter(action: ActionItem, readingList: ReadingList, isAdmin: boolean) {\n if (readingList?.promoted && !isAdmin) return false;\n return true;\n }\n}\n","import { ElementRef, Injectable } from '@angular/core';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ScrollService {\n\n constructor() { }\n\n get scrollPosition() {\n return (window.pageYOffset \n || document.documentElement.scrollTop \n || document.body.scrollTop || 0);\n }\n\n scrollTo(top: number, el: Element | Window = window) {\n el.scroll({\n top: top,\n behavior: 'smooth' \n });\n }\n \n scrollToX(left: number, el: Element | Window = window) {\n el.scroll({\n left: left,\n behavior: 'auto'\n });\n }\n}\n","import { HttpClient, HttpParams } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { of } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { environment } from 'src/environments/environment';\nimport { UtilityService } from '../shared/_services/utility.service';\nimport { Chapter } from '../_models/chapter';\nimport { ChapterMetadata } from '../_models/chapter-metadata';\nimport { CollectionTag } from '../_models/collection-tag';\nimport { PaginatedResult } from '../_models/pagination';\nimport { Series } from '../_models/series';\nimport { RelatedSeries } from '../_models/series-detail/related-series';\nimport { SeriesDetail } from '../_models/series-detail/series-detail';\nimport { SeriesFilter } from '../_models/series-filter';\nimport { SeriesGroup } from '../_models/series-group';\nimport { SeriesMetadata } from '../_models/series-metadata';\nimport { Volume } from '../_models/volume';\nimport { ImageService } from './image.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class SeriesService {\n\n baseUrl = environment.apiUrl;\n paginatedResults: PaginatedResult = new PaginatedResult();\n paginatedSeriesForTagsResults: PaginatedResult = new PaginatedResult();\n\n constructor(private httpClient: HttpClient, private imageService: ImageService, private utilityService: UtilityService) { }\n\n getAllSeries(pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter) {\n let params = new HttpParams();\n params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);\n const data = this.createSeriesFilter(filter);\n\n return this.httpClient.post>(this.baseUrl + 'series/all', data, {observe: 'response', params}).pipe(\n map((response: any) => {\n return this.utilityService.createPaginatedResult(response, this.paginatedResults);\n })\n );\n }\n\n getSeriesForLibrary(libraryId: number, pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter) {\n let params = new HttpParams();\n params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);\n const data = this.createSeriesFilter(filter);\n\n return this.httpClient.post>(this.baseUrl + 'series?libraryId=' + libraryId, data, {observe: 'response', params}).pipe(\n map((response: any) => {\n return this.utilityService.createPaginatedResult(response, this.paginatedResults);\n })\n );\n }\n\n getAllSeriesByIds(seriesIds: Array) {\n return this.httpClient.post(this.baseUrl + 'series/series-by-ids', {seriesIds: seriesIds});\n }\n\n getSeries(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'series/' + seriesId);\n }\n\n getVolumes(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'series/volumes?seriesId=' + seriesId);\n }\n\n getVolume(volumeId: number) {\n return this.httpClient.get(this.baseUrl + 'series/volume?volumeId=' + volumeId);\n }\n\n getChapter(chapterId: number) {\n return this.httpClient.get(this.baseUrl + 'series/chapter?chapterId=' + chapterId);\n }\n\n getChapterMetadata(chapterId: number) {\n return this.httpClient.get(this.baseUrl + 'series/chapter-metadata?chapterId=' + chapterId);\n }\n\n getSeriesForMangaFile(mangaFileId: number) {\n return this.httpClient.get(this.baseUrl + 'series/series-for-mangafile?mangaFileId=' + mangaFileId);\n }\n\n getSeriesForChapter(chapterId: number) {\n return this.httpClient.get(this.baseUrl + 'series/series-for-chapter?chapterId=' + chapterId);\n }\n\n delete(seriesId: number) {\n return this.httpClient.delete(this.baseUrl + 'series/' + seriesId);\n }\n\n deleteMultipleSeries(seriesIds: Array) {\n return this.httpClient.post(this.baseUrl + 'series/delete-multiple', {seriesIds});\n }\n\n updateRating(seriesId: number, userRating: number, userReview: string) {\n return this.httpClient.post(this.baseUrl + 'series/update-rating', {seriesId, userRating, userReview});\n }\n\n updateSeries(model: any) {\n return this.httpClient.post(this.baseUrl + 'series/update', model);\n }\n\n markRead(seriesId: number) {\n return this.httpClient.post(this.baseUrl + 'reader/mark-read', {seriesId});\n }\n\n markUnread(seriesId: number) {\n return this.httpClient.post(this.baseUrl + 'reader/mark-unread', {seriesId});\n }\n\n getRecentlyAdded(libraryId: number = 0, pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter) {\n const data = this.createSeriesFilter(filter);\n let params = new HttpParams();\n params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);\n\n return this.httpClient.post(this.baseUrl + 'series/recently-added?libraryId=' + libraryId, data, {observe: 'response', params}).pipe(\n map(response => {\n return this.utilityService.createPaginatedResult(response, new PaginatedResult());\n })\n );\n }\n\n getRecentlyUpdatedSeries() {\n return this.httpClient.post(this.baseUrl + 'series/recently-updated-series', {});\n }\n\n getOnDeck(libraryId: number = 0, pageNum?: number, itemsPerPage?: number, filter?: SeriesFilter) {\n const data = this.createSeriesFilter(filter);\n\n let params = new HttpParams();\n params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);\n\n return this.httpClient.post(this.baseUrl + 'series/on-deck?libraryId=' + libraryId, data, {observe: 'response', params}).pipe(\n map(response => {\n return this.utilityService.createPaginatedResult(response, new PaginatedResult());\n }));\n }\n\n\n refreshMetadata(series: Series) {\n return this.httpClient.post(this.baseUrl + 'series/refresh-metadata', {libraryId: series.libraryId, seriesId: series.id});\n }\n\n scan(libraryId: number, seriesId: number) {\n return this.httpClient.post(this.baseUrl + 'series/scan', {libraryId: libraryId, seriesId: seriesId});\n }\n\n getMetadata(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'series/metadata?seriesId=' + seriesId).pipe(map(items => {\n items?.collectionTags.forEach(tag => tag.coverImage = this.imageService.getCollectionCoverImage(tag.id));\n return items;\n }));\n }\n\n updateMetadata(seriesMetadata: SeriesMetadata, collectionTags: CollectionTag[]) {\n const data = {\n seriesMetadata,\n collectionTags,\n };\n return this.httpClient.post(this.baseUrl + 'series/metadata', data, {responseType: 'text' as 'json'});\n }\n\n getSeriesForTag(collectionTagId: number, pageNum?: number, itemsPerPage?: number) {\n let params = new HttpParams();\n\n params = this.utilityService.addPaginationIfExists(params, pageNum, itemsPerPage);\n\n return this.httpClient.get>(this.baseUrl + 'series/series-by-collection?collectionId=' + collectionTagId, {observe: 'response', params}).pipe(\n map((response: any) => {\n return this.utilityService.createPaginatedResult(response, this.paginatedSeriesForTagsResults);\n })\n );\n }\n\n getRelatedForSeries(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'series/all-related?seriesId=' + seriesId);\n }\n\n updateRelationships(seriesId: number, adaptations: Array, characters: Array, \n contains: Array, others: Array, prequels: Array, \n sequels: Array, sideStories: Array, spinOffs: Array,\n alternativeSettings: Array, alternativeVersions: Array, doujinshis: Array) {\n return this.httpClient.post(this.baseUrl + 'series/update-related?seriesId=' + seriesId, \n {seriesId, adaptations, characters, sequels, prequels, contains, others, sideStories, spinOffs,\n alternativeSettings, alternativeVersions, doujinshis}); \n }\n\n getSeriesDetail(seriesId: number) {\n return this.httpClient.get(this.baseUrl + 'series/series-detail?seriesId=' + seriesId);\n }\n\n \n\n createSeriesFilter(filter?: SeriesFilter) {\n if (filter !== undefined) return filter;\n const data: SeriesFilter = {\n formats: [],\n libraries: [],\n genres: [],\n writers: [],\n artists: [],\n penciller: [],\n inker: [],\n colorist: [],\n letterer: [],\n coverArtist: [],\n editor: [],\n publisher: [],\n character: [],\n translators: [],\n collectionTags: [],\n rating: 0,\n readStatus: {\n read: true,\n inProgress: true,\n notRead: true\n },\n sortOptions: null,\n ageRating: [],\n tags: [],\n languages: [],\n publicationStatus: [],\n seriesNameQuery: '',\n };\n\n return data;\n }\n}\n","import { DOCUMENT } from '@angular/common';\nimport { HttpClient } from '@angular/common/http';\nimport { Inject, Injectable, OnDestroy, Renderer2, RendererFactory2, SecurityContext } from '@angular/core';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { map, ReplaySubject, Subject, takeUntil } from 'rxjs';\nimport { environment } from 'src/environments/environment';\nimport { ConfirmService } from '../shared/confirm.service';\nimport { NotificationProgressEvent } from '../_models/events/notification-progress-event';\nimport { SiteTheme, ThemeProvider } from '../_models/preferences/site-theme';\nimport { EVENTS, MessageHubService } from './message-hub.service';\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ThemeService implements OnDestroy {\n\n public defaultTheme: string = 'dark';\n public defaultBookTheme: string = 'Dark';\n\n private currentThemeSource = new ReplaySubject(1);\n public currentTheme$ = this.currentThemeSource.asObservable();\n\n private themesSource = new ReplaySubject(1);\n public themes$ = this.themesSource.asObservable();\n\n /**\n * Maintain a cache of themes. SignalR will inform us if we need to refresh cache\n */\n private themeCache: Array = [];\n\n private readonly onDestroy = new Subject();\n private renderer: Renderer2;\n private baseUrl = environment.apiUrl;\n\n\n constructor(rendererFactory: RendererFactory2, @Inject(DOCUMENT) private document: Document, private httpClient: HttpClient,\n messageHub: MessageHubService, private domSantizer: DomSanitizer, private confirmService: ConfirmService) {\n this.renderer = rendererFactory.createRenderer(null, null);\n\n this.getThemes();\n\n messageHub.messages$.pipe(takeUntil(this.onDestroy)).subscribe(message => {\n\n if (message.event !== EVENTS.NotificationProgress) return;\n const notificationEvent = (message.payload as NotificationProgressEvent);\n if (notificationEvent.name !== EVENTS.SiteThemeProgress) return;\n\n if (notificationEvent.eventType === 'ended') {\n if (notificationEvent.name === EVENTS.SiteThemeProgress) this.getThemes().subscribe(() => {});\n }\n });\n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n getColorScheme() {\n return getComputedStyle(this.document.body).getPropertyValue('--color-scheme').trim();\n }\n\n getCssVariable(variable: string) {\n return getComputedStyle(this.document.body).getPropertyValue(variable).trim();\n }\n\n isDarkTheme() {\n return this.getColorScheme().toLowerCase() === 'dark';\n }\n\n getThemes() {\n return this.httpClient.get(this.baseUrl + 'theme').pipe(map(themes => {\n this.themeCache = themes;\n this.themesSource.next(themes);\n return themes;\n }));\n }\n\n /**\n * Used in book reader to remove all themes so book reader can provide custom theming options\n */\n clearThemes() {\n this.unsetThemes();\n }\n\n setDefault(themeId: number) {\n return this.httpClient.post(this.baseUrl + 'theme/update-default', {themeId: themeId}).pipe(map(() => {\n // Refresh the cache when a default state is changed\n this.getThemes().subscribe(() => {});\n }));\n }\n\n scan() {\n return this.httpClient.post(this.baseUrl + 'theme/scan', {});\n }\n\n /**\n * Sets the book theme on the body tag so css variable overrides can take place\n * @param selector brtheme- prefixed string\n */\n setBookTheme(selector: string) {\n this.unsetBookThemes();\n this.renderer.addClass(this.document.querySelector('body'), selector);\n }\n\n clearBookTheme() {\n this.unsetBookThemes();\n }\n\n\n /**\n * Sets the theme as active. Will inject a style tag into document to load a custom theme and apply the selector to the body\n * @param themeName\n */\n setTheme(themeName: string) {\n const theme = this.themeCache.find(t => t.name.toLowerCase() === themeName.toLowerCase());\n if (theme) {\n this.unsetThemes();\n this.renderer.addClass(this.document.querySelector('body'), theme.selector);\n\n if (theme.provider === ThemeProvider.User && !this.hasThemeInHead(theme.name)) {\n // We need to load the styles into the browser\n this.fetchThemeContent(theme.id).subscribe(async (content) => {\n if (content === null) {\n await this.confirmService.alert('There is invalid or unsafe css in the theme. Please reach out to your admin to have this corrected. Defaulting to dark theme.');\n this.setTheme('dark');\n return;\n }\n const styleElem = document.createElement('style');\n styleElem.id = 'theme-' + theme.name;\n styleElem.appendChild(this.document.createTextNode(content));\n\n this.renderer.appendChild(this.document.head, styleElem);\n this.currentThemeSource.next(theme);\n });\n } else {\n this.currentThemeSource.next(theme);\n }\n } else {\n // Only time themes isn't already loaded is on first load\n this.getThemes().subscribe(themes => {\n this.setTheme(themeName);\n });\n }\n }\n\n private hasThemeInHead(themeName: string) {\n const id = 'theme-' + themeName.toLowerCase();\n return Array.from(this.document.head.children).filter(el => el.tagName === 'STYLE' && el.id.toLowerCase() === id).length > 0;\n }\n\n private fetchThemeContent(themeId: number) {\n // TODO: Refactor {responseType: 'text' as 'json'} into a type so i don't have to retype it\n return this.httpClient.get(this.baseUrl + 'theme/download-content?themeId=' + themeId, {responseType: 'text' as 'json'}).pipe(map(encodedCss => {\n return this.domSantizer.sanitize(SecurityContext.STYLE, encodedCss);\n }));\n }\n\n private unsetThemes() {\n this.themeCache.forEach(theme => this.document.body.classList.remove(theme.selector));\n }\n\n private unsetBookThemes() {\n Array.from(this.document.body.classList).filter(cls => cls.startsWith('brtheme-')).forEach(c => this.document.body.classList.remove(c));\n }\n\n\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { environment } from 'src/environments/environment';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class UploadService {\n\n private baseUrl = environment.apiUrl;\n\n constructor(private httpClient: HttpClient) { }\n\n\n uploadByUrl(url: string) {\n return this.httpClient.post(this.baseUrl + 'upload/upload-by-url', {url}, {responseType: 'text' as 'json'});\n }\n\n /**\n * \n * @param seriesId Series to overwrite cover image for\n * @param url A base64 encoded url\n * @returns \n */\n updateSeriesCoverImage(seriesId: number, url: string) {\n return this.httpClient.post(this.baseUrl + 'upload/series', {id: seriesId, url: this._cleanBase64Url(url)});\n }\n\n updateCollectionCoverImage(tagId: number, url: string) {\n return this.httpClient.post(this.baseUrl + 'upload/collection', {id: tagId, url: this._cleanBase64Url(url)});\n }\n\n updateReadingListCoverImage(readingListId: number, url: string) {\n return this.httpClient.post(this.baseUrl + 'upload/reading-list', {id: readingListId, url: this._cleanBase64Url(url)});\n }\n\n updateChapterCoverImage(chapterId: number, url: string) {\n return this.httpClient.post(this.baseUrl + 'upload/chapter', {id: chapterId, url: this._cleanBase64Url(url)});\n }\n\n resetChapterCoverLock(chapterId: number, ) {\n return this.httpClient.post(this.baseUrl + 'upload/reset-chapter-lock', {id: chapterId, url: ''});\n }\n\n _cleanBase64Url(url: string) {\n if (url.startsWith('data')) {\n url = url.split(',')[1];\n }\n return url;\n }\n}\n"," 0\">\n
\n \n
\n \n
1 && adminActions.length > 1\">
\n \n
\n
\n
","import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\nimport { Action, ActionItem } from 'src/app/_services/action-factory.service';\n\n@Component({\n selector: 'app-card-actionables',\n templateUrl: './card-actionables.component.html',\n styleUrls: ['./card-actionables.component.scss']\n})\nexport class CardActionablesComponent implements OnInit {\n\n @Input() iconClass = 'fa-ellipsis-v';\n @Input() btnClass = '';\n @Input() actions: ActionItem[] = [];\n @Input() labelBy = 'card';\n @Input() disabled: boolean = false;\n @Output() actionHandler = new EventEmitter>();\n\n adminActions: ActionItem[] = [];\n nonAdminActions: ActionItem[] = [];\n\n\n constructor() { }\n\n ngOnInit(): void {\n this.nonAdminActions = this.actions.filter(item => !item.requiresAdmin);\n this.adminActions = this.actions.filter(item => item.requiresAdmin);\n }\n\n preventClick(event: any) {\n event.stopPropagation();\n event.preventDefault();\n }\n\n performAction(event: any, action: ActionItem) {\n this.preventClick(event);\n\n if (typeof action.callback === 'function') {\n this.actionHandler.emit(action);\n }\n }\n\n}\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MetadataFilterComponent } from './metadata-filter.component';\nimport { NgbCollapseModule, NgbRatingModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { SharedModule } from '../shared/shared.module';\nimport { TypeaheadModule } from '../typeahead/typeahead.module';\n\n@NgModule({\n declarations: [\n MetadataFilterComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n ReactiveFormsModule,\n NgbTooltipModule, \n NgbRatingModule,\n NgbCollapseModule,\n SharedModule,\n TypeaheadModule\n ],\n exports: [\n MetadataFilterComponent\n ]\n})\nexport class MetadataFilterModule { }\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { SeriesCardComponent } from './series-card/series-card.component';\nimport { LibraryCardComponent } from './library-card/library-card.component';\nimport { CoverImageChooserComponent } from './cover-image-chooser/cover-image-chooser.component';\nimport { EditSeriesModalComponent } from './_modals/edit-series-modal/edit-series-modal.component';\nimport { EditCollectionTagsComponent } from './_modals/edit-collection-tags/edit-collection-tags.component';\nimport { NgbTooltipModule, NgbCollapseModule, NgbPaginationModule, NgbDropdownModule, NgbProgressbarModule, NgbNavModule, NgbRatingModule } from '@ng-bootstrap/ng-bootstrap';\nimport { CardActionablesComponent } from './card-item/card-actionables/card-actionables.component';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { NgxFileDropModule } from 'ngx-file-drop';\nimport { CardItemComponent } from './card-item/card-item.component';\nimport { SharedModule } from '../shared/shared.module';\nimport { RouterModule } from '@angular/router';\nimport { TypeaheadModule } from '../typeahead/typeahead.module';\nimport { CardDetailLayoutComponent } from './card-detail-layout/card-detail-layout.component';\nimport { CardDetailsModalComponent } from './_modals/card-details-modal/card-details-modal.component';\nimport { BulkOperationsComponent } from './bulk-operations/bulk-operations.component';\nimport { BulkAddToCollectionComponent } from './_modals/bulk-add-to-collection/bulk-add-to-collection.component';\nimport { PipeModule } from '../pipe/pipe.module';\nimport { ChapterMetadataDetailComponent } from './chapter-metadata-detail/chapter-metadata-detail.component';\nimport { FileInfoComponent } from './file-info/file-info.component';\nimport { MetadataFilterModule } from '../metadata-filter/metadata-filter.module';\nimport { EditSeriesRelationComponent } from './edit-series-relation/edit-series-relation.component';\n\n\n\n@NgModule({\n declarations: [\n CardItemComponent,\n SeriesCardComponent,\n LibraryCardComponent,\n CoverImageChooserComponent,\n EditSeriesModalComponent,\n EditCollectionTagsComponent,\n CardActionablesComponent,\n CardDetailLayoutComponent,\n CardDetailsModalComponent,\n BulkOperationsComponent,\n BulkAddToCollectionComponent,\n ChapterMetadataDetailComponent,\n FileInfoComponent,\n EditSeriesRelationComponent,\n ],\n imports: [\n CommonModule,\n RouterModule,\n ReactiveFormsModule,\n FormsModule, // EditCollectionsModal\n\n PipeModule,\n SharedModule,\n TypeaheadModule, // edit series modal\n\n MetadataFilterModule,\n\n NgbTooltipModule, // Card item\n NgbCollapseModule,\n NgbRatingModule,\n\n\n\n NgbNavModule, //Series Detail\n NgbPaginationModule, // CardDetailLayoutComponent\n NgbDropdownModule,\n NgbProgressbarModule,\n NgxFileDropModule, // Cover Chooser\n PipeModule // filter for BulkAddToCollectionComponent\n ],\n exports: [\n CardItemComponent,\n SeriesCardComponent,\n LibraryCardComponent,\n SeriesCardComponent,\n LibraryCardComponent,\n CoverImageChooserComponent,\n EditSeriesModalComponent,\n EditCollectionTagsComponent,\n CardActionablesComponent,\n CardDetailLayoutComponent,\n CardDetailsModalComponent,\n BulkOperationsComponent,\n ChapterMetadataDetailComponent,\n EditSeriesRelationComponent\n ]\n})\nexport class CardsModule { }\n","
\n
\n \n \n
\n
\n
\n \n
\n\n
\n
\n Enter a Url\n •\n Drag and drop\n •\n Upload an image\n
\n
\n
\n
\n \n\n \n
\n
\n \n \n \n
\n \n
\n \n
\n \n
\n
\n\n \n\n \n
\n\n
\n
\n \n
\n
\n \n
\n
\n\n
\n\n","import { Component, EventEmitter, Inject, Input, OnDestroy, OnInit, Output } from '@angular/core';\nimport { FormBuilder, FormControl, FormGroup } from '@angular/forms';\nimport { NgxFileDropEntry, FileSystemFileEntry } from 'ngx-file-drop';\nimport { fromEvent, Subject } from 'rxjs';\nimport { takeWhile } from 'rxjs/operators';\nimport { ToastrService } from 'ngx-toastr';\nimport { ImageService } from 'src/app/_services/image.service';\nimport { KEY_CODES } from 'src/app/shared/_services/utility.service';\nimport { UploadService } from 'src/app/_services/upload.service';\nimport { DOCUMENT } from '@angular/common';\n\n@Component({\n selector: 'app-cover-image-chooser',\n templateUrl: './cover-image-chooser.component.html',\n styleUrls: ['./cover-image-chooser.component.scss']\n})\nexport class CoverImageChooserComponent implements OnInit, OnDestroy {\n\n @Input() imageUrls: Array = [];\n @Output() imageUrlsChange: EventEmitter> = new EventEmitter>();\n\n /**\n * Should the control give the ability to select an image that emits the reset status for cover image\n */\n @Input() showReset: boolean = false;\n @Output() resetClicked: EventEmitter = new EventEmitter();\n\n /**\n * Emits the selected index. Used usually to check if something other than the default image was selected.\n */\n @Output() imageSelected: EventEmitter = new EventEmitter();\n /**\n * Emits a base64 encoded image\n */\n @Output() selectedBase64Url: EventEmitter = new EventEmitter();\n\n\n\n selectedIndex: number = 0;\n form!: FormGroup;\n files: NgxFileDropEntry[] = [];\n\n mode: 'file' | 'url' | 'all' = 'all';\n private readonly onDestroy = new Subject();\n\n constructor(public imageService: ImageService, private fb: FormBuilder, private toastr: ToastrService, private uploadService: UploadService,\n @Inject(DOCUMENT) private document: Document) { }\n\n ngOnInit(): void {\n this.form = this.fb.group({\n coverImageUrl: new FormControl('', [])\n });\n }\n\n ngOnDestroy() {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n getBase64Image(img: HTMLImageElement) {\n const canvas = document.createElement(\"canvas\");\n canvas.width = img.width;\n canvas.height = img.height;\n const ctx = canvas.getContext(\"2d\", {alpha: false});\n if (!ctx) {\n return '';\n }\n\n ctx.drawImage(img, 0, 0);\n var dataURL = canvas.toDataURL(\"image/png\");\n return dataURL;\n }\n\n selectImage(index: number) {\n if (this.selectedIndex === index) { return; }\n this.selectedIndex = index;\n this.imageSelected.emit(this.selectedIndex);\n this.selectedBase64Url.emit(this.imageUrls[this.selectedIndex]);\n }\n\n loadImage() {\n const url = this.form.get('coverImageUrl')?.value.trim();\n if (url && url != '') {\n\n this.uploadService.uploadByUrl(url).subscribe(filename => {\n const img = new Image();\n img.crossOrigin = 'Anonymous';\n img.src = this.imageService.getCoverUploadImage(filename);\n img.onload = (e) => this.handleUrlImageAdd(img);\n img.onerror = (e) => {\n this.toastr.error('The image could not be fetched due to server refusing request. Please download and upload from file instead.');\n this.form.get('coverImageUrl')?.setValue('');\n };\n this.form.get('coverImageUrl')?.setValue('');\n });\n }\n }\n\n changeMode(mode: 'url') {\n this.mode = mode;\n this.setupEnterHandler();\n\n setTimeout(() => (this.document.querySelector('#load-image') as HTMLInputElement)?.focus(), 10);\n }\n\n public dropped(files: NgxFileDropEntry[]) {\n this.files = files;\n for (const droppedFile of files) {\n\n // Is it a file?\n if (droppedFile.fileEntry.isFile) {\n const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;\n fileEntry.file((file: File) => {\n const reader = new FileReader();\n reader.onload = (e) => this.handleFileImageAdd(e);\n reader.readAsDataURL(file);\n });\n }\n }\n }\n\n handleFileImageAdd(e: any) {\n if (e.target == null) return;\n\n this.imageUrls.push(e.target.result);\n this.imageUrlsChange.emit(this.imageUrls);\n this.selectedIndex += 1;\n this.imageSelected.emit(this.selectedIndex); // Auto select newly uploaded image\n this.selectedBase64Url.emit(e.target.result);\n }\n\n handleUrlImageAdd(img: HTMLImageElement) {\n const url = this.getBase64Image(img);\n this.imageUrls.push(url);\n this.imageUrlsChange.emit(this.imageUrls);\n\n setTimeout(() => {\n // Auto select newly uploaded image and tell parent of new base64 url\n this.selectImage(this.selectedIndex + 1);\n });\n }\n\n public fileOver(event: any){\n }\n\n public fileLeave(event: any){\n }\n\n reset() {\n this.resetClicked.emit();\n this.selectedIndex = -1;\n }\n\n setupEnterHandler() {\n setTimeout(() => {\n const elem = document.querySelector('input[id=\"load-image\"]');\n if (elem == null) return;\n fromEvent(elem, 'keydown')\n .pipe(takeWhile(() => this.mode === 'url')).subscribe((event) => {\n const evt = event;\n switch(evt.key) {\n case KEY_CODES.ENTER:\n {\n this.loadImage();\n break;\n }\n\n case KEY_CODES.ESC_KEY:\n this.mode = 'all';\n event.stopPropagation();\n break;\n default:\n break;\n }\n });\n });\n }\n\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({\n name: 'filter',\n pure: false\n})\nexport class FilterPipe implements PipeTransform {\n\n transform(items: any[], callback: (item: any) => boolean): any {\n if (!items || !callback) {\n return items;\n }\n return items.filter(item => callback(item));\n}\n\n}\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FilterPipe } from './filter.pipe';\nimport { PublicationStatusPipe } from './publication-status.pipe';\nimport { SentenceCasePipe } from './sentence-case.pipe';\nimport { PersonRolePipe } from './person-role.pipe';\nimport { SafeHtmlPipe } from './safe-html.pipe';\nimport { RelationshipPipe } from './relationship.pipe';\n\n\n\n@NgModule({\n declarations: [\n FilterPipe,\n PersonRolePipe,\n PublicationStatusPipe,\n SentenceCasePipe,\n SafeHtmlPipe,\n RelationshipPipe\n ],\n imports: [\n CommonModule,\n ],\n exports: [\n FilterPipe,\n PersonRolePipe,\n PublicationStatusPipe,\n SentenceCasePipe,\n SafeHtmlPipe,\n RelationshipPipe\n ]\n})\nexport class PipeModule { }\n","import { Pipe, PipeTransform, SecurityContext } from '@angular/core';\nimport { DomSanitizer } from '@angular/platform-browser';\n\n@Pipe({\n name: 'safeHtml'\n})\nexport class SafeHtmlPipe implements PipeTransform {\n\n constructor(private dom: DomSanitizer) {}\n\n transform(value: string): unknown {\n return this.dom.sanitize(SecurityContext.HTML, value);\n }\n\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({\n name: 'sentenceCase'\n})\nexport class SentenceCasePipe implements PipeTransform {\n\n transform(value: string | null): string {\n if (value === null || value === undefined) return '';\n \n return value.charAt(0).toUpperCase() + value.substr(1);\n }\n\n}\n","import {InjectionToken} from '@angular/core'\nimport { saveAs } from 'file-saver';\n\nexport type Saver = (blob: Blob, filename?: string) => void\n\nexport const SAVER = new InjectionToken('saver')\n\nexport function getSaver(): Saver {\n return saveAs;\n}","import { Injectable } from '@angular/core';\nimport { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';\nimport { Pagination } from 'src/app/_models/pagination';\nimport { SeriesFilter, SortField } from 'src/app/_models/series-filter';\nimport { SeriesService } from 'src/app/_services/series.service';\n\n/**\n * Used to pass state between the filter and the url\n */\nexport enum FilterQueryParam {\n Format = 'format',\n Genres = 'genres',\n AgeRating = 'ageRating',\n PublicationStatus = 'publicationStatus',\n Tags = 'tags',\n Languages = 'languages',\n CollectionTags = 'collectionTags',\n Libraries = 'libraries',\n Writers = 'writers',\n Artists = 'artists',\n Character = 'character',\n Colorist = 'colorist',\n CoverArtists = 'coverArtists',\n Editor = 'editor',\n Inker = 'inker',\n Letterer = 'letterer',\n Penciller = 'penciller',\n Publisher = 'publisher',\n Translator = 'translators',\n ReadStatus = 'readStatus',\n SortBy = 'sortBy',\n Rating = 'rating',\n Name = 'name',\n /**\n * This is a pagination control\n */\n Page = 'page'\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class FilterUtilitiesService {\n\n constructor(private route: ActivatedRoute, private seriesService: SeriesService) { }\n\n /**\n * Updates the window location with a custom url based on filter and pagination objects\n * @param pagination \n * @param filter \n */\n updateUrlFromFilter(pagination: Pagination, filter: SeriesFilter | undefined) {\n const params = '?page=' + pagination.currentPage;\n \n const url = this.urlFromFilter(window.location.href.split('?')[0] + params, filter);\n window.history.replaceState(window.location.href, '', this.replacePaginationOnUrl(url, pagination));\n }\n\n /**\n * Patches the page query param in the window location. \n * @param pagination \n */\n updateUrlFromPagination(pagination: Pagination) {\n window.history.replaceState(window.location.href, '', this.replacePaginationOnUrl(window.location.href, pagination));\n }\n\n private replacePaginationOnUrl(url: string, pagination: Pagination) {\n return url.replace(/page=\\d+/i, 'page=' + pagination.currentPage);\n }\n\n /**\n * Will fetch current page from route if present\n * @param ActivatedRouteSnapshot to fetch page from. Must be from component else may get stale data\n * @returns A default pagination object\n */\n pagination(snapshot: ActivatedRouteSnapshot): Pagination {\n return {currentPage: parseInt(snapshot.queryParamMap.get('page') || '1', 10), itemsPerPage: 30, totalItems: 0, totalPages: 1};\n }\n\n\n /**\n * Returns the current url with query params for the filter\n * @param currentUrl Full url, with ?page=1 as a minimum\n * @param filter Filter to build url off\n * @returns current url with query params added\n */\n urlFromFilter(currentUrl: string, filter: SeriesFilter | undefined) {\n if (filter === undefined) return currentUrl;\n let params = '';\n\n params += this.joinFilter(filter.formats, FilterQueryParam.Format);\n params += this.joinFilter(filter.genres, FilterQueryParam.Genres);\n params += this.joinFilter(filter.ageRating, FilterQueryParam.AgeRating);\n params += this.joinFilter(filter.publicationStatus, FilterQueryParam.PublicationStatus);\n params += this.joinFilter(filter.tags, FilterQueryParam.Tags);\n params += this.joinFilter(filter.languages, FilterQueryParam.Languages);\n params += this.joinFilter(filter.collectionTags, FilterQueryParam.CollectionTags);\n params += this.joinFilter(filter.libraries, FilterQueryParam.Libraries);\n\n params += this.joinFilter(filter.writers, FilterQueryParam.Writers);\n params += this.joinFilter(filter.artists, FilterQueryParam.Artists);\n params += this.joinFilter(filter.character, FilterQueryParam.Character);\n params += this.joinFilter(filter.colorist, FilterQueryParam.Colorist);\n params += this.joinFilter(filter.coverArtist, FilterQueryParam.CoverArtists);\n params += this.joinFilter(filter.editor, FilterQueryParam.Editor);\n params += this.joinFilter(filter.inker, FilterQueryParam.Inker);\n params += this.joinFilter(filter.letterer, FilterQueryParam.Letterer);\n params += this.joinFilter(filter.penciller, FilterQueryParam.Penciller);\n params += this.joinFilter(filter.publisher, FilterQueryParam.Publisher);\n params += this.joinFilter(filter.translators, FilterQueryParam.Translator);\n\n // readStatus (we need to do an additonal check as there is a default case)\n if (filter.readStatus && filter.readStatus.inProgress !== true && filter.readStatus.notRead !== true && filter.readStatus.read !== true) {\n params += `&${FilterQueryParam.ReadStatus}=${filter.readStatus.inProgress},${filter.readStatus.notRead},${filter.readStatus.read}`;\n }\n\n // sortBy (additional check to not save to url if default case)\n if (filter.sortOptions && !(filter.sortOptions.sortField === SortField.SortName && filter.sortOptions.isAscending === true)) {\n params += `&${FilterQueryParam.SortBy}=${filter.sortOptions.sortField},${filter.sortOptions.isAscending}`;\n }\n\n if (filter.rating > 0) {\n params += `&${FilterQueryParam.Rating}=${filter.rating}`;\n }\n\n if (filter.seriesNameQuery !== '') {\n params += `&${FilterQueryParam.Name}=${encodeURIComponent(filter.seriesNameQuery)}`;\n }\n \n return currentUrl + params;\n }\n\n private joinFilter(filterProp: Array, key: string) {\n let params = '';\n if (filterProp.length > 0) {\n params += `&${key}=${filterProp.join(',')}`;\n }\n return params;\n }\n\n /**\n * Returns a new instance of a filterSettings that is populated with filter presets from URL\n * @param ActivatedRouteSnapshot to fetch page from. Must be from component else may get stale data\n * @returns The Preset filter and if something was set within\n */\n filterPresetsFromUrl(snapshot: ActivatedRouteSnapshot): [SeriesFilter, boolean] {\n const filter = this.seriesService.createSeriesFilter();\n let anyChanged = false;\n\n const format = snapshot.queryParamMap.get(FilterQueryParam.Format);\n if (format !== undefined && format !== null) {\n filter.formats = [...filter.formats, ...format.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const genres = snapshot.queryParamMap.get(FilterQueryParam.Genres);\n if (genres !== undefined && genres !== null) {\n filter.genres = [...filter.genres, ...genres.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const ageRating = snapshot.queryParamMap.get(FilterQueryParam.AgeRating);\n if (ageRating !== undefined && ageRating !== null) {\n filter.ageRating = [...filter.ageRating, ...ageRating.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const publicationStatus = snapshot.queryParamMap.get(FilterQueryParam.PublicationStatus);\n if (publicationStatus !== undefined && publicationStatus !== null) {\n filter.publicationStatus = [...filter.publicationStatus, ...publicationStatus.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const tags = snapshot.queryParamMap.get(FilterQueryParam.Tags);\n if (tags !== undefined && tags !== null) {\n filter.tags = [...filter.tags, ...tags.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const languages = snapshot.queryParamMap.get(FilterQueryParam.Languages);\n if (languages !== undefined && languages !== null) {\n filter.languages = [...filter.languages, ...languages.split(',')];\n anyChanged = true;\n }\n\n const writers = snapshot.queryParamMap.get(FilterQueryParam.Writers);\n if (writers !== undefined && writers !== null) {\n filter.writers = [...filter.writers, ...writers.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const artists = snapshot.queryParamMap.get(FilterQueryParam.Artists);\n if (artists !== undefined && artists !== null) {\n filter.artists = [...filter.artists, ...artists.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const character = snapshot.queryParamMap.get(FilterQueryParam.Character);\n if (character !== undefined && character !== null) {\n filter.character = [...filter.character, ...character.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const colorist = snapshot.queryParamMap.get(FilterQueryParam.Colorist);\n if (colorist !== undefined && colorist !== null) {\n filter.colorist = [...filter.colorist, ...colorist.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const coverArtists = snapshot.queryParamMap.get(FilterQueryParam.CoverArtists);\n if (coverArtists !== undefined && coverArtists !== null) {\n filter.coverArtist = [...filter.coverArtist, ...coverArtists.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const editor = snapshot.queryParamMap.get(FilterQueryParam.Editor);\n if (editor !== undefined && editor !== null) {\n filter.editor = [...filter.editor, ...editor.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const inker = snapshot.queryParamMap.get(FilterQueryParam.Inker);\n if (inker !== undefined && inker !== null) {\n filter.inker = [...filter.inker, ...inker.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const letterer = snapshot.queryParamMap.get(FilterQueryParam.Letterer);\n if (letterer !== undefined && letterer !== null) {\n filter.letterer = [...filter.letterer, ...letterer.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const penciller = snapshot.queryParamMap.get(FilterQueryParam.Penciller);\n if (penciller !== undefined && penciller !== null) {\n filter.penciller = [...filter.penciller, ...penciller.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const publisher = snapshot.queryParamMap.get(FilterQueryParam.Publisher);\n if (publisher !== undefined && publisher !== null) {\n filter.publisher = [...filter.publisher, ...publisher.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const translators = snapshot.queryParamMap.get(FilterQueryParam.Translator);\n if (translators !== undefined && translators !== null) {\n filter.translators = [...filter.translators, ...translators.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const libraries = snapshot.queryParamMap.get(FilterQueryParam.Libraries);\n if (libraries !== undefined && libraries !== null) {\n filter.libraries = [...filter.libraries, ...libraries.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n const collectionTags = snapshot.queryParamMap.get(FilterQueryParam.CollectionTags);\n if (collectionTags !== undefined && collectionTags !== null) {\n filter.collectionTags = [...filter.collectionTags, ...collectionTags.split(',').map(item => parseInt(item, 10))];\n anyChanged = true;\n }\n\n // Rating, seriesName, \n const rating = snapshot.queryParamMap.get(FilterQueryParam.Rating);\n if (rating !== undefined && rating !== null && parseInt(rating, 10) > 0) {\n filter.rating = parseInt(rating, 10);\n anyChanged = true;\n }\n\n /// Read status is encoded as true,true,true\n const readStatus = snapshot.queryParamMap.get(FilterQueryParam.ReadStatus);\n if (readStatus !== undefined && readStatus !== null) {\n const values = readStatus.split(',').map(i => i === 'true');\n if (values.length === 3) {\n filter.readStatus.inProgress = values[0];\n filter.readStatus.notRead = values[1];\n filter.readStatus.read = values[2];\n anyChanged = true;\n }\n }\n\n const sortBy = snapshot.queryParamMap.get(FilterQueryParam.SortBy);\n if (sortBy !== undefined && sortBy !== null) {\n const values = sortBy.split(',');\n if (values.length === 1) {\n values.push('true');\n }\n if (values.length === 2) {\n filter.sortOptions = {\n isAscending: values[1] === 'true',\n sortField: Number(values[0])\n }\n anyChanged = true;\n }\n }\n\n const searchNameQuery = snapshot.queryParamMap.get(FilterQueryParam.Name);\n if (searchNameQuery !== undefined && searchNameQuery !== null && searchNameQuery !== '') {\n filter.seriesNameQuery = decodeURIComponent(searchNameQuery);\n anyChanged = true;\n }\n \n\n return [filter, false]; // anyChanged. Testing out if having a filter active but keep drawer closed by default works better\n }\n}\n","import { HttpParams } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { ActivatedRouteSnapshot } from '@angular/router';\nimport { Chapter } from 'src/app/_models/chapter';\nimport { LibraryType } from 'src/app/_models/library';\nimport { MangaFormat } from 'src/app/_models/manga-format';\nimport { PaginatedResult } from 'src/app/_models/pagination';\nimport { Series } from 'src/app/_models/series';\nimport { SeriesFilter, SortField } from 'src/app/_models/series-filter';\nimport { Volume } from 'src/app/_models/volume';\n\nexport enum KEY_CODES {\n RIGHT_ARROW = 'ArrowRight',\n LEFT_ARROW = 'ArrowLeft',\n DOWN_ARROW = 'ArrowDown',\n UP_ARROW = 'ArrowUp',\n ESC_KEY = 'Escape',\n SPACE = ' ',\n ENTER = 'Enter',\n G = 'g',\n B = 'b',\n F = 'f',\n BACKSPACE = 'Backspace',\n DELETE = 'Delete',\n SHIFT = 'Shift'\n}\n\nexport enum Breakpoint {\n Mobile = 768,\n Tablet = 1280,\n Desktop = 1440\n}\n\n\n@Injectable({\n providedIn: 'root'\n})\nexport class UtilityService {\n\n mangaFormatKeys: string[] = [];\n\n constructor() { }\n\n sortVolumes = (a: Volume, b: Volume) => {\n if (a === b) { return 0; }\n else if (a.number === 0) { return 1; }\n else if (b.number === 0) { return -1; }\n else {\n return a.number < b.number ? -1 : 1;\n }\n }\n\n sortChapters = (a: Chapter, b: Chapter) => {\n return parseFloat(a.number) - parseFloat(b.number);\n }\n\n mangaFormatToText(format: MangaFormat): string {\n if (this.mangaFormatKeys === undefined || this.mangaFormatKeys.length === 0) {\n this.mangaFormatKeys = Object.keys(MangaFormat);\n }\n\n return this.mangaFormatKeys.filter(item => MangaFormat[format] === item)[0];\n }\n\n /**\n * Formats a Chapter name based on the library it's in\n * @param libraryType \n * @param includeHash For comics only, includes a # which is used for numbering on cards\n * @param includeSpace Add a space at the end of the string. if includeHash and includeSpace are true, only hash will be at the end.\n * @returns \n */\n formatChapterName(libraryType: LibraryType, includeHash: boolean = false, includeSpace: boolean = false) {\n switch(libraryType) {\n case LibraryType.Book:\n return 'Book' + (includeSpace ? ' ' : '');\n case LibraryType.Comic:\n if (includeHash) {\n return 'Issue #';\n }\n return 'Issue' + (includeSpace ? ' ' : '');\n case LibraryType.Manga:\n return 'Chapter' + (includeSpace ? ' ' : '');\n }\n }\n\n cleanSpecialTitle(title: string) {\n let cleaned = title.replace(/_/g, ' ').replace(/SP\\d+/g, '').trim();\n cleaned = cleaned.substring(0, cleaned.lastIndexOf('.'));\n if (cleaned.trim() === '') {\n return title;\n }\n return cleaned;\n }\n\n filter(input: string, filter: string): boolean {\n if (input === null || filter === null) return false;\n const reg = /[_\\.\\-]/gi;\n return input.toUpperCase().replace(reg, '').includes(filter.toUpperCase().replace(reg, ''));\n }\n\n\n mangaFormat(format: MangaFormat): string {\n switch (format) {\n case MangaFormat.EPUB:\n return 'EPUB';\n case MangaFormat.ARCHIVE:\n return 'Archive';\n case MangaFormat.IMAGE:\n return 'Image';\n case MangaFormat.PDF:\n return 'PDF';\n case MangaFormat.UNKNOWN:\n return 'Unknown';\n }\n }\n\n mangaFormatIcon(format: MangaFormat): string {\n switch (format) {\n case MangaFormat.EPUB:\n return 'fa-book';\n case MangaFormat.ARCHIVE:\n return 'fa-file-archive';\n case MangaFormat.IMAGE:\n return 'fa-image';\n case MangaFormat.PDF:\n return 'fa-file-pdf';\n case MangaFormat.UNKNOWN:\n return 'fa-question';\n }\n }\n\n getLibraryTypeIcon(format: LibraryType) {\n switch (format) {\n case LibraryType.Book:\n return 'fa-book';\n case LibraryType.Comic:\n case LibraryType.Manga:\n return 'fa-book-open';\n }\n }\n\n isVolume(d: any) {\n return d != null && d.hasOwnProperty('chapters');\n }\n\n isChapter(d: any) {\n return d != null && d.hasOwnProperty('volumeId');\n }\n\n isSeries(d: any) {\n return d != null && d.hasOwnProperty('originalName');\n }\n\n asVolume(d: any) {\n return d;\n }\n\n asChapter(d: any) {\n return d;\n }\n\n asSeries(d: any) {\n return d;\n }\n\n getActiveBreakpoint(): Breakpoint {\n if (window.innerWidth <= Breakpoint.Mobile) return Breakpoint.Mobile;\n else if (window.innerWidth > Breakpoint.Mobile && window.innerWidth <= Breakpoint.Tablet) return Breakpoint.Tablet;\n else if (window.innerWidth > Breakpoint.Tablet) return Breakpoint.Desktop\n \n return Breakpoint.Desktop;\n }\n\n isInViewport(element: Element, additionalTopOffset: number = 0) {\n const rect = element.getBoundingClientRect();\n return (\n rect.top >= additionalTopOffset &&\n rect.left >= 0 &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n );\n }\n\n deepEqual(object1: any, object2: any) {\n const keys1 = Object.keys(object1);\n const keys2 = Object.keys(object2);\n if (keys1.length !== keys2.length) {\n return false;\n }\n for (const key of keys1) {\n const val1 = object1[key];\n const val2 = object2[key];\n const areObjects = this.isObject(val1) && this.isObject(val2);\n if (\n areObjects && !this.deepEqual(val1, val2) ||\n !areObjects && val1 !== val2\n ) {\n return false;\n }\n }\n return true;\n }\n private isObject(object: any) {\n return object != null && typeof object === 'object';\n }\n\n addPaginationIfExists(params: HttpParams, pageNum?: number, itemsPerPage?: number) {\n if (pageNum !== null && pageNum !== undefined && itemsPerPage !== null && itemsPerPage !== undefined) {\n params = params.append('pageNumber', pageNum + '');\n params = params.append('pageSize', itemsPerPage + '');\n }\n return params;\n }\n\n createPaginatedResult(response: any, paginatedVariable: PaginatedResult | undefined = undefined) {\n if (paginatedVariable === undefined) {\n paginatedVariable = new PaginatedResult();\n }\n if (response.body === null) {\n paginatedVariable.result = [];\n } else {\n paginatedVariable.result = response.body;\n }\n\n const pageHeader = response.headers?.get('Pagination');\n if (pageHeader !== null) {\n paginatedVariable.pagination = JSON.parse(pageHeader);\n }\n\n return paginatedVariable;\n }\n}\n","import { ConfirmButton } from './confirm-button';\n\nexport class ConfirmConfig {\n _type: string = 'confirm'; // internal only: confirm or alert (todo: use enum)\n header: string = 'Confirm';\n content: string = '';\n buttons: Array = [];\n}\n","\n\n
\n

{{config.header}}

\n \n
\n
\n
\n
\n
\n \n
\n \n
\n","import { Component, OnInit } from '@angular/core';\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\nimport { ConfirmButton } from './_models/confirm-button';\nimport { ConfirmConfig } from './_models/confirm-config';\n\n@Component({\n selector: 'app-confirm-dialog',\n templateUrl: './confirm-dialog.component.html',\n styleUrls: ['./confirm-dialog.component.scss']\n})\nexport class ConfirmDialogComponent implements OnInit {\n\n config!: ConfirmConfig;\n\n constructor(public modal: NgbActiveModal) {}\n\n ngOnInit(): void {\n if (this.config) {\n this.config.buttons.sort(this._button_sort);\n }\n }\n\n private _button_sort(x: ConfirmButton, y: ConfirmButton) {\n const xIsSecondary = x.type === 'secondary';\n const yIsSecondary = y.type === 'secondary';\n if (xIsSecondary && !yIsSecondary) {\n return -1;\n } else if (!xIsSecondary && yIsSecondary) {\n return 1;\n }\n return 0;\n }\n\n clickButton(button: ConfirmButton) {\n this.modal.close(button.type === 'primary');\n }\n\n close() {\n this.modal.close(false);\n }\n\n}\n","import { Injectable } from '@angular/core';\nimport { NgbModal } from '@ng-bootstrap/ng-bootstrap';\nimport { take } from 'rxjs/operators';\nimport { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component';\nimport { ConfirmConfig } from './confirm-dialog/_models/confirm-config';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class ConfirmService {\n\n defaultConfirm = new ConfirmConfig();\n defaultAlert = new ConfirmConfig();\n\n constructor(private modalService: NgbModal) {\n this.defaultConfirm.buttons.push({text: 'Cancel', type: 'secondary'});\n this.defaultConfirm.buttons.push({text: 'Confirm', type: 'primary'});\n\n this.defaultAlert._type = 'alert';\n this.defaultAlert.header = 'Alert';\n this.defaultAlert.buttons.push({text: 'Ok', type: 'primary'});\n\n }\n\n public async confirm(content?: string, config?: ConfirmConfig): Promise {\n\n return new Promise((resolve, reject) => {\n if (content === undefined && config === undefined) {\n console.error('Confirm must have either text or a config object passed');\n return reject(false);\n }\n\n if (content !== undefined && config === undefined) {\n config = this.defaultConfirm;\n config.content = content;\n }\n\n const modalRef = this.modalService.open(ConfirmDialogComponent);\n modalRef.componentInstance.config = config;\n modalRef.closed.pipe(take(1)).subscribe(result => {\n return resolve(result);\n });\n modalRef.dismissed.pipe(take(1)).subscribe(() => {\n return resolve(false);\n });\n });\n\n }\n\n public async alert(content?: string, config?: ConfirmConfig): Promise {\n return new Promise((resolve, reject) => {\n if (content === undefined && config === undefined) {\n console.error('Alert must have either text or a config object passed');\n return reject(false);\n }\n\n if (content !== undefined && config === undefined) {\n config = this.defaultConfirm;\n config.content = content;\n }\n\n const modalRef = this.modalService.open(ConfirmDialogComponent);\n modalRef.componentInstance.config = config;\n modalRef.closed.pipe(take(1)).subscribe(result => {\n return resolve(result);\n });\n modalRef.dismissed.pipe(take(1)).subscribe(() => {\n return resolve(false);\n });\n })\n }\n}\n","import { Component, ElementRef, Input, OnChanges, OnDestroy, OnInit, Renderer2, SimpleChanges, ViewChild } from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { CoverUpdateEvent } from 'src/app/_models/events/cover-update-event';\nimport { ImageService } from 'src/app/_services/image.service';\nimport { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';\n\n/**\n * This is used for images with placeholder fallback.\n */\n@Component({\n selector: 'app-image',\n templateUrl: './image.component.html',\n styleUrls: ['./image.component.scss']\n})\nexport class ImageComponent implements OnChanges, OnDestroy {\n\n /**\n * Source url to load image\n */\n @Input() imageUrl!: string;\n /**\n * Width of the image. If not defined, will not be applied\n */\n @Input() width: string = '';\n /**\n * Height of the image. If not defined, will not be applied\n */\n @Input() height: string = '';\n /**\n * Max Width of the image. If not defined, will not be applied\n */\n @Input() maxWidth: string = '';\n /**\n * Max Height of the image. If not defined, will not be applied\n */\n @Input() maxHeight: string = '';\n /**\n * Border Radius of the image. If not defined, will not be applied\n */\n @Input() borderRadius: string = '';\n\n @ViewChild('img', {static: true}) imgElem!: ElementRef;\n\n private readonly onDestroy = new Subject();\n\n constructor(public imageService: ImageService, private renderer: Renderer2, private hubService: MessageHubService) {\n this.hubService.messages$.pipe(takeUntil(this.onDestroy)).subscribe(res => {\n if (res.event === EVENTS.CoverUpdate) {\n const updateEvent = res.payload as CoverUpdateEvent;\n if (this.imageUrl === undefined || this.imageUrl === null || this.imageUrl === '') return;\n const enityType = this.imageService.getEntityTypeFromUrl(this.imageUrl);\n if (enityType === updateEvent.entityType) {\n const tokens = this.imageUrl.split('?')[1].split('&');\n\n //...seriesId=123&random=\n let id = tokens[0].replace(enityType + 'Id=', '');\n if (id.includes('&')) {\n id = id.split('&')[0];\n }\n if (id === (updateEvent.id + '')) {\n this.imageUrl = this.imageService.randomize(this.imageUrl);\n }\n }\n }\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (this.width != '') {\n this.renderer.setStyle(this.imgElem.nativeElement, 'width', this.width);\n }\n\n if (this.height != '') {\n this.renderer.setStyle(this.imgElem.nativeElement, 'height', this.height);\n }\n\n if (this.maxWidth != '') {\n this.renderer.setStyle(this.imgElem.nativeElement, 'max-width', this.maxWidth);\n }\n\n if (this.maxHeight != '') {\n this.renderer.setStyle(this.imgElem.nativeElement, 'max-height', this.maxHeight);\n }\n\n if (this.borderRadius != '') {\n this.renderer.setStyle(this.imgElem.nativeElement, 'border-radius', this.borderRadius);\n }\n }\n\n ngOnDestroy() {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n}\n","","\n  \n \n","import { Component, Input, OnInit } from '@angular/core';\nimport { MangaFormat } from 'src/app/_models/manga-format';\nimport { UtilityService } from '../_services/utility.service';\n\n@Component({\n selector: 'app-series-format',\n templateUrl: './series-format.component.html',\n styleUrls: ['./series-format.component.scss']\n})\nexport class SeriesFormatComponent implements OnInit {\n\n @Input() format: MangaFormat = MangaFormat.UNKNOWN;\n\n get MangaFormat(): typeof MangaFormat {\n return MangaFormat;\n }\n\n constructor(public utilityService: UtilityService) { }\n\n ngOnInit(): void {\n }\n\n}\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { NgbCollapseModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';\nimport { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component';\nimport { ReadMoreComponent } from './read-more/read-more.component';\nimport { RouterModule } from '@angular/router';\nimport { DrawerComponent } from './drawer/drawer.component';\nimport { TagBadgeComponent } from './tag-badge/tag-badge.component';\nimport { ShowIfScrollbarDirective } from './show-if-scrollbar.directive';\nimport { A11yClickDirective } from './a11y-click.directive';\nimport { SeriesFormatComponent } from './series-format/series-format.component';\nimport { UpdateNotificationModalComponent } from './update-notification/update-notification-modal.component';\nimport { CircularLoaderComponent } from './circular-loader/circular-loader.component';\nimport { NgCircleProgressModule } from 'ng-circle-progress';\nimport { PersonBadgeComponent } from './person-badge/person-badge.component';\nimport { BadgeExpanderComponent } from './badge-expander/badge-expander.component';\nimport { ImageComponent } from './image/image.component';\nimport { PipeModule } from '../pipe/pipe.module';\n\n@NgModule({\n declarations: [\n ConfirmDialogComponent,\n ReadMoreComponent,\n DrawerComponent,\n TagBadgeComponent,\n ShowIfScrollbarDirective,\n A11yClickDirective,\n SeriesFormatComponent,\n UpdateNotificationModalComponent,\n CircularLoaderComponent,\n PersonBadgeComponent,\n BadgeExpanderComponent,\n ImageComponent,\n ],\n imports: [\n CommonModule,\n RouterModule,\n ReactiveFormsModule,\n NgbCollapseModule,\n NgbTooltipModule, // TODO: Validate if we still need this\n PipeModule,\n NgCircleProgressModule.forRoot(),\n ],\n exports: [\n ReadMoreComponent, // Used globably\n DrawerComponent, // Can be replaced with boostrap offscreen canvas (v5) (also used in book reader and series metadata filter)\n A11yClickDirective, // Used globally\n SeriesFormatComponent, // Used globally\n TagBadgeComponent, // Used globally\n CircularLoaderComponent, // Used in Cards only\n ImageComponent, // Used globally\n\n ShowIfScrollbarDirective, // Used book reader only?\n\n PersonBadgeComponent, // Used Series Detail\n BadgeExpanderComponent, // Used Series Detail/Metadata\n \n ],\n})\nexport class SharedModule { }\n","
\n

New Update Available!

\n \n
\n
\n
{{updateData.updateTitle}}
\n
\n
\n\n
\n \n Download\n
","import { Component, Input, OnInit } from '@angular/core';\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\nimport { UpdateVersionEvent } from 'src/app/_models/events/update-version-event';\n\n\n\n@Component({\n selector: 'app-update-notification-modal',\n templateUrl: './update-notification-modal.component.html',\n styleUrls: ['./update-notification-modal.component.scss']\n})\nexport class UpdateNotificationModalComponent implements OnInit {\n\n @Input() updateData!: UpdateVersionEvent;\n\n\n constructor(public modal: NgbActiveModal) { }\n\n ngOnInit(): void {\n }\n\n close() {\n this.modal.close({success: false, series: undefined});\n }\n\n}\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { SideNavCompanionBarComponent } from './side-nav-companion-bar/side-nav-companion-bar.component';\nimport { SideNavItemComponent } from './side-nav-item/side-nav-item.component';\nimport { SideNavComponent } from './side-nav/side-nav.component';\nimport { PipeModule } from '../pipe/pipe.module';\nimport { CardsModule } from '../cards/cards.module';\nimport { FormsModule } from '@angular/forms';\nimport { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';\nimport { RouterModule } from '@angular/router';\n\n\n\n@NgModule({\n declarations: [\n SideNavCompanionBarComponent,\n SideNavItemComponent,\n SideNavComponent\n ],\n imports: [\n CommonModule,\n RouterModule,\n PipeModule,\n CardsModule,\n FormsModule,\n NgbTooltipModule,\n ],\n exports: [\n SideNavCompanionBarComponent,\n SideNavItemComponent,\n SideNavComponent\n ]\n})\nexport class SidenavModule { }\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { TypeaheadComponent } from './typeahead.component';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { SharedModule } from '../shared/shared.module';\nimport { PipeModule } from '../pipe/pipe.module';\n\n\n\n@NgModule({\n declarations: [\n TypeaheadComponent\n ],\n imports: [\n CommonModule,\n SharedModule,\n FormsModule,\n ReactiveFormsModule,\n PipeModule\n ],\n exports: [\n TypeaheadComponent\n ]\n})\nexport class TypeaheadModule { }\n","export const environment = {\n production: true,\n apiUrl: '/api/',\n hubUrl: '/hubs/'\n};\n","import { NgModule } from '@angular/core';\nimport { Routes, RouterModule, PreloadAllModules } from '@angular/router';\nimport { AuthGuard } from './_guards/auth.guard';\nimport { LibraryAccessGuard } from './_guards/library-access.guard';\nimport { AdminGuard } from './_guards/admin.guard';\n\n// TODO: Once we modularize the components, use this and measure performance impact: https://angular.io/guide/lazy-loading-ngmodules#preloading-modules\n// TODO: Use Prefetching of LazyLoaded Modules \nconst routes: Routes = [\n {\n path: 'admin',\n canActivate: [AdminGuard],\n loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)\n },\n {\n path: 'collections',\n canActivate: [AuthGuard],\n loadChildren: () => import('./collections/collections.module').then(m => m.CollectionsModule)\n },\n {\n path: 'preferences',\n canActivate: [AuthGuard],\n loadChildren: () => import('./user-settings/user-settings.module').then(m => m.UserSettingsModule)\n },\n {\n path: 'lists',\n canActivate: [AuthGuard],\n loadChildren: () => import('./reading-list/reading-list.module').then(m => m.ReadingListModule)\n },\n {\n path: 'registration',\n loadChildren: () => import('../app/registration/registration.module').then(m => m.RegistrationModule)\n },\n {\n path: 'announcements',\n loadChildren: () => import('../app/announcements/announcements.module').then(m => m.AnnouncementsModule)\n },\n {\n path: 'bookmarks',\n loadChildren: () => import('../app/bookmark/bookmark.module').then(m => m.BookmarkModule)\n },\n {\n path: 'all-series',\n loadChildren: () => import('../app/all-series/all-series.module').then(m => m.AllSeriesModule)\n },\n {\n path: 'libraries',\n loadChildren: () => import('../app/dashboard/dashboard.module').then(m => m.DashboardModule)\n },\n {\n path: 'library',\n runGuardsAndResolvers: 'always',\n canActivate: [AuthGuard, LibraryAccessGuard],\n children: [\n {\n path: ':libraryId', \n pathMatch: 'full',\n loadChildren: () => import('../app/library-detail/library-detail.module').then(m => m.LibraryDetailModule)\n },\n {\n path: ':libraryId/series/:seriesId', \n pathMatch: 'full',\n loadChildren: () => import('../app/series-detail/series-detail.module').then(m => m.SeriesDetailModule)\n },\n {\n path: ':libraryId/series/:seriesId/manga',\n loadChildren: () => import('../app/manga-reader/manga-reader.module').then(m => m.MangaReaderModule)\n },\n {\n path: ':libraryId/series/:seriesId/book',\n loadChildren: () => import('../app/book-reader/book-reader.module').then(m => m.BookReaderModule)\n },\n ]\n },\n {\n path: 'theme',\n loadChildren: () => import('../app/dev-only/dev-only.module').then(m => m.DevOnlyModule)\n },\n {path: 'login', loadChildren: () => import('../app/registration/registration.module').then(m => m.RegistrationModule)},\n {path: '**', pathMatch: 'full', redirectTo: 'libraries'},\n {path: '', pathMatch: 'full', redirectTo: 'libraries'},\n];\n\n@NgModule({\n imports: [RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled', preloadingStrategy: PreloadAllModules})],\n exports: [RouterModule]\n})\nexport class AppRoutingModule { }\n","
\n
\n
\n \n
\n Loading...\n
\n \n
\n
\n
\n
    \n 0\">\n
  • Series
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
  • Collections
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
  • Reading Lists
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
  • Libraries
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
  • Genres
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
  • Tags
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
  • People
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
  • Chapters
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
  • Files
  • \n
      \n
    • \n \n
    • \n
    \n
    \n\n 0\">\n
      \n
    • \n \n
    • \n
    \n\n
    \n
\n
\n\n
\n","import { Component, ContentChild, ElementRef, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';\nimport { FormControl, FormGroup } from '@angular/forms';\nimport { Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { KEY_CODES } from '../../shared/_services/utility.service';\nimport { SearchResultGroup } from '../../_models/search/search-result-group';\n\n@Component({\n selector: 'app-grouped-typeahead',\n templateUrl: './grouped-typeahead.component.html',\n styleUrls: ['./grouped-typeahead.component.scss']\n})\nexport class GroupedTypeaheadComponent implements OnInit, OnDestroy {\n /**\n * Unique id to tie with a label element\n */\n @Input() id: string = 'grouped-typeahead';\n /**\n * Minimum number of characters in input to trigger a search\n */\n @Input() minQueryLength: number = 0;\n /**\n * Initial value of the search model\n */\n @Input() initialValue: string = '';\n @Input() grouppedData: SearchResultGroup = new SearchResultGroup();\n /**\n * Placeholder for the input\n */\n @Input() placeholder: string = '';\n /**\n * Number of milliseconds after typing before triggering inputChanged for data fetching\n */\n @Input() debounceTime: number = 200;\n /**\n * Emits when the input changes from user interaction\n */\n @Output() inputChanged: EventEmitter = new EventEmitter();\n /**\n * Emits when something is clicked/selected\n */\n @Output() selected: EventEmitter = new EventEmitter();\n /**\n * Emits an event when the field is cleared\n */\n @Output() clearField: EventEmitter = new EventEmitter();\n /**\n * Emits when a change in the search field looses/gains focus\n */\n @Output() focusChanged: EventEmitter = new EventEmitter();\n\n @ViewChild('input') inputElem!: ElementRef;\n @ContentChild('itemTemplate') itemTemplate!: TemplateRef;\n @ContentChild('seriesTemplate') seriesTemplate: TemplateRef | undefined;\n @ContentChild('collectionTemplate') collectionTemplate: TemplateRef | undefined;\n @ContentChild('tagTemplate') tagTemplate: TemplateRef | undefined;\n @ContentChild('personTemplate') personTemplate: TemplateRef | undefined;\n @ContentChild('genreTemplate') genreTemplate!: TemplateRef;\n @ContentChild('noResultsTemplate') noResultsTemplate!: TemplateRef;\n @ContentChild('libraryTemplate') libraryTemplate!: TemplateRef;\n @ContentChild('readingListTemplate') readingListTemplate!: TemplateRef;\n @ContentChild('fileTemplate') fileTemplate!: TemplateRef;\n @ContentChild('chapterTemplate') chapterTemplate!: TemplateRef;\n \n\n hasFocus: boolean = false;\n isLoading: boolean = false;\n typeaheadForm: FormGroup = new FormGroup({});\n\n prevSearchTerm: string = '';\n\n private onDestroy: Subject = new Subject();\n\n get searchTerm() {\n return this.typeaheadForm.get('typeahead')?.value || '';\n }\n\n get hasData() {\n return !(this.noResultsTemplate != undefined && !this.grouppedData.persons.length && !this.grouppedData.collections.length \n && !this.grouppedData.series.length && !this.grouppedData.persons.length && !this.grouppedData.tags.length && !this.grouppedData.genres.length && !this.grouppedData.libraries.length\n && !this.grouppedData.files.length && !this.grouppedData.chapters.length);\n\n //return this.grouppedData.persons.length || this.grouppedData.collections.length || this.grouppedData.series.length || this.grouppedData.persons.length || this.grouppedData.tags.length || this.grouppedData.genres.length;\n }\n\n\n constructor() { }\n\n @HostListener('window:click', ['$event'])\n handleDocumentClick(event: any) {\n this.close();\n }\n\n @HostListener('window:keydown', ['$event'])\n handleKeyPress(event: KeyboardEvent) { \n if (!this.hasFocus) { return; }\n\n switch(event.key) {\n case KEY_CODES.ESC_KEY:\n this.close();\n event.stopPropagation();\n break;\n default:\n break;\n }\n }\n\n ngOnInit(): void {\n this.typeaheadForm.addControl('typeahead', new FormControl(this.initialValue, []));\n\n this.typeaheadForm.valueChanges.pipe(debounceTime(this.debounceTime), takeUntil(this.onDestroy)).subscribe(change => {\n const value = this.typeaheadForm.get('typeahead')?.value;\n\n if (value != undefined && value != '' && !this.hasFocus) {\n this.hasFocus = true;\n }\n\n if (value != undefined && value.length >= this.minQueryLength) {\n\n if (this.prevSearchTerm === value) return;\n this.inputChanged.emit(value);\n this.prevSearchTerm = value;\n }\n });\n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n onInputFocus(event: any) {\n if (event) {\n event.stopPropagation();\n event.preventDefault();\n }\n \n this.openDropdown();\n return this.hasFocus;\n }\n\n openDropdown() {\n setTimeout(() => {\n const model = this.typeaheadForm.get('typeahead');\n if (model) {\n model.setValue(model.value);\n }\n });\n }\n\n handleResultlick(item: any) {\n this.selected.emit(item);\n }\n\n resetField() {\n this.prevSearchTerm = '';\n this.typeaheadForm.get('typeahead')?.setValue(this.initialValue);\n this.clearField.emit();\n }\n\n\n close(event?: FocusEvent) {\n if (event) {\n // If the user is tabbing out of the input field, check if there are results first before closing\n if (this.hasData) {\n return;\n }\n }\n if (this.searchTerm === '') {\n this.resetField();\n }\n this.hasFocus = false;\n this.focusChanged.emit(this.hasFocus);\n }\n\n open(event?: FocusEvent) {\n this.hasFocus = true;\n this.focusChanged.emit(this.hasFocus);\n }\n\n public clear() {\n this.prevSearchTerm = '';\n this.typeaheadForm.get('typeahead')?.setValue(this.initialValue);\n }\n\n}\n","\n \n \n\n \n
    \n\n \n
  • \n
    Title goes here
    \n
    Subtitle goes here
    \n
    \n
    \n
    \n
    \n
    \n
  • \n
  • \n
    Title goes here
    \n
    Subtitle goes here
    \n
  • \n
  • \n
    \n
    Scanning Books
    \n
    E:\\\\Books\\\\Demon King Daimaou\\\\Demon King Daimaou - Volume 11.epub
    \n
    \n
    {{prettyPrintProgress(0.1)}}%
    \n
    \n
    \n
    \n
    \n\n
    \n
  • \n
  • \n
    \n
    There was some library scan error
    \n
    Click for more information
    \n
    \n \n
  • \n
    \n \n \n \n
  • \n
    {{message.title}}
    \n
    {{message.subTitle}}
    \n
    \n
    \n
    \n
    \n
    \n
  • \n \n
  • \n
    {{message.title}}
    \n
    {{message.subTitle}}
    \n
    \n
    {{prettyPrintProgress(message.body.progress) + '%'}}
    \n
    \n
    \n
    \n
    \n
  • \n
    \n
    \n
    \n\n \n \n \n
  • \n  Update available\n
  • \n
  • \n
    {{singleUpdate.title}}
    \n
    {{singleUpdate.subTitle}}
    \n
  • \n
    \n
    \n\n \n \n \n
  • \n
    \n
    {{error.title}}
    \n
    Click for more information
    \n
    \n \n
  • \n
    \n
    \n\n \n \n
  • 1\">\n
    {{onlineUsers.length}} Users online
    \n
  • \n
  • Not much going on here
  • \n
  • Active Events: {{activeEvents}}
  • \n
    \n
\n
\n
","import { Component, Input, OnDestroy, OnInit } from '@angular/core';\nimport { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';\nimport { BehaviorSubject, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { ConfirmConfig } from 'src/app/shared/confirm-dialog/_models/confirm-config';\nimport { ConfirmService } from 'src/app/shared/confirm.service';\nimport { UpdateNotificationModalComponent } from 'src/app/shared/update-notification/update-notification-modal.component';\nimport { ErrorEvent } from 'src/app/_models/events/error-event';\nimport { NotificationProgressEvent } from 'src/app/_models/events/notification-progress-event';\nimport { UpdateVersionEvent } from 'src/app/_models/events/update-version-event';\nimport { User } from 'src/app/_models/user';\nimport { AccountService } from 'src/app/_services/account.service';\nimport { EVENTS, Message, MessageHubService } from 'src/app/_services/message-hub.service';\n\n@Component({\n selector: 'app-nav-events-toggle',\n templateUrl: './events-widget.component.html',\n styleUrls: ['./events-widget.component.scss']\n})\nexport class EventsWidgetComponent implements OnInit, OnDestroy {\n @Input() user!: User;\n\n isAdmin: boolean = false;\n\n private readonly onDestroy = new Subject();\n\n /**\n * Progress events (Event Type: 'started', 'ended', 'updated' that have progress property)\n */\n progressEventsSource = new BehaviorSubject([]);\n progressEvents$ = this.progressEventsSource.asObservable();\n\n singleUpdateSource = new BehaviorSubject([]);\n singleUpdates$ = this.singleUpdateSource.asObservable();\n\n errorSource = new BehaviorSubject([]);\n errors$ = this.errorSource.asObservable();\n\n private updateNotificationModalRef: NgbModalRef | null = null;\n\n activeEvents: number = 0;\n\n debugMode: boolean = false;\n\n\n get EVENTS() {\n return EVENTS;\n }\n\n constructor(public messageHub: MessageHubService, private modalService: NgbModal, \n private accountService: AccountService, private confirmService: ConfirmService) { }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n this.progressEventsSource.complete();\n this.singleUpdateSource.complete();\n this.errorSource.complete();\n }\n\n ngOnInit(): void {\n // Debounce for testing. Kavita's too fast\n this.messageHub.messages$.pipe(takeUntil(this.onDestroy)).subscribe(event => {\n if (event.event === EVENTS.NotificationProgress) {\n this.processNotificationProgressEvent(event);\n } else if (event.event === EVENTS.Error) {\n const values = this.errorSource.getValue();\n values.push(event.payload as ErrorEvent);\n this.errorSource.next(values);\n this.activeEvents += 1;\n }\n });\n this.accountService.currentUser$.pipe(takeUntil(this.onDestroy)).subscribe(user => {\n if (user) {\n this.isAdmin = this.accountService.hasAdminRole(user);\n } else {\n this.isAdmin = false;\n }\n });\n }\n\n processNotificationProgressEvent(event: Message) {\n const message = event.payload as NotificationProgressEvent;\n let data;\n let index = -1;\n switch (event.payload.eventType) {\n case 'single':\n const values = this.singleUpdateSource.getValue();\n values.push(message);\n this.singleUpdateSource.next(values);\n this.activeEvents += 1;\n break;\n case 'started':\n // Sometimes we can receive 2 started on long running scans, so better to just treat as a merge then.\n data = this.mergeOrUpdate(this.progressEventsSource.getValue(), message);\n this.progressEventsSource.next(data);\n break;\n case 'updated':\n data = this.mergeOrUpdate(this.progressEventsSource.getValue(), message);\n this.progressEventsSource.next(data);\n break;\n case 'ended':\n data = this.progressEventsSource.getValue();\n data = data.filter(m => m.name !== message.name);\n this.progressEventsSource.next(data);\n this.activeEvents = Math.max(this.activeEvents - 1, 0);\n break;\n default:\n break;\n }\n }\n\n private mergeOrUpdate(data: NotificationProgressEvent[], message: NotificationProgressEvent) {\n const index = data.findIndex(m => m.name === message.name);\n // Sometimes we can receive 2 started on long running scans, so better to just treat as a merge then.\n if (index < 0) {\n data.push(message);\n this.activeEvents += 1;\n } else {\n data[index] = message;\n }\n return data;\n }\n\n\n handleUpdateAvailableClick(message: NotificationProgressEvent) {\n if (this.updateNotificationModalRef != null) { return; }\n this.updateNotificationModalRef = this.modalService.open(UpdateNotificationModalComponent, { scrollable: true, size: 'lg' });\n this.updateNotificationModalRef.componentInstance.updateData = message.body as UpdateVersionEvent;\n this.updateNotificationModalRef.closed.subscribe(() => {\n this.updateNotificationModalRef = null;\n });\n this.updateNotificationModalRef.dismissed.subscribe(() => {\n this.updateNotificationModalRef = null;\n });\n }\n\n async seeMoreError(error: ErrorEvent) {\n const config = new ConfirmConfig();\n config.buttons = [\n {text: 'Dismiss', type: 'primary'},\n {text: 'Ok', type: 'secondary'},\n ];\n config.header = error.title;\n config.content = error.subTitle;\n var result = await this.confirmService.alert(error.subTitle || error.title, config);\n if (result) {\n this.removeError(error);\n }\n }\n\n removeError(error: ErrorEvent, event?: MouseEvent) {\n if (event) {\n event.stopPropagation();\n event.preventDefault();\n }\n let data = this.errorSource.getValue();\n data = data.filter(m => m !== error); \n this.errorSource.next(data);\n this.activeEvents = Math.max(this.activeEvents - 1, 0);\n }\n\n prettyPrintProgress(progress: number) {\n return Math.trunc(progress * 100);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersonRole } from '../_models/person';\n\n@Pipe({\n name: 'personRole'\n})\nexport class PersonRolePipe implements PipeTransform {\n\n transform(value: PersonRole): string {\n switch (value) {\n case PersonRole.Artist: return 'Artist';\n case PersonRole.Character: return 'Character';\n case PersonRole.Colorist: return 'Colorist';\n case PersonRole.CoverArtist: return 'Cover Artist';\n case PersonRole.Editor: return 'Editor';\n case PersonRole.Inker: return 'Inker';\n case PersonRole.Letterer: return 'Letterer';\n case PersonRole.Penciller: return 'Penciller';\n case PersonRole.Publisher: return 'Publisher';\n case PersonRole.Writer: return 'Writer';\n case PersonRole.Other: return '';\n default: return '';\n }\n }\n\n}\n","\n ","import { DOCUMENT } from '@angular/common';\nimport { Component, HostListener, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { Chapter } from 'src/app/_models/chapter';\nimport { MangaFile } from 'src/app/_models/manga-file';\nimport { ScrollService } from 'src/app/_services/scroll.service';\nimport { SeriesService } from 'src/app/_services/series.service';\nimport { FilterQueryParam } from '../../shared/_services/filter-utilities.service';\nimport { CollectionTag } from '../../_models/collection-tag';\nimport { Library } from '../../_models/library';\nimport { PersonRole } from '../../_models/person';\nimport { ReadingList } from '../../_models/reading-list';\nimport { SearchResult } from '../../_models/search-result';\nimport { SearchResultGroup } from '../../_models/search/search-result-group';\nimport { AccountService } from '../../_services/account.service';\nimport { ImageService } from '../../_services/image.service';\nimport { LibraryService } from '../../_services/library.service';\nimport { NavService } from '../../_services/nav.service';\n\n@Component({\n selector: 'app-nav-header',\n templateUrl: './nav-header.component.html',\n styleUrls: ['./nav-header.component.scss']\n})\nexport class NavHeaderComponent implements OnInit, OnDestroy {\n\n @ViewChild('search') searchViewRef!: any;\n\n isLoading = false;\n debounceTime = 300;\n imageStyles = {width: '24px', 'margin-top': '5px'};\n searchResults: SearchResultGroup = new SearchResultGroup();\n searchTerm = '';\n customFilter: (items: SearchResult[], query: string) => SearchResult[] = (items: SearchResult[], query: string) => {\n const normalizedQuery = query.trim().toLowerCase();\n const matches = items.filter(item => {\n const normalizedSeriesName = item.name.toLowerCase().trim();\n const normalizedOriginalName = item.originalName.toLowerCase().trim();\n const normalizedLocalizedName = item.localizedName.toLowerCase().trim();\n return normalizedSeriesName.indexOf(normalizedQuery) >= 0 || normalizedOriginalName.indexOf(normalizedQuery) >= 0 || normalizedLocalizedName.indexOf(normalizedQuery) >= 0;\n });\n return matches;\n };\n\n\n backToTopNeeded = false;\n searchFocused: boolean = false;\n private readonly onDestroy = new Subject();\n\n constructor(public accountService: AccountService, private router: Router, public navService: NavService,\n private libraryService: LibraryService, public imageService: ImageService, @Inject(DOCUMENT) private document: Document,\n private scrollService: ScrollService, private seriesService: SeriesService) { }\n\n ngOnInit(): void {}\n\n @HostListener('body:scroll', [])\n checkBackToTopNeeded() {\n const offset = this.scrollService.scrollPosition;\n if (offset > 100) {\n this.backToTopNeeded = true;\n } else if (offset < 40) {\n this.backToTopNeeded = false;\n }\n }\n\n ngOnDestroy() {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n logout() {\n this.accountService.logout();\n this.navService.hideNavBar();\n this.navService.hideSideNav();\n this.router.navigateByUrl('/login');\n }\n\n moveFocus() {\n this.document.getElementById('content')?.focus();\n }\n\n\n\n onChangeSearch(val: string) {\n this.isLoading = true;\n this.searchTerm = val.trim();\n\n this.libraryService.search(val.trim()).pipe(takeUntil(this.onDestroy)).subscribe(results => {\n this.searchResults = results;\n this.isLoading = false;\n }, err => {\n this.searchResults.reset();\n this.isLoading = false;\n this.searchTerm = '';\n });\n }\n\n goTo(queryParamName: string, filter: any) {\n let params: any = {};\n params[queryParamName] = filter;\n params[FilterQueryParam.Page] = 1;\n this.clearSearch();\n this.router.navigate(['all-series'], {queryParams: params});\n }\n\n goToPerson(role: PersonRole, filter: any) {\n this.clearSearch();\n switch(role) {\n case PersonRole.Writer:\n this.goTo(FilterQueryParam.Writers, filter);\n break;\n case PersonRole.Artist:\n this.goTo(FilterQueryParam.Artists, filter);\n break;\n case PersonRole.Character:\n this.goTo(FilterQueryParam.Character, filter);\n break;\n case PersonRole.Colorist:\n this.goTo(FilterQueryParam.Colorist, filter);\n break;\n case PersonRole.Editor:\n this.goTo(FilterQueryParam.Editor, filter);\n break;\n case PersonRole.Inker:\n this.goTo(FilterQueryParam.Inker, filter);\n break;\n case PersonRole.CoverArtist:\n this.goTo(FilterQueryParam.CoverArtists, filter);\n break;\n case PersonRole.Letterer:\n this.goTo(FilterQueryParam.Letterer, filter);\n break;\n case PersonRole.Penciller:\n this.goTo(FilterQueryParam.Penciller, filter);\n break;\n case PersonRole.Publisher:\n this.goTo(FilterQueryParam.Publisher, filter);\n break;\n case PersonRole.Translator:\n this.goTo(FilterQueryParam.Translator, filter);\n break;\n }\n }\n\n clearSearch() {\n this.searchViewRef.clear();\n this.searchTerm = '';\n this.searchResults = new SearchResultGroup();\n }\n\n clickSeriesSearchResult(item: SearchResult) {\n this.clearSearch();\n const libraryId = item.libraryId;\n const seriesId = item.seriesId;\n this.router.navigate(['library', libraryId, 'series', seriesId]);\n }\n\n clickFileSearchResult(item: MangaFile) {\n this.clearSearch();\n this.seriesService.getSeriesForMangaFile(item.id).subscribe(series => {\n if (series !== undefined && series !== null) {\n this.router.navigate(['library', series.libraryId, 'series', series.id]);\n }\n })\n }\n\n clickChapterSearchResult(item: Chapter) {\n this.clearSearch();\n this.seriesService.getSeriesForChapter(item.id).subscribe(series => {\n if (series !== undefined && series !== null) {\n this.router.navigate(['library', series.libraryId, 'series', series.id]);\n }\n })\n }\n\n clickLibraryResult(item: Library) {\n this.router.navigate(['library', item.id]);\n }\n\n clickCollectionSearchResult(item: CollectionTag) {\n this.clearSearch();\n this.router.navigate(['collections', item.id]);\n }\n\n clickReadingListSearchResult(item: ReadingList) {\n this.clearSearch();\n this.router.navigate(['lists', item.id]);\n }\n\n\n scrollToTop() {\n this.scrollService.scrollTo(0, this.document.body);\n }\n\n focusUpdate(searchFocused: boolean) {\n this.searchFocused = searchFocused\n return searchFocused;\n }\n\n hideSideNav() {\n this.navService.toggleSideNav();\n }\n}\n","\n
\n \n
\n
\n\n\n \n \n \n\n\n\n\n
\n \n
\n \n
\n
\n \n
\n {{title}}\n
\n
\n \n \n \n
","import { Component, Input, OnDestroy, OnInit } from '@angular/core';\nimport { NavigationEnd, Router } from '@angular/router';\nimport { filter, map, Subject, takeUntil } from 'rxjs';\nimport { NavService } from '../../_services/nav.service';\n\n@Component({\n selector: 'app-side-nav-item',\n templateUrl: './side-nav-item.component.html',\n styleUrls: ['./side-nav-item.component.scss']\n})\nexport class SideNavItemComponent implements OnInit, OnDestroy {\n /**\n * Icon to display next to item. ie) 'fa-home'\n */\n @Input() icon: string = '';\n /**\n * Text for the item\n */\n @Input() title: string = '';\n\n /**\n * If a link should be generated when clicked. By default (undefined), no link will be generated\n */\n @Input() link: string | undefined;\n\n @Input() comparisonMethod: 'startsWith' | 'equals' = 'equals';\n\n\n highlighted = false;\n private onDestroy: Subject = new Subject();\n \n constructor(public navService: NavService, private router: Router) {\n router.events\n .pipe(filter(event => event instanceof NavigationEnd), \n takeUntil(this.onDestroy),\n map(evt => evt as NavigationEnd))\n .subscribe((evt: NavigationEnd) => {\n this.updateHightlight(evt.url.split('?')[0]);\n });\n }\n\n ngOnInit(): void {\n setTimeout(() => {\n this.updateHightlight(this.router.url.split('?')[0]);\n }, 100);\n \n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n updateHightlight(page: string) {\n if (this.link === undefined) {\n this.highlighted = false;\n return;\n }\n\n if (!page.endsWith('/')) {\n page = page + '/';\n }\n\n if (this.comparisonMethod === 'equals' && page === this.link) {\n this.highlighted = true;\n return;\n }\n if (this.comparisonMethod === 'startsWith' && page.startsWith(this.link)) {\n this.highlighted = true;\n return;\n }\n\n this.highlighted = false;\n }\n\n}\n","\n
\n \n\n \n \n \n \n \n
10\">\n \n
\n \n \n
\n
\n \n \n \n \n \n
\n
\n
","import { Component, OnDestroy, OnInit } from '@angular/core';\nimport { NavigationEnd, Router } from '@angular/router';\nimport { Observable, Subject } from 'rxjs';\nimport { filter, map, take, takeUntil, takeWhile } from 'rxjs/operators';\nimport { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';\nimport { Breakpoint, UtilityService } from '../../shared/_services/utility.service';\nimport { Library } from '../../_models/library';\nimport { User } from '../../_models/user';\nimport { AccountService } from '../../_services/account.service';\nimport { Action, ActionFactoryService, ActionItem } from '../../_services/action-factory.service';\nimport { ActionService } from '../../_services/action.service';\nimport { LibraryService } from '../../_services/library.service';\nimport { NavService } from '../../_services/nav.service';\n\n@Component({\n selector: 'app-side-nav',\n templateUrl: './side-nav.component.html',\n styleUrls: ['./side-nav.component.scss']\n})\nexport class SideNavComponent implements OnInit, OnDestroy {\n\n user: User | undefined;\n libraries: Library[] = [];\n isAdmin = false;\n actions: ActionItem[] = [];\n\n filterQuery: string = '';\n filterLibrary = (library: Library) => {\n return library.name.toLowerCase().indexOf((this.filterQuery || '').toLowerCase()) >= 0;\n }\n\n private onDestroy: Subject = new Subject();\n\n\n constructor(public accountService: AccountService, private libraryService: LibraryService,\n public utilityService: UtilityService, private messageHub: MessageHubService,\n private actionFactoryService: ActionFactoryService, private actionService: ActionService, public navService: NavService, private router: Router) { }\n\n ngOnInit(): void {\n this.accountService.currentUser$.pipe(take(1)).subscribe(user => {\n this.user = user;\n\n if (this.user) {\n this.isAdmin = this.accountService.hasAdminRole(this.user);\n }\n this.libraryService.getLibrariesForMember().pipe(take(1)).subscribe((libraries: Library[]) => {\n this.libraries = libraries;\n });\n this.actions = this.actionFactoryService.getLibraryActions(this.handleAction.bind(this));\n });\n\n this.messageHub.messages$.pipe(takeUntil(this.onDestroy), filter(event => event.event === EVENTS.LibraryModified)).subscribe(event => {\n this.libraryService.getLibrariesForMember().pipe(take(1)).subscribe((libraries: Library[]) => {\n this.libraries = libraries;\n });\n });\n\n this.router.events\n .pipe(filter(event => event instanceof NavigationEnd), \n takeUntil(this.onDestroy),\n map(evt => evt as NavigationEnd))\n .subscribe((evt: NavigationEnd) => {\n if (this.utilityService.getActiveBreakpoint() < Breakpoint.Tablet) {\n // collapse side nav\n this.navService.sideNavCollapsed$.pipe(take(1)).subscribe(collapsed => {\n if (!collapsed) {\n this.navService.toggleSideNav();\n }\n });\n }\n });\n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n\n handleAction(action: Action, library: Library) {\n switch (action) {\n case(Action.ScanLibrary):\n this.actionService.scanLibrary(library);\n break;\n case(Action.RefreshMetadata):\n this.actionService.refreshMetadata(library);\n break;\n default:\n break;\n }\n }\n\n\n performAction(action: ActionItem, library: Library) {\n if (typeof action.callback === 'function') {\n action.callback(action.action, library);\n }\n }\n\n}","\n
\n \n \n
\n
\n
\n \n
\n
\n \n \n \n
\n \n
\n","import { Component, HostListener, Inject, OnInit } from '@angular/core';\nimport { NavigationStart, Router } from '@angular/router';\nimport { take } from 'rxjs/operators';\nimport { AccountService } from './_services/account.service';\nimport { LibraryService } from './_services/library.service';\nimport { MessageHubService } from './_services/message-hub.service';\nimport { NavService } from './_services/nav.service';\nimport { filter } from 'rxjs/operators';\nimport { NgbModal, NgbRatingConfig } from '@ng-bootstrap/ng-bootstrap';\nimport { DOCUMENT } from '@angular/common';\n\n@Component({\n selector: 'app-root',\n templateUrl: './app.component.html',\n styleUrls: ['./app.component.scss']\n})\nexport class AppComponent implements OnInit {\n\n constructor(private accountService: AccountService, public navService: NavService, \n private messageHub: MessageHubService, private libraryService: LibraryService, \n router: Router, private ngbModal: NgbModal, ratingConfig: NgbRatingConfig, \n @Inject(DOCUMENT) private document: Document) {\n\n // Setup default rating config\n ratingConfig.max = 5;\n ratingConfig.resettable = true;\n \n // Close any open modals when a route change occurs\n router.events\n .pipe(filter(event => event instanceof NavigationStart))\n .subscribe((event) => {\n if (this.ngbModal.hasOpenModals()) {\n this.ngbModal.dismissAll();\n }\n });\n }\n\n @HostListener('window:resize', ['$event'])\n onResize(){\n this.setDocHeight();\n }\n\n @HostListener('window:orientationchange', ['$event'])\n onOrientationChange() {\n this.setDocHeight();\n }\n\n ngOnInit(): void {\n this.setCurrentUser();\n this.setDocHeight();\n }\n\n setCurrentUser() {\n const user = this.accountService.getUserFromLocalStorage();\n this.accountService.setCurrentUser(user);\n\n if (user) {\n this.messageHub.createHubConnection(user, this.accountService.hasAdminRole(user));\n this.libraryService.getLibraryNames().pipe(take(1)).subscribe(() => {/* No Operation */});\n } \n }\n\n setDocHeight() {\n // Sets a CSS variable for the actual device viewport height. Needed for mobile dev.\n let vh = window.innerHeight * 0.01;\n this.document.documentElement.style.setProperty('--vh', `${vh}px`);\n }\n}\n","import { Injectable } from '@angular/core';\nimport {\n HttpRequest,\n HttpHandler,\n HttpEvent,\n HttpInterceptor\n} from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { AccountService } from '../_services/account.service';\nimport { take } from 'rxjs/operators';\n\n@Injectable()\nexport class JwtInterceptor implements HttpInterceptor {\n\n constructor(private accountService: AccountService) {}\n\n intercept(request: HttpRequest, next: HttpHandler): Observable> {\n\n // Take 1 means we don't have to unsubscribe because we take 1 then complete\n this.accountService.currentUser$.pipe(take(1)).subscribe(user => {\n if (user) {\n request = request.clone({\n setHeaders: {\n Authorization: `Bearer ${user.token}`\n }\n });\n }\n });\n\n return next.handle(request);\n }\n}\n","import { Injectable } from '@angular/core';\nimport {\n HttpRequest,\n HttpHandler,\n HttpEvent,\n HttpInterceptor\n} from '@angular/common/http';\nimport { Observable, throwError } from 'rxjs';\nimport { Router } from '@angular/router';\nimport { ToastrService } from 'ngx-toastr';\nimport { catchError } from 'rxjs/operators';\nimport { AccountService } from '../_services/account.service';\n\n@Injectable()\nexport class ErrorInterceptor implements HttpInterceptor {\n\n constructor(private router: Router, private toastr: ToastrService, private accountService: AccountService) {}\n\n\n intercept(request: HttpRequest, next: HttpHandler): Observable> {\n return next.handle(request).pipe(\n catchError(error => {\n if (error === undefined || error === null) {\n return throwError(error);\n }\n\n switch (error.status) {\n case 400:\n this.handleValidationError(error);\n break;\n case 401:\n this.handleAuthError(error);\n break;\n case 404:\n this.handleNotFound(error);\n break;\n case 500:\n this.handleServerException(error);\n break;\n default:\n // Don't throw multiple Something undexpected went wrong\n if (this.toastr.previousToastMessage !== 'Something unexpected went wrong.') {\n this.toastr.error('Something unexpected went wrong.');\n }\n break;\n }\n return throwError(error);\n })\n );\n }\n\n private handleValidationError(error: any) {\n // This 400 can also be a bad request \n if (Array.isArray(error.error)) {\n const modalStateErrors: any[] = [];\n if (error.error.length > 0 && error.error[0].hasOwnProperty('message')) {\n if (error.error[0].details === null) {\n error.error.forEach((issue: {status: string, details: string, message: string}) => {\n modalStateErrors.push(issue.message);\n });\n } else {\n error.error.forEach((issue: {status: string, details: string, message: string}) => {\n modalStateErrors.push(issue.details);\n });\n }\n } else {\n error.error.forEach((issue: {code: string, description: string}) => {\n modalStateErrors.push(issue.description);\n });\n }\n throw modalStateErrors.flat();\n } else if (error.error.errors) {\n // Validation error\n const modalStateErrors = [];\n for (const key in error.error.errors) {\n if (error.error.errors[key]) {\n modalStateErrors.push(error.error.errors[key]);\n }\n }\n throw modalStateErrors.flat();\n } else {\n console.error('error:', error);\n if (error.statusText === 'Bad Request') {\n if (error.error instanceof Blob) {\n this.toastr.error('There was an issue downloading this file or you do not have permissions', error.status); \n return; \n }\n this.toastr.error(error.error, error.status);\n } else {\n this.toastr.error(error.statusText === 'OK' ? error.error : error.statusText, error.status);\n }\n }\n }\n\n private handleNotFound(error: any) {\n this.toastr.error('That url does not exist.'); \n }\n\n private handleServerException(error: any) {\n const err = error.error;\n if (err.hasOwnProperty('message') && err.message.trim() !== '') {\n if (err.message != 'User is not authenticated') {\n console.error('500 error: ', error);\n }\n this.toastr.error(err.message);\n } else if (error.hasOwnProperty('message') && error.message.trim() !== '') {\n if (error.message != 'User is not authenticated') {\n console.error('500 error: ', error);\n }\n this.toastr.error(error.message);\n }\n else {\n this.toastr.error('There was an unknown critical error.');\n console.error('500 error:', error);\n }\n }\n\n private handleAuthError(error: any) {\n\n // Special hack for register url, to not care about auth\n if (location.href.includes('/registration/confirm-email?token=')) {\n return;\n }\n // NOTE: Signin has error.error or error.statusText available. \n // if statement is due to http/2 spec issue: https://github.com/angular/angular/issues/23334\n this.accountService.logout();\n this.router.navigateByUrl('/login');\n }\n}\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { EventsWidgetComponent } from './events-widget/events-widget.component';\nimport { GroupedTypeaheadComponent } from './grouped-typeahead/grouped-typeahead.component';\nimport { NavHeaderComponent } from './nav-header/nav-header.component';\nimport { NgbDropdownModule, NgbPopoverModule, NgbNavModule } from '@ng-bootstrap/ng-bootstrap';\nimport { SharedModule } from '../shared/shared.module';\nimport { PipeModule } from '../pipe/pipe.module';\nimport { TypeaheadModule } from '../typeahead/typeahead.module';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { RouterModule } from '@angular/router';\n\n\n\n@NgModule({\n declarations: [\n NavHeaderComponent,\n EventsWidgetComponent,\n GroupedTypeaheadComponent,\n ],\n imports: [\n CommonModule,\n ReactiveFormsModule,\n RouterModule,\n\n NgbDropdownModule,\n NgbPopoverModule,\n NgbNavModule,\n\n SharedModule, // app image, series-format\n PipeModule,\n TypeaheadModule,\n ],\n exports: [\n NavHeaderComponent,\n SharedModule\n ]\n})\nexport class NavModule { }\n","import { BrowserModule, Title } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\n\nimport { AppRoutingModule } from './app-routing.module';\nimport { AppComponent } from './app.component';\nimport { BrowserAnimationsModule } from '@angular/platform-browser/animations';\nimport { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';\nimport { JwtInterceptor } from './_interceptors/jwt.interceptor';\nimport { ToastrModule } from 'ngx-toastr';\nimport { ErrorInterceptor } from './_interceptors/error.interceptor';\n\nimport { SAVER, getSaver } from './shared/_providers/saver.provider';\nimport { SidenavModule } from './sidenav/sidenav.module';\nimport { NavModule } from './nav/nav.module';\n\n\n\n\n@NgModule({\n declarations: [\n AppComponent,\n ],\n imports: [\n HttpClientModule,\n BrowserModule,\n AppRoutingModule,\n BrowserAnimationsModule,\n\n SidenavModule,\n NavModule,\n\n ToastrModule.forRoot({\n positionClass: 'toast-bottom-right',\n preventDuplicates: true,\n timeOut: 6000,\n countDuplicates: true,\n autoDismiss: true\n }),\n ],\n providers: [\n {provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true},\n {provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true},\n Title,\n {provide: SAVER, useFactory: getSaver},\n ],\n entryComponents: [],\n bootstrap: [AppComponent]\n})\nexport class AppModule { }\n","import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\n\nif (environment.production) {\n enableProdMode();\n}\n\n// function fetchConfig(): Promise {\n// return fetch(environment.apiUrl + 'settings/base-url')\n// .then(response => response.text())\n// .then(response => new ConfigData(response));\n// }\n\n// fetchConfig().then(config => {\n \n// });\nplatformBrowserDynamic().bootstrapModule(AppModule)\n .catch(err => console.error(err));"],"sourceRoot":"webpack:///","file":"main.a45c1f50fcf01c1a.js"}