private async Task UpdateChatMessages(string chatId)
        {
            var messages = GetMessagesCollectionForChat(chatId);

            var oldestMessage = default(ChatMessageModel);
            var newestMessage = default(ChatMessageModel);

            ModifyCollection(messages, collection =>
            {
                oldestMessage = collection.FirstOrDefault();
                if (oldestMessage != null)
                {
                    newestMessage = collection.Last();
                }
            });
            if (oldestMessage == null)
            {
                return;
            }

            var upToDateMessages = await TryLoadLatestMessagesAsync(chatId,
                                                                    oldestMessage.Id, oldestMessage.DateTime).ConfigureAwait(false);

            if (upToDateMessages == null)
            {
                await UpdateChatMessages(chatId); // TODO YP: check recursion

                return;
            }

            ModifyCollection(messages, collection =>
            {
                // find messages for delete
                var messagesToDelete = collection
                                       .Where(x => x.MessageType != MessageType.System)
                                       .Except(upToDateMessages)
                                       .SkipWhile(x => x.IsEarlierThan(oldestMessage))
                                       .TakeWhile(x => x.Status != ChatMessageStatus.Sending && x.IsEarlierOrEqualsThan(newestMessage))
                                       .ToList();
                messagesToDelete.AddRange(collection.Where(x => x == null));
                collection.RemoveAll(x => messagesToDelete.Contains(x));

                // find messages for update
                var updatedMessages = GetUpdatedMessagesWithUpdateCollection(collection, upToDateMessages);

                // find new messages
                var newMessages = upToDateMessages.Except(collection).Where(x => x != null).ToList();
                AddNewMessages(collection, newMessages);

                var updatedResults = new CacheUpdatedResults
                {
                    ChatId             = chatId,
                    NewMessages        = newMessages,
                    UpdatedMessages    = updatedMessages,
                    DeletedMessagesIds = messagesToDelete.Select(x => x.Id).ToList()
                };

                CacheUpdated?.Invoke(updatedResults);
            });
        }
示例#2
0
        protected void SaveData(DateTimeOffset now, bool isUpdated)
        {
            if (!IsInitialized)
            {
                InitializedAt = now;
            }

            if (isUpdated)
            {
                LastUpdatedAt = now;
            }

            LastVerifiedAt = now;
            Save(true);

            if (isUpdated)
            {
                Logger.Trace("Updated: {0}", now);
                CacheUpdated.SafeInvoke(now);
            }
            else
            {
                Logger.Trace("Verified: {0}", now);
            }
        }
示例#3
0
 private void OnCacheUpdated(CacheType cacheType, DateTimeOffset datetime)
 {
     Logger.Trace("OnCacheUpdated cacheType:{0} datetime:{1}", cacheType, datetime);
     if (CacheUpdated != null)
     {
         CacheUpdated.Invoke(cacheType, datetime);
     }
 }
示例#4
0
 public void Reset()
 {
     SignedInAccount = null;
     UserNotificationSubscriptionId = null;
     apiClient = null;
     historicalNotifications.Clear();
     localSettings.Values.Clear();
     CacheUpdated?.Invoke(this, new EventArgs());
 }
        public void Reset()
        {
            Logger.Instance.LogMessage("Resetting the feed");
            m_feed = null;
            m_newNotifications.Clear();
            m_historicalNotifications.Clear();

            CacheUpdated?.Invoke(this, new EventArgs());
        }
        public async void Reset()
        {
            if (m_platform != null)
            {
                Logger.Instance.LogMessage("Shutting down platform");
                await m_platform.ShutdownAsync();

                m_platform = null;
                m_feed     = null;
                m_newNotifications.Clear();
                m_historicalNotifications.Clear();
            }

            CacheUpdated?.Invoke(this, new EventArgs());
        }
示例#7
0
        protected void SaveData(DateTimeOffset now, bool isChanged)
        {
            var isInitialized = IsInitialized;

            isChanged = isChanged || !isInitialized;

            InitializedAt = !isInitialized ? now : InitializedAt;
            LastUpdatedAt = isChanged ? now : LastUpdatedAt;

            Save(true);

            if (isChanged)
            {
                Logger.Trace("Updated: {0}", now);
                CacheUpdated.SafeInvoke(CacheType, now);
            }
        }
示例#8
0
        protected void SaveData(DateTimeOffset now, bool isChanged)
        {
            var isInitialized = IsInitialized;

            isChanged = isChanged || !isInitialized;

            InitializedAt = !isInitialized || InitializedAt == DateTimeOffset.MinValue ? now : InitializedAt;
            LastUpdatedAt = isChanged || LastUpdatedAt == DateTimeOffset.MinValue ? now : LastUpdatedAt;

            Save(true);

            isInvalidating = false;

            if (isChanged)
            {
                CacheUpdated.SafeInvoke(CacheType, now);
            }
        }
