PageRenderTime 82ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/SOViewController.xib.cs

http://github.com/conceptdev/iSOFlair
C# | 341 lines | 257 code | 33 blank | 51 comment | 21 complexity | 7f2f20d6baf3bc3342d060442fa485ea MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.IO;
  5. using MonoTouch.Foundation;
  6. using MonoTouch.UIKit;
  7. using System.Net;
  8. using System.Text;
  9. namespace iSOFlair
  10. {
  11. /// <summary>
  12. /// Flair page 'template', re-used four times
  13. /// </summary>
  14. public partial class SOViewController : UIViewController
  15. {
  16. #region Constructors
  17. // The IntPtr and NSCoder constructors are required for controllers that need
  18. // to be able to be created from a xib rather than from managed code
  19. public SOViewController (IntPtr handle) : base(handle)
  20. {
  21. Initialize ();
  22. }
  23. [Export("initWithCoder:")]
  24. public SOViewController (NSCoder coder) : base(coder)
  25. {
  26. Initialize ();
  27. }
  28. public SOViewController ()
  29. {
  30. Initialize ();
  31. }
  32. void Initialize ()
  33. {
  34. }
  35. #endregion
  36. private TrilogySite _site = null;
  37. public TrilogySite Site {
  38. get { return _site; }
  39. set {
  40. _site = value;
  41. imageLogo.Image = UIImage.FromFile (Site.Logo);
  42. }
  43. }
  44. /// <summary>
  45. /// Path to save image and cache
  46. /// </summary>
  47. public string DocumentsDirectory { get; set; }
  48. public string Username {
  49. get { return labelUsername.Text; }
  50. set { labelUsername.Text = value; }
  51. }
  52. public string Points {
  53. get { return labelPoints.Text; }
  54. set { labelPoints.Text = value; }
  55. }
  56. private string ImagePath {
  57. get { return Path.Combine (DocumentsDirectory, Site.PreferencesPrefix + "gravatar.png"); }
  58. }
  59. private string CachePath {
  60. get { return Path.Combine (DocumentsDirectory, Site.PreferencesPrefix + "cache.txt"); }
  61. }
  62. /// <summary>
  63. /// Setup the button delegates
  64. /// </summary>
  65. public void WireUp ()
  66. {
  67. buttonUpdate.TouchDown += delegate {
  68. buttonUpdate.Hidden = true;
  69. buttonSafari.Hidden = true;
  70. ScreenCapture ();
  71. buttonUpdate.Hidden = false;
  72. buttonSafari.Hidden = false;
  73. };
  74. buttonSafari.TouchDown += delegate { UIApplication.SharedApplication.OpenUrl (new NSUrl (String.Format (Site.ProfileUrl, Site.SiteId))); };
  75. }
  76. #region respond to shaking (OS3+)
  77. // also requires you to put
  78. // UIApplication.SharedApplication.ApplicationSupportsShakeToEdit = true;
  79. // in Main.cs : FinishedLaunching()
  80. public override bool CanBecomeFirstResponder {
  81. get { return true; }
  82. }
  83. public override void ViewDidAppear (bool animated)
  84. {
  85. base.ViewDidAppear (animated);
  86. this.BecomeFirstResponder ();
  87. }
  88. public override void ViewWillDisappear (bool animated)
  89. {
  90. this.ResignFirstResponder ();
  91. base.ViewWillDisappear (animated);
  92. }
  93. public override void MotionEnded (UIEventSubtype motion, UIEvent evt)
  94. {
  95. Console.WriteLine ("Motion detected");
  96. if (motion == UIEventSubtype.MotionShake) {
  97. Console.WriteLine ("and was a shake");
  98. labelLastUpdated.Text = "All shook up! Updating...";
  99. // never appears
  100. // Do your application-specific shake response here...
  101. Update ();
  102. }
  103. }
  104. #endregion
  105. /// <summary>
  106. /// Load data from txt file (cached from last webclient request)
  107. /// </summary>
  108. public bool LoadFromCache ()
  109. {
  110. bool loaded = false;
  111. Console.WriteLine ("Loading from cache.txt");
  112. try {
  113. string cache = "";
  114. if (File.Exists (CachePath)) {
  115. cache = System.IO.File.ReadAllText (CachePath);
  116. }
  117. if (cache == "") {
  118. labelConnectionError.Text = "Cache is empty. Shake to refresh data.";
  119. labelUsername.Text = "";
  120. labelPoints.Text = "";
  121. labelGoldBadges.Text = "";
  122. labelSilverBadges.Text = "";
  123. labelBronzeBadges.Text = "";
  124. textDebug.Text = "";
  125. } else {
  126. string[] cacheItems = cache.Split ('?');
  127. labelUsername.Text = cacheItems[0];
  128. labelPoints.Text = cacheItems[1];
  129. labelGoldBadges.Text = cacheItems[2] + " gold badges";
  130. labelSilverBadges.Text = cacheItems[3] + " silver badges";
  131. labelBronzeBadges.Text = cacheItems[4] + " bronze badges";
  132. //profileUrl = cacheItems[5];
  133. labelLastUpdated.Text = cacheItems[6] + " from cache";
  134. textDebug.Text = "";
  135. // blank out, nothing loaded from the web
  136. if (File.Exists (ImagePath)) {
  137. UIImage img = UIImage.FromFileUncached (ImagePath);
  138. // TODO: WHY didn't FromFile work, when FromFileUncached does?
  139. if (img != null)
  140. this.imageAvatar.Image = img;
  141. }
  142. loaded = true;
  143. }
  144. } catch (Exception ex) {
  145. labelConnectionError.Text = "Cache is invalid. Shake to refresh data.";
  146. labelUsername.Text = "";
  147. labelPoints.Text = "";
  148. labelGoldBadges.Text = "";
  149. labelSilverBadges.Text = "";
  150. labelBronzeBadges.Text = "";
  151. textDebug.Text = "";
  152. }
  153. return loaded;
  154. }
  155. /// <summary>
  156. /// Update this site data from the web, but downloading the flair, parsing
  157. /// and saving in a cache text file
  158. /// </summary>
  159. public void Update ()
  160. {
  161. Console.WriteLine ("Loading from web " + Site.SiteId);
  162. labelLastUpdated.Text = "Loading...";
  163. // Download flair page
  164. WebClient wc = new WebClient ();
  165. Uri uri = new Uri (String.Format (Site.FlairUrl, Site.SiteId));
  166. byte[] bytes = null;
  167. try {
  168. UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
  169. bytes = wc.DownloadData (uri);
  170. } catch (Exception ex) {
  171. Console.WriteLine ("Internet connection failed: " + ex.Message);
  172. textDebug.Text = Environment.NewLine + "DOWNLOADDATA:" + Environment.NewLine + ex.Message;
  173. labelLastUpdated.Text = "Internet connection failed: " + ex.Message;
  174. labelConnectionError.Text = "Update failed: cannot connect to the Internet.";
  175. return;
  176. } finally {
  177. UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false;
  178. }
  179. // Parse flair HTML
  180. try {
  181. string result = Encoding.UTF8.GetString (bytes);
  182. int startpos = result.IndexOf ("<a");
  183. startpos = result.IndexOf ("href=", startpos) + 6;
  184. int endpos = result.IndexOf ("\"", startpos);
  185. string profileUrl = result.Substring (startpos, endpos - startpos);
  186. startpos = result.IndexOf ("img src", endpos) + 9;
  187. endpos = result.IndexOf ("\"", startpos);
  188. // download image
  189. string gravatarUrl = result.Substring (startpos, endpos - startpos);
  190. uri = new Uri (gravatarUrl);
  191. try {
  192. Console.WriteLine ("wc.Download(" + uri + "," + ImagePath + ")");
  193. wc.DownloadFile (uri, ImagePath);
  194. } catch (Exception ex1) {
  195. textDebug.Text += Environment.NewLine + "DOWNLOAD IMAGE:" + Environment.NewLine + gravatarUrl + Environment.NewLine + ImagePath + Environment.NewLine + ex1.Message;
  196. }
  197. // Parse the HTML
  198. //HACK: yes this is a hack... HtmlAgilityPack would've been smarter.
  199. startpos = result.IndexOf ("username", endpos);
  200. startpos = result.IndexOf ("_blank", endpos) + 8;
  201. endpos = result.IndexOf ("<", startpos);
  202. string username = result.Substring (startpos, endpos - startpos);
  203. labelUsername.Text = username;
  204. startpos = result.IndexOf ("reputation score", endpos) + 18;
  205. endpos = result.IndexOf ("<", startpos);
  206. string points = result.Substring (startpos, endpos - startpos);
  207. string goldBadges = "", silverBadges = "", bronzeBadges = "";
  208. startpos = result.IndexOf ("gold badge", endpos);
  209. if (startpos > 0) {
  210. startpos--;
  211. // remove preceding space
  212. endpos = result.IndexOf ("\"", startpos - 10) + 1;
  213. goldBadges = result.Substring (endpos, startpos - endpos);
  214. Console.WriteLine (" " + goldBadges);
  215. labelGoldBadges.Text = goldBadges + " gold badges";
  216. }
  217. startpos = result.IndexOf ("silver badge", endpos);
  218. if (startpos > 0) {
  219. startpos--;
  220. // remove preceding space
  221. endpos = result.IndexOf ("\"", startpos - 10) + 1;
  222. silverBadges = result.Substring (endpos, startpos - endpos);
  223. labelSilverBadges.Text = silverBadges + " silver badges";
  224. }
  225. startpos = result.IndexOf ("bronze badge", endpos);
  226. if (startpos > 0) {
  227. startpos--;
  228. // remove preceding space
  229. endpos = result.IndexOf ("\"", startpos - 10) + 1;
  230. bronzeBadges = result.Substring (endpos, startpos - endpos);
  231. labelBronzeBadges.Text = bronzeBadges + " bronze badges";
  232. }
  233. // load image from file into UIImage
  234. try {
  235. if (File.Exists (ImagePath)) {
  236. //UIImage img = UIImage.FromFile (ImagePath); // WHY does this break???
  237. UIImage img = UIImage.FromFileUncached (ImagePath);
  238. // BUT this works???
  239. if (img != null)
  240. this.imageAvatar.Image = img;
  241. } else {
  242. textDebug.Text += Environment.NewLine + "UIIMAGE NOT EXIST:" + Environment.NewLine + ImagePath;
  243. }
  244. } catch (Exception ex2) {
  245. textDebug.Text += Environment.NewLine + "FROM FILE: " + Environment.NewLine + ImagePath + Environment.NewLine + ex2.Message;
  246. }
  247. Console.WriteLine ("gold " + goldBadges);
  248. Console.WriteLine ("silver " + silverBadges);
  249. Console.WriteLine ("bronze " + bronzeBadges);
  250. labelPoints.Text = points;
  251. string dateUpdated = "Last updated " + DateTime.Now.ToString ("dd-MMM-yy hh:mm:ss");
  252. labelLastUpdated.Text = dateUpdated;
  253. string cache = String.Format ("{0}?{1}?{2}?{3}?{4}?{5}?{6}", username, points, goldBadges, silverBadges, bronzeBadges, profileUrl, dateUpdated);
  254. System.IO.File.WriteAllText (CachePath, cache);
  255. labelConnectionError.Text = "";
  256. // blank out if we get to here without Exception
  257. } catch (Exception ex) {
  258. labelLastUpdated.Text = ex.Message;
  259. textDebug.Text += Environment.NewLine + ex.Message;
  260. }
  261. }
  262. /// <summary>
  263. /// Capture a copy of the current View and:
  264. /// * re-display in a UIImage control
  265. /// * save to the Photos collection
  266. /// * save to disk in the application's Documents folder
  267. /// </summary>
  268. public void ScreenCapture ()
  269. {
  270. Console.WriteLine ("start image cap");
  271. Console.WriteLine ("frame" + this.View.Frame.Size);
  272. UIGraphics.BeginImageContext (View.Frame.Size);
  273. var documentsDirectory = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
  274. var ctx = UIGraphics.GetCurrentContext ();
  275. if (ctx != null) {
  276. Console.WriteLine ("ctx not null");
  277. View.Layer.RenderInContext (ctx);
  278. Console.WriteLine ("render in context");
  279. UIImage img = UIGraphics.GetImageFromCurrentImageContext ();
  280. Console.WriteLine ("get from current content");
  281. UIGraphics.EndImageContext ();
  282. // Set to display in a UIImage control _on_ the view
  283. //imageLogo.Image = img;
  284. // Save to Photos
  285. img.SaveToPhotosAlbum ((sender, args) =>
  286. {
  287. Console.WriteLine ("image saved to Photos");
  288. var av = new UIAlertView ("Screenshot saved", "Image saved to " + Environment.NewLine + "Photos : Camera Roll", null, "Ok thanks", null);
  289. av.Show ();
  290. });
  291. // thought this "might" overwrite the splashscreen
  292. //string png = Path.Combine (documentsDirectory, "../iSOFlair.app/Default.png");
  293. // Save to application's Documents folder, kinda pointless except as an example
  294. // since there is no way to "read" it
  295. string png = Path.Combine (documentsDirectory, "Screenshot.png");
  296. NSData imgData = img.AsPNG ();
  297. NSError err = null;
  298. if (imgData.Save (png, false, out err)) {
  299. Console.WriteLine ("saved " + png);
  300. } else {
  301. Console.WriteLine ("not saved" + png + " because" + err.LocalizedDescription);
  302. }
  303. } else {
  304. Console.WriteLine ("ctx null - doesn't happen but wasn't sure at first");
  305. }
  306. }
  307. }
  308. }