77using MahApps . Metro . Controls . Dialogs ;
88using NETworkManager . ViewModels . Dialogs ;
99using NETworkManager . Views . Dialogs ;
10- using System . Diagnostics ;
11- using NETworkManager . Helpers ;
1210using System ;
1311using System . Windows . Threading ;
1412
@@ -18,6 +16,7 @@ public class CredentialsViewModel : ViewModelBase
1816 {
1917 #region Variables
2018 private IDialogCoordinator dialogCoordinator ;
19+ DispatcherTimer _dispatcherTimer ;
2120
2221 private bool _credentialsFileExists ;
2322 public bool CredentialsFileExists
@@ -47,6 +46,35 @@ public bool CredentialsLoaded
4746 }
4847 }
4948
49+ // Indicates that the UI is locked
50+ private bool _locked = true ;
51+ public bool Locked
52+ {
53+ get { return _locked ; }
54+ set
55+ {
56+ if ( value == _locked )
57+ return ;
58+
59+ _locked = value ;
60+ OnPropertyChanged ( ) ;
61+ }
62+ }
63+
64+ private TimeSpan _timeRemaining ;
65+ public TimeSpan TimeRemaining
66+ {
67+ get { return _timeRemaining ; }
68+ set
69+ {
70+ if ( value == _timeRemaining )
71+ return ;
72+
73+ _timeRemaining = value ;
74+ OnPropertyChanged ( ) ;
75+ }
76+ }
77+
5078 ICollectionView _credentials ;
5179 public ICollectionView Credentials
5280 {
@@ -106,12 +134,31 @@ public CredentialsViewModel(IDialogCoordinator instance)
106134 } ;
107135
108136 CheckCredentialsLoaded ( ) ;
137+
138+ // Set up dispatcher timer
139+ _dispatcherTimer = new DispatcherTimer ( ) ;
140+ _dispatcherTimer . Tick += _dispatcherTimer_Tick ;
141+ _dispatcherTimer . Interval = new TimeSpan ( 0 , 0 , 1 ) ;
109142 }
110143
111- private void CheckCredentialsLoaded ( )
144+ private void _dispatcherTimer_Tick ( object sender , EventArgs e )
112145 {
113- CredentialsFileExists = File . Exists ( CredentialManager . GetCredentialsFilePath ( ) ) ;
114- CredentialsLoaded = CredentialManager . Loaded ;
146+ if ( TimeRemaining == TimeSpan . Zero )
147+ TimerLockUIStop ( ) ;
148+
149+ TimeRemaining = TimeRemaining . Add ( TimeSpan . FromSeconds ( - 1 ) ) ;
150+ }
151+
152+ public void CheckCredentialsLoaded ( )
153+ {
154+ if ( ! CredentialsLoaded )
155+ {
156+ // If file exists, view to decrypt the file is shown
157+ CredentialsFileExists = File . Exists ( CredentialManager . GetCredentialsFilePath ( ) ) ;
158+
159+ // IF credentials are loaded, view to add/edit/remove is shown
160+ CredentialsLoaded = CredentialManager . Loaded ;
161+ }
115162 }
116163 #endregion
117164
@@ -137,6 +184,8 @@ private async void SetMasterPasswordAction()
137184 CredentialManager . CredentialsChanged = true ; // Save to file when application is closed
138185
139186 CheckCredentialsLoaded ( ) ;
187+
188+ TimerLockUIStart ( ) ;
140189 } , instance =>
141190 {
142191 dialogCoordinator . HideMetroDialogAsync ( this , customDialog ) ;
@@ -170,6 +219,8 @@ private async void DecryptAndLoadAction()
170219 await dialogCoordinator . ShowMessageAsync ( this , Application . Current . Resources [ "String_Header_WrongPassword" ] as string , Application . Current . Resources [ "String_WrongPasswordDecryptionFailed" ] as string , MessageDialogStyle . Affirmative , AppearanceManager . MetroDialog ) ;
171220
172221 CheckCredentialsLoaded ( ) ;
222+
223+ TimerLockUIStart ( ) ;
173224 } , instance =>
174225 {
175226 dialogCoordinator . HideMetroDialogAsync ( this , customDialog ) ;
@@ -190,58 +241,28 @@ public ICommand ChangeMasterPasswordCommand
190241
191242 private async void ChangeMasterPasswordAction ( )
192243 {
193- CustomDialog customDialogMasterPassword = new CustomDialog ( )
244+ CustomDialog customDialogSetMasterPassword = new CustomDialog ( )
194245 {
195- Title = Application . Current . Resources [ "String_Header_MasterPassword " ] as string
246+ Title = Application . Current . Resources [ "String_Header_SetMasterPassword " ] as string
196247 } ;
197248
198- CredentialsMasterPasswordViewModel credentialsMasterPasswordViewModel = new CredentialsMasterPasswordViewModel ( async instance =>
249+ CredentialsSetMasterPasswordViewModel credentialsSetMasterPasswordViewModel = new CredentialsSetMasterPasswordViewModel ( instance =>
199250 {
200- await dialogCoordinator . HideMetroDialogAsync ( this , customDialogMasterPassword ) ;
251+ dialogCoordinator . HideMetroDialogAsync ( this , customDialogSetMasterPassword ) ;
201252
202- if ( CredentialManager . VerifyMasterPasword ( instance . Password ) )
203- {
204- CustomDialog customDialogSetMasterPassword = new CustomDialog ( )
205- {
206- Title = Application . Current . Resources [ "String_Header_SetMasterPassword" ] as string
207- } ;
208-
209- CredentialsSetMasterPasswordViewModel credentialsSetMasterPasswordViewModel = new CredentialsSetMasterPasswordViewModel ( instance2 =>
210- {
211- dialogCoordinator . HideMetroDialogAsync ( this , customDialogSetMasterPassword ) ;
212-
213- // Set the new master password
214- CredentialManager . SetMasterPassword ( instance2 . Password ) ;
215-
216- // Save to file
217- CredentialManager . Save ( ) ;
218- } , instance2 =>
219- {
220- dialogCoordinator . HideMetroDialogAsync ( this , customDialogSetMasterPassword ) ;
221- } ) ;
222-
223- customDialogSetMasterPassword . Content = new CredentialsSetMasterPasswordDialog
224- {
225- DataContext = credentialsSetMasterPasswordViewModel
226- } ;
227-
228- await dialogCoordinator . ShowMetroDialogAsync ( this , customDialogSetMasterPassword ) ;
229- }
230- else
231- {
232- await dialogCoordinator . ShowMessageAsync ( this , Application . Current . Resources [ "String_Header_WrongPassword" ] as string , Application . Current . Resources [ "String_WrongPassword" ] as string , MessageDialogStyle . Affirmative , AppearanceManager . MetroDialog ) ;
233- }
253+ // Set the new master password
254+ CredentialManager . SetMasterPassword ( instance . Password ) ;
234255 } , instance =>
235256 {
236- dialogCoordinator . HideMetroDialogAsync ( this , customDialogMasterPassword ) ;
257+ dialogCoordinator . HideMetroDialogAsync ( this , customDialogSetMasterPassword ) ;
237258 } ) ;
238259
239- customDialogMasterPassword . Content = new CredentialsMasterPasswordDialog
260+ customDialogSetMasterPassword . Content = new CredentialsSetMasterPasswordDialog
240261 {
241- DataContext = credentialsMasterPasswordViewModel
262+ DataContext = credentialsSetMasterPasswordViewModel
242263 } ;
243264
244- await dialogCoordinator . ShowMetroDialogAsync ( this , customDialogMasterPassword ) ;
265+ await dialogCoordinator . ShowMetroDialogAsync ( this , customDialogSetMasterPassword ) ;
245266 }
246267
247268 public ICommand AddCommand
@@ -269,6 +290,8 @@ private async void AddAction()
269290 } ;
270291
271292 CredentialManager . AddCredential ( credentialInfo ) ;
293+
294+ TimerLockUIStart ( ) ; // Reset timer
272295 } , instance =>
273296 {
274297 dialogCoordinator . HideMetroDialogAsync ( this , customDialog ) ;
@@ -310,7 +333,7 @@ private async void EditAction()
310333
311334 CredentialManager . AddCredential ( credentialInfo ) ;
312335
313- Debug . WriteLine ( SecureStringHelper . ConvertToString ( instance . Password ) ) ;
336+ TimerLockUIStart ( ) ; // Reset timer
314337 } , instance =>
315338 {
316339 dialogCoordinator . HideMetroDialogAsync ( this , customDialog ) ;
@@ -341,6 +364,8 @@ private async void DeleteAction()
341364 dialogCoordinator . HideMetroDialogAsync ( this , customDialog ) ;
342365
343366 CredentialManager . RemoveCredential ( SelectedCredential ) ;
367+
368+ TimerLockUIStart ( ) ; // Reset timer
344369 } , instance =>
345370 {
346371 dialogCoordinator . HideMetroDialogAsync ( this , customDialog ) ;
@@ -353,6 +378,64 @@ private async void DeleteAction()
353378
354379 await dialogCoordinator . ShowMetroDialogAsync ( this , customDialog ) ;
355380 }
381+
382+ public ICommand LockUnlockCommand
383+ {
384+ get { return new RelayCommand ( p => LockUnlockAction ( ) ) ; }
385+ }
386+
387+ private async void LockUnlockAction ( )
388+ {
389+ if ( Locked )
390+ {
391+ CustomDialog customDialogMasterPassword = new CustomDialog ( )
392+ {
393+ Title = Application . Current . Resources [ "String_Header_MasterPassword" ] as string
394+ } ;
395+
396+ CredentialsMasterPasswordViewModel credentialsMasterPasswordViewModel = new CredentialsMasterPasswordViewModel ( async instance =>
397+ {
398+ await dialogCoordinator . HideMetroDialogAsync ( this , customDialogMasterPassword ) ;
399+
400+ if ( CredentialManager . VerifyMasterPasword ( instance . Password ) )
401+ TimerLockUIStart ( ) ;
402+ else
403+ await dialogCoordinator . ShowMessageAsync ( this , Application . Current . Resources [ "String_Header_WrongPassword" ] as string , Application . Current . Resources [ "String_WrongPassword" ] as string , MessageDialogStyle . Affirmative , AppearanceManager . MetroDialog ) ;
404+ } , instance =>
405+ {
406+ dialogCoordinator . HideMetroDialogAsync ( this , customDialogMasterPassword ) ;
407+ } ) ;
408+
409+ customDialogMasterPassword . Content = new CredentialsMasterPasswordDialog
410+ {
411+ DataContext = credentialsMasterPasswordViewModel
412+ } ;
413+
414+ await dialogCoordinator . ShowMetroDialogAsync ( this , customDialogMasterPassword ) ;
415+ }
416+ else
417+ {
418+ TimerLockUIStop ( ) ;
419+ }
420+ }
421+ #endregion
422+
423+ #region Methods
424+ private void TimerLockUIStart ( )
425+ {
426+ Locked = false ;
427+
428+ TimeRemaining = TimeSpan . FromSeconds ( 10 ) ;
429+
430+ _dispatcherTimer . Start ( ) ;
431+ }
432+
433+ private void TimerLockUIStop ( )
434+ {
435+ _dispatcherTimer . Stop ( ) ;
436+
437+ Locked = true ;
438+ }
356439 #endregion
357440 }
358441}
0 commit comments