Upload via GUI (186 Dateien)

This commit is contained in:
2026-10-04 14:48:53 +00:00
parent c0b552ef39
commit 8efd5bc497
25 changed files with 2344 additions and 1015 deletions
+120
View File
@@ -0,0 +1,120 @@
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Windows.Threading;
namespace DeskCore;
public class UsageEntry
{
public int Count { get; set; }
public DateTime Last { get; set; }
}
/// <summary>
/// Merkt sich, was wie oft und wann zuletzt über DeskCore gestartet wurde (für „Meistgenutzt“, „Zuletzt benutzt“
/// und die Schnellstart-Suche). Liegt getrennt von den Einstellungen in usage.json, weil es sich ständig ändert.
/// </summary>
public static class Usage
{
/// <summary>Schlüssel-Präfix für Start-Gruppen (die keinen Dateipfad haben).</summary>
public const string GroupPrefix = "gruppe:";
private static readonly string FilePath = Path.Combine(AppSettings.Folder, "usage.json");
private static readonly Dictionary<string, UsageEntry> _data = Load();
private static DispatcherTimer? _saveTimer;
/// <summary>Etwas wurde gestartet (z. B. damit „Zuletzt benutzt“-Boxen sich aktualisieren).</summary>
public static event Action? Changed;
private static Dictionary<string, UsageEntry> Load()
{
try
{
if (File.Exists(FilePath) &&
JsonSerializer.Deserialize<Dictionary<string, UsageEntry>>(File.ReadAllText(FilePath)) is { } d)
return new(d, StringComparer.OrdinalIgnoreCase);
}
catch { }
return new(StringComparer.OrdinalIgnoreCase);
}
/// <summary>Programm/Datei starten und den Start mitzählen. Wirft bei Fehlern wie Process.Start.</summary>
public static void Start(string path)
{
Process.Start(new ProcessStartInfo(path) { UseShellExecute = true });
Record(path);
}
public static void Record(string key)
{
if (!_data.TryGetValue(key, out var e)) _data[key] = e = new UsageEntry();
e.Count++;
e.Last = DateTime.Now;
ScheduleSave();
Changed?.Invoke();
}
public static int Count(string key) => _data.TryGetValue(key, out var e) ? e.Count : 0;
/// <summary>
/// Wie „beliebt“ etwas ist: Anzahl der Starts, mit der Zeit abnehmend gewichtet –
/// was du früher oft, aber seit Wochen nicht mehr benutzt hast, rutscht langsam nach hinten.
/// </summary>
public static double Score(string key)
{
if (!_data.TryGetValue(key, out var e)) return 0;
double days = Math.Max(0, (DateTime.Now - e.Last).TotalDays);
return e.Count / (1 + days / 30);
}
/// <summary>Zuletzt gestartete Dateien, die es noch gibt (neueste zuerst).</summary>
public static List<string> Recent(int max) => _data
.Where(kv => !kv.Key.StartsWith(GroupPrefix) && (File.Exists(kv.Key) || Directory.Exists(kv.Key)))
.OrderByDescending(kv => kv.Value.Last)
.Take(max)
.Select(kv => kv.Key)
.ToList();
/// <summary>Datei wurde umbenannt/verschoben → Zählung mitnehmen.</summary>
public static void Rename(string oldKey, string newKey)
{
if (!_data.Remove(oldKey, out var e)) return;
if (_data.TryGetValue(newKey, out var existing))
{
existing.Count += e.Count;
if (e.Last > existing.Last) existing.Last = e.Last;
}
else _data[newKey] = e;
ScheduleSave();
}
public static void Forget(string key)
{
if (_data.Remove(key)) { ScheduleSave(); Changed?.Invoke(); }
}
private static void ScheduleSave()
{
_saveTimer ??= new DispatcherTimer(TimeSpan.FromSeconds(2), DispatcherPriority.Background, (_, _) => Flush(),
Dispatcher.CurrentDispatcher);
_saveTimer.Stop();
_saveTimer.Start();
}
/// <summary>Sofort speichern (z. B. beim Beenden).</summary>
public static void Flush()
{
_saveTimer?.Stop();
try
{
// Nicht mehr vorhandene Einträge, die lange nicht benutzt wurden, aufräumen
foreach (var key in _data.Where(kv => kv.Value.Last < DateTime.Now.AddDays(-180) && !kv.Key.StartsWith(GroupPrefix)
&& !File.Exists(kv.Key) && !Directory.Exists(kv.Key)).Select(kv => kv.Key).ToList())
_data.Remove(key);
Directory.CreateDirectory(AppSettings.Folder);
File.WriteAllText(FilePath, JsonSerializer.Serialize(_data));
}
catch { }
}
}