v0.8.6.2 - General Settings Hotfix (#3756)

Co-authored-by: Amelia <77553571+Fesaa@users.noreply.github.com>
Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Lyrq <lyrq.ku@gmail.com>
Co-authored-by: Ricky Tigg <ricky.tigg@gmail.com>
Co-authored-by: 無情天 <kofzhanganguo@126.com>
This commit is contained in:
Joe Milazzo 2025-04-20 10:46:33 -06:00 committed by GitHub
parent d3f8a503c2
commit 14bf4400a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 28 additions and 10 deletions

View File

@ -28,7 +28,7 @@ body:
label: Kavita Version Number - If you don't see your version number listed, please update Kavita and see if your issue still persists. label: Kavita Version Number - If you don't see your version number listed, please update Kavita and see if your issue still persists.
multiple: false multiple: false
options: options:
- 0.8.6.1 - Stable - 0.8.6.2 - Stable
- Nightly Testing Branch - Nightly Testing Branch
validations: validations:
required: true required: true

View File

@ -13,7 +13,7 @@ name: "CodeQL"
on: on:
push: push:
branches: [ "develop", "main" ] branches: [ "develop"]
pull_request: pull_request:
# The branches below must be a subset of the branches above # The branches below must be a subset of the branches above
branches: [ "develop" ] branches: [ "develop" ]

View File

@ -115,6 +115,7 @@
<None Remove="Hangfire-log.db" /> <None Remove="Hangfire-log.db" />
<None Remove="obj\**" /> <None Remove="obj\**" />
<None Remove="cache\**" /> <None Remove="cache\**" />
<None Remove="cache-long\**" />
<None Remove="backups\**" /> <None Remove="backups\**" />
<None Remove="logs\**" /> <None Remove="logs\**" />
<None Remove="temp\**" /> <None Remove="temp\**" />

View File

@ -186,6 +186,7 @@ public class CacheService : ICacheService
} }
else else
{ {
// Potential BUG: If the folder is left here and there are no files within, this could theoretically return without proper cache
return chapter; return chapter;
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"TokenKey": "super secret unguessable key that is longer because we require it", "TokenKey": "super secret unguessable key that is longer because we require it",
"Port": 5000, "Port": 5000,
"IpAddresses": "0.0.0.0,::", "IpAddresses": "",
"BaseUrl": "/", "BaseUrl": "/",
"Cache": 75, "Cache": 75,
"AllowIFraming": false "AllowIFraming": false

View File

@ -64,7 +64,7 @@
@if (settingsForm.get('ipAddresses'); as formControl) { @if (settingsForm.get('ipAddresses'); as formControl) {
<app-setting-item [title]="t('ip-address-label')" [subtitle]="t('ip-address-tooltip')"> <app-setting-item [title]="t('ip-address-label')" [subtitle]="t('ip-address-tooltip')">
<ng-template #view> <ng-template #view>
{{formControl.value}} {{formControl.value | defaultValue}}
</ng-template> </ng-template>
<ng-template #edit> <ng-template #edit>
<div class="input-group"> <div class="input-group">
@ -75,7 +75,7 @@
@if(settingsForm.dirty || !settingsForm.untouched) { @if(settingsForm.dirty || !settingsForm.untouched) {
<div id="ipaddresses-validations" class="invalid-feedback"> <div id="ipaddresses-validations" class="invalid-feedback">
@if (formControl.errors?.pattern) { @if (formControl.errors?.emptyOrPattern) {
<div>{{t('ip-address-validation')}}</div> <div>{{t('ip-address-validation')}}</div>
} }
</div> </div>

View File

@ -1,5 +1,5 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject, OnInit} from '@angular/core'; import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject, OnInit} from '@angular/core';
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms'; import {FormControl, FormGroup, ReactiveFormsModule, ValidatorFn, Validators} from '@angular/forms';
import {ToastrService} from 'ngx-toastr'; import {ToastrService} from 'ngx-toastr';
import {take} from 'rxjs/operators'; import {take} from 'rxjs/operators';
import {ServerService} from 'src/app/_services/server.service'; import {ServerService} from 'src/app/_services/server.service';
@ -62,7 +62,7 @@ export class ManageSettingsComponent implements OnInit {
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required])); this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required])); this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
this.settingsForm.addControl('taskCleanup', new FormControl(this.serverSettings.taskCleanup, [Validators.required])); this.settingsForm.addControl('taskCleanup', new FormControl(this.serverSettings.taskCleanup, [Validators.required]));
this.settingsForm.addControl('ipAddresses', new FormControl(this.serverSettings.ipAddresses, [Validators.required, Validators.pattern(ValidIpAddress)])); this.settingsForm.addControl('ipAddresses', new FormControl(this.serverSettings.ipAddresses, [this.emptyOrPattern(ValidIpAddress)]));
this.settingsForm.addControl('port', new FormControl(this.serverSettings.port, [Validators.required])); this.settingsForm.addControl('port', new FormControl(this.serverSettings.port, [Validators.required]));
this.settingsForm.addControl('loggingLevel', new FormControl(this.serverSettings.loggingLevel, [Validators.required])); this.settingsForm.addControl('loggingLevel', new FormControl(this.serverSettings.loggingLevel, [Validators.required]));
this.settingsForm.addControl('allowStatCollection', new FormControl(this.serverSettings.allowStatCollection, [Validators.required])); this.settingsForm.addControl('allowStatCollection', new FormControl(this.serverSettings.allowStatCollection, [Validators.required]));
@ -77,6 +77,7 @@ export class ManageSettingsComponent implements OnInit {
this.settingsForm.addControl('onDeckProgressDays', new FormControl(this.serverSettings.onDeckProgressDays, [Validators.required])); this.settingsForm.addControl('onDeckProgressDays', new FormControl(this.serverSettings.onDeckProgressDays, [Validators.required]));
this.settingsForm.addControl('onDeckUpdateDays', new FormControl(this.serverSettings.onDeckUpdateDays, [Validators.required])); this.settingsForm.addControl('onDeckUpdateDays', new FormControl(this.serverSettings.onDeckUpdateDays, [Validators.required]));
// Automatically save settings as we edit them // Automatically save settings as we edit them
this.settingsForm.valueChanges.pipe( this.settingsForm.valueChanges.pipe(
distinctUntilChanged(), distinctUntilChanged(),
@ -186,4 +187,19 @@ export class ManageSettingsComponent implements OnInit {
console.error('error: ', err); console.error('error: ', err);
}); });
} }
emptyOrPattern(pattern: RegExp): ValidatorFn {
return (control) => {
if (!control.value || control.value.length === 0) {
return null;
}
if (pattern.test(control.value)) {
return null;
}
return { 'emptyOrPattern': { 'requiredPattern': pattern.toString(), 'actualValue': control.value } };
}
}
} }

