/// <summary>
        /// Gets the initial set of feeds, either from local storage or 
        /// from the app package if there is nothing in local storage.
        /// </summary>
        public static async Task<List<FeedViewModel>> GetFeedsAsync()
        {
            var feeds = new List<FeedViewModel>();

            var favoritesFile = await ApplicationData.Current.LocalFolder.TryGetItemAsync("favorites.dat") as StorageFile;
            if (favoritesFile != null)
            {
                var buffer = await FileIO.ReadBufferAsync(favoritesFile);
                feeds.Add(Serializer.Deserialize<FeedViewModel>(buffer.ToArray()));
            }
            else
            {
                var feed = new FeedViewModel
                {
                    Name = "Favorites",
                    Description = "Articles that you've starred",
                    Symbol = Symbol.OutlineStar, 
                    Link = new Uri("http://localhost"),
                    IsFavoritesFeed = true
                };
                feeds.Add(feed);
            }

            var feedFile =
                await ApplicationData.Current.LocalFolder.TryGetItemAsync("feeds.dat") as StorageFile ??
                await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/feeds.dat"));
            if (feedFile != null)
            {
                var bytes = (await FileIO.ReadBufferAsync(feedFile)).ToArray();
                var feedData = Serializer.Deserialize<string[][]>(bytes);
                foreach (var feed in feedData) feeds.Add(new FeedViewModel { Name = feed[0], Link = new Uri(feed[1]) });
            }

            return feeds;
        }
        /// <summary>
        /// Retrieves feed data from the server and updates the appropriate FeedViewModel properties.
        /// </summary>
        public static async Task RefreshAsync(this FeedViewModel feedViewModel)
        {
            if (feedViewModel.Link.Host == "localhost" ||
                (feedViewModel.Link.Scheme != "http" && feedViewModel.Link.Scheme != "https")) return;

            feedViewModel.IsInError = false;
            feedViewModel.ErrorMessage = null;
            feedViewModel.IsLoading = true;
            feedViewModel.Symbol = Symbol.PostUpdate;

            Func<Task<bool>> tryGetFeed = async () =>
            { 
                try
                {
                    var feed = await new SyndicationClient().RetrieveFeedAsync(feedViewModel.Link);

                    feedViewModel.Name = String.IsNullOrEmpty(feedViewModel.Name) ? feed.Title.Text : feedViewModel.Name;
                    feedViewModel.Description = feed.Subtitle?.Text ?? String.Empty;

                    feed.Items.Select(item => new ArticleViewModel
                    {
                        Title = item.Title.Text,
                        Summary = item.Summary == null ? string.Empty :
                            item.Summary.Text.RegexRemove("\\&.{0,4}\\;").RegexRemove("<.*?>"),
                        Author = item.Authors.Select(a => a.NodeValue).FirstOrDefault(),
                        Link = item.ItemUri ?? item.Links.Select(l => l.Uri).FirstOrDefault(),
                        PublishedDate = item.PublishedDate
                    })
                    .ToList().ForEach(article =>
                    {
                        var favorites = AppShell.Current.ViewModel.FavoritesFeed;
                        var existingCopy = favorites.Articles.FirstOrDefault(a => a.Equals(article));
                        article = existingCopy ?? article;
                        if (!feedViewModel.Articles.Contains(article)) feedViewModel.Articles.Add(article);
                    });
                    return true;
                }
                catch (Exception)
                {
                    if (feedViewModel.Articles.Count == 0)
                    {
                        feedViewModel.IsInError = true;
                        feedViewModel.ErrorMessage = "Hmm... Are you sure this is an RSS URL?";
                    }
                    else
                    {
                        // TODO display error state that doesn't replace articles that have already been retrieved.
                    }
                    return false;
                }
            };

            int numberOfAttempts = 5;
            bool success = false;
            do { success = await tryGetFeed(); }
            while (!success && numberOfAttempts-- > 0);

            feedViewModel.IsLoading = false;
        }
Example #3
0
        /// <summary>
        /// Saves the favorites feed (the first feed of the feeds list) to local storage.
        /// </summary>
        public static async Task SaveFavoritesAsync(this FeedViewModel favorites)
        {
            var file = await ApplicationData.Current.LocalFolder
                       .CreateFileAsync("favorites.dat", CreationCollisionOption.ReplaceExisting);

            byte[] array = Serializer.Serialize(favorites);
            await FileIO.WriteBytesAsync(file, array);
        }
