PageRenderTime 66ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/BaconographyWP8Core/View/LinkedPictureView.xaml.cs

https://github.com/hippiehunter/Baconography
C# | 356 lines | 314 code | 37 blank | 5 comment | 85 complexity | d2c858c7c05cf22670c2bbddb6be61cc MD5 | raw file
  1. using BaconographyPortable.Common;
  2. using BaconographyPortable.Messages;
  3. using BaconographyPortable.Services;
  4. using BaconographyPortable.ViewModel;
  5. using BaconographyWP8.Common;
  6. using BaconographyWP8.Converters;
  7. using BaconographyWP8.Messages;
  8. using BaconographyWP8.PlatformServices;
  9. using BaconographyWP8Core;
  10. using BaconographyWP8Core.Common;
  11. using BaconographyWP8Core.View;
  12. using GalaSoft.MvvmLight;
  13. using GalaSoft.MvvmLight.Command;
  14. using GalaSoft.MvvmLight.Messaging;
  15. using Microsoft.Phone.Controls;
  16. using Microsoft.Practices.ServiceLocation;
  17. using Microsoft.Xna.Framework.Media;
  18. using Newtonsoft.Json;
  19. using System;
  20. using System.Collections.Generic;
  21. using System.Collections.ObjectModel;
  22. using System.IO;
  23. using System.Linq;
  24. using System.Net;
  25. using System.Threading;
  26. using System.Threading.Tasks;
  27. using System.Windows;
  28. using System.Windows.Controls;
  29. using System.Windows.Controls.Primitives;
  30. using System.Windows.Data;
  31. using System.Windows.Documents;
  32. using System.Windows.Input;
  33. using System.Windows.Media;
  34. using System.Windows.Media.Imaging;
  35. using System.Windows.Navigation;
  36. using Windows.Foundation;
  37. using Windows.Foundation.Collections;
  38. // The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237
  39. namespace BaconographyWP8.View
  40. {
  41. /// <summary>
  42. /// A basic page that provides characteristics common to most applications.
  43. /// </summary>
  44. [ViewUri("/BaconographyWP8Core;component/View/LinkedPictureView.xaml")]
  45. public sealed partial class LinkedPictureView : PhoneApplicationPage
  46. {
  47. //cheating a little bit here but its for the best
  48. string _pictureData;
  49. LinkedPictureViewModel _pictureViewModel;
  50. IViewModelContextService _viewModelContextService;
  51. ISmartOfflineService _smartOfflineService;
  52. public LinkedPictureView()
  53. {
  54. using (ServiceLocator.Current.GetInstance<ISuspendableWorkQueue>().HighValueOperationToken)
  55. {
  56. this.InitializeComponent();
  57. }
  58. _viewModelContextService = ServiceLocator.Current.GetInstance<IViewModelContextService>();
  59. _smartOfflineService = ServiceLocator.Current.GetInstance<ISmartOfflineService>();
  60. _saveCommand = new RelayCommand(SaveImage_Tap);
  61. }
  62. void myGridGestureListener_Handle(object sender, Microsoft.Phone.Controls.GestureEventArgs e)
  63. {
  64. appBar.Interact();
  65. }
  66. protected override void OnNavigatedTo(NavigationEventArgs e)
  67. {
  68. this.AdjustForOrientation(this.Orientation);
  69. if (this.State != null && this.State.ContainsKey("PictureViewModelData"))
  70. {
  71. _pictureData = this.State["PictureViewModelData"] as string;
  72. if (_pictureData != null)
  73. {
  74. var deserializedObject = JsonConvert.DeserializeObject<Tuple<string, IEnumerable<Tuple<string, string>>, string>>(_pictureData);
  75. if (deserializedObject != null)
  76. {
  77. _pictureViewModel = new LinkedPictureViewModel
  78. {
  79. LinkTitle = deserializedObject.Item1.Replace("&amp;", "&").Replace("&lt;", "<").Replace("&gt;", ">").Replace("&quot;", "\"").Replace("&apos;", "'").Trim(),
  80. LinkId = deserializedObject.Item3,
  81. Pictures = deserializedObject.Item2.Select(tpl => new LinkedPictureViewModel.LinkedPicture
  82. {
  83. Title = tpl.Item1.Replace("&amp;", "&").Replace("&lt;", "<").Replace("&gt;", ">").Replace("&quot;", "\"").Replace("&apos;", "'").Trim(),
  84. ImageSource = tpl.Item2, Url = tpl.Item2
  85. })
  86. };
  87. }
  88. }
  89. }
  90. else if (this.NavigationContext.QueryString["data"] != null)
  91. {
  92. var unescapedData = HttpUtility.UrlDecode(this.NavigationContext.QueryString["data"]);
  93. var deserializedObject = JsonConvert.DeserializeObject<Tuple<string, IEnumerable<Tuple<string, string>>, string>>(unescapedData);
  94. if (deserializedObject != null)
  95. {
  96. _pictureViewModel = new LinkedPictureViewModel
  97. {
  98. LinkTitle = deserializedObject.Item1.Replace("&amp;", "&").Replace("&lt;", "<").Replace("&gt;", ">").Replace("&quot;", "\"").Replace("&apos;", "'").Trim(),
  99. LinkId = deserializedObject.Item3,
  100. Pictures = deserializedObject.Item2.Select(tpl => new LinkedPictureViewModel.LinkedPicture
  101. {
  102. Title = tpl.Item1.Replace("&amp;", "&").Replace("&lt;", "<").Replace("&gt;", ">").Replace("&quot;", "\"").Replace("&apos;", "'").Trim(),
  103. ImageSource = tpl.Item2, Url = tpl.Item2
  104. })
  105. };
  106. _pictureData = unescapedData;
  107. }
  108. }
  109. if (DataContext == null || e == null)
  110. {
  111. DataContext = _pictureViewModel;
  112. albumPivot.DataContext = _pictureViewModel.Pictures;
  113. }
  114. _viewModelContextService.PushViewModelContext(DataContext as ViewModelBase);
  115. _smartOfflineService.NavigatedToView(typeof(LinkedPictureView), e == null ? true : e.NavigationMode == NavigationMode.New);
  116. }
  117. protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
  118. {
  119. if (e.NavigationMode == NavigationMode.New && e.Uri.ToString() == "/BaconographyWP8Core;component/MainPage.xaml" && e.IsCancelable)
  120. {
  121. e.Cancel = true;
  122. }
  123. _viewModelContextService.PopViewModelContext(DataContext as ViewModelBase);
  124. }
  125. private void AdjustForOrientation(PageOrientation orientation)
  126. {
  127. Messenger.Default.Send<OrientationChangedMessage>(new OrientationChangedMessage { Orientation = orientation });
  128. lastKnownOrientation = orientation;
  129. if (albumPivot != null)
  130. {
  131. if (orientation == PageOrientation.LandscapeRight)
  132. albumPivot.Margin = new Thickness(0, 0, 60, 0);
  133. else if (orientation == PageOrientation.LandscapeLeft)
  134. albumPivot.Margin = new Thickness(0, 0, 60, 0);
  135. else
  136. albumPivot.Margin = new Thickness(0, 0, 0, 90);
  137. }
  138. }
  139. PageOrientation lastKnownOrientation;
  140. protected override void OnOrientationChanged(OrientationChangedEventArgs e)
  141. {
  142. AdjustForOrientation(e.Orientation);
  143. base.OnOrientationChanged(e);
  144. }
  145. protected override void OnNavigatedFrom(NavigationEventArgs e)
  146. {
  147. if(e.NavigationMode == NavigationMode.Back)
  148. CleanupImageSource();
  149. if (e.NavigationMode == NavigationMode.New && e.IsNavigationInitiator)
  150. {
  151. var absPath = e.Uri.ToString().Contains('?') ? e.Uri.ToString().Substring(0, e.Uri.ToString().IndexOf("?")) : e.Uri.ToString();
  152. if (absPath == "/BaconographyWP8Core;component/View/LinkedPictureView.xaml" || absPath == "/BaconographyWP8Core;component/View/LinkedReadabilityView.xaml" ||
  153. absPath == "/BaconographyWP8Core;component/View/LinkedSelfTextPageView.xaml" || absPath == "/BaconographyWP8Core;component/View/LinkedVideoView.xaml")
  154. {
  155. CleanupImageSource();
  156. ServiceLocator.Current.GetInstance<INavigationService>().RemoveBackEntry();
  157. }
  158. }
  159. else if (e.NavigationMode == NavigationMode.New)
  160. {
  161. var absPath = e.Uri.ToString().Contains('?') ? e.Uri.ToString().Substring(0, e.Uri.ToString().IndexOf("?")) : e.Uri.ToString();
  162. if (absPath == "app://external/")
  163. {
  164. ReifiedAlbumItemConverter.CancelSource.Cancel();
  165. ReifiedAlbumItemConverter.CancelSource = new CancellationTokenSource();
  166. }
  167. }
  168. }
  169. private void CleanupImageSource()
  170. {
  171. try
  172. {
  173. ReifiedAlbumItemConverter.CancelSource.Cancel();
  174. ReifiedAlbumItemConverter.CancelSource = new CancellationTokenSource();
  175. this.State.Clear();
  176. foreach (var item in albumPivot.Items)
  177. {
  178. if (item is PivotItem)
  179. {
  180. var content = ((PivotItem)item).Content;
  181. if (content is ScalingGifView)
  182. {
  183. ((ScalingGifView)content).ImageSource = null;
  184. }
  185. else if (content is ScalingPictureView)
  186. {
  187. ((ScalingPictureView)content).ImageSource = null;
  188. }
  189. ((PivotItem)item).Content = null;
  190. var context = ((PivotItem)item).DataContext as BaconographyPortable.ViewModel.LinkedPictureViewModel.LinkedPicture;
  191. context.ImageSource = null;
  192. }
  193. else if (item is BaconographyPortable.ViewModel.LinkedPictureViewModel.LinkedPicture)
  194. {
  195. ((BaconographyPortable.ViewModel.LinkedPictureViewModel.LinkedPicture)item).ImageSource = null;
  196. }
  197. }
  198. ((LinkedPictureViewModel)DataContext).Cleanup();
  199. if (albumPivot.ItemsSource is ObservableCollection<PivotItem>)
  200. {
  201. ((ObservableCollection<PivotItem>)albumPivot.ItemsSource).Clear();
  202. }
  203. DataContext = null;
  204. this.Content = null;
  205. if (_gcCount <= 0)
  206. Task.Factory.StartNew(RunGC, TaskCreationOptions.LongRunning);
  207. }
  208. catch
  209. {
  210. }
  211. }
  212. private static int _gcCount = 0;
  213. private static void RunGC()
  214. {
  215. if (_gcCount >= 1)
  216. return;
  217. _gcCount++;
  218. for(int i = 0; i < 3; i++)
  219. {
  220. GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
  221. GC.WaitForPendingFinalizers();
  222. }
  223. _gcCount--;
  224. }
  225. private PivotItem _priorItem;
  226. private PivotItem _currentItem;
  227. private PivotItem _nextItem;
  228. private Tuple<PivotItem, PivotItem, PivotItem> GenerateItemTripplet(PivotItem newCurrent)
  229. {
  230. PivotItem prior = null, current = newCurrent, next = null;
  231. var currentIndex = albumPivot.Items.IndexOf(newCurrent);
  232. if (currentIndex > 0)
  233. prior = albumPivot.Items[currentIndex - 1] as PivotItem;
  234. if (currentIndex + 1 < albumPivot.Items.Count)
  235. next = albumPivot.Items[currentIndex + 1] as PivotItem;
  236. return Tuple.Create(prior, current, next);
  237. }
  238. private async void albumPivot_LoadingPivotItem(object sender, PivotItemEventArgs e)
  239. {
  240. appBar.Interact();
  241. if (e.Item != null)
  242. {
  243. var itemTpl = GenerateItemTripplet(e.Item);
  244. if (itemTpl.Item2 != null && itemTpl.Item2.Content == null)
  245. {
  246. lock (itemTpl.Item2)
  247. {
  248. if(itemTpl.Item2.Content == null)
  249. itemTpl.Item2.Content = ReifiedAlbumItemConverter.MapPictureVM(itemTpl.Item2.DataContext as ViewModelBase);
  250. }
  251. }
  252. await Task.Yield();
  253. if (itemTpl.Item3 != null && itemTpl.Item3.Content == null && _priorItem != itemTpl.Item2)
  254. {
  255. lock (itemTpl.Item3)
  256. {
  257. if (itemTpl.Item3.Content == null)
  258. itemTpl.Item3.Content = ReifiedAlbumItemConverter.MapPictureVM(itemTpl.Item3.DataContext as ViewModelBase);
  259. }
  260. }
  261. lock (this)
  262. {
  263. _priorItem = itemTpl.Item1;
  264. _currentItem = itemTpl.Item2;
  265. _nextItem = itemTpl.Item3;
  266. }
  267. }
  268. }
  269. private void albumPivot_UnloadingPivotItem(object sender, PivotItemEventArgs e)
  270. {
  271. if (e.Item != null)
  272. {
  273. ClearItem(e.Item);
  274. if(_gcCount <= 0)
  275. Task.Factory.StartNew(RunGC, TaskCreationOptions.LongRunning);
  276. }
  277. }
  278. private static void ClearItem(PivotItem item)
  279. {
  280. if (item.Content is ScalingGifView)
  281. {
  282. ((ScalingGifView)item.Content).ImageSource = null;
  283. }
  284. else if (item.Content is ScalingPictureView)
  285. {
  286. ((ScalingPictureView)item.Content).ImageSource = null;
  287. }
  288. item.Content = null;
  289. }
  290. public void myGridGestureListener_Flick(object sender, FlickGestureEventArgs e)
  291. {
  292. FlipViewUtility.FlickHandler(sender, e, DataContext as ViewModelBase, this);
  293. }
  294. private RelayCommand _saveCommand;
  295. public RelayCommand SaveCommand
  296. {
  297. get
  298. {
  299. return _saveCommand;
  300. }
  301. }
  302. private async void SaveImage_Tap()
  303. {
  304. var linkedPicture = _pictureViewModel.Pictures.ToList()[albumPivot.SelectedIndex];
  305. Messenger.Default.Send<LoadingMessage>(new LoadingMessage { Loading = true });
  306. if (linkedPicture != null)
  307. {
  308. MediaLibrary library = new MediaLibrary();
  309. var libraryPicture = library.SavePicture(linkedPicture.Url.Substring(linkedPicture.Url.LastIndexOf('/') + 1), await ImagesService.ImageStreamFromUrl(linkedPicture.Url));
  310. var notificationService = ServiceLocator.Current.GetInstance<INotificationService>();
  311. if (libraryPicture != null)
  312. notificationService.CreateNotification("Picture saved.");
  313. else
  314. notificationService.CreateNotification("Error downloading picture.");
  315. }
  316. Messenger.Default.Send<LoadingMessage>(new LoadingMessage { Loading = false });
  317. }
  318. }
  319. }