1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-11 05:43:30 +00:00

Merge branch 'main' into feature/maui-migration-passkeys

This commit is contained in:
Federico Maccaroni
2024-03-22 15:42:51 -03:00
5 changed files with 166 additions and 134 deletions

View File

@@ -73,17 +73,28 @@ namespace Bit.Droid.Services
public bool LaunchApp(string appName) public bool LaunchApp(string appName)
{ {
if ((int)Build.VERSION.SdkInt < 33) try
{
if ((int)Build.VERSION.SdkInt < 33)
{
// API 33 required to avoid using wildcard app visibility or dangerous permissions
// https://developer.android.com/reference/android/content/pm/PackageManager#getLaunchIntentSenderForPackage(java.lang.String)
return false;
}
var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
appName = appName.Replace("androidapp://", string.Empty);
var launchIntentSender = activity?.PackageManager?.GetLaunchIntentSenderForPackage(appName);
launchIntentSender?.SendIntent(activity, Result.Ok, null, null, null);
return launchIntentSender != null;
}
catch (IntentSender.SendIntentException)
{
return false;
}
catch (Android.Util.AndroidException)
{ {
// API 33 required to avoid using wildcard app visibility or dangerous permissions
// https://developer.android.com/reference/android/content/pm/PackageManager#getLaunchIntentSenderForPackage(java.lang.String)
return false; return false;
} }
var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
appName = appName.Replace("androidapp://", string.Empty);
var launchIntentSender = activity?.PackageManager?.GetLaunchIntentSenderForPackage(appName);
launchIntentSender?.SendIntent(activity, Result.Ok, null, null, null);
return launchIntentSender != null;
} }
public async Task ShowLoadingAsync(string text) public async Task ShowLoadingAsync(string text)

View File