View File

@ -10,7 +10,7 @@
"devices-tab": "{{tabs.devices-tab}}", "devices-tab": "{{tabs.devices-tab}}",
"smart-filters-tab": "{{tabs.smart-filters-tab}}", "smart-filters-tab": "{{tabs.smart-filters-tab}}",
"success-toast": "Käyttäjäasetukset päivitetty", "success-toast": "Käyttäjäasetukset päivitetty",
"global-settings-title": "Laajamittaiset asetukset", "global-settings-title": "Yleisesti pätevät asetukset",
"page-layout-mode-label": "Sivun asettelutila", "page-layout-mode-label": "Sivun asettelutila",
"page-layout-mode-tooltip": "Näytä kohteet kortteina tai luettelonäkymänä Sarjojen yksityiskohdat -sivulla.", "page-layout-mode-tooltip": "Näytä kohteet kortteina tai luettelonäkymänä Sarjojen yksityiskohdat -sivulla.",
"locale-label": "Kieliasetus", "locale-label": "Kieliasetus",

View File

@ -2219,12 +2219,12 @@
"delete-device": "您确定要删除该设备吗?", "delete-device": "您确定要删除该设备吗?",
"confirm-regen-covers": "刷新封面将强制重新生成所有封面图片。这是一项繁重的运算。您确定执行,而不想使用扫描操作代替吗?", "confirm-regen-covers": "刷新封面将强制重新生成所有封面图片。这是一项繁重的运算。您确定执行,而不想使用扫描操作代替吗?",
"alert-long-running": "这是一个长时间运行的任务。请等待其完成后再次进行操作。", "alert-long-running": "这是一个长时间运行的任务。请等待其完成后再次进行操作。",
"confirm-delete-multiple-series": "您确定要删除{{count}}个系列吗?这不会修改磁盘上的文件。", "confirm-delete-multiple-series": "您确定要删除{{count}} 个系列吗?这不会修改磁盘上的文件。",
"confirm-delete-series": "您确定要删除此系列吗?这不会修改磁盘上的文件。", "confirm-delete-series": "您确定要删除此系列吗?这不会修改磁盘上的文件。",
"confirm-delete-chapter": "您确定要删除此章节吗?它不会修改磁盘上的文件。", "confirm-delete-chapter": "您确定要删除此章节吗?它不会修改磁盘上的文件。",
"confirm-delete-volume": "您确定要删除此卷吗?它不会修改磁盘上的文件。", "confirm-delete-volume": "您确定要删除此卷吗?它不会修改磁盘上的文件。",
"alert-bad-theme": "主题中存在无效或不安全的CSS。请联系管理员进行修正。将默认为暗色主题。", "alert-bad-theme": "主题中存在无效或不安全的CSS。请联系管理员进行修正。将默认为暗色主题。",
"confirm-library-delete": "您确定要删除{{name}}资料库吗?此操作无法撤销。", "confirm-library-delete": "您确定要删除 {{name}} 资料库吗?此操作无法撤销。",
"confirm-library-type-change": "更改资料库类型将触发具有不同解析规则的新扫描,并可能导致重新创建系列,因此您可能会丢失进度和书签。您应该在执行此操作之前进行备份。您确定要继续吗?", "confirm-library-type-change": "更改资料库类型将触发具有不同解析规则的新扫描,并可能导致重新创建系列,因此您可能会丢失进度和书签。您应该在执行此操作之前进行备份。您确定要继续吗?",
"confirm-download-size": "{{entityType}}的大小为{{size}}。确定要继续吗?", "confirm-download-size": "{{entityType}}的大小为{{size}}。确定要继续吗?",
"confirm-download-size-ios": "iOS 在下载大于 200MB 的文件时出现问题,此下载可能无法完成。", "confirm-download-size-ios": "iOS 在下载大于 200MB 的文件时出现问题,此下载可能无法完成。",