Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ScanQrCodeViewModel.cs
1using System.Collections.ObjectModel;
2using System.ComponentModel;
3using CommunityToolkit.Mvvm.ComponentModel;
4using CommunityToolkit.Mvvm.Input;
7using ZXing.Net.Maui;
8
10{
14 public partial class ScanQrCodeViewModel : BaseViewModel
15 {
16 private readonly ScanQrCodeNavigationArgs? navigationArgs;
17 private IDispatcherTimer? countDownTimer;
18 private bool suppressModeHandler;
19
24 {
25 this.navigationArgs = ServiceRef.NavigationService.PopLatestArgs<ScanQrCodeNavigationArgs>();
26 // Default: automatic scan => enable detecting
27 this.isAutomaticScan = true; // backing field to avoid recursion
28 this.isDetecting = true;
29 if (this.navigationArgs is not null &&
30 this.navigationArgs.AllowedSchemas is not null &&
31 this.navigationArgs.AllowedSchemas.Length > 0 &&
32 this.Icons.Count == 0)
33 {
34 foreach (string Schema in this.navigationArgs.AllowedSchemas)
35 {
36 switch (Schema)
37 {
39 this.Icons.Add(new UriSchemaIcon(Geometries.UserIconPath, Geometries.UserColor, this));
40 break;
41
44 break;
45
48 break;
49
52 break;
53
56 break;
57
60 break;
61
64 break;
65
68 break;
69
71 default:
72 break;
73 }
74 }
75
76 if (this.Icons.Count == 0)
78 }
79 }
80
81
82 [RelayCommand]
83 private async Task SwitchMode()
84 {
85 // Toggle IsAutomaticScan; page listens for change to animate & adjust camera
86 this.suppressModeHandler = true;
87 this.IsAutomaticScan = !this.IsAutomaticScan;
88 this.suppressModeHandler = false;
89 await Task.CompletedTask;
90 }
91
92 [RelayCommand]
93 private void SwitchCamera()
94 {
95 this.CameraLocation = this.CameraLocation == CameraLocation.Rear ? CameraLocation.Front : CameraLocation.Rear;
96 }
97
98 [RelayCommand]
99 private void SwitchTorch()
100 {
101 this.IsTorchOn = !this.IsTorchOn;
102 }
103
104 private static bool CanPickPhoto() => false; // Disabled for now
105
106 [RelayCommand(CanExecute = nameof(CanPickPhoto))]
107 private async Task PickPhoto()
108 {
109#if ANDROID
110 // Platform-specific implementation previously in page; keep placeholder for future
111 await Task.CompletedTask;
112#else
113 await Task.CompletedTask;
114#endif
115 }
116
117
119 public override async Task OnInitializeAsync()
120 {
121 await base.OnInitializeAsync();
122
123 LocalizationManager.Current.PropertyChanged += this.LocalizationManagerEventHandler;
124
125 if (App.Current is not null)
126 {
127 this.countDownTimer = App.Current.Dispatcher.CreateTimer();
128 this.countDownTimer.Interval = TimeSpan.FromMilliseconds(500);
129 this.countDownTimer.Tick += this.CountDownEventHandler;
130 }
131 }
132
134 public override async Task OnDisposeAsync()
135 {
136 LocalizationManager.Current.PropertyChanged -= this.LocalizationManagerEventHandler;
137
138 if (this.countDownTimer is not null)
139 {
140 this.countDownTimer.Stop();
141 this.countDownTimer.Tick -= this.CountDownEventHandler;
142 this.countDownTimer = null;
143 }
144
145 if (this.navigationArgs?.QrCodeScanned is TaskCompletionSource<string> TaskSource)
146 TaskSource.TrySetResult(string.Empty);
147
148 await base.OnDisposeAsync();
149 }
150
151 private void CountDownEventHandler(object? sender, EventArgs e)
152 {
153 this.countDownTimer?.Stop();
154 this.OnBackgroundColorChanged();
155 }
156
157 private void OnBackgroundColorChanged()
158 {
159 this.OnPropertyChanged(nameof(this.IconBackgroundColor));
160
161 foreach (UriSchemaIcon Icon in this.Icons)
162 Icon.BackgroundColorChanged();
163 }
164
165 public void LocalizationManagerEventHandler(object? sender, PropertyChangedEventArgs e)
166 {
167 this.OnPropertyChanged(nameof(this.LocalizedQrPageTitle));
168 }
169
170 public Task DoSwitchMode(bool IsAutomaticScan)
171 {
172 this.IsAutomaticScan = IsAutomaticScan;
173 return Task.CompletedTask;
174 }
175
176 public Task SetScannedText(string? ScannedText)
177 {
178 this.ScannedText = ScannedText ?? string.Empty;
179 this.countDownTimer?.Stop();
180 this.OnBackgroundColorChanged();
181
182 if (this.CanOpen(ScannedText))
183 {
184 return this.TrySetResultAndClosePage(ScannedText!.Trim());
185 }
186 this.countDownTimer?.Start();
187 this.OnBackgroundColorChanged();
188
189 return Task.CompletedTask;
190 }
191
196 private async Task TrySetResultAndClosePage(string? Url)
197 {
198 if (this.navigationArgs?.QrCodeScanned is not null)
199 {
200 TaskCompletionSource<string?> TaskSource = this.navigationArgs.QrCodeScanned;
201 this.navigationArgs.QrCodeScanned = null;
202
203 await MainThread.InvokeOnMainThreadAsync(async () =>
204 {
205 try
206 {
207 await base.GoBack();
208 TaskSource.TrySetResult(Url);
209 }
210 catch (Exception ex)
211 {
212 ServiceRef.LogService.LogException(ex);
213 }
214 });
215 }
216 }
217
218 #region Properties
219
223 [ObservableProperty]
224 [NotifyCanExecuteChangedFor(nameof(OpenUrlCommand))]
225 private string? manualText;
226
230 [ObservableProperty]
231 private string? scannedText;
232
236 [ObservableProperty]
237 private bool isAutomaticScan = true;
238
239 partial void OnIsAutomaticScanChanged(bool value)
240 {
241 if (!this.suppressModeHandler)
242 {
243 // When entering automatic mode, enable detecting; when leaving, disable
244 this.IsDetecting = value;
245 }
246 }
247
251 [ObservableProperty]
252 private bool isDetecting;
253
257 [ObservableProperty]
258 private bool isTorchOn;
259
263 [ObservableProperty]
264 private CameraLocation cameraLocation = CameraLocation.Rear;
265
269 public bool HasAllowedSchemas => this.navigationArgs?.AllowedSchemas is not null && this.navigationArgs.AllowedSchemas.Length > 0;
270
274 [ObservableProperty]
275 [NotifyPropertyChangedFor(nameof(MultipleIcons))]
276 [NotifyPropertyChangedFor(nameof(SingleIcon))]
277 private ObservableCollection<UriSchemaIcon> icons = [];
278
282 public bool MultipleIcons => this.Icons.Count > 1;
283
287 public bool SingleIcon => this.Icons.Count == 1;
288
293 {
294 get
295 {
296 if (string.IsNullOrEmpty(this.ScannedText))
297 return Colors.White;
298
299 string Url = this.ScannedText.Trim();
300
301 if ((this.countDownTimer?.IsRunning ?? false) &&
302 (this.navigationArgs?.AllowedSchemas is not null) &&
303 this.navigationArgs.AllowedSchemas.Length > 0)
304 {
305 return this.IsPermittedUrl(Url) ? Colors.White : Colors.LightSalmon;
306 }
307
308 return Colors.White;
309 }
310 }
311
312 private bool IsPermittedUrl(string Url)
313 {
314 if (this.navigationArgs?.AllowedSchemas is not null &&
315 System.Uri.TryCreate(Url, UriKind.Absolute, out Uri? Uri))
316 {
317 foreach (string Schema in this.navigationArgs.AllowedSchemas)
318 {
319 if (string.Equals(Uri.Scheme, Schema, StringComparison.OrdinalIgnoreCase))
320 return true;
321 }
322 }
323
324 return false;
325 }
326
331 {
332 get
333 {
334 if (this.navigationArgs?.QrTitle is not null)
335 return ServiceRef.Localizer[this.navigationArgs.QrTitle];
336
337 return string.Empty;
338 }
339 }
340
341 private bool CanOpen(string? Text)
342 {
343 string? Url = Text?.Trim();
344 if (string.IsNullOrEmpty(Url))
345 return false;
346
347 if (this.navigationArgs?.AllowedSchemas is not null && this.navigationArgs.AllowedSchemas.Length > 0)
348 return this.IsPermittedUrl(Url);
349 else
350 return Url.Length > 0;
351 }
352
356 public bool CanOpenScanned => this.CanOpen(this.ScannedText);
357
361 public bool CanOpenManual => this.CanOpen(this.ManualText);
362
363 #endregion
364
365 [RelayCommand(CanExecute = nameof(CanOpenManual))]
366 private Task OpenUrl()
367 {
368 return this.TrySetResultAndClosePage(this.ManualText!.Trim());
369 }
370
372 public override Task GoBack()
373 {
374 return this.TrySetResultAndClosePage(null);
375 }
376 }
377}
Represents an instance of the Neuro-Access app.
Definition: App.xaml.cs:125
static new? App Current
Gets the current application instance.
Definition: App.xaml.cs:169
const string TagSign
TAG Signature (Quick-Login) URI Scheme (tagsign)
Definition: Constants.cs:168
const string IotSc
The IoT Smart Contract URI Scheme (iotsc)
Definition: Constants.cs:163
const string Onboarding
Onboarding URI Scheme (obinfo)
Definition: Constants.cs:183
const string NeuroFeature
eDaler URI Scheme (edaler)
Definition: Constants.cs:178
const string Aes256
AES-256-encrypted data.
Definition: Constants.cs:193
const string IotDisco
The IoT Discovery URI Scheme (iotdisco)
Definition: Constants.cs:158
const string Xmpp
XMPP URI Scheme (xmpp)
Definition: Constants.cs:188
const string IotId
The IoT ID URI Scheme (iotid)
Definition: Constants.cs:153
const string EDaler
eDaler URI Scheme (edaler)
Definition: Constants.cs:173
A set of never changing property constants and helpful values.
Definition: Constants.cs:24
Base class that references services in the app.
Definition: ServiceRef.cs:43
static ILogService LogService
Log service.
Definition: ServiceRef.cs:214
static INavigationService NavigationService
The navigation service for navigating between pages.
Definition: ServiceRef.cs:178
static IReportingStringLocalizer Localizer
Localization service
Definition: ServiceRef.cs:370
Static class containing SVG Paths for symbols used in the app.
Definition: Geometries.cs:11
static readonly Color UserColor
Default user icon color
Definition: Geometries.cs:347
static readonly Color EDalerColor
Default eDaler icon color
Definition: Geometries.cs:378
static readonly Geometry UserIconPath
User symbol for QR codes
Definition: Geometries.cs:352
static readonly Geometry OnboardingIconPath
Onboarding symbol for QR codes
Definition: Geometries.cs:367
static readonly Color OnboardingColor
Default onboarding icon color
Definition: Geometries.cs:362
static readonly Color TokenColor
Default token icon color
Definition: Geometries.cs:456
static readonly Geometry SignatureIconPath
Signature symbol for QR codes
Definition: Geometries.cs:412
static readonly Geometry EDalerIconPath
eDaler symbol for QR codes
Definition: Geometries.cs:383
static readonly Color Aes256Color
Default encrypted icon color
Definition: Geometries.cs:392
static readonly Color ContractColor
Default contract icon color
Definition: Geometries.cs:421
static readonly Geometry Aes256IconPath
Encrypted symbol for QR codes
Definition: Geometries.cs:397
static readonly Geometry ThingsIconPath
Things symbol for QR codes
Definition: Geometries.cs:443
static readonly Geometry ContractIconPath
Contract symbol for QR codes
Definition: Geometries.cs:426
static readonly Geometry TokenIconPath
Token symbol for QR codes
Definition: Geometries.cs:461
static readonly Color ThingsColor
Default things icon color
Definition: Geometries.cs:438
static readonly Color SignatureColor
Default signature icon color
Definition: Geometries.cs:407
A base class for all view models, inheriting from the BindableObject. NOTE: using this class requir...
The view model to bind to when scanning a QR code.
ScanQrCodeViewModel()
The view model to bind to when scanning a QR code.
override Task GoBack()
Method called when user wants to navigate to the previous screen.
bool CanOpenManual
If the manual code can be opened
override async Task OnDisposeAsync()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
string LocalizedQrPageTitle
The localized page title text to display.
bool HasAllowedSchemas
If scanning of codes is restricted to a set of allowed schemas.
Color IconBackgroundColor
Background color of displayed icon.
override async Task OnInitializeAsync()
Method called when view is initialized for the first time. Use this method to implement registration ...
bool CanOpenScanned
If the scanned code can be opened
bool MultipleIcons
If the view shows more than one icon.
class UriSchemaIcon(Geometry Geometry, Color ForegroundColor, ScanQrCodeViewModel ParentViewModel)
Represents an icon for an URI schema.