Feature/release cleanup (#597)

* Deselect all after bulk operations complete.

* Implemented a way to trigger selection code on mobile.

* When selection mode is active, make the clickable area the whole image.

* Series detail shouldn't use gutters for card layout as it can cause skewing on mobile

* Long press on card items to trigger the selection on mobile

* Code cleanup

* One more

* Misread the code issue
This commit is contained in:
Joseph Milazzo 2021-09-26 05:40:52 -07:00 committed by GitHub
parent 5ceb74e210
commit 5e2606b0de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 54 additions and 25 deletions

View File

@ -2,6 +2,8 @@ using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using API.Extensions;
using API.Middleware;
using API.Services;
@ -9,6 +11,7 @@ using API.Services.HostedServices;
using API.SignalR;
using Hangfire;
using Hangfire.MemoryStorage;
using Kavita.Common;
using Kavita.Common.EnvironmentInfo;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
@ -109,7 +112,7 @@ namespace API
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials() // For SignalR token query param
.WithOrigins("http://localhost:4200")
.WithOrigins("http://localhost:4200", $"http://{GetLocalIpAddress()}:4200")
.WithExposedHeaders("Content-Disposition", "Pagination"));
}
@ -164,6 +167,14 @@ namespace API
Console.WriteLine("You may now close the application window.");
}
private static string GetLocalIpAddress()
{
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0);
socket.Connect("8.8.8.8", 65530);
if (socket.LocalEndPoint is IPEndPoint endPoint) return endPoint.Address.ToString();
throw new KavitaException("No network adapters with an IPv4 address in the system!");
}
}
}

View File

