using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.IO.IsolatedStorage; using System.Linq; using System.ServiceModel; using System.Threading; using System.Windows; using MahTweets.Mobile.Core; using MahTweets.Mobile.Core.Filters; using MahTweets.Mobile.Core.Interfaces; using MahTweets.Mobile.Core.Repositories; using MahTweets.Mobile.Core.Services; //using MahTweets.Mobile.TumblrPlugin.Models; using MahTweets.Mobile.mtpush; using MahTweets.Mobile.TwitterPlugin.Models; using MahTweets.Mobile.Views; //using MahTweets.Mobile.YammerPlugin.Models; using Microsoft.Phone.Controls; using Microsoft.Phone.Notification; namespace MahTweets.Mobile.ViewModels { public class MainViewModel : MahViewModelBase, IDisposable { public static HttpNotificationChannel Channel; //private const string ChannelName = "mahtweets"; //private const string PushAddress = "http://192.168.0.19:8732/Design_Time_Addresses/SiteStreamingNotifications/Service1/"; //private const string PushAddress = "http://services.mahtweets.com:8000/push/"; private Timer _refreshTimer; private readonly INavigationService _navigationService; private readonly ContactRepository _contactRepository; private readonly Func _streamViewModelFactory; private readonly Func _microBlogFactory; private readonly IApplicationSettings _applicationSettings; private AccountRepository _accounts; private string _prevSharedPhotoId = ""; private IStatusUpdatesManager StatusManager { get; set; } public AvailableMicroblogs AvailableConnections { get; set; } public FilterRepository Filters { get; set; } private SearchRepository _searchRepository { get; set; } private ObservableCollection _pivotItems = new ObservableCollection(); public ObservableCollection PivotItems { get { return _pivotItems; } set { _pivotItems = value; RaisePropertyChanged(() => PivotItems); } } public ObservableCollection Streams { get; set; } public ObservableCollection Searches { get; set; } public MainViewModel( INavigationService navigationService, AccountRepository accounts, ContactRepository contactRepository, IStatusUpdatesManager statusUpdatesManager, FilterRepository filterRepository, SearchRepository searchRepository, AvailableMicroblogs availableMicroblogs, IEnumerable registeredBlogs, IApplicationSettings applicationSettings, Func streamViewModelFactory, Func microBlogFactory ) { _navigationService = navigationService; _contactRepository = contactRepository; _applicationSettings = applicationSettings; _streamViewModelFactory = streamViewModelFactory; _microBlogFactory = microBlogFactory; Streams = new ObservableCollection(); Searches = new ObservableCollection(); Accounts = accounts; Filters = filterRepository; _searchRepository = searchRepository; StatusManager = statusUpdatesManager; AvailableConnections = availableMicroblogs; foreach (var registeredBlog in registeredBlogs) { if (!AvailableConnections.Contains(registeredBlog)) AvailableConnections.Add(registeredBlog); } Startup(); } public void Startup() { AddExistingAccounts(); _refreshTimer = new Timer(o => Refresh(false), null, 0, 180000); SetupFeatures(); } public void StopTimer() { _refreshTimer.Dispose(); } public void RestartTimer() { _refreshTimer = new Timer(o => Refresh(false), null, 0, 180000); } private void SetupFeatures() { //Setup filters if (Filters.Count > 0) return; List filters = Settings.GetFilters().ToList(); foreach (var f in filters) { foreach (var inner in f.Filters.OfType()) { var x = inner; var microblog = Accounts.Where(a => a.Credentials.AccountName == x.MicroblogAccountName && a.Protocol == x.MicroblogName).FirstOrDefault(); if (microblog != null) x.Microblog = microblog; //MahTweets.Mobile.Core.MentionUpdate x.UpdateType = GetUpdateType(x.UpdateTypeName); } Filters.Add(f); } List searches = Settings.GetSavedSearches().ToList(); foreach (var s in searches) { _searchRepository.Add(s); } } public UpdateType GetUpdateType(String name) { //MahTweets.Mobile.Core.MentionUpdate return (from u in App.UpdateTypes where u.GetType().AssemblyQualifiedName == name select (UpdateType)Activator.CreateInstance(u.GetType())).FirstOrDefault(); } private void AddExistingAccounts() { var accounts = Settings.GetCredentials().ToList(); try { foreach (var account in accounts) { var account1 = account; var b = from mb in AvailableConnections where mb.Protocol.Equals(account1.Protocol) select mb; if (b.Count() > 0) CreateAndAddAccount(b.First(), account, false); } } catch (NullReferenceException) { //this occurs on the first run of the app, need to dig into Phone.Data.Entity } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { } } } public void Refresh(bool force) { DateTime? lastRefresh = null; if (IsolatedStorageSettings.ApplicationSettings.Contains("LastRefreshTime")) lastRefresh = _applicationSettings.LastRefreshTime; if (force || lastRefresh == null || DateTime.Now.Subtract((DateTime)lastRefresh).TotalMinutes > 3) { foreach (var connection in Accounts) { var microblog = connection; if (!microblog.IsRefreshing) AddWork(() => microblog.Refresh(force)); } foreach (var s in Searches) AddWork(() => s.Search(s.Term, false)); PerformWork(); _applicationSettings.LastRefreshTime = DateTime.Now; } } public void CreateAndAddAccount(IMicroblog baseAccount, Credential credentials, bool isNewAccount) { var newAccount = _microBlogFactory(baseAccount.GetType()); newAccount.Credentials = credentials; newAccount.Connect(); if (isNewAccount) newAccount.Refresh(true); Accounts.Add(newAccount); } public AccountRepository Accounts { get { return _accounts; } set { _accounts = value; RaisePropertyChanged(() => Accounts); } } public void LoadInitialStreams() { if (Streams == null) Streams = new ObservableCollection(); PivotItems = new ObservableCollection(); RaisePropertyChanged(() => PivotItems); if (PivotItems.Count > 0) return; GlobalDispatcher.Dispatcher.BeginInvoke( () => { if (Accounts.Count > 0) { //Load up the streams if (Filters.Count > 0) SetupExistingFilters(); else NoFiltersPrompt(); } }); } private void NoFiltersPrompt() { MessageBoxResult result = MessageBox.Show( "Oops! Looks like you've got no columns, would you like the defaults setup?", "No filters!", MessageBoxButton.OKCancel); if (result == MessageBoxResult.OK) { StreamModel defaultEverything = StreamModel.CreateDefault(); var defaultResponses = new StreamModel { GroupName = "@me", Filters = new ObservableCollection { new UpdateTypeFilter(FilterBehaviour.Include,Accounts[0],new MentionUpdate()), new UpdateTypeFilter(FilterBehaviour.Include,Accounts[0],new DirectMessageUpdate()) } }; Filters.Add(defaultResponses); Filters.Add(defaultEverything); Settings.StoreStream(defaultResponses); Settings.StoreStream(defaultEverything); RaisePropertyChanged(() => Filters); RaisePropertyChanged(() => Streams); LoadInitialStreams(); //_navigationService.Navigate(new Uri("/Views/MainView.xaml?" + DateTime.Now, UriKind.RelativeOrAbsolute)); } } private void SetupExistingFilters() { foreach (var filter in Filters) { StreamViewModel svm = Streams.Where(s => s.Filters != null && s.Filters.GroupName == filter.GroupName).FirstOrDefault(); if (svm == null) { svm = _streamViewModelFactory(); svm.Filters = new StreamModel { Filters = filter.Filters, GroupName = filter.GroupName }; } if (!Streams.Contains(svm)) Streams.Add(svm); try { var sv = new StreamView { DataContext = svm }; var pi = new PivotItem { Header = svm.Filters.GroupName, Content = sv, HorizontalContentAlignment = HorizontalAlignment.Stretch }; PivotItems.Add(pi); RaisePropertyChanged(() => PivotItems); RaisePropertyChanged(() => Streams); } catch (Exception ex) { //TODO: Logging Debug.WriteLine(ex); } } foreach (var s in _searchRepository) { var svm = new SearchViewModel(_accounts, _contactRepository, _searchRepository) { Term = s.Term }; Searches.Add(svm); var sv = new SearchStreamView { DataContext = svm }; var pi = new PivotItem { Header = s.Term, Content = sv, HorizontalContentAlignment = HorizontalAlignment.Stretch }; PivotItems.Add(pi); RaisePropertyChanged(() => PivotItems); } } public void EditColumn(PivotItem pi) { if (pi == null) return; if (pi.Content is StreamView) ((StreamView)pi.Content).BeginEdit(); if (pi.Content is SearchStreamView) ((SearchStreamView)pi.Content).BeginEdit(); } public StreamView GetColumn(PivotItem pi) { if (pi != null && pi.Content is StreamView) { return ((StreamView)pi.Content); } return null; } public void GotoSettings() { _navigationService.Navigate(new Uri("/Views/SettingsView.xaml", UriKind.RelativeOrAbsolute)); } public void ShowComposition() { _navigationService.Navigate(new Uri("/Views/CompositionView.xaml", UriKind.RelativeOrAbsolute)); } public void SharePhoto(string fileId) { if (!_prevSharedPhotoId.Equals(fileId)) { _navigationService.Navigate(new Uri("/Views/CompositionView.xaml?FileId=" + fileId, UriKind.RelativeOrAbsolute)); _prevSharedPhotoId = fileId; } } internal void GoToNewColumn() { _navigationService.Navigate(new Uri("/Views/AddColumnView.xaml", UriKind.RelativeOrAbsolute)); } public new void Dispose() { _refreshTimer.Dispose(); base.Dispose(); } public void GoToSearch() { _navigationService.Navigate(new Uri("/Views/SearchView.xaml", UriKind.RelativeOrAbsolute)); } public void LoadTimeline() { //return; var knownStatusTypes = new List { typeof (Tweet), typeof (SelfDirectMessage), typeof (DirectMessage), //typeof (YammerUpdate), //typeof (TumblrUpdate) }; using (var store = IsolatedStorageFile.GetUserStoreForApplication()) foreach (var t in knownStatusTypes) { var path = t.FullName + ".dat"; try { if (store.FileExists(path)) using (Stream s = store.OpenFile(path, FileMode.Open)) { var reader = new BinaryReader(s); var itemCount = reader.ReadInt32(); var updates = new List(); for (var i = 0; i < itemCount; i++) { var update = (IStatusUpdate)Activator.CreateInstance(t); update.Load("", reader, _contactRepository, Accounts); updates.Add(update); } StatusManager.Send(updates); } } catch (Exception) { //TODO: Logging store.DeleteFile(path); } } } public void SaveTimeline() { var x = StatusManager.Collection.GroupBy(t => t.GetType()); foreach (var y in x) { using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { try { var path = y.Key.FullName + ".dat"; using (Stream s = store.OpenFile(path, FileMode.Create, FileAccess.Write)) { var writer = new BinaryWriter(s); writer.Write(y.Count()); foreach (var i in y.OrderByDescending(t => t.Time).Take(50)) { i.Save(writer); } writer.Flush(); } } catch (IsolatedStorageException ex) { Debug.WriteLine(ex); } } } } /* #region Notification stuff public void HandleNotifications() { if (!Accounts.Any()) return; if (String.IsNullOrEmpty(_applicationSettings.PushAccount)) return; var id = Accounts.Where(a => a.Protocol == "twitter" && a.Credentials.AccountId == _applicationSettings.PushAccount).First().Credentials.AccountId; if (id == null) return; try { Channel = HttpNotificationChannel.Find(ChannelName); if (Channel != null) { Debug.WriteLine(Channel.ChannelUri.ToString()); if (!Channel.IsShellTileBound) Channel.BindToShellTile(); if (!Channel.IsShellToastBound) Channel.BindToShellToast(); SetNotifications(id); } else { Channel = new HttpNotificationChannel(ChannelName); Channel.ChannelUriUpdated += (updatedSender, updatedArgs) => { Debug.WriteLine(Channel.ChannelUri.ToString()); SetNotifications(id); }; Channel.ErrorOccurred += (errorSender, errorArgs) => { Debug.WriteLine(errorArgs.ErrorAdditionalData); SetNotifications(id); }; Channel.Open(); Channel.BindToShellTile(); Channel.BindToShellToast(); } } catch (Exception ex) { Console.Write(ex.Message); Debug.WriteLine(ex); } //}); } public void SetNotifications(String id) { Channel = HttpNotificationChannel.Find(ChannelName); if (Channel == null) { HandleNotifications(); return; } var option = _applicationSettings.Push; var c = new SiteStreamingServiceClient(new BasicHttpBinding(), new EndpointAddress(PushAddress)); c.RequestNotificationsCompleted += c_RequestNotificationsCompleted; c.StopNotificationsCompleted += c_StopNotificationsCompleted; c.OpenCompleted += (s, ie) => c.RequestNotificationsAsync(id, Channel.ChannelUri.ToString(), option); c.OpenAsync(); } void c_RequestNotificationsCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { } void c_StopNotificationsCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { } internal void RemoveNotifications(String Id) { if (Channel == null) { HandleNotifications(); return; } Channel = HttpNotificationChannel.Find(ChannelName); var c = new SiteStreamingServiceClient(new BasicHttpBinding(), new EndpointAddress(PushAddress)); c.OpenCompleted += (s, ie) => c.StopNotificationsAsync(Id, null); c.OpenAsync(); } #endregion */ } }