using System; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using InABox.Core; using InABox.Mobile; using Xamarin.CommunityToolkit.Converters; using Xamarin.Forms; namespace PRS.Mobile { public abstract class DigitalFormEmbeddedMedia : Grid, IDigitalFormField where T : DFLayoutField, new() where TProperties : DFLayoutFieldProperties, new() { protected abstract bool IsVideo { get; } private readonly MobileCard _card; private readonly Image _image; private readonly MobileButton _cameraButton; private readonly MobileButton _libraryButton; private readonly MobileButton _clearButton; private T _definition; public T Definition { get => _definition; set { _definition = value; Initialize(value ?? new T()); } } private DFLayoutEmbeddedMediaValue _value = new(); public DFLayoutEmbeddedMediaValue Value { get => _value; set { _value = value; UpdateUI(); } } protected abstract byte[] CreateThumbnail(byte[] data, float maxwidth = 200, float maxheight = 200); private void UpdateUI() { if ((_value?.Thumbnail?.Any() != true) && (_value?.Data?.Any() == true)) _value.Thumbnail = CreateThumbnail(_value.Data); _image.Source = _value?.Thumbnail?.Any() == true ? ImageSource.FromStream(() => new MemoryStream(_value.Thumbnail)) : null; } public bool IsEmpty => Value.Data?.Any() != true; private bool _readOnly; public bool ReadOnly { get => _readOnly; set { _readOnly = value; UpdateStatus(); } } public void Deserialize(string serialized) { _value.Load(serialized); UpdateUI(); } public string Serialize() { if (_value == null) return new DFLayoutEmbeddedMediaValue().ToString(); if ((_value.Data?.Any() == true) && (_value.ID == Guid.Empty)) _value.ID = DigitalFormDocumentFactory.SaveDocument(_value.Data); return _value?.ToString() ?? ""; } public event DigitalFormViewChangedHandler ValueChanged; protected DigitalFormEmbeddedMedia() { HeightRequest = 250; ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) }); RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); _card = new MobileCard() { Padding = 5, IsClickable = true, }; _card.Clicked += ((o,e) => Image_Tapped()); SetRow(_card, 0); SetColumn(_card, 0); SetRowSpan(_card, 4); Children.Add(_card); _image = new Image() { Aspect = Aspect.AspectFit }; _image.GestureRecognizers.Add(new TapGestureRecognizer() { Command = new Command(Image_Tapped) }); _card.Content = _image; _cameraButton = new MobileButton { Image = "camera", ImageSize = new Size(25, 25), Orientation = StackOrientation.Vertical, CornerRadius = 5, WidthRequest = 40, HeightRequest = 40, }; SetRow(_cameraButton, 0); SetColumn(_cameraButton, 1); _cameraButton.Clicked += CameraButton_Clicked; Children.Add(_cameraButton); _libraryButton = new MobileButton { Image = "gallery", ImageSize = new Size(25, 25), Orientation = StackOrientation.Vertical, CornerRadius = 5, WidthRequest = 40, HeightRequest = 40, }; SetRow(_libraryButton, 1); SetColumn(_libraryButton, 1); _libraryButton.Clicked += LibraryButton_Clicked; Children.Add(_libraryButton); _clearButton = new MobileButton { Image = "cross", ImageSize = new Size(25, 25), Orientation = StackOrientation.Vertical, CornerRadius = 5, WidthRequest = 40, HeightRequest = 40, }; SetRow(_clearButton, 3); SetColumn(_clearButton, 1); _clearButton.Clicked += ClearButton_Clicked; Children.Add(_clearButton); } private void Image_Tapped() { if (_value == null) return; if (_value.Data?.Any() == true) Navigation.PushAsync(new ImageViewerPage(_value.Data)); else { if (_value.ID != Guid.Empty) { DigitalFormDocumentFactory.LoadDocument( _value.ID, data => { Device.BeginInvokeOnMainThread(() => { _value.Data = data; Navigation.PushAsync(new ImageViewerPage(data)); }); } ); } } } private void ClearButton_Clicked(object sender, MobileButtonClickEventArgs args) { _value.ID = Guid.Empty; _value.Thumbnail = null; _value.Data = null; UpdateUI(); } protected abstract Task CaptureMedia(); protected abstract Task SelectMedia(); private async void CameraButton_Clicked(object sender, MobileButtonClickEventArgs args) { var doc = await CaptureMedia(); if (doc != null) { _value.ID = Guid.Empty; _value.Thumbnail = CreateThumbnail(doc.Data); _value.Data = doc.Data; } Device.BeginInvokeOnMainThread(UpdateUI); } private async void LibraryButton_Clicked(object sender, MobileButtonClickEventArgs args) { var doc = await SelectMedia(); if (doc != null) { _value.ID = Guid.Empty; _value.Thumbnail = CreateThumbnail(doc.Data); _value.Data = doc.Data; } Device.BeginInvokeOnMainThread(UpdateUI); } private void Initialize(T definition) { UpdateStatus(); } protected abstract bool DisableLibrary { get; } protected abstract bool Secure { get; } protected abstract bool Required { get; } private void UpdateStatus() { _cameraButton.Image = IsVideo ? ImageSource.FromFile("camcorder") : ImageSource.FromFile("camera"); _libraryButton.Image = IsVideo ? ImageSource.FromFile("videolibrary") : ImageSource.FromFile("photolibrary"); _libraryButton.IsEnabled = !DisableLibrary; bool enabled = !_readOnly && !Secure; _cameraButton.IsEnabled = enabled; _libraryButton.IsEnabled = enabled && !DisableLibrary; var colors = DigitalFormUtils.GetColors(!enabled, Required, false); _card.BackgroundColor = colors.Background; _card.BorderColor = colors.Border; colors = DigitalFormUtils.GetColors(!enabled, Required, true); _cameraButton.BackgroundColor = colors.Background; _cameraButton.BorderColor = colors.Border; _libraryButton.BackgroundColor = colors.Background; _libraryButton.BorderColor = colors.Border; _clearButton.BackgroundColor = colors.Background; _clearButton.BorderColor = colors.Border; } } }