Example #4
0
        /// <summary>
        /// Retrieves feed data from the server and updates the appropriate FeedViewModel properties.
        /// </summary>
        private static async Task <bool> TryGetFeedAsync(FeedViewModel feedViewModel, CancellationToken?cancellationToken = null)
        {
            try
            {
                var feed = await new SyndicationClient().RetrieveFeedAsync(feedViewModel.Link);

                if (cancellationToken.HasValue && cancellationToken.Value.IsCancellationRequested)
                {
                    return(false);
                }

                feedViewModel.LastSyncDateTime = DateTime.Now;
                feedViewModel.Name             = String.IsNullOrEmpty(feedViewModel.Name) ? feed.Title.Text : feedViewModel.Name;
                feedViewModel.Description      = feed.Subtitle?.Text ?? feed.Title.Text;

                feed.Items.Select(item => new ArticleViewModel
                {
                    Title   = item.Title.Text,
                    Summary = item.Summary == null ? string.Empty :
                              item.Summary.Text.RegexRemove("\\&.{0,4}\\;").RegexRemove("<.*?>"),
                    Author        = item.Authors.Select(a => a.NodeValue).FirstOrDefault(),
                    Link          = item.ItemUri ?? item.Links.Select(l => l.Uri).FirstOrDefault(),
                    PublishedDate = item.PublishedDate
                })
                .ToList().ForEach(article =>
                {
                    var favorites    = AppShell.Current.ViewModel.FavoritesFeed;
                    var existingCopy = favorites.Articles.FirstOrDefault(a => a.Equals(article));
                    article          = existingCopy ?? article;
                    if (!feedViewModel.Articles.Contains(article))
                    {
                        feedViewModel.Articles.Add(article);
                    }
                });
                feedViewModel.IsInError    = false;
                feedViewModel.ErrorMessage = null;
                return(true);
            }
            catch (Exception)
            {
                if (!cancellationToken.HasValue || !cancellationToken.Value.IsCancellationRequested)
                {
                    feedViewModel.IsInError    = true;
                    feedViewModel.ErrorMessage = feedViewModel.Articles.Count == 0 ? BAD_URL_MESSAGE : NO_REFRESH_MESSAGE;
                }
                return(false);
            }
        }
        /// <summary>
        /// Retrieves feed data from the server and updates the appropriate FeedViewModel properties.
        /// </summary>
        public static async Task RefreshAsync(this FeedViewModel feedViewModel)
        {
            if (feedViewModel.Link.Host == "localhost" ||
                (feedViewModel.Link.Scheme != "http" && feedViewModel.Link.Scheme != "https"))
            {
                return;
            }

            feedViewModel.IsInError    = false;
            feedViewModel.ErrorMessage = null;
            feedViewModel.IsLoading    = true;
            feedViewModel.Symbol       = Symbol.PostUpdate;

            try
            {
                var feed = await new SyndicationClient().RetrieveFeedAsync(feedViewModel.Link);

                feedViewModel.Name        = String.IsNullOrEmpty(feedViewModel.Name) ? feed.Title.Text : feedViewModel.Name;
                feedViewModel.Description = feed.Subtitle?.Text ?? String.Empty;

                feed.Items.Select(item => new ArticleViewModel
                {
                    Title   = item.Title.Text,
                    Summary = item.Summary == null ? string.Empty :
                              item.Summary.Text.RegexRemove("\\&.{0,4}\\;").RegexRemove("<.*?>"),
                    Author        = item.Authors.Select(a => a.NodeValue).FirstOrDefault(),
                    Link          = item.ItemUri ?? item.Links.Select(l => l.Uri).FirstOrDefault(),
                    PublishedDate = item.PublishedDate
                })
                .ToList().ForEach(article =>
                {
                    var favorites    = AppShell.Current.ViewModel.FavoritesFeed;
                    var existingCopy = favorites.Articles.FirstOrDefault(a => a.Equals(article));
                    article          = existingCopy ?? article;
                    if (!feedViewModel.Articles.Contains(article))
                    {
                        feedViewModel.Articles.Add(article);
                    }
                });
            }
            catch (Exception)
            {
                feedViewModel.IsInError    = true;
                feedViewModel.ErrorMessage = "Hmm... Are you sure this is an RSS URL?";
            }
            feedViewModel.IsLoading = false;
        }
Example #6
0
        /// <summary>
        /// Attempts to update the feed with new data from the server.
        /// </summary>
        public static async Task RefreshAsync(this FeedViewModel feedViewModel, CancellationToken?cancellationToken = null)
        {
            if (feedViewModel.Link.Host == "localhost" ||
                (feedViewModel.Link.Scheme != "http" && feedViewModel.Link.Scheme != "https"))
            {
                return;
            }

            feedViewModel.IsLoading = true;

            int  numberOfAttempts = 5;
            bool success          = false;

            do
            {
                success = await TryGetFeedAsync(feedViewModel, cancellationToken);
            }while (!success && numberOfAttempts-- > 0 &&
                    (!cancellationToken.HasValue || !cancellationToken.Value.IsCancellationRequested));

            feedViewModel.IsLoading = false;
        }
Example #7
0
        /// <summary>
        /// Gets the initial set of feeds, either from local storage or
        /// from the app package if there is nothing in local storage.
        /// </summary>
        public static async Task <List <FeedViewModel> > GetFeedsAsync()
        {
            var feeds    = new List <FeedViewModel>();
            var feedFile =
                await ApplicationData.Current.LocalFolder.TryGetItemAsync("feeds.dat") as StorageFile ??
                await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/feeds.dat"));

            if (feedFile != null)
            {
                var bytes    = (await FileIO.ReadBufferAsync(feedFile)).ToArray();
                var feedData = Serializer.Deserialize <string[][]>(bytes);
                foreach (var feed in feedData)
                {
                    var feedVM = new FeedViewModel {
                        Name = feed[0], Link = new Uri(feed[1])
                    };
                    feeds.Add(feedVM);
                    var withoutAwait = feedVM.RefreshAsync();
                }
            }
            return(feeds);
        }