
* Added trackby so when series scan event comes through, cards can update too * Added chapter boundary toasts on book reader * Handle closing the reader when in a reading list * Somehow the trackby save didn't happen * Fixed an issue where after opening a chapter info modal, then trying to open another in specials tab it would fail due to a pass by reference issue with our factory. * When a series update occurs, if we loose specials tab, but we were on it, reselect volumes/chapters tab * Fixed an issue where older releases would show as available, even though they were already installed. * Converted tabs within modals to use vertical orientation (except on mobile) * Implemented webp support. Only Safari does not support this format natively. MacOS users can use an alternative browser. * Refactored ScannerService and MetadataService to be fully async
290 lines
7.6 KiB
TypeScript
290 lines
7.6 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
import { Chapter } from '../_models/chapter';
|
|
import { CollectionTag } from '../_models/collection-tag';
|
|
import { Library } from '../_models/library';
|
|
import { MangaFormat } from '../_models/manga-format';
|
|
import { ReadingList } from '../_models/reading-list';
|
|
import { Series } from '../_models/series';
|
|
import { Volume } from '../_models/volume';
|
|
import { AccountService } from './account.service';
|
|
|
|
export enum Action {
|
|
MarkAsRead = 0,
|
|
MarkAsUnread = 1,
|
|
ScanLibrary = 2,
|
|
Delete = 3,
|
|
Edit = 4,
|
|
Info = 5,
|
|
RefreshMetadata = 6,
|
|
Download = 7,
|
|
Bookmarks = 8,
|
|
IncognitoRead = 9,
|
|
AddToReadingList = 10
|
|
}
|
|
|
|
export interface ActionItem<T> {
|
|
title: string;
|
|
action: Action;
|
|
callback: (action: Action, data: T) => void;
|
|
requiresAdmin: boolean;
|
|
}
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class ActionFactoryService {
|
|
|
|
libraryActions: Array<ActionItem<Library>> = [];
|
|
|
|
seriesActions: Array<ActionItem<Series>> = [];
|
|
|
|
volumeActions: Array<ActionItem<Volume>> = [];
|
|
|
|
chapterActions: Array<ActionItem<Chapter>> = [];
|
|
|
|
collectionTagActions: Array<ActionItem<CollectionTag>> = [];
|
|
|
|
readingListActions: Array<ActionItem<ReadingList>> = [];
|
|
|
|
isAdmin = false;
|
|
hasDownloadRole = false;
|
|
|
|
constructor(private accountService: AccountService) {
|
|
this.accountService.currentUser$.subscribe(user => {
|
|
if (user) {
|
|
this.isAdmin = this.accountService.hasAdminRole(user);
|
|
this.hasDownloadRole = this.accountService.hasDownloadRole(user);
|
|
} else {
|
|
this._resetActions();
|
|
return; // If user is logged out, we don't need to do anything
|
|
}
|
|
|
|
this._resetActions();
|
|
|
|
if (this.isAdmin) {
|
|
this.collectionTagActions.push({
|
|
action: Action.Edit,
|
|
title: 'Edit',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: true
|
|
});
|
|
|
|
this.seriesActions.push({
|
|
action: Action.ScanLibrary,
|
|
title: 'Scan Series',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: true
|
|
});
|
|
|
|
this.seriesActions.push({
|
|
action: Action.RefreshMetadata,
|
|
title: 'Refresh Metadata',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: true
|
|
});
|
|
|
|
this.seriesActions.push({
|
|
action: Action.Delete,
|
|
title: 'Delete',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: true
|
|
});
|
|
|
|
this.seriesActions.push({
|
|
action: Action.Edit,
|
|
title: 'Edit',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: true
|
|
});
|
|
|
|
this.libraryActions.push({
|
|
action: Action.ScanLibrary,
|
|
title: 'Scan Library',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: true
|
|
});
|
|
|
|
this.libraryActions.push({
|
|
action: Action.RefreshMetadata,
|
|
title: 'Refresh Metadata',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: true
|
|
});
|
|
|
|
this.chapterActions.push({
|
|
action: Action.Edit,
|
|
title: 'Info',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
});
|
|
}
|
|
|
|
if (this.hasDownloadRole || this.isAdmin) {
|
|
this.volumeActions.push({
|
|
action: Action.Download,
|
|
title: 'Download',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
});
|
|
|
|
this.chapterActions.push({
|
|
action: Action.Download,
|
|
title: 'Download',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
getLibraryActions(callback: (action: Action, library: Library) => void) {
|
|
const actions = this.libraryActions.map(a => {return {...a}});
|
|
actions.forEach(action => action.callback = callback);
|
|
return actions;
|
|
}
|
|
|
|
getSeriesActions(callback: (action: Action, series: Series) => void) {
|
|
const actions = this.seriesActions.map(a => {return {...a}});
|
|
actions.forEach(action => action.callback = callback);
|
|
return actions;
|
|
}
|
|
|
|
getVolumeActions(callback: (action: Action, volume: Volume) => void) {
|
|
const actions = this.volumeActions.map(a => {return {...a}});
|
|
actions.forEach(action => action.callback = callback);
|
|
return actions;
|
|
}
|
|
|
|
getChapterActions(callback: (action: Action, chapter: Chapter) => void) {
|
|
const actions = this.chapterActions.map(a => {return {...a}});
|
|
actions.forEach(action => action.callback = callback);
|
|
return actions;
|
|
}
|
|
|
|
getCollectionTagActions(callback: (action: Action, collectionTag: CollectionTag) => void) {
|
|
const actions = this.collectionTagActions.map(a => {return {...a}});
|
|
actions.forEach(action => action.callback = callback);
|
|
return actions;
|
|
}
|
|
|
|
getReadingListActions(callback: (action: Action, readingList: ReadingList) => void) {
|
|
const actions = this.readingListActions.map(a => {return {...a}});
|
|
actions.forEach(action => action.callback = callback);
|
|
return actions;
|
|
}
|
|
|
|
filterBookmarksForFormat(action: ActionItem<Series>, series: Series) {
|
|
if (action.action === Action.Bookmarks && series?.format === MangaFormat.EPUB) return false;
|
|
return true;
|
|
}
|
|
|
|
dummyCallback(action: Action, data: any) {}
|
|
|
|
_resetActions() {
|
|
this.libraryActions = [];
|
|
|
|
this.collectionTagActions = [];
|
|
|
|
this.seriesActions = [
|
|
{
|
|
action: Action.MarkAsRead,
|
|
title: 'Mark as Read',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.MarkAsUnread,
|
|
title: 'Mark as Unread',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.Bookmarks,
|
|
title: 'Bookmarks',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.AddToReadingList,
|
|
title: 'Add to Reading List',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
];
|
|
|
|
this.volumeActions = [
|
|
{
|
|
action: Action.MarkAsRead,
|
|
title: 'Mark as Read',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.MarkAsUnread,
|
|
title: 'Mark as Unread',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.AddToReadingList,
|
|
title: 'Add to Reading List',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.IncognitoRead,
|
|
title: 'Read in Incognito',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.Edit,
|
|
title: 'Info',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
}
|
|
];
|
|
|
|
this.chapterActions = [
|
|
{
|
|
action: Action.MarkAsRead,
|
|
title: 'Mark as Read',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.MarkAsUnread,
|
|
title: 'Mark as Unread',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.IncognitoRead,
|
|
title: 'Read in Incognito',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.AddToReadingList,
|
|
title: 'Add to Reading List',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
];
|
|
|
|
this.readingListActions = [
|
|
{
|
|
action: Action.Edit,
|
|
title: 'Edit',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
{
|
|
action: Action.Delete,
|
|
title: 'Delete',
|
|
callback: this.dummyCallback,
|
|
requiresAdmin: false
|
|
},
|
|
];
|
|
}
|
|
}
|