| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- using Comal.Classes;
- using CommunityToolkit.Mvvm.ComponentModel;
- using CommunityToolkit.Mvvm.Input;
- using InABox.Avalonia;
- using InABox.Avalonia.Dialogs;
- using InABox.Avalonia.Platform.Barcodes;
- using InABox.Core;
- using Microsoft.Maui.Devices;
- using PRS.Avalonia.Modules;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- namespace PRS.Avalonia.Components;
- [Flags]
- public enum ScannerMode
- {
- None = 0,
- Equipment = 1,
- Delivery = 2,
- Setout = 4,
- ManufacturingPacket = 8,
- Product = 16,
- All = ScannerMode.Equipment | ScannerMode.Delivery | ScannerMode.Setout | ScannerMode.ManufacturingPacket | ScannerMode.Product
- }
- public partial class ScannerViewModel : ModuleViewModel
- {
- public override string Title => "Scanner";
- [ObservableProperty]
- private bool _cameraEnabled;
- [ObservableProperty]
- private bool _processing;
- [ObservableProperty]
- private Func<IReadOnlySet<BarcodeResult>, Task<bool>>? _itemScanned;
- [ObservableProperty]
- private ScannerMode _mode;
- private (ScannerMode Mode, Func<BarcodeResult, Task<IScanResult?>> Func)[] Modes;
- [ObservableProperty]
- private bool _scannerVisible = true;
- public ScannerViewModel()
- {
- Modes = [
- (ScannerMode.Setout, ScanSetout),
- (ScannerMode.ManufacturingPacket, ScanManufacturingPacket),
- (ScannerMode.Product, ScanProduct),
- (ScannerMode.Equipment, ScanEquipment),
- (ScannerMode.Delivery, ScanDelivery)
- ];
- }
- protected override Task OnActivated()
- {
- CameraEnabled = true;
- return base.OnActivated();
- }
- protected override Task OnDeactivated()
- {
- CameraEnabled = false;
- return base.OnDeactivated();
- }
- private interface IScanResult
- {
- public string Name { get; }
- public Task Continue();
- }
- private class ScanResult<T>(string name, T obj, Func<T, Task> continuation) : IScanResult
- {
- public string Name { get; set; } = name;
- public T Object { get; set; } = obj;
- public Func<T, Task> Continuation { get; set; } = continuation;
- public async Task Continue()
- {
- await Continuation(Object);
- }
- }
- private ScanResult<T> Result<T>(string name, T obj, Func<T, Task> continuation) => new ScanResult<T>(name, obj, continuation);
- [RelayCommand]
- private async Task DetectionFinished(IReadOnlySet<BarcodeResult> result)
- {
- if(result.Count > 0)
- {
- if (Processing || !CameraEnabled) return;
- Processing = true;
- var scanned = false;
- if(ItemScanned != null)
- {
- if(await ItemScanned.Invoke(result))
- {
- scanned = true;
- CameraEnabled = false;
- }
- }
- if (!scanned && Mode != ScannerMode.None)
- {
- var results = new List<IScanResult>();
- var modes = Modes.Where(x => Mode.HasFlag(x.Mode)).ToArray();
- foreach(var barcode in result.ToArray())
- {
- var tasks = modes.ToArray(x => x.Func(barcode));
- await Task.WhenAll(tasks);
- results.AddRange(tasks.Select(x => x.Result).NotNull());
- }
- if(results.Count == 1)
- {
- Vibration.Vibrate();
- await results[0].Continue();
- }
- else if(results.Count > 1)
- {
- Vibration.Vibrate();
- ScannerVisible = false;
- var choice = await OptionDialog.Execute("Choose Item:", results.ToArray(x => x.Name));
- ScannerVisible = true;
- var selected = choice is not null ? results.FirstOrDefault(x => x.Name == choice) : null;
- if(selected is not null)
- {
- await selected.Continue();
- }
- }
- else
- {
- Vibration.Vibrate();
- await Task.Delay(200);
- Vibration.Vibrate();
- await Task.Delay(1000);
- }
- }
- Processing = false;
- }
- }
- private async Task<IScanResult?> ScanSetout(BarcodeResult barcode)
- {
- var filter = Guid.TryParse(barcode.RawValue, out var id)
- ? new Filter<DeliveryItem>(x => x.ID).IsEqualTo(id)
- : new Filter<DeliveryItem>(x => x.Barcode).IsEqualTo(barcode.RawValue);
- var model = new DeliveryItemModel(
- DataAccess,
- () => filter,
- () => DefaultCacheFileName<DeliveryItemShell>());
- await model.RefreshAsync(true);
- var item = model.FirstOrDefault();
- if(item is null || item.SetoutID == Guid.Empty)
- {
- return null;
- }
- var setoutModel = new SetoutModel(
- DataAccess,
- () => new Filter<Setout>(x => x.ID).IsEqualTo(item.SetoutID),
- () => DefaultCacheFileName<SetoutShell>(item.SetoutID));
- await setoutModel.RefreshAsync(true);
- var setout = setoutModel.FirstOrDefault();
- if(setout is null)
- {
- return null;
- }
- return Result($"Design {setout.Number}", setout, OpenSetout);
- }
- private Task OpenSetout(SetoutShell shell)
- {
- Navigation.Navigate<ManufacturingDesignDetailsViewModel>(model =>
- {
- model.Shell = shell;
- });
- return Task.CompletedTask;
- }
- private async Task<IScanResult?> ScanManufacturingPacket(BarcodeResult barcode)
- {
- if (!Mode.HasFlag(ScannerMode.ManufacturingPacket)) return null;
- if(!Guid.TryParse(barcode.RawValue, out var id))
- {
- return null;
- }
- var model = new ManufacturingPacketModel(
- DataAccess,
- () => new Filter<ManufacturingPacket>(x => x.ID).IsEqualTo(id),
- () => DefaultCacheFileName<ManufacturingPacketShell>());
- await model.RefreshAsync(true);
- var packet = model.FirstOrDefault();
- return packet is not null
- ? Result($"Manufacturing packet {packet.SetoutNumber}", packet, OpenManufacturingPacket)
- : null;
- }
- private Task OpenManufacturingPacket(ManufacturingPacketShell shell)
- {
- Navigation.Navigate<ManufacturingPacketDetailsViewModel>(model =>
- {
- model.Shell = shell;
- });
- return Task.CompletedTask;
- }
- private Task<IScanResult?> ScanProduct(BarcodeResult barcode)
- {
- return Task.FromResult<IScanResult?>(null);
- }
- private async Task<IScanResult?> ScanDelivery(BarcodeResult barcode)
- {
- if(!Guid.TryParse(barcode.RawValue, out var id))
- {
- return null;
- }
- var model = new DeliveryModel(
- DataAccess,
- () => new Filter<Delivery>(x => x.ID).IsEqualTo(id),
- () => DefaultCacheFileName<DeliveryShell>());
- await model.RefreshAsync(true);
- var delivery = model.FirstOrDefault();
- return delivery is not null
- ? Result($"Delivery {delivery.Number} {delivery.TypeDescription}", delivery, OpenDelivery)
- : null;
- }
- private Task OpenDelivery(DeliveryShell shell)
- {
- Navigation.Navigate<DeliveryViewModel>(model =>
- {
- model.Delivery = shell;
- });
- return Task.CompletedTask;
- }
- private async Task<IScanResult?> ScanEquipment(BarcodeResult barcode)
- {
- var filter = Guid.TryParse(barcode.RawValue, out var id)
- ? new Filter<Equipment>(x => x.ID).IsEqualTo(id)
- : new Filter<Equipment>(x => x.Code).IsEqualTo(barcode.RawValue);
- var model = new EquipmentModel(
- DataAccess,
- () => filter,
- () => DefaultCacheFileName<EquipmentShell>());
- await model.RefreshAsync(true);
- var equipment = model.FirstOrDefault();
- if(equipment is null)
- {
- return null;
- }
- else
- {
- return Result($"Equipment {equipment.Code}", equipment, OpenEquipment);
- }
- }
- private Task OpenEquipment(EquipmentShell shell)
- {
- Navigation.Navigate<EquipmentDetailsViewModel>(model =>
- {
- model.Shell = shell;
- });
- return Task.CompletedTask;
- }
- }
|