LoadDb and SaveDb respect the SyncInBackground preference
This commit is contained in:
		| @@ -141,5 +141,8 @@ namespace keepass2android | |||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | 		bool SyncInBackgroundPreference { get; set; } | ||||||
|  |  | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -186,8 +186,11 @@ namespace keepass2android.Io | |||||||
|                 Kp2aLog.Log("couldn't open from remote " + ioc.Path); |                 Kp2aLog.Log("couldn't open from remote " + ioc.Path); | ||||||
| #endif | #endif | ||||||
| 				Kp2aLog.Log(ex.ToString()); | 				Kp2aLog.Log(ex.ToString()); | ||||||
|  |                 if (TriggerWarningWhenFallingBackToCache) | ||||||
|  |                 { | ||||||
|                     _cacheSupervisor.CouldntOpenFromRemote(ioc, ex); |                     _cacheSupervisor.CouldntOpenFromRemote(ioc, ex); | ||||||
|  |                 } | ||||||
|  | 				 | ||||||
| 				return File.OpenRead(cachedFilePath); | 				return File.OpenRead(cachedFilePath); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -327,7 +330,10 @@ namespace keepass2android.Io | |||||||
| 				Kp2aLog.Log("couldn't save to remote " + ioc.Path); | 				Kp2aLog.Log("couldn't save to remote " + ioc.Path); | ||||||
| 				Kp2aLog.Log(e.ToString()); | 				Kp2aLog.Log(e.ToString()); | ||||||
| 				//notify the supervisor so it might display a warning or schedule a retry | 				//notify the supervisor so it might display a warning or schedule a retry | ||||||
| 				_cacheSupervisor.CouldntSaveToRemote(ioc, e); |                 if (TriggerWarningWhenFallingBackToCache) | ||||||
|  |                 { | ||||||
|  |                     _cacheSupervisor.CouldntSaveToRemote(ioc, e); } | ||||||
|  | 				 | ||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -632,6 +638,8 @@ namespace keepass2android.Io | |||||||
| 			set { _cachedStorage.IsOffline = value; } | 			set { _cachedStorage.IsOffline = value; } | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  |         public bool TriggerWarningWhenFallingBackToCache { get; set; } | ||||||
|  |  | ||||||
|         public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode, |         public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode, | ||||||
| 			string[] permissions, Permission[] grantResults) | 			string[] permissions, Permission[] grantResults) | ||||||
| 		{ | 		{ | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ namespace keepass2android.Io | |||||||
| 	public interface IOfflineSwitchable | 	public interface IOfflineSwitchable | ||||||
| 	{ | 	{ | ||||||
| 		bool IsOffline { get; set; } | 		bool IsOffline { get; set; } | ||||||
|  |         bool TriggerWarningWhenFallingBackToCache { get; set; } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| /// <summary> | /// <summary> | ||||||
| @@ -21,6 +22,7 @@ namespace keepass2android.Io | |||||||
| 	{ | 	{ | ||||||
| 		private readonly IFileStorage _baseStorage; | 		private readonly IFileStorage _baseStorage; | ||||||
| 		public bool IsOffline { get; set; } | 		public bool IsOffline { get; set; } | ||||||
|  |         public bool TriggerWarningWhenFallingBackToCache { get; set; } | ||||||
|  |  | ||||||
|         public OfflineSwitchableFileStorage(IFileStorage baseStorage) |         public OfflineSwitchableFileStorage(IFileStorage baseStorage) | ||||||
| 		{ | 		{ | ||||||
|   | |||||||
| @@ -194,9 +194,9 @@ namespace keepass2android | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
| 		public void SaveData()  { | 		public void SaveData(IFileStorage fileStorage)  { | ||||||
|              |              | ||||||
| 			using (IWriteTransaction trans = _app.GetFileStorage(Ioc).OpenWriteTransaction(Ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions))) | 			using (IWriteTransaction trans = fileStorage.OpenWriteTransaction(Ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions))) | ||||||
| 			{ | 			{ | ||||||
| 				DatabaseFormat.Save(KpDatabase, trans.OpenFile()); | 				DatabaseFormat.Save(KpDatabase, trans.OpenFile()); | ||||||
| 				 | 				 | ||||||
|   | |||||||
| @@ -21,8 +21,10 @@ using System.Linq; | |||||||
| using System.Threading; | using System.Threading; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Android.App; | using Android.App; | ||||||
|  | using Android.OS; | ||||||
| using KeePass.Util; | using KeePass.Util; | ||||||
| using keepass2android.database.edit; | using keepass2android.database.edit; | ||||||
|  | using keepass2android.Io; | ||||||
| using KeePassLib; | using KeePassLib; | ||||||
| using KeePassLib.Keys; | using KeePassLib.Keys; | ||||||
| using KeePassLib.Serialization; | using KeePassLib.Serialization; | ||||||
| @@ -47,8 +49,6 @@ namespace keepass2android | |||||||
| 			_keyfileOrProvider = keyfileOrProvider; | 			_keyfileOrProvider = keyfileOrProvider; | ||||||
| 		    _updateLastUsageTimestamp = updateLastUsageTimestamp; | 		    _updateLastUsageTimestamp = updateLastUsageTimestamp; | ||||||
| 		    _makeCurrent = makeCurrent; | 		    _makeCurrent = makeCurrent; | ||||||
|  |  | ||||||
|  |  | ||||||
| 		    _rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile);  | 		    _rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile);  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -65,16 +65,31 @@ namespace keepass2android | |||||||
|                     //make sure the file data is stored in the recent files list even if loading fails |                     //make sure the file data is stored in the recent files list even if loading fails | ||||||
| 				    SaveFileData(_ioc, _keyfileOrProvider); | 				    SaveFileData(_ioc, _keyfileOrProvider); | ||||||
|  |  | ||||||
|  |                     var fileStorage = _app.GetFileStorage(_ioc); | ||||||
|  |  | ||||||
|  |                     bool requiresSubsequentSync = false; | ||||||
|  |  | ||||||
|  |  | ||||||
|                     StatusLogger.UpdateMessage(UiStringKey.loading_database); |                     StatusLogger.UpdateMessage(UiStringKey.loading_database); | ||||||
| 					//get the stream data into a single stream variable (databaseStream) regardless whether its preloaded or not: | 					//get the stream data into a single stream variable (databaseStream) regardless whether its preloaded or not: | ||||||
| 					MemoryStream preloadedMemoryStream = _databaseData == null ? null : _databaseData.Result; | 					MemoryStream preloadedMemoryStream = _databaseData == null ? null : _databaseData.Result; | ||||||
| 					MemoryStream databaseStream; | 					MemoryStream databaseStream; | ||||||
|                     if (preloadedMemoryStream != null) |                     if (preloadedMemoryStream != null) | ||||||
|  |                     { | ||||||
|  | 						//note: if the stream has been loaded already, we don't need to trigger another sync later on | ||||||
|                         databaseStream = preloadedMemoryStream; |                         databaseStream = preloadedMemoryStream; | ||||||
|  |                     } | ||||||
|                     else |                     else | ||||||
| 					{ | 					{ | ||||||
| 						using (Stream s = _app.GetFileStorage(_ioc).OpenFileForRead(_ioc)) |                         if (_app.SyncInBackgroundPreference && fileStorage is IOfflineSwitchable offlineSwitchable) | ||||||
|  |                         { | ||||||
|  |                             offlineSwitchable.IsOffline = true; | ||||||
|  | 							//no warning. We'll trigger a sync later. | ||||||
|  |                             offlineSwitchable.TriggerWarningWhenFallingBackToCache = false; | ||||||
|  |                             requiresSubsequentSync = true; | ||||||
|  |  | ||||||
|  |                         } | ||||||
|  |                         using (Stream s = fileStorage.OpenFileForRead(_ioc)) | ||||||
| 						{ | 						{ | ||||||
| 							databaseStream = new MemoryStream(); | 							databaseStream = new MemoryStream(); | ||||||
| 							s.CopyTo(databaseStream); | 							s.CopyTo(databaseStream); | ||||||
| @@ -83,8 +98,8 @@ namespace keepass2android | |||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					//ok, try to load the database. Let's start with Kdbx format and retry later if that is the wrong guess: | 					//ok, try to load the database. Let's start with Kdbx format and retry later if that is the wrong guess: | ||||||
| 					_format = new KdbxDatabaseFormat(KdbxDatabaseFormat.GetFormatToUse(_app.GetFileStorage(_ioc).GetFileExtension(_ioc))); | 					_format = new KdbxDatabaseFormat(KdbxDatabaseFormat.GetFormatToUse(fileStorage.GetFileExtension(_ioc))); | ||||||
| 					TryLoad(databaseStream); | 					TryLoad(databaseStream, requiresSubsequentSync); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -136,7 +151,7 @@ namespace keepass2android | |||||||
| 		/// </summary> | 		/// </summary> | ||||||
| 		public Exception Exception { get; set; } | 		public Exception Exception { get; set; } | ||||||
|  |  | ||||||
| 		Database TryLoad(MemoryStream databaseStream) | 		Database TryLoad(MemoryStream databaseStream, bool requiresSubsequentSync) | ||||||
| 		{ | 		{ | ||||||
| 			//create a copy of the stream so we can try again if we get an exception which indicates we should change parameters | 			//create a copy of the stream so we can try again if we get an exception which indicates we should change parameters | ||||||
| 			//This is not optimal in terms of (short-time) memory usage but is hard to avoid because the Keepass library closes streams also in case of errors. | 			//This is not optimal in terms of (short-time) memory usage but is hard to avoid because the Keepass library closes streams also in case of errors. | ||||||
| @@ -152,13 +167,26 @@ namespace keepass2android | |||||||
|                 Database newDb = _app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format, _makeCurrent); |                 Database newDb = _app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format, _makeCurrent); | ||||||
|                 Kp2aLog.Log("LoadDB OK"); |                 Kp2aLog.Log("LoadDB OK"); | ||||||
|                  |                  | ||||||
|  |                 if (requiresSubsequentSync) | ||||||
|  |                 { | ||||||
|  |                     var syncTask = new SynchronizeCachedDatabase(ActiveActivity, _app, new ActionOnOperationFinished(ActiveActivity, | ||||||
|  |                         (success, message, activeActivity) => | ||||||
|  |                         { | ||||||
|  |                             if (!String.IsNullOrEmpty(message)) | ||||||
|  |                                 _app.ShowMessage(activeActivity, message, success ? MessageSeverity.Info : MessageSeverity.Error); | ||||||
|  |                            | ||||||
|  |                         })   | ||||||
|  |                     ); | ||||||
|  |                     BackgroundOperationRunner.Instance.Run(ActiveActivity, _app, syncTask); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 Finish(true, _format.SuccessMessage); |                 Finish(true, _format.SuccessMessage); | ||||||
| 			    return newDb; | 			    return newDb; | ||||||
| 			} | 			} | ||||||
| 			catch (OldFormatException) | 			catch (OldFormatException) | ||||||
| 			{ | 			{ | ||||||
| 				_format = new KdbDatabaseFormat(_app); | 				_format = new KdbDatabaseFormat(_app); | ||||||
| 				return TryLoad(databaseStream); | 				return TryLoad(databaseStream, requiresSubsequentSync); | ||||||
| 			} | 			} | ||||||
| 			catch (InvalidCompositeKeyException) | 			catch (InvalidCompositeKeyException) | ||||||
| 			{ | 			{ | ||||||
| @@ -170,7 +198,7 @@ namespace keepass2android | |||||||
| 					//retry without password: | 					//retry without password: | ||||||
| 					_compositeKey.RemoveUserKey(passwordKey); | 					_compositeKey.RemoveUserKey(passwordKey); | ||||||
| 					//retry: | 					//retry: | ||||||
| 					return TryLoad(databaseStream); | 					return TryLoad(databaseStream, requiresSubsequentSync); | ||||||
| 				} | 				} | ||||||
| 				else throw; | 				else throw; | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -38,6 +38,7 @@ namespace keepass2android | |||||||
| 		private readonly IKp2aApp _app; | 		private readonly IKp2aApp _app; | ||||||
| 	    private readonly Database _db; | 	    private readonly Database _db; | ||||||
| 	    private readonly bool _dontSave; | 	    private readonly bool _dontSave; | ||||||
|  | 		private bool requiresSubsequentSync = false; //if true, we need to sync the file after saving. | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| 		/// stream for reading the data from the original file. If this is set to a non-null value, we know we need to sync | 		/// stream for reading the data from the original file. If this is set to a non-null value, we know we need to sync | ||||||
| @@ -108,13 +109,23 @@ namespace keepass2android | |||||||
| 					IOConnectionInfo ioc = _db.Ioc; | 					IOConnectionInfo ioc = _db.Ioc; | ||||||
| 					IFileStorage fileStorage = _app.GetFileStorage(ioc); | 					IFileStorage fileStorage = _app.GetFileStorage(ioc); | ||||||
|  |  | ||||||
|  |                     if (_app.SyncInBackgroundPreference && fileStorage is IOfflineSwitchable offlineSwitchable) | ||||||
|  |                     { | ||||||
|  |                         offlineSwitchable.IsOffline = true; | ||||||
|  |                         //no warning. We'll trigger a sync later. | ||||||
|  |                         offlineSwitchable.TriggerWarningWhenFallingBackToCache = false; | ||||||
|  |                         requiresSubsequentSync = true; | ||||||
|  |  | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |  | ||||||
|                     if (_streamForOrigFile == null) |                     if (_streamForOrigFile == null) | ||||||
| 					{ | 					{ | ||||||
| 						if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave)) | 						if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave)) | ||||||
| 							|| (_db.KpDatabase.HashOfFileOnDisk == null)) //first time saving | 							|| (_db.KpDatabase.HashOfFileOnDisk == null)) //first time saving | ||||||
| 						{ | 						{ | ||||||
| 							PerformSaveWithoutCheck(fileStorage, ioc); | 							PerformSaveWithoutCheck(fileStorage, ioc); | ||||||
| 							Finish(true); | 							FinishWithSuccess(); | ||||||
| 							return; | 							return; | ||||||
| 						}	 | 						}	 | ||||||
| 					} | 					} | ||||||
| @@ -123,9 +134,9 @@ namespace keepass2android | |||||||
|                     bool hasStreamForOrigFile = (_streamForOrigFile != null); |                     bool hasStreamForOrigFile = (_streamForOrigFile != null); | ||||||
|                     bool hasChangeFast = hasStreamForOrigFile || |                     bool hasChangeFast = hasStreamForOrigFile || | ||||||
|                                          fileStorage.CheckForFileChangeFast(ioc, _db.LastFileVersion);  //first try to use the fast change detection; |                                          fileStorage.CheckForFileChangeFast(ioc, _db.LastFileVersion);  //first try to use the fast change detection; | ||||||
|                     bool hasHashChanged = hasChangeFast || |                     bool hasHashChanged = !requiresSubsequentSync && (hasChangeFast || | ||||||
|                                           (FileHashChanged(ioc, _db.KpDatabase.HashOfFileOnDisk) == |                                           (FileHashChanged(ioc, _db.KpDatabase.HashOfFileOnDisk) == | ||||||
|                                            FileHashChange.Changed); //if that fails, hash the file and compare: |                                            FileHashChange.Changed)); //if that fails, hash the file and compare: | ||||||
|  |  | ||||||
| 					if (hasHashChanged) | 					if (hasHashChanged) | ||||||
| 					{ | 					{ | ||||||
| @@ -158,7 +169,7 @@ namespace keepass2android | |||||||
| 								RunInWorkerThread(() => | 								RunInWorkerThread(() => | ||||||
| 									{ | 									{ | ||||||
| 										PerformSaveWithoutCheck(fileStorage, ioc); | 										PerformSaveWithoutCheck(fileStorage, ioc); | ||||||
| 										Finish(true); | 										FinishWithSuccess(); | ||||||
| 									}); | 									}); | ||||||
| 							}, | 							}, | ||||||
| 							//cancel  | 							//cancel  | ||||||
| @@ -174,7 +185,7 @@ namespace keepass2android | |||||||
| 					else | 					else | ||||||
| 					{ | 					{ | ||||||
| 						PerformSaveWithoutCheck(fileStorage, ioc); | 						PerformSaveWithoutCheck(fileStorage, ioc); | ||||||
| 						Finish(true); | 						FinishWithSuccess(); | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 				} | 				} | ||||||
| @@ -194,11 +205,28 @@ namespace keepass2android | |||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				Finish(true); | 				FinishWithSuccess(); | ||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  |         private void FinishWithSuccess() | ||||||
|  |         { | ||||||
|  |             if (requiresSubsequentSync) | ||||||
|  |             { | ||||||
|  |                 var syncTask = new SynchronizeCachedDatabase(ActiveActivity, _app, new ActionOnOperationFinished(ActiveActivity, | ||||||
|  |                     (success, message, activeActivity) => | ||||||
|  |                     { | ||||||
|  |                         if (!System.String.IsNullOrEmpty(message)) | ||||||
|  |                             _app.ShowMessage(activeActivity, message, success ? MessageSeverity.Info : MessageSeverity.Error); | ||||||
|  |  | ||||||
|  |                     }) | ||||||
|  |                 ); | ||||||
|  |                 BackgroundOperationRunner.Instance.Run(ActiveActivity, _app, syncTask); | ||||||
|  |             } | ||||||
|  |             Finish(true); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         private void MergeAndFinish(IFileStorage fileStorage, IOConnectionInfo ioc) |         private void MergeAndFinish(IFileStorage fileStorage, IOConnectionInfo ioc) | ||||||
|         { |         { | ||||||
|             //note: when synced, the file might be downloaded once again from the server. Caching the data |             //note: when synced, the file might be downloaded once again from the server. Caching the data | ||||||
| @@ -207,7 +235,7 @@ namespace keepass2android | |||||||
|             MergeIn(fileStorage, ioc); |             MergeIn(fileStorage, ioc); | ||||||
|             PerformSaveWithoutCheck(fileStorage, ioc); |             PerformSaveWithoutCheck(fileStorage, ioc); | ||||||
|             _db.UpdateGlobals(); |             _db.UpdateGlobals(); | ||||||
|             Finish(true); |             FinishWithSuccess(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void RunInWorkerThread(Action runHandler) |         private void RunInWorkerThread(Action runHandler) | ||||||
| @@ -282,7 +310,7 @@ namespace keepass2android | |||||||
| 		private void PerformSaveWithoutCheck(IFileStorage fileStorage, IOConnectionInfo ioc) | 		private void PerformSaveWithoutCheck(IFileStorage fileStorage, IOConnectionInfo ioc) | ||||||
| 		{ | 		{ | ||||||
| 			StatusLogger.UpdateSubMessage(""); | 			StatusLogger.UpdateSubMessage(""); | ||||||
| 			_db.SaveData(); | 			_db.SaveData(fileStorage); | ||||||
| 			_db.LastFileVersion = fileStorage.GetCurrentFileVersionFast(ioc); | 			_db.LastFileVersion = fileStorage.GetCurrentFileVersionFast(ioc); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1753,17 +1753,10 @@ namespace keepass2android | |||||||
|                 cbOfflineMode.Checked = |                 cbOfflineMode.Checked = | ||||||
|                     App.Kp2a |                     App.Kp2a | ||||||
|                         .OfflineModePreference; //this won't overwrite new user settings because every change is directly saved in settings |                         .OfflineModePreference; //this won't overwrite new user settings because every change is directly saved in settings | ||||||
|             LinearLayout offlineModeContainer = FindViewById<LinearLayout>(Resource.Id.work_offline_container); |  | ||||||
|             var cachingFileStorage = App.Kp2a.GetFileStorage(_ioConnection) as CachingFileStorage; |             CheckBox cbSyncInBackground = (CheckBox)FindViewById(Resource.Id.sync_in_background)!; | ||||||
|             if ((cachingFileStorage != null) && cachingFileStorage.IsCached(_ioConnection)) |             cbSyncInBackground.Checked = App.Kp2a.SyncInBackgroundPreference; | ||||||
|             { |             UpdateInternalCacheCheckboxesVisibility(); | ||||||
|                 offlineModeContainer.Visibility = ViewStates.Visible; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 offlineModeContainer.Visibility = ViewStates.Gone; |  | ||||||
|                 App.Kp2a.OfflineMode = false; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -2040,6 +2033,34 @@ namespace keepass2android | |||||||
| 				App.Kp2a.OfflineModePreference = App.Kp2a.OfflineMode = args.IsChecked; | 				App.Kp2a.OfflineModePreference = App.Kp2a.OfflineMode = args.IsChecked; | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
|  |             CheckBox cbSyncInBackground = (CheckBox)FindViewById(Resource.Id.sync_in_background); | ||||||
|  |             cbSyncInBackground.CheckedChange += (sender, args) => | ||||||
|  |             { | ||||||
|  |                 App.Kp2a.SyncInBackgroundPreference = args.IsChecked; | ||||||
|  |                 UpdateInternalCacheCheckboxesVisibility(); | ||||||
|  |  | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void UpdateInternalCacheCheckboxesVisibility() | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |             LinearLayout syncInBackgroundContainer = FindViewById<LinearLayout>(Resource.Id.sync_in_background_container)!; | ||||||
|  |  | ||||||
|  |             LinearLayout offlineModeContainer = FindViewById<LinearLayout>(Resource.Id.work_offline_container)!; | ||||||
|  |             var cachingFileStorage = App.Kp2a.GetFileStorage(_ioConnection) as CachingFileStorage; | ||||||
|  |             if ((cachingFileStorage != null) && cachingFileStorage.IsCached(_ioConnection)) | ||||||
|  |             { | ||||||
|  |                 syncInBackgroundContainer.Visibility = ViewStates.Visible; | ||||||
|  |                 offlineModeContainer.Visibility = | ||||||
|  |                     App.Kp2a.SyncInBackgroundPreference ? ViewStates.Gone : ViewStates.Visible; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 syncInBackgroundContainer.Visibility = offlineModeContainer.Visibility = ViewStates.Gone; | ||||||
|  |                 App.Kp2a.OfflineMode = false; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private String LoadKeyProviderStringForIoc(String filename) { |         private String LoadKeyProviderStringForIoc(String filename) { | ||||||
|   | |||||||
| @@ -318,6 +318,30 @@ | |||||||
| 			          android:text="@string/help_quickunlock" | 			          android:text="@string/help_quickunlock" | ||||||
|                       /> |                       /> | ||||||
|                   </LinearLayout> |                   </LinearLayout> | ||||||
|  |  | ||||||
|  |                      | ||||||
|  |                     <LinearLayout | ||||||
|  |                       android:id="@+id/sync_in_background_container" | ||||||
|  |                       android:orientation="horizontal" | ||||||
|  |                       android:layout_width="fill_parent" | ||||||
|  |                       android:layout_height="wrap_content"> | ||||||
|  |  | ||||||
|  |                       <CheckBox | ||||||
|  |                         android:id="@+id/sync_in_background" | ||||||
|  |                         android:layout_width="wrap_content" | ||||||
|  |                         android:layout_height="wrap_content" | ||||||
|  |                         android:layout_marginTop="16dp" | ||||||
|  |                         android:text="@string/SyncOfflineCacheInBackground_title" /> | ||||||
|  |                       <keepass2android.views.Kp2aShortHelpView | ||||||
|  |                         android:layout_width="wrap_content" | ||||||
|  |                         android:layout_height="wrap_content" | ||||||
|  |                         style="@style/TextAppearance_Help_Dense" | ||||||
|  |                        | ||||||
|  |                         app:help_text="@string/SyncOfflineCacheInBackground_summary" | ||||||
|  |                         app:title_text="@string/SyncOfflineCacheInBackground_title" | ||||||
|  |                         android:text="@string/SyncOfflineCacheInBackground_summary" | ||||||
|  |                       /> | ||||||
|  |                     </LinearLayout> | ||||||
|                   <LinearLayout |                   <LinearLayout | ||||||
|                     android:id="@+id/work_offline_container" |                     android:id="@+id/work_offline_container" | ||||||
|                     android:orientation="horizontal" |                     android:orientation="horizontal" | ||||||
| @@ -328,7 +352,7 @@ | |||||||
|                           android:id="@+id/work_offline" |                           android:id="@+id/work_offline" | ||||||
|                           android:layout_width="wrap_content" |                           android:layout_width="wrap_content" | ||||||
|                           android:layout_height="wrap_content" |                           android:layout_height="wrap_content" | ||||||
|                           android:layout_marginTop="16dp" |                            | ||||||
|                           android:text="@string/UseOfflineMode" /> |                           android:text="@string/UseOfflineMode" /> | ||||||
|                     <keepass2android.views.Kp2aShortHelpView |                     <keepass2android.views.Kp2aShortHelpView | ||||||
|                       android:layout_width="wrap_content" |                       android:layout_width="wrap_content" | ||||||
| @@ -341,6 +365,7 @@ | |||||||
|                       /> |                       /> | ||||||
|                   </LinearLayout> |                   </LinearLayout> | ||||||
|  |  | ||||||
|  |  | ||||||
|                   <Button |                   <Button | ||||||
|                         android:id="@+id/kill_app" |                         android:id="@+id/kill_app" | ||||||
|                         android:text="@string/kill_app_label" |                         android:text="@string/kill_app_label" | ||||||
|   | |||||||
| @@ -55,13 +55,17 @@ namespace keepass2android | |||||||
|             var filestorage = App.Kp2a.GetFileStorage(App.Kp2a.CurrentDb.Ioc); |             var filestorage = App.Kp2a.GetFileStorage(App.Kp2a.CurrentDb.Ioc); | ||||||
|             OperationWithFinishHandler task; |             OperationWithFinishHandler task; | ||||||
|             OnOperationFinishedHandler onOperationFinishedHandler = new ActionOnOperationFinished(_activity, (success, message, activity) => |             OnOperationFinishedHandler onOperationFinishedHandler = new ActionOnOperationFinished(_activity, (success, message, activity) => | ||||||
|  |             { | ||||||
|  |                 new Handler(Looper.MainLooper).Post(() => | ||||||
|                 { |                 { | ||||||
|                     if (!String.IsNullOrEmpty(message)) |                     if (!String.IsNullOrEmpty(message)) | ||||||
|                         App.Kp2a.ShowMessage(activity, message, success ? MessageSeverity.Info : MessageSeverity.Error); |                         App.Kp2a.ShowMessage(activity, message, success ? MessageSeverity.Info : MessageSeverity.Error); | ||||||
|  |  | ||||||
|                     // Tell the adapter to refresh it's list |                     // Tell the adapter to refresh it's list | ||||||
|                     BaseAdapter adapter = (activity as GroupBaseActivity)?.ListAdapter; |                     BaseAdapter adapter = (activity as GroupBaseActivity)?.ListAdapter; | ||||||
|                 new Handler(Looper.MainLooper).Post(() => adapter?.NotifyDataSetChanged()); |  | ||||||
|  |                     adapter?.NotifyDataSetChanged(); | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|                 if (App.Kp2a.CurrentDb?.OtpAuxFileIoc != null) |                 if (App.Kp2a.CurrentDb?.OtpAuxFileIoc != null) | ||||||
|                 { |                 { | ||||||
|   | |||||||
| @@ -45,8 +45,11 @@ namespace keepass2android.Utils | |||||||
|     internal class ToastPresenter : IMessagePresenter |     internal class ToastPresenter : IMessagePresenter | ||||||
|     { |     { | ||||||
|         public void ShowMessage(Message message) |         public void ShowMessage(Message message) | ||||||
|  |         { | ||||||
|  |             new Handler(Looper.MainLooper).Post(() => | ||||||
|             { |             { | ||||||
|                 Toast.MakeText(App.Context, message.Text, ToastLength.Long).Show(); |                 Toast.MakeText(App.Context, message.Text, ToastLength.Long).Show(); | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public List<Message> PendingMessages => new(); |         public List<Message> PendingMessages => new(); | ||||||
|   | |||||||
| @@ -798,9 +798,14 @@ namespace keepass2android | |||||||
| 					fileStorage = innerFileStorage; | 					fileStorage = innerFileStorage; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if (fileStorage is IOfflineSwitchable) | 			if (fileStorage is IOfflineSwitchable switchable) | ||||||
| 			{ | 			{ | ||||||
| 				((IOfflineSwitchable)fileStorage).IsOffline = App.Kp2a.OfflineMode; | 				switchable.IsOffline = App.Kp2a.OfflineMode; | ||||||
|  |                 if (switchable.IsOffline) | ||||||
|  |                 { | ||||||
|  | 					//users of the file storage can set this to false, but the default is to show a warning: | ||||||
|  |                     switchable.TriggerWarningWhenFallingBackToCache = true; | ||||||
|  |                 } | ||||||
| 			} | 			} | ||||||
| 			return fileStorage; | 			return fileStorage; | ||||||
| 		} | 		} | ||||||
| @@ -1151,6 +1156,24 @@ namespace keepass2android | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         public bool SyncInBackgroundPreference | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 var prefs = PreferenceManager.GetDefaultSharedPreferences(LocaleManager.LocalizedAppContext); | ||||||
|  |                 return prefs.GetBoolean(LocaleManager.LocalizedAppContext.GetString(Resource.String.SyncOfflineCacheInBackground_key), false); | ||||||
|  |             } | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(LocaleManager.LocalizedAppContext); | ||||||
|  |                 ISharedPreferencesEditor edit = prefs.Edit(); | ||||||
|  |                 edit.PutBoolean(LocaleManager.LocalizedAppContext.GetString(Resource.String.SyncOfflineCacheInBackground_key), value); | ||||||
|  |                 edit.Commit(); | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// true if the app is used in offline mode |         /// true if the app is used in offline mode | ||||||
|         /// </summary> |         /// </summary> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll