The last push before release (#2696)

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2024-02-07 14:03:30 -06:00 committed by GitHub
parent 2227dc354b
commit 033dc61d54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 681 additions and 433 deletions

View File

@ -1687,6 +1687,35 @@ public class ReaderServiceTests
}
[Fact]
public async Task GetContinuePoint_ShouldReturnFirstChapter_WhenHasSpecial()
{
await ResetDb();
var series = new SeriesBuilder("Test")
// Loose chapters
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).Build())
.WithChapter(new ChapterBuilder("Prologue").WithIsSpecial(true).WithPages(1).Build())
.Build())
.Build();
series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
_context.Series.Add(series);
_context.AppUser.Add(new AppUser()
{
UserName = "majora2007"
});
await _context.SaveChangesAsync();
var nextChapter = await _readerService.GetContinuePoint(1, 1);
Assert.Equal("1", nextChapter.Range);
}
[Fact]
public async Task GetContinuePoint_ShouldReturnFirstSpecial()
{

View File

@ -31,7 +31,9 @@ public class LicenseController(
[ResponseCache(CacheProfileName = ResponseCacheProfiles.LicenseCache)]
public async Task<ActionResult<bool>> HasValidLicense(bool forceCheck = false)
{
return Ok(await licenseService.HasActiveLicense(forceCheck));
var result = await licenseService.HasActiveLicense(forceCheck);
await taskScheduler.ScheduleKavitaPlusTasks();
return Ok(result);
}
/// <summary>
@ -66,7 +68,11 @@ public class LicenseController(
public async Task<ActionResult> ResetLicense(UpdateLicenseDto dto)
{
logger.LogInformation("Resetting license on file for Server");
if (await licenseService.ResetLicense(dto.License, dto.Email)) return Ok();
if (await licenseService.ResetLicense(dto.License, dto.Email))
{
await taskScheduler.ScheduleKavitaPlusTasks();
return Ok();
}
return BadRequest(localizationService.Translate(User.GetUserId(), "unable-to-reset-k+"));
}

View File

@ -1,36 +1,33 @@
<table>
<tr>
<td valign="top" style="text-align: center; padding: 20px 0 10px 20px;">
<h1 style="margin: 0; font-family: 'Montserrat', sans-serif; font-size: 30px; line-height: 36px; font-weight: bold;">Email Change Update</h1> </td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 18px; line-height: 20px;">
<p style="margin: 0;">Your account's email has been updated on {{InvitingUser}}'s Kavita instance.</p>
</td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 18px; line-height: 20px;">
<p style="margin: 0;">Please click the following link to validate your email change. The email is not changed until you complete validation.</p>
</td>
</tr>
<tr>
<td valign="top" align="center" style="text-align: center; padding: 15px 0px 20px 0px;">
<!-- Button : BEGIN -->
<center>
<table role="presentation" align="center" cellspacing="0" cellpadding="0" border="0" class="center-on-narrow" style="text-align: center;">
<tr>
<td style="border-radius: 50px; background: #153643; text-align: center;" class="button-td">
<a href="{{Link}}" style="background: #153643; border: 15px solid #153643; font-family: 'Montserrat', sans-serif; font-size: 14px; line-height: 1.1; text-align: center; text-decoration: none; display: block; border-radius: 50px; font-weight: bold;" class="button-a"> <span style="color:#ffffff;" class="button-link">&nbsp;&nbsp;&nbsp;&nbsp;CONFIRM EMAIL&nbsp;&nbsp;&nbsp;&nbsp;</span> </a>
</td>
</tr>
</table>
</center>
<!-- Button : END -->
</td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 12px; line-height: 20px;">
<p style="margin: 0;">If the button above does not work, please find the link here: <a style="color:inherit;margin: 0;width: 100%;word-break: break-all;" href="{{Link}}">{{Link}}</a></p>
</td>
</tr>
</table>
<style>
.small {
font-size: 10px;
color: lightgrey;
}
</style>
<tr>
<td>
<h1>Email Change Update</h1>
<p>Your account's email has been updated on {{InvitingUser}}'s Kavita instance.</p>
<p>Please click the following link to validate your email change. The email is not changed until you complete validation.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="center">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td> <a href="{{Link}}" target="_blank">CONFIRM EMAIL</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p class="small">If the button above does not work, please find the link here: {{Link}}</p>
</td>
</tr>

View File

@ -1,36 +1,32 @@
<table>
<tr>
<td valign="top" style="text-align: center; padding: 20px 0 10px 20px;">
<h1 style="margin: 0; font-family: 'Montserrat', sans-serif; font-size: 30px; line-height: 36px; font-weight: bold;">You've Been Invited</h1> </td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 18px; line-height: 20px;">
<p style="margin: 0;">You have been invited to {{InvitingUser}}'s Kavita instance.</p>
</td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 18px; line-height: 20px;">
<p style="margin: 0;">Please click the following link to setup an account for yourself and start reading.</p>
</td>
</tr>
<tr>
<td valign="top" align="center" style="text-align: center; padding: 15px 0px 20px 0px;">
<!-- Button : BEGIN -->
<center>
<table role="presentation" align="center" cellspacing="0" cellpadding="0" border="0" class="center-on-narrow" style="text-align: center;">
<tr>
<td style="border-radius: 50px; background: #153643; text-align: center;" class="button-td">
<a href="{{Link}}" style="background: #153643; border: 15px solid #153643; font-family: 'Montserrat', sans-serif; font-size: 14px; line-height: 1.1; text-align: center; text-decoration: none; display: block; border-radius: 50px; font-weight: bold;" class="button-a"> <span style="color:#ffffff;" class="button-link">&nbsp;&nbsp;&nbsp;&nbsp;ACCEPT INVITE&nbsp;&nbsp;&nbsp;&nbsp;</span> </a>
</td>
</tr>
</table>
</center>
<!-- Button : END -->
</td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 12px; line-height: 20px;">
<p style="margin: 0;">If the button above does not work, please find the link here: <a style="color:inherit;margin: 0;width: 100%;word-break: break-all;" href="{{Link}}">{{Link}}</a></p>
</td>
</tr>
</table>
<style>
.small {
font-size: 10px;
color: lightgrey;
}
</style>
<tr>
<td>
<h1>You've Been Invited!</h1>
<p>You have been invited to {{InvitingUser}}'s Kavita instance.</p>
<p>Please click the following link to setup an account for yourself and start reading.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="center">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td> <a href="{{Link}}" target="_blank">ACCEPT INVITE</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p class="small">If the button above does not work, please find the link here: {{Link}}</p>
</td>
</tr>

View File

@ -1,36 +1,33 @@
<table>
<tr>
<td valign="top" style="text-align: center; padding: 20px 0 10px 20px;">
<h1 style="margin: 0; font-family: 'Montserrat', sans-serif; font-size: 30px; line-height: 36px; font-weight: bold;">Forgot your password?</h1> </td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 18px; line-height: 20px;">
<p style="margin: 0;">That's okay, it happens! Click on the button below to reset your password.</p>
</td>
</tr>
<tr>
<td valign="top" align="center" style="text-align: center; padding: 15px 0px 20px 0px;">
<!-- Button : BEGIN -->
<center>
<table role="presentation" align="center" cellspacing="0" cellpadding="0" border="0" class="center-on-narrow" style="text-align: center;">
<tr>
<td style="border-radius: 50px; background: #153643; text-align: center;" class="button-td">
<a href="{{Link}}" style="background: #153643; border: 15px solid #153643; font-family: 'Montserrat', sans-serif; font-size: 14px; line-height: 1.1; text-align: center; text-decoration: none; display: block; border-radius: 50px; font-weight: bold;" class="button-a"> <span style="color:#ffffff;" class="button-link">&nbsp;&nbsp;&nbsp;&nbsp;RESET YOUR PASSWORD&nbsp;&nbsp;&nbsp;&nbsp;</span> </a>
</td>
</tr>
</table>
</center>
<!-- Button : END -->
</td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 0px 20px 0px 20px; font-family: sans-serif; font-size: 12px; line-height: 20px;">
<p style="margin: 0;">If you did not perform this action, ignore this email.</p>
</td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 12px; line-height: 20px;">
<p style="margin: 0;">If the button above does not work, please find the link here: <a style="color:inherit;margin: 0;width: 100%;word-break: break-all;" href="{{Link}}">{{Link}}</a></p>
</td>
</tr>
</table>
<style>
.small {
font-size: 10px;
color: lightgrey;
}
</style>
<tr>
<td>
<h1>Forgot your password?</h1>
<p>That's okay, it happens! Click on the button below to reset your password.</p>
<p>If you did not perform this action, ignore this email. Your account is safe.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="center">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td> <a href="{{Link}}" target="_blank">RESET YOUR PASSWORD</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p class="small">If the button above does not work, please find the link here: {{Link}}</p>
</td>
</tr>

View File

@ -1,11 +1,8 @@
<table>
<tr>
<td valign="top" style="text-align: center; padding: 20px 0 10px 20px;">
<h1 style="margin: 0; font-family: 'Montserrat', sans-serif; font-size: 30px; line-height: 36px; font-weight: bold;">This is a Test Email</h1> </td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 18px; line-height: 20px;">
<p style="margin: 0;">If you've received this email, your KavitaEmail is setup</p>
</td>
</tr>
</table>
<tr>
<td>
<h1>This is a Test Email</h1>
<p>Congrats! Your instance of Kavita is setup to email correctly!</p>
<p>If you did not perform this action, ignore this email. Your account is safe.</p>
</td>
</tr>

View File

@ -1,11 +1,6 @@
<table>
<tr>
<td valign="top" style="text-align: center; padding: 20px 0 10px 20px;">
<h1 style="margin: 0; font-family: 'Montserrat', sans-serif; font-size: 30px; line-height: 36px; font-weight: bold;">You sent a file from Kavita</h1> </td>
</tr>
<tr>
<td valign="top" style="text-align: center; padding: 10px 20px 15px 20px; font-family: sans-serif; font-size: 18px; line-height: 20px;">
<p style="margin: 0;">Please find attached the file(s) you've sent.</p>
</td>
</tr>
</table>
<tr>
<td>
<h1>You sent file(s) from Kavita</h1>
<p>Please find attached the file(s) you've sent.</p>
</td>
</tr>

View File

@ -1,320 +1,523 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<meta charset="utf-8">
<!-- utf-8 works for most cases -->
<meta name="viewport" content="width=device-width">
<!-- Forcing initial-scale shouldn't be necessary -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Use the latest (edge) version of IE rendering engine -->
<meta name="x-apple-disable-message-reformatting">
<!-- Disable auto-scale in iOS 10 Mail entirely -->
<title>Kavita - [Plain HTML]</title>
<!-- The title tag shows in email notifications, like Android 4.4. -->
<!-- Web Font / @font-face : BEGIN -->
<!-- NOTE: If web fonts are not required, lines 10 - 27 can be safely removed. -->
<!-- Desktop Outlook chokes on web font references and defaults to Times New Roman, so we force a safe fallback font. -->
<!--[if mso]>
<style>
* {
font-family: Arial, sans-serif !important;
}
</style>
<![endif]-->
<!-- All other clients get the webfont reference; some will render the font and others will silently fail to the fallbacks. More on that here: http://stylecampaign.com/blog/2015/02/webfont-support-in-email/ -->
<!--[if !mso]><!-->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Spartan:wght@500;700&display=swap" rel="stylesheet">
<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">
<!-- Supports dark mode -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Spartan:wght@500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<!--<![endif]-->
<!-- Web Font / @font-face : END -->
<!-- CSS Reset -->
<title>Kavita - {{Preheader}}</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Spartan:wght@500;700&display=swap');
/* What it does: Remove spaces around the email design added by some email clients. */
/* Beware: It can remove the padding / margin and add a background color to the compose a reply window. */
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
html,
body {
margin: 0 auto !important;
padding: 0 !important;
height: 100% !important;
width: 100% !important;
/*All the styling goes here*/
:root {
Color-scheme: light dark;
supported-color-schemes: light dark;
}
/* What it does: Stops email clients resizing small text. */
* {
.dark-img { display: none !important; }
@media (prefers-color-scheme: dark) {
.dark-img {
display: inline-block !important;
}
.light-img {
display: none !important;
}
}
[data-ogsc] .dark-img {
display: inline-block !important;
}
[data-ogsc] .light-img {
display: none !important;
}
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%;
}
body {
background-color: #eaebed;
font-family: sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
line-height: 1.4;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
/* What it does: Centers email on Android 4.4 */
div[style*="margin: 16px 0"] {
margin: 0 !important;
}
/* What it does: Stops Outlook from adding extra spacing to tables. */
table,
td {
mso-table-lspace: 0pt !important;
mso-table-rspace: 0pt !important;
}
/* What it does: Fixes webkit padding issue. Fix for Yahoo mail table alignment bug. Applies table-layout to the first 2 tables then removes for anything nested deeper. */
table {
border-spacing: 0 !important;
border-collapse: collapse !important;
table-layout: fixed !important;
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
min-width: 100%;
width: 100%; }
table td {
font-family: sans-serif;
font-size: 14px;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: #eaebed;
width: 100%;
}
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block;
margin: 0 auto !important;
/* makes it centered */
max-width: 680px;
width: 680px;
}
table table table {
table-layout: auto;
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
box-sizing: border-box;
display: block;
margin: 0 auto;
max-width: 680px;
padding: 0;
}
i {
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #ffffff;
border-radius: 3px;
width: 100%;
}
.header {
padding: 10px 40px;
background-color: #4AC694;
background-image: linear-gradient(#4AC694, #4AC694);
text-align: center;
}
u + .body .gmail-blend-screen {
background:#000;
mix-blend-mode:screen;
}
u + .body .gmail-blend-difference {
background:#000;
mix-blend-mode:difference;
}
@media (prefers-color-scheme: dark ) {
.header {
background-color: transparent !important;
}
.header-text {
color: #fffffe !important;
}
.logo-text {
color: #fffffe !important;
}
}
.header-text, .logo-text {
font-weight: 700;
font-family: 'Spartan', sans-serif;
text-decoration: none;
color: #ffffff;
font-size: 2rem;
vertical-align: middle;
margin: 0
}
.logo-text {
color: #fff;
font-size: 26px;
}
/* What it does: Uses a better rendering method when resizing images in IE. */
img {
-ms-interpolation-mode: bicubic;
.header-text img {
vertical-align: middle;
width: 200px;
}
/* What it does: A work-around for email clients meddling in triggered links. */
*[x-apple-data-detectors],
/* iOS */
.x-gmail-data-detectors,
/* Gmail */
.x-gmail-data-detectors *,
.aBn {
border-bottom: 0 !important;
cursor: default !important;
color: inherit !important;
text-decoration: none !important;
font-size: inherit !important;
font-family: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
.header-text div, .header-text p {
vertical-align: middle;
min-height: 75px;
line-height: 75px;
display: inline-block;
}
/* What it does: Prevents Gmail from displaying an download button on large, non-linked images. */
.a6S {
display: none !important;
opacity: 0.01 !important;
.wrapper {
box-sizing: border-box;
padding: 20px;
}
/* If the above doesn't work, add a .g-img class to any image in question. */
img.g-img + div {
display: none !important;
.content-block {
padding-bottom: 10px;
padding-top: 10px;
}
/* What it does: Prevents underlining the button text in Windows 10 */
.button-link {
text-decoration: none !important;
.content-block > * {
padding-right: 10px;
}
/* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89 */
/* Create one of these media queries for each additional viewport size you'd like to fix */
/* Thanks to Eric Lepetit @ericlepetitsf) for help troubleshooting */
@media only screen and (min-device-width: 375px) and (max-device-width: 413px) {
/* iPhone 6 and 6+ */
.email-container {
min-width: 375px !important;
.footer {
clear: both;
text-align: center;
width: 100%;
background-color: #222;
background-image: linear-gradient(#222, #222);
color: #fffffe;
}
.footer td,
.footer p,
.footer span,
.footer a {
color: #fffffe;
font-size: 12px;
text-align: center;
}
.footer .icon {
margin:0;
padding:0 10px;
border:none;
display:inline-block;
}
@media (prefers-color-scheme: dark ) {
.footer {
background-color: rgba(0,0,0,0) !important;
background-image: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0)) !important;
}
}
</style>
<!-- Progressive Enhancements -->
<style>
/* What it does: Hover styles for buttons */
.button-td,
.button-a {
transition: all 100ms ease-in;
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1,
h2,
h3,
h4 {
color: #06090f;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
margin-bottom: 30px;
}
.button-td:hover,
.button-a:hover {
background: #000000 !important;
border-color: #000000 !important;
color: white !important;
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize;
}
/* Media Queries */
@media screen and (max-width: 480px) {
/* What it does: Forces elements to resize to the full width of their container. Useful for resizing images beyond their max-width. */
.fluid {
p,
ul,
ol {
font-family: sans-serif;
font-size: 14px;
font-weight: normal;
margin: 0;
margin-bottom: 15px;
}
p li,
ul li,
ol li {
list-style-position: inside;
margin-left: 5px;
}
a {
color: #4AC694;
text-decoration: underline;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%; }
.btn > tbody > tr > td {
padding-bottom: 15px; }
.btn table {
min-width: auto;
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 5px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 1px #4AC694;
border-radius: 5px;
box-sizing: border-box;
color: #4AC694;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 25px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #4AC694;
background-image: linear-gradient(#4AC694, #4AC694);
}
.btn-primary a {
background-color: #4AC694;
background-image: linear-gradient(#4AC694, #4AC694);
border-color: #4AC694;
color: #fffffe;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
hr {
border: 0;
border-bottom: 1px solid #f6f6f6;
Margin: 20px 0;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] p,
table[class=body] ul,
table[class=body] ol,
table[class=body] td,
table[class=body] span,
table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper,
table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
max-width: 100% !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
margin-left: auto !important;
margin-right: auto !important;
}
/* What it does: Forces table cells into full-width rows. */
.stack-column,
.stack-column-center {
display: block !important;
width: 100% !important;
max-width: 100% !important;
direction: ltr !important;
width: auto !important;
}
/* And center justify these ones. */
.stack-column-center {
text-align: center !important;
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
/* What it does: Generic utility class for centering. Useful for images, buttons, and nested tables. */
.center-on-narrow {
text-align: center !important;
display: block !important;
margin-left: auto !important;
margin-right: auto !important;
float: none !important;
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
table.center-on-narrow {
display: inline-block !important;
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
/* What it does: Adjust typography on small screens to improve readability */
.email-container p {
font-size: 17px !important;
line-height: 22px !important;
.btn-primary table td:hover {
background-color: #d5075d !important;
}
.btn-primary a:hover {
background-color: #d5075d !important;
border-color: #d5075d !important;
}
}
</style>
<!-- What it does: Makes background images in 72ppi Outlook render at correct size. -->
<!--[if gte mso 9]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]-->
</head>
<body class="">
<body width="100%" bgcolor="#F1F1F1" style="margin: 0; mso-line-height-rule: exactly;">
<center style="width: 100%; background: #F1F1F1; text-align: left;">
<!-- Visually Hidden Preheader Text : BEGIN -->
<div style="display:none;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;mso-hide:all;font-family: sans-serif;"> Your account's email has been updated on {{InvitingUser}}'s Kavita instance. Click the button to validate your email.</div>
<!-- Visually Hidden Preheader Text : END -->
<!--
Set the email width. Defined in two places:
1. max-width for all clients except Desktop Windows Outlook, allowing the email to squish on narrow but never go wider than 680px.
2. MSO tags for Desktop Windows Outlook enforce a 680px width.
Note: The Fluid and Responsive templates have a different width (600px). The hybrid grid is more "fragile", and I've found that 680px is a good width. Change with caution.
-->
<div style="max-width: 680px; margin: auto;" class="email-container">
<!--[if mso]>
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="680" align="center">
<tr>
<td>
<![endif]-->
<!-- Email Body : BEGIN -->
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="center" width="100%" style="max-width: 680px;" class="email-container">
<!-- HEADER : BEGIN -->
<tr>
<td bgcolor="#4AC694">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="margin-left: -10px;padding: 10px 40px 10px 40px; text-align: center;"> <img src="https://www.kavitareader.com/img/email/logo-256.png" alt="kavita_logo" width="75" style="height:auto;display:inline-block;vertical-align:middle;" />
<div style="min-height:75px;line-height:75px;display:inline-block;vertical-align:middle;color:#fff;font-family: 'Spartan', sans-serif;font-size:2rem;font-weight:700;">Kavita</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- HEADER : END -->
<!-- HERO : BEGIN -->
<tr>
<td bgcolor="#fff" align="center" valign="top" style="text-align: center; background-position: center center !important; background-size: cover !important;">
<!--[if gte mso 9]>
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:680px; height:380px; background-position: center center !important;">
<v:fill type="tile" src="background.png" color="#222222" />
<v:textbox inset="0,0,0,0">
<![endif]-->
<div>
<!--[if mso]>
<table role="presentation" border="0" cellspacing="0" cellpadding="0" align="center" width="500">
<!-- Visually Hidden Preheader Text-->
<div style="display:none;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;mso-hide:all;font-family: sans-serif;">{{Preheader}}</div>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td class="container">
<div class="header">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td align="center" valign="middle" width="500">
<![endif]-->
<table role="presentation" border="0" cellpadding="0" cellspacing="0" align="center" width="100%" style="max-width:500px; margin: auto;">
<tr>
<td height="20" style="font-size:20px; line-height:20px;">&nbsp;</td>
</tr>
<tr>
<td align="center" valign="middle">
{{Body}}
<td class="align-center" width="100%">
<a class="header-text" href="https://www.kavitareader.com" target="_blank">
<img class="light-img" src="https://www.kavitareader.com/img/email/email-logo.png" alt="Kavita" width="40" style="vertical-align:middle;" />
<!--[if !mso]><! -->
<img class="dark-img" src="https://www.kavitareader.com/img/email/email-logo.png" alt="Kavita" width="40" style="vertical-align:middle;" />
<!--<![endif]-->
</a>
</td>
</tr>
<tr>
<td height="20" style="font-size:20px; line-height:20px;">&nbsp;</td>
</tr>
</table>
</div>
<div class="content">
<table role="presentation" class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
{{Body}}
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
<div class="gmail-blend-screen">
<div class="gmail-blend-difference">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block" style="text-align: center;">
<table align="center" style="text-align: center;">
<tr>
<td class="icon">
<a href="https://discord.gg/b52wT37kt7" target="_blank">
Discord
</a>
</td>
<td class="icon">
<a href="https://github.com/Kareadita/Kavita/">
Github
</a>
</td>
<td class="icon">
<a href="https://wiki.kavitareader.com/en">
Wiki
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</td>
</tr>
<tr>
<!-- SOCIAL : BEGIN -->
<tr>
<td bgcolor="#292828">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="padding: 15px 30px; text-align: center;">
<table align="center" style="text-align: center;">
<tr>
<td>
<a href="https://discord.gg/b52wT37kt7"><img style="width:25px" src="https://www.kavitareader.com/img/email/discord-white.png" width="" height="" style="margin:0; padding:0; border:none; display:block;" border="0" alt="Discord"></a>
</td>
<td width="20">&nbsp;</td>
<td>
<a href="https://www.reddit.com/r/KavitaManga/"><img style="width:25px" src="https://www.kavitareader.com/img/email/reddit-white.png" width="" height="" style="margin:0; padding:0; border:none; display:block;" border="0" alt="Reddit"></a>
</td>
<td width="20">&nbsp;</td>
<td>
<a href="https://github.com/Kareadita/Kavita/"><img style="width:25px" src="https://www.kavitareader.com/img/email/github-white.png" width="" height="" style="margin:0; padding:0; border:none; display:block;" border="0" alt="Github"></a>
</td>
<td width="20">&nbsp;</td>
<td>
<a href="https://opencollective.com/kavita"><img style="width:25px" src="https://www.kavitareader.com/img/email/open-collective-white.png" width="" height="" style="margin:0; padding:0; border:none; display:block;" border="0" alt="Open Collective"></a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- SOCIAL : END -->
</tr>
</table>
<!--[if mso]>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER -->
</div>
</td>
</tr>
</table>
<![endif]-->
</div>
<!--[if gte mso 9]>
</v:textbox>
</v:rect>
<![endif]-->
</td>
</tr>
<!-- HERO : END -->
</table>
<!-- Email Body : END -->
<!--[if mso]>
</td>
</tr>
</table>
<![endif]-->
</div>
</center>
</table>
</body>
</html>

View File

@ -20,10 +20,11 @@ namespace API.Services;
internal class EmailOptionsDto
{
public IList<string> ToEmails { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public IList<KeyValuePair<string, string>> PlaceHolders { get; set; }
public required IList<string> ToEmails { get; set; }
public required string Subject { get; set; }
public required string Body { get; set; }
public required string Preheader { get; set; }
public IList<KeyValuePair<string, string>>? PlaceHolders { get; set; }
/// <summary>
/// Filenames to attach
/// </summary>
@ -81,7 +82,6 @@ public class EmailService : IEmailService
return result;
}
// TODO: Come back and update the template. We can't do it with the v0.8.0 release
var placeholders = new List<KeyValuePair<string, string>>
{
new ("{{Host}}", settings.HostName),
@ -91,8 +91,9 @@ public class EmailService : IEmailService
{
var emailOptions = new EmailOptionsDto()
{
Subject = "KavitaEmail Test",
Subject = "Kavita - Email Test",
Body = UpdatePlaceHolders(await GetEmailBody("EmailTest"), placeholders),
Preheader = "Kavita - Email Test",
ToEmails = new List<string>()
{
adminEmail
@ -127,6 +128,7 @@ public class EmailService : IEmailService
{
Subject = UpdatePlaceHolders("Your email has been changed on {{InvitingUser}}'s Server", placeholders),
Body = UpdatePlaceHolders(await GetEmailBody("EmailChange"), placeholders),
Preheader = UpdatePlaceHolders("Your email has been changed on {{InvitingUser}}'s Server", placeholders),
ToEmails = new List<string>()
{
data.EmailAddress
@ -182,6 +184,7 @@ public class EmailService : IEmailService
{
Subject = UpdatePlaceHolders("You've been invited to join {{InvitingUser}}'s Server", placeholders),
Body = UpdatePlaceHolders(await GetEmailBody("EmailConfirm"), placeholders),
Preheader = UpdatePlaceHolders("You've been invited to join {{InvitingUser}}'s Server", placeholders),
ToEmails = new List<string>()
{
data.EmailAddress
@ -207,6 +210,7 @@ public class EmailService : IEmailService
{
Subject = UpdatePlaceHolders("A password reset has been requested", placeholders),
Body = UpdatePlaceHolders(await GetEmailBody("EmailPasswordReset"), placeholders),
Preheader = "A password reset has been requested",
ToEmails = new List<string>()
{
dto.EmailAddress
@ -225,6 +229,7 @@ public class EmailService : IEmailService
var emailOptions = new EmailOptionsDto()
{
Subject = "Send file from Kavita",
Preheader = "File(s) sent from Kavita",
ToEmails = new List<string>()
{
data.DestinationEmail
@ -249,7 +254,8 @@ public class EmailService : IEmailService
// Inject the body into the base template
var fullBody = UpdatePlaceHolders(await GetEmailBody("base"), new List<KeyValuePair<string, string>>()
{
new ("{{Body}}", userEmailOptions.Body)
new ("{{Body}}", userEmailOptions.Body),
new ("{{Preheader}}", userEmailOptions.Preheader),
});
var body = new BodyBuilder
@ -320,7 +326,7 @@ public class EmailService : IEmailService
return body;
}
private static string UpdatePlaceHolders(string text, IList<KeyValuePair<string, string>> keyValuePairs)
private static string UpdatePlaceHolders(string text, IList<KeyValuePair<string, string>>? keyValuePairs)
{
if (string.IsNullOrEmpty(text) || keyValuePairs == null) return text;

View File

@ -531,8 +531,24 @@ public class ReaderService : IReaderService
if (!await _unitOfWork.AppUserProgressRepository.AnyUserProgressForSeriesAsync(seriesId, userId))
{
// I think i need a way to sort volumes last
return volumes.OrderBy(v => v.MinNumber.ToString(CultureInfo.InvariantCulture).AsDouble(), _chapterSortComparer).First().Chapters
.OrderBy(c => c.Number.AsFloat()).First();
var chapters = volumes.OrderBy(v => v.MinNumber, _chapterSortComparer).First().Chapters
.OrderBy(c => c.Number.AsFloat())
.ToList();
// If there are specials, then return the first Non-special
if (chapters.Exists(c => c.IsSpecial))
{
var firstChapter = chapters.FirstOrDefault(c => !c.IsSpecial);
if (firstChapter == null)
{
// If there is no non-special chapter, then return first chapter
return chapters[0];
}
return firstChapter;
}
// Else use normal logic
return chapters[0];
}
// Loop through all chapters that are not in volume 0

View File

@ -130,7 +130,7 @@ public class VersionUpdaterService : IVersionUpdaterService
{
if (update == null) return;
var updateVersion = new Version(update.CurrentVersion);
var updateVersion = new Version(update.UpdateVersion);
if (BuildInfo.Version < updateVersion)
{
@ -138,12 +138,6 @@ public class VersionUpdaterService : IVersionUpdaterService
await _eventHub.SendMessageAsync(MessageFactory.UpdateAvailable, MessageFactory.UpdateVersionEvent(update),
true);
}
else if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == Environments.Development)
{
_logger.LogWarning("Server is up to date. Current: {CurrentVersion}", BuildInfo.Version);
await _eventHub.SendMessageAsync(MessageFactory.UpdateAvailable, MessageFactory.UpdateVersionEvent(update),
true);
}
}

View File

@ -615,6 +615,7 @@
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.1.0.tgz",
"integrity": "sha512-WDpO4WvC5ItjaRexnpFpKPpT+cu+5GYkWF8h74iHhfxOgU+gaQiMWERHylWCqF25AzmhKu0iI3ZZtaIJ6qqwog==",
"dev": true,
"dependencies": {
"@babel/core": "7.23.2",
"@jridgewell/sourcemap-codec": "^1.4.14",
@ -5542,6 +5543,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@ -5787,6 +5789,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -6092,6 +6095,7 @@
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"funding": [
{
"type": "individual",
@ -6340,7 +6344,8 @@
"node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"dev": true
},
"node_modules/cookie": {
"version": "0.5.0",
@ -7230,6 +7235,7 @@
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"dev": true,
"optional": true,
"dependencies": {
"iconv-lite": "^0.6.2"
@ -7239,6 +7245,7 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"optional": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@ -8318,6 +8325,7 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@ -9092,6 +9100,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
@ -10868,6 +10877,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -12258,6 +12268,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
@ -12268,7 +12279,8 @@
"node_modules/reflect-metadata": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
"dev": true
},
"node_modules/regenerate": {
"version": "1.4.2",
@ -12720,7 +12732,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"devOptional": true
"dev": true
},
"node_modules/sass": {
"version": "1.69.7",
@ -12836,6 +12848,7 @@
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
@ -12850,6 +12863,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
@ -12860,7 +12874,8 @@
"node_modules/semver/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/send": {
"version": "0.18.0",
@ -13967,6 +13982,7 @@
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"

View File

@ -13,7 +13,7 @@ import {
OnInit,
ViewChild
} from '@angular/core';
import {DOCUMENT, NgStyle, NgIf, NgFor, NgSwitch, NgSwitchCase, PercentPipe, NgClass, AsyncPipe} from '@angular/common';
import {AsyncPipe, DOCUMENT, NgClass, NgFor, NgIf, NgStyle, NgSwitch, NgSwitchCase, PercentPipe} from '@angular/common';
import {ActivatedRoute, Router} from '@angular/router';
import {
BehaviorSubject,
@ -29,9 +29,9 @@ import {
take,
tap
} from 'rxjs';
import { ChangeContext, LabelType, Options, NgxSliderModule } from 'ngx-slider-v2';
import {ChangeContext, LabelType, NgxSliderModule, Options} from 'ngx-slider-v2';
import {animate, state, style, transition, trigger} from '@angular/animations';
import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import {FormBuilder, FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
import {NgbModal, NgbProgressbar} from '@ng-bootstrap/ng-bootstrap';
import {ToastrService} from 'ngx-toastr';
import {ShortcutsModalComponent} from 'src/app/reader-shared/_modals/shortcuts-modal/shortcuts-modal.component';
@ -61,12 +61,12 @@ import {ChapterInfo} from '../../_models/chapter-info';
import {DoubleNoCoverRendererComponent} from '../double-renderer-no-cover/double-no-cover-renderer.component';
import {SwipeEvent} from 'src/app/ng-swipe/ag-swipe.core';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import { FullscreenIconPipe } from '../../../_pipes/fullscreen-icon.pipe';
import { ReaderModeIconPipe } from '../../../_pipes/reader-mode-icon.pipe';
import { FittingIconPipe } from '../../../_pipes/fitting-icon.pipe';
import { InfiniteScrollerComponent } from '../infinite-scroller/infinite-scroller.component';
import { SwipeDirective } from '../../../ng-swipe/ng-swipe.directive';
import { LoadingComponent } from '../../../shared/loading/loading.component';
import {FullscreenIconPipe} from '../../../_pipes/fullscreen-icon.pipe';
import {ReaderModeIconPipe} from '../../../_pipes/reader-mode-icon.pipe';
import {FittingIconPipe} from '../../../_pipes/fitting-icon.pipe';
import {InfiniteScrollerComponent} from '../infinite-scroller/infinite-scroller.component';
import {SwipeDirective} from '../../../ng-swipe/ng-swipe.directive';
import {LoadingComponent} from '../../../shared/loading/loading.component';
import {translate, TranslocoDirective} from "@ngneat/transloco";
import {shareReplay} from "rxjs/operators";
@ -676,11 +676,6 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
}
break;
case ReaderMode.Webtoon:
if (event.key === KEY_CODES.DOWN_ARROW) {
this.nextPage()
} else if (event.key === KEY_CODES.UP_ARROW) {
this.prevPage()
}
break;
}
@ -1220,14 +1215,14 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
this.pagingDirectionSubject.next(PAGING_DIRECTION.BACKWARDS);
const pageAmount = Math.max(this.canvasRenderer.getPageAmount(PAGING_DIRECTION.BACKWARDS),
const pageAmount = this.readerMode === ReaderMode.Webtoon ? 1 : Math.max(this.canvasRenderer.getPageAmount(PAGING_DIRECTION.BACKWARDS),
this.singleRenderer.getPageAmount(PAGING_DIRECTION.BACKWARDS),
this.doubleRenderer.getPageAmount(PAGING_DIRECTION.BACKWARDS),
this.doubleNoCoverRenderer.getPageAmount(PAGING_DIRECTION.BACKWARDS),
this.doubleReverseRenderer.getPageAmount(PAGING_DIRECTION.BACKWARDS)
);
const notInSplit = this.canvasRenderer.shouldMovePrev();
const notInSplit = this.readerMode === ReaderMode.Webtoon ? true : this.canvasRenderer.shouldMovePrev();
if ((this.pageNum - 1 < 0 && notInSplit)) {
// Move to next volume/chapter automatically

View File

@ -32,7 +32,8 @@
</div>
<div class="mb-3">
<label for="library-type" class="form-label">{{t('type-label')}}</label><i class="fa fa-info-circle ms-1" placement="right" [ngbTooltip]="typeTooltip" role="button" tabindex="0"></i>
<label for="library-type" class="form-label">{{t('type-label')}}</label>
<i class="fa fa-info-circle ms-1" placement="right" [ngbTooltip]="typeTooltip" role="button" tabindex="0"></i>
<ng-template #typeTooltip>{{t('type-tooltip')}}</ng-template>
<span class="visually-hidden" id="library-type-help">
<ng-container [ngTemplateOutlet]="typeTooltip"></ng-container>
@ -233,7 +234,7 @@
</div>
</form>
<div class="modal-footer">
<button type="button" class="btn btn-light" (click)="forceScan()" position="above"
<button type="button" class="btn btn-light" (click)="forceScan()" [placement]="'above'"
[ngbTooltip]="t('force-scan-tooltip')">{{t('force-scan')}}</button>
<button type="button" class="btn btn-light" (click)="reset()">{{t('reset')}}</button>
<button type="button" class="btn btn-secondary" (click)="close()">{{t('cancel')}}</button>

View File

@ -7,7 +7,7 @@
"name": "GPL-3.0",
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
},
"version": "0.7.13.20"
"version": "0.7.13.21"
},
"servers": [
{