using InABox.Core; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; namespace InABox.Avalonia; public static class CacheManager { private static Dictionary _expiries = new(); private static Timer? _timer; private static void StartTimer() { if (_timer is not null) return; // _timer = new Timer(ProcessCache, null, TimeSpan.Zero, TimeSpan.FromMinutes(5)); } private static void ProcessCache(object? state) { var now = DateTime.Now; var toDelete = _expiries.Where(x => x.Value < now).Select(x => x.Key).ToArray(); foreach (var item in toDelete) { try { File.Delete(CacheFileName(item)); } catch(Exception e) { MobileLogging.Log(e); } } lock (_expiries) { foreach (var item in toDelete) { _expiries.Remove(item); } } } private static void AddExpiry(string key, DateTime expiry) { // lock (_expiries) // { // _expiries[key] = expiry; // } // SaveExpiries(); } private static Guid CacheID { get; set; } private static bool IsCached(string key) => File.Exists(CacheFileName(key)); private static string CacheFileName(string key) => Path.Combine(CacheFolder(), key); private static string CacheFolder() { var result = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); if (OperatingSystem.IsWindows()) { var assembly = Path.GetFileNameWithoutExtension(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName); result = Path.Combine(result, assembly); } if (CacheID != Guid.Empty) result = Path.Combine(result, CacheID.ToString()); if (!Directory.Exists(result)) Directory.CreateDirectory(result); return result; } private const string EXPIRY_FILE = "cache_expiry.json"; private static void LoadExpiries() { var filename = CacheFileName(EXPIRY_FILE); if (File.Exists(filename)) { var json = File.ReadAllText(filename); lock (_expiries) { _expiries = Serialization.Deserialize>(json) ?? []; } } else { lock (_expiries) { _expiries = []; } } } private static void SaveExpiries() { try { lock (_expiries) { var file = CacheFileName(EXPIRY_FILE); var json = Serialization.Serialize(_expiries); File.WriteAllText(file, json); } } catch (Exception e) { MobileLogging.Log(e); } } #region Public Interface public static void Initialise(Guid cacheID) { CacheID = cacheID; // LoadExpiries(); StartTimer(); } public static bool TryLoadBinary(string key, [NotNullWhen(true)] out T? value, out DateTime lastUpdated) where T : class, ISerializeBinary, new() { var filename = CacheFileName(key); if (File.Exists(filename)) { lastUpdated = File.GetLastWriteTime(filename); using var stream = new FileStream(filename, FileMode.Open); value = Serialization.ReadBinary(stream, BinarySerializationSettings.Latest); return true; } else { lastUpdated = default; value = null; return false; } } public static void SaveBinary(string key, T value, DateTime expiry) where T : class, ISerializeBinary, new() { var data = value.WriteBinary(BinarySerializationSettings.Latest); try { var file = CacheFileName(key); File.WriteAllBytes(file, data); AddExpiry(key, expiry); } catch (Exception e) { MobileLogging.Log(e); } } public static bool TryLoadJSON(string key, [NotNullWhen(true)] out T? value, out DateTime lastUpdated) where T : class, new() { var filename = CacheFileName(key); if (File.Exists(filename)) { lastUpdated = File.GetLastWriteTime(filename); var json = File.ReadAllText(filename); value = Serialization.Deserialize(json); return value is not null; } else { lastUpdated = default; value = null; return false; } } public static void SaveJSON(string key, T value, DateTime expiry) where T : class, new() { try { var file = CacheFileName(key); var json = Serialization.Serialize(value); File.WriteAllText(file, json); AddExpiry(key, expiry); } catch (Exception e) { MobileLogging.Log(e); } } #endregion }