private void UpdateSelectedItem(Ao3PageViewModel newselected) { var oldSelected = selectedItem; selectedItem = null; ListView.SelectedItem = null; if (!(oldSelected is null) && newselected != oldSelected) { oldSelected.IsSelected = false; } if (!(newselected is null)) { newselected.IsSelected = true; selectedItem = newselected; } Xamarin.Forms.Device.BeginInvokeOnMainThread(() => { if (selectedItem?.IsSelected != false && ListView.SelectedItem != selectedItem) { try { ListView.SelectedItem = selectedItem; } catch { } } }); }
public void Goto(Ao3PageViewModel item, bool latest, bool fullwork) { if (item.BaseData.Type == Models.Ao3PageType.Work && !(item.BaseData.Details is null) && item.BaseData.Details.WorkId != 0) { if (latest) { wvp.NavigateToLast(item.BaseData.Details.WorkId, fullwork); } else { wvp.Navigate(item.BaseData.Details.WorkId, fullwork); } } else if (latest && item.BaseData.Type == Models.Ao3PageType.Series && item.BaseData.SeriesWorks?.Count > 0) { long workid = 0; foreach (var workmodel in item.BaseData.SeriesWorks) { workid = workmodel.Details.WorkId; int chapters_finished = 0; if (item.WorkChapters.TryGetValue(workid, out var workchap)) { chapters_finished = (int)workchap.number; if (!(workchap.location is null)) { chapters_finished--; } } if (chapters_finished < workmodel.Details.Chapters.Available) { break; } } if (workid != 0) { wvp.NavigateToLast(workid, false); } else { wvp.Navigate(item.Uri); } } else { wvp.Navigate(item.Uri); } IsOnScreen = false; }
async Task <Ao3PageViewModel> AddAsyncImpl(string href, long timestamp) { if (!(readingListBacking.FindInAll((m) => m.Uri.AbsoluteUri == href) is null)) { return(null); } var model = Ao3SiteDataLookup.LookupQuick(href); if (model is null) { return(null); } if (!(readingListBacking.FindInAll((m) => m.Uri.AbsoluteUri == model.Uri.AbsoluteUri) is null)) { return(null); } return(await wvp.DoOnMainThreadAsync(async() => { var viewmodel = new Ao3PageViewModel(model.Uri, model.HasChapters ? 0 : (int?)null, model.Type == Ao3PageType.Work ? tagTypeVisible : null) // Set unread to 0. this is to prevents UI locks when importing huge reading lists during syncs { TagsVisible = tags_visible }; viewmodel.PropertyChanged += Viewmodel_PropertyChanged; await viewmodel.SetBaseDataAsync(model, false); readingListBacking.Add(viewmodel); await App.Database.ReadingListCached.InsertOrUpdateAsync(new ReadingList(model, timestamp, viewmodel.ChaptersRead)); var uri = Ao3SiteDataLookup.ReadingListlUri(wvp.CurrentUri.AbsoluteUri); if (uri == viewmodel.Uri) { wvp.AddRemoveReadingListToolBarItem_IsActive = AddPageButton.IsActive = true; } return viewmodel; })); }
public async Task RefreshAsync(Ao3PageViewModel viewmodel) { var model = await Ao3SiteDataLookup.LookupAsync(viewmodel.Uri.AbsoluteUri); if (!(model is null)) { if (viewmodel.Uri.AbsoluteUri != model.Uri.AbsoluteUri) { await App.Database.ReadingListCached.DeleteAsync(viewmodel.Uri.AbsoluteUri); var pvm = readingListBacking.FindInAll((m) => m.Uri.AbsoluteUri == model.Uri.AbsoluteUri); if (!(pvm is null)) { await wvp.DoOnMainThreadAsync(() => { readingListBacking.Remove(pvm); pvm.Dispose(); }); } } // If missing title in update, get it from old if (string.IsNullOrEmpty(model.Title)) { model.Title = viewmodel.BaseData?.Title; } await wvp.DoOnMainThreadAsync(async() => { await viewmodel.SetBaseDataAsync(model, true); viewmodel.Loaded = true; readingListBacking.Remove(viewmodel); readingListBacking.Add(viewmodel); }); await WriteViewModelToDbAsync(viewmodel, new ReadingList(model, 0, viewmodel.Unread)); } }
private async Task WriteViewModelToDbAsync(Ao3PageViewModel viewmodel, ReadingList dbentry) { bool changed = false; if (dbentry.Unread != viewmodel.Unread) { changed = true; dbentry.Unread = viewmodel.Unread; } string model = Ao3PageModel.Serialize(viewmodel.BaseData); if (!(model is null) && dbentry.Model != model) { changed = true; dbentry.Model = model; } if (changed) { await App.Database.ReadingListCached.InsertOrUpdateAsync(dbentry); } }
protected override void Execute() { Ao3PageViewModel item = Target as Ao3PageViewModel; ReadingList?.Goto(item, true, false); }
void RestoreReadingList() { Task.Factory.StartNew(async() => { await App.Database.ReadingListCached.BeginDeferralAsync(); try { // Restore the reading list contents! var items = new Dictionary <string, ReadingList>(); foreach (var i in await App.Database.ReadingListCached.SelectAsync()) { items[i.Uri] = i; } var tasks = new Queue <Task>(); using (var tasklimit = new SemaphoreSlim(MaxRefreshTasks)) { await wvp.DoOnMainThreadAsync(() => ListView.ItemsSource = readingListBacking); if (items.Count == 0) { tasks.Enqueue(AddAsyncImpl("http://archiveofourown.org/", DateTime.UtcNow.ToUnixTime())); } else { var timestamp = DateTime.UtcNow.ToUnixTime(); foreach (var item in items.Values) { var model = Ao3PageModel.Deserialize(item.Model) ?? Ao3SiteDataLookup.LookupQuick(item.Uri); if (model == null) { continue; } if (model.Uri.AbsoluteUri != item.Uri) { await App.Database.ReadingListCached.DeleteAsync(item.Uri); await App.Database.ReadingListCached.InsertOrUpdateAsync(new ReadingList(model, timestamp, item.Unread)); } if (readingListBacking.FindInAll((m) => m.Uri.AbsoluteUri == model.Uri.AbsoluteUri) is null) { var viewmodel = new Ao3PageViewModel(model.Uri, model.HasChapters ? item.Unread : (int?)null, model.Type == Ao3PageType.Work ? tagTypeVisible : null) { TagsVisible = tags_visible, Favourite = item.Favourite }; await tasklimit.WaitAsync(); tasks.Enqueue(Task.Run(async() => { await viewmodel.SetBaseDataAsync(model, false); if (!readingListBacking.Contains(viewmodel)) { await wvp.DoOnMainThreadAsync(() => { viewmodel.PropertyChanged += Viewmodel_PropertyChanged; readingListBacking.Add(viewmodel); }); } await RefreshAsync(viewmodel); await Task.Delay(RefreshDelay); tasklimit.Release(); })); } #pragma warning disable 4014 while (tasks.Count > 0 && tasks.Peek().IsCompleted) { tasks.Dequeue(); } #pragma warning restore 4014 } } } await wvp.DoOnMainThreadAsync(() => { restored.SetResult(true); SyncIndicator.Content = new ActivityIndicator() { IsVisible = IsOnScreen, IsRunning = IsOnScreen, IsEnabled = IsOnScreen }; App.Database.GetVariableEvents("LogFontSizeUI").Updated += LogFontSizeUI_Updated; }); GC.Collect(); // If we don't have network access, we wait till it's available if (!App.Current.HaveNetwork) { tcsNetworkAvailable = new TaskCompletionSource <bool>(); App.Current.HaveNetworkChanged += App_HaveNetworkChanged; await tcsNetworkAvailable.Task; } #pragma warning disable 4014 while (tasks.Count > 0 && tasks.Peek().IsCompleted) { tasks.Dequeue(); } #pragma warning restore 4014 await Task.WhenAll(tasks); await SyncToServerAsync(false, true); } finally { await App.Database.ReadingListCached.EndDeferralAsync().ConfigureAwait(false); } await wvp.DoOnMainThreadAsync(() => { RefreshButton.IsEnabled = true; SyncIndicator.Content = null; }).ConfigureAwait(false); }, TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning); }