1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-05 23:53:33 +00:00

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

# Conflicts:
#	.github/workflows/build.yml
#	nuget.config
#	src/App/App.csproj
#	src/App/Platforms/Android/AndroidManifest.xml
#	src/App/Platforms/iOS/AppDelegate.cs
#	src/Core/Core.csproj
#	src/Core/Pages/Settings/AutofillSettingsPageViewModel.android.cs
#	src/Core/Utilities/ThemeManager.cs
#	src/iOS.Autofill/CredentialProviderViewController.cs
#	src/iOS.Autofill/iOS.Autofill.csproj
This commit is contained in:
Federico Maccaroni
2024-02-14 14:19:51 -03:00
15 changed files with 123 additions and 69 deletions

4
.github/CODEOWNERS vendored
View File

@@ -11,11 +11,11 @@
.github/workflows @bitwarden/dept-devops .github/workflows @bitwarden/dept-devops
# DevOps for Version Bumping # DevOps for Version Bumping
src/Android/Properties/AndroidManifest.xml src/App/Platforms/Android/AndroidManifest.xml
src/iOS.Autofill/Info.plist src/iOS.Autofill/Info.plist
src/iOS.Extension/Info.plist src/iOS.Extension/Info.plist
src/iOS.ShareExtension/Info.plist src/iOS.ShareExtension/Info.plist
src/iOS/Info.plist src/App/Platforms/iOS/Info.plist
## Auth team files ## ## Auth team files ##

View File

@@ -226,7 +226,7 @@ jobs:
- name: Upload Prod .aab artifact - name: Upload Prod .aab artifact
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: com.x8bit.bitwarden.aab name: com.x8bit.bitwarden.aab
path: ./com.x8bit.bitwarden.aab path: ./com.x8bit.bitwarden.aab
@@ -234,7 +234,7 @@ jobs:
- name: Upload Prod .apk artifact - name: Upload Prod .apk artifact
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: com.x8bit.bitwarden.apk name: com.x8bit.bitwarden.apk
path: ./com.x8bit.bitwarden.apk path: ./com.x8bit.bitwarden.apk
@@ -242,7 +242,7 @@ jobs:
- name: Upload Other .apk artifact - name: Upload Other .apk artifact
if: ${{ matrix.variant != 'prod' }} if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: com.x8bit.bitwarden.${{ matrix.variant }}.apk name: com.x8bit.bitwarden.${{ matrix.variant }}.apk
path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk
@@ -262,7 +262,7 @@ jobs:
- name: Upload .apk sha file for prod - name: Upload .apk sha file for prod
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-android-apk-sha256.txt name: bw-android-apk-sha256.txt
path: ./bw-android-apk-sha256.txt path: ./bw-android-apk-sha256.txt
@@ -270,7 +270,7 @@ jobs:
- name: Upload .apk sha file for other - name: Upload .apk sha file for other
if: ${{ matrix.variant != 'prod' }} if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-android-${{ matrix.variant }}-apk-sha256.txt name: bw-android-${{ matrix.variant }}-apk-sha256.txt
path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt
@@ -422,7 +422,7 @@ jobs:
Copy-Item $signedApkPath $signedApkDestPath Copy-Item $signedApkPath $signedApkDestPath
- name: Upload F-Droid .apk artifact - name: Upload F-Droid .apk artifact
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
path: ./com.x8bit.bitwarden-fdroid.apk path: ./com.x8bit.bitwarden-fdroid.apk
@@ -434,7 +434,7 @@ jobs:
-t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt -t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt
- name: Upload F-Droid sha file - name: Upload F-Droid sha file
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-fdroid-apk-sha256.txt name: bw-fdroid-apk-sha256.txt
path: ./bw-fdroid-apk-sha256.txt path: ./bw-fdroid-apk-sha256.txt
@@ -529,6 +529,8 @@ jobs:
echo "##### Setting CFBundleVersion $BUILD_NUMBER" echo "##### Setting CFBundleVersion $BUILD_NUMBER"
echo "########################################" echo "########################################"
echo "### CFBundleVersion $BUILD_NUMBER" >> $GITHUB_STEP_SUMMARY
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./${{ env.ios_folder_path }}/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./${{ env.ios_folder_path }}/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist
@@ -662,7 +664,7 @@ jobs:
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
- name: Upload App Store .ipa & dSYMs artifacts - name: Upload App Store .ipa & dSYMs artifacts
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden iOS name: Bitwarden iOS
path: | path: |
@@ -671,7 +673,7 @@ jobs:
if-no-files-found: error if-no-files-found: error
- name: Upload .app file for Automation CI - name: Upload .app file for Automation CI
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: ${{ env.app_ci_output_filename }}.app.zip name: ${{ env.app_ci_output_filename }}.app.zip
path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip
@@ -768,7 +770,7 @@ jobs:
secrets: "crowdin-api-token" secrets: "crowdin-api-token"
- name: Upload Sources - name: Upload Sources
uses: crowdin/github-action@97bef4fd3f1b853eb105bc99b8d0d563760e024c # v1.17.0 uses: crowdin/github-action@198daeb2d30636c4608d6a6bb96c009dbefc02a2 # v1.18.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}

