private async Task FavRemoveAsyncInternal(IProgress<string> p, CancellationToken ct, IReadOnlyList<long> statusIds, TabClass tab) { if (ct.IsCancellationRequested) return; if (!CheckAccountValid()) throw new WebApiException("Auth error. Check your account"); var successIds = new List<long>(); await Task.Run(() => { //スレッド処理はしない var allCount = 0; var failedCount = 0; foreach (var statusId in statusIds) { allCount++; var post = tab.Posts[statusId]; p.Report(Properties.Resources.GetTimelineWorker_RunWorkerCompletedText17 + allCount + "/" + statusIds.Count + Properties.Resources.GetTimelineWorker_RunWorkerCompletedText18 + failedCount); if (!post.IsFav) continue; var err = this.tw.PostFavRemove(post.RetweetedId ?? post.StatusId); if (!string.IsNullOrEmpty(err)) { failedCount++; continue; } successIds.Add(statusId); post.IsFav = false; // リスト再描画必要 if (this._statuses.ContainsKey(statusId)) { this._statuses[statusId].IsFav = false; } // 検索,リスト,UserTimeline,Relatedの各タブに反映 foreach (var tb in this._statuses.GetTabsInnerStorageType()) { if (tb.Contains(statusId)) tb.Posts[statusId].IsFav = false; } } }); if (ct.IsCancellationRequested) return; this.RemovePostFromFavTab(successIds.ToArray()); this.RefreshTimeline(false); if (this._curList != null && this._curTab != null && this._curTab.Text == tab.TabName) { if (tab.TabType == MyCommon.TabUsageType.Favorites) { // 色変えは不要 } else { using (ControlTransaction.Update(this._curList)) { foreach (var statusId in successIds) { var idx = tab.IndexOf(statusId); if (idx == -1) continue; var post = tab.Posts[statusId]; this.ChangeCacheStyleRead(post.IsRead, idx); } } if (successIds.Contains(this._curPost.StatusId)) await this.DispSelectedPost(true); // 選択アイテム再表示 } } }
private async Task FavAddAsyncInternal(IProgress<string> p, CancellationToken ct, IReadOnlyList<long> statusIds, TabClass tab) { if (ct.IsCancellationRequested) return; if (!CheckAccountValid()) throw new WebApiException("Auth error. Check your account"); var successIds = new List<long>(); await Task.Run(() => { //スレッド処理はしない var allCount = 0; var failedCount = 0; foreach (var statusId in statusIds) { allCount++; p.Report(Properties.Resources.GetTimelineWorker_RunWorkerCompletedText15 + allCount + "/" + statusIds.Count + Properties.Resources.GetTimelineWorker_RunWorkerCompletedText16 + failedCount); var post = tab.Posts[statusId]; if (post.IsFav) continue; var err = this.tw.PostFavAdd(post.RetweetedId ?? post.StatusId); if (!string.IsNullOrEmpty(err)) { failedCount++; continue; } successIds.Add(statusId); post.IsFav = true; // リスト再描画必要 this._favTimestamps.Add(DateTime.Now); // TLでも取得済みならfav反映 if (this._statuses.ContainsKey(statusId)) { var postTl = this._statuses[statusId]; postTl.IsFav = true; var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites); favTab.Add(statusId, postTl.IsRead, false); } // 検索,リスト,UserTimeline,Relatedの各タブに反映 foreach (var tb in this._statuses.GetTabsInnerStorageType()) { if (tb.Contains(statusId)) tb.Posts[statusId].IsFav = true; } } // 時速表示用 var oneHour = DateTime.Now - TimeSpan.FromHours(1); foreach (var i in MyCommon.CountDown(this._favTimestamps.Count - 1, 0)) { if (this._favTimestamps[i] < oneHour) this._favTimestamps.RemoveAt(i); } this._statuses.DistributePosts(); }); if (ct.IsCancellationRequested) return; this.RefreshTimeline(false); if (this._curList != null && this._curTab != null && this._curTab.Text == tab.TabName) { using (ControlTransaction.Update(this._curList)) { foreach (var statusId in successIds) { var idx = tab.IndexOf(statusId); if (idx == -1) continue; var post = tab.Posts[statusId]; this.ChangeCacheStyleRead(post.IsRead, idx); } } if (successIds.Contains(this._curPost.StatusId)) await this.DispSelectedPost(true); // 選択アイテム再表示 } }
private async Task GetRelatedTweetsAsyncInternal(IProgress<string> p, CancellationToken ct, TabClass tab) { if (ct.IsCancellationRequested) return; if (!CheckAccountValid()) throw new WebApiException("Auth error. Check your account"); bool read; if (!this._cfgCommon.UnreadManage) read = true; else read = this._initial && this._cfgCommon.Read; p.Report("Related refreshing..."); await Task.Run(() => { var err = this.tw.GetRelatedResult(read, tab); if (!string.IsNullOrEmpty(err)) throw new WebApiException(err); this._statuses.DistributePosts(); }); if (ct.IsCancellationRequested) return; p.Report("Related refreshed"); this.RefreshTimeline(false); var tabPage = this.ListTab.TabPages.Cast<TabPage>() .FirstOrDefault(x => x.Text == tab.TabName); if (tabPage != null) { // TODO: 非同期更新中にタブが閉じられている場合を厳密に考慮したい var listView = (DetailsListView)tabPage.Tag; var index = tab.IndexOf(tab.RelationTargetPost.RetweetedId ?? tab.RelationTargetPost.StatusId); if (index != -1 && index < listView.Items.Count) { listView.SelectedIndices.Add(index); listView.Items[index].Focused = true; } } }
private async Task FavAddAsyncInternal(IProgress<string> p, CancellationToken ct, long statusId, TabClass tab) { if (ct.IsCancellationRequested) return; if (!CheckAccountValid()) throw new WebApiException("Auth error. Check your account"); PostClass post; if (!tab.Posts.TryGetValue(statusId, out post)) return; if (post.IsFav) return; await Task.Run(() => { p.Report(string.Format(Properties.Resources.GetTimelineWorker_RunWorkerCompletedText15, 0, 1, 0)); try { this.tw.PostFavAdd(post.RetweetedId ?? post.StatusId); this._favTimestamps.Add(DateTime.Now); // TLでも取得済みならfav反映 if (this._statuses.ContainsKey(statusId)) { var postTl = this._statuses[statusId]; postTl.IsFav = true; var favTab = this._statuses.GetTabByType(MyCommon.TabUsageType.Favorites); favTab.AddPostQueue(statusId, postTl.IsRead); } // 検索,リスト,UserTimeline,Relatedの各タブに反映 foreach (var tb in this._statuses.GetTabsInnerStorageType()) { if (tb.Contains(statusId)) tb.Posts[statusId].IsFav = true; } p.Report(string.Format(Properties.Resources.GetTimelineWorker_RunWorkerCompletedText15, 1, 1, 0)); } catch (WebApiException) { p.Report(string.Format(Properties.Resources.GetTimelineWorker_RunWorkerCompletedText15, 1, 1, 1)); throw; } // 時速表示用 var oneHour = DateTime.Now - TimeSpan.FromHours(1); foreach (var i in MyCommon.CountDown(this._favTimestamps.Count - 1, 0)) { if (this._favTimestamps[i] < oneHour) this._favTimestamps.RemoveAt(i); } this._statuses.DistributePosts(); }); if (ct.IsCancellationRequested) return; this.RefreshTimeline(); if (this._curList != null && this._curTab != null && this._curTab.Text == tab.TabName) { using (ControlTransaction.Update(this._curList)) { var idx = tab.IndexOf(statusId); if (idx != -1) this.ChangeCacheStyleRead(post.IsRead, idx); } if (statusId == this._curPost.StatusId) await this.DispSelectedPost(true); // 選択アイテム再表示 } }
/// <summary> /// <see cref="SaveListViewStatus"/> によって保存された選択状態を復元します /// </summary> private void RestoreListViewSelection(DetailsListView listView, TabClass tab, ListViewSelection listSelection) { // status_id から ListView 上のインデックスに変換 int[] selectedIndices = null; if (listSelection.SelectedStatusIds != null) selectedIndices = tab.IndexOf(listSelection.SelectedStatusIds).Where(x => x != -1).ToArray(); var focusedIndex = -1; if (listSelection.FocusedStatusId != null) focusedIndex = tab.IndexOf(listSelection.FocusedStatusId.Value); var selectionMarkIndex = -1; if (listSelection.SelectionMarkStatusId != null) selectionMarkIndex = tab.IndexOf(listSelection.SelectionMarkStatusId.Value); listView.SelectedIndexChanged -= this.MyList_SelectedIndexChanged; try { this.SelectListItem(listView, selectedIndices, focusedIndex, selectionMarkIndex); } finally { listView.SelectedIndexChanged += this.MyList_SelectedIndexChanged; } }
/// <summary> /// <see cref="SaveListViewScroll"/> によって保存されたスクロール位置を復元します /// </summary> private void RestoreListViewScroll(DetailsListView listView, TabClass tab, ListViewScroll listScroll) { if (listView.VirtualListSize == 0) return; switch (listScroll.ScrollLockMode) { case ScrollLockMode.FixedToTop: listView.EnsureVisible(0); break; case ScrollLockMode.FixedToBottom: listView.EnsureVisible(listView.VirtualListSize - 1); break; case ScrollLockMode.FixedToItem: var topIndex = listScroll.TopItemStatusId != null ? tab.IndexOf(listScroll.TopItemStatusId.Value) : -1; if (topIndex != -1) listView.TopItem = listView.Items[topIndex]; break; case ScrollLockMode.None: default: break; } }