示例#9
0
        private void HandleCachePolicyChanged()
        {
            if (_cacheEnabled)
            {
                _cacheUpdatedCallback = (IntPtr resource, IntPtr representation, IntPtr userData) =>
                {
                    if (CacheEnabled)
                    {
                        Representation repr = null;
                        try
                        {
                            repr = new Representation(representation);
                        }
                        catch (Exception exp)
                        {
                            Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to new Representation: " + exp.Message);
                            return;
                        }

                        CacheUpdatedEventArgs e = new CacheUpdatedEventArgs()
                        {
                            Representation = repr
                        };
                        CacheUpdated?.Invoke(this, e);
                    }
                };

                int ret = Interop.IoTConnectivity.Client.RemoteResource.StartCaching(_remoteResourceHandle, _cacheUpdatedCallback, IntPtr.Zero);
                if (ret != (int)IoTConnectivityError.None)
                {
                    Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to add cache updated event handler");
                    throw IoTConnectivityErrorFactory.GetException(ret);
                }
            }
            else
            {
                int ret = Interop.IoTConnectivity.Client.RemoteResource.StopCaching(_remoteResourceHandle);
                if (ret != (int)IoTConnectivityError.None)
                {
                    Log.Error(IoTConnectivityErrorFactory.LogTag, "Failed to remove cache updated event handler");
                    throw IoTConnectivityErrorFactory.GetException(ret);
                }
            }
        }
        private async void ReadNotifications(UserNotificationReader reader)
        {
            var notifications = await reader.ReadBatchAsync(UInt32.MaxValue);

            Logger.Instance.LogMessage($"Read {notifications.Count} notifications");

            foreach (var notification in notifications)
            {
                //Logger.Instance.LogMessage($"UserNotification: {notification.Id} Status: {notification.Status} ReadState: {notification.ReadState} UserActionState: {notification.UserActionState}");

                if (notification.Status == UserNotificationStatus.Active)
                {
                    m_newNotifications.RemoveAll((n) => { return(n.Id == notification.Id); });
                    if (notification.UserActionState == UserNotificationUserActionState.NoInteraction)
                    {
                        // Brand new notification, add to new
                        m_newNotifications.Add(notification);
                        Logger.Instance.LogMessage($"UserNotification not interacted: {notification.Id}");
                        if (!string.IsNullOrEmpty(notification.Content) && notification.ReadState != UserNotificationReadState.Read)
                        {
                            RemoveToastNotification(notification.Id);
                            ShowToastNotification(BuildToastNotification(notification.Id, notification.Content));
                        }
                    }
                    else
                    {
                        RemoveToastNotification(notification.Id);
                    }

                    m_historicalNotifications.RemoveAll((n) => { return(n.Id == notification.Id); });
                    m_historicalNotifications.Insert(0, notification);
                }
                else
                {
                    // Historical notification is marked as deleted, remove from display
                    m_newNotifications.RemoveAll((n) => { return(n.Id == notification.Id); });
                    m_historicalNotifications.RemoveAll((n) => { return(n.Id == notification.Id); });
                    RemoveToastNotification(notification.Id);
                }
            }

            CacheUpdated?.Invoke(this, new EventArgs());
        }
示例#11
0
        private void UpdateCache(IReadOnlyList <UserNotification> notifications)
        {
            Debug.WriteLine($"Updating cache with {notifications?.Count} notifications");
            foreach (var notification in notifications)
            {
                if (notification.Status != UserNotificationStatus.Deleted)
                {
                    if (notification.UserActionState == UserNotificationUserActionState.None)
                    {
                        // Brand new notification
                        NewNotifications = true;
                        Debug.WriteLine($"UserNotification not interacted: {notification.Id}");
                        if (!string.IsNullOrEmpty(notification.Payload.RawContent) && !notification.ReadState)
                        {
                            RemoveToastNotification(notification.Id);
                            ShowToastNotification(BuildToastNotification(notification.Id, notification.AppNotificationId, notification.Payload.RawContent));
                        }
                    }
                    else
                    {
                        RemoveToastNotification(notification.Id);
                    }

                    historicalNotifications.RemoveAll((n) => { return(n.Id == notification.Id); });
                    historicalNotifications.Insert(0, notification);
                }
                else
                {
                    // Historical notification is marked as deleted, remove from display
                    historicalNotifications.RemoveAll((n) => { return(n.Id == notification.Id); });
                    RemoveToastNotification(notification.Id);
                }
            }

            CacheUpdated?.Invoke(this, new EventArgs());
        }
