using System; using System.IO; using System.Threading.Tasks; using Plugin.Media; using Plugin.Media.Abstractions; using Syncfusion.Pdf; using Syncfusion.Pdf.Graphics; using Xamarin.Essentials; namespace InABox.Mobile { public enum MobileDocumentSize { Small, Medium, Large, Full } public enum MobileDocumentQuality { Low, Medium, High, } public interface IMobileDocumentOptions { } public class MobileDocumentCameraOptions : IMobileDocumentOptions { public MobileDocumentSize Size { get; set; } public int Compression { get; set; } public MobileDocumentCameraOptions() { Size = MobileDocumentSize.Medium; Compression = 10; } } public class MobileDocumentPhotoLibraryOptions : IMobileDocumentOptions { public MobileDocumentSize Size { get; set; } public int Compression { get; set; } public MobileDocumentPhotoLibraryOptions() { Size = MobileDocumentSize.Medium; Compression = 10; } } public class MobileDocumentVideoOptions : IMobileDocumentOptions { public MobileDocumentSize Size { get; set; } public int Compression { get; set; } public MobileDocumentQuality Quality { get; set; } public MobileDocumentVideoOptions() { Size = MobileDocumentSize.Medium; Compression = 10; Quality = MobileDocumentQuality.Medium; } } public class MobileDocumentVideoLibraryOptions : IMobileDocumentOptions { // Picking a video actually doesnt have any options } public abstract class MobileDocumentSource { public abstract Task From(); } public abstract class MobileDocumentSource : MobileDocumentSource where TOptions : class, IMobileDocumentOptions, new() { protected TOptions Options { get; } protected MobileDocumentSource(TOptions options = null) { Options = options ?? new TOptions(); } protected abstract bool IsEnabled { get; } protected abstract Task Capture(); public override async Task From() { await CrossMedia.Current.Initialize(); var result = new MobileDocument(); if (IsEnabled) { try { var file = await Capture(); if (file != null) { result.FileName = Path.GetFileName(file.OriginalFilename ?? file.Path); await using (var stream = file.GetStream()) { BinaryReader br = new BinaryReader(stream); result.Data = br.ReadBytes((int)stream.Length); } } } catch (FeatureNotSupportedException fnsEx) { MobileLogging.Log(fnsEx, "Capture(FNS)"); } catch (PermissionException pEx) { MobileLogging.Log(pEx, "Capture(PERM)"); } catch (Exception ex) { MobileLogging.Log(ex, "Capture(ERR)"); } } return result; } } public class MobileDocumentCameraSource : MobileDocumentSource { public MobileDocumentCameraSource(MobileDocumentCameraOptions options = null) : base(options) { } protected override bool IsEnabled => CrossMedia.Current.IsCameraAvailable && CrossMedia.Current.IsTakePhotoSupported; protected override async Task Capture() { return await CrossMedia.Current.TakePhotoAsync( new StoreCameraMediaOptions() { Name = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}.png", CompressionQuality = Options.Compression, PhotoSize = Options.Size switch { MobileDocumentSize.Small => PhotoSize.Small, MobileDocumentSize.Large => PhotoSize.Large, MobileDocumentSize.Full => PhotoSize.Full, _ => PhotoSize.Medium }, } ); } } public class MobileDocumentPhotoLibrarySource : MobileDocumentSource { public MobileDocumentPhotoLibrarySource(MobileDocumentPhotoLibraryOptions options = null) : base(options) { } protected override bool IsEnabled => CrossMedia.Current.IsPickPhotoSupported; protected override async Task Capture() { return await CrossMedia.Current.PickPhotoAsync( new PickMediaOptions() { CompressionQuality = Options.Compression, PhotoSize = Options.Size switch { MobileDocumentSize.Small => PhotoSize.Small, MobileDocumentSize.Large => PhotoSize.Large, MobileDocumentSize.Full => PhotoSize.Full, _ => PhotoSize.Medium }, } ); } } public class MobileDocumentVideoSource : MobileDocumentSource { public MobileDocumentVideoSource(MobileDocumentVideoOptions options = null) : base(options) { } protected override bool IsEnabled => CrossMedia.Current.IsCameraAvailable && CrossMedia.Current.IsTakeVideoSupported; protected override async Task Capture() { return await CrossMedia.Current.TakeVideoAsync( new StoreVideoOptions() { Name = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}.mp4", CompressionQuality = Options.Compression, PhotoSize = Options.Size switch { MobileDocumentSize.Small => PhotoSize.Small, MobileDocumentSize.Large => PhotoSize.Large, MobileDocumentSize.Full => PhotoSize.Full, _ => PhotoSize.Medium }, Quality = Options.Quality switch { MobileDocumentQuality.Low => VideoQuality.Low, MobileDocumentQuality.High => VideoQuality.High, _ => VideoQuality.Medium } } ); } } public class MobileDocumentVideoLibrarySource : MobileDocumentSource { public MobileDocumentVideoLibrarySource(MobileDocumentVideoLibraryOptions options = null) : base(options) { } protected override bool IsEnabled => CrossMedia.Current.IsPickVideoSupported; protected override async Task Capture() { return await CrossMedia.Current.PickVideoAsync(); } } public static class MobileDocumentExtensions { } public class MobileDocument { public string FileName { get; set; } public byte[] Data { get; set; } public MobileDocument() { FileName = ""; Data = new byte[] { }; } public MobileDocument(string filename, byte[] data) { FileName = filename; Data = data; } public void ConvertToPDF() { using (var img = new MemoryStream(Data)) { var image = new PdfBitmap(img); var pdfDoc = new PdfDocument(); var section = pdfDoc.Sections.Add(); section.PageSettings.Margins.All = 0; section.PageSettings.Width = image.Width; section.PageSettings.Height = image.Height; var page = section.Pages.Add(); page.Graphics.DrawImage(image, 0, 0, page.Size.Width, page.Size.Height); using (var ms = new MemoryStream()) { pdfDoc.Save(ms); Data = ms.GetBuffer(); FileName = Path.ChangeExtension(FileName, "pdf"); } } } public bool IsPDF() => FileName.ToUpper().EndsWith(".PDF"); public static async Task From(T source = null) where T : MobileDocumentSource { source ??= (T)Activator.CreateInstance(typeof(T), new object[] { null }); return await source.From(); } } }