public RepositoryViewModel(RepositoryDatabase repositoryDatabase,
                                   GitHubAuthenticationService gitHubAuthenticationService,
                                   GitHubGraphQLApiService gitHubGraphQLApiService,
                                   IAnalyticsService analyticsService,
                                   MobileSortingService sortingService,
                                   GitHubApiV3Service gitHubApiV3Service,
                                   NotificationService notificationService,
                                   IMainThread mainThread,
                                   GitHubUserService gitHubUserService) : base(analyticsService, mainThread)
        {
            LanguageService.PreferredLanguageChanged += HandlePreferredLanguageChanged;

            SetTitleText();

            _repositoryDatabase          = repositoryDatabase;
            _gitHubAuthenticationService = gitHubAuthenticationService;
            _gitHubGraphQLApiService     = gitHubGraphQLApiService;
            _sortingService     = sortingService;
            _gitHubApiV3Service = gitHubApiV3Service;
            _gitHubUserService  = gitHubUserService;

            RefreshState = RefreshState.Uninitialized;

            PullToRefreshCommand      = new AsyncCommand(() => ExecutePullToRefreshCommand(gitHubUserService.Alias));
            FilterRepositoriesCommand = new Command <string>(SetSearchBarText);
            SortRepositoriesCommand   = new Command <SortingOption>(ExecuteSortRepositoriesCommand);

            notificationService.SortingOptionRequested            += HandleSortingOptionRequested;
            gitHubAuthenticationService.LoggedOut                 += HandleGitHubAuthenticationServiceLoggedOut;
            gitHubAuthenticationService.AuthorizeSessionCompleted += HandleAuthorizeSessionCompleted;
            gitHubAuthenticationService.DemoUserActivated         += HandleDemoUserActivated;
        }
        public void GetSortingCategoryTest_InvalidOption(SortingOption sortingOption)
        {
            //Arrange

            //Act //Assert
            Assert.Throws <NotSupportedException>(() => MobileSortingService.GetSortingCategory(sortingOption));
        }
        public void SortReferringSitesTests()
        {
            const int    largestTotalCount       = 1000;
            const int    largestTotalUniqueCount = 11;
            const string lastReferer             = "t.co";

            //Arrange
            var referringSitesList = new List <MobileReferringSiteModel>
            {
                new MobileReferringSiteModel(new ReferringSiteModel(10, 10, "Google")),
                new MobileReferringSiteModel(new ReferringSiteModel(10, 10, "codetraver.io")),
                new MobileReferringSiteModel(new ReferringSiteModel(10, 10, lastReferer)),
                new MobileReferringSiteModel(new ReferringSiteModel(100, largestTotalUniqueCount, "facebook.com")),
                new MobileReferringSiteModel(new ReferringSiteModel(100, 9, "linkedin.com")),
                new MobileReferringSiteModel(new ReferringSiteModel(largestTotalCount, 9, "reddit.com"))
            };

            //Act
            var sortedReferringSitesList = MobileSortingService.SortReferringSites(referringSitesList);

            //Assert
            Assert.IsTrue(sortedReferringSitesList.First().TotalCount is largestTotalCount);
            Assert.IsTrue(sortedReferringSitesList.Skip(1).First().TotalUniqueCount is largestTotalUniqueCount);
            Assert.IsTrue(sortedReferringSitesList.Last().Referrer is lastReferer);
        }