@ -82,6 +82,8 @@ $image-width: 160px;
&.always-show {
visibility: visible !important;
width: $image-width;
height: $image-height;
}
input[type="checkbox"] {

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { Observable, Subject } from 'rxjs';
import { finalize, take, takeUntil, takeWhile } from 'rxjs/operators';
@ -118,6 +118,24 @@ export class CardItemComponent implements OnInit, OnDestroy {
this.onDestroy.complete();
}
prevTouchTime: number = 0;
@HostListener('touchstart', ['$event'])
onTouchStart(event: TouchEvent) {
this.prevTouchTime = event.timeStamp;
}
@HostListener('touchend', ['$event'])
onTouchEnd(event: TouchEvent) {
if (event.timeStamp - this.prevTouchTime >= 200) {
this.handleSelection();
event.stopPropagation();
event.preventDefault();
}
this.prevTouchTime = 0;
}
handleClick(event?: any) {
this.clicked.emit(this.title);
}

View File

@ -46,16 +46,20 @@ export class CollectionDetailComponent implements OnInit {
switch (action) {
case Action.AddToReadingList:
this.actionService.addMultipleSeriesToReadingList(selectedSeries);
this.actionService.addMultipleSeriesToReadingList(selectedSeries, () => {
this.bulkSelectionService.deselectAll();
});
break;
case Action.MarkAsRead:
this.actionService.markMultipleSeriesAsRead(selectedSeries, () => {
this.loadPage();
this.bulkSelectionService.deselectAll();
});
break;
case Action.MarkAsUnread:
this.actionService.markMultipleSeriesAsUnread(selectedSeries, () => {
this.loadPage();
this.bulkSelectionService.deselectAll();
});
break;
}

View File

@ -33,30 +33,26 @@ export class LibraryDetailComponent implements OnInit {
};
bulkActionCallback = (action: Action, data: any) => {
console.log('handling bulk action callback');
// we need to figure out what is actually selected now
const selectedSeriesIndexies = this.bulkSelectionService.getSelectedCardsForSource('series');
const selectedSeries = this.series.filter((series, index: number) => selectedSeriesIndexies.includes(index + ''));
switch (action) {
case Action.AddToReadingList:
this.actionService.addMultipleSeriesToReadingList(selectedSeries);
this.actionService.addMultipleSeriesToReadingList(selectedSeries, () => {
this.bulkSelectionService.deselectAll();
});
break;
case Action.MarkAsRead:
console.log('marking series as read: ', selectedSeries)
this.actionService.markMultipleSeriesAsRead(selectedSeries, () => {
this.loadPage();
this.bulkSelectionService.deselectAll();
});
break;
case Action.MarkAsUnread:
//console.log('marking volumes as unread: ', selectedVolumeIds)
//console.log('marking chapters as unread: ', chapters)
this.actionService.markMultipleSeriesAsUnread(selectedSeries, () => {
this.loadPage();
this.bulkSelectionService.deselectAll();
});
break;
}

View File

@ -102,7 +102,7 @@
<li [ngbNavItem]="1" *ngIf="hasSpecials">
<a ngbNavLink>Specials</a>
<ng-template ngbNavContent>
<div class="row">
<div class="row no-gutters">
<div *ngFor="let chapter of specials; let idx = index; trackBy: trackByChapterIdentity">
<app-card-item class="col-auto" *ngIf="chapter.isSpecial" [entity]="chapter" [title]="chapter.title || chapter.range" (click)="openChapter(chapter)"
[imageUrl]="imageService.getChapterCoverImage(chapter.id)"
@ -114,7 +114,7 @@
<li [ngbNavItem]="2" *ngIf="hasNonSpecialVolumeChapters">
<a ngbNavLink>Volumes/Chapters</a>
<ng-template ngbNavContent>
<div class="row">
<div class="row no-gutters">
<div *ngFor="let volume of volumes; let idx = index; trackBy: trackByVolumeIdentity">
<app-card-item class="col-auto" *ngIf="volume.number != 0" [entity]="volume" [title]="'Volume ' + volume.name" (click)="openVolume(volume)"
[imageUrl]="imageService.getVolumeCoverImage(volume.id) + '&offset=' + coverImageOffset"

View File

@ -91,7 +91,6 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
trackByChapterIdentity = (index: number, item: Chapter) => `${item.title}_${item.number}_${item.pagesRead}`;
bulkActionCallback = (action: Action, data: any) => {
console.log('handling bulk action callback');
if (this.series === undefined) {
return;
}
@ -101,32 +100,31 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
const selectedChapterIndexes = this.bulkSelectionService.getSelectedCardsForSource('chapter');
const selectedSpecialIndexes = this.bulkSelectionService.getSelectedCardsForSource('special');
const selectedChapterIds = this.chapters.filter((chapter, index: number) => selectedChapterIndexes.includes(index + ''));
const selectedVolumeIds = this.volumes.filter((volume, index: number) => selectedVolumeIndexes.includes(index + ''));
const selectedSpecials = this.specials.filter((chapter, index: number) => selectedSpecialIndexes.includes(index + ''));
const selectedChapterIds = this.chapters.filter((_chapter, index: number) => selectedChapterIndexes.includes(index + ''));
const selectedVolumeIds = this.volumes.filter((_volume, index: number) => selectedVolumeIndexes.includes(index + ''));
const selectedSpecials = this.specials.filter((_chapter, index: number) => selectedSpecialIndexes.includes(index + ''));
const chapters = [...selectedChapterIds, ...selectedSpecials];
switch (action) {
case Action.AddToReadingList:
this.actionService.addMultipleToReadingList(seriesId, selectedVolumeIds, chapters, () => this.actionInProgress = false);
this.actionService.addMultipleToReadingList(seriesId, selectedVolumeIds, chapters, () => {
this.actionInProgress = false;
this.bulkSelectionService.deselectAll();
});
break;
case Action.MarkAsRead:
console.log('marking volumes as read: ', selectedVolumeIds)
console.log('marking chapters as read: ', chapters)
this.actionService.markMultipleAsRead(seriesId, selectedVolumeIds, chapters, () => {
this.setContinuePoint();
this.actionInProgress = false;
this.bulkSelectionService.deselectAll();
});
break;
case Action.MarkAsUnread:
console.log('marking volumes as unread: ', selectedVolumeIds)
console.log('marking chapters as unread: ', chapters)
this.actionService.markMultipleAsUnread(seriesId, selectedVolumeIds, chapters, () => {
this.setContinuePoint();
this.actionInProgress = false;
this.bulkSelectionService.deselectAll();
});
break;
}