示例#12
0
 private void OnCacheUpdated(CacheType cacheType, DateTimeOffset datetime)
 {
     CacheUpdated.SafeInvoke(cacheType, datetime);
 }
 private void ClearCache()
 {
     CacheUpdated.Fire();
 }
 public void UpdateCache(Account account)
 {
     CurrentAccount = account;
     CacheUpdated?.Invoke();
 }
示例#15
0
        /// <summary>
        /// Resolves an image Uri asynchronously. If the image has already been downloaded previously and is available in the cache, its path on disk is returned immediately.
        /// Otherwise, it is queued for download and when it becomes available, the <see cref="CacheUpdated"/> event is invoked. If an image is requested again while it is
        /// being downloaded, a new download of the image is prevented.
        /// </summary>
        /// <param name="imageUri">The Uri of the image to download, either absolute or relative to the <paramref name="baseUriString"/>.</param>
        /// <param name="baseUriString">The base Uri for resolving the <paramref name="imageUri"/>.</param>
        /// <returns>An <see cref="ImageRetrievalResult"/> containing the path to a copy of the image file on disk. If the <see cref="ImageRetrievalResult.ImagePath"/>
        /// property of the return value is <see langword="null"/>, the image was not available in the cache and has been queued for download.</returns>
        public static ImageRetrievalResult ImageUriResolverAsynchronous(string imageUri, string baseUriString)
        {
            bool   found;
            string cachedImage;

            lock (cacheLock)
            {
                found = imageCache.TryGetValue(baseUriString + "|||" + imageUri, out cachedImage);
            }

            if (!found)
            {
                bool notAlreadyFetching;

                lock (cacheLock)
                {
                    notAlreadyFetching = fetchingImages.Add(baseUriString + "|||" + imageUri);
                }

                if (notAlreadyFetching)
                {
                    Thread thr = new Thread(() =>
                    {
                        (string imagePath, bool wasDownloaded) = VectSharp.Markdown.HTTPUtils.ResolveImageURI(imageUri, baseUriString);

                        if (!string.IsNullOrEmpty(imagePath) && File.Exists(imagePath))
                        {
                            string id = Guid.NewGuid().ToString();

                            string cachedImage = Path.Combine(imageCacheFolder, id + Path.GetExtension(imagePath));

                            if (wasDownloaded)
                            {
                                if (!Directory.Exists(imageCacheFolder))
                                {
                                    Directory.CreateDirectory(imageCacheFolder);
                                }

                                File.Move(imagePath, cachedImage);
                                Directory.Delete(Path.GetDirectoryName(imagePath));
                            }
                            else
                            {
                                File.Copy(imagePath, cachedImage);
                            }

                            lock (cacheLock)
                            {
                                imageCache[baseUriString + "|||" + imageUri] = cachedImage;
                                fetchingImages.Remove(baseUriString + "|||" + imageUri);
                            }

                            CacheUpdated?.Invoke(null, new CacheUpdatedEventArgs(baseUriString, imageUri));
                        }
                        else
                        {
                            lock (cacheLock)
                            {
                                fetchingImages.Remove(baseUriString + "|||" + imageUri);
                            }
                        }
                    });

                    thr.Start();
                }

                return(new ImageRetrievalResult(null, false));
            }
            else
            {
                return(new ImageRetrievalResult(cachedImage, false));
            }
        }
 protected virtual void OnCacheUpdated(CacheEventArgs e)
 {
     CacheUpdated?.Invoke(this, e);
 }
示例#17
0
 private void OnCacheUpdated(CacheType cacheType, DateTimeOffset datetime)
 {
     Logger.Trace("OnCacheUpdated cacheType:{0} datetime:{1}", cacheType, datetime);
     CacheUpdated.SafeInvoke(cacheType, datetime);
 }
示例#18
0
 /// <summary>
 /// Raises the CacheUpdated event.
 /// </summary>
 /// <param name="sender">The event sender.</param>
 /// <param name="args">The event arguments.</param>
 protected static void OnCacheUpdated(TInstanceType sender, CacheRefresherEventArgs args)
 {
     CacheUpdated?.Invoke(sender, args);
 }
示例#19
0
 private void RaiseCacheUpdated() => CacheUpdated?.Invoke(this, EventArgs.Empty);
 protected virtual void OnCacheUpdated()
 {
     CacheUpdated?.Invoke(this, EventArgs.Empty);
 }