Example #4
0
        public InformationButton(MobileSortingService mobileSortingService, IMainThread mainThread)
        {
            _mainThread = mainThread;

            RowDefinitions    = Rows.Define(AbsoluteGridLength(_diameter));
            ColumnDefinitions = Columns.Define(AbsoluteGridLength(_diameter));

            Children.Add(new FloatingActionTextButton(mobileSortingService, FloatingActionButtonSize.Mini, FloatingActionButtonType.Statistic1).Assign(out _statistic1FloatingActionButton)
                         .Bind <FloatingActionTextButton, IReadOnlyList <Repository>, string>(FloatingActionTextButton.TextProperty, nameof(RepositoryViewModel.VisibleRepositoryList), convert: repositories => GetLabelTextConverter(mobileSortingService, repositories, FloatingActionButtonType.Statistic1))
                         .Invoke(fab => fab.SetBinding(IsVisibleProperty, getIsVisibleBinding())));

            Children.Add(new FloatingActionTextButton(mobileSortingService, FloatingActionButtonSize.Mini, FloatingActionButtonType.Statistic2).Assign(out _statistic2FloatingActionButton)
                         .Bind <FloatingActionTextButton, IReadOnlyList <Repository>, string>(FloatingActionTextButton.TextProperty, nameof(RepositoryViewModel.VisibleRepositoryList), convert: repositories => GetLabelTextConverter(mobileSortingService, repositories, FloatingActionButtonType.Statistic2))
                         .Invoke(fab => fab.SetBinding(IsVisibleProperty, getIsVisibleBinding())));

            Children.Add(new FloatingActionTextButton(mobileSortingService, FloatingActionButtonSize.Mini, FloatingActionButtonType.Statistic3).Assign(out _statistic3FloatingActionButton)
                         .Bind <FloatingActionTextButton, IReadOnlyList <Repository>, string>(FloatingActionTextButton.TextProperty, nameof(RepositoryViewModel.VisibleRepositoryList), convert: repositories => GetLabelTextConverter(mobileSortingService, repositories, FloatingActionButtonType.Statistic3))
                         .Invoke(fab => fab.SetBinding(IsVisibleProperty, getIsVisibleBinding())));

            Children.Add(new FloatingActionTextButton(mobileSortingService, FloatingActionButtonSize.Normal, FloatingActionButtonType.Information, new AsyncCommand(ExecuteFloatingActionButtonCommand))
            {
                FontFamily = FontFamilyConstants.RobotoMedium, Text = "TOTAL"
            }.Center()
                         .DynamicResource(FloatingActionButtonView.RippleColorProperty, nameof(BaseTheme.PageBackgroundColor))
                         .Invoke(fab => fab.SetBinding(IsVisibleProperty, getIsVisibleBinding())));
 public ExtendedNotificationService(IPreferences preferences,
                                    ISecureStorage secureStorage,
                                    IAnalyticsService analyticsService,
                                    MobileSortingService sortingService,
                                    DeepLinkingService deepLinkingService,
                                    INotificationManager notificationManager,
                                    INotificationService notificationService,
                                    AzureFunctionsApiService azureFunctionsApiService) :
     base(preferences, secureStorage, analyticsService, sortingService, deepLinkingService, notificationManager, notificationService, azureFunctionsApiService)
 {
 }
        public void GetSortingCategoryTest_ValidOption(SortingOption sortingOption, SortingCategory expectedSortingCategory)
        {
            //Arrange
            SortingCategory actualSortingCategory;

            //Act
            actualSortingCategory = MobileSortingService.GetSortingCategory(sortingOption);

            //Assert
            Assert.AreEqual(expectedSortingCategory, actualSortingCategory);
        }
Example #7
0
        public async Task VerifySortingOptions(SortingOption sortingOption)
        {
            //Fail all tests if the DefaultSortingOption has changed
            Assert.AreEqual(MobileSortingService.DefaultSortingOption, SortingOption.Views);

            //Arrange
            string floatingActionTextButtonStatistic1Text, floatingActionTextButtonStatistic2Text, floatingActionTextButtonStatistic3Text;

            Repository finalFirstRepository, finalSecondTopRepository, finalLastRepository;
            Repository initialFirstRepository     = RepositoryPage.VisibleCollection.First();
            Repository initialSecondTopRepository = RepositoryPage.VisibleCollection.Skip(1).First();
            Repository initialLastRepository      = RepositoryPage.VisibleCollection.Last();


            //Act
            await RepositoryPage.SetSortingOption(sortingOption).ConfigureAwait(false);

            floatingActionTextButtonStatistic1Text = RepositoryPage.InformationButtonStatistic1Text;
            floatingActionTextButtonStatistic2Text = RepositoryPage.InformationButtonStatistic2Text;
            floatingActionTextButtonStatistic3Text = RepositoryPage.InformationButtonStatistic3Text;

            RepositoryPage.TapInformationButton();

            //Assert
            finalFirstRepository     = RepositoryPage.VisibleCollection.First();
            finalSecondTopRepository = RepositoryPage.VisibleCollection.Skip(1).First();
            finalLastRepository      = RepositoryPage.VisibleCollection.Last();

            if (initialFirstRepository.IsTrending == initialSecondTopRepository.IsTrending)
            {
                Assert.GreaterOrEqual(initialFirstRepository.TotalViews, initialSecondTopRepository.TotalViews);
            }

            Assert.GreaterOrEqual(initialFirstRepository.TotalViews, initialLastRepository.TotalViews);


            var floatingActionTextButtonStatistic1Text_Expected = StatisticsService.GetFloatingActionTextButtonText(MobileSortingService.GetSortingCategory(sortingOption), RepositoryPage.VisibleCollection, FloatingActionButtonType.Statistic1);
            var floatingActionTextButtonStatistic2Text_Expected = StatisticsService.GetFloatingActionTextButtonText(MobileSortingService.GetSortingCategory(sortingOption), RepositoryPage.VisibleCollection, FloatingActionButtonType.Statistic2);
            var floatingActionTextButtonStatistic3Text_Expected = StatisticsService.GetFloatingActionTextButtonText(MobileSortingService.GetSortingCategory(sortingOption), RepositoryPage.VisibleCollection, FloatingActionButtonType.Statistic3);

            Assert.AreEqual(floatingActionTextButtonStatistic1Text_Expected, floatingActionTextButtonStatistic1Text);
            Assert.AreEqual(floatingActionTextButtonStatistic2Text_Expected, floatingActionTextButtonStatistic2Text);
            Assert.AreEqual(floatingActionTextButtonStatistic3Text_Expected, floatingActionTextButtonStatistic3Text);

            switch (sortingOption)
            {
            case SortingOption.Views when finalFirstRepository.IsTrending == finalSecondTopRepository.IsTrending:
                Assert.LessOrEqual(finalFirstRepository.TotalViews, finalSecondTopRepository.TotalViews);
                break;

            case SortingOption.Views:
                Assert.LessOrEqual(finalSecondTopRepository.TotalViews, finalLastRepository.TotalViews);
                break;

            case SortingOption.Stars when finalFirstRepository.IsTrending == finalSecondTopRepository.IsTrending:
                Assert.GreaterOrEqual(finalFirstRepository.StarCount, finalSecondTopRepository.StarCount);
                break;

            case SortingOption.Stars:
                Assert.GreaterOrEqual(finalSecondTopRepository.StarCount, finalLastRepository.StarCount);
                break;

            case SortingOption.Forks when finalFirstRepository.IsTrending == finalSecondTopRepository.IsTrending:
                Assert.GreaterOrEqual(finalFirstRepository.ForkCount, finalSecondTopRepository.ForkCount);
                break;

            case SortingOption.Forks:
                Assert.GreaterOrEqual(finalSecondTopRepository.ForkCount, finalLastRepository.ForkCount);
                break;

            case SortingOption.Issues when finalFirstRepository.IsTrending == finalSecondTopRepository.IsTrending:
                Assert.GreaterOrEqual(finalFirstRepository.IssuesCount, finalSecondTopRepository.IssuesCount);
                break;

            case SortingOption.Issues:
                Assert.GreaterOrEqual(finalSecondTopRepository.IssuesCount, finalLastRepository.IssuesCount);
                break;

            case SortingOption.Clones when finalFirstRepository.IsTrending == finalSecondTopRepository.IsTrending:
                Assert.GreaterOrEqual(finalFirstRepository.TotalClones, finalSecondTopRepository.TotalClones);
                break;

            case SortingOption.Clones:
                Assert.GreaterOrEqual(finalSecondTopRepository.TotalClones, finalLastRepository.TotalClones);
                break;

            case SortingOption.UniqueClones when finalFirstRepository.IsTrending == finalSecondTopRepository.IsTrending:
                Assert.GreaterOrEqual(finalFirstRepository.TotalUniqueClones, finalSecondTopRepository.TotalUniqueClones);
                break;

            case SortingOption.UniqueClones:
                Assert.GreaterOrEqual(finalSecondTopRepository.TotalUniqueClones, finalLastRepository.TotalUniqueClones);
                break;

            case SortingOption.UniqueViews when finalFirstRepository.IsTrending == finalSecondTopRepository.IsTrending:
                Assert.GreaterOrEqual(finalFirstRepository.TotalUniqueViews, finalSecondTopRepository.TotalUniqueViews);
                break;

            case SortingOption.UniqueViews:
                Assert.GreaterOrEqual(finalSecondTopRepository.TotalUniqueViews, finalLastRepository.TotalUniqueViews);
                break;

            default:
                throw new NotSupportedException();
            }
            ;
        }
Example #8
0
        public RepositoryPage(RepositoryViewModel repositoryViewModel,
                              IAnalyticsService analyticsService,
                              MobileSortingService sortingService,
                              DeepLinkingService deepLinkingService,
                              IMainThread mainThread,
                              FirstRunService firstRunService,
                              GitHubUserService gitHubUserService) : base(repositoryViewModel, analyticsService, mainThread)
        {
            _firstRunService    = firstRunService;
            _gitHubUserService  = gitHubUserService;
            _deepLinkingService = deepLinkingService;

            ViewModel.PullToRefreshFailed += HandlePullToRefreshFailed;
            SearchBarTextChanged          += HandleSearchBarTextChanged;

            var collectionView = new CollectionView
            {
                ItemTemplate    = new RepositoryDataTemplateSelector(sortingService),
                BackgroundColor = Color.Transparent,
                SelectionMode   = SelectionMode.Single,
                AutomationId    = RepositoryPageAutomationIds.CollectionView,
                //Work around for https://github.com/xamarin/Xamarin.Forms/issues/9879
                Header = Device.RuntimePlatform is Device.Android ? new BoxView {
                    HeightRequest = BaseRepositoryDataTemplate.BottomPadding
                } : null,
                Footer = Device.RuntimePlatform is Device.Android ? new BoxView {
                    HeightRequest = BaseRepositoryDataTemplate.TopPadding
                } : null,
                EmptyView = new EmptyDataView("EmptyRepositoriesList", RepositoryPageAutomationIds.EmptyDataView)
                            .Bind <EmptyDataView, bool, bool>(IsVisibleProperty, nameof(RepositoryViewModel.IsRefreshing), convert: isRefreshing => !isRefreshing)
                            .Bind(EmptyDataView.TitleProperty, nameof(RepositoryViewModel.EmptyDataViewTitle))
                            .Bind(EmptyDataView.DescriptionProperty, nameof(RepositoryViewModel.EmptyDataViewDescription))
            };

            collectionView.SelectionChanged += HandleCollectionViewSelectionChanged;
            collectionView.SetBinding(CollectionView.ItemsSourceProperty, nameof(RepositoryViewModel.VisibleRepositoryList));

            _refreshView = new RefreshView
            {
                AutomationId = RepositoryPageAutomationIds.RefreshView,
                Content      = collectionView
            }.DynamicResource(RefreshView.RefreshColorProperty, nameof(BaseTheme.PullToRefreshColor))
            .Bind(RefreshView.IsRefreshingProperty, nameof(RepositoryViewModel.IsRefreshing))
            .Bind(RefreshView.CommandProperty, nameof(RepositoryViewModel.PullToRefreshCommand));

            var settingsToolbarItem = new ToolbarItem
            {
                Text            = PageTitles.SettingsPage,
                IconImageSource = Device.RuntimePlatform is Device.iOS ? "Settings" : null,
                Order           = Device.RuntimePlatform is Device.Android ? ToolbarItemOrder.Secondary : ToolbarItemOrder.Default,
                AutomationId    = RepositoryPageAutomationIds.SettingsButton,
                Command         = new AsyncCommand(ExecuteSetttingsToolbarItemCommand)
            };

            ToolbarItems.Add(settingsToolbarItem);

            var sortToolbarItem = new ToolbarItem
            {
                Text            = RepositoryPageConstants.SortToolbarItemText,
                Priority        = 1,
                IconImageSource = Device.RuntimePlatform is Device.iOS ? "Sort" : null,
                Order           = Device.RuntimePlatform is Device.Android ? ToolbarItemOrder.Secondary : ToolbarItemOrder.Default,
                AutomationId    = RepositoryPageAutomationIds.SortButton,
                Command         = new AsyncCommand(ExecuteSortToolbarItemCommand)
            };

            ToolbarItems.Add(sortToolbarItem);

            //Work-around to prevent LargeNavigationBar from collapsing when CollectionView is scrolled; prevents janky animation when LargeNavigationBar collapses
            if (Device.RuntimePlatform is Device.iOS)
            {
                Content = new Grid
                {
                    Children =
                    {
                        new BoxView {
                            HeightRequest = 0
                        },
                        _refreshView
                    }
                };
            }
            else
            {
                Content = _refreshView;
            }

            this.SetBinding(TitleProperty, nameof(RepositoryViewModel.TitleText));
        }
 public InformationButton(MobileSortingService mobileSortingService, in IMainThread mainThread, in IAnalyticsService analyticsService)
Example #10
0
 public RepositoryDataTemplateSelector(MobileSortingService sortingService) => _sortingService = sortingService;
        public void SortRepositoriesTests(SortingOption sortingOption, bool isReversed)
        {
            //Arrange
            Repository topRepository, bottomRepository;

            List <Repository> repositoryList = new List <Repository>();

            for (int i = 0; i < DemoDataConstants.RepoCount; i++)
            {
                repositoryList.Add(CreateRepository());
            }

            //Act
            var sortedRepositoryList = MobileSortingService.SortRepositories(repositoryList, sortingOption, isReversed);

            topRepository    = sortedRepositoryList.First();
            bottomRepository = sortedRepositoryList.Last();

            //Assert
            switch (sortingOption)
            {
            case SortingOption.Clones when isReversed:
                Assert.Less(topRepository.TotalClones, bottomRepository.TotalClones);
                break;

            case SortingOption.Clones:
                Assert.Greater(topRepository.TotalClones, bottomRepository.TotalClones);
                break;

            case SortingOption.Forks when isReversed:
                Assert.Less(topRepository.ForkCount, bottomRepository.ForkCount);
                break;

            case SortingOption.Forks:
                Assert.Greater(topRepository.ForkCount, bottomRepository.ForkCount);
                break;

            case SortingOption.Issues when isReversed:
                Assert.Less(topRepository.IssuesCount, bottomRepository.IssuesCount);
                break;

            case SortingOption.Issues:
                Assert.Greater(topRepository.IssuesCount, bottomRepository.IssuesCount);
                break;

            case SortingOption.Stars when isReversed:
                Assert.Less(topRepository.StarCount, bottomRepository.StarCount);
                break;

            case SortingOption.Stars:
                Assert.Greater(topRepository.StarCount, bottomRepository.StarCount);
                break;

            case SortingOption.UniqueClones when isReversed:
                Assert.Less(topRepository.TotalUniqueClones, bottomRepository.TotalUniqueClones);
                break;

            case SortingOption.UniqueClones:
                Assert.Greater(topRepository.TotalUniqueClones, bottomRepository.TotalUniqueClones);
                break;

            case SortingOption.UniqueViews when isReversed:
                Assert.Less(topRepository.TotalUniqueViews, bottomRepository.TotalUniqueViews);
                break;

            case SortingOption.UniqueViews:
                Assert.Greater(topRepository.TotalUniqueViews, bottomRepository.TotalUniqueViews);
                break;

            case SortingOption.Views when isReversed:
                Assert.Less(topRepository.TotalViews, bottomRepository.TotalViews);
                break;

            case SortingOption.Views:
                Assert.Greater(topRepository.TotalViews, bottomRepository.TotalViews);
                break;

            default:
                throw new NotSupportedException();
            }
        }
Example #12
0
        public RepositoryPage(IMainThread mainThread,
                              FirstRunService firstRunService,
                              IAnalyticsService analyticsService,
                              GitHubUserService gitHubUserService,
                              DeepLinkingService deepLinkingService,
                              RepositoryViewModel repositoryViewModel,
                              MobileSortingService mobileSortingService) : base(repositoryViewModel, analyticsService, mainThread)
        {
            _firstRunService    = firstRunService;
            _gitHubUserService  = gitHubUserService;
            _deepLinkingService = deepLinkingService;

            SearchBarTextChanged += HandleSearchBarTextChanged;
            RepositoryViewModel.PullToRefreshFailed  += HandlePullToRefreshFailed;
            LanguageService.PreferredLanguageChanged += HandlePreferredLanguageChanged;

            this.SetBinding(TitleProperty, nameof(RepositoryViewModel.TitleText));

            ToolbarItems.Add(new ToolbarItem
            {
                Text            = PageTitles.SettingsPage,
                IconImageSource = Device.RuntimePlatform is Device.iOS ? "Settings" : null,
                Order           = Device.RuntimePlatform is Device.Android ? ToolbarItemOrder.Secondary : ToolbarItemOrder.Default,
                AutomationId    = RepositoryPageAutomationIds.SettingsButton,
                Command         = new AsyncCommand(ExecuteSetttingsToolbarItemCommand)
            });

            ToolbarItems.Add(new ToolbarItem
            {
                Text            = RepositoryPageConstants.SortToolbarItemText,
                Priority        = 1,
                IconImageSource = Device.RuntimePlatform is Device.iOS ? "Sort" : null,
                Order           = Device.RuntimePlatform is Device.Android ? ToolbarItemOrder.Secondary : ToolbarItemOrder.Default,
                AutomationId    = RepositoryPageAutomationIds.SortButton,
                Command         = new AsyncCommand(ExecuteSortToolbarItemCommand)
            });

            Content = new Grid
            {
                RowDefinitions = Rows.Define(
                    (Row.Totals, AbsoluteGridLength(125)),
                    (Row.CollectionView, Star),
                    (Row.Information, AbsoluteGridLength(100))),

                ColumnDefinitions = Columns.Define(
                    (Column.CollectionView, Star),
                    (Column.Information, AbsoluteGridLength(100))),

                Children =
                {
                    new TotalsLabel().Row(Row.Totals).ColumnSpan(All <Column>())
                    .Bind <Label,                                                bool,                                  bool>(IsVisibleProperty,    nameof(RepositoryViewModel.IsRefreshing),          convert: isRefreshing => !isRefreshing)
                    .Bind <Label,                                                IReadOnlyList <Repository>,            string>(Label.TextProperty, nameof(RepositoryViewModel.VisibleRepositoryList), convert: repositories => totalsLabelConverter(repositories, mobileSortingService)),

                    new RefreshView
                    {
                        AutomationId = RepositoryPageAutomationIds.RefreshView,
                        Content      = new CollectionView
                        {
                            ItemTemplate    = new RepositoryDataTemplateSelector(mobileSortingService),
                            BackgroundColor = Color.Transparent,
                            SelectionMode   = SelectionMode.Single,
                            AutomationId    = RepositoryPageAutomationIds.CollectionView,
                            //Work around for https://github.com/xamarin/Xamarin.Forms/issues/9879
                            Header = Device.RuntimePlatform is Device.Android ? new BoxView {
                                HeightRequest = BaseRepositoryDataTemplate.BottomPadding
                            } : null,
                            Footer = Device.RuntimePlatform is Device.Android ? new BoxView {
                                HeightRequest = BaseRepositoryDataTemplate.TopPadding
                            } : null,
                            EmptyView = new EmptyDataView("EmptyRepositoriesList",RepositoryPageAutomationIds.EmptyDataView)
                                        .Bind <EmptyDataView,                    bool,                                  bool>(IsVisibleProperty,    nameof(RepositoryViewModel.IsRefreshing),          convert: isRefreshing => !isRefreshing)
                                        .Bind(EmptyDataView.TitleProperty,       nameof(RepositoryViewModel.EmptyDataViewTitle))
                                        .Bind(EmptyDataView.DescriptionProperty, nameof(RepositoryViewModel.EmptyDataViewDescription))
                        }.Bind(CollectionView.ItemsSourceProperty,               nameof(RepositoryViewModel.VisibleRepositoryList))
                        .Invoke(collectionView => collectionView.SelectionChanged += HandleCollectionViewSelectionChanged)
                    }.RowSpan(All <Row>()).ColumnSpan(All <Column>()).Assign(out _refreshView)
                    .Bind(RefreshView.IsRefreshingProperty,                      nameof(RepositoryViewModel.IsRefreshing))
                    .Bind(RefreshView.CommandProperty,                           nameof(RepositoryViewModel.PullToRefreshCommand))
                    .DynamicResource(RefreshView.RefreshColorProperty,           nameof(BaseTheme.PullToRefreshColor)),
                }
            }.Assign(out Grid grid);