PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/BaconographyWP8Core/Common/Utility.cs

https://github.com/hippiehunter/Baconography
C# | 708 lines | 550 code | 101 blank | 57 comment | 123 complexity | 56a43ccc2e1473e5e4596d52c0c6b7aa MD5 | raw file
  1. using BaconographyPortable.Messages;
  2. using BaconographyPortable.Model;
  3. using BaconographyPortable.Model.Reddit;
  4. using BaconographyPortable.Services;
  5. using BaconographyWP8.Converters;
  6. using BaconographyWP8.PlatformServices;
  7. using BaconographyWP8.ViewModel;
  8. using BaconographyWP8BackgroundControls.View;
  9. using GalaSoft.MvvmLight.Messaging;
  10. using Microsoft.Phone.Scheduler;
  11. using Microsoft.Practices.ServiceLocation;
  12. using Newtonsoft.Json;
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Diagnostics;
  16. using System.IO;
  17. using System.IO.IsolatedStorage;
  18. using System.Linq;
  19. using System.Text;
  20. using System.Threading.Tasks;
  21. using System.Windows;
  22. using System.Windows.Controls;
  23. using System.Windows.Media;
  24. using System.Windows.Media.Imaging;
  25. using System.Windows.Threading;
  26. using Windows.Networking.Connectivity;
  27. namespace BaconographyWP8.Common
  28. {
  29. public class Utility
  30. {
  31. public static SolidColorBrush GetColorFromHexa(string hexaColor)
  32. {
  33. return new SolidColorBrush(
  34. Color.FromArgb(
  35. Convert.ToByte(hexaColor.Substring(1, 2), 16),
  36. Convert.ToByte(hexaColor.Substring(3, 2), 16),
  37. Convert.ToByte(hexaColor.Substring(5, 2), 16),
  38. Convert.ToByte(hexaColor.Substring(7, 2), 16)
  39. )
  40. );
  41. }
  42. public const string ReadMailGlyph = "\uE166";
  43. public const string UnreadMailGlyph = "\uE119";
  44. private static bool loadingActiveLockScreen = false;
  45. private static string CleanRedditLink(string userInput, User user)
  46. {
  47. if (userInput == "/")
  48. return userInput;
  49. if (user != null && !string.IsNullOrWhiteSpace(user.Username))
  50. {
  51. var selfMulti = "/" + user.Username + "/m/";
  52. if (userInput.Contains(selfMulti))
  53. {
  54. return "/me/m/" + userInput.Substring(userInput.IndexOf(selfMulti) + selfMulti.Length);
  55. }
  56. }
  57. if (userInput.StartsWith("me/m/"))
  58. return "/" + userInput;
  59. else if (userInput.StartsWith("/m/"))
  60. return "/me" + userInput;
  61. else if (userInput.StartsWith("/me/m/"))
  62. return userInput;
  63. if (userInput.StartsWith("/u/"))
  64. {
  65. return userInput.Replace("/u/", "/user/");
  66. }
  67. if (userInput.StartsWith("r/"))
  68. return "/" + userInput;
  69. else if (userInput.StartsWith("/") && !userInput.StartsWith("/r/"))
  70. return "/r" + userInput;
  71. else if (userInput.StartsWith("/r/"))
  72. return userInput;
  73. else
  74. return "/r/" + userInput;
  75. }
  76. public static async Task DoActiveLockScreen(ISettingsService settingsService, IRedditService redditService, IUserService userService, IImagesService imagesService, INotificationService notificationService, bool supressInit)
  77. {
  78. try
  79. {
  80. if (loadingActiveLockScreen)
  81. {
  82. while (loadingActiveLockScreen)
  83. await Task.Yield();
  84. return;
  85. }
  86. var connectionProfile = NetworkInformation.GetInternetConnectionProfile();
  87. var connectionCostType = connectionProfile.GetConnectionCost().NetworkCostType;
  88. loadingActiveLockScreen = true;
  89. Messenger.Default.Send<LoadingMessage>(new LoadingMessage { Loading = true });
  90. var user = await userService.GetUser();
  91. var loginCookie = user.LoginCookie;
  92. var liveTileService = ServiceLocator.Current.GetInstance<ILiveTileService>();
  93. IEnumerable<string> lockScreenImages = new string[0];
  94. IEnumerable<string> tileImages = new string[0];
  95. if ((settingsService.UpdateImagesOnlyOnWifi && Microsoft.Phone.Net.NetworkInformation.DeviceNetworkInformation.IsWiFiEnabled) ||
  96. (!settingsService.UpdateImagesOnlyOnWifi && connectionCostType != NetworkCostType.Variable))
  97. {
  98. if(!settingsService.UseImagePickerForLockScreen)
  99. lockScreenImages = await MakeLockScreenImages(settingsService, redditService, userService, imagesService, liveTileService);
  100. tileImages = await MakeTileImages(settingsService, redditService, userService, imagesService);
  101. }
  102. else if(File.Exists(Windows.Storage.ApplicationData.Current.LocalFolder.Path + "taskSettings.json"))
  103. {
  104. //find the images we used last time
  105. var taskSettings = liveTileService.LoadTaskSettings();
  106. if (taskSettings != null)
  107. {
  108. if (!settingsService.UseImagePickerForLockScreen)
  109. {
  110. if (taskSettings.Value.lock_images.Length == 0
  111. && connectionCostType == NetworkCostType.Unrestricted)
  112. {
  113. lockScreenImages = await MakeLockScreenImages(settingsService, redditService, userService, imagesService, liveTileService, 1);
  114. }
  115. else
  116. lockScreenImages = taskSettings.Value.lock_images;
  117. }
  118. tileImages = taskSettings.Value.tile_images;
  119. }
  120. }
  121. if (settingsService.UseImagePickerForLockScreen)
  122. {
  123. lockScreenImages = new string[] { Windows.Storage.ApplicationData.Current.LocalFolder.Path + "\\lockScreenCache0.jpg" };
  124. }
  125. liveTileService.StoreTaskSettings((unused) =>
  126. {
  127. return new TaskSettings { rounded = settingsService.RoundedLockScreen, cookie = loginCookie ?? "", opacity = settingsService.OverlayOpacity.ToString(), number_of_items = settingsService.OverlayItemCount.ToString(), link_reddit = CleanRedditLink(settingsService.LockScreenReddit, user), live_reddit = CleanRedditLink(settingsService.LiveTileReddit, user), lock_images = lockScreenImages.ToArray(), tile_images = tileImages.ToArray() };
  128. }, false);
  129. //this can happen when the user is still trying to use the application so dont lock up the UI thread with this work
  130. await Task.Yield();
  131. var lockScreenViewModel = await MakeLockScreenControl(settingsService, redditService, userService, lockScreenImages);
  132. //nasty nasty hack for stupid platform limitation, no data binding if you're not in the visual tree
  133. var lockScreenView = new LockScreenViewControl(lockScreenViewModel);
  134. lockScreenView.Width = settingsService.ScreenWidth;
  135. lockScreenView.Height = settingsService.ScreenHeight;
  136. lockScreenView.UpdateLayout();
  137. lockScreenView.Measure(new Size(settingsService.ScreenWidth, settingsService.ScreenHeight));
  138. lockScreenView.Arrange(new Rect(0, 0, settingsService.ScreenWidth, settingsService.ScreenHeight));
  139. WriteableBitmap bitmap = new WriteableBitmap(settingsService.ScreenWidth, settingsService.ScreenHeight);
  140. bitmap.Render(lockScreenView, new ScaleTransform() { ScaleX = 1, ScaleY = 1 });
  141. bitmap.Invalidate();
  142. string targetFilePath = Windows.Storage.ApplicationData.Current.LocalFolder.Path + "\\lockscreen.jpg";
  143. if (File.Exists(targetFilePath))
  144. {
  145. targetFilePath = Windows.Storage.ApplicationData.Current.LocalFolder.Path + "\\lockscreenAlt.jpg";
  146. }
  147. using (var lockscreenJpg = File.Create(targetFilePath))
  148. {
  149. bitmap.SaveJpeg(lockscreenJpg, settingsService.ScreenWidth, settingsService.ScreenHeight, 0, 100);
  150. lockscreenJpg.Flush(true);
  151. lockscreenJpg.Close();
  152. }
  153. //this can happen when the user is still trying to use the application so dont lock up the UI thread with this work
  154. await Task.Yield();
  155. LockHelper(Path.GetFileName(targetFilePath), false, supressInit);
  156. if (targetFilePath.EndsWith("lockscreenAlt.jpg") && File.Exists(Windows.Storage.ApplicationData.Current.LocalFolder.Path + "\\lockscreen.jpg"))
  157. {
  158. File.Delete(Windows.Storage.ApplicationData.Current.LocalFolder.Path + "\\lockscreen.jpg");
  159. }
  160. else if (targetFilePath.EndsWith("lockscreen.jpg") && File.Exists(Windows.Storage.ApplicationData.Current.LocalFolder.Path + "\\lockscreenAlt.jpg"))
  161. {
  162. File.Delete(Windows.Storage.ApplicationData.Current.LocalFolder.Path + "\\lockscreenAlt.jpg");
  163. }
  164. if(settingsService.EnableUpdates)
  165. StartPeriodicAgent();
  166. if(settingsService.EnableOvernightUpdates)
  167. StartIntensiveAgent();
  168. }
  169. catch
  170. {
  171. notificationService.CreateNotification("There was an error while setting the lock screen");
  172. }
  173. finally
  174. {
  175. loadingActiveLockScreen = false;
  176. Messenger.Default.Send<LoadingMessage>(new LoadingMessage { Loading = false });
  177. }
  178. }
  179. public static void RemoveAgent(string name)
  180. {
  181. try
  182. {
  183. ScheduledActionService.Remove(name);
  184. }
  185. catch (Exception)
  186. {
  187. }
  188. }
  189. public static readonly string periodicTaskName = "LockScreen_Updater";
  190. public static readonly string intensiveTaskName = "Intensive_Baconography_Updater";
  191. public static void StartPeriodicAgent()
  192. {
  193. // Obtain a reference to the period task, if one exists
  194. var periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;
  195. // If the task already exists and background agents are enabled for the
  196. // application, you must remove the task and then add it again to update
  197. // the schedule
  198. var disableBackground = ServiceLocator.Current.GetInstance<ISettingsService>().DisableBackground;
  199. if (periodicTask != null)
  200. {
  201. if (periodicTask.LastExitReason == AgentExitReason.None && periodicTask.IsScheduled && !disableBackground)
  202. {
  203. return;
  204. }
  205. RemoveAgent(periodicTaskName);
  206. }
  207. if (disableBackground)
  208. return;
  209. periodicTask = new PeriodicTask(periodicTaskName);
  210. // The description is required for periodic agents. This is the string that the user
  211. // will see in the background services Settings page on the device.
  212. periodicTask.Description = "Keeps your lockscreen up to date with the latest redditing";
  213. // Place the call to Add in a try block in case the user has disabled agents.
  214. try
  215. {
  216. ScheduledActionService.Add(periodicTask);
  217. //ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(20));
  218. }
  219. catch (InvalidOperationException exception)
  220. {
  221. if (exception.Message.Contains("BNS Error: The action is disabled"))
  222. {
  223. MessageBox.Show("Background agents for this application have been disabled by the user.");
  224. }
  225. if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
  226. {
  227. // No user action required. The system prompts the user when the hard limit of periodic tasks has been reached.
  228. }
  229. }
  230. catch (SchedulerServiceException)
  231. {
  232. }
  233. }
  234. public static void StartIntensiveAgent()
  235. {
  236. // Obtain a reference to the period task, if one exists
  237. var intensiveTask = ScheduledActionService.Find(intensiveTaskName) as ResourceIntensiveTask;
  238. // If the task already exists and background agents are enabled for the
  239. // application, you must remove the task and then add it again to update
  240. // the schedule
  241. if (intensiveTask != null)
  242. {
  243. RemoveAgent(intensiveTaskName);
  244. }
  245. if (ServiceLocator.Current.GetInstance<ISettingsService>().DisableBackground)
  246. return;
  247. intensiveTask = new ResourceIntensiveTask(intensiveTaskName);
  248. // The description is required for periodic agents. This is the string that the user
  249. // will see in the background services Settings page on the device.
  250. intensiveTask.Description = "This task does all of the heavy lifting for the lock screen updater and overnight offlining support";
  251. // Place the call to Add in a try block in case the user has disabled agents.
  252. try
  253. {
  254. ScheduledActionService.Add(intensiveTask);
  255. //ScheduledActionService.LaunchForTest(intensiveTaskName, TimeSpan.FromSeconds(60));
  256. }
  257. catch (InvalidOperationException exception)
  258. {
  259. if (exception.Message.Contains("BNS Error: The action is disabled"))
  260. {
  261. MessageBox.Show("Background agents for this application have been disabled by the user.");
  262. }
  263. if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
  264. {
  265. // No user action required. The system prompts the user when the hard limit of periodic tasks has been reached.
  266. }
  267. }
  268. catch (SchedulerServiceException)
  269. {
  270. }
  271. }
  272. public static async Task<IEnumerable<string>> MakeLockScreenImages(ISettingsService settingsService, IRedditService redditService, IUserService userService, IImagesService imagesService, ILiveTileService liveTileService, int limiter = 10)
  273. {
  274. try
  275. {
  276. //find the images we used last time
  277. var lockScreenSettings = liveTileService.LoadTaskSettings();
  278. if (lockScreenSettings != null && lockScreenSettings.Value.lock_images != null && lockScreenSettings.Value.lock_images.Length > 0)
  279. {
  280. var dateTime = File.GetLastWriteTime(Windows.Storage.ApplicationData.Current.LocalFolder.Path + "\\lockScreenCache0.jpg");
  281. if ((DateTime.Now - dateTime).TotalDays < 3)
  282. return lockScreenSettings.Value.lock_images;
  283. }
  284. }
  285. catch (Exception ex)
  286. {
  287. Debug.WriteLine(ex.ToString());
  288. }
  289. List<string> results = new List<string>();
  290. var imagesSubredditResult = await redditService.GetPostsBySubreddit(CleanRedditLink(settingsService.ImagesSubreddit, await userService.GetUser()), 100);
  291. var imagesLinks = new List<Thing>(imagesSubredditResult.Data.Children);
  292. imagesLinks.Select(thing => thing.Data is Link && imagesService.IsImage(((Link)thing.Data).Url)).ToList();
  293. if (imagesLinks.Count > 0)
  294. {
  295. //download images one at a time, check resolution
  296. //set LockScreenViewModel properties
  297. //render to bitmap
  298. //save bitmap
  299. BitmapImage imageSource = null;
  300. for (int i = 0; i < imagesLinks.Count; i++)
  301. {
  302. if (!(imagesLinks[i].Data is Link))
  303. continue;
  304. try
  305. {
  306. var url = ((Link)imagesLinks[i].Data).Url;
  307. imageSource = new BitmapImage();
  308. imageSource.CreateOptions = BitmapCreateOptions.None;
  309. var imagesList = await imagesService.GetImagesFromUrl("", url);
  310. if (imagesList == null || imagesList.Count() == 0)
  311. continue;
  312. url = imagesList.First().Item2;
  313. using (var stream = await ImagesService.ImageStreamFromUrl(url))
  314. {
  315. try
  316. {
  317. if (url.EndsWith(".jpg") || url.EndsWith(".jpeg"))
  318. {
  319. var dimensions = GetJpegDimensions(stream);
  320. stream.Seek(0, SeekOrigin.Begin);
  321. //bigger than 16 megs when loaded means we need to chuck it
  322. if (dimensions == null || (dimensions.Height * dimensions.Width * 4) > 16 * 1024 * 1024)
  323. continue;
  324. }
  325. else if (stream.Length > 1024 * 1024) //its too big drop it
  326. {
  327. continue;
  328. }
  329. }
  330. catch
  331. {
  332. if (stream.Length > 1024 * 1024) //its too big drop it
  333. {
  334. continue;
  335. }
  336. }
  337. imageSource.SetSource(stream);
  338. }
  339. if (imageSource.PixelHeight == 0 || imageSource.PixelWidth == 0)
  340. continue;
  341. if (settingsService.HighresLockScreenOnly
  342. && (imageSource.PixelHeight < 800
  343. || imageSource.PixelWidth < 480))
  344. continue;
  345. MakeSingleLockScreenFromImage(results.Count, imageSource);
  346. //this can happen when the user is still trying to use the application so dont lock up the UI thread with this work
  347. await Task.Yield();
  348. results.Add(string.Format("lockScreenCache{0}.jpg", results.Count.ToString()));
  349. if (results.Count >= limiter)
  350. break;
  351. }
  352. catch (OutOfMemoryException oom)
  353. {
  354. //we're done here
  355. break;
  356. }
  357. catch
  358. {
  359. continue;
  360. }
  361. }
  362. }
  363. return results;
  364. }
  365. public static void MakeSingleLockScreenFromImage(int pos, BitmapImage imageSource)
  366. {
  367. Image lockScreenView = new Image();
  368. lockScreenView.Width = 480;
  369. lockScreenView.Height = 800;
  370. lockScreenView.Source = imageSource;
  371. lockScreenView.Stretch = Stretch.UniformToFill;
  372. lockScreenView.UpdateLayout();
  373. lockScreenView.Measure(new Size(480, 800));
  374. lockScreenView.Arrange(new Rect(0, 0, 480, 800));
  375. WriteableBitmap bitmap = new WriteableBitmap(480, 800);
  376. bitmap.Render(lockScreenView, new ScaleTransform() { ScaleX = 1, ScaleY = 1 });
  377. bitmap.Invalidate();
  378. using (var theFile = File.Create(Windows.Storage.ApplicationData.Current.LocalFolder.Path + string.Format("\\lockScreenCache{0}.jpg", pos.ToString())))
  379. {
  380. bitmap.SaveJpeg(theFile, 480, 800, 0, 100);
  381. theFile.Flush(true);
  382. theFile.Close();
  383. }
  384. }
  385. public static Dimensions GetJpegDimensions(Stream fs)
  386. {
  387. if (!fs.CanSeek) throw new ArgumentException("Stream must be seekable");
  388. long blockStart;
  389. var buf = new byte[4];
  390. fs.Read(buf, 0, 4);
  391. if (buf.SequenceEqual(new byte[] { 0xff, 0xd8, 0xff, 0xe0 }))
  392. {
  393. blockStart = fs.Position;
  394. fs.Read(buf, 0, 2);
  395. var blockLength = ((buf[0] << 8) + buf[1]);
  396. fs.Read(buf, 0, 4);
  397. if (Encoding.UTF8.GetString(buf, 0, 4) == "JFIF"
  398. && fs.ReadByte() == 0)
  399. {
  400. blockStart += blockLength;
  401. while (blockStart < fs.Length)
  402. {
  403. fs.Position = blockStart;
  404. fs.Read(buf, 0, 4);
  405. blockLength = ((buf[2] << 8) + buf[3]);
  406. if (blockLength >= 7 && buf[0] == 0xff && buf[1] == 0xc0)
  407. {
  408. fs.Position += 1;
  409. fs.Read(buf, 0, 4);
  410. var height = (buf[0] << 8) + buf[1];
  411. var width = (buf[2] << 8) + buf[3];
  412. return new Dimensions(width, height);
  413. }
  414. blockStart += blockLength + 2;
  415. }
  416. }
  417. }
  418. return null;
  419. }
  420. public class Dimensions
  421. {
  422. private readonly int width;
  423. private readonly int height;
  424. public Dimensions(int width, int height)
  425. {
  426. this.width = width;
  427. this.height = height;
  428. }
  429. public int Width
  430. {
  431. get { return width; }
  432. }
  433. public int Height
  434. {
  435. get { return height; }
  436. }
  437. public override string ToString()
  438. {
  439. return string.Format("width:{0}, height:{1}", Width, Height);
  440. }
  441. }
  442. public static async Task<IEnumerable<string>> MakeTileImages(ISettingsService settingsService, IRedditService redditService, IUserService userService, IImagesService imagesService)
  443. {
  444. List<string> results = new List<string>();
  445. var linksSubredditResult = await redditService.GetPostsBySubreddit(CleanRedditLink(settingsService.LiveTileReddit, await userService.GetUser()), 100);
  446. var imagesLinks = new List<Thing>(linksSubredditResult.Data.Children);
  447. if (imagesLinks.Count > 0)
  448. {
  449. //download images one at a time, check resolution
  450. //set LockScreenViewModel properties
  451. //render to bitmap
  452. //save bitmap
  453. BitmapImage imageSource = null;
  454. for (int i = 0; i < imagesLinks.Count; i++)
  455. {
  456. if (!(imagesLinks[i].Data is Link))
  457. continue;
  458. try
  459. {
  460. var url = ((Link)imagesLinks[i].Data).Url;
  461. imageSource = new BitmapImage();
  462. imageSource.CreateOptions = BitmapCreateOptions.None;
  463. var imagesList = await imagesService.GetImagesFromUrl("", url);
  464. if (imagesList == null || imagesList.Count() == 0)
  465. continue;
  466. url = imagesList.First().Item2;
  467. var imageBytes = await imagesService.ImageBytesFromUrl(url);
  468. if (imageBytes != null)
  469. {
  470. using (var stream = new MemoryStream(imageBytes))
  471. {
  472. imageSource.SetSource(stream);
  473. }
  474. }
  475. if (imageSource.PixelHeight == 0 || imageSource.PixelWidth == 0)
  476. continue;
  477. Image lockScreenView = new Image();
  478. lockScreenView.Width = 691;
  479. lockScreenView.Height = 336;
  480. lockScreenView.Source = imageSource;
  481. lockScreenView.Stretch = Stretch.UniformToFill;
  482. lockScreenView.UpdateLayout();
  483. lockScreenView.Measure(new Size(691, 336));
  484. lockScreenView.Arrange(new Rect(0, 0, 691, 336));
  485. WriteableBitmap bitmap = new WriteableBitmap(691, 336);
  486. bitmap.Render(lockScreenView, new ScaleTransform() { ScaleX = 1, ScaleY = 1 });
  487. bitmap.Invalidate();
  488. using (var store = IsolatedStorageFile.GetUserStoreForApplication())
  489. {
  490. var filename = string.Format("/Shared/ShellContent/tileCache{0}.jpg", results.Count.ToString());
  491. using (var st = new IsolatedStorageFileStream(filename, FileMode.Create, FileAccess.Write, store))
  492. {
  493. bitmap.SaveJpeg(st, 691, 336, 0, 90);
  494. }
  495. }
  496. results.Add(string.Format("tileCache{0}.jpg", results.Count.ToString()));
  497. if (results.Count > 17)
  498. break;
  499. //this can happen when the user is still trying to use the application so dont lock up the UI thread with this work
  500. await Task.Yield();
  501. }
  502. catch
  503. {
  504. continue;
  505. }
  506. }
  507. }
  508. return results;
  509. }
  510. public static async Task<bool> RequestLockAccess()
  511. {
  512. try
  513. {
  514. var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;
  515. if (!isProvider)
  516. {
  517. // If you're not the provider, this call will prompt the user for permission.
  518. // Calling RequestAccessAsync from a background agent is not allowed.
  519. var op = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();
  520. // Only do further work if the access was granted.
  521. isProvider = op == Windows.Phone.System.UserProfile.LockScreenRequestResult.Granted;
  522. }
  523. return isProvider;
  524. }
  525. catch (System.Exception ex)
  526. {
  527. System.Diagnostics.Debug.WriteLine(ex.ToString());
  528. }
  529. return false;
  530. }
  531. public static async void LockHelper(string filePathOfTheImage, bool isAppResource, bool supressInit)
  532. {
  533. try
  534. {
  535. var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;
  536. if (!isProvider && !supressInit)
  537. {
  538. // If you're not the provider, this call will prompt the user for permission.
  539. // Calling RequestAccessAsync from a background agent is not allowed.
  540. var op = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();
  541. // Only do further work if the access was granted.
  542. isProvider = op == Windows.Phone.System.UserProfile.LockScreenRequestResult.Granted;
  543. }
  544. if (isProvider)
  545. {
  546. // At this stage, the app is the active lock screen background provider.
  547. // The following code example shows the new URI schema.
  548. // ms-appdata points to the root of the local app data folder.
  549. // ms-appx points to the Local app install folder, to reference resources bundled in the XAP package.
  550. var schema = isAppResource ? "ms-appx:///" : "ms-appdata:///Local/";
  551. var uri = new Uri(schema + filePathOfTheImage, UriKind.Absolute);
  552. // Set the lock screen background image.
  553. Windows.Phone.System.UserProfile.LockScreen.SetImageUri(uri);
  554. }
  555. }
  556. catch (System.Exception ex)
  557. {
  558. System.Diagnostics.Debug.WriteLine(ex.ToString());
  559. }
  560. }
  561. public static async Task<LockScreenViewModel> MakeLockScreenControl(ISettingsService settingsService, IRedditService redditService, IUserService userService, IEnumerable<string> lockScreenImages)
  562. {
  563. var user = (await userService.GetUser());
  564. LinkGlyphConverter linkGlyphConverter = new LinkGlyphConverter();
  565. List<LockScreenMessage> lockScreenMessages = new List<LockScreenMessage>();
  566. //dont call for messages here, its wastefull and we're going to toast them if there are an new messages anyway
  567. //if (user != null && user.LoginCookie != null && settingsService.MessagesInLockScreenOverlay)
  568. //{
  569. // var messages = await redditService.GetMessages(null);
  570. // lockScreenMessages.AddRange(messages.Data.Children.Where(thing => thing.Data is Message && ((Message)thing.Data).New).Take(3).Select(thing => new LockScreenMessage
  571. // {
  572. // DisplayText = thing.Data is CommentMessage ? ((CommentMessage)thing.Data).LinkTitle : ((Message)thing.Data).Subject,
  573. // Glyph = ((Message)thing.Data).New ? UnreadMailGlyph : ReadMailGlyph
  574. // }));
  575. //}
  576. if (settingsService.PostsInLockScreenOverlay && settingsService.OverlayItemCount > 0)
  577. {
  578. //call for posts from selected subreddit (defaults to front page)
  579. var frontPageResult = new List<Thing>((await redditService.GetPostsBySubreddit(CleanRedditLink(settingsService.LockScreenReddit, user), 10)).Data.Children);
  580. Shuffle(frontPageResult);
  581. lockScreenMessages.AddRange(frontPageResult.Where(thing => thing.Data is Link).Take(settingsService.OverlayItemCount - lockScreenMessages.Count).Select(thing => new LockScreenMessage { DisplayText = ((Link)thing.Data).Title, Glyph = linkGlyphConverter != null ? (string)linkGlyphConverter.Convert(((Link)thing.Data), typeof(String), null, System.Globalization.CultureInfo.CurrentCulture) : "" }));
  582. }
  583. List<string> shuffledLockScreenImages = new List<string>(lockScreenImages);
  584. Shuffle(shuffledLockScreenImages);
  585. var vml = new ViewModelLocator().LockScreen;
  586. vml.ImageSource = shuffledLockScreenImages.FirstOrDefault();
  587. vml.OverlayItems = lockScreenMessages;
  588. vml.OverlayOpacity = settingsService.OverlayOpacity;
  589. vml.NumberOfItems = settingsService.OverlayItemCount;
  590. vml.RoundedCorners = settingsService.RoundedLockScreen;
  591. return vml;
  592. }
  593. public static void Shuffle<T>(IList<T> list)
  594. {
  595. Random rng = new Random();
  596. int n = list.Count;
  597. while (n > 1)
  598. {
  599. n--;
  600. int k = rng.Next(n + 1);
  601. T value = list[k];
  602. list[k] = list[n];
  603. list[n] = value;
  604. }
  605. }
  606. }
  607. }