| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 | using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Runtime.CompilerServices;using System.Threading;using System.Threading.Tasks;using InABox.Clients;using InABox.Core;using Newtonsoft.Json.Linq;namespace InABox.Mobile{    public interface IQueueUpdater    {        void ProcessQueue();    }        public interface IQueueUpdater<TEntity> : IQueueUpdater        where TEntity : Entity, IPersistent, IRemotable, new()    {        void Add(TEntity entity);        TEntity[] Items { get; }    }    public class QueuedUpdaterState    {        public Guid ID { get; set; }        public string OriginalState { get; set; }        public Dictionary<string,object> Changes { get; set; } = new();                public bool DisableUpdates { get; set; }    }        public class QueueUpdater<TEntity> : IDisposable, IQueueUpdater<TEntity>         where TEntity : Entity, IPersistent, IRemotable, new()    {                private static String StateFile(Guid id) => $"{id}.{typeof(TEntity).Name.Split('.').Last()}";         private Dictionary<TEntity, QueuedUpdaterState> _cache = new();        private string _path;        private IModelHost _host;        public QueueUpdater(IModelHost host, string path)        {            _host = host;            _path = path;            LoadCache();            _host.AddUpdateQueue(this);        }                public void Add(TEntity entity)        {            var _state = new QueuedUpdaterState();            _state.ID = Guid.NewGuid();            _state.OriginalState = Serialization.Serialize(entity);            Save(_state);            _cache[entity] = _state;                        entity.PropertyChanged += (sender, args) =>            {                var state = _cache[entity];                state.Changes[args.PropertyName] = CoreUtils.GetPropertyValue(entity,args.PropertyName);                Save(state);            };        }        public void Update(TEntity entity, Action<TEntity> action)        {            var state = _cache[entity];            state.DisableUpdates = true;            action(entity);            Save(state);            state.DisableUpdates = false;        }        private void Save(QueuedUpdaterState state)        {            var _text = Serialization.Serialize(state);            File.WriteAllText(StateFile(state.ID), _text);        }        public TEntity[] Items => _cache.Keys.ToArray();                private void LoadCache()        {            _cache.Clear();            var files = Directory.GetFiles(_path, $"*.{typeof(TEntity).Name.Split('.').Last()}");            foreach (var file in files)            {                if (!Guid.TryParse(Path.GetFileNameWithoutExtension(file), out Guid id))                    continue;                                var _text = File.ReadAllText(file);                if (string.IsNullOrWhiteSpace(_text))                    continue;                                var _state = Serialization.Deserialize<QueuedUpdaterState>(_text);                if (_state == null)                    continue;                                var _entity = Serialization.Deserialize<TEntity>(_state.OriginalState);                if (_entity == null)                    continue;                                foreach (var change in _state.Changes)                     CoreUtils.SetPropertyValue(_entity,change.Key,change.Value);                                        _cache[_entity] = _state;            }        }        public void ProcessQueue()        {            var item = Items.FirstOrDefault();            if (item != null)            {                if (item.IsChanged() && _host.IsConnected())                {                    new Client<TEntity>().Save(item, "Updated from Mobile Device");                    var state = Serialization.Serialize(item);                    File.WriteAllText(StateFile(_cache[item].ID),state);                }            }        }                public void Dispose()        {            _host.RemoveUpdateQueue(this);        }    }    }
 |