Correctly remove implicit profiles when updating

- Add actions (library actions aren't working ?)
- Auto update for implicit is going off too often
This commit is contained in:
Amelia 2025-05-30 12:58:47 +02:00
parent 823121f335
commit 558a1d73f5
No known key found for this signature in database
GPG key ID: D6D0ECE365407EAA
14 changed files with 242 additions and 73 deletions

View file

@ -126,6 +126,10 @@ export enum Action {
* Add to a reading profile
*/
SetReadingProfile = 30,
/**
* Remove the reading profile from the entity
*/
ClearReadingProfile = 31,
}
/**
@ -346,6 +350,37 @@ export class ActionFactoryService {
requiredRoles: [Role.Admin],
children: [],
},
{
action: Action.Submenu,
title: 'reading-profiles',
description: '',
callback: this.dummyCallback,
shouldRender: this.dummyShouldRender,
requiresAdmin: false,
requiredRoles: [],
children: [
{
action: Action.SetReadingProfile,
title: 'set-reading-profile',
description: 'set-reading-profile-tooltip',
callback: this.dummyCallback,
shouldRender: this.dummyShouldRender,
requiresAdmin: false,
requiredRoles: [],
children: [],
},
{
action: Action.ClearReadingProfile,
title: 'clear-reading-profile',
description: 'clear-reading-profile-tooltip',
callback: this.dummyCallback,
shouldRender: this.dummyShouldRender,
requiresAdmin: false,
requiredRoles: [],
children: [],
},
],
},
{
action: Action.Submenu,
title: 'others',
@ -559,6 +594,37 @@ export class ActionFactoryService {
}
],
},
{
action: Action.Submenu,
title: 'reading-profiles',
description: '',
callback: this.dummyCallback,
shouldRender: this.dummyShouldRender,
requiresAdmin: false,
requiredRoles: [],
children: [
{
action: Action.SetReadingProfile,
title: 'set-reading-profile',
description: 'set-reading-profile-tooltip',
callback: this.dummyCallback,
shouldRender: this.dummyShouldRender,
requiresAdmin: false,
requiredRoles: [],
children: [],
},
{
action: Action.ClearReadingProfile,
title: 'clear-reading-profile',
description: 'clear-reading-profile-tooltip',
callback: this.dummyCallback,
shouldRender: this.dummyShouldRender,
requiresAdmin: false,
requiredRoles: [],
children: [],
},
],
},
{
action: Action.Submenu,
title: 'others',
@ -598,16 +664,6 @@ export class ActionFactoryService {
requiredRoles: [Role.Admin],
children: [],
},
{
action: Action.SetReadingProfile,
title: 'set-reading-profile',
description: 'set-reading-profile-tooltip',
callback: this.dummyCallback,
shouldRender: this.dummyShouldRender,
requiresAdmin: false,
requiredRoles: [],
children: [],
},
{
action: Action.Delete,
title: 'delete',

View file

@ -819,12 +819,38 @@ export class ActionService {
* @param series
* @param callback
*/
SetReadingProfileForMultiple(series: Array<Series>, callback?: BooleanActionCallback) {
setReadingProfileForMultiple(series: Array<Series>, callback?: BooleanActionCallback) {
if (this.readingListModalRef != null) { return; }
this.readingListModalRef = this.modalService.open(BulkSetReadingProfileComponent, { scrollable: true, size: 'md', fullscreen: 'md' });
this.readingListModalRef.componentInstance.seriesIds = series.map(s => s.id)
this.readingListModalRef.componentInstance.title = "hi"
this.readingListModalRef.componentInstance.title = ""
this.readingListModalRef.closed.pipe(take(1)).subscribe(() => {
this.readingListModalRef = null;
if (callback) {
callback(true);
}
});
this.readingListModalRef.dismissed.pipe(take(1)).subscribe(() => {
this.readingListModalRef = null;
if (callback) {
callback(false);
}
});
}
/**
* Sets the reading profile for multiple series
* @param library
* @param callback
*/
setReadingProfileForLibrary(library: Library, callback?: BooleanActionCallback) {
if (this.readingListModalRef != null) { return; }
this.readingListModalRef = this.modalService.open(BulkSetReadingProfileComponent, { scrollable: true, size: 'md', fullscreen: 'md' });
this.readingListModalRef.componentInstance.libraryId = library.id;
this.readingListModalRef.componentInstance.title = ""
this.readingListModalRef.closed.pipe(take(1)).subscribe(() => {
this.readingListModalRef = null;

View file

@ -44,20 +44,20 @@ export class ReadingProfileService {
return this.httpClient.post(this.baseUrl + `ReadingProfile/series/${seriesId}?profileId=${id}`, {});
}
removeFromSeries(id: number, seriesId: number) {
return this.httpClient.delete(this.baseUrl + `ReadingProfile/series/${seriesId}?profileId=${id}`, {});
clearSeriesProfiles(seriesId: number) {
return this.httpClient.delete(this.baseUrl + `ReadingProfile/series/${seriesId}`, {});
}
addToLibrary(id: number, libraryId: number) {
return this.httpClient.post(this.baseUrl + `ReadingProfile/library/${libraryId}?profileId=${id}`, {});
}
removeFromLibrary(id: number, libraryId: number) {
return this.httpClient.delete(this.baseUrl + `ReadingProfile/library/${libraryId}?profileId=${id}`, {});
clearLibraryProfiles(libraryId: number) {
return this.httpClient.delete(this.baseUrl + `ReadingProfile/library/${libraryId}`, {});
}
batchAddToSeries(id: number, seriesIds: number[]) {
return this.httpClient.post(this.baseUrl + `ReadingProfile/batch?profileId=${id}`, seriesIds);
bulkAddToSeries(id: number, seriesIds: number[]) {
return this.httpClient.post(this.baseUrl + `ReadingProfile/bulk?profileId=${id}`, seriesIds);
}
}

View file

@ -27,9 +27,10 @@ export class BulkSetReadingProfileComponent implements OnInit, AfterViewInit {
@Input({required: true}) title!: string;
/**
* Series Ids to add to Collection Tag
* Series Ids to add to Reading Profile
*/
@Input() seriesIds: Array<number> = [];
@Input() libraryId: number | undefined;
@ViewChild('title') inputElem!: ElementRef<HTMLInputElement>;
profiles: Array<ReadingProfile> = [];
@ -63,12 +64,28 @@ export class BulkSetReadingProfileComponent implements OnInit, AfterViewInit {
}
addToProfile(profile: ReadingProfile) {
if (this.seriesIds.length === 0) return;
if (this.seriesIds.length == 1) {
this.readingProfileService.addToSeries(profile.id, this.seriesIds[0]).subscribe(() => {
this.toastr.success(translate('toasts.series-added-to-reading-profile', {name: profile.name}));
this.modal.close();
});
return;
}
this.readingProfileService.batchAddToSeries(profile.id, this.seriesIds).subscribe(() => {
this.toastr.success(translate('toasts.series-added-to-reading-profile', {name: profile.name}));
this.modal.close();
});
if (this.seriesIds.length > 1) {
this.readingProfileService.bulkAddToSeries(profile.id, this.seriesIds).subscribe(() => {
this.toastr.success(translate('toasts.series-added-to-reading-profile', {name: profile.name}));
this.modal.close();
});
return;
}
if (this.libraryId) {
this.readingProfileService.addToLibrary(profile.id, this.libraryId).subscribe(() => {
this.toastr.success(translate('toasts.library-added-to-reading-profile', {name: profile.name}));
this.modal.close();
});
}
}
filterList = (listItem: ReadingProfile) => {

View file

@ -24,7 +24,7 @@ import {RelationKind} from 'src/app/_models/series-detail/relation-kind';
import {DecimalPipe} from "@angular/common";
import {RelationshipPipe} from "../../_pipes/relationship.pipe";
import {Device} from "../../_models/device/device";
import {translate, TranslocoDirective} from "@jsverse/transloco";
import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloco";
import {SeriesPreviewDrawerComponent} from "../../_single-module/series-preview-drawer/series-preview-drawer.component";
import {CardActionablesComponent} from "../../_single-module/card-actionables/card-actionables.component";
import {DefaultValuePipe} from "../../_pipes/default-value.pipe";
@ -41,6 +41,7 @@ import {ScrollService} from "../../_services/scroll.service";
import {ReaderService} from "../../_services/reader.service";
import {SeriesFormatComponent} from "../../shared/series-format/series-format.component";
import {DefaultModalOptions} from "../../_models/default-modal-options";
import {ReadingProfileService} from "../../_services/reading-profile.service";
function deepClone(obj: any): any {
if (obj === null || typeof obj !== 'object') {
@ -92,6 +93,8 @@ export class SeriesCardComponent implements OnInit, OnChanges {
private readonly downloadService = inject(DownloadService);
private readonly scrollService = inject(ScrollService);
private readonly readerService = inject(ReaderService);
private readonly readingProfilesService = inject(ReadingProfileService);
private readonly translocoService = inject(TranslocoService);
@Input({required: true}) series!: Series;
@Input() libraryId = 0;
@ -277,7 +280,12 @@ export class SeriesCardComponent implements OnInit, OnChanges {
this.downloadService.download('series', this.series);
break;
case Action.SetReadingProfile:
this.actionService.SetReadingProfileForMultiple([this.series]);
this.actionService.setReadingProfileForMultiple([series]);
break;
case Action.ClearReadingProfile:
this.readingProfilesService.clearSeriesProfiles(series.id).subscribe(() => {
this.toastr.success(this.translocoService.translate('actionable.cleared-profile'));
});
break;
default:
break;

View file

@ -150,7 +150,7 @@ export class LibraryDetailComponent implements OnInit {
});
break;
case Action.SetReadingProfile:
this.actionService.SetReadingProfileForMultiple(selectedSeries, (success) => {
this.actionService.setReadingProfileForMultiple(selectedSeries, (success) => {
this.bulkLoader = false;
this.cdRef.markForCheck();
if (!success) return;

View file

@ -533,21 +533,6 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
swipeToPaginate: new FormControl(this.readingProfile.swipeToPaginate)
});
// Update implicit reading profile while changing settings
this.generalSettingsForm.valueChanges.pipe(
debounceTime(300),
distinctUntilChanged(),
takeUntilDestroyed(this.destroyRef),
tap(_ => {
this.readingProfileService.updateImplicit(this.packReadingProfile(), this.seriesId).subscribe({
error: err => {
console.error(err);
}
})
})
).subscribe();
this.readerModeSubject.next(this.readerMode);
this.pagingDirectionSubject.next(this.pagingDirection);
@ -630,6 +615,26 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
});
this.init();
// TODO: Fix this, it's going off way too often
// Update implicit reading profile while changing settings
this.generalSettingsForm.valueChanges.pipe(
debounceTime(300),
distinctUntilChanged(),
takeUntilDestroyed(this.destroyRef),
map(_ => this.packReadingProfile()),
distinctUntilChanged(),
tap(newProfile => {
this.readingProfileService.updateImplicit(newProfile, this.seriesId).subscribe({
next: () => {
this.readingProfile = newProfile;
},
error: err => {
console.error(err);
}
})
})
).subscribe();
});
}

View file

@ -110,6 +110,7 @@ import {LicenseService} from "../../../_services/license.service";
import {PageBookmark} from "../../../_models/readers/page-bookmark";
import {VolumeRemovedEvent} from "../../../_models/events/volume-removed-event";
import {ReviewsComponent} from "../../../_single-module/reviews/reviews.component";
import {ReadingProfileService} from "../../../_services/reading-profile.service";
enum TabID {
@ -175,6 +176,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
private readonly cdRef = inject(ChangeDetectorRef);
private readonly scrollService = inject(ScrollService);
private readonly translocoService = inject(TranslocoService);
private readonly readingProfileService = inject(ReadingProfileService);
protected readonly bulkSelectionService = inject(BulkSelectionService);
protected readonly utilityService = inject(UtilityService);
protected readonly imageService = inject(ImageService);
@ -610,7 +612,12 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
break;
}
case Action.SetReadingProfile:
this.actionService.SetReadingProfileForMultiple([this.series]);
this.actionService.setReadingProfileForMultiple([this.series]);
break;
case Action.ClearReadingProfile:
this.readingProfileService.clearSeriesProfiles(this.seriesId).subscribe(() => {
this.toastr.success(this.translocoService.translate('actionable.cleared-profile'));
});
break;
default:
break;

View file

@ -16,7 +16,7 @@ import {AsyncPipe, NgClass} from "@angular/common";
import {SideNavItemComponent} from "../side-nav-item/side-nav-item.component";
import {FilterPipe} from "../../../_pipes/filter.pipe";
import {FormsModule} from "@angular/forms";
import {translate, TranslocoDirective} from "@jsverse/transloco";
import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloco";
import {CardActionablesComponent} from "../../../_single-module/card-actionables/card-actionables.component";
import {SideNavStream} from "../../../_models/sidenav/sidenav-stream";
import {SideNavStreamType} from "../../../_models/sidenav/sidenav-stream-type.enum";
@ -25,6 +25,7 @@ import {SettingsTabId} from "../../preference-nav/preference-nav.component";
import {LicenseService} from "../../../_services/license.service";
import {CdkDrag, CdkDragDrop, CdkDropList} from "@angular/cdk/drag-drop";
import {ToastrService} from "ngx-toastr";
import {ReadingProfileService} from "../../../_services/reading-profile.service";
@Component({
selector: 'app-side-nav',
@ -53,7 +54,9 @@ export class SideNavComponent implements OnInit {
protected readonly licenseService = inject(LicenseService);
private readonly destroyRef = inject(DestroyRef);
private readonly actionFactoryService = inject(ActionFactoryService);
private readonly toastr = inject(ToastrService)
private readonly toastr = inject(ToastrService);
private readonly readingProfilesService = inject(ReadingProfileService);
private readonly translocoService = inject(TranslocoService);
cachedData: SideNavStream[] | null = null;
@ -175,6 +178,14 @@ export class SideNavComponent implements OnInit {
case (Action.Edit):
this.actionService.editLibrary(lib, () => window.scrollTo(0, 0));
break;
case (Action.SetReadingProfile):
this.actionService.setReadingProfileForLibrary(lib);
break;
case (Action.ClearReadingProfile):
this.readingProfilesService.clearLibraryProfiles(lib.id).subscribe(() => {
this.toastr.success(this.translocoService.translate('actionable.cleared-profile'));
});
break;
default:
break;
}

View file

@ -2714,7 +2714,11 @@
"remove-from-want-to-read-tooltip": "Remove series from Want to Read",
"remove-from-on-deck": "Remove From On Deck",
"remove-from-on-deck-tooltip": "Remove series from showing from On Deck",
"reading-profiles": "Reading Profiles",
"set-reading-profile": "Set Reading Profile",
"clear-reading-profile": "Clear Reading Profile",
"cleared-profile": "Cleared Reading Profile",
"others": "Others",
"add-to-reading-list": "Add to Reading List",