using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Xml.Serialization;
using MiniTwitter.Extensions;
using MiniTwitter.Net.Twitter;
namespace MiniTwitter{
[Serializable]
public class Timeline : PropertyChangedBase
{
public Timeline()
{
SinceID = 0;
ListID = 0;
VerticalOffset = 0;
UnreadCount = 0;
MaxCount = 10000;
Name = "unknown";
Type = TimelineType.User;
Items = new ObservableCollection<ITwitterItem>();
View = (ListCollectionView)CollectionViewSource.GetDefaultView(Items);
}
private object thisLock = new object();
private string name;
[XmlAttribute]
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
OnPropertyChanged("Name");
}
}
}
[XmlAttribute]
public TimelineType Type { get; set; }
[XmlAttribute]
public int MaxCount { get; set; }
[XmlAttribute]
public int ListID { get; set; }
private int _unreadCount;
[XmlIgnore]
public int UnreadCount
{
get { return _unreadCount; }
set
{
if (_unreadCount != value)
{
_unreadCount = value;
OnPropertyChanged("UnreadCount");
}
}
}
private List<Filter> filters;
[XmlElement("Filter")]
public List<Filter> Filters
{
get
{
if (filters == null)
{
filters = new List<Filter>();
}
return filters;
}
set { filters = value; }
}
[XmlIgnore]
public ListCollectionView View { get; private set; }
[XmlIgnore]
public long SinceID { get; set; }
[XmlIgnore]
public double VerticalOffset { get; set; }
[XmlIgnore]
public ObservableCollection<ITwitterItem> Items { get; private set; }
public void Update<T>(IEnumerable<T> appendItems) where T : ITwitterItem
{
lock (thisLock)
{
if (appendItems == null)
{
return;
}
foreach (var item in Items)
{
item.UpdateRelativeTime();
}
int count = 0;
int unreadCount = 0;
foreach (var item in appendItems.Where(x => !Items.Contains(x) && IsFilterMatch(x)))
{
count++;
if (item.IsNewest)
{
unreadCount++;
}
Items.Add(item);
}
UnreadCount += unreadCount;
if (Items.Count > MaxCount)
{
var deleteItems = (from p in Items orderby p.CreatedAt select p).Take(Items.Count - MaxCount).TakeWhile(p => !p.IsNewest);
foreach (var item in deleteItems)
{
Items.Remove(item);
}
}
if (VerticalOffset != 0.0)
{
VerticalOffset += count;
}
View.Refresh();
}
}
public void Remove(ITwitterItem removeItem)
{
lock (thisLock)
{
if (removeItem == null)
{
return;
}
if (Items.Remove(removeItem))
{
if (removeItem.IsNewest)
{
UnreadCount--;
}
View.Refresh();
}
}
}
public void RemoveAll(Predicate<ITwitterItem> match)
{
lock (thisLock)
{
int count = 0;
for (int i = 0; i < Items.Count; i++)
{
if (match(Items[i]))
{
if (Items[i].IsNewest)
{
count++;
}
Items.RemoveAt(i--);
}
}
UnreadCount -= count;
View.Refresh();
}
}
public void Clear()
{
lock (thisLock)
{
UnreadCount = 0;
View.Filter = null;
Items.Clear();
View.Refresh();
}
}
public T[] Normalize<T>(IEnumerable<T> items) where T : ITwitterItem
{
lock (thisLock)
{
if (items == null)
{
return null;
}
return items.Where(x => !Items.Contains(x) && IsFilterMatch(x)).ToArray();
}
}
public void Sort(ListSortCategory category, ListSortDirection direction)
{
lock (thisLock)
{
View.SortDescriptions.Clear();
View.SortDescriptions.Add(new SortDescription(category.ToPropertyPath(), direction));
if (category != ListSortCategory.CreatedAt)
{
View.SortDescriptions.Add(new SortDescription(ListSortCategory.CreatedAt.ToPropertyPath(), direction));
}
View.SortDescriptions.Add(new SortDescription(ListSortCategory.ID.ToPropertyPath(), direction));
}
}
public void Search(string term)
{
lock (thisLock)
{
if (term.IsNullOrEmpty())
{
View.Filter = null;
}
else
{
View.Filter = state =>
{
var item = (ITwitterItem)state;
return item.Text.IndexOf(term, StringComparison.OrdinalIgnoreCase) != -1 || item.Sender.ScreenName.IndexOf(term, StringComparison.OrdinalIgnoreCase) != -1;
};
}
View.Refresh();
}
}
public void Trim()
{
}
private bool IsFilterMatch(ITwitterItem item)
{
return Filters.Count == 0 || Filters.Any(filter => filter.Process(item));
}
}
}
|