-
Notifications
You must be signed in to change notification settings - Fork 36
/
NewsPage.cs
105 lines (84 loc) · 3.28 KB
/
NewsPage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
namespace CommunityToolkit.Maui.Markup.Sample.Pages;
sealed class NewsPage : BaseContentPage<NewsViewModel>
{
readonly IDispatcher dispatcher;
readonly RefreshView refreshView;
public NewsPage(IDispatcher dispatcher,
NewsViewModel newsViewModel) : base(newsViewModel, "Top Stories")
{
this.dispatcher = dispatcher;
BindingContext.PullToRefreshFailed += HandlePullToRefreshFailed;
SettingsService.NumberOfTopStoriesToFetchChanged += HandleNumberOfTopStoriesToFetchChanged;
ToolbarItems.Add(new ToolbarItem { Command = new AsyncRelayCommand(NavigateToSettingsPage) }.Text("Settings"));
Content = new RefreshView
{
Content = new CollectionView
{
BackgroundColor = Colors.Transparent,
SelectionMode = SelectionMode.Single,
}.ItemTemplate(new StoryDataTemplate())
.Invoke(collectionView => collectionView.SelectionChanged += HandleSelectionChanged)
.Bind(CollectionView.ItemsSourceProperty, nameof(NewsViewModel.TopStoryCollection))
.AutomationId("NewsCollectionView")
}.Bind(RefreshView.IsRefreshingProperty, (NewsViewModel vm) => vm.IsListRefreshing, (NewsViewModel vm, bool isRefreshing) => vm.IsListRefreshing = isRefreshing)
.Bind(RefreshView.CommandProperty, nameof(NewsViewModel.PullToRefreshCommand))
.AppThemeColorBinding(RefreshView.RefreshColorProperty, Colors.Black, Colors.LightGray)
.Assign(out refreshView);
}
protected override void OnAppearing()
{
base.OnAppearing();
if (refreshView.Content is CollectionView collectionView
&& IsNullOrEmpty(collectionView.ItemsSource))
{
TryRefreshCollectionView();
}
static bool IsNullOrEmpty(in IEnumerable? enumerable) => !enumerable?.GetEnumerator().MoveNext() ?? true;
}
async void HandleSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
ArgumentNullException.ThrowIfNull(sender);
var collectionView = (CollectionView)sender;
collectionView.SelectedItem = null;
if (e.CurrentSelection.FirstOrDefault() is StoryModel storyModel)
{
if (!string.IsNullOrEmpty(storyModel.Url))
{
await NavigateToNewsDetailPage(storyModel);
}
else
{
await DisplayAlert("Invalid Article", "ASK HN articles have no url", "OK");
}
}
}
async void HandlePullToRefreshFailed(object? sender, string message) =>
await dispatcher.DispatchAsync(() => DisplayAlert("Refresh Failed", message, "OK"));
bool TryRefreshCollectionView()
{
if (!refreshView.IsRefreshing)
{
refreshView.IsRefreshing = true;
return true;
}
return false;
}
void HandleNumberOfTopStoriesToFetchChanged(object? sender, int e) => TryRefreshCollectionView();
Task NavigateToSettingsPage() => dispatcher.DispatchAsync(() =>
{
var route = AppShell.GetRoute<SettingsPage, SettingsViewModel>();
return Shell.Current.GoToAsync(route);
});
Task NavigateToNewsDetailPage(StoryModel storyModel) => dispatcher.DispatchAsync(() =>
{
var route = AppShell.GetRoute<NewsDetailPage, NewsDetailViewModel>();
// Shell passes these parameters to NewsDetailViewModel.ApplyQueryAttributes
var parameters = new Dictionary<string, object>
{
{ nameof(NewsDetailViewModel.Uri), storyModel.Url },
{ nameof(NewsDetailViewModel.Title), storyModel.Title },
{ nameof(NewsDetailViewModel.ScoreDescription), storyModel.Description}
};
return Shell.Current.GoToAsync(route, parameters);
});
}