mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-05-24 00:52:23 -04:00
* Fixed a bug where cache TTL was using a field which always was 0. * Updated Scan Series task (from UI) to always re-calculate what's on file and not rely on last update. This leads to more reliable results, despite extra overhead. * Added image range processing on images for the reader, for slower networks or large files * On manga (single) try to use prefetched image, rather than re-requesting an image on pagination * Reduced some more latency when rendering first page of next chapter via continuous reading mode * Fixed a bug where metadata filter, after updating a typeahead, collapsing filter area then re-opening, the filter would still be applied, but the typeahead wouldn't show the modification. * Coded an idea around download reporting, commiting for history, might not go with it. * Refactored the download indicator into it's own component. Cleaning up some code for download within card component * Another throw away commit. Put in some temp code, not working but not sure if I'm ditching entirely. * Updated download service to enable range processing (so downloads can resume) and to reduce re-zipping if we've just downloaded something. * Refactored events widget download indicator to the correct design. I will be moving forward with this new functionality. * Added Required fields to ProgressDTO * Cleaned up the event widget and updated existing download progress to indicate preparing the download, rather than the download itself. * Updated dependencies for security alerts * Refactored all download code to be streamlined and globally handled * Updated ScanSeries to find the highest folder path before library, not just within the files. This could lead to scan series missing files due to nested folders on same parent level. * Updated the caching code to use a builtin annotation. Images are now caching correctly. * Fixed a bad redirect on an auth guard * Tweaked how long we allow cache for, as the cover update now doesn't work well. * Fixed a bug on downloading bookmarks from multiple series, where it would just choose the first series id for the temp file. * Added an extra check for downloading bookmarks * UI Security updates, Fixed a bug on bookmark reader, the reader on last page would throw some errors and not show No Next Chapter toast. * After scan, clear temp * Code smells
457 lines
16 KiB
C#
457 lines
16 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using API.DTOs.Update;
|
|
using API.Entities;
|
|
using API.Extensions;
|
|
|
|
namespace API.SignalR
|
|
{
|
|
public static class MessageFactoryEntityTypes
|
|
{
|
|
public const string Series = "series";
|
|
public const string Volume = "volume";
|
|
public const string Chapter = "chapter";
|
|
public const string CollectionTag = "collection";
|
|
public const string ReadingList = "readingList";
|
|
}
|
|
public static class MessageFactory
|
|
{
|
|
/// <summary>
|
|
/// An update is available for the Kavita instance
|
|
/// </summary>
|
|
public const string UpdateAvailable = "UpdateAvailable";
|
|
/// <summary>
|
|
/// Used to tell when a scan series completes. This also informs UI to update series metadata
|
|
/// </summary>
|
|
public const string ScanSeries = "ScanSeries";
|
|
/// <summary>
|
|
/// Event sent out during Refresh Metadata for progress tracking
|
|
/// </summary>
|
|
private const string CoverUpdateProgress = "CoverUpdateProgress";
|
|
/// <summary>
|
|
/// Series is added to server
|
|
/// </summary>
|
|
public const string SeriesAdded = "SeriesAdded";
|
|
/// <summary>
|
|
/// Series is removed from server
|
|
/// </summary>
|
|
public const string SeriesRemoved = "SeriesRemoved";
|
|
/// <summary>
|
|
/// When a user is connects/disconnects from server
|
|
/// </summary>
|
|
public const string OnlineUsers = "OnlineUsers";
|
|
/// <summary>
|
|
/// When a series is added to a collection
|
|
/// </summary>
|
|
public const string SeriesAddedToCollection = "SeriesAddedToCollection";
|
|
/// <summary>
|
|
/// Event sent out during backing up the database
|
|
/// </summary>
|
|
private const string BackupDatabaseProgress = "BackupDatabaseProgress";
|
|
/// <summary>
|
|
/// Event sent out during cleaning up temp and cache folders
|
|
/// </summary>
|
|
private const string CleanupProgress = "CleanupProgress";
|
|
/// <summary>
|
|
/// Event sent out during downloading of files
|
|
/// </summary>
|
|
private const string DownloadProgress = "DownloadProgress";
|
|
/// <summary>
|
|
/// A cover was updated
|
|
/// </summary>
|
|
public const string CoverUpdate = "CoverUpdate";
|
|
/// <summary>
|
|
/// A custom site theme was removed or added
|
|
/// </summary>
|
|
private const string SiteThemeProgress = "SiteThemeProgress";
|
|
/// <summary>
|
|
/// A custom book theme was removed or added
|
|
/// </summary>
|
|
private const string BookThemeProgress = "BookThemeProgress";
|
|
/// <summary>
|
|
/// A type of event that has progress (determinate or indeterminate).
|
|
/// The underlying event will have a name to give details on how to handle.
|
|
/// </summary>
|
|
/// <remarks>This is not an Event Name, it is used as the method only</remarks>
|
|
public const string NotificationProgress = "NotificationProgress";
|
|
/// <summary>
|
|
/// Event sent out when Scan Loop is parsing a file
|
|
/// </summary>
|
|
private const string FileScanProgress = "FileScanProgress";
|
|
/// <summary>
|
|
/// A generic error that can occur in background processing
|
|
/// </summary>
|
|
public const string Error = "Error";
|
|
/// <summary>
|
|
/// When DB updates are occuring during a library/series scan
|
|
/// </summary>
|
|
private const string ScanProgress = "ScanProgress";
|
|
/// <summary>
|
|
/// When a library is created/deleted in the Server
|
|
/// </summary>
|
|
public const string LibraryModified = "LibraryModified";
|
|
/// <summary>
|
|
/// A user's progress was modified
|
|
/// </summary>
|
|
public const string UserProgressUpdate = "UserProgressUpdate";
|
|
/// <summary>
|
|
/// A user's account or preferences were updated and UI needs to refresh to stay in sync
|
|
/// </summary>
|
|
public const string UserUpdate = "UserUpdate";
|
|
/// <summary>
|
|
/// When bulk bookmarks are being converted
|
|
/// </summary>
|
|
private const string ConvertBookmarksProgress = "ConvertBookmarksProgress";
|
|
/// <summary>
|
|
/// When files are being scanned to calculate word count
|
|
/// </summary>
|
|
private const string WordCountAnalyzerProgress = "WordCountAnalyzerProgress";
|
|
|
|
|
|
|
|
public static SignalRMessage ScanSeriesEvent(int libraryId, int seriesId, string seriesName)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = ScanSeries,
|
|
EventType = ProgressEventType.Single,
|
|
Body = new
|
|
{
|
|
LibraryId = libraryId,
|
|
SeriesId = seriesId,
|
|
SeriesName = seriesName
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage SeriesAddedEvent(int seriesId, string seriesName, int libraryId)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = SeriesAdded,
|
|
Body = new
|
|
{
|
|
SeriesId = seriesId,
|
|
SeriesName = seriesName,
|
|
LibraryId = libraryId
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage SeriesRemovedEvent(int seriesId, string seriesName, int libraryId)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = SeriesRemoved,
|
|
Body = new
|
|
{
|
|
SeriesId = seriesId,
|
|
SeriesName = seriesName,
|
|
LibraryId = libraryId
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
public static SignalRMessage WordCountAnalyzerProgressEvent(int libraryId, float progress, string eventType, string subtitle = "")
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = WordCountAnalyzerProgress,
|
|
Title = "Analyzing Word count",
|
|
SubTitle = subtitle,
|
|
EventType = eventType,
|
|
Progress = ProgressType.Determinate,
|
|
Body = new
|
|
{
|
|
LibraryId = libraryId,
|
|
Progress = progress,
|
|
EventTime = DateTime.Now
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage CoverUpdateProgressEvent(int libraryId, float progress, string eventType, string subtitle = "")
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = CoverUpdateProgress,
|
|
Title = "Refreshing Covers",
|
|
SubTitle = subtitle,
|
|
EventType = eventType,
|
|
Progress = ProgressType.Determinate,
|
|
Body = new
|
|
{
|
|
LibraryId = libraryId,
|
|
Progress = progress,
|
|
EventTime = DateTime.Now
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage BackupDatabaseProgressEvent(float progress, string subtitle = "")
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = BackupDatabaseProgress,
|
|
Title = "Backing up Database",
|
|
SubTitle = subtitle,
|
|
EventType = progress switch
|
|
{
|
|
0f => "started",
|
|
1f => "ended",
|
|
_ => "updated"
|
|
},
|
|
Progress = ProgressType.Determinate,
|
|
Body = new
|
|
{
|
|
Progress = progress
|
|
}
|
|
};
|
|
}
|
|
public static SignalRMessage CleanupProgressEvent(float progress, string subtitle = "")
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = CleanupProgress,
|
|
Title = "Performing Cleanup",
|
|
SubTitle = subtitle,
|
|
EventType = progress switch
|
|
{
|
|
0f => "started",
|
|
1f => "ended",
|
|
_ => "updated"
|
|
},
|
|
Progress = ProgressType.Determinate,
|
|
Body = new
|
|
{
|
|
Progress = progress
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
public static SignalRMessage UpdateVersionEvent(UpdateNotificationDto update)
|
|
{
|
|
return new SignalRMessage
|
|
{
|
|
Name = UpdateAvailable,
|
|
Title = "Update Available",
|
|
SubTitle = update.UpdateTitle,
|
|
EventType = ProgressEventType.Single,
|
|
Progress = ProgressType.None,
|
|
Body = update
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage SeriesAddedToCollectionEvent(int tagId, int seriesId)
|
|
{
|
|
return new SignalRMessage
|
|
{
|
|
Name = SeriesAddedToCollection,
|
|
Progress = ProgressType.None,
|
|
EventType = ProgressEventType.Single,
|
|
Body = new
|
|
{
|
|
TagId = tagId,
|
|
SeriesId = seriesId
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* A generic error that will show on events widget in the UI
|
|
*/
|
|
public static SignalRMessage ErrorEvent(string title, string subtitle)
|
|
{
|
|
return new SignalRMessage
|
|
{
|
|
Name = Error,
|
|
Title = title,
|
|
SubTitle = subtitle,
|
|
Progress = ProgressType.None,
|
|
EventType = ProgressEventType.Single,
|
|
Body = new
|
|
{
|
|
Title = title,
|
|
SubTitle = subtitle,
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage LibraryModifiedEvent(int libraryId, string action)
|
|
{
|
|
return new SignalRMessage
|
|
{
|
|
Name = LibraryModified,
|
|
Title = "Library modified",
|
|
Progress = ProgressType.None,
|
|
EventType = ProgressEventType.Single,
|
|
Body = new
|
|
{
|
|
LibrayId = libraryId,
|
|
Action = action,
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage DownloadProgressEvent(string username, string downloadName, float progress, string eventType = "updated")
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = DownloadProgress,
|
|
Title = $"Downloading {downloadName}",
|
|
SubTitle = $"Preparing {username.SentenceCase()} the download of {downloadName}",
|
|
EventType = eventType,
|
|
Progress = ProgressType.Determinate,
|
|
Body = new
|
|
{
|
|
UserName = username,
|
|
DownloadName = downloadName,
|
|
Progress = progress
|
|
}
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a file being scanned by Kavita for processing and grouping
|
|
/// </summary>
|
|
/// <remarks>Does not have a progress as it's unknown how many files there are. Instead sends -1 to represent indeterminate</remarks>
|
|
/// <param name="filename"></param>
|
|
/// <param name="libraryName"></param>
|
|
/// <param name="eventType"></param>
|
|
/// <returns></returns>
|
|
public static SignalRMessage FileScanProgressEvent(string filename, string libraryName, string eventType)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = FileScanProgress,
|
|
Title = $"Scanning {libraryName}",
|
|
SubTitle = Path.GetFileName(filename),
|
|
EventType = eventType,
|
|
Progress = ProgressType.Indeterminate,
|
|
Body = new
|
|
{
|
|
Title = $"Scanning {libraryName}",
|
|
Subtitle = filename,
|
|
Filename = filename,
|
|
EventTime = DateTime.Now,
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage LibraryScanProgressEvent(string libraryName, string eventType, string seriesName = "")
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = ScanProgress,
|
|
Title = $"Scanning {libraryName}",
|
|
SubTitle = seriesName,
|
|
EventType = eventType,
|
|
Progress = ProgressType.Indeterminate,
|
|
Body = null
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage CoverUpdateEvent(int id, string entityType)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = CoverUpdate,
|
|
Title = "Updating Cover",
|
|
Progress = ProgressType.None,
|
|
Body = new
|
|
{
|
|
Id = id,
|
|
EntityType = entityType,
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage UserProgressUpdateEvent(int userId, string username, int seriesId, int volumeId, int chapterId, int pagesRead)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = UserProgressUpdate,
|
|
Title = "Updating User Progress",
|
|
Progress = ProgressType.None,
|
|
Body = new
|
|
{
|
|
UserId = userId,
|
|
Username = username,
|
|
SeriesId = seriesId,
|
|
VolumeId = volumeId,
|
|
ChapterId = chapterId,
|
|
PagesRead = pagesRead,
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage SiteThemeProgressEvent(string subtitle, string themeName, string eventType)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = SiteThemeProgress,
|
|
Title = "Scanning Site Theme",
|
|
SubTitle = subtitle,
|
|
EventType = eventType,
|
|
Progress = ProgressType.Indeterminate,
|
|
Body = new
|
|
{
|
|
ThemeName = themeName,
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage BookThemeProgressEvent(string subtitle, string themeName, string eventType)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = BookThemeProgress,
|
|
Title = "Scanning Book Theme",
|
|
SubTitle = subtitle,
|
|
EventType = eventType,
|
|
Progress = ProgressType.Indeterminate,
|
|
Body = new
|
|
{
|
|
ThemeName = themeName,
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage UserUpdateEvent(int userId, string userName)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = UserUpdate,
|
|
Title = "User Update",
|
|
Progress = ProgressType.None,
|
|
Body = new
|
|
{
|
|
UserId = userId,
|
|
UserName = userName
|
|
}
|
|
};
|
|
}
|
|
|
|
public static SignalRMessage ConvertBookmarksProgressEvent(float progress, string eventType)
|
|
{
|
|
return new SignalRMessage()
|
|
{
|
|
Name = ConvertBookmarksProgress,
|
|
Title = "Converting Bookmarks to WebP",
|
|
SubTitle = string.Empty,
|
|
EventType = eventType,
|
|
Progress = ProgressType.Determinate,
|
|
Body = new
|
|
{
|
|
Progress = progress,
|
|
EventTime = DateTime.Now
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|