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:
parent
823121f335
commit
558a1d73f5
14 changed files with 242 additions and 73 deletions
|
|
@ -221,7 +221,7 @@ public class ReadingProfileServiceTest: AbstractDbTest
|
|||
Context.AppUserReadingProfile.Add(profile1);
|
||||
await UnitOfWork.CommitAsync();
|
||||
|
||||
await rps.RemoveProfileFromSeries(user.Id, profile1.Id, series.Id);
|
||||
await rps.ClearSeriesProfile(user.Id, series.Id);
|
||||
var profile = await rps.GetReadingProfileForSeries(user.Id, series.Id);
|
||||
Assert.Null(profile);
|
||||
|
||||
|
|
@ -254,7 +254,7 @@ public class ReadingProfileServiceTest: AbstractDbTest
|
|||
await UnitOfWork.CommitAsync();
|
||||
|
||||
var someSeriesIds = lib.Series.Take(lib.Series.Count / 2).Select(s => s.Id).ToList();
|
||||
await rps.BatchAddProfileToSeries(user.Id, profile.Id, someSeriesIds);
|
||||
await rps.BulkAddProfileToSeries(user.Id, profile.Id, someSeriesIds);
|
||||
|
||||
foreach (var id in someSeriesIds)
|
||||
{
|
||||
|
|
@ -264,7 +264,7 @@ public class ReadingProfileServiceTest: AbstractDbTest
|
|||
}
|
||||
|
||||
var allIds = lib.Series.Select(s => s.Id).ToList();
|
||||
await rps.BatchAddProfileToSeries(user.Id, profile2.Id, allIds);
|
||||
await rps.BulkAddProfileToSeries(user.Id, profile2.Id, allIds);
|
||||
|
||||
foreach (var id in allIds)
|
||||
{
|
||||
|
|
@ -342,7 +342,7 @@ public class ReadingProfileServiceTest: AbstractDbTest
|
|||
Assert.True(seriesProfile.Implicit);
|
||||
}
|
||||
|
||||
await rps.BatchAddProfileToSeries(user.Id, profile.Id, ids);
|
||||
await rps.BulkAddProfileToSeries(user.Id, profile.Id, ids);
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -127,15 +127,14 @@ public class ReadingProfileController(ILogger<ReadingProfileController> logger,
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the reading profile from a series for the current logged-in user
|
||||
/// Clears the reading profile for the given series for the currently logged-in user
|
||||
/// </summary>
|
||||
/// <param name="seriesId"></param>
|
||||
/// <param name="profileId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("series/{seriesId}")]
|
||||
public async Task<IActionResult> DeleteProfileFromSeries(int seriesId, [FromQuery] int profileId)
|
||||
public async Task<IActionResult> ClearSeriesProfile(int seriesId)
|
||||
{
|
||||
await readingProfileService.RemoveProfileFromSeries(User.GetUserId(), profileId, seriesId);
|
||||
await readingProfileService.ClearSeriesProfile(User.GetUserId(), seriesId);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
|
@ -153,15 +152,15 @@ public class ReadingProfileController(ILogger<ReadingProfileController> logger,
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the reading profile from a library for the current logged-in user
|
||||
/// Clears the reading profile for the given library for the currently logged-in user
|
||||
/// </summary>
|
||||
/// <param name="libraryId"></param>
|
||||
/// <param name="profileId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("library/{libraryId}")]
|
||||
public async Task<IActionResult> DeleteProfileFromLibrary(int libraryId, [FromQuery] int profileId)
|
||||
public async Task<IActionResult> ClearLibraryProfile(int libraryId)
|
||||
{
|
||||
await readingProfileService.RemoveProfileFromLibrary(User.GetUserId(), profileId, libraryId);
|
||||
await readingProfileService.ClearLibraryProfile(User.GetUserId(), libraryId);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
|
@ -171,10 +170,10 @@ public class ReadingProfileController(ILogger<ReadingProfileController> logger,
|
|||
/// <param name="profileId"></param>
|
||||
/// <param name="seriesIds"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("batch")]
|
||||
public async Task<IActionResult> BatchAddReadingProfile([FromQuery] int profileId, [FromBody] IList<int> seriesIds)
|
||||
[HttpPost("bulk")]
|
||||
public async Task<IActionResult> BulkAddReadingProfile([FromQuery] int profileId, [FromBody] IList<int> seriesIds)
|
||||
{
|
||||
await readingProfileService.BatchAddProfileToSeries(User.GetUserId(), profileId, seriesIds);
|
||||
await readingProfileService.BulkAddProfileToSeries(User.GetUserId(), profileId, seriesIds);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,14 @@ public interface IAppUserReadingProfileRepository
|
|||
Task<IList<AppUserReadingProfile>> GetProfilesForUser(int userId, bool nonImplicitOnly, ReadingProfileIncludes includes = ReadingProfileIncludes.None);
|
||||
Task<IList<UserReadingProfileDto>> GetProfilesDtoForUser(int userId, bool nonImplicitOnly, ReadingProfileIncludes includes = ReadingProfileIncludes.None);
|
||||
Task<AppUserReadingProfile?> GetProfileForSeries(int userId, int seriesId, ReadingProfileIncludes includes = ReadingProfileIncludes.None);
|
||||
/// <summary>
|
||||
/// Returns both implicit and "real" reading profiles
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="seriesId"></param>
|
||||
/// <param name="includes"></param>
|
||||
/// <returns></returns>
|
||||
Task<IList<AppUserReadingProfile>> GetAllProfilesForSeries(int userId, int seriesId, ReadingProfileIncludes includes = ReadingProfileIncludes.None);
|
||||
Task<IList<AppUserReadingProfile>> GetProfilesForSeries(int userId, IList<int> seriesIds, bool implicitOnly, ReadingProfileIncludes includes = ReadingProfileIncludes.None);
|
||||
Task<UserReadingProfileDto?> GetProfileDtoForSeries(int userId, int seriesId);
|
||||
Task<AppUserReadingProfile?> GetProfileForLibrary(int userId, int libraryId, ReadingProfileIncludes includes = ReadingProfileIncludes.None);
|
||||
|
|
@ -76,6 +84,14 @@ public class AppUserReadingProfileRepository(DataContext context, IMapper mapper
|
|||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<IList<AppUserReadingProfile>> GetAllProfilesForSeries(int userId, int seriesId, ReadingProfileIncludes includes = ReadingProfileIncludes.None)
|
||||
{
|
||||
return await context.AppUserReadingProfile
|
||||
.Where(rp => rp.UserId == userId && rp.Series.Any(s => s.SeriesId == seriesId))
|
||||
.Includes(includes)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<IList<AppUserReadingProfile>> GetProfilesForSeries(int userId, IList<int> seriesIds, bool implicitOnly, ReadingProfileIncludes includes = ReadingProfileIncludes.None)
|
||||
{
|
||||
return await context.AppUserReadingProfile
|
||||
|
|
|
|||
|
|
@ -68,11 +68,11 @@ public interface IReadingProfileService
|
|||
Task SetDefaultReadingProfile(int userId, int profileId);
|
||||
|
||||
Task AddProfileToSeries(int userId, int profileId, int seriesId);
|
||||
Task BatchAddProfileToSeries(int userId, int profileId, IList<int> seriesIds);
|
||||
Task RemoveProfileFromSeries(int userId, int profileId, int seriesId);
|
||||
Task BulkAddProfileToSeries(int userId, int profileId, IList<int> seriesIds);
|
||||
Task ClearSeriesProfile(int userId, int seriesId);
|
||||
|
||||
Task AddProfileToLibrary(int userId, int profileId, int libraryId);
|
||||
Task RemoveProfileFromLibrary(int userId, int profileId, int libraryId);
|
||||
Task ClearLibraryProfile(int userId, int libraryId);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -200,6 +200,10 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
|||
|
||||
if (profile.UserId != userId) throw new UnauthorizedAccessException();
|
||||
|
||||
// Remove all implicit profiles
|
||||
var implicitProfiles = await unitOfWork.AppUserReadingProfileRepository.GetProfilesForSeries(userId, [seriesId], true);
|
||||
unitOfWork.AppUserReadingProfileRepository.RemoveRange(implicitProfiles);
|
||||
|
||||
var seriesProfile = await unitOfWork.AppUserReadingProfileRepository.GetSeriesProfile(userId, seriesId);
|
||||
if (seriesProfile != null)
|
||||
{
|
||||
|
|
@ -219,7 +223,7 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
|||
await unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
public async Task BatchAddProfileToSeries(int userId, int profileId, IList<int> seriesIds)
|
||||
public async Task BulkAddProfileToSeries(int userId, int profileId, IList<int> seriesIds)
|
||||
{
|
||||
var profile = await unitOfWork.AppUserReadingProfileRepository.GetProfile(profileId, ReadingProfileIncludes.Series);
|
||||
if (profile == null) throw new KavitaException("profile-not-found");
|
||||
|
|
@ -254,14 +258,23 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
|||
await unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
public async Task RemoveProfileFromSeries(int userId, int profileId, int seriesId)
|
||||
public async Task ClearSeriesProfile(int userId, int seriesId)
|
||||
{
|
||||
var profile = await unitOfWork.AppUserReadingProfileRepository.GetProfile(profileId);
|
||||
if (profile == null) throw new KavitaException("profile-not-found");
|
||||
var profiles = await unitOfWork.AppUserReadingProfileRepository.GetAllProfilesForSeries(userId, seriesId, ReadingProfileIncludes.Series);
|
||||
if (!profiles.Any()) return;
|
||||
|
||||
if (profile.UserId != userId) throw new UnauthorizedAccessException();
|
||||
foreach (var profile in profiles)
|
||||
{
|
||||
if (profile.Implicit)
|
||||
{
|
||||
unitOfWork.AppUserReadingProfileRepository.Remove(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile.Series = profile.Series.Where(s => !(s.SeriesId == seriesId && s.AppUserId == userId)).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
profile.Series = profile.Series.Where(s => s.SeriesId != seriesId).ToList();
|
||||
await unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
|
|
@ -286,14 +299,21 @@ public class ReadingProfileService(IUnitOfWork unitOfWork, ILocalizationService
|
|||
await unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
public async Task RemoveProfileFromLibrary(int userId, int profileId, int libraryId)
|
||||
public async Task ClearLibraryProfile(int userId, int libraryId)
|
||||
{
|
||||
var profile = await unitOfWork.AppUserReadingProfileRepository.GetProfile(profileId);
|
||||
if (profile == null) throw new KavitaException("profile-not-found");
|
||||
var profile = await unitOfWork.AppUserReadingProfileRepository.GetProfileForLibrary(userId, libraryId, ReadingProfileIncludes.Library);
|
||||
if (profile == null) return;
|
||||
|
||||
if (profile.UserId != userId) throw new UnauthorizedAccessException();
|
||||
if (profile.Implicit)
|
||||
{
|
||||
unitOfWork.AppUserReadingProfileRepository.Remove(profile);
|
||||
await unitOfWork.CommitAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
profile.Libraries = profile.Libraries.Where(s => s.LibraryId != libraryId).ToList();
|
||||
profile.Libraries = profile.Libraries
|
||||
.Where(s => !(s.LibraryId == libraryId && s.AppUserId == userId))
|
||||
.ToList();
|
||||
await unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
this.readingProfileService.batchAddToSeries(profile.id, this.seriesIds).subscribe(() => {
|
||||
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;
|
||||
}
|
||||
|
||||
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) => {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue