mirror of
https://github.com/chylex/Discord-History-Tracker.git
synced 2024-11-25 14:42:44 +01:00
Compare commits
7 Commits
59129ba20a
...
8f1c91b2cc
Author | SHA1 | Date | |
---|---|---|---|
8f1c91b2cc | |||
9ae5ece24b | |||
053ab5b091 | |||
71c628fdf8 | |||
af621b8d46 | |||
31fe6aed35 | |||
c25426af55 |
@ -9,7 +9,7 @@ using DHT.Utils.Tasks;
|
||||
|
||||
namespace DHT.Desktop.Main.Controls {
|
||||
sealed class AttachmentFilterPanelModel : BaseModel, IDisposable {
|
||||
public sealed record Unit(string Name, int Scale);
|
||||
public sealed record Unit(string Name, uint Scale);
|
||||
|
||||
private static readonly Unit[] AllUnits = {
|
||||
new ("B", 1),
|
||||
@ -26,7 +26,7 @@ namespace DHT.Desktop.Main.Controls {
|
||||
public string FilterStatisticsText { get; private set; } = "";
|
||||
|
||||
private bool limitSize = false;
|
||||
private int maximumSize = 0;
|
||||
private ulong maximumSize = 0L;
|
||||
private Unit maximumSizeUnit = AllUnits[0];
|
||||
|
||||
public bool LimitSize {
|
||||
@ -34,7 +34,7 @@ namespace DHT.Desktop.Main.Controls {
|
||||
set => Change(ref limitSize, value);
|
||||
}
|
||||
|
||||
public int MaximumSize {
|
||||
public ulong MaximumSize {
|
||||
get => maximumSize;
|
||||
set => Change(ref maximumSize, value);
|
||||
}
|
||||
@ -116,7 +116,11 @@ namespace DHT.Desktop.Main.Controls {
|
||||
AttachmentFilter filter = new();
|
||||
|
||||
if (LimitSize) {
|
||||
filter.MaxBytes = maximumSize * maximumSizeUnit.Scale;
|
||||
try {
|
||||
filter.MaxBytes = maximumSize * maximumSizeUnit.Scale;
|
||||
} catch (ArithmeticException) {
|
||||
// set no size limit, because the overflown size is larger than any file could possibly be
|
||||
}
|
||||
}
|
||||
|
||||
return filter;
|
||||
|
@ -169,7 +169,7 @@ namespace DHT.Desktop.Main.Controls {
|
||||
var exportedMessageCountStr = exportedMessageCount?.Format() ?? "(...)";
|
||||
var totalMessageCountStr = totalMessageCount?.Format() ?? "(...)";
|
||||
|
||||
FilterStatisticsText = verb + " " + exportedMessageCountStr + " out of " + totalMessageCountStr + " message" + (totalMessageCount is null or 0 ? "." : "s.");
|
||||
FilterStatisticsText = verb + " " + exportedMessageCountStr + " out of " + totalMessageCountStr + " message" + (totalMessageCount is null or 1 ? "." : "s.");
|
||||
OnPropertyChanged(nameof(FilterStatisticsText));
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,6 @@ namespace DHT.Desktop.Main.Pages {
|
||||
};
|
||||
|
||||
db.RemoveDownloadItems(allExceptFailedFilter, FilterRemovalMode.KeepMatching);
|
||||
downloadStatisticsComputer.Recompute();
|
||||
|
||||
if (IsDownloading) {
|
||||
EnqueueDownloadItems();
|
||||
|
@ -1,7 +1,7 @@
|
||||
const DISCORD = (function() {
|
||||
const regex = {
|
||||
formatBold: /\*\*([\s\S]+?)\*\*(?!\*)/g,
|
||||
formatItalic: /(.)?\*([\s\S]+?)\*(?!\*)/g,
|
||||
formatItalic: /(.)?([_*])([\s\S]+?)\2(?!\2)/g,
|
||||
formatUnderline: /__([\s\S]+?)__(?!_)/g,
|
||||
formatStrike: /~~([\s\S]+?)~~(?!~)/g,
|
||||
formatCodeInline: /(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/g,
|
||||
@ -9,7 +9,7 @@ const DISCORD = (function() {
|
||||
formatUrl: /(\b(?:https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig,
|
||||
formatUrlNoEmbed: /<(\b(?:https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])>/ig,
|
||||
specialEscapedBacktick: /\\`/g,
|
||||
specialEscapedSingle: /\\([*\\])/g,
|
||||
specialEscapedSingle: /\\([*_\\])/g,
|
||||
specialEscapedDouble: /\\__|_\\_|\\_\\_|\\~~|~\\~|\\~\\~/g,
|
||||
specialUnescaped: /([*_~\\])/g,
|
||||
mentionRole: /<@&(\d+?)>/g,
|
||||
@ -47,8 +47,8 @@ const DISCORD = (function() {
|
||||
.replace(regex.specialEscapedSingle, escapeHtmlMatch)
|
||||
.replace(regex.specialEscapedDouble, full => full.replace(/\\/g, "").replace(/(.)/g, escapeHtmlMatch))
|
||||
.replace(regex.formatBold, "<b>$1</b>")
|
||||
.replace(regex.formatItalic, (full, pre, match) => pre === "\\" ? full : (pre || "") + "<i>" + match + "</i>")
|
||||
.replace(regex.formatUnderline, "<u>$1</u>")
|
||||
.replace(regex.formatItalic, (full, pre, char, match) => pre === "\\" ? full : (pre || "") + "<i>" + match + "</i>")
|
||||
.replace(regex.formatStrike, "<s>$1</s>");
|
||||
}
|
||||
|
||||
@ -128,12 +128,12 @@ const DISCORD = (function() {
|
||||
|
||||
// noinspection HtmlUnknownTarget
|
||||
templateEmbedImage = new TEMPLATE([
|
||||
"<a href='{url}' class='embed thumbnail'><img src='{src}' alt='(image attachment is loading...)' onerror='DISCORD.handleImageLoadError(this)'></a><br>"
|
||||
"<a href='{url}' class='embed thumbnail loading'><img src='{src}' alt='' onload='DISCORD.handleImageLoad(this)' onerror='DISCORD.handleImageLoadError(this)'></a><br>"
|
||||
].join(""));
|
||||
|
||||
// noinspection HtmlUnknownTarget
|
||||
templateEmbedImageWithSize = new TEMPLATE([
|
||||
"<a href='{url}' class='embed thumbnail'><img src='{src}' width='{width}' height='{height}' alt='(image attachment is loading...)' onerror='DISCORD.handleImageLoadError(this)'></a><br>"
|
||||
"<a href='{url}' class='embed thumbnail loading'><img src='{src}' width='{width}' height='{height}' alt='' onload='DISCORD.handleImageLoad(this)' onerror='DISCORD.handleImageLoadError(this)'></a><br>"
|
||||
].join(""));
|
||||
|
||||
// noinspection HtmlUnknownTarget
|
||||
@ -164,9 +164,14 @@ const DISCORD = (function() {
|
||||
].join(""));
|
||||
},
|
||||
|
||||
handleImageLoad(ele) {
|
||||
ele.parentElement.classList.remove("loading");
|
||||
},
|
||||
|
||||
handleImageLoadError(ele) {
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
ele.onerror = null;
|
||||
ele.parentElement.classList.remove("loading");
|
||||
ele.setAttribute("alt", "(image attachment not found)");
|
||||
},
|
||||
|
||||
|
@ -107,10 +107,23 @@
|
||||
}
|
||||
|
||||
.message .thumbnail {
|
||||
position: relative;
|
||||
max-width: calc(100% - 20px);
|
||||
max-height: 320px;
|
||||
}
|
||||
|
||||
.message .thumbnail.loading::after {
|
||||
content: "";
|
||||
background: rgba(0, 0, 0, 0.75)
|
||||
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 300' preserveAspectRatio='xMidYMid'%3E %3Ccircle cx='150' cy='150' fill='none' stroke='%237983f5' stroke-width='8' r='42' stroke-dasharray='198 68'%3E %3CanimateTransform attributeName='transform' type='rotate' repeatCount='indefinite' dur='1.25s' values='0 150 150;360 150 150' keyTimes='0;1' /%3E %3C/circle%3E %3C/svg%3E")
|
||||
no-repeat center center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.message .thumbnail img {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace DHT.Server.Data.Filters {
|
||||
public sealed class AttachmentFilter {
|
||||
public long? MaxBytes { get; set; } = null;
|
||||
public ulong? MaxBytes { get; set; } = null;
|
||||
|
||||
public DownloadItemRules? DownloadItemRule { get; set; } = null;
|
||||
|
||||
|
@ -403,21 +403,17 @@ LEFT JOIN replied_to rt ON m.message_id = rt.message_id" + filter.GenerateWhereC
|
||||
}
|
||||
|
||||
public void RemoveMessages(MessageFilter filter, FilterRemovalMode mode) {
|
||||
var whereClause = filter.GenerateWhereClause(invert: mode == FilterRemovalMode.KeepMatching);
|
||||
|
||||
if (!string.IsNullOrEmpty(whereClause)) {
|
||||
var perf = log.Start();
|
||||
|
||||
DeleteFromTable("messages", whereClause);
|
||||
totalMessagesComputer.Recompute();
|
||||
|
||||
perf.End();
|
||||
}
|
||||
var perf = log.Start();
|
||||
|
||||
DeleteFromTable("messages", filter.GenerateWhereClause(invert: mode == FilterRemovalMode.KeepMatching));
|
||||
totalMessagesComputer.Recompute();
|
||||
|
||||
perf.End();
|
||||
}
|
||||
|
||||
public int CountAttachments(AttachmentFilter? filter = null) {
|
||||
using var conn = pool.Take();
|
||||
using var cmd = conn.Command("SELECT COUNT(*) FROM attachments a" + filter.GenerateWhereClause("a"));
|
||||
using var cmd = conn.Command("SELECT COUNT(DISTINCT url) FROM attachments a" + filter.GenerateWhereClause("a"));
|
||||
using var reader = cmd.ExecuteReader();
|
||||
|
||||
return reader.Read() ? reader.GetInt32(0) : 0;
|
||||
@ -476,7 +472,7 @@ LEFT JOIN replied_to rt ON m.message_id = rt.message_id" + filter.GenerateWhereC
|
||||
|
||||
public void EnqueueDownloadItems(AttachmentFilter? filter = null) {
|
||||
using var conn = pool.Take();
|
||||
using var cmd = conn.Command("INSERT INTO downloads (url, status, size) SELECT a.url, :enqueued, a.size FROM attachments a" + filter.GenerateWhereClause("a"));
|
||||
using var cmd = conn.Command("INSERT INTO downloads (url, status, size) SELECT a.url, :enqueued, MAX(a.size) FROM attachments a" + filter.GenerateWhereClause("a") + " GROUP BY a.url");
|
||||
cmd.AddAndSet(":enqueued", SqliteType.Integer, (int) DownloadStatus.Enqueued);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
@ -502,16 +498,13 @@ LEFT JOIN replied_to rt ON m.message_id = rt.message_id" + filter.GenerateWhereC
|
||||
}
|
||||
|
||||
public void RemoveDownloadItems(DownloadItemFilter? filter, FilterRemovalMode mode) {
|
||||
var whereClause = filter.GenerateWhereClause(invert: mode == FilterRemovalMode.KeepMatching);
|
||||
|
||||
if (!string.IsNullOrEmpty(whereClause)) {
|
||||
DeleteFromTable("downloads", whereClause);
|
||||
}
|
||||
DeleteFromTable("downloads", filter.GenerateWhereClause(invert: mode == FilterRemovalMode.KeepMatching));
|
||||
totalDownloadsComputer.Recompute();
|
||||
}
|
||||
|
||||
public DownloadStatusStatistics GetDownloadStatusStatistics() {
|
||||
static void LoadUndownloadedStatistics(ISqliteConnection conn, DownloadStatusStatistics result) {
|
||||
using var cmd = conn.Command("SELECT IFNULL(COUNT(filtered.size), 0), IFNULL(SUM(filtered.size), 0) FROM (SELECT DISTINCT a.url, a.size FROM attachments a WHERE a.url NOT IN (SELECT d.url FROM downloads d)) filtered");
|
||||
using var cmd = conn.Command("SELECT IFNULL(COUNT(size), 0), IFNULL(SUM(size), 0) FROM (SELECT MAX(a.size) size FROM attachments a WHERE a.url NOT IN (SELECT d.url FROM downloads d) GROUP BY a.url)");
|
||||
using var reader = cmd.ExecuteReader();
|
||||
|
||||
if (reader.Read()) {
|
||||
@ -655,7 +648,7 @@ FROM downloads");
|
||||
|
||||
private long ComputeAttachmentStatistics() {
|
||||
using var conn = pool.Take();
|
||||
return conn.SelectScalar("SELECT COUNT(*) FROM attachments") as long? ?? 0L;
|
||||
return conn.SelectScalar("SELECT COUNT(DISTINCT url) FROM attachments") as long? ?? 0L;
|
||||
}
|
||||
|
||||
private void UpdateAttachmentStatistics(long totalAttachments) {
|
||||
|
Loading…
Reference in New Issue
Block a user