Refactored how system fonts were loaded (at least covered for local development) so that instead of going through the api, they are instead resolved by using assets/fonts/{fontName}/{fontFile}.
This commit is contained in:
parent
9fae799c63
commit
58800c0b4e
88 changed files with 177 additions and 97 deletions
|
@ -6,18 +6,15 @@ using System.Threading.Tasks;
|
|||
using API.Constants;
|
||||
using API.Data;
|
||||
using API.DTOs.Font;
|
||||
using API.Extensions;
|
||||
using API.Entities.Enums.Font;
|
||||
using API.Services;
|
||||
using API.Services.Tasks;
|
||||
using API.Services.Tasks.Scanner.Parser;
|
||||
using AutoMapper;
|
||||
using Kavita.Common;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MimeTypes;
|
||||
using Serilog;
|
||||
|
||||
namespace API.Controllers;
|
||||
|
||||
|
@ -25,72 +22,98 @@ public class FontController : BaseApiController
|
|||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IDirectoryService _directoryService;
|
||||
private readonly ITaskScheduler _taskScheduler;
|
||||
private readonly IFontService _fontService;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly Regex _fontFileExtensionRegex = new(Parser.FontFileExtensions, RegexOptions.IgnoreCase, Parser.RegexTimeout);
|
||||
|
||||
public FontController(IUnitOfWork unitOfWork, ITaskScheduler taskScheduler, IDirectoryService directoryService,
|
||||
public FontController(IUnitOfWork unitOfWork, IDirectoryService directoryService,
|
||||
IFontService fontService, IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_directoryService = directoryService;
|
||||
_taskScheduler = taskScheduler;
|
||||
_fontService = fontService;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
[ResponseCache(CacheProfileName = "10Minute")]
|
||||
/// <summary>
|
||||
/// List out the fonts
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[ResponseCache(CacheProfileName = ResponseCacheProfiles.TenMinute)]
|
||||
[HttpGet("all")]
|
||||
public async Task<ActionResult<IEnumerable<EpubFontDto>>> GetFonts()
|
||||
{
|
||||
return Ok(await _unitOfWork.EpubFontRepository.GetFontDtosAsync());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a font
|
||||
/// </summary>
|
||||
/// <param name="fontId"></param>
|
||||
/// <param name="apiKey"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> GetFont(int fontId, string apiKey)
|
||||
{
|
||||
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
|
||||
|
||||
if (userId == 0) return BadRequest();
|
||||
|
||||
var font = await _unitOfWork.EpubFontRepository.GetFontAsync(fontId);
|
||||
|
||||
if (font == null) return NotFound();
|
||||
|
||||
// var fontDirectory = _directoryService.EpubFontDirectory;
|
||||
// if (font.Provider == FontProvider.System)
|
||||
// {
|
||||
// fontDirectory = _directoryService.
|
||||
// }
|
||||
|
||||
var contentType = MimeTypeMap.GetMimeType(Path.GetExtension(font.FileName));
|
||||
var path = Path.Join(_directoryService.EpubFontDirectory, font.FileName);
|
||||
|
||||
return PhysicalFile(path, contentType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a font from the system
|
||||
/// </summary>
|
||||
/// <param name="fontId"></param>
|
||||
/// <param name="confirmed">If the font is in use by other users and an admin wants it deleted, they must confirm to force delete it</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
public async Task<IActionResult> DeleteFont(int fontId)
|
||||
public async Task<IActionResult> DeleteFont(int fontId, bool confirmed = false)
|
||||
{
|
||||
// TODO: We need to check if this font is used by anyone else and if so, need to inform the user
|
||||
// Need to check if this is a system font as well
|
||||
var forceDelete = User.IsInRole(PolicyConstants.AdminRole) && confirmed;
|
||||
await _fontService.Delete(fontId);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manual upload
|
||||
/// </summary>
|
||||
/// <param name="formFile"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("upload")]
|
||||
public async Task<ActionResult<EpubFontDto>> UploadFont(IFormFile formFile)
|
||||
{
|
||||
if (!_fontFileExtensionRegex.IsMatch(Path.GetExtension(formFile.FileName)))
|
||||
return BadRequest("Invalid file");
|
||||
if (!_fontFileExtensionRegex.IsMatch(Path.GetExtension(formFile.FileName))) return BadRequest("Invalid file");
|
||||
|
||||
if (formFile.FileName.Contains("..")) return BadRequest("Invalid file");
|
||||
|
||||
if (formFile.FileName.Contains(".."))
|
||||
return BadRequest("Invalid file");
|
||||
|
||||
var tempFile = await UploadToTemp(formFile);
|
||||
var font = await _fontService.CreateFontFromFileAsync(tempFile);
|
||||
return Ok(_mapper.Map<EpubFontDto>(font));
|
||||
}
|
||||
|
||||
[HttpPost("upload-url")]
|
||||
public async Task<ActionResult<EpubFontDto>> UploadFontByUrl(string url)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
// [HttpPost("upload-url")]
|
||||
// public async Task<ActionResult<EpubFontDto>> UploadFontByUrl(string url)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
private async Task<string> UploadToTemp(IFormFile file)
|
||||
{
|
||||
|
|
|
@ -40,7 +40,7 @@ public class ThemeController : BaseApiController
|
|||
_mapper = mapper;
|
||||
}
|
||||
|
||||
[ResponseCache(CacheProfileName = "10Minute")]
|
||||
[ResponseCache(CacheProfileName = ResponseCacheProfiles.TenMinute)]
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<IEnumerable<SiteThemeDto>>> GetThemes()
|
||||
|
|
|
@ -8,6 +8,6 @@ public class EpubFontDto
|
|||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public FontProvider Provider { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public string FileName { get; set; }
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Threading.Tasks;
|
||||
using API.DTOs.Font;
|
||||
using API.Entities;
|
||||
using API.Extensions;
|
||||
using AutoMapper;
|
||||
using AutoMapper.QueryableExtensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
@ -52,6 +53,8 @@ public class EpubFontRepository: IEpubFontRepository
|
|||
public async Task<IEnumerable<EpubFontDto>> GetFontDtosAsync()
|
||||
{
|
||||
return await _context.EpubFont
|
||||
.OrderBy(s => s.Name == "Default" ? -1 : 0)
|
||||
.ThenBy(s => s)
|
||||
.ProjectTo<EpubFontDto>(_mapper.ConfigurationProvider)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
@ -67,7 +70,7 @@ public class EpubFontRepository: IEpubFontRepository
|
|||
public async Task<EpubFontDto?> GetFontDtoByNameAsync(string name)
|
||||
{
|
||||
return await _context.EpubFont
|
||||
.Where(f => f.Name.Equals(name))
|
||||
.Where(f => f.NormalizedName.Equals(name.ToNormalized()))
|
||||
.ProjectTo<EpubFontDto>(_mapper.ConfigurationProvider)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
|
|
@ -32,13 +32,90 @@ public static class Seed
|
|||
[
|
||||
..new List<EpubFont>
|
||||
{
|
||||
new ()
|
||||
{
|
||||
Name = "Default",
|
||||
NormalizedName = Parser.Normalize("Default"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = string.Empty,
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Merriweather",
|
||||
NormalizedName = Parser.Normalize("Merriweather"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "Merriweather-Regular.woff2",
|
||||
}
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "EB Garamond",
|
||||
NormalizedName = Parser.Normalize("EB Garamond"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "EBGaramond-VariableFont_wght.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Fira Sans",
|
||||
NormalizedName = Parser.Normalize("Fira Sans"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "FiraSans-Regular.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Lato",
|
||||
NormalizedName = Parser.Normalize("Lato"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "Lato-Regular.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Libre Baskerville",
|
||||
NormalizedName = Parser.Normalize("Libre Baskerville"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "LibreBaskerville-Regular.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Libre Caslon",
|
||||
NormalizedName = Parser.Normalize("Libre Caslon"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "LibreCaslonText-Regular.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Nanum Gothic",
|
||||
NormalizedName = Parser.Normalize("Nanum Gothic"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "NanumGothic-Regular.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Open Dyslexic 2",
|
||||
NormalizedName = Parser.Normalize("Open Dyslexic 2"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "OpenDyslexic-Regular.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Oswald",
|
||||
NormalizedName = Parser.Normalize("Oswald"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "Oswald-VariableFont_wght.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "RocknRoll One",
|
||||
NormalizedName = Parser.Normalize("RocknRoll One"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "RocknRollOne-Regular.woff2",
|
||||
},
|
||||
new ()
|
||||
{
|
||||
Name = "Spartan",
|
||||
NormalizedName = Parser.Normalize("Spartan"),
|
||||
Provider = FontProvider.System,
|
||||
FileName = "Spartan-VariableFont_wght.woff2",
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -159,7 +236,7 @@ public static class Seed
|
|||
|
||||
foreach (var theme in DefaultThemes)
|
||||
{
|
||||
var existing = context.SiteTheme.FirstOrDefault(s => s.Name.Equals(theme.Name));
|
||||
var existing = await context.SiteTheme.FirstOrDefaultAsync(s => s.Name.Equals(theme.Name));
|
||||
if (existing == null)
|
||||
{
|
||||
await context.SiteTheme.AddAsync(theme);
|
||||
|
@ -172,9 +249,10 @@ public static class Seed
|
|||
public static async Task SeedFonts(DataContext context)
|
||||
{
|
||||
await context.Database.EnsureCreatedAsync();
|
||||
|
||||
foreach (var font in DefaultFonts)
|
||||
{
|
||||
var existing = context.SiteTheme.FirstOrDefaultAsync(f => f.Name.Equals(font.Name));
|
||||
var existing = await context.EpubFont.FirstOrDefaultAsync(f => f.Name.Equals(font.Name));
|
||||
if (existing == null)
|
||||
{
|
||||
await context.EpubFont.AddAsync(font);
|
||||
|
@ -290,7 +368,7 @@ public static class Seed
|
|||
|
||||
foreach (var defaultSetting in DefaultSettings)
|
||||
{
|
||||
var existing = context.ServerSetting.FirstOrDefault(s => s.Key == defaultSetting.Key);
|
||||
var existing = await context.ServerSetting.FirstOrDefaultAsync(s => s.Key == defaultSetting.Key);
|
||||
if (existing == null)
|
||||
{
|
||||
await context.ServerSetting.AddAsync(defaultSetting);
|
||||
|
@ -300,15 +378,15 @@ public static class Seed
|
|||
await context.SaveChangesAsync();
|
||||
|
||||
// Port, IpAddresses and LoggingLevel are managed in appSettings.json. Update the DB values to match
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.Port).Value =
|
||||
(await context.ServerSetting.FirstAsync(s => s.Key == ServerSettingKey.Port)).Value =
|
||||
Configuration.Port + string.Empty;
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.IpAddresses).Value =
|
||||
(await context.ServerSetting.FirstAsync(s => s.Key == ServerSettingKey.IpAddresses)).Value =
|
||||
Configuration.IpAddresses;
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.CacheDirectory).Value =
|
||||
(await context.ServerSetting.FirstAsync(s => s.Key == ServerSettingKey.CacheDirectory)).Value =
|
||||
directoryService.CacheDirectory + string.Empty;
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.BackupDirectory).Value =
|
||||
(await context.ServerSetting.FirstAsync(s => s.Key == ServerSettingKey.BackupDirectory)).Value =
|
||||
DirectoryService.BackupDirectory + string.Empty;
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.CacheSize).Value =
|
||||
(await context.ServerSetting.FirstAsync(s => s.Key == ServerSettingKey.CacheSize)).Value =
|
||||
Configuration.CacheSize + string.Empty;
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
|
|
|
@ -79,16 +79,14 @@ public class FontService: IFontService
|
|||
}
|
||||
|
||||
var font = await _unitOfWork.EpubFontRepository.GetFontAsync(fontId);
|
||||
if (font == null)
|
||||
return;
|
||||
if (font == null) return;
|
||||
|
||||
await RemoveFont(font);
|
||||
}
|
||||
|
||||
public async Task RemoveFont(EpubFont font)
|
||||
{
|
||||
if (font.Provider == FontProvider.System)
|
||||
return;
|
||||
if (font.Provider == FontProvider.System) return;
|
||||
|
||||
var prefs = await _unitOfWork.UserRepository.GetAllPreferencesByFontAsync(font.Name);
|
||||
foreach (var pref in prefs)
|
||||
|
|
|
@ -13,6 +13,5 @@ export interface EpubFont {
|
|||
id: number;
|
||||
name: string;
|
||||
provider: FontProvider;
|
||||
created: Date;
|
||||
lastModified: Date;
|
||||
fileName: string;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import {DestroyRef, inject, Injectable} from "@angular/core";
|
||||
import {map, ReplaySubject} from "rxjs";
|
||||
import {EpubFont} from "../_models/preferences/epub-font";
|
||||
import {EpubFont, FontProvider} from "../_models/preferences/epub-font";
|
||||
import {environment} from 'src/environments/environment';
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {EVENTS, MessageHubService} from "./message-hub.service";
|
||||
import {MessageHubService} from "./message-hub.service";
|
||||
import {NgxFileDropEntry} from "ngx-file-drop";
|
||||
import {AccountService} from "./account.service";
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {NotificationProgressEvent} from "../_models/events/notification-progress-event";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@ -41,6 +40,10 @@ export class FontService {
|
|||
}
|
||||
|
||||
getFontFace(font: EpubFont): FontFace {
|
||||
if (font.provider === FontProvider.System) {
|
||||
return new FontFace(font.name, `url('/assets/fonts/${font.name}/${font.fileName}')`);
|
||||
}
|
||||
|
||||
return new FontFace(font.name, `url(${this.baseUrl}font?fontId=${font.id}&apiKey=${this.encodedKey})`);
|
||||
}
|
||||
|
||||
|
|
|
@ -588,6 +588,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.fontService.getFonts().subscribe(fonts => {
|
||||
fonts.forEach(font => {
|
||||
this.fontService.getFontFace(font).load().then(loadedFace => {
|
||||
console.log('loaded font: ', loadedFace);
|
||||
(this.document as any).fonts.add(loadedFace);
|
||||
});
|
||||
})
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
<div class="mb-3">
|
||||
<label for="library-type" class="form-label">{{t('font-family-label')}}</label>
|
||||
<select class="form-select" id="library-type" formControlName="bookReaderFontFamily">
|
||||
<option [value]="opt" *ngFor="let opt of fontOptions; let i = index">{{opt | titlecase}}</option>
|
||||
@for(opt of fontFamilies; track opt) {
|
||||
<option [value]="opt.name">{{opt.name | titlecase}}</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -85,6 +85,7 @@ export const bookColorThemes = [
|
|||
];
|
||||
|
||||
const mobileBreakpointMarginOverride = 700;
|
||||
const defaultFontFamily = 'Default';
|
||||
|
||||
@Component({
|
||||
selector: 'app-reader-settings',
|
||||
|
@ -132,7 +133,6 @@ export class ReaderSettingsComponent implements OnInit {
|
|||
/**
|
||||
* List of all font families user can select from
|
||||
*/
|
||||
fontOptions: Array<string> = [];
|
||||
fontFamilies: Array<EpubFont> = [];
|
||||
/**
|
||||
* Internal property used to capture all the different css properties to render on all elements
|
||||
|
@ -178,7 +178,6 @@ export class ReaderSettingsComponent implements OnInit {
|
|||
ngOnInit(): void {
|
||||
this.fontService.getFonts().subscribe(fonts => {
|
||||
this.fontFamilies = fonts;
|
||||
this.fontOptions = fonts.map(f => f.name);
|
||||
this.cdRef.markForCheck();
|
||||
})
|
||||
|
||||
|
@ -187,7 +186,7 @@ export class ReaderSettingsComponent implements OnInit {
|
|||
this.user = user;
|
||||
|
||||
if (this.user.preferences.bookReaderFontFamily === undefined) {
|
||||
this.user.preferences.bookReaderFontFamily = 'default';
|
||||
this.user.preferences.bookReaderFontFamily = defaultFontFamily;
|
||||
}
|
||||
if (this.user.preferences.bookReaderFontSize === undefined || this.user.preferences.bookReaderFontSize < 50) {
|
||||
this.user.preferences.bookReaderFontSize = 100;
|
||||
|
@ -211,7 +210,8 @@ export class ReaderSettingsComponent implements OnInit {
|
|||
|
||||
this.settingsForm.addControl('bookReaderFontFamily', new FormControl(this.user.preferences.bookReaderFontFamily, []));
|
||||
this.settingsForm.get('bookReaderFontFamily')!.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(fontName => {
|
||||
if (fontName === 'default') {
|
||||
console.log('updating font-family to ', fontName);
|
||||
if (fontName === defaultFontFamily) {
|
||||
this.pageStyles['font-family'] = 'inherit';
|
||||
} else {
|
||||
this.pageStyles['font-family'] = "'" + fontName + "'";
|
||||
|
|
|
@ -74,7 +74,6 @@ import {ManageScrobblingProvidersComponent} from "../manage-scrobbling-providers
|
|||
import {PdfLayoutModePipe} from "../../pdf-reader/_pipe/pdf-layout-mode.pipe";
|
||||
import {PdfTheme} from "../../_models/preferences/pdf-theme";
|
||||
import {PdfScrollMode} from "../../_models/preferences/pdf-scroll-mode";
|
||||
import {PdfLayoutMode} from "../../_models/preferences/pdf-layout-mode";
|
||||
import {PdfSpreadMode} from "../../_models/preferences/pdf-spread-mode";
|
||||
import {FontManagerComponent} from "../font-manager/font-manager/font-manager.component";
|
||||
import {FontService} from "../../_services/font.service";
|
||||
|
@ -234,7 +233,7 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
|
|||
this.user.preferences = results.pref;
|
||||
|
||||
if (this.fontFamilies.indexOf(this.user.preferences.bookReaderFontFamily) < 0) {
|
||||
this.user.preferences.bookReaderFontFamily = 'default';
|
||||
this.user.preferences.bookReaderFontFamily = 'Default';
|
||||
}
|
||||
|
||||
this.settingsForm.addControl('readingDirection', new FormControl(this.user.preferences.readingDirection, []));
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
// Global Styles
|
||||
@font-face {
|
||||
font-family: "EBGarmond";
|
||||
src: url("assets/fonts/EBGarmond/EBGaramond-VariableFont_wght.woff2") format("woff2");
|
||||
src: url("assets/fonts/EB Garmond/EBGaramond-VariableFont_wght.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
|
|
68
openapi.json
68
openapi.json
|
@ -2,7 +2,7 @@
|
|||
"openapi": "3.0.1",
|
||||
"info": {
|
||||
"title": "Kavita",
|
||||
"description": "Kavita provides a set of APIs that are authenticated by JWT. JWT token can be copied from local storage. Assume all fields of a payload are required. Built against v0.8.2.0",
|
||||
"description": "Kavita provides a set of APIs that are authenticated by JWT. JWT token can be copied from local storage. Assume all fields of a payload are required. Built against v0.8.2.1",
|
||||
"license": {
|
||||
"name": "GPL-3.0",
|
||||
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
|
||||
|
@ -2319,6 +2319,7 @@
|
|||
"tags": [
|
||||
"Font"
|
||||
],
|
||||
"summary": "List out the fonts",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
|
@ -2357,10 +2358,12 @@
|
|||
"tags": [
|
||||
"Font"
|
||||
],
|
||||
"summary": "Returns a font",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "fontId",
|
||||
"in": "query",
|
||||
"description": "",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
|
@ -2369,6 +2372,7 @@
|
|||
{
|
||||
"name": "apiKey",
|
||||
"in": "query",
|
||||
"description": "",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
|
@ -2384,14 +2388,25 @@
|
|||
"tags": [
|
||||
"Font"
|
||||
],
|
||||
"summary": "Removes a font from the system",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "fontId",
|
||||
"in": "query",
|
||||
"description": "",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "confirmed",
|
||||
"in": "query",
|
||||
"description": "If the font is in use by other users and an admin wants it deleted, they must confirm to force delete it",
|
||||
"schema": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
@ -2406,6 +2421,7 @@
|
|||
"tags": [
|
||||
"Font"
|
||||
],
|
||||
"summary": "Manual upload",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"multipart/form-data": {
|
||||
|
@ -2450,44 +2466,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/Font/upload-url": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Font"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "url",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"text/plain": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/EpubFontDto"
|
||||
}
|
||||
},
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/EpubFontDto"
|
||||
}
|
||||
},
|
||||
"text/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/EpubFontDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/Health": {
|
||||
"get": {
|
||||
"tags": [
|
||||
|
@ -13818,7 +13796,7 @@
|
|||
},
|
||||
"missingSeriesFromSource": {
|
||||
"type": "string",
|
||||
"description": "A \n separated string of all missing series",
|
||||
"description": "A \r\n separated string of all missing series",
|
||||
"nullable": true
|
||||
},
|
||||
"appUser": {
|
||||
|
@ -13913,7 +13891,7 @@
|
|||
},
|
||||
"missingSeriesFromSource": {
|
||||
"type": "string",
|
||||
"description": "A \n separated string of all missing series",
|
||||
"description": "A \r\n separated string of all missing series",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
|
@ -16373,13 +16351,9 @@
|
|||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"created": {
|
||||
"fileName": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"lastModified": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue