mirror of
https://github.com/bitwarden/mobile
synced 2026-01-02 08:33:17 +00:00
[EC-1002] [BEEEP] Add ability to change language in app (#2299)
* EC-1002 BEEEP Added ability to change language in app * EC-1002 fix format * EC-1002 Renamed IPreferencesStorageService to ISynchronousStorageService * EC-1002 Moved get/set Locale to the StateService and added the StorageMediatorService to a new way to interact with the storage. Later the StateService will only interact with this mediator instead of directly with the storage services, with this we have more control inside the mediator and we can have both sync and async methods to interact with storages handled by the mediator
This commit is contained in:
committed by
GitHub
parent
5164762f2e
commit
470e08f165
@@ -9,6 +9,7 @@ namespace Bit.Core.Abstractions
|
||||
CultureInfo Culture { get; set; }
|
||||
StringComparer StringComparer { get; }
|
||||
Dictionary<string, string> LocaleNames { get; }
|
||||
void SetCurrentCulture(CultureInfo culture);
|
||||
string T(string id, string p1 = null, string p2 = null, string p3 = null);
|
||||
string Translate(string id, string p1 = null, string p2 = null, string p3 = null);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Domain;
|
||||
using Bit.Core.Models.Response;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Core.Abstractions
|
||||
{
|
||||
@@ -165,5 +166,7 @@ namespace Bit.Core.Abstractions
|
||||
Task<string> GetAvatarColorAsync(string userId = null);
|
||||
Task<string> GetPreLoginEmailAsync();
|
||||
Task SetPreLoginEmailAsync(string value);
|
||||
string GetLocale();
|
||||
void SetLocale(string locale);
|
||||
}
|
||||
}
|
||||
|
||||
16
src/Core/Abstractions/IStorageMediatorService.cs
Normal file
16
src/Core/Abstractions/IStorageMediatorService.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Core.Abstractions
|
||||
{
|
||||
public interface IStorageMediatorService
|
||||
{
|
||||
T Get<T>(string key);
|
||||
void Save<T>(string key, T obj);
|
||||
void Remove(string key);
|
||||
|
||||
Task<T> GetAsync<T>(string key, StorageMediatorOptions options = default);
|
||||
Task SaveAsync<T>(string key, T obj, StorageMediatorOptions options = default);
|
||||
Task RemoveAsync(string key, StorageMediatorOptions options = default);
|
||||
}
|
||||
}
|
||||
9
src/Core/Abstractions/ISynchronousStorageService.cs
Normal file
9
src/Core/Abstractions/ISynchronousStorageService.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Bit.Core.Abstractions
|
||||
{
|
||||
public interface ISynchronousStorageService
|
||||
{
|
||||
T Get<T>(string key);
|
||||
void Save<T>(string key, T obj);
|
||||
void Remove(string key);
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@
|
||||
/// which is used to handle Apple Watch state logic
|
||||
/// </summary>
|
||||
public const string LastUserShouldConnectToWatchKey = "lastUserShouldConnectToWatch";
|
||||
public const string AppLocaleKey = "appLocale";
|
||||
public const int SelectFileRequestCode = 42;
|
||||
public const int SelectFilePermissionRequestCode = 43;
|
||||
public const int SaveFileRequestCode = 44;
|
||||
|
||||
@@ -14,8 +14,11 @@ namespace Bit.Core.Services
|
||||
{
|
||||
public class StateService : IStateService
|
||||
{
|
||||
// TODO: Refactor this removing all storage services and use the IStorageMediatorService instead
|
||||
|
||||
private readonly IStorageService _storageService;
|
||||
private readonly IStorageService _secureStorageService;
|
||||
private readonly IStorageMediatorService _storageMediatorService;
|
||||
private readonly IMessagingService _messagingService;
|
||||
|
||||
private State _state;
|
||||
@@ -25,10 +28,12 @@ namespace Bit.Core.Services
|
||||
|
||||
public StateService(IStorageService storageService,
|
||||
IStorageService secureStorageService,
|
||||
IStorageMediatorService storageMediatorService,
|
||||
IMessagingService messagingService)
|
||||
{
|
||||
_storageService = storageService;
|
||||
_secureStorageService = secureStorageService;
|
||||
_storageMediatorService = storageMediatorService;
|
||||
_messagingService = messagingService;
|
||||
}
|
||||
|
||||
@@ -891,6 +896,16 @@ namespace Bit.Core.Services
|
||||
await SetValueAsync(Constants.AutoDarkThemeKey, value, await GetDefaultStorageOptionsAsync());
|
||||
}
|
||||
|
||||
public string GetLocale()
|
||||
{
|
||||
return _storageMediatorService.Get<string>(Constants.AppLocaleKey);
|
||||
}
|
||||
|
||||
public void SetLocale(string locale)
|
||||
{
|
||||
_storageMediatorService.Save(Constants.AppLocaleKey, locale);
|
||||
}
|
||||
|
||||
public async Task<bool?> GetAddSitePromptShownAsync(string userId = null)
|
||||
{
|
||||
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
|
||||
@@ -1222,11 +1237,13 @@ namespace Bit.Core.Services
|
||||
|
||||
// Helpers
|
||||
|
||||
[Obsolete("Use IStorageMediatorService instead")]
|
||||
private async Task<T> GetValueAsync<T>(string key, StorageOptions options)
|
||||
{
|
||||
return await GetStorageService(options).GetAsync<T>(key);
|
||||
}
|
||||
|
||||
[Obsolete("Use IStorageMediatorService instead")]
|
||||
private async Task SetValueAsync<T>(string key, T value, StorageOptions options)
|
||||
{
|
||||
if (value == null)
|
||||
@@ -1237,11 +1254,17 @@ namespace Bit.Core.Services
|
||||
await GetStorageService(options).SaveAsync(key, value);
|
||||
}
|
||||
|
||||
[Obsolete("Use IStorageMediatorService instead")]
|
||||
private IStorageService GetStorageService(StorageOptions options)
|
||||
{
|
||||
return options.UseSecureStorage.GetValueOrDefault(false) ? _secureStorageService : _storageService;
|
||||
}
|
||||
|
||||
private async Task<string> ComposeKeyAsync(Func<string, string> userDependantKey, string userId = null)
|
||||
{
|
||||
return userDependantKey(userId ?? await GetActiveUserIdAsync());
|
||||
}
|
||||
|
||||
private async Task<Account> GetAccountAsync(StorageOptions options)
|
||||
{
|
||||
await CheckStateAsync();
|
||||
@@ -1437,6 +1460,12 @@ namespace Bit.Core.Services
|
||||
return requestedOptions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default options for storage.
|
||||
/// If it's only used for composing the constant key with the user id
|
||||
/// then use <see cref="ComposeKeyAsync(Func{string, string}, string)"/> instead
|
||||
/// which saves time if the user id is already known
|
||||
/// </summary>
|
||||
private async Task<StorageOptions> GetDefaultStorageOptionsAsync()
|
||||
{
|
||||
return new StorageOptions()
|
||||
|
||||
8
src/Core/Services/StorageMediatorOptions.cs
Normal file
8
src/Core/Services/StorageMediatorOptions.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public struct StorageMediatorOptions
|
||||
{
|
||||
public bool UseSecureStorage { get; set; }
|
||||
public bool AllowSaveNull { get; set; }
|
||||
}
|
||||
}
|
||||
62
src/Core/Services/StorageMediatorService.cs
Normal file
62
src/Core/Services/StorageMediatorService.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Abstractions;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
public class StorageMediatorService : IStorageMediatorService
|
||||
{
|
||||
private readonly IStorageService _storageService;
|
||||
private readonly IStorageService _secureStorageService;
|
||||
private readonly ISynchronousStorageService _synchronousStorageService;
|
||||
|
||||
public StorageMediatorService(IStorageService storageService,
|
||||
IStorageService secureStorageService,
|
||||
ISynchronousStorageService synchronousStorageService)
|
||||
{
|
||||
_storageService = storageService;
|
||||
_secureStorageService = secureStorageService;
|
||||
_synchronousStorageService = synchronousStorageService;
|
||||
}
|
||||
|
||||
public T Get<T>(string key)
|
||||
{
|
||||
return _synchronousStorageService.Get<T>(key);
|
||||
}
|
||||
|
||||
public void Save<T>(string key, T obj)
|
||||
{
|
||||
_synchronousStorageService.Save<T>(key, obj);
|
||||
}
|
||||
|
||||
public void Remove(string key)
|
||||
{
|
||||
_synchronousStorageService.Remove(key);
|
||||
}
|
||||
|
||||
public Task<T> GetAsync<T>(string key, StorageMediatorOptions options = default)
|
||||
{
|
||||
return GetAsyncStorage(options).GetAsync<T>(key);
|
||||
}
|
||||
|
||||
public async Task SaveAsync<T>(string key, T obj, StorageMediatorOptions options = default)
|
||||
{
|
||||
if (obj is null && !options.AllowSaveNull)
|
||||
{
|
||||
await GetAsyncStorage(options).RemoveAsync(key);
|
||||
return;
|
||||
}
|
||||
|
||||
await GetAsyncStorage(options).SaveAsync<T>(key, obj);
|
||||
}
|
||||
|
||||
public Task RemoveAsync(string key, StorageMediatorOptions options = default)
|
||||
{
|
||||
return GetAsyncStorage(options).RemoveAsync(key);
|
||||
}
|
||||
|
||||
IStorageService GetAsyncStorage(StorageMediatorOptions options)
|
||||
{
|
||||
return options.UseSecureStorage ? _secureStorageService : _storageService;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user