@@ -9,6 +9,7 @@ using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models.Data; using Bit.Core.Models.Data;
using Bit.Core.Models.Domain;
using Bit.Core.Models.Response; using Bit.Core.Models.Response;
using Bit.Core.Pages; using Bit.Core.Pages;
using Bit.Core.Services; using Bit.Core.Services;
@@ -167,132 +168,153 @@ namespace Bit.App
_accountsManager.Init(() => Options, this); _accountsManager.Init(() => Options, this);
Bootstrap(); _broadcasterService.Subscribe(nameof(App), BroadcastServiceMessageCallbackAsync);
_broadcasterService.Subscribe(nameof(App), async (message) =>
{
try
{
if (message.Command == "showDialog")
{
var details = message.Data as DialogDetails;
var confirmed = true;
var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ?
AppResources.Ok : details.ConfirmText;
await MainThread.InvokeOnMainThreadAsync(async () =>
{
if (!string.IsNullOrWhiteSpace(details.CancelText))
{
confirmed = await MainPage.DisplayAlert(details.Title, details.Text, confirmText,
details.CancelText);
}
else
{
await MainPage.DisplayAlert(details.Title, details.Text, confirmText);
}
_messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
});
}
#if IOS
else if (message.Command == AppHelpers.RESUMED_MESSAGE_COMMAND)
{
ResumedAsync().FireAndForget();
}
else if (message.Command == "slept")
{
await SleptAsync();
}
#endif
else if (message.Command == "migrated")
{
await Task.Delay(1000);
await _accountsManager.NavigateOnAccountChangeAsync();
}
else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE ||
message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
{
if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
{
Options.OtpData = new OtpData((string)message.Data);
}
await MainThread.InvokeOnMainThreadAsync(async () => Bootstrap();
}
private async void BroadcastServiceMessageCallbackAsync(Message message)
{
try
{
ArgumentNullException.ThrowIfNull(message);
if (message.Command == "showDialog")
{
var details = message.Data as DialogDetails;
ArgumentNullException.ThrowIfNull(details);
ArgumentNullException.ThrowIfNull(MainPage);
var confirmed = true;
var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ?
AppResources.Ok : details.ConfirmText;
await MainThread.InvokeOnMainThreadAsync(ShowDialogAction);
async Task ShowDialogAction()
{
if (!string.IsNullOrWhiteSpace(details.CancelText))
{ {
if (MainPage is TabsPage tabsPage) confirmed = await MainPage.DisplayAlert(details.Title, details.Text, confirmText,
details.CancelText);
}
else
{
await MainPage.DisplayAlert(details.Title, details.Text, confirmText);
}
_messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
}
}
#if IOS
else if (message.Command == AppHelpers.RESUMED_MESSAGE_COMMAND)
{
ResumedAsync().FireAndForget();
}
else if (message.Command == "slept")
{
await SleptAsync();
}
#endif
else if (message.Command == "migrated")
{
await Task.Delay(1000);
await _accountsManager.NavigateOnAccountChangeAsync();
}
else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE ||
message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
{
if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
{
Options.OtpData = new OtpData((string)message.Data);
}
await MainThread.InvokeOnMainThreadAsync(ExecuteNavigationAction);
async Task ExecuteNavigationAction()
{
if (MainPage is TabsPage tabsPage)
{
ArgumentNullException.ThrowIfNull(tabsPage.Navigation);
ArgumentNullException.ThrowIfNull(tabsPage.Navigation.ModalStack);
while (tabsPage.Navigation.ModalStack.Count > 0)
{ {
while (tabsPage.Navigation.ModalStack.Count > 0) await tabsPage.Navigation.PopModalAsync(false);
{ }
await tabsPage.Navigation.PopModalAsync(false); if (message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE)
} {
if (message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE) MainPage = new NavigationPage(new CipherSelectionPage(Options));
{ }
MainPage = new NavigationPage(new CipherSelectionPage(Options)); else if (message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE)
} {
else if (message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE) Options.MyVaultTile = false;
{ tabsPage.ResetToVaultPage();
Options.MyVaultTile = false; }
tabsPage.ResetToVaultPage(); else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE)
} {
else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE) Options.GeneratorTile = false;
{ tabsPage.ResetToGeneratorPage();
Options.GeneratorTile = false; }
tabsPage.ResetToGeneratorPage(); else if (message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE)
} {
else if (message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE) tabsPage.ResetToSendPage();
{ }
tabsPage.ResetToSendPage(); else if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
} {
else if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE) tabsPage.ResetToVaultPage();
{ ArgumentNullException.ThrowIfNull(tabsPage.Navigation);
tabsPage.ResetToVaultPage(); await tabsPage.Navigation.PushModalAsync(new NavigationPage(new CipherSelectionPage(Options)));
await tabsPage.Navigation.PushModalAsync(new NavigationPage(new CipherSelectionPage(Options)));
}
} }
});
}
else if (message.Command == "convertAccountToKeyConnector")
{
await MainThread.InvokeOnMainThreadAsync(async () =>
{
await MainPage.Navigation.PushModalAsync(
new NavigationPage(new RemoveMasterPasswordPage()));
});
}
else if (message.Command == Constants.ForceUpdatePassword)
{
await MainThread.InvokeOnMainThreadAsync(async () =>
{
await MainPage.Navigation.PushModalAsync(
new NavigationPage(new UpdateTempPasswordPage()));
});
}
else if (message.Command == Constants.ForceSetPassword)
{
await MainThread.InvokeOnMainThreadAsync(() => MainPage.Navigation.PushModalAsync(
new NavigationPage(new SetPasswordPage(orgIdentifier: (string)message.Data))));
}
else if (message.Command == "syncCompleted")
{
await _configService.GetAsync(true);
}
else if (message.Command == Constants.PasswordlessLoginRequestKey
|| message.Command == "unlocked"
|| message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED)
{
lock (_processingLoginRequestLock)
{
// lock doesn't allow for async execution
CheckPasswordlessLoginRequestsAsync().Wait();
} }
} }
} }
catch (Exception ex) else if (message.Command == "convertAccountToKeyConnector")
{ {
LoggerHelper.LogEvenIfCantBeResolved(ex); ArgumentNullException.ThrowIfNull(MainPage);
await MainThread.InvokeOnMainThreadAsync(NavigateToRemoveMasterPasswordPageAction);
async Task NavigateToRemoveMasterPasswordPageAction()
{
await MainPage.Navigation.PushModalAsync(
new NavigationPage(new RemoveMasterPasswordPage()));
}
} }
}); else if (message.Command == Constants.ForceUpdatePassword)
{
ArgumentNullException.ThrowIfNull(MainPage);
await MainThread.InvokeOnMainThreadAsync(NavigateToUpdateTempPasswordPageAction);
async Task NavigateToUpdateTempPasswordPageAction()
{
await MainPage.Navigation.PushModalAsync(
new NavigationPage(new UpdateTempPasswordPage()));
}
}
else if (message.Command == Constants.ForceSetPassword)
{
ArgumentNullException.ThrowIfNull(MainPage);
await MainThread.InvokeOnMainThreadAsync(NavigateToSetPasswordPageAction);
void NavigateToSetPasswordPageAction()
{
MainPage.Navigation.PushModalAsync(
new NavigationPage(new SetPasswordPage(orgIdentifier: (string)message.Data)));
}
}
else if (message.Command == "syncCompleted")
{
await _configService.GetAsync(true);
}
else if (message.Command == Constants.PasswordlessLoginRequestKey
|| message.Command == "unlocked"
|| message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED)
{
lock (_processingLoginRequestLock)
{
// lock doesn't allow for async execution
CheckPasswordlessLoginRequestsAsync().Wait();
}
}
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
private async Task CheckPasswordlessLoginRequestsAsync() private async Task CheckPasswordlessLoginRequestsAsync()
@@ -307,7 +329,6 @@ namespace Bit.App
{ {
return; return;
} }
var notification = await _stateService.GetPasswordlessLoginNotificationAsync(); var notification = await _stateService.GetPasswordlessLoginNotificationAsync();
if (notification == null) if (notification == null)
{ {

View File

@@ -2878,12 +2878,12 @@
<value>أعدنّ ميزة إلغاء القُفْل لتغيير إجراء مهلة المخزن الخاص بك.</value> <value>أعدنّ ميزة إلغاء القُفْل لتغيير إجراء مهلة المخزن الخاص بك.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve"> <data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value> <value>تسجيل الدخول لـ Duo من خطوتين مطلوب لحسابك. </value>
</data> </data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve"> <data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value> <value>اتبع الخطوات من Duo لإنهاء تسجيل الدخول.</value>
</data> </data>
<data name="LaunchDuo" xml:space="preserve"> <data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value> <value>تشغيل Duo</value>
</data> </data>
</root> </root>

View File

@@ -371,7 +371,7 @@
<comment>Label for a username.</comment> <comment>Label for a username.</comment>
</data> </data>
<data name="ValidationFieldRequired" xml:space="preserve"> <data name="ValidationFieldRequired" xml:space="preserve">
<value>Het {0}-veld is vereist.</value> <value>Vul het veld {0} in.</value>
<comment>Validation message for when a form field is left blank and is required to be entered.</comment> <comment>Validation message for when a form field is left blank and is required to be entered.</comment>
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
@@ -996,7 +996,7 @@ Het scannen gebeurt automatisch.</value>
<value>Beveiligingscode kopiëren</value> <value>Beveiligingscode kopiëren</value>
</data> </data>
<data name="Number" xml:space="preserve"> <data name="Number" xml:space="preserve">
<value>Kaartummer</value> <value>Kaartnummer</value>
</data> </data>
<data name="SecurityCode" xml:space="preserve"> <data name="SecurityCode" xml:space="preserve">
<value>Beveiligingscode</value> <value>Beveiligingscode</value>

View File

@@ -2879,12 +2879,12 @@ Vill du byta till detta konto?</value>
<value>Ställ in ett upplåsningsalternativ för att ändra vad som händer när tidsgränsen uppnås.</value> <value>Ställ in ett upplåsningsalternativ för att ändra vad som händer när tidsgränsen uppnås.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve"> <data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value> <value>Duo tvåstegsverifiering krävs för ditt konto. </value>
</data> </data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve"> <data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value> <value>Följ stegen från Duo för att slutföra inloggningen.</value>
</data> </data>
<data name="LaunchDuo" xml:space="preserve"> <data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value> <value>Starta Duo</value>
</data> </data>
</root> </root>