NewReplyNotification.xaml.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. using InABox.Core;
  2. using Plugin.Media;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using Comal.Classes;
  10. using Xamarin.Forms;
  11. using Xamarin.Forms.Xaml;
  12. using XF.Material.Forms.UI.Dialogs;
  13. using comal.timesheets.CustomControls;
  14. using InABox.Clients;
  15. namespace comal.timesheets
  16. {
  17. [XamlCompilation(XamlCompilationOptions.Compile)]
  18. public partial class NewReplyNotification
  19. {
  20. Guid notificationID = new Guid();
  21. List<Document> newDocuments = new List<Document>();
  22. Notification notification = new Notification();
  23. public NewReplyNotification(Guid id = new Guid())
  24. {
  25. InitializeComponent();
  26. NavigationPage.SetHasBackButton(this, false);
  27. notificationID = id;
  28. notification.Sender.ID = App.Data.Me.ID;
  29. if (App.DeviceString == "i")
  30. {
  31. photosFrame.Margin = new Thickness(5, 5, 5, 15);
  32. }
  33. if (notificationID != Guid.Empty)
  34. {
  35. LoadExistingNotification();
  36. }
  37. }
  38. private void ExitBtn_Clicked(object sender, EventArgs e)
  39. {
  40. Navigation.PopAsync();
  41. }
  42. void LoadExistingNotification()
  43. {
  44. Task.Run(() =>
  45. {
  46. CoreTable table = new Client<Notification>().Query(
  47. new Filter<Notification>(x => x.ID).IsEqualTo(notificationID),
  48. new Columns<Notification>(
  49. x => x.ID,
  50. x => x.Title,
  51. x => x.Description,
  52. x => x.EntityID,
  53. x => x.EntityType,
  54. x => x.Sender.ID,
  55. x => x.Sender.Name)
  56. );
  57. if (table.Rows.Any())
  58. {
  59. notification = table.Rows.FirstOrDefault().ToObject<Notification>();
  60. Device.BeginInvokeOnMainThread(() =>
  61. {
  62. try
  63. {
  64. titleEdt.Text = notification.Title;
  65. StringBuilder sb = new StringBuilder();
  66. if (!string.IsNullOrWhiteSpace(notification.Sender.Name))
  67. {
  68. titleLbl.Text = "Replying " + notification.Sender.Name;
  69. sb.AppendFormat("Hi {0},\n\n\nAt {1:HH:mmtt} on {1:dd MMM yy}, {2} wrote:\n", notification.Sender.Name.Split(" ").FirstOrDefault(), notification.Created, notification.Sender.Name);
  70. notification.Employee.ID = notification.Sender.ID;
  71. notification.Employee.Name = notification.Sender.Name;
  72. recipientNameLbl.Text = notification.Employee.Name;
  73. }
  74. var origtext = CoreUtils.StripHTML(notification.Description);
  75. foreach (var line in origtext.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Where(x => !String.IsNullOrWhiteSpace(x)))
  76. {
  77. sb.AppendFormat(">> {0}\n", line.Trim());
  78. }
  79. descriptionEdt.Text = sb.ToString();
  80. LoadPhotos();
  81. ForceLayout();
  82. }
  83. catch { }
  84. });
  85. }
  86. });
  87. }
  88. void LoadPhotos()
  89. {
  90. Task.Run(() =>
  91. {
  92. CoreTable table = new Client<NotificationDocument>().Query(
  93. new Filter<NotificationDocument>(x => x.EntityLink.ID).IsEqualTo(notificationID),
  94. new Columns<NotificationDocument>(x => x.ID, x => x.DocumentLink.ID)
  95. );
  96. if (table.Rows.Any())
  97. {
  98. Device.BeginInvokeOnMainThread(() =>
  99. {
  100. photosLbl.Text = "Loading " + table.Rows.Count + " Photos";
  101. photosLbl.TextColor = Color.Orange;
  102. });
  103. foreach (CoreRow row in table.Rows)
  104. {
  105. CoreTable table2 = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(Guid.Parse(row.Values[1].ToString())), new Columns<Document>(x => x.Data));
  106. DataToImage(table2.Rows.FirstOrDefault().ToObject<Document>().Data);
  107. }
  108. Device.BeginInvokeOnMainThread(() =>
  109. {
  110. photosLbl.Text = "Photos";
  111. photosLbl.TextColor = Color.Default;
  112. });
  113. }
  114. });
  115. }
  116. void SelectRecipientBtn_Clicked(object sender, EventArgs e)
  117. {
  118. Navigation.PushAsync(new EmployeeSelectionPage(employee =>
  119. {
  120. recipientNameLbl.Text = employee.Name;
  121. notification.Employee.ID = employee.ID;
  122. notification.Employee.Name = employee.Name;
  123. }));
  124. }
  125. async void SendBtn_Clicked(object sender, EventArgs e)
  126. {
  127. if (notification.Employee.ID == Guid.Empty)
  128. {
  129. DisplayAlert("Unable to send", "Notification requires a recipient", "OK");
  130. return;
  131. }
  132. if (string.IsNullOrWhiteSpace(notification.Title))
  133. {
  134. DisplayAlert("Unable to send", "Notification requires a title", "OK");
  135. return;
  136. }
  137. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Sending"))
  138. {
  139. new Client<Notification>().Save(notification, "Notification sent on mobile device");
  140. if (newDocuments.Count > 0)
  141. {
  142. SavePhotos();
  143. }
  144. DisplayAlert("Success", "Notification sent to " + notification.Employee.Name, "OK");
  145. Navigation.PopAsync();
  146. }
  147. }
  148. void SavePhotos()
  149. {
  150. List<NotificationDocument> nDocsToSave = new List<NotificationDocument>();
  151. new Client<Document>().Save(newDocuments, "Saved from Notifications on Mobile");
  152. foreach (Document doc in newDocuments)
  153. {
  154. NotificationDocument notificationDocument = new NotificationDocument();
  155. notificationDocument.EntityLink.ID = notification.ID;
  156. notificationDocument.DocumentLink.ID = doc.ID;
  157. nDocsToSave.Add(notificationDocument);
  158. }
  159. Task.Run(() => { new Client<NotificationDocument>().Save(nDocsToSave, "Saved from Notifications on Mobile"); });
  160. }
  161. void TitleEdt_Changed(object sender, EventArgs e)
  162. {
  163. notification.Title = titleEdt.Text;
  164. }
  165. void DescriptionEdt_Changed(object sender, EventArgs e)
  166. {
  167. notification.Description = descriptionEdt.Text;
  168. }
  169. #region Photos
  170. void TakePhoto_Clicked(object sender, EventArgs e)
  171. {
  172. TakeAPhoto();
  173. }
  174. void ChooseImage_Clicked(object sender, EventArgs e)
  175. {
  176. ChooseAPhoto();
  177. }
  178. private async void TakeAPhoto()
  179. {
  180. await CrossMedia.Current.Initialize();
  181. if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
  182. {
  183. await DisplayAlert("No Camera", ":( No camera available.", "OK");
  184. return;
  185. }
  186. String filename = String.Format("{0:yyyy-MM-dd HH:mm:ss.fff}.png", DateTime.Now);
  187. var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
  188. {
  189. Name = filename,
  190. CompressionQuality = 10,
  191. PhotoSize = Plugin.Media.Abstractions.PhotoSize.Full
  192. });
  193. if (file == null)
  194. return;
  195. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Adding Photo"))
  196. {
  197. Image img = null;
  198. var memoryStream = new MemoryStream();
  199. file.GetStream().CopyTo(memoryStream);
  200. var data = memoryStream.ToArray();
  201. Document doc = new Document()
  202. {
  203. FileName = filename,
  204. Data = data,
  205. CRC = CoreUtils.CalculateCRC(data),
  206. TimeStamp = DateTime.Now
  207. };
  208. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  209. img = new Image();
  210. img.HeightRequest = 150;
  211. img.WidthRequest = 150;
  212. img.Aspect = Aspect.AspectFit;
  213. img.Source = src;
  214. img.GestureRecognizers.Add(new TapGestureRecognizer
  215. {
  216. Command = new Command(OnTap),
  217. CommandParameter = src,
  218. NumberOfTapsRequired = 1
  219. });
  220. newDocuments.Add(doc);
  221. file.Dispose();
  222. if (img != null)
  223. {
  224. Device.BeginInvokeOnMainThread(() =>
  225. {
  226. ImageScroller.IsVisible = true;
  227. images.Children.Add(img);
  228. });
  229. }
  230. }
  231. }
  232. private async void ChooseAPhoto()
  233. {
  234. await CrossMedia.Current.Initialize();
  235. if (!CrossMedia.Current.IsPickPhotoSupported)
  236. {
  237. await DisplayAlert("No Library", ":( No Photo Library available.", "OK");
  238. return;
  239. }
  240. var file = await CrossMedia.Current.PickPhotoAsync(new Plugin.Media.Abstractions.PickMediaOptions()
  241. {
  242. CompressionQuality = 10,
  243. PhotoSize = Plugin.Media.Abstractions.PhotoSize.Full
  244. });
  245. if (file == null)
  246. return;
  247. using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Adding Photo"))
  248. {
  249. Image img = null;
  250. var memoryStream = new MemoryStream();
  251. file.GetStream().CopyTo(memoryStream);
  252. var data = memoryStream.ToArray();
  253. Document doc = new Document()
  254. {
  255. FileName = Path.GetFileName(file.Path),
  256. Data = data,
  257. CRC = CoreUtils.CalculateCRC(data),
  258. TimeStamp = DateTime.Now
  259. };
  260. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  261. img = new Image();
  262. img.HeightRequest = 150;
  263. img.WidthRequest = 150;
  264. img.Aspect = Aspect.AspectFit;
  265. img.Source = src;
  266. img.GestureRecognizers.Add(new TapGestureRecognizer
  267. {
  268. Command = new Command(OnTap),
  269. CommandParameter = src,
  270. NumberOfTapsRequired = 1
  271. });
  272. newDocuments.Add(doc);
  273. file.Dispose();
  274. if (img != null)
  275. {
  276. Device.BeginInvokeOnMainThread(() =>
  277. {
  278. ImageScroller.IsVisible = true;
  279. images.Children.Add(img);
  280. });
  281. }
  282. }
  283. }
  284. private void OnTap(object obj)
  285. {
  286. ImageViewerEditor viewer = new ImageViewerEditor(obj as ImageSource, false);
  287. Navigation.PushAsync(viewer);
  288. viewer.OnSaveSelected += ImageViewEditor_OnSaveSelected;
  289. }
  290. private void ImageViewEditor_OnSaveSelected(byte[] array)
  291. {
  292. String filename = String.Format("{0:yyyy-MM-dd HH:mm:ss.fff}.png", DateTime.Now);
  293. DataToImage(array, filename);
  294. }
  295. public void DataToImage(byte[] data, string filename = "")
  296. {
  297. try
  298. {
  299. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  300. Image image = new Image();
  301. image.HeightRequest = 200;
  302. image.WidthRequest = 200;
  303. image.Aspect = Aspect.AspectFit;
  304. image.VerticalOptions = LayoutOptions.FillAndExpand;
  305. image.HorizontalOptions = LayoutOptions.FillAndExpand;
  306. image.Source = src;
  307. image.GestureRecognizers.Add(new TapGestureRecognizer
  308. {
  309. Command = new Command(OnTap),
  310. CommandParameter = src,
  311. NumberOfTapsRequired = 1
  312. });
  313. if (image != null)
  314. {
  315. Device.BeginInvokeOnMainThread(() =>
  316. {
  317. images.Children.Add(image);
  318. });
  319. }
  320. if (!string.IsNullOrWhiteSpace(filename))
  321. {
  322. Document doc = new Document()
  323. {
  324. FileName = filename,
  325. Data = data,
  326. CRC = CoreUtils.CalculateCRC(data),
  327. TimeStamp = DateTime.Now
  328. };
  329. newDocuments.Add(doc);
  330. }
  331. }
  332. catch
  333. { }
  334. }
  335. #endregion
  336. }
  337. }