mirror of
https://github.com/bitwarden/mobile
synced 2026-01-17 07:53:33 +00:00
Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys
This commit is contained in:
20
.github/workflows/build.yml
vendored
20
.github/workflows/build.yml
vendored
@@ -153,17 +153,17 @@ jobs:
|
|||||||
# - name: Verify Format
|
# - name: Verify Format
|
||||||
# run: dotnet tool run dotnet-format --check
|
# run: dotnet tool run dotnet-format --check
|
||||||
|
|
||||||
# - name: Run Core tests
|
- name: Run Core tests
|
||||||
# run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx"
|
run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" /p:CustomConstants=UT
|
||||||
|
|
||||||
#- name: Report test results
|
- name: Report test results
|
||||||
# uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226 # v1.6.0
|
uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226 # v1.6.0
|
||||||
# if: always()
|
if: always()
|
||||||
# with:
|
with:
|
||||||
# name: Test Results
|
name: Test Results
|
||||||
# path: "**/test-results.trx"
|
path: "**/test-results.trx"
|
||||||
# reporter: dotnet-trx
|
reporter: dotnet-trx
|
||||||
# fail-on-error: true
|
fail-on-error: true
|
||||||
|
|
||||||
- name: Build Play Store publisher
|
- name: Build Play Store publisher
|
||||||
if: ${{ matrix.variant == 'prod' }}
|
if: ${{ matrix.variant == 'prod' }}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<MauiVersion>8.0.4-nightly.*</MauiVersion>
|
<MauiVersion>8.0.4-nightly.*</MauiVersion>
|
||||||
|
<!-- Uncomment this when Unit Testing-->
|
||||||
|
<!-- <CustomConstants>UT</CustomConstants> -->
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -46,6 +46,7 @@ namespace Bit.App
|
|||||||
// This queue keeps those actions so that when the app has resumed they can still be executed.
|
// This queue keeps those actions so that when the app has resumed they can still be executed.
|
||||||
// Links: https://github.com/dotnet/maui/issues/11501 and https://bitwarden.atlassian.net/wiki/spaces/NMME/pages/664862722/MainPage+Assignments+not+working+on+Android+on+Background+or+App+resume
|
// Links: https://github.com/dotnet/maui/issues/11501 and https://bitwarden.atlassian.net/wiki/spaces/NMME/pages/664862722/MainPage+Assignments+not+working+on+Android+on+Background+or+App+resume
|
||||||
private readonly Queue<Action> _onResumeActions = new Queue<Action>();
|
private readonly Queue<Action> _onResumeActions = new Queue<Action>();
|
||||||
|
private bool _hasNavigatedToAutofillWindow;
|
||||||
|
|
||||||
#if ANDROID
|
#if ANDROID
|
||||||
|
|
||||||
@@ -89,7 +90,7 @@ namespace Bit.App
|
|||||||
{
|
{
|
||||||
Options = appOptions ?? new AppOptions();
|
Options = appOptions ?? new AppOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Window CreateWindow(IActivationState activationState)
|
protected override Window CreateWindow(IActivationState activationState)
|
||||||
{
|
{
|
||||||
//When executing from AutofillExternalActivity we don't have "Options" so we need to filter "manually"
|
//When executing from AutofillExternalActivity we don't have "Options" so we need to filter "manually"
|
||||||
@@ -106,18 +107,37 @@ namespace Bit.App
|
|||||||
if (Options != null && (Options.FromAutofillFramework || Options.Uri != null || Options.OtpData != null || Options.CreateSend != null))
|
if (Options != null && (Options.FromAutofillFramework || Options.Uri != null || Options.OtpData != null || Options.CreateSend != null))
|
||||||
{
|
{
|
||||||
_isResumed = true; //Specifically for the Autofill scenario we need to manually set the _isResumed here
|
_isResumed = true; //Specifically for the Autofill scenario we need to manually set the _isResumed here
|
||||||
|
_hasNavigatedToAutofillWindow = true;
|
||||||
return new AutoFillWindow(new NavigationPage(new AndroidNavigationRedirectPage()));
|
return new AutoFillWindow(new NavigationPage(new AndroidNavigationRedirectPage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var homePage = new HomePage(Options);
|
||||||
|
// WORKAROUND: If the user autofills with Accessibility Services enabled and goes back to the application then there is currently an issue
|
||||||
|
// where this method is called again
|
||||||
|
// thus it goes through here and the user goes to HomePage as we see here.
|
||||||
|
// So to solve this, the next flag check has been added which then turns on a flag on the home page
|
||||||
|
// that will trigger a navigation on the accounts manager when it loads; workarounding this behavior and navigating the user
|
||||||
|
// to the proper page depending on its state.
|
||||||
|
// WARNING: this doens't navigate the user to where they were but it acts as if the user had changed their account.
|
||||||
|
if(_hasNavigatedToAutofillWindow)
|
||||||
|
{
|
||||||
|
homePage.PerformNavigationOnAccountChangedOnLoad = true;
|
||||||
|
// this is needed because when coming back from AutofillWindow OnResume won't be called and we need this flag
|
||||||
|
// so that void Navigate(NavigationTarget navTarget, INavigationParams navParams) doesn't enqueue the navigation
|
||||||
|
// and it performs it directly.
|
||||||
|
_isResumed = true;
|
||||||
|
_hasNavigatedToAutofillWindow = false;
|
||||||
|
}
|
||||||
|
|
||||||
//If we have an existing MainAppWindow we can use that one
|
//If we have an existing MainAppWindow we can use that one
|
||||||
var mainAppWindow = Windows.OfType<MainAppWindow>().FirstOrDefault();
|
var mainAppWindow = Windows.OfType<MainAppWindow>().FirstOrDefault();
|
||||||
if (mainAppWindow != null)
|
if (mainAppWindow != null)
|
||||||
{
|
{
|
||||||
mainAppWindow.PendingPage = new NavigationPage(new HomePage(Options));
|
mainAppWindow.PendingPage = new NavigationPage(homePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create new main window
|
//Create new main window
|
||||||
return new MainAppWindow(new NavigationPage(new HomePage(Options)));
|
return new MainAppWindow(new NavigationPage(homePage));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly
|
//iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly
|
||||||
|
|||||||
@@ -13,6 +13,11 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string WEB_VAULT_SETTINGS_FORMAT = "{0}/#/settings";
|
public const string WEB_VAULT_SETTINGS_FORMAT = "{0}/#/settings";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Link to go to individual vault import page. Requires to pass vault URL as parameter.
|
||||||
|
/// </summary>
|
||||||
|
public const string WEB_VAULT_TOOLS_IMPORT_FORMAT = "{0}/#/tools/import";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// General website, not in the full format of a URL given that this is used as parameter of string resources to be shown to the user.
|
/// General website, not in the full format of a URL given that this is used as parameter of string resources to be shown to the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
x:DataType="pages:HomeViewModel"
|
x:DataType="pages:HomeViewModel"
|
||||||
HideSoftInputOnTapped="True"
|
HideSoftInputOnTapped="True"
|
||||||
x:Name="_page"
|
x:Name="_page"
|
||||||
|
Loaded="HomePage_Loaded"
|
||||||
Title="{Binding PageTitle}">
|
Title="{Binding PageTitle}">
|
||||||
<ContentPage.BindingContext>
|
<ContentPage.BindingContext>
|
||||||
<pages:HomeViewModel />
|
<pages:HomeViewModel />
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using Bit.App.Models;
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Models;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Microsoft.Maui.Platform;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
@@ -44,6 +44,21 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool PerformNavigationOnAccountChangedOnLoad { get; internal set; }
|
||||||
|
|
||||||
|
void HomePage_Loaded(System.Object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
#if ANDROID
|
||||||
|
// WORKAROUND: This is needed to fix the navigation when coming back from autofill when Accessibility Services is enabled
|
||||||
|
// See App.xaml.cs -> CreateWindow(...) for more info.
|
||||||
|
if (PerformNavigationOnAccountChangedOnLoad && ServiceContainer.TryResolve<IAccountsManager>(out var accountsManager))
|
||||||
|
{
|
||||||
|
PerformNavigationOnAccountChangedOnLoad = false;
|
||||||
|
accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public async Task DismissRegisterPageAndLogInAsync(string email)
|
public async Task DismissRegisterPageAndLogInAsync(string email)
|
||||||
{
|
{
|
||||||
await Navigation.PopModalAsync();
|
await Navigation.PopModalAsync();
|
||||||
|
|||||||
@@ -41,11 +41,11 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
private async Task GoToImportItemsAsync()
|
private async Task GoToImportItemsAsync()
|
||||||
{
|
{
|
||||||
var webVaultUrl = _environmentService.GetWebVaultUrl();
|
var toolsImportUrl = string.Format(ExternalLinksConstants.WEB_VAULT_TOOLS_IMPORT_FORMAT, _environmentService.GetWebVaultUrl());
|
||||||
var body = string.Format(AppResources.YouCanImportDataToYourVaultOnX, webVaultUrl);
|
var body = string.Format(AppResources.YouCanImportDataToYourVaultOnX, toolsImportUrl);
|
||||||
if (await _platformUtilsService.ShowDialogAsync(body, AppResources.ContinueToWebApp, AppResources.Continue, AppResources.Cancel))
|
if (await _platformUtilsService.ShowDialogAsync(body, AppResources.ContinueToWebApp, AppResources.Continue, AppResources.Cancel))
|
||||||
{
|
{
|
||||||
_platformUtilsService.LaunchUri(webVaultUrl);
|
_platformUtilsService.LaunchUri(toolsImportUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,6 @@
|
|||||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<RootNamespace>Bit.Core.Test</RootNamespace>
|
<RootNamespace>Bit.Core.Test</RootNamespace>
|
||||||
|
|
||||||
<!-- Uncomment this to load the referenced projects into this one. I've added the restriction so it doesn't mess up with the restore.
|
|
||||||
This is useful when working with the test project.
|
|
||||||
<CustomConstants>UT</CustomConstants>
|
|
||||||
-->
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
|||||||
Reference in New Issue
Block a user