View File

@@ -30,7 +30,7 @@ jobs:
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Download translations - name: Download translations
uses: crowdin/github-action@97bef4fd3f1b853eb105bc99b8d0d563760e024c # v1.17.0 uses: crowdin/github-action@198daeb2d30636c4608d6a6bb96c009dbefc02a2 # v1.18.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}

View File

@@ -56,7 +56,7 @@ jobs:
- name: Create GitHub deployment - name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@@ -87,7 +87,7 @@ jobs:
- name: Create release - name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0 uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
with: with:
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab, artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk, ./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk,
@@ -147,7 +147,7 @@ jobs:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Set up Node - name: Set up Node
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
node-version: '16.x' node-version: '16.x'

View File

@@ -1,5 +1,5 @@
--- ---
name: Version Auto Bump name: Auto Bump Mobile Version
on: on:
push: push:
@@ -7,14 +7,12 @@ on:
- v** - v**
jobs: jobs:
setup: bump-version:
name: "Setup" name: Bump Mobile Version
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
outputs:
version_number: ${{ steps.version.outputs.new-version }}
steps: steps:
- name: Checkout Branch - name: Checkout Branch
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Calculate bumped version - name: Calculate bumped version
id: version id: version
@@ -29,12 +27,23 @@ jobs:
NEW_PATCH=$((CURR_PATCH+1)) NEW_PATCH=$((CURR_PATCH+1))
NEW_VER=$CURR_MAJOR.$NEW_PATCH NEW_VER=$CURR_MAJOR.$NEW_PATCH
echo "New Version: $NEW_VER" echo "New Version: $NEW_VER"
echo "new-version=$NEW_VER" >> $GITHUB_OUTPUT echo "new_version=$NEW_VER" >> $GITHUB_OUTPUT
trigger_version_bump: - name: Login to Azure - CI Subscription
name: Bump version to ${{ needs.setup.outputs.version_number }} uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
needs: setup with:
uses: ./.github/workflows/version-bump.yml creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
with:
version_number: ${{ needs.setup.outputs.version_number }} - name: Retrieve bot secrets
secrets: inherit id: retrieve-bot-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: bitwarden-ci
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: "Bump version to ${{ steps.version.outputs.new_version }}"
env:
GH_TOKEN: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
run: |
echo '{"cut_rc_branch": "false", "version_number": "${{ steps.version.outputs.new_version }}"}' | \
gh workflow run version-bump.yml --json --repo bitwarden/mobile

View File

@@ -72,7 +72,7 @@ jobs:
CURRENT_VERSION=$(xmllint --xpath ' CURRENT_VERSION=$(xmllint --xpath '
string(/manifest/@*[local-name()="versionName" string(/manifest/@*[local-name()="versionName"
and namespace-uri()="http://schemas.android.com/apk/res/android"]) and namespace-uri()="http://schemas.android.com/apk/res/android"])
' src/Android/Properties/AndroidManifest.xml) ' src/App/Platforms/Android/AndroidManifest.xml)
# Error if version has not changed. # Error if version has not changed.
if [[ "$NEW_VERSION" == "$CURRENT_VERSION" ]]; then if [[ "$NEW_VERSION" == "$CURRENT_VERSION" ]]; then
@@ -93,7 +93,7 @@ jobs:
uses: bitwarden/gh-actions/version-bump@main uses: bitwarden/gh-actions/version-bump@main
with: with:
version: ${{ inputs.version_number }} version: ${{ inputs.version_number }}
file_path: "src/Android/Properties/AndroidManifest.xml" file_path: "src/App/Platforms/Android/AndroidManifest.xml"
- name: Bump Version - iOS.Autofill - name: Bump Version - iOS.Autofill
uses: bitwarden/gh-actions/version-bump@main uses: bitwarden/gh-actions/version-bump@main
@@ -117,7 +117,7 @@ jobs:
uses: bitwarden/gh-actions/version-bump@main uses: bitwarden/gh-actions/version-bump@main
with: with:
version: ${{ inputs.version_number }} version: ${{ inputs.version_number }}
file_path: "src/iOS/Info.plist" file_path: "src/App/Platforms/iOS/Info.plist"
- name: Setup git - name: Setup git
run: | run: |
@@ -191,22 +191,26 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: main ref: main
- name: Install xmllint
run: sudo apt install -y libxml2-utils
- name: Verify version has been updated - name: Verify version has been updated
env: env:
NEW_VERSION: ${{ inputs.version_number }} NEW_VERSION: ${{ inputs.version_number }}
run: | run: |
CURRENT_VERSION=$(xmllint --xpath ' # Wait for version to change.
while : ; do
echo "Waiting for version to be updated..."
git pull --force
CURRENT_VERSION=$(xmllint --xpath '
string(/manifest/@*[local-name()="versionName" string(/manifest/@*[local-name()="versionName"
and namespace-uri()="http://schemas.android.com/apk/res/android"]) and namespace-uri()="http://schemas.android.com/apk/res/android"])
' src/Android/Properties/AndroidManifest.xml) ' src/App/Platforms/Android/AndroidManifest.xml)
# Wait for version to change. # If the versions don't match we continue the loop, otherwise we break out of the loop.
while [[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] [[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
do
echo "Waiting for version to be updated..."
sleep 10 sleep 10
git pull --force
done done
- name: Cut RC branch - name: Cut RC branch

View File

@@ -2,9 +2,9 @@ project_id_env: _CROWDIN_PROJECT_ID
api_token_env: CROWDIN_API_TOKEN api_token_env: CROWDIN_API_TOKEN
preserve_hierarchy: true preserve_hierarchy: true
files: files:
- source: /src/App/Resources/AppResources.resx - source: /src/Core/Resources/Localization/AppResources.resx
dest: /src/App/Resources/%original_file_name% dest: /src/Core/Resources/Localization/%original_file_name%
translation: /src/App/Resources/AppResources.%two_letters_code%.resx translation: /src/Core/Resources/Localization/AppResources.%two_letters_code%.resx
update_option: update_as_unapproved update_option: update_as_unapproved
languages_mapping: languages_mapping:
two_letters_code: two_letters_code:

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.2.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.2.2" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />

View File

@@ -79,24 +79,29 @@ namespace Bit.Droid.Services
} }
var context = Android.App.Application.Context; var context = Android.App.Application.Context;
var intent = new Intent(context, typeof(MainActivity)); var intent = context.PackageManager?.GetLaunchIntentForPackage(context.PackageName ?? string.Empty);
intent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
var pendingIntentFlags = AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, true);
var pendingIntent = PendingIntent.GetActivity(context, 20220801, intent, pendingIntentFlags);
var deleteIntent = new Intent(context, typeof(NotificationDismissReceiver)); var builder = new NotificationCompat.Builder(context, Bit.Core.Constants.AndroidNotificationChannelId);
deleteIntent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data)); if(intent != null && context.PackageManager != null && !string.IsNullOrEmpty(context.PackageName))
var deletePendingIntent = PendingIntent.GetBroadcast(context, 20220802, deleteIntent, pendingIntentFlags); {
intent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
var pendingIntentFlags = AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, true);
var pendingIntent = PendingIntent.GetActivity(context, 20220801, intent, pendingIntentFlags);
var builder = new NotificationCompat.Builder(context, Bit.Core.Constants.AndroidNotificationChannelId) var deleteIntent = new Intent(context, typeof(NotificationDismissReceiver));
.SetContentIntent(pendingIntent) deleteIntent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
.SetContentTitle(title) var deletePendingIntent = PendingIntent.GetBroadcast(context, 20220802, deleteIntent, pendingIntentFlags);
builder.SetContentIntent(pendingIntent)
.SetDeleteIntent(deletePendingIntent);
}
builder.SetContentTitle(title)
.SetContentText(message) .SetContentText(message)
.SetSmallIcon(Bit.Core.Resource.Drawable.ic_notification) .SetSmallIcon(Bit.Core.Resource.Drawable.ic_notification)
.SetColor((int)Android.Graphics.Color.White) .SetColor((int)Android.Graphics.Color.White)
.SetDeleteIntent(deletePendingIntent)
.SetAutoCancel(true); .SetAutoCancel(true);
if (data is PasswordlessNotificationData passwordlessNotificationData && passwordlessNotificationData.TimeoutInMinutes > 0) if (data is PasswordlessNotificationData passwordlessNotificationData && passwordlessNotificationData.TimeoutInMinutes > 0)
{ {
builder.SetTimeoutAfter(passwordlessNotificationData.TimeoutInMinutes * 60000); builder.SetTimeoutAfter(passwordlessNotificationData.TimeoutInMinutes * 60000);

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden</string> <string>com.8bit.bitwarden</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2024.2.1</string> <string>2024.2.2</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>CFBundleIconName</key> <key>CFBundleIconName</key>

View File

@@ -9,6 +9,10 @@ using Bit.Core.Utilities;
using Microsoft.Maui.ApplicationModel; using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Controls; using Microsoft.Maui.Controls;
using Microsoft.Maui; using Microsoft.Maui;
#if IOS
using Foundation;
using UIKit;
#endif
namespace Bit.App.Utilities namespace Bit.App.Utilities
{ {
@@ -65,12 +69,11 @@ namespace Bit.App.Utilities
resources.MergedDictionaries.Add(new ControlTemplates()); resources.MergedDictionaries.Add(new ControlTemplates());
// Platform styles // Platform styles
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes if (DeviceInfo.Platform == DevicePlatform.Android)
if (Device.RuntimePlatform == Device.Android)
{ {
resources.MergedDictionaries.Add(new Styles.Android()); resources.MergedDictionaries.Add(new Styles.Android());
} }
else if (Device.RuntimePlatform == Device.iOS) else if (DeviceInfo.Platform == DevicePlatform.iOS)
{ {
resources.MergedDictionaries.Add(new iOS()); resources.MergedDictionaries.Add(new iOS());
} }
@@ -147,17 +150,47 @@ namespace Bit.App.Utilities
return stateService.GetAutoDarkThemeAsync().GetAwaiter().GetResult(); return stateService.GetAutoDarkThemeAsync().GetAwaiter().GetResult();
} }
//HACK: OsDarkModeEnabled() is divided into Android and iOS implementations due to a MAUI bug.
// Currently on iOS when resuming the app after showing a System "Share/Sheet" (or other similar UI)
// MAUI reports the incorrect Theme. To avoid this we are fetching the current OS Theme directly on iOS from the iOS API.
// MAUI Issue: https://github.com/dotnet/maui/issues/19614
public static bool OsDarkModeEnabled() public static bool OsDarkModeEnabled()
{ {
if (Application.Current == null) #if UT
{ return false;
// called from iOS extension #else
var app = new App(new AppOptions { IosExtension = true });
return app.RequestedTheme == AppTheme.Dark; #if ANDROID
}
return Application.Current.RequestedTheme == AppTheme.Dark; return Application.Current.RequestedTheme == AppTheme.Dark;
#else
var requestedTheme = AppTheme.Unspecified;
if (!OperatingSystem.IsIOSVersionAtLeast(13, 0))
return false;
var traits = InvokeOnMainThread(() => WindowStateManager.Default.GetCurrentUIViewController()?.TraitCollection) ?? UITraitCollection.CurrentTraitCollection;
var uiStyle = traits.UserInterfaceStyle;
requestedTheme = uiStyle switch
{
UIUserInterfaceStyle.Light => AppTheme.Light,
UIUserInterfaceStyle.Dark => AppTheme.Dark,
_ => AppTheme.Unspecified
};
return requestedTheme == AppTheme.Dark;
#endif
#endif
} }
#if IOS
private static T InvokeOnMainThread<T>(Func<T> factory)
{
T value = default;
NSRunLoop.Main.InvokeOnMainThread(() => value = factory());
return value;
}
#endif
public static void ApplyResourcesTo(VisualElement element) public static void ApplyResourcesTo(VisualElement element)
{ {
foreach (var resourceDict in Resources().MergedDictionaries) foreach (var resourceDict in Resources().MergedDictionaries)

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using AuthenticationServices; using AuthenticationServices;
using Bit.App.Abstractions; using Bit.App.Abstractions;

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden.autofill</string> <string>com.8bit.bitwarden.autofill</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2024.2.1</string> <string>2024.2.2</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>CFBundleLocalizations</key> <key>CFBundleLocalizations</key>

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden.find-login-action-extension</string> <string>com.8bit.bitwarden.find-login-action-extension</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2024.2.1</string> <string>2024.2.2</string>
<key>CFBundleLocalizations</key> <key>CFBundleLocalizations</key>
<array> <array>
<string>en</string> <string>en</string>

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>XPC!</string> <string>XPC!</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2024.2.1</string> <string>2024.2.2</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>